wallet-core: report possible actions in transactions list

This commit is contained in:
Florian Dold 2023-05-30 15:58:28 +02:00
parent 000359a5e7
commit 2a92ca8732
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
12 changed files with 407 additions and 55 deletions

View File

@ -125,6 +125,15 @@ export enum TransactionMinorState {
AcceptRefund = "accept-refund", AcceptRefund = "accept-refund",
} }
export enum TransactionAction {
Delete = "delete",
Suspend = "suspend",
Resume = "resume",
Abort = "abort",
Fail = "fail",
Retry = "retry",
}
export interface TransactionsResponse { export interface TransactionsResponse {
// a list of past and pending transactions sorted by pending, timestamp and transactionId. // a list of past and pending transactions sorted by pending, timestamp and transactionId.
// In case two events are both pending and have the same timestamp, // In case two events are both pending and have the same timestamp,
@ -149,6 +158,11 @@ export interface TransactionCommon {
*/ */
txState: TransactionState; txState: TransactionState;
/**
* Possible transitions based on the current state.
*/
txActions: string[];
/** /**
* Raw amount of the transaction (exclusive of fees or other extra costs). * Raw amount of the transaction (exclusive of fees or other extra costs).
*/ */

View File

@ -1131,7 +1131,7 @@ export enum PurchaseStatus {
/** /**
* Proposal downloaded, but the user needs to accept/reject it. * Proposal downloaded, but the user needs to accept/reject it.
*/ */
Proposed = 30, DialogProposed = 30,
/** /**
* The user has rejected the proposal. * The user has rejected the proposal.

View File

@ -418,7 +418,7 @@ export async function exportBackup(
break; break;
case PurchaseStatus.PendingPayingReplay: case PurchaseStatus.PendingPayingReplay:
case PurchaseStatus.PendingDownloadingProposal: case PurchaseStatus.PendingDownloadingProposal:
case PurchaseStatus.Proposed: case PurchaseStatus.DialogProposed:
case PurchaseStatus.PendingPaying: case PurchaseStatus.PendingPaying:
propStatus = BackupProposalStatus.Proposed; propStatus = BackupProposalStatus.Proposed;
break; break;

View File

@ -578,7 +578,7 @@ export async function importBackup(
proposalStatus = PurchaseStatus.Done; proposalStatus = PurchaseStatus.Done;
break; break;
case BackupProposalStatus.Proposed: case BackupProposalStatus.Proposed:
proposalStatus = PurchaseStatus.Proposed; proposalStatus = PurchaseStatus.DialogProposed;
break; break;
case BackupProposalStatus.PermanentlyFailed: case BackupProposalStatus.PermanentlyFailed:
proposalStatus = PurchaseStatus.AbortedIncompletePayment; proposalStatus = PurchaseStatus.AbortedIncompletePayment;

View File

@ -59,11 +59,11 @@ import {
TransactionType, TransactionType,
URL, URL,
WireFee, WireFee,
TransactionAction,
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
import { import {
DenominationRecord, DenominationRecord,
DepositGroupRecord, DepositGroupRecord,
OperationStatus,
DepositElementStatus, DepositElementStatus,
} from "../db.js"; } from "../db.js";
import { TalerError } from "@gnu-taler/taler-util"; import { TalerError } from "@gnu-taler/taler-util";
@ -115,6 +115,7 @@ export function computeDepositTransactionStatus(
major: TransactionMajorState.Done, major: TransactionMajorState.Done,
}; };
} }
// FIXME: We should actually use separate pending states for this!
case DepositOperationStatus.Pending: { case DepositOperationStatus.Pending: {
const numTotal = dg.payCoinSelection.coinPubs.length; const numTotal = dg.payCoinSelection.coinPubs.length;
let numDeposited = 0; let numDeposited = 0;
@ -134,9 +135,6 @@ export function computeDepositTransactionStatus(
} }
} }
logger.info(`num total ${numTotal}`);
logger.info(`num deposited ${numDeposited}`);
if (numKycRequired > 0) { if (numKycRequired > 0) {
return { return {
major: TransactionMajorState.Pending, major: TransactionMajorState.Pending,
@ -181,6 +179,57 @@ export function computeDepositTransactionStatus(
} }
} }
export function computeDepositTransactionActions(
dg: DepositGroupRecord,
): TransactionAction[] {
switch (dg.operationStatus) {
case DepositOperationStatus.Finished: {
return [TransactionAction.Delete];
}
case DepositOperationStatus.Pending: {
const numTotal = dg.payCoinSelection.coinPubs.length;
let numDeposited = 0;
let numKycRequired = 0;
let numWired = 0;
for (let i = 0; i < numTotal; i++) {
if (dg.depositedPerCoin[i]) {
numDeposited++;
}
switch (dg.transactionPerCoin[i]) {
case DepositElementStatus.KycRequired:
numKycRequired++;
break;
case DepositElementStatus.Wired:
numWired++;
break;
}
}
if (numKycRequired > 0) {
return [TransactionAction.Suspend, TransactionAction.Fail];
}
if (numDeposited == numTotal) {
return [TransactionAction.Suspend, TransactionAction.Fail];
}
return [TransactionAction.Suspend, TransactionAction.Abort];
}
case DepositOperationStatus.Suspended:
return [TransactionAction.Resume];
case DepositOperationStatus.Aborting:
return [TransactionAction.Fail, TransactionAction.Suspend];
case DepositOperationStatus.Aborted:
return [TransactionAction.Delete];
case DepositOperationStatus.Failed:
return [TransactionAction.Delete];
case DepositOperationStatus.SuspendedAborting:
return [TransactionAction.Resume, TransactionAction.Fail];
default:
throw Error(`unexpected deposit group state (${dg.operationStatus})`);
}
}
export async function suspendDepositGroup( export async function suspendDepositGroup(
ws: InternalWalletState, ws: InternalWalletState,
depositGroupId: string, depositGroupId: string,
@ -309,7 +358,7 @@ export async function abortDepositGroup(
notifyTransition(ws, transactionId, transitionInfo); notifyTransition(ws, transactionId, transitionInfo);
} }
export async function cancelAbortingDepositGroup( export async function failDepositTransaction(
ws: InternalWalletState, ws: InternalWalletState,
depositGroupId: string, depositGroupId: string,
): Promise<void> { ): Promise<void> {

View File

@ -70,6 +70,7 @@ import {
TalerProtocolTimestamp, TalerProtocolTimestamp,
TalerProtocolViolationError, TalerProtocolViolationError,
TalerUriAction, TalerUriAction,
TransactionAction,
TransactionMajorState, TransactionMajorState,
TransactionMinorState, TransactionMinorState,
TransactionState, TransactionState,
@ -547,7 +548,7 @@ async function processDownloadProposal(
await tx.purchases.put(p); await tx.purchases.put(p);
} }
} else { } else {
p.purchaseStatus = PurchaseStatus.Proposed; p.purchaseStatus = PurchaseStatus.DialogProposed;
await tx.purchases.put(p); await tx.purchases.put(p);
} }
const newTxState = computePayMerchantTransactionState(p); const newTxState = computePayMerchantTransactionState(p);
@ -994,7 +995,7 @@ export async function checkPaymentByProposalId(
return tx.purchases.get(proposalId); return tx.purchases.get(proposalId);
}); });
if (!purchase || purchase.purchaseStatus === PurchaseStatus.Proposed) { if (!purchase || purchase.purchaseStatus === PurchaseStatus.DialogProposed) {
// If not already paid, check if we could pay for it. // If not already paid, check if we could pay for it.
const res = await selectPayCoinsNew(ws, { const res = await selectPayCoinsNew(ws, {
auditors: [], auditors: [],
@ -1417,7 +1418,7 @@ export async function confirmPay(
} }
const oldTxState = computePayMerchantTransactionState(p); const oldTxState = computePayMerchantTransactionState(p);
switch (p.purchaseStatus) { switch (p.purchaseStatus) {
case PurchaseStatus.Proposed: case PurchaseStatus.DialogProposed:
p.payInfo = { p.payInfo = {
payCoinSelection: coinSelection, payCoinSelection: coinSelection,
payCoinSelectionUid: encodeCrock(getRandomBytes(16)), payCoinSelectionUid: encodeCrock(getRandomBytes(16)),
@ -1498,7 +1499,7 @@ export async function processPurchase(
case PurchaseStatus.FailedClaim: case PurchaseStatus.FailedClaim:
case PurchaseStatus.Done: case PurchaseStatus.Done:
case PurchaseStatus.RepurchaseDetected: case PurchaseStatus.RepurchaseDetected:
case PurchaseStatus.Proposed: case PurchaseStatus.DialogProposed:
case PurchaseStatus.AbortedProposalRefused: case PurchaseStatus.AbortedProposalRefused:
case PurchaseStatus.AbortedIncompletePayment: case PurchaseStatus.AbortedIncompletePayment:
case PurchaseStatus.SuspendedAbortingWithRefund: case PurchaseStatus.SuspendedAbortingWithRefund:
@ -1713,7 +1714,7 @@ export async function refuseProposal(
logger.trace(`proposal ${proposalId} not found, won't refuse proposal`); logger.trace(`proposal ${proposalId} not found, won't refuse proposal`);
return undefined; return undefined;
} }
if (proposal.purchaseStatus !== PurchaseStatus.Proposed) { if (proposal.purchaseStatus !== PurchaseStatus.DialogProposed) {
return undefined; return undefined;
} }
const oldTxState = computePayMerchantTransactionState(proposal); const oldTxState = computePayMerchantTransactionState(proposal);
@ -1791,7 +1792,7 @@ export async function abortPayMerchant(
ws.workAvailable.trigger(); ws.workAvailable.trigger();
} }
export async function cancelAbortingPaymentTransaction( export async function failPaymentTransaction(
ws: InternalWalletState, ws: InternalWalletState,
proposalId: string, proposalId: string,
): Promise<void> { ): Promise<void> {
@ -2023,7 +2024,7 @@ export function computePayMerchantTransactionState(
major: TransactionMajorState.SuspendedAborting, major: TransactionMajorState.SuspendedAborting,
}; };
// Dialog States // Dialog States
case PurchaseStatus.Proposed: case PurchaseStatus.DialogProposed:
return { return {
major: TransactionMajorState.Dialog, major: TransactionMajorState.Dialog,
minor: TransactionMinorState.MerchantOrderProposed, minor: TransactionMinorState.MerchantOrderProposed,
@ -2060,6 +2061,68 @@ export function computePayMerchantTransactionState(
} }
} }
export function computePayMerchantTransactionActions(
purchaseRecord: PurchaseRecord,
): TransactionAction[] {
switch (purchaseRecord.purchaseStatus) {
// Pending States
case PurchaseStatus.PendingDownloadingProposal:
return [TransactionAction.Suspend, TransactionAction.Abort];
case PurchaseStatus.PendingPaying:
return [TransactionAction.Suspend, TransactionAction.Abort];
case PurchaseStatus.PendingPayingReplay:
// Special "abort" since it goes back to "done".
return [TransactionAction.Suspend, TransactionAction.Abort];
case PurchaseStatus.PendingQueryingAutoRefund:
// Special "abort" since it goes back to "done".
return [TransactionAction.Suspend, TransactionAction.Abort];
case PurchaseStatus.PendingQueryingRefund:
// Special "abort" since it goes back to "done".
return [TransactionAction.Suspend, TransactionAction.Abort];
case PurchaseStatus.PendingAcceptRefund:
// Special "abort" since it goes back to "done".
return [TransactionAction.Suspend, TransactionAction.Abort];
// Suspended Pending States
case PurchaseStatus.SuspendedDownloadingProposal:
return [TransactionAction.Resume, TransactionAction.Abort];
case PurchaseStatus.SuspendedPaying:
return [TransactionAction.Resume, TransactionAction.Abort];
case PurchaseStatus.SuspendedPayingReplay:
// Special "abort" since it goes back to "done".
return [TransactionAction.Resume, TransactionAction.Abort];
case PurchaseStatus.SuspendedQueryingAutoRefund:
// Special "abort" since it goes back to "done".
return [TransactionAction.Resume, TransactionAction.Abort];
case PurchaseStatus.SuspendedQueryingRefund:
// Special "abort" since it goes back to "done".
return [TransactionAction.Resume, TransactionAction.Abort];
case PurchaseStatus.SuspendedPendingAcceptRefund:
// Special "abort" since it goes back to "done".
return [TransactionAction.Resume, TransactionAction.Abort];
// Aborting States
case PurchaseStatus.AbortingWithRefund:
return [TransactionAction.Fail, TransactionAction.Suspend];
case PurchaseStatus.SuspendedAbortingWithRefund:
return [TransactionAction.Fail, TransactionAction.Resume];
// Dialog States
case PurchaseStatus.DialogProposed:
return [];
// Final States
case PurchaseStatus.AbortedProposalRefused:
return [TransactionAction.Delete];
case PurchaseStatus.Done:
return [TransactionAction.Delete];
case PurchaseStatus.RepurchaseDetected:
return [TransactionAction.Delete];
case PurchaseStatus.AbortedIncompletePayment:
return [TransactionAction.Delete];
case PurchaseStatus.FailedClaim:
return [TransactionAction.Delete];
case PurchaseStatus.FailedAbort:
return [TransactionAction.Delete];
}
}
async function processPurchaseAutoRefund( async function processPurchaseAutoRefund(
ws: InternalWalletState, ws: InternalWalletState,
purchase: PurchaseRecord, purchase: PurchaseRecord,

View File

@ -79,6 +79,7 @@ import {
TransactionMajorState, TransactionMajorState,
TransactionMinorState, TransactionMinorState,
TalerPreciseTimestamp, TalerPreciseTimestamp,
TransactionAction,
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
import { SpendCoinDetails } from "../crypto/cryptoImplementation.js"; import { SpendCoinDetails } from "../crypto/cryptoImplementation.js";
import { import {
@ -2008,7 +2009,36 @@ export function computePeerPushDebitTransactionState(
case PeerPushPaymentInitiationStatus.Failed: case PeerPushPaymentInitiationStatus.Failed:
return { return {
major: TransactionMajorState.Failed, major: TransactionMajorState.Failed,
} };
}
}
export function computePeerPushDebitTransactionActions(
ppiRecord: PeerPushPaymentInitiationRecord,
): TransactionAction[] {
switch (ppiRecord.status) {
case PeerPushPaymentInitiationStatus.PendingCreatePurse:
return [TransactionAction.Abort, TransactionAction.Suspend];
case PeerPushPaymentInitiationStatus.PendingReady:
return [TransactionAction.Abort, TransactionAction.Suspend];
case PeerPushPaymentInitiationStatus.Aborted:
return [TransactionAction.Delete];
case PeerPushPaymentInitiationStatus.AbortingDeletePurse:
return [TransactionAction.Suspend, TransactionAction.Fail];
case PeerPushPaymentInitiationStatus.AbortingRefresh:
return [TransactionAction.Suspend, TransactionAction.Fail];
case PeerPushPaymentInitiationStatus.SuspendedAbortingDeletePurse:
return [TransactionAction.Resume, TransactionAction.Fail];
case PeerPushPaymentInitiationStatus.SuspendedAbortingRefresh:
return [TransactionAction.Resume, TransactionAction.Fail];
case PeerPushPaymentInitiationStatus.SuspendedCreatePurse:
return [TransactionAction.Resume, TransactionAction.Abort];
case PeerPushPaymentInitiationStatus.SuspendedReady:
return [TransactionAction.Suspend, TransactionAction.Abort];
case PeerPushPaymentInitiationStatus.Done:
return [TransactionAction.Delete];
case PeerPushPaymentInitiationStatus.Failed:
return [TransactionAction.Delete];
} }
} }
@ -2072,7 +2102,7 @@ export async function abortPeerPushDebitTransaction(
notifyTransition(ws, transactionId, transitionInfo); notifyTransition(ws, transactionId, transitionInfo);
} }
export async function cancelAbortingPeerPushDebitTransaction( export async function failPeerPushDebitTransaction(
ws: InternalWalletState, ws: InternalWalletState,
pursePub: string, pursePub: string,
) { ) {
@ -2316,8 +2346,7 @@ export async function abortPeerPullDebitTransaction(
notifyTransition(ws, transactionId, transitionInfo); notifyTransition(ws, transactionId, transitionInfo);
} }
export async function failPeerPullDebitTransaction(
export async function cancelAbortingPeerPullDebitTransaction(
ws: InternalWalletState, ws: InternalWalletState,
peerPullPaymentIncomingId: string, peerPullPaymentIncomingId: string,
) { ) {
@ -2501,7 +2530,6 @@ export async function suspendPeerPushCreditTransaction(
notifyTransition(ws, transactionId, transitionInfo); notifyTransition(ws, transactionId, transitionInfo);
} }
export async function abortPeerPushCreditTransaction( export async function abortPeerPushCreditTransaction(
ws: InternalWalletState, ws: InternalWalletState,
peerPushPaymentIncomingId: string, peerPushPaymentIncomingId: string,
@ -2568,7 +2596,7 @@ export async function abortPeerPushCreditTransaction(
notifyTransition(ws, transactionId, transitionInfo); notifyTransition(ws, transactionId, transitionInfo);
} }
export async function cancelAbortingPeerPushCreditTransaction( export async function failPeerPushCreditTransaction(
ws: InternalWalletState, ws: InternalWalletState,
peerPushPaymentIncomingId: string, peerPushPaymentIncomingId: string,
) { ) {
@ -2765,7 +2793,7 @@ export async function abortPeerPullCreditTransaction(
notifyTransition(ws, transactionId, transitionInfo); notifyTransition(ws, transactionId, transitionInfo);
} }
export async function cancelAbortingPeerPullCreditTransaction( export async function failPeerPullCreditTransaction(
ws: InternalWalletState, ws: InternalWalletState,
pursePub: string, pursePub: string,
) { ) {
@ -2996,12 +3024,41 @@ export function computePeerPushCreditTransactionState(
}; };
case PeerPushPaymentIncomingStatus.Aborted: case PeerPushPaymentIncomingStatus.Aborted:
return { return {
major: TransactionMajorState.Aborted major: TransactionMajorState.Aborted,
}; };
case PeerPushPaymentIncomingStatus.Failed: case PeerPushPaymentIncomingStatus.Failed:
return { return {
major: TransactionMajorState.Failed, major: TransactionMajorState.Failed,
} };
default:
assertUnreachable(pushCreditRecord.status);
}
}
export function computePeerPushCreditTransactionActions(
pushCreditRecord: PeerPushPaymentIncomingRecord,
): TransactionAction[] {
switch (pushCreditRecord.status) {
case PeerPushPaymentIncomingStatus.DialogProposed:
return [];
case PeerPushPaymentIncomingStatus.PendingMerge:
return [TransactionAction.Abort, TransactionAction.Suspend];
case PeerPushPaymentIncomingStatus.Done:
return [TransactionAction.Delete];
case PeerPushPaymentIncomingStatus.PendingMergeKycRequired:
return [TransactionAction.Abort, TransactionAction.Suspend];
case PeerPushPaymentIncomingStatus.PendingWithdrawing:
return [TransactionAction.Suspend, TransactionAction.Fail];
case PeerPushPaymentIncomingStatus.SuspendedMerge:
return [TransactionAction.Resume, TransactionAction.Abort];
case PeerPushPaymentIncomingStatus.SuspendedMergeKycRequired:
return [TransactionAction.Resume, TransactionAction.Abort];
case PeerPushPaymentIncomingStatus.SuspendedWithdrawing:
return [TransactionAction.Resume, TransactionAction.Fail];
case PeerPushPaymentIncomingStatus.Aborted:
return [TransactionAction.Delete];
case PeerPushPaymentIncomingStatus.Failed:
return [TransactionAction.Delete];
default: default:
assertUnreachable(pushCreditRecord.status); assertUnreachable(pushCreditRecord.status);
} }
@ -3076,6 +3133,39 @@ export function computePeerPullCreditTransactionState(
} }
} }
export function computePeerPullCreditTransactionActions(
pullCreditRecord: PeerPullPaymentInitiationRecord,
): TransactionAction[] {
switch (pullCreditRecord.status) {
case PeerPullPaymentInitiationStatus.PendingCreatePurse:
return [TransactionAction.Abort, TransactionAction.Suspend];
case PeerPullPaymentInitiationStatus.PendingMergeKycRequired:
return [TransactionAction.Abort, TransactionAction.Suspend];
case PeerPullPaymentInitiationStatus.PendingReady:
return [TransactionAction.Abort, TransactionAction.Suspend];
case PeerPullPaymentInitiationStatus.DonePurseDeposited:
return [TransactionAction.Delete];
case PeerPullPaymentInitiationStatus.PendingWithdrawing:
return [TransactionAction.Abort, TransactionAction.Suspend];
case PeerPullPaymentInitiationStatus.SuspendedCreatePurse:
return [TransactionAction.Resume, TransactionAction.Abort];
case PeerPullPaymentInitiationStatus.SuspendedReady:
return [TransactionAction.Abort, TransactionAction.Resume];
case PeerPullPaymentInitiationStatus.SuspendedWithdrawing:
return [TransactionAction.Resume, TransactionAction.Fail];
case PeerPullPaymentInitiationStatus.SuspendedMergeKycRequired:
return [TransactionAction.Resume, TransactionAction.Fail];
case PeerPullPaymentInitiationStatus.Aborted:
return [TransactionAction.Delete];
case PeerPullPaymentInitiationStatus.AbortingDeletePurse:
return [TransactionAction.Suspend, TransactionAction.Fail];
case PeerPullPaymentInitiationStatus.Failed:
return [TransactionAction.Delete];
case PeerPullPaymentInitiationStatus.SuspendedAbortingDeletePurse:
return [TransactionAction.Resume, TransactionAction.Fail];
}
}
export function computePeerPullDebitTransactionState( export function computePeerPullDebitTransactionState(
pullDebitRecord: PeerPullPaymentIncomingRecord, pullDebitRecord: PeerPullPaymentIncomingRecord,
): TransactionState { ): TransactionState {
@ -3119,3 +3209,26 @@ export function computePeerPullDebitTransactionState(
}; };
} }
} }
export function computePeerPullDebitTransactionActions(
pullDebitRecord: PeerPullPaymentIncomingRecord,
): TransactionAction[] {
switch (pullDebitRecord.status) {
case PeerPullDebitRecordStatus.DialogProposed:
return [];
case PeerPullDebitRecordStatus.PendingDeposit:
return [TransactionAction.Abort, TransactionAction.Suspend];
case PeerPullDebitRecordStatus.DonePaid:
return [TransactionAction.Delete];
case PeerPullDebitRecordStatus.SuspendedDeposit:
return [TransactionAction.Resume, TransactionAction.Abort];
case PeerPullDebitRecordStatus.Aborted:
return [TransactionAction.Delete];
case PeerPullDebitRecordStatus.AbortingRefresh:
return [TransactionAction.Fail, TransactionAction.Suspend];
case PeerPullDebitRecordStatus.Failed:
return [TransactionAction.Delete];
case PeerPullDebitRecordStatus.SuspendedAbortingRefresh:
return [TransactionAction.Resume, TransactionAction.Fail];
}
}

View File

@ -50,6 +50,7 @@ import {
TalerErrorDetail, TalerErrorDetail,
TalerPreciseTimestamp, TalerPreciseTimestamp,
TalerProtocolTimestamp, TalerProtocolTimestamp,
TransactionAction,
TransactionMajorState, TransactionMajorState,
TransactionState, TransactionState,
TransactionType, TransactionType,
@ -96,7 +97,10 @@ import {
PendingTaskType, PendingTaskType,
WalletConfig, WalletConfig,
} from "../index.js"; } from "../index.js";
import { constructTransactionIdentifier, notifyTransition } from "./transactions.js"; import {
constructTransactionIdentifier,
notifyTransition,
} from "./transactions.js";
const logger = new Logger("refresh.ts"); const logger = new Logger("refresh.ts");
@ -1076,8 +1080,12 @@ export async function createRefreshGroup(
* Timestamp after which the wallet would do the next check for an auto-refresh. * Timestamp after which the wallet would do the next check for an auto-refresh.
*/ */
function getAutoRefreshCheckThreshold(d: DenominationRecord): AbsoluteTime { function getAutoRefreshCheckThreshold(d: DenominationRecord): AbsoluteTime {
const expireWithdraw = AbsoluteTime.fromProtocolTimestamp(d.stampExpireWithdraw); const expireWithdraw = AbsoluteTime.fromProtocolTimestamp(
const expireDeposit = AbsoluteTime.fromProtocolTimestamp(d.stampExpireDeposit); d.stampExpireWithdraw,
);
const expireDeposit = AbsoluteTime.fromProtocolTimestamp(
d.stampExpireDeposit,
);
const delta = AbsoluteTime.difference(expireWithdraw, expireDeposit); const delta = AbsoluteTime.difference(expireWithdraw, expireDeposit);
const deltaDiv = durationMul(delta, 0.75); const deltaDiv = durationMul(delta, 0.75);
return AbsoluteTime.addDuration(expireWithdraw, deltaDiv); return AbsoluteTime.addDuration(expireWithdraw, deltaDiv);
@ -1087,8 +1095,12 @@ function getAutoRefreshCheckThreshold(d: DenominationRecord): AbsoluteTime {
* Timestamp after which the wallet would do an auto-refresh. * Timestamp after which the wallet would do an auto-refresh.
*/ */
function getAutoRefreshExecuteThreshold(d: DenominationRecord): AbsoluteTime { function getAutoRefreshExecuteThreshold(d: DenominationRecord): AbsoluteTime {
const expireWithdraw = AbsoluteTime.fromProtocolTimestamp(d.stampExpireWithdraw); const expireWithdraw = AbsoluteTime.fromProtocolTimestamp(
const expireDeposit = AbsoluteTime.fromProtocolTimestamp(d.stampExpireDeposit); d.stampExpireWithdraw,
);
const expireDeposit = AbsoluteTime.fromProtocolTimestamp(
d.stampExpireDeposit,
);
const delta = AbsoluteTime.difference(expireWithdraw, expireDeposit); const delta = AbsoluteTime.difference(expireWithdraw, expireDeposit);
const deltaDiv = durationMul(delta, 0.5); const deltaDiv = durationMul(delta, 0.5);
return AbsoluteTime.addDuration(expireWithdraw, deltaDiv); return AbsoluteTime.addDuration(expireWithdraw, deltaDiv);
@ -1175,7 +1187,8 @@ export async function autoRefresh(
logger.info( logger.info(
`next refresh check at ${AbsoluteTime.toIsoString(minCheckThreshold)}`, `next refresh check at ${AbsoluteTime.toIsoString(minCheckThreshold)}`,
); );
exchange.nextRefreshCheck = AbsoluteTime.toPreciseTimestamp(minCheckThreshold); exchange.nextRefreshCheck =
AbsoluteTime.toPreciseTimestamp(minCheckThreshold);
await tx.exchanges.put(exchange); await tx.exchanges.put(exchange);
}); });
return OperationAttemptResult.finishedEmpty(); return OperationAttemptResult.finishedEmpty();
@ -1204,6 +1217,21 @@ export function computeRefreshTransactionState(
} }
} }
export function computeRefreshTransactionActions(
rg: RefreshGroupRecord,
): TransactionAction[] {
switch (rg.operationStatus) {
case RefreshOperationStatus.Finished:
return [TransactionAction.Delete];
case RefreshOperationStatus.Failed:
return [TransactionAction.Delete];
case RefreshOperationStatus.Pending:
return [TransactionAction.Suspend, TransactionAction.Fail];
case RefreshOperationStatus.Suspended:
return [TransactionAction.Resume, TransactionAction.Fail];
}
}
export async function suspendRefreshGroup( export async function suspendRefreshGroup(
ws: InternalWalletState, ws: InternalWalletState,
refreshGroupId: string, refreshGroupId: string,
@ -1292,7 +1320,7 @@ export async function resumeRefreshGroup(
notifyTransition(ws, transactionId, transitionInfo); notifyTransition(ws, transactionId, transitionInfo);
} }
export async function cancelAbortingRefreshGroup( export async function failRefreshGroup(
ws: InternalWalletState, ws: InternalWalletState,
refreshGroupId: string, refreshGroupId: string,
): Promise<void> { ): Promise<void> {
@ -1321,7 +1349,7 @@ export async function abortRefreshGroup(
let newStatus: RefreshOperationStatus | undefined; let newStatus: RefreshOperationStatus | undefined;
switch (dg.operationStatus) { switch (dg.operationStatus) {
case RefreshOperationStatus.Finished: case RefreshOperationStatus.Finished:
break;; break;
case RefreshOperationStatus.Pending: case RefreshOperationStatus.Pending:
case RefreshOperationStatus.Suspended: case RefreshOperationStatus.Suspended:
newStatus = RefreshOperationStatus.Failed; newStatus = RefreshOperationStatus.Failed;

View File

@ -36,6 +36,7 @@ import {
TalerPreciseTimestamp, TalerPreciseTimestamp,
TalerProtocolTimestamp, TalerProtocolTimestamp,
TipPlanchetDetail, TipPlanchetDetail,
TransactionAction,
TransactionMajorState, TransactionMajorState,
TransactionMinorState, TransactionMinorState,
TransactionState, TransactionState,
@ -111,6 +112,24 @@ export function computeTipTransactionStatus(
} }
} }
export function computeTipTransactionActions(
tipRecord: TipRecord,
): TransactionAction[] {
switch (tipRecord.status) {
case TipRecordStatus.Done:
return [TransactionAction.Delete];
case TipRecordStatus.Aborted:
return [TransactionAction.Delete];
case TipRecordStatus.PendingPickup:
return [TransactionAction.Suspend, TransactionAction.Fail];
case TipRecordStatus.SuspendidPickup:
return [TransactionAction.Resume, TransactionAction.Fail];
default:
assertUnreachable(tipRecord.status);
}
}
export async function prepareTip( export async function prepareTip(
ws: InternalWalletState, ws: InternalWalletState,
talerTipUri: string, talerTipUri: string,
@ -526,7 +545,7 @@ export async function resumeTipTransaction(
notifyTransition(ws, transactionId, transitionInfo); notifyTransition(ws, transactionId, transitionInfo);
} }
export async function cancelAbortingTipTransaction( export async function failTipTransaction(
ws: InternalWalletState, ws: InternalWalletState,
walletTipId: string, walletTipId: string,
): Promise<void> { ): Promise<void> {

View File

@ -73,32 +73,34 @@ import { constructTaskIdentifier, TaskIdentifiers } from "../util/retries.js";
import { resetOperationTimeout, TombstoneTag } from "./common.js"; import { resetOperationTimeout, TombstoneTag } from "./common.js";
import { import {
abortDepositGroup, abortDepositGroup,
cancelAbortingDepositGroup, failDepositTransaction,
computeDepositTransactionStatus, computeDepositTransactionStatus,
deleteDepositGroup, deleteDepositGroup,
resumeDepositGroup, resumeDepositGroup,
suspendDepositGroup, suspendDepositGroup,
computeDepositTransactionActions,
} from "./deposits.js"; } from "./deposits.js";
import { getExchangeDetails } from "./exchanges.js"; import { getExchangeDetails } from "./exchanges.js";
import { import {
abortPayMerchant, abortPayMerchant,
cancelAbortingPaymentTransaction, failPaymentTransaction,
computePayMerchantTransactionState, computePayMerchantTransactionState,
computeRefundTransactionState, computeRefundTransactionState,
expectProposalDownload, expectProposalDownload,
extractContractData, extractContractData,
resumePayMerchant, resumePayMerchant,
suspendPayMerchant, suspendPayMerchant,
computePayMerchantTransactionActions,
} from "./pay-merchant.js"; } from "./pay-merchant.js";
import { import {
abortPeerPullCreditTransaction, abortPeerPullCreditTransaction,
abortPeerPullDebitTransaction, abortPeerPullDebitTransaction,
abortPeerPushCreditTransaction, abortPeerPushCreditTransaction,
abortPeerPushDebitTransaction, abortPeerPushDebitTransaction,
cancelAbortingPeerPullCreditTransaction, failPeerPullCreditTransaction,
cancelAbortingPeerPullDebitTransaction, failPeerPullDebitTransaction,
cancelAbortingPeerPushCreditTransaction, failPeerPushCreditTransaction,
cancelAbortingPeerPushDebitTransaction, failPeerPushDebitTransaction,
computePeerPullCreditTransactionState, computePeerPullCreditTransactionState,
computePeerPullDebitTransactionState, computePeerPullDebitTransactionState,
computePeerPushCreditTransactionState, computePeerPushCreditTransactionState,
@ -111,28 +113,35 @@ import {
suspendPeerPullDebitTransaction, suspendPeerPullDebitTransaction,
suspendPeerPushCreditTransaction, suspendPeerPushCreditTransaction,
suspendPeerPushDebitTransaction, suspendPeerPushDebitTransaction,
computePeerPushDebitTransactionActions,
computePeerPullDebitTransactionActions,
computePeerPullCreditTransactionActions,
computePeerPushCreditTransactionActions,
} from "./pay-peer.js"; } from "./pay-peer.js";
import { import {
abortRefreshGroup, abortRefreshGroup,
cancelAbortingRefreshGroup, failRefreshGroup,
computeRefreshTransactionState, computeRefreshTransactionState,
resumeRefreshGroup, resumeRefreshGroup,
suspendRefreshGroup, suspendRefreshGroup,
computeRefreshTransactionActions,
} from "./refresh.js"; } from "./refresh.js";
import { import {
abortTipTransaction, abortTipTransaction,
cancelAbortingTipTransaction, failTipTransaction,
computeTipTransactionStatus, computeTipTransactionStatus,
resumeTipTransaction, resumeTipTransaction,
suspendTipTransaction, suspendTipTransaction,
computeTipTransactionActions,
} from "./tip.js"; } from "./tip.js";
import { import {
abortWithdrawalTransaction, abortWithdrawalTransaction,
augmentPaytoUrisForWithdrawal, augmentPaytoUrisForWithdrawal,
cancelAbortingWithdrawalTransaction, failWithdrawalTransaction,
computeWithdrawalTransactionStatus, computeWithdrawalTransactionStatus,
resumeWithdrawalTransaction, resumeWithdrawalTransaction,
suspendWithdrawalTransaction, suspendWithdrawalTransaction,
computeWithdrawalTransactionActions,
} from "./withdraw.js"; } from "./withdraw.js";
const logger = new Logger("taler-wallet-core:transactions.ts"); const logger = new Logger("taler-wallet-core:transactions.ts");
@ -429,6 +438,7 @@ function buildTransactionForPushPaymentDebit(
return { return {
type: TransactionType.PeerPushDebit, type: TransactionType.PeerPushDebit,
txState: computePeerPushDebitTransactionState(pi), txState: computePeerPushDebitTransactionState(pi),
txActions: computePeerPushDebitTransactionActions(pi),
amountEffective: pi.totalCost, amountEffective: pi.totalCost,
amountRaw: pi.amount, amountRaw: pi.amount,
exchangeBaseUrl: pi.exchangeBaseUrl, exchangeBaseUrl: pi.exchangeBaseUrl,
@ -456,6 +466,7 @@ function buildTransactionForPullPaymentDebit(
return { return {
type: TransactionType.PeerPullDebit, type: TransactionType.PeerPullDebit,
txState: computePeerPullDebitTransactionState(pi), txState: computePeerPullDebitTransactionState(pi),
txActions: computePeerPullDebitTransactionActions(pi),
amountEffective: pi.coinSel?.totalCost amountEffective: pi.coinSel?.totalCost
? pi.coinSel?.totalCost ? pi.coinSel?.totalCost
: Amounts.stringify(pi.contractTerms.amount), : Amounts.stringify(pi.contractTerms.amount),
@ -503,6 +514,7 @@ function buildTransactionForPeerPullCredit(
return { return {
type: TransactionType.PeerPullCredit, type: TransactionType.PeerPullCredit,
txState: computePeerPullCreditTransactionState(pullCredit), txState: computePeerPullCreditTransactionState(pullCredit),
txActions: computePeerPullCreditTransactionActions(pullCredit),
amountEffective: Amounts.stringify(wsr.denomsSel.totalCoinValue), amountEffective: Amounts.stringify(wsr.denomsSel.totalCoinValue),
amountRaw: Amounts.stringify(wsr.instructedAmount), amountRaw: Amounts.stringify(wsr.instructedAmount),
exchangeBaseUrl: wsr.exchangeBaseUrl, exchangeBaseUrl: wsr.exchangeBaseUrl,
@ -533,6 +545,7 @@ function buildTransactionForPeerPullCredit(
return { return {
type: TransactionType.PeerPullCredit, type: TransactionType.PeerPullCredit,
txState: computePeerPullCreditTransactionState(pullCredit), txState: computePeerPullCreditTransactionState(pullCredit),
txActions: computePeerPullCreditTransactionActions(pullCredit),
amountEffective: Amounts.stringify(pullCredit.estimatedAmountEffective), amountEffective: Amounts.stringify(pullCredit.estimatedAmountEffective),
amountRaw: Amounts.stringify(peerContractTerms.amount), amountRaw: Amounts.stringify(peerContractTerms.amount),
exchangeBaseUrl: pullCredit.exchangeBaseUrl, exchangeBaseUrl: pullCredit.exchangeBaseUrl,
@ -569,6 +582,7 @@ function buildTransactionForPeerPushCredit(
return { return {
type: TransactionType.PeerPushCredit, type: TransactionType.PeerPushCredit,
txState: computePeerPushCreditTransactionState(pushInc), txState: computePeerPushCreditTransactionState(pushInc),
txActions: computePeerPushCreditTransactionActions(pushInc),
amountEffective: Amounts.stringify(wsr.denomsSel.totalCoinValue), amountEffective: Amounts.stringify(wsr.denomsSel.totalCoinValue),
amountRaw: Amounts.stringify(wsr.instructedAmount), amountRaw: Amounts.stringify(wsr.instructedAmount),
exchangeBaseUrl: wsr.exchangeBaseUrl, exchangeBaseUrl: wsr.exchangeBaseUrl,
@ -588,6 +602,7 @@ function buildTransactionForPeerPushCredit(
return { return {
type: TransactionType.PeerPushCredit, type: TransactionType.PeerPushCredit,
txState: computePeerPushCreditTransactionState(pushInc), txState: computePeerPushCreditTransactionState(pushInc),
txActions: computePeerPushCreditTransactionActions(pushInc),
// FIXME: This is wrong, needs to consider fees! // FIXME: This is wrong, needs to consider fees!
amountEffective: Amounts.stringify(peerContractTerms.amount), amountEffective: Amounts.stringify(peerContractTerms.amount),
amountRaw: Amounts.stringify(peerContractTerms.amount), amountRaw: Amounts.stringify(peerContractTerms.amount),
@ -615,6 +630,7 @@ function buildTransactionForBankIntegratedWithdraw(
return { return {
type: TransactionType.Withdrawal, type: TransactionType.Withdrawal,
txState: computeWithdrawalTransactionStatus(wgRecord), txState: computeWithdrawalTransactionStatus(wgRecord),
txActions: computeWithdrawalTransactionActions(wgRecord),
amountEffective: Amounts.stringify(wgRecord.denomsSel.totalCoinValue), amountEffective: Amounts.stringify(wgRecord.denomsSel.totalCoinValue),
amountRaw: Amounts.stringify(wgRecord.instructedAmount), amountRaw: Amounts.stringify(wgRecord.instructedAmount),
withdrawalDetails: { withdrawalDetails: {
@ -656,6 +672,7 @@ function buildTransactionForManualWithdraw(
return { return {
type: TransactionType.Withdrawal, type: TransactionType.Withdrawal,
txState: computeWithdrawalTransactionStatus(withdrawalGroup), txState: computeWithdrawalTransactionStatus(withdrawalGroup),
txActions: computeWithdrawalTransactionActions(withdrawalGroup),
amountEffective: Amounts.stringify( amountEffective: Amounts.stringify(
withdrawalGroup.denomsSel.totalCoinValue, withdrawalGroup.denomsSel.totalCoinValue,
), ),
@ -706,6 +723,7 @@ function buildTransactionForRefund(
refundGroupId: refundRecord.refundGroupId, refundGroupId: refundRecord.refundGroupId,
}), }),
txState: computeRefundTransactionState(refundRecord), txState: computeRefundTransactionState(refundRecord),
txActions: [],
paymentInfo, paymentInfo,
}; };
} }
@ -725,6 +743,7 @@ function buildTransactionForRefresh(
return { return {
type: TransactionType.Refresh, type: TransactionType.Refresh,
txState: computeRefreshTransactionState(refreshGroupRecord), txState: computeRefreshTransactionState(refreshGroupRecord),
txActions: computeRefreshTransactionActions(refreshGroupRecord),
refreshReason: refreshGroupRecord.reason, refreshReason: refreshGroupRecord.reason,
amountEffective: Amounts.stringify( amountEffective: Amounts.stringify(
Amounts.zeroOfCurrency(refreshGroupRecord.currency), Amounts.zeroOfCurrency(refreshGroupRecord.currency),
@ -759,6 +778,7 @@ function buildTransactionForDeposit(
return { return {
type: TransactionType.Deposit, type: TransactionType.Deposit,
txState: computeDepositTransactionStatus(dg), txState: computeDepositTransactionStatus(dg),
txActions: computeDepositTransactionActions(dg),
amountRaw: Amounts.stringify(dg.effectiveDepositAmount), amountRaw: Amounts.stringify(dg.effectiveDepositAmount),
amountEffective: Amounts.stringify(dg.totalPayCost), amountEffective: Amounts.stringify(dg.totalPayCost),
timestamp: dg.timestampCreated, timestamp: dg.timestampCreated,
@ -791,6 +811,7 @@ function buildTransactionForTip(
return { return {
type: TransactionType.Tip, type: TransactionType.Tip,
txState: computeTipTransactionStatus(tipRecord), txState: computeTipTransactionStatus(tipRecord),
txActions: computeTipTransactionActions(tipRecord),
amountEffective: Amounts.stringify(tipRecord.tipAmountEffective), amountEffective: Amounts.stringify(tipRecord.tipAmountEffective),
amountRaw: Amounts.stringify(tipRecord.tipAmountRaw), amountRaw: Amounts.stringify(tipRecord.tipAmountRaw),
timestamp: tipRecord.acceptedTimestamp, timestamp: tipRecord.acceptedTimestamp,
@ -860,6 +881,7 @@ async function buildTransactionForPurchase(
return { return {
type: TransactionType.Payment, type: TransactionType.Payment,
txState: computePayMerchantTransactionState(purchaseRecord), txState: computePayMerchantTransactionState(purchaseRecord),
txActions: computePayMerchantTransactionActions(purchaseRecord),
amountRaw: Amounts.stringify(contractData.amount), amountRaw: Amounts.stringify(contractData.amount),
amountEffective: Amounts.stringify(purchaseRecord.payInfo.totalPayCost), amountEffective: Amounts.stringify(purchaseRecord.payInfo.totalPayCost),
totalRefundRaw: Amounts.stringify(zero), // FIXME! totalRefundRaw: Amounts.stringify(zero), // FIXME!
@ -1493,7 +1515,7 @@ export async function suspendTransaction(
} }
} }
export async function cancelAbortingTransaction( export async function failTransaction(
ws: InternalWalletState, ws: InternalWalletState,
transactionId: string, transactionId: string,
): Promise<void> { ): Promise<void> {
@ -1503,34 +1525,34 @@ export async function cancelAbortingTransaction(
} }
switch (tx.tag) { switch (tx.tag) {
case TransactionType.Deposit: case TransactionType.Deposit:
await cancelAbortingDepositGroup(ws, tx.depositGroupId); await failDepositTransaction(ws, tx.depositGroupId);
return; return;
case TransactionType.InternalWithdrawal: case TransactionType.InternalWithdrawal:
case TransactionType.Withdrawal: case TransactionType.Withdrawal:
await cancelAbortingWithdrawalTransaction(ws, tx.withdrawalGroupId); await failWithdrawalTransaction(ws, tx.withdrawalGroupId);
return; return;
case TransactionType.Payment: case TransactionType.Payment:
await cancelAbortingPaymentTransaction(ws, tx.proposalId); await failPaymentTransaction(ws, tx.proposalId);
return; return;
case TransactionType.Refund: case TransactionType.Refund:
throw Error("can't do cancel-aborting on refund transaction"); throw Error("can't do cancel-aborting on refund transaction");
case TransactionType.Tip: case TransactionType.Tip:
await cancelAbortingTipTransaction(ws, tx.walletTipId); await failTipTransaction(ws, tx.walletTipId);
return; return;
case TransactionType.Refresh: case TransactionType.Refresh:
await cancelAbortingRefreshGroup(ws, tx.refreshGroupId); await failRefreshGroup(ws, tx.refreshGroupId);
return; return;
case TransactionType.PeerPullCredit: case TransactionType.PeerPullCredit:
await cancelAbortingPeerPullCreditTransaction(ws, tx.pursePub); await failPeerPullCreditTransaction(ws, tx.pursePub);
return; return;
case TransactionType.PeerPullDebit: case TransactionType.PeerPullDebit:
await cancelAbortingPeerPullDebitTransaction(ws, tx.peerPullPaymentIncomingId); await failPeerPullDebitTransaction(ws, tx.peerPullPaymentIncomingId);
return; return;
case TransactionType.PeerPushCredit: case TransactionType.PeerPushCredit:
await cancelAbortingPeerPushCreditTransaction(ws, tx.peerPushPaymentIncomingId); await failPeerPushCreditTransaction(ws, tx.peerPushPaymentIncomingId);
return; return;
case TransactionType.PeerPushDebit: case TransactionType.PeerPushDebit:
await cancelAbortingPeerPushDebitTransaction(ws, tx.pursePub); await failPeerPushDebitTransaction(ws, tx.pursePub);
return; return;
default: default:
assertUnreachable(tx); assertUnreachable(tx);

View File

@ -67,6 +67,7 @@ import {
TransactionMajorState, TransactionMajorState,
TransactionMinorState, TransactionMinorState,
TalerPreciseTimestamp, TalerPreciseTimestamp,
TransactionAction,
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
import { EddsaKeypair } from "../crypto/cryptoImplementation.js"; import { EddsaKeypair } from "../crypto/cryptoImplementation.js";
import { import {
@ -338,7 +339,7 @@ export async function abortWithdrawalTransaction(
notifyTransition(ws, transactionId, transitionInfo); notifyTransition(ws, transactionId, transitionInfo);
} }
export async function cancelAbortingWithdrawalTransaction( export async function failWithdrawalTransaction(
ws: InternalWalletState, ws: InternalWalletState,
withdrawalGroupId: string, withdrawalGroupId: string,
) { ) {
@ -483,6 +484,49 @@ export function computeWithdrawalTransactionStatus(
} }
} }
export function computeWithdrawalTransactionActions(
wgRecord: WithdrawalGroupRecord,
): TransactionAction[] {
switch (wgRecord.status) {
case WithdrawalGroupStatus.FailedBankAborted:
return [TransactionAction.Delete];
case WithdrawalGroupStatus.Finished:
return [TransactionAction.Delete];
case WithdrawalGroupStatus.PendingRegisteringBank:
return [TransactionAction.Suspend, TransactionAction.Abort];
case WithdrawalGroupStatus.PendingReady:
return [TransactionAction.Suspend, TransactionAction.Abort];
case WithdrawalGroupStatus.PendingQueryingStatus:
return [TransactionAction.Suspend, TransactionAction.Abort];
case WithdrawalGroupStatus.PendingWaitConfirmBank:
return [TransactionAction.Suspend, TransactionAction.Abort];
case WithdrawalGroupStatus.AbortingBank:
return [TransactionAction.Suspend, TransactionAction.Fail];
case WithdrawalGroupStatus.SuspendedAbortingBank:
return [TransactionAction.Resume, TransactionAction.Fail];
case WithdrawalGroupStatus.SuspendedQueryingStatus:
return [TransactionAction.Resume, TransactionAction.Abort];
case WithdrawalGroupStatus.SuspendedRegisteringBank:
return [TransactionAction.Resume, TransactionAction.Abort]
case WithdrawalGroupStatus.SuspendedWaitConfirmBank:
return [TransactionAction.Resume, TransactionAction.Abort];
case WithdrawalGroupStatus.SuspendedReady:
return [TransactionAction.Resume, TransactionAction.Abort];
case WithdrawalGroupStatus.PendingAml:
return [TransactionAction.Resume, TransactionAction.Abort];
case WithdrawalGroupStatus.PendingKyc:
return [TransactionAction.Resume, TransactionAction.Abort];
case WithdrawalGroupStatus.SuspendedAml:
return [TransactionAction.Resume, TransactionAction.Abort];
case WithdrawalGroupStatus.SuspendedKyc:
return [TransactionAction.Resume, TransactionAction.Abort]
case WithdrawalGroupStatus.FailedAbortingBank:
return [TransactionAction.Delete];
case WithdrawalGroupStatus.AbortedExchange:
return [TransactionAction.Delete];
}
}
/** /**
* Get information about a withdrawal from * Get information about a withdrawal from
* a taler://withdraw URI by asking the bank. * a taler://withdraw URI by asking the bank.

View File

@ -232,7 +232,7 @@ import {
import { acceptTip, prepareTip, processTip } from "./operations/tip.js"; import { acceptTip, prepareTip, processTip } from "./operations/tip.js";
import { import {
abortTransaction, abortTransaction,
cancelAbortingTransaction, failTransaction,
deleteTransaction, deleteTransaction,
getTransactionById, getTransactionById,
getTransactions, getTransactions,
@ -1233,7 +1233,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
} }
case WalletApiOperation.CancelAbortingTransaction: { case WalletApiOperation.CancelAbortingTransaction: {
const req = codecForCancelAbortingTransactionRequest().decode(payload); const req = codecForCancelAbortingTransactionRequest().decode(payload);
await cancelAbortingTransaction(ws, req.transactionId); await failTransaction(ws, req.transactionId);
return {}; return {};
} }
case WalletApiOperation.ResumeTransaction: { case WalletApiOperation.ResumeTransaction: {