aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2024-06-10 16:04:18 +0200
committerFlorian Dold <florian@dold.me>2024-06-10 16:04:18 +0200
commit472899f066ce29b86bdc6b02a621f755a7c3b260 (patch)
treee4fe80c64443817455ddd9188233faeff28c1616
parent01e10b0510a2c65845a943a0dcfa7b1edb3d43a2 (diff)
downloadwallet-core-472899f066ce29b86bdc6b02a621f755a7c3b260.tar.xz
wallet-core: introduce finalizing state
-rw-r--r--packages/taler-util/src/transactions-types.ts5
-rw-r--r--packages/taler-wallet-core/src/balance.ts8
-rw-r--r--packages/taler-wallet-core/src/db.ts12
-rw-r--r--packages/taler-wallet-core/src/pay-merchant.ts45
-rw-r--r--packages/taler-wallet-core/src/shepherd.ts8
-rw-r--r--packages/taler-wallet-core/src/transactions.ts40
-rw-r--r--packages/taler-wallet-core/src/versions.ts2
7 files changed, 83 insertions, 37 deletions
diff --git a/packages/taler-util/src/transactions-types.ts b/packages/taler-util/src/transactions-types.ts
index db2133944..a6ac5aec6 100644
--- a/packages/taler-util/src/transactions-types.ts
+++ b/packages/taler-util/src/transactions-types.ts
@@ -105,8 +105,11 @@ export enum TransactionMajorState {
Done = "done",
Aborting = "aborting",
Aborted = "aborted",
- Suspended = "suspended",
Dialog = "dialog",
+ Finalizing = "finalizing",
+ // Plain suspended is always a suspended pending state.
+ Suspended = "suspended",
+ SuspendedFinalizing = "suspended-finalizing",
SuspendedAborting = "suspended-aborting",
Failed = "failed",
Expired = "expired",
diff --git a/packages/taler-wallet-core/src/balance.ts b/packages/taler-wallet-core/src/balance.ts
index 4f06e3756..381028906 100644
--- a/packages/taler-wallet-core/src/balance.ts
+++ b/packages/taler-wallet-core/src/balance.ts
@@ -69,8 +69,8 @@ import { ExchangeRestrictionSpec, findMatchingWire } from "./coinSelection.js";
import {
DepositOperationStatus,
ExchangeEntryDbRecordStatus,
- OPERATION_STATUS_ACTIVE_FIRST,
- OPERATION_STATUS_ACTIVE_LAST,
+ OPERATION_STATUS_NONFINAL_FIRST,
+ OPERATION_STATUS_NONFINAL_LAST,
PeerPushDebitStatus,
RefreshGroupRecord,
RefreshOperationStatus,
@@ -304,8 +304,8 @@ export async function getBalancesInsideTransaction(
const balanceStore: BalancesStore = new BalancesStore(wex, tx);
const keyRangeActive = GlobalIDB.KeyRange.bound(
- OPERATION_STATUS_ACTIVE_FIRST,
- OPERATION_STATUS_ACTIVE_LAST,
+ OPERATION_STATUS_NONFINAL_FIRST,
+ OPERATION_STATUS_NONFINAL_LAST,
);
await tx.exchanges.iter().forEachAsync(async (ex) => {
diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts
index 6bf212c6f..5c381eea7 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -248,6 +248,9 @@ export function timestampOptionalAbsoluteFromDb(
* 0x0103_nnnn: aborting
* 0x0110_nnnn: suspended
* 0x0113_nnnn: suspended-aborting
+ * a=2: finalizing
+ * 0x0200_nnnn: finalizing
+ * 0x0210_nnnn: suspended-finalizing
* a=5: final
* 0x0500_nnnn: done
* 0x0501_nnnn: failed
@@ -260,12 +263,12 @@ export function timestampOptionalAbsoluteFromDb(
/**
* First possible operation status in the active range (inclusive).
*/
-export const OPERATION_STATUS_ACTIVE_FIRST = 0x0100_0000;
+export const OPERATION_STATUS_NONFINAL_FIRST = 0x0100_0000;
/**
* LAST possible operation status in the active range (inclusive).
*/
-export const OPERATION_STATUS_ACTIVE_LAST = 0x0113_ffff;
+export const OPERATION_STATUS_NONFINAL_LAST = 0x0210_ffff;
/**
* Status of a withdrawal.
@@ -1094,10 +1097,15 @@ export enum PurchaseStatus {
/**
* Query for refund (until auto-refund deadline is reached).
+ *
+ * Legacy state for compatibility.
*/
PendingQueryingAutoRefund = 0x0100_0004,
SuspendedQueryingAutoRefund = 0x0110_0004,
+ FinalizingQueryingAutoRefund = 0x0200_0001,
+ SuspendedFinalizingQueryingAutoRefund = 0x0210_0001,
+
PendingAcceptRefund = 0x0100_0005,
SuspendedPendingAcceptRefund = 0x0110_0005,
diff --git a/packages/taler-wallet-core/src/pay-merchant.ts b/packages/taler-wallet-core/src/pay-merchant.ts
index 91ea4bd1d..ee154252f 100644
--- a/packages/taler-wallet-core/src/pay-merchant.ts
+++ b/packages/taler-wallet-core/src/pay-merchant.ts
@@ -2093,6 +2093,7 @@ export async function processPurchase(
case PurchaseStatus.PendingPayingReplay:
return processPurchasePay(wex, proposalId);
case PurchaseStatus.PendingQueryingRefund:
+ case PurchaseStatus.FinalizingQueryingAutoRefund:
return processPurchaseQueryRefund(wex, purchase);
case PurchaseStatus.PendingQueryingAutoRefund:
return processPurchaseAutoRefund(wex, purchase);
@@ -2117,6 +2118,7 @@ export async function processPurchase(
case PurchaseStatus.SuspendedPendingAcceptRefund:
case PurchaseStatus.SuspendedQueryingAutoRefund:
case PurchaseStatus.SuspendedQueryingRefund:
+ case PurchaseStatus.SuspendedFinalizingQueryingAutoRefund:
case PurchaseStatus.FailedAbort:
case PurchaseStatus.FailedPaidByOther:
return TaskRunResult.finished();
@@ -2494,6 +2496,9 @@ const transitionSuspend: {
[PurchaseStatus.PendingQueryingAutoRefund]: {
next: PurchaseStatus.SuspendedQueryingAutoRefund,
},
+ [PurchaseStatus.FinalizingQueryingAutoRefund]: {
+ next: PurchaseStatus.SuspendedFinalizingQueryingAutoRefund,
+ },
};
const transitionResume: {
@@ -2516,6 +2521,9 @@ const transitionResume: {
[PurchaseStatus.SuspendedQueryingAutoRefund]: {
next: PurchaseStatus.PendingQueryingAutoRefund,
},
+ [PurchaseStatus.SuspendedFinalizingQueryingAutoRefund]: {
+ next: PurchaseStatus.FinalizingQueryingAutoRefund,
+ },
};
export function computePayMerchantTransactionState(
@@ -2644,6 +2652,16 @@ export function computePayMerchantTransactionState(
major: TransactionMajorState.Failed,
minor: TransactionMinorState.PaidByOther,
};
+ case PurchaseStatus.FinalizingQueryingAutoRefund:
+ return {
+ major: TransactionMajorState.Finalizing,
+ minor: TransactionMinorState.AutoRefund,
+ };
+ case PurchaseStatus.SuspendedFinalizingQueryingAutoRefund:
+ return {
+ major: TransactionMajorState.SuspendedFinalizing,
+ minor: TransactionMinorState.AutoRefund,
+ };
default:
assertUnreachable(purchaseRecord.purchaseStatus);
}
@@ -2742,6 +2760,14 @@ export function computePayMerchantTransactionActions(
return [TransactionAction.Delete];
case PurchaseStatus.FailedPaidByOther:
return [TransactionAction.Delete];
+ case PurchaseStatus.FinalizingQueryingAutoRefund:
+ return [
+ TransactionAction.Suspend,
+ TransactionAction.Retry,
+ TransactionAction.Delete,
+ ];
+ case PurchaseStatus.SuspendedFinalizingQueryingAutoRefund:
+ return [TransactionAction.Resume, TransactionAction.Delete];
default:
assertUnreachable(purchaseRecord.purchaseStatus);
}
@@ -2944,8 +2970,12 @@ async function processPurchaseAutoRefund(
logger.warn("purchase does not exist anymore");
return;
}
- if (p.purchaseStatus !== PurchaseStatus.PendingQueryingAutoRefund) {
- return;
+ switch (p.purchaseStatus) {
+ case PurchaseStatus.PendingQueryingAutoRefund:
+ case PurchaseStatus.FinalizingQueryingAutoRefund:
+ break;
+ default:
+ return;
}
const oldTxState = computePayMerchantTransactionState(p);
p.purchaseStatus = PurchaseStatus.Done;
@@ -2991,8 +3021,12 @@ async function processPurchaseAutoRefund(
logger.warn("purchase does not exist anymore");
return;
}
- if (p.purchaseStatus !== PurchaseStatus.PendingQueryingAutoRefund) {
- return;
+ switch (p.purchaseStatus) {
+ case PurchaseStatus.PendingQueryingAutoRefund:
+ case PurchaseStatus.FinalizingQueryingAutoRefund:
+ break;
+ default:
+ return;
}
const oldTxState = computePayMerchantTransactionState(p);
p.purchaseStatus = PurchaseStatus.PendingAcceptRefund;
@@ -3536,7 +3570,8 @@ async function storeRefunds(
if (isAborting) {
myPurchase.purchaseStatus = PurchaseStatus.AbortedRefunded;
} else if (shouldCheckAutoRefund) {
- myPurchase.purchaseStatus = PurchaseStatus.PendingQueryingAutoRefund;
+ myPurchase.purchaseStatus =
+ PurchaseStatus.FinalizingQueryingAutoRefund;
} else {
myPurchase.purchaseStatus = PurchaseStatus.Done;
}
diff --git a/packages/taler-wallet-core/src/shepherd.ts b/packages/taler-wallet-core/src/shepherd.ts
index 0f285eb39..470f45aff 100644
--- a/packages/taler-wallet-core/src/shepherd.ts
+++ b/packages/taler-wallet-core/src/shepherd.ts
@@ -50,8 +50,8 @@ import {
parseTaskIdentifier,
} from "./common.js";
import {
- OPERATION_STATUS_ACTIVE_FIRST,
- OPERATION_STATUS_ACTIVE_LAST,
+ OPERATION_STATUS_NONFINAL_FIRST,
+ OPERATION_STATUS_NONFINAL_LAST,
OperationRetryRecord,
WalletDbAllStoresReadOnlyTransaction,
WalletDbReadOnlyTransaction,
@@ -1012,8 +1012,8 @@ export async function getActiveTaskIds(
},
async (tx) => {
const active = GlobalIDB.KeyRange.bound(
- OPERATION_STATUS_ACTIVE_FIRST,
- OPERATION_STATUS_ACTIVE_LAST,
+ OPERATION_STATUS_NONFINAL_FIRST,
+ OPERATION_STATUS_NONFINAL_LAST,
);
// Withdrawals
diff --git a/packages/taler-wallet-core/src/transactions.ts b/packages/taler-wallet-core/src/transactions.ts
index 0f7b1c3ca..7782d09ba 100644
--- a/packages/taler-wallet-core/src/transactions.ts
+++ b/packages/taler-wallet-core/src/transactions.ts
@@ -62,8 +62,8 @@ import {
DenomLossEventRecord,
DepositElementStatus,
DepositGroupRecord,
- OPERATION_STATUS_ACTIVE_FIRST,
- OPERATION_STATUS_ACTIVE_LAST,
+ OPERATION_STATUS_NONFINAL_FIRST,
+ OPERATION_STATUS_NONFINAL_LAST,
OperationRetryRecord,
PeerPullCreditRecord,
PeerPullDebitRecordStatus,
@@ -1968,8 +1968,8 @@ async function iterRecordsForWithdrawal(
let withdrawalGroupRecords: WithdrawalGroupRecord[];
if (filter.onlyState === "nonfinal") {
const keyRange = GlobalIDB.KeyRange.bound(
- OPERATION_STATUS_ACTIVE_FIRST,
- OPERATION_STATUS_ACTIVE_LAST,
+ OPERATION_STATUS_NONFINAL_FIRST,
+ OPERATION_STATUS_NONFINAL_LAST,
);
withdrawalGroupRecords =
await tx.withdrawalGroups.indexes.byStatus.getAll(keyRange);
@@ -1990,8 +1990,8 @@ async function iterRecordsForDeposit(
let dgs: DepositGroupRecord[];
if (filter.onlyState === "nonfinal") {
const keyRange = GlobalIDB.KeyRange.bound(
- OPERATION_STATUS_ACTIVE_FIRST,
- OPERATION_STATUS_ACTIVE_LAST,
+ OPERATION_STATUS_NONFINAL_FIRST,
+ OPERATION_STATUS_NONFINAL_LAST,
);
dgs = await tx.depositGroups.indexes.byStatus.getAll(keyRange);
} else {
@@ -2011,8 +2011,8 @@ async function iterRecordsForDenomLoss(
let dgs: DenomLossEventRecord[];
if (filter.onlyState === "nonfinal") {
const keyRange = GlobalIDB.KeyRange.bound(
- OPERATION_STATUS_ACTIVE_FIRST,
- OPERATION_STATUS_ACTIVE_LAST,
+ OPERATION_STATUS_NONFINAL_FIRST,
+ OPERATION_STATUS_NONFINAL_LAST,
);
dgs = await tx.denomLossEvents.indexes.byStatus.getAll(keyRange);
} else {
@@ -2031,8 +2031,8 @@ async function iterRecordsForRefund(
): Promise<void> {
if (filter.onlyState === "nonfinal") {
const keyRange = GlobalIDB.KeyRange.bound(
- OPERATION_STATUS_ACTIVE_FIRST,
- OPERATION_STATUS_ACTIVE_LAST,
+ OPERATION_STATUS_NONFINAL_FIRST,
+ OPERATION_STATUS_NONFINAL_LAST,
);
await tx.refundGroups.indexes.byStatus.iter(keyRange).forEachAsync(f);
} else {
@@ -2047,8 +2047,8 @@ async function iterRecordsForPurchase(
): Promise<void> {
if (filter.onlyState === "nonfinal") {
const keyRange = GlobalIDB.KeyRange.bound(
- OPERATION_STATUS_ACTIVE_FIRST,
- OPERATION_STATUS_ACTIVE_LAST,
+ OPERATION_STATUS_NONFINAL_FIRST,
+ OPERATION_STATUS_NONFINAL_LAST,
);
await tx.purchases.indexes.byStatus.iter(keyRange).forEachAsync(f);
} else {
@@ -2063,8 +2063,8 @@ async function iterRecordsForPeerPullCredit(
): Promise<void> {
if (filter.onlyState === "nonfinal") {
const keyRange = GlobalIDB.KeyRange.bound(
- OPERATION_STATUS_ACTIVE_FIRST,
- OPERATION_STATUS_ACTIVE_LAST,
+ OPERATION_STATUS_NONFINAL_FIRST,
+ OPERATION_STATUS_NONFINAL_LAST,
);
await tx.peerPullCredit.indexes.byStatus.iter(keyRange).forEachAsync(f);
} else {
@@ -2079,8 +2079,8 @@ async function iterRecordsForPeerPullDebit(
): Promise<void> {
if (filter.onlyState === "nonfinal") {
const keyRange = GlobalIDB.KeyRange.bound(
- OPERATION_STATUS_ACTIVE_FIRST,
- OPERATION_STATUS_ACTIVE_LAST,
+ OPERATION_STATUS_NONFINAL_FIRST,
+ OPERATION_STATUS_NONFINAL_LAST,
);
await tx.peerPullDebit.indexes.byStatus.iter(keyRange).forEachAsync(f);
} else {
@@ -2095,8 +2095,8 @@ async function iterRecordsForPeerPushDebit(
): Promise<void> {
if (filter.onlyState === "nonfinal") {
const keyRange = GlobalIDB.KeyRange.bound(
- OPERATION_STATUS_ACTIVE_FIRST,
- OPERATION_STATUS_ACTIVE_LAST,
+ OPERATION_STATUS_NONFINAL_FIRST,
+ OPERATION_STATUS_NONFINAL_LAST,
);
await tx.peerPushDebit.indexes.byStatus.iter(keyRange).forEachAsync(f);
} else {
@@ -2111,8 +2111,8 @@ async function iterRecordsForPeerPushCredit(
): Promise<void> {
if (filter.onlyState === "nonfinal") {
const keyRange = GlobalIDB.KeyRange.bound(
- OPERATION_STATUS_ACTIVE_FIRST,
- OPERATION_STATUS_ACTIVE_LAST,
+ OPERATION_STATUS_NONFINAL_FIRST,
+ OPERATION_STATUS_NONFINAL_LAST,
);
await tx.peerPushCredit.indexes.byStatus.iter(keyRange).forEachAsync(f);
} else {
diff --git a/packages/taler-wallet-core/src/versions.ts b/packages/taler-wallet-core/src/versions.ts
index d33a23cdd..8c1ac5fc2 100644
--- a/packages/taler-wallet-core/src/versions.ts
+++ b/packages/taler-wallet-core/src/versions.ts
@@ -52,7 +52,7 @@ export const WALLET_BANK_CONVERSION_API_PROTOCOL_VERSION = "2:0:0";
/**
* Libtool version of the wallet-core API.
*/
-export const WALLET_CORE_API_PROTOCOL_VERSION = "5:0:0";
+export const WALLET_CORE_API_PROTOCOL_VERSION = "7:0:0";
/**
* Libtool rules: