wallet-core: remove deprecated txid parsing

This commit is contained in:
Florian Dold 2023-05-24 14:09:25 +02:00
parent 4627c0781c
commit f14c7e5f2a
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
6 changed files with 417 additions and 410 deletions

View File

@ -362,42 +362,6 @@ export enum TombstoneTag {
DeletePeerPushCredit = "delete-peer-push-credit", DeletePeerPushCredit = "delete-peer-push-credit",
} }
/**
* Create an event ID from the type and the primary key for the event.
*
* @deprecated use constructTransactionIdentifier instead
*/
export function makeTransactionId(
type: TransactionType,
...args: string[]
): string {
return `txn:${type}:${args.map((x) => encodeURIComponent(x)).join(":")}`;
}
export function parseId(
idType: "txn" | "tmb" | "any",
txId: string,
): {
type: TransactionType;
args: string[];
} {
const txnParts = txId.split(":");
if (txnParts.length < 3) {
throw Error("id should have al least 3 parts separated by ':'");
}
const [prefix, typeStr, ...args] = txnParts;
const type = typeStr as TransactionType;
if (idType != "any" && prefix !== idType) {
throw Error(`id should start with ${idType}`);
}
if (args.length === 0) {
throw Error("id should have one or more arguments");
}
return { type, args };
}
/** /**
* Create an event ID from the type and the primary key for the event. * Create an event ID from the type and the primary key for the event.

View File

@ -118,7 +118,6 @@ import {
TaskIdentifiers, TaskIdentifiers,
} from "../util/retries.js"; } from "../util/retries.js";
import { import {
makeTransactionId,
runLongpollAsync, runLongpollAsync,
runOperationWithErrorReporting, runOperationWithErrorReporting,
spendCoins, spendCoins,

View File

@ -59,7 +59,7 @@ import {
OperationAttemptResult, OperationAttemptResult,
OperationAttemptResultType, OperationAttemptResultType,
} from "../util/retries.js"; } from "../util/retries.js";
import { makeCoinAvailable, makeTransactionId } from "./common.js"; import { makeCoinAvailable } from "./common.js";
import { updateExchangeFromUrl } from "./exchanges.js"; import { updateExchangeFromUrl } from "./exchanges.js";
import { import {
getCandidateWithdrawalDenoms, getCandidateWithdrawalDenoms,

View File

@ -67,7 +67,6 @@ import {
PeerPushPaymentIncomingStatus, PeerPushPaymentIncomingStatus,
PeerPullPaymentInitiationRecord, PeerPullPaymentInitiationRecord,
RefundGroupRecord, RefundGroupRecord,
ContractTermsRecord,
} from "../db.js"; } from "../db.js";
import { InternalWalletState } from "../internal-wallet-state.js"; import { InternalWalletState } from "../internal-wallet-state.js";
import { PendingTaskType } from "../pending-types.js"; import { PendingTaskType } from "../pending-types.js";
@ -76,8 +75,6 @@ import { checkDbInvariant, checkLogicInvariant } from "../util/invariants.js";
import { constructTaskIdentifier, TaskIdentifiers } from "../util/retries.js"; import { constructTaskIdentifier, TaskIdentifiers } from "../util/retries.js";
import { import {
makeTombstoneId, makeTombstoneId,
makeTransactionId,
parseId,
resetOperationTimeout, resetOperationTimeout,
runOperationWithErrorReporting, runOperationWithErrorReporting,
TombstoneTag, TombstoneTag,
@ -164,209 +161,227 @@ export async function getTransactionById(
ws: InternalWalletState, ws: InternalWalletState,
req: TransactionByIdRequest, req: TransactionByIdRequest,
): Promise<Transaction> { ): Promise<Transaction> {
const { type, args: rest } = parseId("txn", req.transactionId); const parsedTx = parseTransactionIdentifier(req.transactionId);
if (type === TransactionType.Withdrawal) {
const withdrawalGroupId = rest[0];
return await ws.db
.mktx((x) => [
x.withdrawalGroups,
x.exchangeDetails,
x.exchanges,
x.operationRetries,
])
.runReadWrite(async (tx) => {
const withdrawalGroupRecord = await tx.withdrawalGroups.get(
withdrawalGroupId,
);
if (!withdrawalGroupRecord) throw Error("not found"); if (!parsedTx) {
throw Error("invalid transaction ID");
}
const opId = TaskIdentifiers.forWithdrawal(withdrawalGroupRecord); switch (parsedTx.tag) {
const ort = await tx.operationRetries.get(opId); case TransactionType.Withdrawal: {
const withdrawalGroupId = parsedTx.withdrawalGroupId;
return await ws.db
.mktx((x) => [
x.withdrawalGroups,
x.exchangeDetails,
x.exchanges,
x.operationRetries,
])
.runReadWrite(async (tx) => {
const withdrawalGroupRecord = await tx.withdrawalGroups.get(
withdrawalGroupId,
);
if ( if (!withdrawalGroupRecord) throw Error("not found");
withdrawalGroupRecord.wgInfo.withdrawalType ===
WithdrawalRecordType.BankIntegrated const opId = TaskIdentifiers.forWithdrawal(withdrawalGroupRecord);
) { const ort = await tx.operationRetries.get(opId);
return buildTransactionForBankIntegratedWithdraw(
if (
withdrawalGroupRecord.wgInfo.withdrawalType ===
WithdrawalRecordType.BankIntegrated
) {
return buildTransactionForBankIntegratedWithdraw(
withdrawalGroupRecord,
ort,
);
}
const exchangeDetails = await getExchangeDetails(
tx,
withdrawalGroupRecord.exchangeBaseUrl,
);
if (!exchangeDetails) throw Error("not exchange details");
return buildTransactionForManualWithdraw(
withdrawalGroupRecord, withdrawalGroupRecord,
exchangeDetails,
ort, ort,
); );
} });
const exchangeDetails = await getExchangeDetails( }
tx,
withdrawalGroupRecord.exchangeBaseUrl,
);
if (!exchangeDetails) throw Error("not exchange details");
return buildTransactionForManualWithdraw( case TransactionType.Payment: {
withdrawalGroupRecord, const proposalId = parsedTx.proposalId;
exchangeDetails, return await ws.db
ort, .mktx((x) => [
); x.purchases,
}); x.tombstones,
} else if (type === TransactionType.Payment) { x.operationRetries,
const proposalId = rest[0]; x.contractTerms,
return await ws.db ])
.mktx((x) => [ .runReadWrite(async (tx) => {
x.purchases, const purchase = await tx.purchases.get(proposalId);
x.tombstones, if (!purchase) throw Error("not found");
x.operationRetries, const download = await expectProposalDownload(ws, purchase, tx);
x.contractTerms, const contractData = download.contractData;
]) const payOpId = TaskIdentifiers.forPay(purchase);
.runReadWrite(async (tx) => { const payRetryRecord = await tx.operationRetries.get(payOpId);
const purchase = await tx.purchases.get(proposalId);
if (!purchase) throw Error("not found");
const download = await expectProposalDownload(ws, purchase, tx);
const contractData = download.contractData;
const payOpId = TaskIdentifiers.forPay(purchase);
const payRetryRecord = await tx.operationRetries.get(payOpId);
return buildTransactionForPurchase( return buildTransactionForPurchase(
purchase, purchase,
contractData, contractData,
[], // FIXME: Add refunds from refund group records here. [], // FIXME: Add refunds from refund group records here.
payRetryRecord, payRetryRecord,
); );
}); });
} else if (type === TransactionType.Refresh) { }
const refreshGroupId = rest[0];
throw Error(`no tx for refresh`);
} else if (type === TransactionType.Tip) {
const tipId = rest[0];
return await ws.db
.mktx((x) => [x.tips, x.operationRetries])
.runReadWrite(async (tx) => {
const tipRecord = await tx.tips.get(tipId);
if (!tipRecord) throw Error("not found");
const retries = await tx.operationRetries.get( case TransactionType.Refresh: {
TaskIdentifiers.forTipPickup(tipRecord), // FIXME: We should return info about the refresh here!
); throw Error(`no tx for refresh`);
return buildTransactionForTip(tipRecord, retries); }
});
} else if (type === TransactionType.Deposit) {
const depositGroupId = rest[0];
return await ws.db
.mktx((x) => [x.depositGroups, x.operationRetries])
.runReadWrite(async (tx) => {
const depositRecord = await tx.depositGroups.get(depositGroupId);
if (!depositRecord) throw Error("not found");
const retries = await tx.operationRetries.get( case TransactionType.Tip: {
TaskIdentifiers.forDeposit(depositRecord), const tipId = parsedTx.walletTipId;
); return await ws.db
return buildTransactionForDeposit(depositRecord, retries); .mktx((x) => [x.tips, x.operationRetries])
}); .runReadWrite(async (tx) => {
} else if (type === TransactionType.Refund) { const tipRecord = await tx.tips.get(tipId);
// FIXME! if (!tipRecord) throw Error("not found");
throw Error("not implemented");
} else if (type === TransactionType.PeerPullDebit) {
const peerPullPaymentIncomingId = rest[0];
return await ws.db
.mktx((x) => [x.peerPullPaymentIncoming])
.runReadWrite(async (tx) => {
const debit = await tx.peerPullPaymentIncoming.get(
peerPullPaymentIncomingId,
);
if (!debit) throw Error("not found");
return buildTransactionForPullPaymentDebit(debit);
});
} else if (type === TransactionType.PeerPushDebit) {
const pursePub = rest[0];
return await ws.db
.mktx((x) => [x.peerPushPaymentInitiations, x.contractTerms])
.runReadWrite(async (tx) => {
const debit = await tx.peerPushPaymentInitiations.get(pursePub);
if (!debit) throw Error("not found");
const ct = await tx.contractTerms.get(debit.contractTermsHash);
checkDbInvariant(!!ct);
return buildTransactionForPushPaymentDebit(debit, ct.contractTermsRaw);
});
} else if (type === TransactionType.PeerPushCredit) {
const peerPushPaymentIncomingId = rest[0];
return await ws.db
.mktx((x) => [
x.peerPushPaymentIncoming,
x.contractTerms,
x.withdrawalGroups,
x.operationRetries,
])
.runReadWrite(async (tx) => {
const pushInc = await tx.peerPushPaymentIncoming.get(
peerPushPaymentIncomingId,
);
if (!pushInc) throw Error("not found");
const ct = await tx.contractTerms.get(pushInc.contractTermsHash);
checkDbInvariant(!!ct);
let wg: WithdrawalGroupRecord | undefined = undefined; const retries = await tx.operationRetries.get(
let wgOrt: OperationRetryRecord | undefined = undefined; TaskIdentifiers.forTipPickup(tipRecord),
if (pushInc.withdrawalGroupId) { );
wg = await tx.withdrawalGroups.get(pushInc.withdrawalGroupId); return buildTransactionForTip(tipRecord, retries);
if (wg) { });
const withdrawalOpId = TaskIdentifiers.forWithdrawal(wg); }
wgOrt = await tx.operationRetries.get(withdrawalOpId);
case TransactionType.Deposit: {
const depositGroupId = parsedTx.depositGroupId;
return await ws.db
.mktx((x) => [x.depositGroups, x.operationRetries])
.runReadWrite(async (tx) => {
const depositRecord = await tx.depositGroups.get(depositGroupId);
if (!depositRecord) throw Error("not found");
const retries = await tx.operationRetries.get(
TaskIdentifiers.forDeposit(depositRecord),
);
return buildTransactionForDeposit(depositRecord, retries);
});
}
case TransactionType.Refund:
// FIXME!
throw Error("not implemented");
case TransactionType.PeerPullDebit: {
return await ws.db
.mktx((x) => [x.peerPullPaymentIncoming])
.runReadWrite(async (tx) => {
const debit = await tx.peerPullPaymentIncoming.get(
parsedTx.peerPullPaymentIncomingId,
);
if (!debit) throw Error("not found");
return buildTransactionForPullPaymentDebit(debit);
});
}
case TransactionType.PeerPushDebit: {
return await ws.db
.mktx((x) => [x.peerPushPaymentInitiations, x.contractTerms])
.runReadWrite(async (tx) => {
const debit = await tx.peerPushPaymentInitiations.get(
parsedTx.pursePub,
);
if (!debit) throw Error("not found");
const ct = await tx.contractTerms.get(debit.contractTermsHash);
checkDbInvariant(!!ct);
return buildTransactionForPushPaymentDebit(
debit,
ct.contractTermsRaw,
);
});
}
case TransactionType.PeerPushCredit: {
const peerPushPaymentIncomingId = parsedTx.peerPushPaymentIncomingId;
return await ws.db
.mktx((x) => [
x.peerPushPaymentIncoming,
x.contractTerms,
x.withdrawalGroups,
x.operationRetries,
])
.runReadWrite(async (tx) => {
const pushInc = await tx.peerPushPaymentIncoming.get(
peerPushPaymentIncomingId,
);
if (!pushInc) throw Error("not found");
const ct = await tx.contractTerms.get(pushInc.contractTermsHash);
checkDbInvariant(!!ct);
let wg: WithdrawalGroupRecord | undefined = undefined;
let wgOrt: OperationRetryRecord | undefined = undefined;
if (pushInc.withdrawalGroupId) {
wg = await tx.withdrawalGroups.get(pushInc.withdrawalGroupId);
if (wg) {
const withdrawalOpId = TaskIdentifiers.forWithdrawal(wg);
wgOrt = await tx.operationRetries.get(withdrawalOpId);
}
} }
} const pushIncOpId = TaskIdentifiers.forPeerPushCredit(pushInc);
const pushIncOpId = TaskIdentifiers.forPeerPushCredit(pushInc); let pushIncOrt = await tx.operationRetries.get(pushIncOpId);
let pushIncOrt = await tx.operationRetries.get(pushIncOpId);
return buildTransactionForPeerPushCredit( return buildTransactionForPeerPushCredit(
pushInc, pushInc,
pushIncOrt, pushIncOrt,
ct.contractTermsRaw, ct.contractTermsRaw,
wg, wg,
wgOrt, wgOrt,
); );
}); });
} else if (type === TransactionType.PeerPullCredit) { }
const pursePub = rest[0];
return await ws.db
.mktx((x) => [
x.peerPullPaymentInitiations,
x.contractTerms,
x.withdrawalGroups,
x.operationRetries,
])
.runReadWrite(async (tx) => {
const pushInc = await tx.peerPullPaymentInitiations.get(pursePub);
if (!pushInc) throw Error("not found");
const ct = await tx.contractTerms.get(pushInc.contractTermsHash);
checkDbInvariant(!!ct);
let wg: WithdrawalGroupRecord | undefined = undefined; case TransactionType.PeerPullCredit: {
let wgOrt: OperationRetryRecord | undefined = undefined; const pursePub = parsedTx.pursePub;
if (pushInc.withdrawalGroupId) { return await ws.db
wg = await tx.withdrawalGroups.get(pushInc.withdrawalGroupId); .mktx((x) => [
if (wg) { x.peerPullPaymentInitiations,
const withdrawalOpId = TaskIdentifiers.forWithdrawal(wg); x.contractTerms,
wgOrt = await tx.operationRetries.get(withdrawalOpId); x.withdrawalGroups,
x.operationRetries,
])
.runReadWrite(async (tx) => {
const pushInc = await tx.peerPullPaymentInitiations.get(pursePub);
if (!pushInc) throw Error("not found");
const ct = await tx.contractTerms.get(pushInc.contractTermsHash);
checkDbInvariant(!!ct);
let wg: WithdrawalGroupRecord | undefined = undefined;
let wgOrt: OperationRetryRecord | undefined = undefined;
if (pushInc.withdrawalGroupId) {
wg = await tx.withdrawalGroups.get(pushInc.withdrawalGroupId);
if (wg) {
const withdrawalOpId = TaskIdentifiers.forWithdrawal(wg);
wgOrt = await tx.operationRetries.get(withdrawalOpId);
}
} }
} const pushIncOpId =
const pushIncOpId = TaskIdentifiers.forPeerPullPaymentInitiation(pushInc);
TaskIdentifiers.forPeerPullPaymentInitiation(pushInc); let pushIncOrt = await tx.operationRetries.get(pushIncOpId);
let pushIncOrt = await tx.operationRetries.get(pushIncOpId);
return buildTransactionForPeerPullCredit( return buildTransactionForPeerPullCredit(
pushInc, pushInc,
pushIncOrt, pushIncOrt,
ct.contractTermsRaw, ct.contractTermsRaw,
wg, wg,
wgOrt, wgOrt,
); );
}); });
} else { }
const unknownTxType: never = type;
throw Error(`can't retrieve a '${unknownTxType}' transaction`);
} }
} }
// FIXME: Just a marker helper for unknown states until DD37 is fully implemented.
const mkTxStateUnknown = () => ({
major: TransactionMajorState.Unknown,
});
function buildTransactionForPushPaymentDebit( function buildTransactionForPushPaymentDebit(
pi: PeerPushPaymentInitiationRecord, pi: PeerPushPaymentInitiationRecord,
contractTerms: PeerContractTerms, contractTerms: PeerContractTerms,
@ -1293,7 +1308,13 @@ export function constructTransactionIdentifier(
export function parseTransactionIdentifier( export function parseTransactionIdentifier(
transactionId: string, transactionId: string,
): ParsedTransactionIdentifier | undefined { ): ParsedTransactionIdentifier | undefined {
const { type, args: rest } = parseId("any", transactionId); const txnParts = transactionId.split(":");
if (txnParts.length < 3) {
throw Error("id should have al least 3 parts separated by ':'");
}
const [prefix, type, ...rest] = txnParts;
switch (type) { switch (type) {
case TransactionType.Deposit: case TransactionType.Deposit:
@ -1489,25 +1510,92 @@ export async function deleteTransaction(
ws: InternalWalletState, ws: InternalWalletState,
transactionId: string, transactionId: string,
): Promise<void> { ): Promise<void> {
const { type, args: rest } = parseId("txn", transactionId); const parsedTx = parseTransactionIdentifier(transactionId);
if (type === TransactionType.PeerPushCredit) { if (!parsedTx) {
const peerPushPaymentIncomingId = rest[0]; throw Error("invalid transaction ID");
await ws.db }
.mktx((x) => [
x.withdrawalGroups, switch (parsedTx.tag) {
x.peerPushPaymentIncoming, case TransactionType.PeerPushCredit: {
x.tombstones, const peerPushPaymentIncomingId = parsedTx.peerPushPaymentIncomingId;
]) await ws.db
.runReadWrite(async (tx) => { .mktx((x) => [
const pushInc = await tx.peerPushPaymentIncoming.get( x.withdrawalGroups,
peerPushPaymentIncomingId, x.peerPushPaymentIncoming,
); x.tombstones,
if (!pushInc) { ])
return; .runReadWrite(async (tx) => {
} const pushInc = await tx.peerPushPaymentIncoming.get(
if (pushInc.withdrawalGroupId) { peerPushPaymentIncomingId,
const withdrawalGroupId = pushInc.withdrawalGroupId; );
if (!pushInc) {
return;
}
if (pushInc.withdrawalGroupId) {
const withdrawalGroupId = pushInc.withdrawalGroupId;
const withdrawalGroupRecord = await tx.withdrawalGroups.get(
withdrawalGroupId,
);
if (withdrawalGroupRecord) {
await tx.withdrawalGroups.delete(withdrawalGroupId);
await tx.tombstones.put({
id:
TombstoneTag.DeleteWithdrawalGroup + ":" + withdrawalGroupId,
});
}
}
await tx.peerPushPaymentIncoming.delete(peerPushPaymentIncomingId);
await tx.tombstones.put({
id:
TombstoneTag.DeletePeerPushCredit +
":" +
peerPushPaymentIncomingId,
});
});
return;
}
case TransactionType.PeerPullCredit: {
const pursePub = parsedTx.pursePub;
await ws.db
.mktx((x) => [
x.withdrawalGroups,
x.peerPullPaymentInitiations,
x.tombstones,
])
.runReadWrite(async (tx) => {
const pullIni = await tx.peerPullPaymentInitiations.get(pursePub);
if (!pullIni) {
return;
}
if (pullIni.withdrawalGroupId) {
const withdrawalGroupId = pullIni.withdrawalGroupId;
const withdrawalGroupRecord = await tx.withdrawalGroups.get(
withdrawalGroupId,
);
if (withdrawalGroupRecord) {
await tx.withdrawalGroups.delete(withdrawalGroupId);
await tx.tombstones.put({
id:
TombstoneTag.DeleteWithdrawalGroup + ":" + withdrawalGroupId,
});
}
}
await tx.peerPullPaymentInitiations.delete(pursePub);
await tx.tombstones.put({
id: TombstoneTag.DeletePeerPullCredit + ":" + pursePub,
});
});
return;
}
case TransactionType.Withdrawal: {
const withdrawalGroupId = parsedTx.withdrawalGroupId;
await ws.db
.mktx((x) => [x.withdrawalGroups, x.tombstones])
.runReadWrite(async (tx) => {
const withdrawalGroupRecord = await tx.withdrawalGroups.get( const withdrawalGroupRecord = await tx.withdrawalGroups.get(
withdrawalGroupId, withdrawalGroupId,
); );
@ -1516,170 +1604,124 @@ export async function deleteTransaction(
await tx.tombstones.put({ await tx.tombstones.put({
id: TombstoneTag.DeleteWithdrawalGroup + ":" + withdrawalGroupId, id: TombstoneTag.DeleteWithdrawalGroup + ":" + withdrawalGroupId,
}); });
return;
} }
}
await tx.peerPushPaymentIncoming.delete(peerPushPaymentIncomingId);
await tx.tombstones.put({
id:
TombstoneTag.DeletePeerPushCredit + ":" + peerPushPaymentIncomingId,
}); });
}); return;
} else if (type === TransactionType.PeerPullCredit) { }
const pursePub = rest[0];
await ws.db case TransactionType.Payment: {
.mktx((x) => [ const proposalId = parsedTx.proposalId;
x.withdrawalGroups, await ws.db
x.peerPullPaymentInitiations, .mktx((x) => [x.purchases, x.tombstones])
x.tombstones, .runReadWrite(async (tx) => {
]) let found = false;
.runReadWrite(async (tx) => { const purchase = await tx.purchases.get(proposalId);
const pullIni = await tx.peerPullPaymentInitiations.get(pursePub); if (purchase) {
if (!pullIni) { found = true;
return; await tx.purchases.delete(proposalId);
} }
if (pullIni.withdrawalGroupId) { if (found) {
const withdrawalGroupId = pullIni.withdrawalGroupId;
const withdrawalGroupRecord = await tx.withdrawalGroups.get(
withdrawalGroupId,
);
if (withdrawalGroupRecord) {
await tx.withdrawalGroups.delete(withdrawalGroupId);
await tx.tombstones.put({ await tx.tombstones.put({
id: TombstoneTag.DeleteWithdrawalGroup + ":" + withdrawalGroupId, id: TombstoneTag.DeletePayment + ":" + proposalId,
}); });
} }
}
await tx.peerPullPaymentInitiations.delete(pursePub);
await tx.tombstones.put({
id: TombstoneTag.DeletePeerPullCredit + ":" + pursePub,
}); });
}); return;
} else if (type === TransactionType.Withdrawal) { }
const withdrawalGroupId = rest[0];
await ws.db
.mktx((x) => [x.withdrawalGroups, x.tombstones])
.runReadWrite(async (tx) => {
const withdrawalGroupRecord = await tx.withdrawalGroups.get(
withdrawalGroupId,
);
if (withdrawalGroupRecord) {
await tx.withdrawalGroups.delete(withdrawalGroupId);
await tx.tombstones.put({
id: TombstoneTag.DeleteWithdrawalGroup + ":" + withdrawalGroupId,
});
return;
}
});
} else if (type === TransactionType.Payment) {
const proposalId = rest[0];
await ws.db
.mktx((x) => [x.purchases, x.tombstones])
.runReadWrite(async (tx) => {
let found = false;
const purchase = await tx.purchases.get(proposalId);
if (purchase) {
found = true;
await tx.purchases.delete(proposalId);
}
if (found) {
await tx.tombstones.put({
id: TombstoneTag.DeletePayment + ":" + proposalId,
});
}
});
} else if (type === TransactionType.Refresh) {
const refreshGroupId = rest[0];
await ws.db
.mktx((x) => [x.refreshGroups, x.tombstones])
.runReadWrite(async (tx) => {
const rg = await tx.refreshGroups.get(refreshGroupId);
if (rg) {
await tx.refreshGroups.delete(refreshGroupId);
await tx.tombstones.put({
id: TombstoneTag.DeleteRefreshGroup + ":" + refreshGroupId,
});
}
});
} else if (type === TransactionType.Tip) {
const tipId = rest[0];
await ws.db
.mktx((x) => [x.tips, x.tombstones])
.runReadWrite(async (tx) => {
const tipRecord = await tx.tips.get(tipId);
if (tipRecord) {
await tx.tips.delete(tipId);
await tx.tombstones.put({
id: TombstoneTag.DeleteTip + ":" + tipId,
});
}
});
} else if (type === TransactionType.Deposit) {
const depositGroupId = rest[0];
await ws.db
.mktx((x) => [x.depositGroups, x.tombstones])
.runReadWrite(async (tx) => {
const tipRecord = await tx.depositGroups.get(depositGroupId);
if (tipRecord) {
await tx.depositGroups.delete(depositGroupId);
await tx.tombstones.put({
id: TombstoneTag.DeleteDepositGroup + ":" + depositGroupId,
});
}
});
} else if (type === TransactionType.Refund) {
const proposalId = rest[0];
const executionTimeStr = rest[1];
await ws.db case TransactionType.Refresh: {
.mktx((x) => [x.purchases, x.tombstones]) const refreshGroupId = parsedTx.refreshGroupId;
.runReadWrite(async (tx) => { await ws.db
const purchase = await tx.purchases.get(proposalId); .mktx((x) => [x.refreshGroups, x.tombstones])
if (purchase) { .runReadWrite(async (tx) => {
// This should just influence the history view, const rg = await tx.refreshGroups.get(refreshGroupId);
// but won't delete any actual refund information. if (rg) {
await tx.tombstones.put({ await tx.refreshGroups.delete(refreshGroupId);
id: makeTombstoneId( await tx.tombstones.put({
TombstoneTag.DeleteRefund, id: TombstoneTag.DeleteRefreshGroup + ":" + refreshGroupId,
proposalId, });
executionTimeStr, }
), });
});
} return;
}); }
} else if (type === TransactionType.PeerPullDebit) {
const peerPullPaymentIncomingId = rest[0]; case TransactionType.Tip: {
await ws.db const tipId = parsedTx.walletTipId;
.mktx((x) => [x.peerPullPaymentIncoming, x.tombstones]) await ws.db
.runReadWrite(async (tx) => { .mktx((x) => [x.tips, x.tombstones])
const debit = await tx.peerPullPaymentIncoming.get( .runReadWrite(async (tx) => {
peerPullPaymentIncomingId, const tipRecord = await tx.tips.get(tipId);
); if (tipRecord) {
if (debit) { await tx.tips.delete(tipId);
await tx.peerPullPaymentIncoming.delete(peerPullPaymentIncomingId); await tx.tombstones.put({
await tx.tombstones.put({ id: TombstoneTag.DeleteTip + ":" + tipId,
id: makeTombstoneId( });
TombstoneTag.DeletePeerPullDebit, }
peerPullPaymentIncomingId, });
), return;
}); }
}
}); case TransactionType.Deposit: {
} else if (type === TransactionType.PeerPushDebit) { const depositGroupId = parsedTx.depositGroupId;
const pursePub = rest[0]; await ws.db
await ws.db .mktx((x) => [x.depositGroups, x.tombstones])
.mktx((x) => [x.peerPushPaymentInitiations, x.tombstones]) .runReadWrite(async (tx) => {
.runReadWrite(async (tx) => { const tipRecord = await tx.depositGroups.get(depositGroupId);
const debit = await tx.peerPushPaymentInitiations.get(pursePub); if (tipRecord) {
if (debit) { await tx.depositGroups.delete(depositGroupId);
await tx.peerPushPaymentInitiations.delete(pursePub); await tx.tombstones.put({
await tx.tombstones.put({ id: TombstoneTag.DeleteDepositGroup + ":" + depositGroupId,
id: makeTombstoneId(TombstoneTag.DeletePeerPushDebit, pursePub), });
}); }
} });
});
} else { return;
const unknownTxType: never = type; }
throw Error(`can't delete a '${unknownTxType}' transaction`);
case TransactionType.Refund: {
// FIXME: Implement!
return;
}
case TransactionType.PeerPullDebit: {
const peerPullPaymentIncomingId = parsedTx.peerPullPaymentIncomingId;
await ws.db
.mktx((x) => [x.peerPullPaymentIncoming, x.tombstones])
.runReadWrite(async (tx) => {
const debit = await tx.peerPullPaymentIncoming.get(
peerPullPaymentIncomingId,
);
if (debit) {
await tx.peerPullPaymentIncoming.delete(peerPullPaymentIncomingId);
await tx.tombstones.put({
id: makeTombstoneId(
TombstoneTag.DeletePeerPullDebit,
peerPullPaymentIncomingId,
),
});
}
});
return;
}
case TransactionType.PeerPushDebit: {
const pursePub = parsedTx.pursePub;
await ws.db
.mktx((x) => [x.peerPushPaymentInitiations, x.tombstones])
.runReadWrite(async (tx) => {
const debit = await tx.peerPushPaymentInitiations.get(pursePub);
if (debit) {
await tx.peerPushPaymentInitiations.delete(pursePub);
await tx.tombstones.put({
id: makeTombstoneId(TombstoneTag.DeletePeerPushDebit, pursePub),
});
}
});
return;
}
} }
} }

View File

@ -118,7 +118,6 @@ import {
WALLET_BANK_INTEGRATION_PROTOCOL_VERSION, WALLET_BANK_INTEGRATION_PROTOCOL_VERSION,
WALLET_EXCHANGE_PROTOCOL_VERSION, WALLET_EXCHANGE_PROTOCOL_VERSION,
} from "../versions.js"; } from "../versions.js";
import { makeTransactionId } from "./common.js";
import { import {
getExchangeDetails, getExchangeDetails,
getExchangePaytoUri, getExchangePaytoUri,
@ -1456,10 +1455,10 @@ export async function processWithdrawalGroup(
if (numKycRequired > 0) { if (numKycRequired > 0) {
if (kycInfo) { if (kycInfo) {
const txId = makeTransactionId( const txId = constructTransactionIdentifier({
TransactionType.Withdrawal, tag: TransactionType.Withdrawal,
withdrawalGroup.withdrawalGroupId, withdrawalGroupId: withdrawalGroup.withdrawalGroupId,
); });
await checkWithdrawalKycStatus( await checkWithdrawalKycStatus(
ws, ws,
withdrawalGroup.exchangeBaseUrl, withdrawalGroup.exchangeBaseUrl,
@ -2050,12 +2049,13 @@ async function processReserveBankStatus(
r.wgInfo.bankInfo.timestampBankConfirmed = now; r.wgInfo.bankInfo.timestampBankConfirmed = now;
r.status = WithdrawalGroupStatus.PendingQueryingStatus; r.status = WithdrawalGroupStatus.PendingQueryingStatus;
// FIXME: Notification is deprecated with DD37. // FIXME: Notification is deprecated with DD37.
const transactionId = constructTransactionIdentifier({
tag: TransactionType.Withdrawal,
withdrawalGroupId: r.withdrawalGroupId,
});
ws.notify({ ws.notify({
type: NotificationType.WithdrawalGroupBankConfirmed, type: NotificationType.WithdrawalGroupBankConfirmed,
transactionId: makeTransactionId( transactionId,
TransactionType.Withdrawal,
r.withdrawalGroupId,
),
}); });
} else { } else {
logger.info("withdrawal: transfer not yet confirmed by bank"); logger.info("withdrawal: transfer not yet confirmed by bank");

View File

@ -159,6 +159,7 @@ describe("Withdraw CTA states", () => {
paytoUris: ["payto://"], paytoUris: ["payto://"],
tosAccepted: true, tosAccepted: true,
ageRestrictionOptions: [], ageRestrictionOptions: [],
numCoins: 42,
}, },
); );
@ -222,6 +223,7 @@ describe("Withdraw CTA states", () => {
paytoUris: ["payto://"], paytoUris: ["payto://"],
tosAccepted: false, tosAccepted: false,
ageRestrictionOptions: [], ageRestrictionOptions: [],
numCoins: 42,
}, },
); );