diff options
-rw-r--r-- | packages/taler-harness/src/harness/faultInjection.ts | 17 | ||||
-rw-r--r-- | packages/taler-harness/src/integrationtests/testrunner.ts | 2 | ||||
-rw-r--r-- | packages/taler-util/src/transactions-types.ts | 11 | ||||
-rw-r--r-- | packages/taler-util/src/wallet-types.ts | 20 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/db.ts | 14 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/operations/backup/export.ts | 2 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/operations/exchanges.ts | 2 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/operations/pay-merchant.ts | 118 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/operations/transactions.ts | 68 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/util/query.ts | 1 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/wallet-api-types.ts | 18 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/wallet.ts | 11 |
12 files changed, 202 insertions, 82 deletions
diff --git a/packages/taler-harness/src/harness/faultInjection.ts b/packages/taler-harness/src/harness/faultInjection.ts index 4c3d0c123..f4d7fc4b9 100644 --- a/packages/taler-harness/src/harness/faultInjection.ts +++ b/packages/taler-harness/src/harness/faultInjection.ts @@ -47,6 +47,10 @@ export interface FaultInjectionRequestContext { requestHeaders: Record<string, string | string[] | undefined>; requestBody?: Buffer; dropRequest: boolean; + // These are only used when the request is dropped + substituteResponseBody?: Buffer; + substituteResponseStatusCode?: number; + substituteResponseHeaders?: Record<string, string | string[] | undefined>; } export interface FaultInjectionResponseContext { @@ -101,7 +105,18 @@ export class FaultProxy { } if (faultReqContext.dropRequest) { - res.destroy(); + if (faultReqContext.substituteResponseStatusCode) { + const statusCode = faultReqContext.substituteResponseStatusCode; + res.writeHead( + statusCode, + http.STATUS_CODES[statusCode], + faultReqContext.substituteResponseHeaders, + ); + res.write(faultReqContext.substituteResponseBody); + res.end(); + } else { + res.destroy(); + } return; } diff --git a/packages/taler-harness/src/integrationtests/testrunner.ts b/packages/taler-harness/src/integrationtests/testrunner.ts index 9e64a151a..b5afa5d5b 100644 --- a/packages/taler-harness/src/integrationtests/testrunner.ts +++ b/packages/taler-harness/src/integrationtests/testrunner.ts @@ -97,6 +97,7 @@ import { runAgeRestrictionsMixedMerchantTest } from "./test-age-restrictions-mix import { runWalletCryptoWorkerTest } from "./test-wallet-cryptoworker.js"; import { runWithdrawalHighTest } from "./test-withdrawal-high.js"; import { runKycTest } from "./test-kyc.js"; +import { runPaymentAbortTest } from "./test-payment-abort.js"; /** * Test runner. @@ -159,6 +160,7 @@ const allTests: TestMainFunction[] = [ runPaymentIdempotencyTest, runPaymentMultipleTest, runPaymentTest, + runPaymentAbortTest, runPaymentTransientTest, runPaymentZeroTest, runPayPaidTest, diff --git a/packages/taler-util/src/transactions-types.ts b/packages/taler-util/src/transactions-types.ts index 62caaa055..59116a150 100644 --- a/packages/taler-util/src/transactions-types.ts +++ b/packages/taler-util/src/transactions-types.ts @@ -49,6 +49,15 @@ import { TransactionIdStr, } from "./wallet-types.js"; +export enum ExtendedStatus { + Pending = "pending", + Done = "done", + Aborting = "aborting", + Aborted = "aborted", + Failed = "failed", + KycRequired = "kyc-required", +} + export interface TransactionsRequest { /** * return only transactions in the given currency @@ -80,6 +89,8 @@ export interface TransactionCommon { // main timestamp of the transaction timestamp: TalerProtocolTimestamp; + extendedStatus: ExtendedStatus; + // true if the transaction is still pending, false otherwise // If a transaction is not longer pending, its timestamp will be updated, // but its transactionId will remain unchanged diff --git a/packages/taler-util/src/wallet-types.ts b/packages/taler-util/src/wallet-types.ts index b33eac0df..1ad5ef0ec 100644 --- a/packages/taler-util/src/wallet-types.ts +++ b/packages/taler-util/src/wallet-types.ts @@ -538,7 +538,7 @@ export interface WalletDiagnostics { export interface TalerErrorDetail { code: TalerErrorCode; - when: string; + when?: string; hint?: string; [x: string]: unknown; } @@ -1553,8 +1553,8 @@ export const codecForAcceptTipRequest = (): Codec<AcceptTipRequest> => .property("walletTipId", codecForString()) .build("AcceptTipRequest"); -export interface AbortPayRequest { - proposalId: string; +export interface AbortTransactionRequest { + transactionId: string; /** * Move the payment immediately into an aborted state. @@ -1563,15 +1563,15 @@ export interface AbortPayRequest { * * Defaults to false. */ - cancelImmediately?: boolean; + forceImmediateAbort?: boolean; } -export const codecForAbortPayRequest = - (): Codec<AbortPayRequest> => - buildCodecForObject<AbortPayRequest>() - .property("proposalId", codecForString()) - .property("cancelImmediately", codecOptional(codecForBoolean())) - .build("AbortPayRequest"); +export const codecForAbortTransaction = + (): Codec<AbortTransactionRequest> => + buildCodecForObject<AbortTransactionRequest>() + .property("transactionId", codecForString()) + .property("forceImmediateAbort", codecOptional(codecForBoolean())) + .build("AbortTransactionRequest"); export interface GetFeeForDepositRequest { depositPaytoUri: string; diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts index f3ef3aea5..7f114df78 100644 --- a/packages/taler-wallet-core/src/db.ts +++ b/packages/taler-wallet-core/src/db.ts @@ -849,6 +849,13 @@ export enum RefreshOperationStatus { } /** + * Additional information about the reason of a refresh. + */ +export interface RefreshReasonDetails { + proposalId?: string; +} + +/** * Group of refresh operations. The refreshed coins do not * have to belong to the same exchange, but must have the same * currency. @@ -880,6 +887,11 @@ export interface RefreshGroupRecord { */ reason: RefreshReason; + /** + * Extra information depending on the reason. + */ + reasonDetails?: RefreshReasonDetails; + oldCoinPubs: string[]; // FIXME: Should this go into a separate @@ -2006,7 +2018,7 @@ export const WalletStoresV1 = { ), }, ), - exchangeSignkeys: describeStore( + exchangeSignKeys: describeStore( "exchangeSignKeys", describeContents<ExchangeSignkeysRecord>({ keyPath: ["exchangeDetailsRowId", "signkeyPub"], diff --git a/packages/taler-wallet-core/src/operations/backup/export.ts b/packages/taler-wallet-core/src/operations/backup/export.ts index 965d51776..a66444485 100644 --- a/packages/taler-wallet-core/src/operations/backup/export.ts +++ b/packages/taler-wallet-core/src/operations/backup/export.ts @@ -89,7 +89,7 @@ export async function exportBackup( x.config, x.exchanges, x.exchangeDetails, - x.exchangeSignkeys, + x.exchangeSignKeys, x.coins, x.contractTerms, x.denominations, diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts b/packages/taler-wallet-core/src/operations/exchanges.ts index b6e2a9d73..67f77de77 100644 --- a/packages/taler-wallet-core/src/operations/exchanges.ts +++ b/packages/taler-wallet-core/src/operations/exchanges.ts @@ -675,7 +675,7 @@ export async function updateExchangeFromUrlHandler( x.exchanges, x.exchangeTos, x.exchangeDetails, - x.exchangeSignkeys, + x.exchangeSignKeys, x.denominations, x.coins, x.refreshGroups, diff --git a/packages/taler-wallet-core/src/operations/pay-merchant.ts b/packages/taler-wallet-core/src/operations/pay-merchant.ts index c8e3230b9..2f1f3375c 100644 --- a/packages/taler-wallet-core/src/operations/pay-merchant.ts +++ b/packages/taler-wallet-core/src/operations/pay-merchant.ts @@ -125,6 +125,7 @@ import { } from "../util/retries.js"; import { makeTransactionId, + runOperationWithErrorReporting, spendCoins, storeOperationError, storeOperationPending, @@ -1135,9 +1136,9 @@ export function selectForced( export type SelectPayCoinsResult = | { - type: "failure"; - insufficientBalanceDetails: PayMerchantInsufficientBalanceDetails; - } + type: "failure"; + insufficientBalanceDetails: PayMerchantInsufficientBalanceDetails; + } | { type: "success"; coinSel: PayCoinSelection }; /** @@ -1594,7 +1595,12 @@ export async function runPayForConfirmPay( ws: InternalWalletState, proposalId: string, ): Promise<ConfirmPayResult> { - const res = await processPurchasePay(ws, proposalId, { forceNow: true }); + logger.trace("processing proposal for confirmPay"); + const opId = RetryTags.byPaymentProposalId(proposalId); + const res = await runOperationWithErrorReporting(ws, opId, async () => { + return await processPurchasePay(ws, proposalId, { forceNow: true }); + }); + logger.trace(`processPurchasePay response type ${res.type}`); switch (res.type) { case OperationAttemptResultType.Finished: { const purchase = await ws.db @@ -1623,9 +1629,10 @@ export async function runPayForConfirmPay( const numRetry = opRetry?.retryInfo.retryCounter ?? 0; if ( res.errorDetail.code === - TalerErrorCode.WALLET_PAY_MERCHANT_SERVER_ERROR && + TalerErrorCode.WALLET_PAY_MERCHANT_SERVER_ERROR && numRetry < maxRetry ) { + logger.trace("hiding transient error from caller"); // Pretend the operation is pending instead of reporting // an error, but only up to maxRetry attempts. await storeOperationPending( @@ -1638,20 +1645,11 @@ export async function runPayForConfirmPay( transactionId: makeTransactionId(TransactionType.Payment, proposalId), }; } else { - // FIXME: allocate error code! - await storeOperationError( - ws, - RetryTags.byPaymentProposalId(proposalId), - res.errorDetail, - ); throw Error("payment failed"); } } case OperationAttemptResultType.Pending: - await storeOperationPending( - ws, - `${PendingTaskType.Purchase}:${proposalId}`, - ); + logger.trace("reporting pending as confirmPay response"); return { type: ConfirmPayResultType.Pending, transactionId: makeTransactionId(TransactionType.Payment, proposalId), @@ -1968,29 +1966,12 @@ export async function processPurchasePay( result: undefined, }; } + } - if (resp.status >= 400 && resp.status <= 499) { - const errDetails = await readUnexpectedResponseDetails(resp); - logger.warn(`server returned ${resp.status} response for /pay`); - logger.warn(j2s(errDetails)); - await ws.db - .mktx((x) => [x.purchases]) - .runReadWrite(async (tx) => { - const purch = await tx.purchases.get(proposalId); - if (!purch) { - return; - } - // FIXME: Should be some "PayPermanentlyFailed" and error info should be stored - purch.purchaseStatus = PurchaseStatus.PaymentAbortFinished; - await tx.purchases.put(purch); - }); - throw makePendingOperationFailedError( - errDetails, - TransactionType.Payment, - proposalId, - ); - } - + if (resp.status >= 400 && resp.status <= 499) { + logger.trace("got generic 4xx from merchant"); + const err = await readTalerErrorResponse(resp); + throwUnexpectedRequestError(resp, err); } const merchantResp = await readSuccessResponseJsonOrThrow( @@ -2395,16 +2376,18 @@ async function acceptRefunds( } } - const refreshCoinsPubs = Object.values(refreshCoinsMap); - logger.info(`refreshCoinMap ${j2s(refreshCoinsMap)}`); - if (refreshCoinsPubs.length > 0) { - await createRefreshGroup( - ws, - tx, - Amounts.currencyOf(refreshCoinsPubs[0].amount), - refreshCoinsPubs, - RefreshReason.Refund, - ); + if (reason === RefundReason.AbortRefund) { + const refreshCoinsPubs = Object.values(refreshCoinsMap); + logger.info(`refreshCoinMap ${j2s(refreshCoinsMap)}`); + if (refreshCoinsPubs.length > 0) { + await createRefreshGroup( + ws, + tx, + Amounts.currencyOf(refreshCoinsPubs[0].amount), + refreshCoinsPubs, + RefreshReason.Refund, + ); + } } // Are we done with querying yet, or do we need to do another round @@ -2808,12 +2791,21 @@ export async function processPurchaseQueryRefund( return OperationAttemptResult.finishedEmpty(); } -export async function abortFailedPayWithRefund( +export async function abortPay( ws: InternalWalletState, proposalId: string, + cancelImmediately?: boolean, ): Promise<void> { + const opId = RetryTags.byPaymentProposalId(proposalId); await ws.db - .mktx((x) => [x.purchases]) + .mktx((x) => [ + x.purchases, + x.refreshGroups, + x.denominations, + x.coinAvailability, + x.coins, + x.operationRetries, + ]) .runReadWrite(async (tx) => { const purchase = await tx.purchases.get(proposalId); if (!purchase) { @@ -2828,10 +2820,30 @@ export async function abortFailedPayWithRefund( purchase.purchaseStatus = PurchaseStatus.AbortingWithRefund; } await tx.purchases.put(purchase); + await tx.operationRetries.delete(opId); + if (purchase.payInfo) { + const coinSel = purchase.payInfo.payCoinSelection; + const currency = Amounts.currencyOf(purchase.payInfo.totalPayCost); + const refreshCoins: CoinRefreshRequest[] = []; + for (let i = 0; i < coinSel.coinPubs.length; i++) { + refreshCoins.push({ + amount: coinSel.coinContributions[i], + coinPub: coinSel.coinPubs[i], + }); + } + await createRefreshGroup( + ws, + tx, + currency, + refreshCoins, + RefreshReason.AbortPay, + ); + } + }); + + runOperationWithErrorReporting(ws, opId, async () => { + return await processPurchaseQueryRefund(ws, proposalId, { + forceNow: true, }); - processPurchaseQueryRefund(ws, proposalId, { - forceNow: true, - }).catch((e) => { - logger.trace(`error during refund processing after abort pay: ${e}`); }); } diff --git a/packages/taler-wallet-core/src/operations/transactions.ts b/packages/taler-wallet-core/src/operations/transactions.ts index 3fb13d2a0..2570a4e5f 100644 --- a/packages/taler-wallet-core/src/operations/transactions.ts +++ b/packages/taler-wallet-core/src/operations/transactions.ts @@ -23,6 +23,7 @@ import { Amounts, constructPayPullUri, constructPayPushUri, + ExtendedStatus, Logger, OrderShortInfo, PaymentStatus, @@ -66,6 +67,7 @@ import { import { processDepositGroup } from "./deposits.js"; import { getExchangeDetails } from "./exchanges.js"; import { + abortPay, expectProposalDownload, extractContractData, processPurchasePay, @@ -352,6 +354,10 @@ function buildTransactionForPushPaymentDebit( summary: contractTerms.summary, }, frozen: false, + extendedStatus: + pi.status != PeerPushPaymentInitiationStatus.PurseCreated + ? ExtendedStatus.Pending + : ExtendedStatus.Done, pending: pi.status != PeerPushPaymentInitiationStatus.PurseCreated, timestamp: pi.timestampCreated, talerUri: constructPayPushUri({ @@ -377,6 +383,7 @@ function buildTransactionForPullPaymentDebit( exchangeBaseUrl: pi.exchangeBaseUrl, frozen: false, pending: false, + extendedStatus: ExtendedStatus.Done, info: { expiration: pi.contractTerms.purse_expiration, summary: pi.contractTerms.summary, @@ -401,6 +408,7 @@ function buildTransactionForPullPaymentCredit( amountEffective: Amounts.stringify(wsr.denomsSel.totalCoinValue), amountRaw: Amounts.stringify(wsr.instructedAmount), exchangeBaseUrl: wsr.exchangeBaseUrl, + extendedStatus: ExtendedStatus.Done, pending: !wsr.timestampFinish, timestamp: wsr.timestampStart, info: { @@ -435,6 +443,9 @@ function buildTransactionForPushPaymentCredit( expiration: wsr.wgInfo.contractTerms.purse_expiration, summary: wsr.wgInfo.contractTerms.summary, }, + extendedStatus: wsr.timestampFinish + ? ExtendedStatus.Done + : ExtendedStatus.Pending, pending: !wsr.timestampFinish, timestamp: wsr.timestampStart, transactionId: makeTransactionId( @@ -464,6 +475,9 @@ function buildTransactionForBankIntegratedWithdraw( bankConfirmationUrl: wsr.wgInfo.bankInfo.confirmUrl, }, exchangeBaseUrl: wsr.exchangeBaseUrl, + extendedStatus: wsr.timestampFinish + ? ExtendedStatus.Done + : ExtendedStatus.Pending, pending: !wsr.timestampFinish, timestamp: wsr.timestampStart, transactionId: makeTransactionId( @@ -504,6 +518,9 @@ function buildTransactionForManualWithdraw( exchangePaytoUris, }, exchangeBaseUrl: withdrawalGroup.exchangeBaseUrl, + extendedStatus: withdrawalGroup.timestampFinish + ? ExtendedStatus.Done + : ExtendedStatus.Pending, pending: !withdrawalGroup.timestampFinish, timestamp: withdrawalGroup.timestampStart, transactionId: makeTransactionId( @@ -523,6 +540,9 @@ function buildTransactionForDeposit( type: TransactionType.Deposit, amountRaw: Amounts.stringify(dg.effectiveDepositAmount), amountEffective: Amounts.stringify(dg.totalPayCost), + extendedStatus: dg.timestampFinished + ? ExtendedStatus.Done + : ExtendedStatus.Pending, pending: !dg.timestampFinished, frozen: false, timestamp: dg.timestampCreated, @@ -547,6 +567,9 @@ function buildTransactionForTip( type: TransactionType.Tip, amountEffective: Amounts.stringify(tipRecord.tipAmountEffective), amountRaw: Amounts.stringify(tipRecord.tipAmountRaw), + extendedStatus: tipRecord.pickedUpTimestamp + ? ExtendedStatus.Done + : ExtendedStatus.Pending, pending: !tipRecord.pickedUpTimestamp, frozen: false, timestamp: tipRecord.acceptedTimestamp, @@ -654,6 +677,7 @@ async function buildTransactionForRefund( purchaseRecord.refundAmountAwaiting === undefined ? undefined : Amounts.stringify(purchaseRecord.refundAmountAwaiting), + extendedStatus: ExtendedStatus.Done, pending: false, frozen: false, ...(ort?.lastError ? { error: ort.lastError } : {}), @@ -710,6 +734,33 @@ async function buildTransactionForPurchase( checkDbInvariant(!!timestamp); checkDbInvariant(!!purchaseRecord.payInfo); + + let status: ExtendedStatus; + switch (purchaseRecord.purchaseStatus) { + case PurchaseStatus.AbortingWithRefund: + status = ExtendedStatus.Aborting; + break; + case PurchaseStatus.Paid: + case PurchaseStatus.RepurchaseDetected: + status = ExtendedStatus.Done; + break; + case PurchaseStatus.DownloadingProposal: + case PurchaseStatus.QueryingRefund: + case PurchaseStatus.Proposed: + case PurchaseStatus.Paying: + status = ExtendedStatus.Pending; + break; + case PurchaseStatus.ProposalDownloadFailed: + status = ExtendedStatus.Failed; + break; + case PurchaseStatus.PaymentAbortFinished: + status = ExtendedStatus.Aborted; + break; + default: + // FIXME: Should we have some unknown status? + status = ExtendedStatus.Pending; + } + return { type: TransactionType.Payment, amountRaw: Amounts.stringify(contractData.amount), @@ -723,6 +774,7 @@ async function buildTransactionForPurchase( status: purchaseRecord.timestampFirstSuccessfulPay ? PaymentStatus.Paid : PaymentStatus.Accepted, + extendedStatus: status, pending: purchaseRecord.purchaseStatus === PurchaseStatus.Paying, refunds, timestamp, @@ -1163,3 +1215,19 @@ export async function deleteTransaction( throw Error(`can't delete a '${unknownTxType}' transaction`); } } + +export async function abortTransaction( + ws: InternalWalletState, + transactionId: string, + forceImmediateAbort?: boolean, +): Promise<void> { + const { type, args: rest } = parseId("txn", transactionId); + + if (type === TransactionType.Payment) { + const proposalId = rest[0]; + await abortPay(ws, proposalId, forceImmediateAbort); + } else { + const unknownTxType: any = type; + throw Error(`can't abort a '${unknownTxType}' transaction`); + } +} diff --git a/packages/taler-wallet-core/src/util/query.ts b/packages/taler-wallet-core/src/util/query.ts index 4eb354f3e..56a23c2dd 100644 --- a/packages/taler-wallet-core/src/util/query.ts +++ b/packages/taler-wallet-core/src/util/query.ts @@ -660,7 +660,6 @@ export class DbAccess<StoreMap> { const storeNames: string[] = []; const accessibleStores: { [x: string]: StoreWithIndexes<any, any, any> } = {}; - for (let i = 0; i < this.db.objectStoreNames.length; i++) { const sn = this.db.objectStoreNames[i]; const swi = (this.stores as any)[sn] as StoreWithIndexes<any, any, any>; diff --git a/packages/taler-wallet-core/src/wallet-api-types.ts b/packages/taler-wallet-core/src/wallet-api-types.ts index 3daa817e8..88ae3a5c1 100644 --- a/packages/taler-wallet-core/src/wallet-api-types.ts +++ b/packages/taler-wallet-core/src/wallet-api-types.ts @@ -24,7 +24,7 @@ * Imports. */ import { - AbortPayRequest as AbortPayRequest, + AbortTransactionRequest as AbortTransactionRequest, AcceptBankIntegratedWithdrawalRequest, AcceptExchangeTosRequest, AcceptManualWithdrawalRequest, @@ -150,7 +150,7 @@ export enum WalletApiOperation { GetExchangeTos = "getExchangeTos", GetExchangeDetailedInfo = "getExchangeDetailedInfo", RetryPendingNow = "retryPendingNow", - AbortPay = "abortPay", + AbortTransaction = "abortTransaction", ConfirmPay = "confirmPay", DumpCoins = "dumpCoins", SetCoinSuspended = "setCoinSuspended", @@ -329,13 +329,13 @@ export type ConfirmPayOp = { }; /** - * Abort a pending payment. - * Puts the payment into an "aborting" state - * that can be cancelled. + * Abort a transaction + * + * For payment transactions, it puts the payment into an "aborting" state. */ -export type AbortPayOp = { - op: WalletApiOperation.AbortPay; - request: AbortPayRequest; +export type AbortTransactionOp = { + op: WalletApiOperation.AbortTransaction; + request: AbortTransactionRequest; response: EmptyObject; }; @@ -829,7 +829,7 @@ export type WalletOperations = { [WalletApiOperation.GetContractTermsDetails]: GetContractTermsDetailsOp; [WalletApiOperation.WithdrawTestkudos]: WithdrawTestkudosOp; [WalletApiOperation.ConfirmPay]: ConfirmPayOp; - [WalletApiOperation.AbortPay]: AbortPayOp; + [WalletApiOperation.AbortTransaction]: AbortTransactionOp; [WalletApiOperation.GetBalances]: GetBalancesOp; [WalletApiOperation.GetTransactions]: GetTransactionsOp; [WalletApiOperation.GetTransactionById]: GetTransactionByIdOp; diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index 2b386f0a8..e2a2b43f6 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -25,7 +25,7 @@ import { AbsoluteTime, Amounts, - codecForAbortPayRequest, + codecForAbortTransaction, codecForAcceptBankIntegratedWithdrawalRequest, codecForAcceptExchangeTosRequest, codecForAcceptManualWithdrawalRequet, @@ -180,7 +180,7 @@ import { } from "./operations/exchanges.js"; import { getMerchantInfo } from "./operations/merchants.js"; import { - abortFailedPayWithRefund, + abortPay as abortPay, applyRefund, applyRefundFromPurchaseId, confirmPay, @@ -217,6 +217,7 @@ import { } from "./operations/testing.js"; import { acceptTip, prepareTip, processTip } from "./operations/tip.js"; import { + abortTransaction, deleteTransaction, getTransactionById, getTransactions, @@ -1163,9 +1164,9 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>( const req = codecForConfirmPayRequest().decode(payload); return await confirmPay(ws, req.proposalId, req.sessionId); } - case WalletApiOperation.AbortPay: { - const req = codecForAbortPayRequest().decode(payload); - await abortFailedPayWithRefund(ws, req.proposalId); + case WalletApiOperation.AbortTransaction: { + const req = codecForAbortTransaction().decode(payload); + await abortTransaction(ws, req.transactionId, req.forceImmediateAbort); return {}; } case WalletApiOperation.DumpCoins: { |