commit 45c3cd31b0db889575f30a0ed3962061f2f2d62b
parent 783f7d0b9a1df3ed2316cb402ac76a33d3b92ab3
Author: Florian Dold <florian@dold.me>
Date: Wed, 3 Jun 2026 19:34:50 +0200
wallet-core: return scopeInfo for each choice
Diffstat:
2 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/packages/taler-util/src/types-taler-wallet.ts b/packages/taler-util/src/types-taler-wallet.ts
@@ -2598,6 +2598,7 @@ export interface ChoiceSelectionDetailPaymentPossible {
status: ChoiceSelectionDetailType.PaymentPossible;
amountRaw: AmountString;
amountEffective: AmountString;
+ scopeInfo: ScopeInfo;
tokenDetails?: PaymentTokenAvailabilityDetails;
}
diff --git a/packages/taler-wallet-core/src/pay-merchant.ts b/packages/taler-wallet-core/src/pay-merchant.ts
@@ -174,7 +174,11 @@ import {
WalletIndexedDbTransaction,
} from "./db.js";
import { acceptDonauBlindSigs, generateDonauPlanchets } from "./donau.js";
-import { getScopeForAllCoins, getScopeForAllExchanges } from "./exchanges.js";
+import {
+ getExchangeScopeInfoOrUndefined,
+ getScopeForAllCoins,
+ getScopeForAllExchanges,
+} from "./exchanges.js";
import {
calculateRefreshOutput,
createRefreshGroup,
@@ -2684,6 +2688,8 @@ export async function getChoicesForPayment(
logger.trace("coin selection result", selectCoinsResult);
+ const exchanges: Set<string> = new Set();
+
switch (selectCoinsResult.type) {
case "success": {
amountEffective = await getTotalPaymentCostInTx(
@@ -2692,6 +2698,9 @@ export async function getChoicesForPayment(
currency,
selectCoinsResult.coinSel.coins,
);
+ selectCoinsResult.coinSel.coins.forEach((x) => {
+ exchanges.add(x.exchangeBaseUrl);
+ });
break;
}
case "prospective": {
@@ -2701,6 +2710,9 @@ export async function getChoicesForPayment(
currency,
selectCoinsResult.result.prospectiveCoins,
);
+ selectCoinsResult.result.prospectiveCoins.forEach((x) => {
+ exchanges.add(x.exchangeBaseUrl);
+ });
break;
}
case "failure": {
@@ -2724,8 +2736,25 @@ export async function getChoicesForPayment(
tokenDetails: tokenSelection.details,
};
} else {
+ // We use the first known scope for the
+ // exchanges of the selected coins.
+ // If no such scope exists, we return
+ // the global currency scope as a fallback.
+ let scopeInfo = await wex.runLegacyWalletDbTx(async (tx) => {
+ for (const exch of exchanges) {
+ const s = await getExchangeScopeInfoOrUndefined(tx, exch);
+ if (s != null) {
+ return s;
+ }
+ }
+ return {
+ type: ScopeType.Global,
+ currency,
+ } satisfies ScopeInfo;
+ });
choice = {
status: ChoiceSelectionDetailType.PaymentPossible,
+ scopeInfo,
amountRaw: amountRaw,
amountEffective: Amounts.stringify(amountEffective!),
tokenDetails: tokenSelection.details,