aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/operations/balance.ts
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2023-06-26 19:27:34 +0200
committerFlorian Dold <florian@dold.me>2023-06-26 19:27:42 +0200
commita844136489611525726c117cb28086b854bee5c0 (patch)
treebb3384fab39600c35675cd8e36caac9246ef9782 /packages/taler-wallet-core/src/operations/balance.ts
parent2779086a32a62d6d16b7813c2ca4944dc02c4d93 (diff)
downloadwallet-core-a844136489611525726c117cb28086b854bee5c0.tar.xz
wallet-core: make changes to available amount atomic
W.r.t. transactions
Diffstat (limited to 'packages/taler-wallet-core/src/operations/balance.ts')
-rw-r--r--packages/taler-wallet-core/src/operations/balance.ts60
1 files changed, 46 insertions, 14 deletions
diff --git a/packages/taler-wallet-core/src/operations/balance.ts b/packages/taler-wallet-core/src/operations/balance.ts
index 3ab6649d7..af88181c0 100644
--- a/packages/taler-wallet-core/src/operations/balance.ts
+++ b/packages/taler-wallet-core/src/operations/balance.ts
@@ -20,14 +20,17 @@
* There are multiple definition of the wallet's balance.
* We use the following terminology:
*
- * - "available": Balance that the wallet believes will certainly be available
- * for spending, modulo any failures of the exchange or double spending issues.
- * This includes available coins *not* allocated to any
- * spending/refresh/... operation. Pending withdrawals are *not* counted
- * towards this balance, because they are not certain to succeed.
- * Pending refreshes *are* counted towards this balance.
- * This balance type is nice to show to the user, because it does not
- * temporarily decrease after payment when we are waiting for refreshes
+ * - "available": Balance that is available
+ * for spending from transactions in their final state and
+ * expected to be available from pending refreshes.
+ *
+ * - "pending-incoming": Expected (positive!) delta
+ * to the available balance that we expect to have
+ * after pending operations reach the "done" state.
+ *
+ * - "pending-outgoing": Amount that is currently allocated
+ * to be spent, but the spend operation could still be aborted
+ * and part of the pending-outgoing amount could be recovered.
*
* - "material": Balance that the wallet believes it could spend *right now*,
* without waiting for any operations to complete.
@@ -61,11 +64,13 @@ import {
AllowedExchangeInfo,
RefreshGroupRecord,
WalletStoresV1,
+ WithdrawalGroupStatus,
} from "../db.js";
import { InternalWalletState } from "../internal-wallet-state.js";
import { checkLogicInvariant } from "../util/invariants.js";
import { GetReadOnlyAccess } from "../util/query.js";
import { getExchangeDetails } from "./exchanges.js";
+import { assertUnreachable } from "../util/assertUnreachable.js";
/**
* Logger.
@@ -133,7 +138,8 @@ export async function getBalancesInsideTransaction(
await tx.coinAvailability.iter().forEach((ca) => {
const b = initBalance(ca.currency);
- for (let i = 0; i < ca.freshCoinCount; i++) {
+ const count = ca.visibleCoinCount ?? 0;
+ for (let i = 0; i < count; i++) {
b.available = Amounts.add(b.available, {
currency: ca.currency,
fraction: ca.amountFrac,
@@ -150,14 +156,40 @@ export async function getBalancesInsideTransaction(
).amount;
});
- await tx.withdrawalGroups.iter().forEach((wds) => {
- if (wds.timestampFinish) {
- return;
+ // FIXME: Use indexing to filter out final transactions.
+ await tx.withdrawalGroups.iter().forEach((wgRecord) => {
+ switch (wgRecord.status) {
+ case WithdrawalGroupStatus.AbortedBank:
+ case WithdrawalGroupStatus.AbortedExchange:
+ case WithdrawalGroupStatus.FailedAbortingBank:
+ case WithdrawalGroupStatus.FailedBankAborted:
+ case WithdrawalGroupStatus.Finished:
+ // Does not count as pendingIncoming
+ return;
+ case WithdrawalGroupStatus.PendingReady:
+ case WithdrawalGroupStatus.AbortingBank:
+ case WithdrawalGroupStatus.PendingAml:
+ case WithdrawalGroupStatus.PendingKyc:
+ case WithdrawalGroupStatus.PendingQueryingStatus:
+ case WithdrawalGroupStatus.SuspendedWaitConfirmBank:
+ case WithdrawalGroupStatus.SuspendedReady:
+ case WithdrawalGroupStatus.SuspendedRegisteringBank:
+ case WithdrawalGroupStatus.SuspendedKyc:
+ case WithdrawalGroupStatus.SuspendedAbortingBank:
+ case WithdrawalGroupStatus.SuspendedAml:
+ case WithdrawalGroupStatus.PendingRegisteringBank:
+ case WithdrawalGroupStatus.PendingWaitConfirmBank:
+ case WithdrawalGroupStatus.SuspendedQueryingStatus:
+ break;
+ default:
+ assertUnreachable(wgRecord.status);
}
- const b = initBalance(Amounts.currencyOf(wds.denomsSel.totalWithdrawCost));
+ const b = initBalance(
+ Amounts.currencyOf(wgRecord.denomsSel.totalWithdrawCost),
+ );
b.pendingIncoming = Amounts.add(
b.pendingIncoming,
- wds.denomsSel.totalCoinValue,
+ wgRecord.denomsSel.totalCoinValue,
).amount;
});