commit fb87b6b5ef97d0e461b232b1ae6c0ca968fdc216
parent aaa79dd33b884d362d6ec39b17baf1efb6f88b5b
Author: Florian Dold <florian@dold.me>
Date: Tue, 2 Jun 2026 01:46:54 +0200
Revert "wallet-core: subtract prospective coin selections from available balance"
This reverts commit aaa79dd33b884d362d6ec39b17baf1efb6f88b5b.
Diffstat:
3 files changed, 26 insertions(+), 126 deletions(-)
diff --git a/packages/taler-wallet-core/src/balance.ts b/packages/taler-wallet-core/src/balance.ts
@@ -110,8 +110,7 @@ const logger = new Logger("operations/balance.ts");
interface WalletBalance {
scopeInfo: ScopeInfo;
- availablePos: AmountJson;
- availableNeg: AmountJson;
+ available: AmountJson;
pendingIncoming: AmountJson;
pendingOutgoing: AmountJson;
flagIncomingKyc: boolean;
@@ -211,8 +210,7 @@ class BalancesStore {
const zero = Amounts.zeroOfCurrency(currency);
b = this.balanceStore[balanceKey] = {
scopeInfo,
- availablePos: zero,
- availableNeg: zero,
+ available: zero,
pendingIncoming: zero,
pendingOutgoing: zero,
flagIncomingConfirmation: false,
@@ -263,16 +261,7 @@ class BalancesStore {
amount: AmountLike,
): Promise<void> {
const b = await this.initBalance(currency, exchangeBaseUrl);
- b.availablePos = Amounts.add(b.availablePos, amount).amount;
- }
-
- async subAvailable(
- currency: string,
- exchangeBaseUrl: string,
- amount: AmountLike,
- ): Promise<void> {
- const b = await this.initBalance(currency, exchangeBaseUrl);
- b.availableNeg = Amounts.sub(b.availableNeg, amount).amount;
+ b.available = Amounts.add(b.available, amount).amount;
}
async addPendingIncoming(
@@ -389,9 +378,7 @@ class BalancesStore {
}
balancesResponse.balances.push({
scopeInfo: v.scopeInfo,
- available: Amounts.stringify(
- Amounts.sub(v.availablePos, v.availableNeg).amount,
- ),
+ available: Amounts.stringify(v.available),
pendingIncoming: Amounts.stringify(v.pendingIncoming),
pendingOutgoing: Amounts.stringify(v.pendingOutgoing),
flags,
@@ -584,28 +571,14 @@ export async function getBalancesInsideTransaction(
await tx.peerPushDebit.indexes.byStatus
.iter(keyRangeActive)
.forEachAsync(async (ppdRecord) => {
- const currency = Amounts.currencyOf(ppdRecord.amount);
switch (ppdRecord.status) {
- case PeerPushDebitStatus.PendingCreatePurse:
- case PeerPushDebitStatus.SuspendedCreatePurse: {
- if (ppdRecord.coinSel == null) {
- await balanceStore.subAvailable(
- currency,
- ppdRecord.exchangeBaseUrl,
- ppdRecord.totalCost,
- );
- }
- await balanceStore.addPendingOutgoing(
- currency,
- ppdRecord.exchangeBaseUrl,
- ppdRecord.totalCost,
- );
- break;
- }
case PeerPushDebitStatus.AbortingDeletePurse:
case PeerPushDebitStatus.SuspendedAbortingDeletePurse:
case PeerPushDebitStatus.PendingReady:
- case PeerPushDebitStatus.SuspendedReady: {
+ case PeerPushDebitStatus.SuspendedReady:
+ case PeerPushDebitStatus.PendingCreatePurse:
+ case PeerPushDebitStatus.SuspendedCreatePurse: {
+ const currency = Amounts.currencyOf(ppdRecord.amount);
await balanceStore.addPendingOutgoing(
currency,
ppdRecord.exchangeBaseUrl,
@@ -681,27 +654,12 @@ export async function getBalancesInsideTransaction(
await tx.peerPullDebit.indexes.byStatus
.iter(keyRangeActive)
.forEachAsync(async (rec) => {
- const currency = Amounts.currencyOf(rec.amount);
- switch (rec.status) {
- case PeerPullDebitRecordStatus.PendingDeposit:
- case PeerPullDebitRecordStatus.SuspendedDeposit:
- // We're on a prospective coin selection,
- // thus the amount of this transaction gets
- // deducted from the available amount.
- if (rec.coinSel == null) {
- await balanceStore.subAvailable(
- currency,
- rec.exchangeBaseUrl,
- rec.totalCostEstimated,
- );
- }
- break;
- }
switch (rec.status) {
case PeerPullDebitRecordStatus.PendingDeposit:
- case PeerPullDebitRecordStatus.SuspendedDeposit:
case PeerPullDebitRecordStatus.AbortingRefresh:
- case PeerPullDebitRecordStatus.SuspendedAbortingRefresh: {
+ case PeerPullDebitRecordStatus.SuspendedAbortingRefresh:
+ case PeerPullDebitRecordStatus.SuspendedDeposit:
+ const currency = Amounts.currencyOf(rec.amount);
const amount = rec.coinSel?.totalCost ?? rec.amount;
await balanceStore.addPendingOutgoing(
currency,
@@ -709,7 +667,6 @@ export async function getBalancesInsideTransaction(
amount,
);
break;
- }
}
});
@@ -719,38 +676,23 @@ export async function getBalancesInsideTransaction(
switch (rec.purchaseStatus) {
case PurchaseStatus.SuspendedPaying:
case PurchaseStatus.PendingPaying:
- // We're on a prospective coin selection,
- // thus the amount of this transaction gets
- // deducted from the available amount.
- if (
- rec.payInfo &&
- !rec.payInfo.payCoinSelection &&
- rec.payInfo.prospectivePayCoinSelection
- ) {
- const currency = Amounts.currencyOf(rec.payInfo.totalPayCost);
- for (const pr of rec.payInfo.prospectivePayCoinSelection)
- await balanceStore.subAvailable(
- currency,
- pr.contribution,
- pr.exchangeBaseUrl,
- );
+ if (!rec.payInfo || !rec.payInfo.payCoinSelection?.coinPubs) {
+ break;
}
- if (rec.payInfo && rec.payInfo.payCoinSelection?.coinPubs) {
- // FIXME: This is pretty slow, cache?
- const currency = Amounts.currencyOf(rec.payInfo.totalPayCost);
- const sel = rec.payInfo.payCoinSelection;
- for (let i = 0; i < sel.coinPubs.length; i++) {
- const coinPub = sel.coinPubs[i];
- const coinRec = await tx.coins.get(coinPub);
- if (!coinRec) {
- continue;
- }
- await balanceStore.addPendingOutgoing(
- currency,
- coinRec.exchangeBaseUrl,
- sel.coinContributions[i],
- );
+ // FIXME: This is pretty slow, cache?
+ const currency = Amounts.currencyOf(rec.payInfo.totalPayCost);
+ const sel = rec.payInfo.payCoinSelection;
+ for (let i = 0; i < sel.coinPubs.length; i++) {
+ const coinPub = sel.coinPubs[i];
+ const coinRec = await tx.coins.get(coinPub);
+ if (!coinRec) {
+ continue;
}
+ await balanceStore.addPendingOutgoing(
+ currency,
+ coinRec.exchangeBaseUrl,
+ sel.coinContributions[i],
+ );
}
}
});
@@ -772,21 +714,6 @@ export async function getBalancesInsideTransaction(
case DepositOperationStatus.SuspendedDepositKyc:
case DepositOperationStatus.SuspendedDepositKycAuth:
await balanceStore.setFlagOutgoingKyc(currency, e);
- if (dgRecord.payCoinSelection == null) {
- // We're on a prospective coin selection,
- // thus the amount of this transaction gets
- // deducted from the available amount.
- const perExchange = dgRecord.infoPerExchange;
- if (perExchange) {
- for (const [e, v] of Object.entries(perExchange)) {
- await balanceStore.subAvailable(
- currency,
- e,
- v.amountEffective,
- );
- }
- }
- }
}
switch (dgRecord.operationStatus) {
case DepositOperationStatus.SuspendedAggregateKyc:
diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts
@@ -1516,7 +1516,6 @@ export interface PurchasePayInfo {
* Undefined if payment is blocked by a pending refund.
*/
payCoinSelection?: DbCoinSelection;
-
/**
* Undefined if payment is blocked by a pending refund.
*/
@@ -1524,11 +1523,6 @@ export interface PurchasePayInfo {
payTokenSelection?: DbTokenSelection;
- prospectivePayCoinSelection?: {
- exchangeBaseUrl: string;
- contribution: AmountString;
- }[];
-
/**
* Token signatures from merchant.
*/
diff --git a/packages/taler-wallet-core/src/pay-merchant.ts b/packages/taler-wallet-core/src/pay-merchant.ts
@@ -86,7 +86,6 @@ import {
PreparePayResult,
PreparePayResultType,
PreparePayTemplateRequest,
- ProspectivePayCoinSelection,
randomBytes,
RefreshReason,
RefundInfoShort,
@@ -1524,23 +1523,6 @@ function setCoinSel(rec: PurchaseRecord, coinSel: PayCoinSelection): void {
rec.exchanges.sort();
}
-function setProspectiveCoinSel(
- rec: PurchaseRecord,
- coinSel: ProspectivePayCoinSelection,
-): void {
- checkLogicInvariant(!!rec.payInfo);
- rec.payInfo.prospectivePayCoinSelection = coinSel.prospectiveCoins.map(
- (x) => ({
- contribution: x.contribution,
- exchangeBaseUrl: x.exchangeBaseUrl,
- }),
- );
- rec.exchanges = [
- ...new Set(coinSel.prospectiveCoins.map((x) => x.exchangeBaseUrl)),
- ];
- rec.exchanges.sort();
-}
-
async function reselectCoinsTx(
tx: WalletIndexedDbTransaction,
ctx: PayMerchantTransactionContext,
@@ -2953,9 +2935,6 @@ export async function confirmPay(
if (selectCoinsResult.type === "success") {
setCoinSel(p, selectCoinsResult.coinSel);
}
- if (selectCoinsResult.type === "prospective") {
- setProspectiveCoinSel(p, selectCoinsResult.result);
- }
p.lastSessionId = sessionId;
p.timestampAccept = timestampPreciseToDb(TalerPreciseTimestamp.now());
p.purchaseStatus = PurchaseStatus.PendingPaying;