taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

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:
Mpackages/taler-util/src/types-taler-wallet.ts | 1+
Mpackages/taler-wallet-core/src/pay-merchant.ts | 31++++++++++++++++++++++++++++++-
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,