diff options
author | Florian Dold <florian@dold.me> | 2023-06-05 18:38:17 +0200 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2023-06-05 18:38:17 +0200 |
commit | da927b5e48453b5bddb56944f7073619f693f526 (patch) | |
tree | 1aa84cfad016bbe665715e1ef7171dd9a3d586b5 /packages/taler-wallet-core/src/operations/pay-peer-pull-debit.ts | |
parent | bdb67c83a9d0244ba58e22f4811736722bbcb659 (diff) |
wallet-core: handle Gone in peer-pull-debit
Diffstat (limited to 'packages/taler-wallet-core/src/operations/pay-peer-pull-debit.ts')
-rw-r--r-- | packages/taler-wallet-core/src/operations/pay-peer-pull-debit.ts | 149 |
1 files changed, 131 insertions, 18 deletions
diff --git a/packages/taler-wallet-core/src/operations/pay-peer-pull-debit.ts b/packages/taler-wallet-core/src/operations/pay-peer-pull-debit.ts index 212d69eea..2be21c68d 100644 --- a/packages/taler-wallet-core/src/operations/pay-peer-pull-debit.ts +++ b/packages/taler-wallet-core/src/operations/pay-peer-pull-debit.ts @@ -17,8 +17,10 @@ import { AcceptPeerPullPaymentResponse, Amounts, + CoinRefreshRequest, ConfirmPeerPullDebitRequest, ExchangePurseDeposits, + HttpStatusCode, Logger, PeerContractTerms, PreparePeerPullDebitRequest, @@ -48,6 +50,8 @@ import { PeerPullDebitRecordStatus, PeerPullPaymentIncomingRecord, PendingTaskType, + RefreshOperationStatus, + createRefreshGroup, } from "../index.js"; import { assertUnreachable } from "../util/assertUnreachable.js"; import { @@ -68,6 +72,7 @@ import { notifyTransition, stopLongpolling, } from "./transactions.js"; +import { checkLogicInvariant } from "../util/invariants.js"; const logger = new Logger("pay-peer-pull-debit.ts"); @@ -104,24 +109,89 @@ async function processPeerPullDebitPendingDeposit( logger.trace(`purse deposit payload: ${j2s(depositPayload)}`); } - const httpResp = await ws.http.postJson(purseDepositUrl.href, depositPayload); - const resp = await readSuccessResponseJsonOrThrow(httpResp, codecForAny()); - logger.trace(`purse deposit response: ${j2s(resp)}`); + const transactionId = constructTransactionIdentifier({ + tag: TransactionType.PeerPullDebit, + peerPullPaymentIncomingId, + }); - await ws.db - .mktx((x) => [x.peerPullPaymentIncoming]) - .runReadWrite(async (tx) => { - const pi = await tx.peerPullPaymentIncoming.get( - peerPullPaymentIncomingId, - ); - if (!pi) { - throw Error("peer pull payment not found anymore"); - } - if (pi.status === PeerPullDebitRecordStatus.PendingDeposit) { + const httpResp = await ws.http.fetch(purseDepositUrl.href, { + method: "POST", + body: depositPayload, + }); + if (httpResp.status === HttpStatusCode.Gone) { + const transitionInfo = await ws.db + .mktx((x) => [ + x.peerPullPaymentIncoming, + x.refreshGroups, + x.denominations, + x.coinAvailability, + x.coins, + ]) + .runReadWrite(async (tx) => { + const pi = await tx.peerPullPaymentIncoming.get( + peerPullPaymentIncomingId, + ); + if (!pi) { + throw Error("peer pull payment not found anymore"); + } + if (pi.status !== PeerPullDebitRecordStatus.PendingDeposit) { + return; + } + const oldTxState = computePeerPullDebitTransactionState(pi); + + const currency = Amounts.currencyOf(pi.totalCostEstimated); + const coinPubs: CoinRefreshRequest[] = []; + + if (!pi.coinSel) { + throw Error("invalid db state"); + } + + for (let i = 0; i < pi.coinSel.coinPubs.length; i++) { + coinPubs.push({ + amount: pi.coinSel.contributions[i], + coinPub: pi.coinSel.coinPubs[i], + }); + } + + const refresh = await createRefreshGroup( + ws, + tx, + currency, + coinPubs, + RefreshReason.AbortPeerPushDebit, + ); + + pi.status = PeerPullDebitRecordStatus.AbortingRefresh; + pi.abortRefreshGroupId = refresh.refreshGroupId; + const newTxState = computePeerPullDebitTransactionState(pi); + await tx.peerPullPaymentIncoming.put(pi); + return { oldTxState, newTxState }; + }); + notifyTransition(ws, transactionId, transitionInfo); + } else { + const resp = await readSuccessResponseJsonOrThrow(httpResp, codecForAny()); + logger.trace(`purse deposit response: ${j2s(resp)}`); + + const transitionInfo = await ws.db + .mktx((x) => [x.peerPullPaymentIncoming]) + .runReadWrite(async (tx) => { + const pi = await tx.peerPullPaymentIncoming.get( + peerPullPaymentIncomingId, + ); + if (!pi) { + throw Error("peer pull payment not found anymore"); + } + if (pi.status !== PeerPullDebitRecordStatus.PendingDeposit) { + return; + } + const oldTxState = computePeerPullDebitTransactionState(pi); pi.status = PeerPullDebitRecordStatus.DonePaid; - } - await tx.peerPullPaymentIncoming.put(pi); - }); + const newTxState = computePeerPullDebitTransactionState(pi); + await tx.peerPullPaymentIncoming.put(pi); + return { oldTxState, newTxState }; + }); + notifyTransition(ws, transactionId, transitionInfo); + } return { type: OperationAttemptResultType.Finished, @@ -133,7 +203,50 @@ async function processPeerPullDebitAbortingRefresh( ws: InternalWalletState, peerPullInc: PeerPullPaymentIncomingRecord, ): Promise<OperationAttemptResult> { - throw Error("not implemented"); + const peerPullPaymentIncomingId = peerPullInc.peerPullPaymentIncomingId; + const abortRefreshGroupId = peerPullInc.abortRefreshGroupId; + checkLogicInvariant(!!abortRefreshGroupId); + const transactionId = constructTransactionIdentifier({ + tag: TransactionType.PeerPullDebit, + peerPullPaymentIncomingId, + }); + const transitionInfo = await ws.db + .mktx((x) => [x.refreshGroups, x.peerPullPaymentIncoming]) + .runReadWrite(async (tx) => { + const refreshGroup = await tx.refreshGroups.get(abortRefreshGroupId); + let newOpState: PeerPullDebitRecordStatus | undefined; + if (!refreshGroup) { + // Maybe it got manually deleted? Means that we should + // just go into failed. + logger.warn("no aborting refresh group found for deposit group"); + newOpState = PeerPullDebitRecordStatus.Failed; + } else { + if (refreshGroup.operationStatus === RefreshOperationStatus.Finished) { + newOpState = PeerPullDebitRecordStatus.Aborted; + } else if ( + refreshGroup.operationStatus === RefreshOperationStatus.Failed + ) { + newOpState = PeerPullDebitRecordStatus.Failed; + } + } + if (newOpState) { + const newDg = await tx.peerPullPaymentIncoming.get( + peerPullPaymentIncomingId, + ); + if (!newDg) { + return; + } + const oldTxState = computePeerPullDebitTransactionState(newDg); + newDg.status = newOpState; + const newTxState = computePeerPullDebitTransactionState(newDg); + await tx.peerPullPaymentIncoming.put(newDg); + return { oldTxState, newTxState }; + } + return undefined; + }); + notifyTransition(ws, transactionId, transitionInfo); + // FIXME: Shouldn't this be finished in some cases?! + return OperationAttemptResult.pendingEmpty(); } export async function processPeerPullDebit( @@ -158,7 +271,7 @@ export async function processPeerPullDebit( return { type: OperationAttemptResultType.Finished, result: undefined, - } + }; } export async function confirmPeerPullDebit( |