From 000359a5e746d9b704b05f2f3eb8442e10a31f75 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 30 May 2023 12:28:21 +0200 Subject: finish implementation of abort / cancelAborting on all tx types --- .../taler-wallet-core/src/operations/pay-peer.ts | 410 +++++++++++++++++++++ 1 file changed, 410 insertions(+) (limited to 'packages/taler-wallet-core/src/operations/pay-peer.ts') diff --git a/packages/taler-wallet-core/src/operations/pay-peer.ts b/packages/taler-wallet-core/src/operations/pay-peer.ts index 95878543b..031bdfb92 100644 --- a/packages/taler-wallet-core/src/operations/pay-peer.ts +++ b/packages/taler-wallet-core/src/operations/pay-peer.ts @@ -2005,6 +2005,10 @@ export function computePeerPushDebitTransactionState( return { major: TransactionMajorState.Done, }; + case PeerPushPaymentInitiationStatus.Failed: + return { + major: TransactionMajorState.Failed, + } } } @@ -2048,6 +2052,8 @@ export async function abortPeerPushDebitTransaction( case PeerPushPaymentInitiationStatus.Aborted: // Do nothing break; + case PeerPushPaymentInitiationStatus.Failed: + break; default: assertUnreachable(pushDebitRec.status); } @@ -2104,6 +2110,7 @@ export async function cancelAbortingPeerPushDebitTransaction( case PeerPushPaymentInitiationStatus.PendingCreatePurse: case PeerPushPaymentInitiationStatus.Done: case PeerPushPaymentInitiationStatus.Aborted: + case PeerPushPaymentInitiationStatus.Failed: // Do nothing break; default: @@ -2166,6 +2173,7 @@ export async function suspendPeerPushDebitTransaction( case PeerPushPaymentInitiationStatus.SuspendedCreatePurse: case PeerPushPaymentInitiationStatus.Done: case PeerPushPaymentInitiationStatus.Aborted: + case PeerPushPaymentInitiationStatus.Failed: // Do nothing break; default: @@ -2220,6 +2228,138 @@ export async function suspendPeerPullDebitTransaction( break; case PeerPullDebitRecordStatus.SuspendedDeposit: break; + case PeerPullDebitRecordStatus.Aborted: + break; + case PeerPullDebitRecordStatus.AbortingRefresh: + newStatus = PeerPullDebitRecordStatus.SuspendedAbortingRefresh; + break; + case PeerPullDebitRecordStatus.Failed: + break; + case PeerPullDebitRecordStatus.SuspendedAbortingRefresh: + break; + default: + assertUnreachable(pullDebitRec.status); + } + if (newStatus != null) { + const oldTxState = computePeerPullDebitTransactionState(pullDebitRec); + pullDebitRec.status = newStatus; + const newTxState = computePeerPullDebitTransactionState(pullDebitRec); + await tx.peerPullPaymentIncoming.put(pullDebitRec); + return { + oldTxState, + newTxState, + }; + } + return undefined; + }); + notifyTransition(ws, transactionId, transitionInfo); +} + +export async function abortPeerPullDebitTransaction( + ws: InternalWalletState, + peerPullPaymentIncomingId: string, +) { + const taskId = constructTaskIdentifier({ + tag: PendingTaskType.PeerPullDebit, + peerPullPaymentIncomingId, + }); + const transactionId = constructTransactionIdentifier({ + tag: TransactionType.PeerPullDebit, + peerPullPaymentIncomingId, + }); + stopLongpolling(ws, taskId); + const transitionInfo = await ws.db + .mktx((x) => [x.peerPullPaymentIncoming]) + .runReadWrite(async (tx) => { + const pullDebitRec = await tx.peerPullPaymentIncoming.get( + peerPullPaymentIncomingId, + ); + if (!pullDebitRec) { + logger.warn(`peer pull debit ${peerPullPaymentIncomingId} not found`); + return; + } + let newStatus: PeerPullDebitRecordStatus | undefined = undefined; + switch (pullDebitRec.status) { + case PeerPullDebitRecordStatus.DialogProposed: + newStatus = PeerPullDebitRecordStatus.Aborted; + break; + case PeerPullDebitRecordStatus.DonePaid: + break; + case PeerPullDebitRecordStatus.PendingDeposit: + newStatus = PeerPullDebitRecordStatus.AbortingRefresh; + break; + case PeerPullDebitRecordStatus.SuspendedDeposit: + break; + case PeerPullDebitRecordStatus.Aborted: + break; + case PeerPullDebitRecordStatus.AbortingRefresh: + break; + case PeerPullDebitRecordStatus.Failed: + break; + case PeerPullDebitRecordStatus.SuspendedAbortingRefresh: + break; + default: + assertUnreachable(pullDebitRec.status); + } + if (newStatus != null) { + const oldTxState = computePeerPullDebitTransactionState(pullDebitRec); + pullDebitRec.status = newStatus; + const newTxState = computePeerPullDebitTransactionState(pullDebitRec); + await tx.peerPullPaymentIncoming.put(pullDebitRec); + return { + oldTxState, + newTxState, + }; + } + return undefined; + }); + notifyTransition(ws, transactionId, transitionInfo); +} + + +export async function cancelAbortingPeerPullDebitTransaction( + ws: InternalWalletState, + peerPullPaymentIncomingId: string, +) { + const taskId = constructTaskIdentifier({ + tag: PendingTaskType.PeerPullDebit, + peerPullPaymentIncomingId, + }); + const transactionId = constructTransactionIdentifier({ + tag: TransactionType.PeerPullDebit, + peerPullPaymentIncomingId, + }); + stopLongpolling(ws, taskId); + const transitionInfo = await ws.db + .mktx((x) => [x.peerPullPaymentIncoming]) + .runReadWrite(async (tx) => { + const pullDebitRec = await tx.peerPullPaymentIncoming.get( + peerPullPaymentIncomingId, + ); + if (!pullDebitRec) { + logger.warn(`peer pull debit ${peerPullPaymentIncomingId} not found`); + return; + } + let newStatus: PeerPullDebitRecordStatus | undefined = undefined; + switch (pullDebitRec.status) { + case PeerPullDebitRecordStatus.DialogProposed: + newStatus = PeerPullDebitRecordStatus.Aborted; + break; + case PeerPullDebitRecordStatus.DonePaid: + break; + case PeerPullDebitRecordStatus.PendingDeposit: + break; + case PeerPullDebitRecordStatus.SuspendedDeposit: + break; + case PeerPullDebitRecordStatus.Aborted: + break; + case PeerPullDebitRecordStatus.Failed: + break; + case PeerPullDebitRecordStatus.SuspendedAbortingRefresh: + case PeerPullDebitRecordStatus.AbortingRefresh: + // FIXME: abort underlying refresh! + newStatus = PeerPullDebitRecordStatus.Failed; + break; default: assertUnreachable(pullDebitRec.status); } @@ -2270,6 +2410,15 @@ export async function resumePeerPullDebitTransaction( case PeerPullDebitRecordStatus.SuspendedDeposit: newStatus = PeerPullDebitRecordStatus.PendingDeposit; break; + case PeerPullDebitRecordStatus.Aborted: + break; + case PeerPullDebitRecordStatus.AbortingRefresh: + break; + case PeerPullDebitRecordStatus.Failed: + break; + case PeerPullDebitRecordStatus.SuspendedAbortingRefresh: + newStatus = PeerPullDebitRecordStatus.AbortingRefresh; + break; default: assertUnreachable(pullDebitRec.status); } @@ -2330,6 +2479,10 @@ export async function suspendPeerPushCreditTransaction( // FIXME: Suspend internal withdrawal transaction! newStatus = PeerPushPaymentIncomingStatus.SuspendedWithdrawing; break; + case PeerPushPaymentIncomingStatus.Aborted: + break; + case PeerPushPaymentIncomingStatus.Failed: + break; default: assertUnreachable(pushCreditRec.status); } @@ -2348,6 +2501,81 @@ export async function suspendPeerPushCreditTransaction( notifyTransition(ws, transactionId, transitionInfo); } + +export async function abortPeerPushCreditTransaction( + ws: InternalWalletState, + peerPushPaymentIncomingId: string, +) { + const taskId = constructTaskIdentifier({ + tag: PendingTaskType.PeerPushCredit, + peerPushPaymentIncomingId, + }); + const transactionId = constructTransactionIdentifier({ + tag: TransactionType.PeerPushCredit, + peerPushPaymentIncomingId, + }); + stopLongpolling(ws, taskId); + const transitionInfo = await ws.db + .mktx((x) => [x.peerPushPaymentIncoming]) + .runReadWrite(async (tx) => { + const pushCreditRec = await tx.peerPushPaymentIncoming.get( + peerPushPaymentIncomingId, + ); + if (!pushCreditRec) { + logger.warn(`peer push credit ${peerPushPaymentIncomingId} not found`); + return; + } + let newStatus: PeerPushPaymentIncomingStatus | undefined = undefined; + switch (pushCreditRec.status) { + case PeerPushPaymentIncomingStatus.DialogProposed: + newStatus = PeerPushPaymentIncomingStatus.Aborted; + break; + case PeerPushPaymentIncomingStatus.Done: + break; + case PeerPushPaymentIncomingStatus.SuspendedMerge: + case PeerPushPaymentIncomingStatus.SuspendedMergeKycRequired: + case PeerPushPaymentIncomingStatus.SuspendedWithdrawing: + newStatus = PeerPushPaymentIncomingStatus.Aborted; + break; + case PeerPushPaymentIncomingStatus.PendingMergeKycRequired: + newStatus = PeerPushPaymentIncomingStatus.Aborted; + break; + case PeerPushPaymentIncomingStatus.PendingMerge: + newStatus = PeerPushPaymentIncomingStatus.Aborted; + break; + case PeerPushPaymentIncomingStatus.PendingWithdrawing: + newStatus = PeerPushPaymentIncomingStatus.Aborted; + break; + case PeerPushPaymentIncomingStatus.Aborted: + break; + case PeerPushPaymentIncomingStatus.Failed: + break; + default: + assertUnreachable(pushCreditRec.status); + } + if (newStatus != null) { + const oldTxState = computePeerPushCreditTransactionState(pushCreditRec); + pushCreditRec.status = newStatus; + const newTxState = computePeerPushCreditTransactionState(pushCreditRec); + await tx.peerPushPaymentIncoming.put(pushCreditRec); + return { + oldTxState, + newTxState, + }; + } + return undefined; + }); + notifyTransition(ws, transactionId, transitionInfo); +} + +export async function cancelAbortingPeerPushCreditTransaction( + ws: InternalWalletState, + peerPushPaymentIncomingId: string, +) { + // We don't have any "aborting" states! + throw Error("can't run cancel-aborting on peer-push-credit transaction"); +} + export async function resumePeerPushCreditTransaction( ws: InternalWalletState, peerPushPaymentIncomingId: string, @@ -2388,6 +2616,10 @@ export async function resumePeerPushCreditTransaction( // FIXME: resume underlying "internal-withdrawal" transaction. newStatus = PeerPushPaymentIncomingStatus.PendingWithdrawing; break; + case PeerPushPaymentIncomingStatus.Aborted: + break; + case PeerPushPaymentIncomingStatus.Failed: + break; default: assertUnreachable(pushCreditRec.status); } @@ -2442,11 +2674,135 @@ export async function suspendPeerPullCreditTransaction( case PeerPullPaymentInitiationStatus.PendingReady: newStatus = PeerPullPaymentInitiationStatus.SuspendedReady; break; + case PeerPullPaymentInitiationStatus.AbortingDeletePurse: + newStatus = + PeerPullPaymentInitiationStatus.SuspendedAbortingDeletePurse; + break; + case PeerPullPaymentInitiationStatus.DonePurseDeposited: + case PeerPullPaymentInitiationStatus.SuspendedCreatePurse: + case PeerPullPaymentInitiationStatus.SuspendedMergeKycRequired: + case PeerPullPaymentInitiationStatus.SuspendedReady: + case PeerPullPaymentInitiationStatus.SuspendedWithdrawing: + case PeerPullPaymentInitiationStatus.Aborted: + case PeerPullPaymentInitiationStatus.Failed: + case PeerPullPaymentInitiationStatus.SuspendedAbortingDeletePurse: + break; + default: + assertUnreachable(pullCreditRec.status); + } + if (newStatus != null) { + const oldTxState = computePeerPullCreditTransactionState(pullCreditRec); + pullCreditRec.status = newStatus; + const newTxState = computePeerPullCreditTransactionState(pullCreditRec); + await tx.peerPullPaymentInitiations.put(pullCreditRec); + return { + oldTxState, + newTxState, + }; + } + return undefined; + }); + notifyTransition(ws, transactionId, transitionInfo); +} + +export async function abortPeerPullCreditTransaction( + ws: InternalWalletState, + pursePub: string, +) { + const taskId = constructTaskIdentifier({ + tag: PendingTaskType.PeerPullCredit, + pursePub, + }); + const transactionId = constructTransactionIdentifier({ + tag: TransactionType.PeerPullCredit, + pursePub, + }); + stopLongpolling(ws, taskId); + const transitionInfo = await ws.db + .mktx((x) => [x.peerPullPaymentInitiations]) + .runReadWrite(async (tx) => { + const pullCreditRec = await tx.peerPullPaymentInitiations.get(pursePub); + if (!pullCreditRec) { + logger.warn(`peer pull credit ${pursePub} not found`); + return; + } + let newStatus: PeerPullPaymentInitiationStatus | undefined = undefined; + switch (pullCreditRec.status) { + case PeerPullPaymentInitiationStatus.PendingCreatePurse: + case PeerPullPaymentInitiationStatus.PendingMergeKycRequired: + newStatus = PeerPullPaymentInitiationStatus.AbortingDeletePurse; + break; + case PeerPullPaymentInitiationStatus.PendingWithdrawing: + throw Error("can't abort anymore"); + case PeerPullPaymentInitiationStatus.PendingReady: + newStatus = PeerPullPaymentInitiationStatus.AbortingDeletePurse; + break; + case PeerPullPaymentInitiationStatus.DonePurseDeposited: + case PeerPullPaymentInitiationStatus.SuspendedCreatePurse: + case PeerPullPaymentInitiationStatus.SuspendedMergeKycRequired: + case PeerPullPaymentInitiationStatus.SuspendedReady: + case PeerPullPaymentInitiationStatus.SuspendedWithdrawing: + case PeerPullPaymentInitiationStatus.Aborted: + case PeerPullPaymentInitiationStatus.AbortingDeletePurse: + case PeerPullPaymentInitiationStatus.Failed: + case PeerPullPaymentInitiationStatus.SuspendedAbortingDeletePurse: + break; + default: + assertUnreachable(pullCreditRec.status); + } + if (newStatus != null) { + const oldTxState = computePeerPullCreditTransactionState(pullCreditRec); + pullCreditRec.status = newStatus; + const newTxState = computePeerPullCreditTransactionState(pullCreditRec); + await tx.peerPullPaymentInitiations.put(pullCreditRec); + return { + oldTxState, + newTxState, + }; + } + return undefined; + }); + notifyTransition(ws, transactionId, transitionInfo); +} + +export async function cancelAbortingPeerPullCreditTransaction( + ws: InternalWalletState, + pursePub: string, +) { + const taskId = constructTaskIdentifier({ + tag: PendingTaskType.PeerPullCredit, + pursePub, + }); + const transactionId = constructTransactionIdentifier({ + tag: TransactionType.PeerPullCredit, + pursePub, + }); + stopLongpolling(ws, taskId); + const transitionInfo = await ws.db + .mktx((x) => [x.peerPullPaymentInitiations]) + .runReadWrite(async (tx) => { + const pullCreditRec = await tx.peerPullPaymentInitiations.get(pursePub); + if (!pullCreditRec) { + logger.warn(`peer pull credit ${pursePub} not found`); + return; + } + let newStatus: PeerPullPaymentInitiationStatus | undefined = undefined; + switch (pullCreditRec.status) { + case PeerPullPaymentInitiationStatus.PendingCreatePurse: + case PeerPullPaymentInitiationStatus.PendingMergeKycRequired: + case PeerPullPaymentInitiationStatus.PendingWithdrawing: + case PeerPullPaymentInitiationStatus.PendingReady: case PeerPullPaymentInitiationStatus.DonePurseDeposited: case PeerPullPaymentInitiationStatus.SuspendedCreatePurse: case PeerPullPaymentInitiationStatus.SuspendedMergeKycRequired: case PeerPullPaymentInitiationStatus.SuspendedReady: case PeerPullPaymentInitiationStatus.SuspendedWithdrawing: + case PeerPullPaymentInitiationStatus.Aborted: + case PeerPullPaymentInitiationStatus.Failed: + break; + case PeerPullPaymentInitiationStatus.AbortingDeletePurse: + case PeerPullPaymentInitiationStatus.SuspendedAbortingDeletePurse: + newStatus = PeerPullPaymentInitiationStatus.Failed; break; default: assertUnreachable(pullCreditRec.status); @@ -2493,7 +2849,11 @@ export async function resumePeerPullCreditTransaction( case PeerPullPaymentInitiationStatus.PendingMergeKycRequired: case PeerPullPaymentInitiationStatus.PendingWithdrawing: case PeerPullPaymentInitiationStatus.PendingReady: + case PeerPullPaymentInitiationStatus.AbortingDeletePurse: case PeerPullPaymentInitiationStatus.DonePurseDeposited: + case PeerPullPaymentInitiationStatus.Failed: + case PeerPullPaymentInitiationStatus.Aborted: + break; case PeerPullPaymentInitiationStatus.SuspendedCreatePurse: newStatus = PeerPullPaymentInitiationStatus.PendingCreatePurse; break; @@ -2506,6 +2866,9 @@ export async function resumePeerPullCreditTransaction( case PeerPullPaymentInitiationStatus.SuspendedWithdrawing: newStatus = PeerPullPaymentInitiationStatus.PendingWithdrawing; break; + case PeerPullPaymentInitiationStatus.SuspendedAbortingDeletePurse: + newStatus = PeerPullPaymentInitiationStatus.AbortingDeletePurse; + break; default: assertUnreachable(pullCreditRec.status); } @@ -2566,6 +2929,7 @@ export async function resumePeerPushDebitTransaction( case PeerPushPaymentInitiationStatus.PendingReady: case PeerPushPaymentInitiationStatus.Done: case PeerPushPaymentInitiationStatus.Aborted: + case PeerPushPaymentInitiationStatus.Failed: // Do nothing break; default: @@ -2630,6 +2994,16 @@ export function computePeerPushCreditTransactionState( major: TransactionMajorState.Suspended, minor: TransactionMinorState.Withdraw, }; + case PeerPushPaymentIncomingStatus.Aborted: + return { + major: TransactionMajorState.Aborted + }; + case PeerPushPaymentIncomingStatus.Failed: + return { + major: TransactionMajorState.Failed, + } + default: + assertUnreachable(pushCreditRecord.status); } } @@ -2681,6 +3055,24 @@ export function computePeerPullCreditTransactionState( major: TransactionMajorState.Suspended, minor: TransactionMinorState.MergeKycRequired, }; + case PeerPullPaymentInitiationStatus.Aborted: + return { + major: TransactionMajorState.Aborted, + }; + case PeerPullPaymentInitiationStatus.AbortingDeletePurse: + return { + major: TransactionMajorState.Aborting, + minor: TransactionMinorState.DeletePurse, + }; + case PeerPullPaymentInitiationStatus.Failed: + return { + major: TransactionMajorState.Failed, + }; + case PeerPullPaymentInitiationStatus.SuspendedAbortingDeletePurse: + return { + major: TransactionMajorState.Aborting, + minor: TransactionMinorState.DeletePurse, + }; } } @@ -2707,5 +3099,23 @@ export function computePeerPullDebitTransactionState( major: TransactionMajorState.Suspended, minor: TransactionMinorState.Deposit, }; + case PeerPullDebitRecordStatus.Aborted: + return { + major: TransactionMajorState.Aborted, + }; + case PeerPullDebitRecordStatus.AbortingRefresh: + return { + major: TransactionMajorState.Aborting, + minor: TransactionMinorState.Refresh, + }; + case PeerPullDebitRecordStatus.Failed: + return { + major: TransactionMajorState.Failed, + }; + case PeerPullDebitRecordStatus.SuspendedAbortingRefresh: + return { + major: TransactionMajorState.SuspendedAborting, + minor: TransactionMinorState.Refresh, + }; } } -- cgit v1.2.3