diff options
author | Florian Dold <florian@dold.me> | 2023-06-05 17:58:20 +0200 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2023-06-05 17:58:25 +0200 |
commit | 9fca44893a6f7fcee5c828da5fc10e7d76592b5d (patch) | |
tree | 634830c7a769302d5e107f2aee323c3f705cf113 /packages/taler-wallet-core/src/operations/pay-peer-pull-debit.ts | |
parent | 6e7c88a62073082b28ef563561d08f56acc0b017 (diff) | |
download | wallet-core-9fca44893a6f7fcee5c828da5fc10e7d76592b5d.tar.xz |
wallet-core: handle more p2p abort cases nicely
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 | 127 |
1 files changed, 112 insertions, 15 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 fdec42bbd..212d69eea 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 @@ -15,55 +15,152 @@ */ import { - ConfirmPeerPullDebitRequest, AcceptPeerPullPaymentResponse, Amounts, - j2s, - TalerError, - TalerErrorCode, - TransactionType, - RefreshReason, + ConfirmPeerPullDebitRequest, + ExchangePurseDeposits, Logger, PeerContractTerms, PreparePeerPullDebitRequest, PreparePeerPullDebitResponse, + RefreshReason, + TalerError, + TalerErrorCode, TalerPreciseTimestamp, + TransactionAction, + TransactionMajorState, + TransactionMinorState, + TransactionState, + TransactionType, + codecForAny, codecForExchangeGetContractResponse, codecForPeerContractTerms, decodeCrock, eddsaGetPublic, encodeCrock, getRandomBytes, + j2s, parsePayPullUri, - TransactionAction, - TransactionMajorState, - TransactionMinorState, - TransactionState, } from "@gnu-taler/taler-util"; +import { readSuccessResponseJsonOrThrow } from "@gnu-taler/taler-util/http"; import { InternalWalletState, PeerPullDebitRecordStatus, PeerPullPaymentIncomingRecord, PendingTaskType, } from "../index.js"; -import { TaskIdentifiers, constructTaskIdentifier } from "../util/retries.js"; -import { spendCoins, runOperationWithErrorReporting } from "./common.js"; +import { assertUnreachable } from "../util/assertUnreachable.js"; +import { + OperationAttemptResult, + OperationAttemptResultType, + TaskIdentifiers, + constructTaskIdentifier, +} from "../util/retries.js"; +import { runOperationWithErrorReporting, spendCoins } from "./common.js"; import { codecForExchangePurseStatus, getTotalPeerPaymentCost, + queryCoinInfosForSelection, selectPeerCoins, } from "./pay-peer-common.js"; -import { processPeerPullDebit } from "./pay-peer-push-credit.js"; import { constructTransactionIdentifier, notifyTransition, stopLongpolling, } from "./transactions.js"; -import { readSuccessResponseJsonOrThrow } from "@gnu-taler/taler-util/http"; -import { assertUnreachable } from "../util/assertUnreachable.js"; const logger = new Logger("pay-peer-pull-debit.ts"); +async function processPeerPullDebitPendingDeposit( + ws: InternalWalletState, + peerPullInc: PeerPullPaymentIncomingRecord, +): Promise<OperationAttemptResult> { + const peerPullPaymentIncomingId = peerPullInc.peerPullPaymentIncomingId; + const pursePub = peerPullInc.pursePub; + + const coinSel = peerPullInc.coinSel; + if (!coinSel) { + throw Error("invalid state, no coins selected"); + } + + const coins = await queryCoinInfosForSelection(ws, coinSel); + + const depositSigsResp = await ws.cryptoApi.signPurseDeposits({ + exchangeBaseUrl: peerPullInc.exchangeBaseUrl, + pursePub: peerPullInc.pursePub, + coins, + }); + + const purseDepositUrl = new URL( + `purses/${pursePub}/deposit`, + peerPullInc.exchangeBaseUrl, + ); + + const depositPayload: ExchangePurseDeposits = { + deposits: depositSigsResp.deposits, + }; + + if (logger.shouldLogTrace()) { + 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)}`); + + 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) { + pi.status = PeerPullDebitRecordStatus.DonePaid; + } + await tx.peerPullPaymentIncoming.put(pi); + }); + + return { + type: OperationAttemptResultType.Finished, + result: undefined, + }; +} + +async function processPeerPullDebitAbortingRefresh( + ws: InternalWalletState, + peerPullInc: PeerPullPaymentIncomingRecord, +): Promise<OperationAttemptResult> { + throw Error("not implemented"); +} + +export async function processPeerPullDebit( + ws: InternalWalletState, + peerPullPaymentIncomingId: string, +): Promise<OperationAttemptResult> { + const peerPullInc = await ws.db + .mktx((x) => [x.peerPullPaymentIncoming]) + .runReadOnly(async (tx) => { + return tx.peerPullPaymentIncoming.get(peerPullPaymentIncomingId); + }); + if (!peerPullInc) { + throw Error("peer pull debit not found"); + } + + switch (peerPullInc.status) { + case PeerPullDebitRecordStatus.PendingDeposit: + return await processPeerPullDebitPendingDeposit(ws, peerPullInc); + case PeerPullDebitRecordStatus.AbortingRefresh: + return await processPeerPullDebitAbortingRefresh(ws, peerPullInc); + } + return { + type: OperationAttemptResultType.Finished, + result: undefined, + } +} + export async function confirmPeerPullDebit( ws: InternalWalletState, req: ConfirmPeerPullDebitRequest, |