From f14c7e5f2a1495613c16bcf1acf74d08fd91fb48 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 24 May 2023 14:09:25 +0200 Subject: wallet-core: remove deprecated txid parsing --- .../taler-wallet-core/src/operations/common.ts | 36 - .../src/operations/pay-merchant.ts | 1 - packages/taler-wallet-core/src/operations/tip.ts | 2 +- .../src/operations/transactions.ts | 774 +++++++++++---------- .../taler-wallet-core/src/operations/withdraw.ts | 18 +- 5 files changed, 418 insertions(+), 413 deletions(-) (limited to 'packages/taler-wallet-core/src') diff --git a/packages/taler-wallet-core/src/operations/common.ts b/packages/taler-wallet-core/src/operations/common.ts index c3dc622d7..95551010c 100644 --- a/packages/taler-wallet-core/src/operations/common.ts +++ b/packages/taler-wallet-core/src/operations/common.ts @@ -362,42 +362,6 @@ export enum TombstoneTag { 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. diff --git a/packages/taler-wallet-core/src/operations/pay-merchant.ts b/packages/taler-wallet-core/src/operations/pay-merchant.ts index b39d5f8c1..54953246d 100644 --- a/packages/taler-wallet-core/src/operations/pay-merchant.ts +++ b/packages/taler-wallet-core/src/operations/pay-merchant.ts @@ -118,7 +118,6 @@ import { TaskIdentifiers, } from "../util/retries.js"; import { - makeTransactionId, runLongpollAsync, runOperationWithErrorReporting, spendCoins, diff --git a/packages/taler-wallet-core/src/operations/tip.ts b/packages/taler-wallet-core/src/operations/tip.ts index 4139234f4..a6e1a8fec 100644 --- a/packages/taler-wallet-core/src/operations/tip.ts +++ b/packages/taler-wallet-core/src/operations/tip.ts @@ -59,7 +59,7 @@ import { OperationAttemptResult, OperationAttemptResultType, } from "../util/retries.js"; -import { makeCoinAvailable, makeTransactionId } from "./common.js"; +import { makeCoinAvailable } from "./common.js"; import { updateExchangeFromUrl } from "./exchanges.js"; import { getCandidateWithdrawalDenoms, diff --git a/packages/taler-wallet-core/src/operations/transactions.ts b/packages/taler-wallet-core/src/operations/transactions.ts index 551e495dc..2e42eb8d8 100644 --- a/packages/taler-wallet-core/src/operations/transactions.ts +++ b/packages/taler-wallet-core/src/operations/transactions.ts @@ -67,7 +67,6 @@ import { PeerPushPaymentIncomingStatus, PeerPullPaymentInitiationRecord, RefundGroupRecord, - ContractTermsRecord, } from "../db.js"; import { InternalWalletState } from "../internal-wallet-state.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 { makeTombstoneId, - makeTransactionId, - parseId, resetOperationTimeout, runOperationWithErrorReporting, TombstoneTag, @@ -164,209 +161,227 @@ export async function getTransactionById( ws: InternalWalletState, req: TransactionByIdRequest, ): Promise { - const { type, args: rest } = parseId("txn", 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, - ); + const parsedTx = parseTransactionIdentifier(req.transactionId); - if (!withdrawalGroupRecord) throw Error("not found"); + if (!parsedTx) { + throw Error("invalid transaction ID"); + } - const opId = TaskIdentifiers.forWithdrawal(withdrawalGroupRecord); - const ort = await tx.operationRetries.get(opId); + switch (parsedTx.tag) { + 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 ( - withdrawalGroupRecord.wgInfo.withdrawalType === - WithdrawalRecordType.BankIntegrated - ) { - return buildTransactionForBankIntegratedWithdraw( + if (!withdrawalGroupRecord) throw Error("not found"); + + const opId = TaskIdentifiers.forWithdrawal(withdrawalGroupRecord); + const ort = await tx.operationRetries.get(opId); + + 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, + exchangeDetails, ort, ); - } - const exchangeDetails = await getExchangeDetails( - tx, - withdrawalGroupRecord.exchangeBaseUrl, - ); - if (!exchangeDetails) throw Error("not exchange details"); + }); + } - return buildTransactionForManualWithdraw( - withdrawalGroupRecord, - exchangeDetails, - ort, - ); - }); - } else if (type === TransactionType.Payment) { - const proposalId = rest[0]; - return await ws.db - .mktx((x) => [ - x.purchases, - x.tombstones, - x.operationRetries, - x.contractTerms, - ]) - .runReadWrite(async (tx) => { - 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); + case TransactionType.Payment: { + const proposalId = parsedTx.proposalId; + return await ws.db + .mktx((x) => [ + x.purchases, + x.tombstones, + x.operationRetries, + x.contractTerms, + ]) + .runReadWrite(async (tx) => { + 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( + purchase, + contractData, + [], // FIXME: Add refunds from refund group records here. + payRetryRecord, + ); + }); + } - return buildTransactionForPurchase( - purchase, - contractData, - [], // FIXME: Add refunds from refund group records here. - 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( - TaskIdentifiers.forTipPickup(tipRecord), - ); - 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( - TaskIdentifiers.forDeposit(depositRecord), - ); - return buildTransactionForDeposit(depositRecord, retries); - }); - } else if (type === TransactionType.Refund) { - // FIXME! - 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); + case TransactionType.Refresh: { + // FIXME: We should return info about the refresh here! + throw Error(`no tx for refresh`); + } - 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); + case TransactionType.Tip: { + const tipId = parsedTx.walletTipId; + 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( + TaskIdentifiers.forTipPickup(tipRecord), + ); + return buildTransactionForTip(tipRecord, retries); + }); + } + + 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); - let pushIncOrt = await tx.operationRetries.get(pushIncOpId); + const pushIncOpId = TaskIdentifiers.forPeerPushCredit(pushInc); + let pushIncOrt = await tx.operationRetries.get(pushIncOpId); - return buildTransactionForPeerPushCredit( - pushInc, - pushIncOrt, - ct.contractTermsRaw, - wg, - 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); + return buildTransactionForPeerPushCredit( + pushInc, + pushIncOrt, + ct.contractTermsRaw, + wg, + wgOrt, + ); + }); + } - 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); + case TransactionType.PeerPullCredit: { + const pursePub = parsedTx.pursePub; + 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; + 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.forPeerPullPaymentInitiation(pushInc); - let pushIncOrt = await tx.operationRetries.get(pushIncOpId); + const pushIncOpId = + TaskIdentifiers.forPeerPullPaymentInitiation(pushInc); + let pushIncOrt = await tx.operationRetries.get(pushIncOpId); - return buildTransactionForPeerPullCredit( - pushInc, - pushIncOrt, - ct.contractTermsRaw, - wg, - wgOrt, - ); - }); - } else { - const unknownTxType: never = type; - throw Error(`can't retrieve a '${unknownTxType}' transaction`); + return buildTransactionForPeerPullCredit( + pushInc, + pushIncOrt, + ct.contractTermsRaw, + wg, + wgOrt, + ); + }); + } } } -// FIXME: Just a marker helper for unknown states until DD37 is fully implemented. -const mkTxStateUnknown = () => ({ - major: TransactionMajorState.Unknown, -}); - function buildTransactionForPushPaymentDebit( pi: PeerPushPaymentInitiationRecord, contractTerms: PeerContractTerms, @@ -1293,7 +1308,13 @@ export function constructTransactionIdentifier( export function parseTransactionIdentifier( transactionId: string, ): 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) { case TransactionType.Deposit: @@ -1489,25 +1510,92 @@ export async function deleteTransaction( ws: InternalWalletState, transactionId: string, ): Promise { - const { type, args: rest } = parseId("txn", transactionId); - - if (type === TransactionType.PeerPushCredit) { - const peerPushPaymentIncomingId = rest[0]; - await ws.db - .mktx((x) => [ - x.withdrawalGroups, - x.peerPushPaymentIncoming, - x.tombstones, - ]) - .runReadWrite(async (tx) => { - const pushInc = await tx.peerPushPaymentIncoming.get( - peerPushPaymentIncomingId, - ); - if (!pushInc) { - return; - } - if (pushInc.withdrawalGroupId) { - const withdrawalGroupId = pushInc.withdrawalGroupId; + const parsedTx = parseTransactionIdentifier(transactionId); + + if (!parsedTx) { + throw Error("invalid transaction ID"); + } + + switch (parsedTx.tag) { + case TransactionType.PeerPushCredit: { + const peerPushPaymentIncomingId = parsedTx.peerPushPaymentIncomingId; + await ws.db + .mktx((x) => [ + x.withdrawalGroups, + x.peerPushPaymentIncoming, + x.tombstones, + ]) + .runReadWrite(async (tx) => { + const pushInc = await tx.peerPushPaymentIncoming.get( + peerPushPaymentIncomingId, + ); + 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( withdrawalGroupId, ); @@ -1516,170 +1604,124 @@ export async function deleteTransaction( await tx.tombstones.put({ id: TombstoneTag.DeleteWithdrawalGroup + ":" + withdrawalGroupId, }); + return; } - } - await tx.peerPushPaymentIncoming.delete(peerPushPaymentIncomingId); - await tx.tombstones.put({ - id: - TombstoneTag.DeletePeerPushCredit + ":" + peerPushPaymentIncomingId, }); - }); - } else if (type === TransactionType.PeerPullCredit) { - const pursePub = rest[0]; - 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, + return; + } + + case TransactionType.Payment: { + const proposalId = parsedTx.proposalId; + 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, + }); + } + }); + return; + } + + case TransactionType.Refresh: { + const refreshGroupId = parsedTx.refreshGroupId; + 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, + }); + } + }); + + return; + } + + case TransactionType.Tip: { + const tipId = parsedTx.walletTipId; + 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, + }); + } + }); + return; + } + + case TransactionType.Deposit: { + const depositGroupId = parsedTx.depositGroupId; + 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, + }); + } + }); + + return; + } + + 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 (withdrawalGroupRecord) { - await tx.withdrawalGroups.delete(withdrawalGroupId); + if (debit) { + await tx.peerPullPaymentIncoming.delete(peerPullPaymentIncomingId); await tx.tombstones.put({ - id: TombstoneTag.DeleteWithdrawalGroup + ":" + withdrawalGroupId, + id: makeTombstoneId( + TombstoneTag.DeletePeerPullDebit, + peerPullPaymentIncomingId, + ), }); } - } - await tx.peerPullPaymentInitiations.delete(pursePub); - await tx.tombstones.put({ - id: TombstoneTag.DeletePeerPullCredit + ":" + pursePub, }); - }); - } 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 - .mktx((x) => [x.purchases, x.tombstones]) - .runReadWrite(async (tx) => { - const purchase = await tx.purchases.get(proposalId); - if (purchase) { - // This should just influence the history view, - // but won't delete any actual refund information. - await tx.tombstones.put({ - id: makeTombstoneId( - TombstoneTag.DeleteRefund, - proposalId, - executionTimeStr, - ), - }); - } - }); - } else if (type === TransactionType.PeerPullDebit) { - const peerPullPaymentIncomingId = rest[0]; - 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, - ), - }); - } - }); - } else if (type === TransactionType.PeerPushDebit) { - const pursePub = rest[0]; - 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), - }); - } - }); - } else { - const unknownTxType: never = type; - throw Error(`can't delete a '${unknownTxType}' transaction`); + + 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; + } } } diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts index 2cb0a6253..d59d9fea3 100644 --- a/packages/taler-wallet-core/src/operations/withdraw.ts +++ b/packages/taler-wallet-core/src/operations/withdraw.ts @@ -118,7 +118,6 @@ import { WALLET_BANK_INTEGRATION_PROTOCOL_VERSION, WALLET_EXCHANGE_PROTOCOL_VERSION, } from "../versions.js"; -import { makeTransactionId } from "./common.js"; import { getExchangeDetails, getExchangePaytoUri, @@ -1456,10 +1455,10 @@ export async function processWithdrawalGroup( if (numKycRequired > 0) { if (kycInfo) { - const txId = makeTransactionId( - TransactionType.Withdrawal, - withdrawalGroup.withdrawalGroupId, - ); + const txId = constructTransactionIdentifier({ + tag: TransactionType.Withdrawal, + withdrawalGroupId: withdrawalGroup.withdrawalGroupId, + }); await checkWithdrawalKycStatus( ws, withdrawalGroup.exchangeBaseUrl, @@ -2050,12 +2049,13 @@ async function processReserveBankStatus( r.wgInfo.bankInfo.timestampBankConfirmed = now; r.status = WithdrawalGroupStatus.PendingQueryingStatus; // FIXME: Notification is deprecated with DD37. + const transactionId = constructTransactionIdentifier({ + tag: TransactionType.Withdrawal, + withdrawalGroupId: r.withdrawalGroupId, + }); ws.notify({ type: NotificationType.WithdrawalGroupBankConfirmed, - transactionId: makeTransactionId( - TransactionType.Withdrawal, - r.withdrawalGroupId, - ), + transactionId, }); } else { logger.info("withdrawal: transfer not yet confirmed by bank"); -- cgit v1.2.3