From a8fb16021d6f71e6d0c7fae6b440e5c3197b8867 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 20 Aug 2020 14:34:56 +0530 Subject: handle withdrawals aborted by the bank, add test --- .../taler-wallet-core/src/operations/reserves.ts | 32 +++++++++++++++++++++- .../src/operations/transactions.ts | 4 +++ 2 files changed, 35 insertions(+), 1 deletion(-) (limited to 'packages/taler-wallet-core/src/operations') diff --git a/packages/taler-wallet-core/src/operations/reserves.ts b/packages/taler-wallet-core/src/operations/reserves.ts index fb525da45..8adaeea81 100644 --- a/packages/taler-wallet-core/src/operations/reserves.ts +++ b/packages/taler-wallet-core/src/operations/reserves.ts @@ -60,6 +60,7 @@ import { guardOperationException, OperationFailedAndReportedError, makeErrorDetails, + OperationFailedError, } from "./errors"; import { NotificationType } from "../types/notifications"; import { codecForReserveStatus } from "../types/ReserveStatus"; @@ -358,7 +359,7 @@ async function registerReserveWithBank( return processReserveBankStatus(ws, reservePub); } -export async function processReserveBankStatus( +async function processReserveBankStatus( ws: InternalWalletState, reservePub: string, ): Promise { @@ -393,6 +394,25 @@ async function processReserveBankStatusImpl( codecForWithdrawOperationStatusResponse(), ); + if (status.aborted) { + logger.trace("bank aborted the withdrawal"); + await ws.db.mutate(Stores.reserves, reservePub, (r) => { + switch (r.reserveStatus) { + case ReserveRecordStatus.REGISTERING_BANK: + case ReserveRecordStatus.WAIT_CONFIRM_BANK: + break; + default: + return; + } + const now = getTimestampNow(); + r.timestampBankConfirmed = now; + r.reserveStatus = ReserveRecordStatus.BANK_ABORTED; + r.retryInfo = initRetryInfo(); + return r; + }); + return; + } + if (status.selection_done) { if (reserve.reserveStatus === ReserveRecordStatus.REGISTERING_BANK) { await registerReserveWithBank(ws, reservePub); @@ -612,6 +632,8 @@ async function processReserveImpl( case ReserveRecordStatus.WAIT_CONFIRM_BANK: await processReserveBankStatus(ws, reservePub); break; + case ReserveRecordStatus.BANK_ABORTED: + break; default: console.warn("unknown reserve record status:", reserve.reserveStatus); assertUnreachable(reserve.reserveStatus); @@ -802,6 +824,14 @@ export async function createTalerWithdrawReserve( // We do this here, as the reserve should be registered before we return, // so that we can redirect the user to the bank's status page. await processReserveBankStatus(ws, reserve.reservePub); + const processedReserve = await ws.db.get(Stores.reserves, reserve.reservePub); + if (processedReserve?.reserveStatus === ReserveRecordStatus.BANK_ABORTED) { + throw OperationFailedError.fromCode( + TalerErrorCode.WALLET_WITHDRAWAL_OPERATION_ABORTED_BY_BANK, + "withdrawal aborted by bank", + {}, + ); + } return { reservePub: reserve.reservePub, confirmTransferUrl: withdrawInfo.confirmTransferUrl, diff --git a/packages/taler-wallet-core/src/operations/transactions.ts b/packages/taler-wallet-core/src/operations/transactions.ts index 8d0558dbd..b79ac3b27 100644 --- a/packages/taler-wallet-core/src/operations/transactions.ts +++ b/packages/taler-wallet-core/src/operations/transactions.ts @@ -23,6 +23,7 @@ import { WithdrawalSourceType, WalletRefundItem, RefundState, + ReserveRecordStatus, } from "../types/dbTypes"; import { Amounts, AmountJson } from "../util/amounts"; import { timestampCmp, Timestamp } from "../util/time"; @@ -186,6 +187,9 @@ export async function getTransactions( if (r.initialWithdrawalStarted) { return; } + if (r.reserveStatus === ReserveRecordStatus.BANK_ABORTED) { + return; + } let withdrawalDetails: WithdrawalDetails; if (r.bankInfo) { withdrawalDetails = { -- cgit v1.2.3