taler-typescript-core

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

commit 9208f77d20e1b50f3dedd0d38da6c3bb79969c2e
parent c5ed91b66e42f699d1668c360fd38424cae2c708
Author: Florian Dold <florian@dold.me>
Date:   Mon,  1 Jun 2026 13:28:19 +0200

wallet-core: add defaultExpiration to checkPeerPushDebit response

Diffstat:
Mpackages/taler-util/src/types-taler-wallet.ts | 6++++++
Mpackages/taler-wallet-core/src/db.ts | 2++
Mpackages/taler-wallet-core/src/exchanges.ts | 3+++
Mpackages/taler-wallet-core/src/pay-peer-push-debit.ts | 23++++++++++++++++++++++-
4 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/packages/taler-util/src/types-taler-wallet.ts b/packages/taler-util/src/types-taler-wallet.ts @@ -3479,6 +3479,12 @@ export interface CheckPeerPushDebitOkResponse { * coin. */ maxExpirationDate: TalerProtocolTimestamp; + + /** + * Default expiration, as given by the exchange + * (or 1d if the exchange does not specify it). + */ + defaultExpiration: TalerProtocolDuration; } export interface InitiatePeerPushDebitRequest { diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts @@ -693,6 +693,8 @@ export interface ExchangeDetailsRecord { * for compliance with the rules of that bank. */ bankComplianceLanguage: string | undefined; + + defaultPeerPushExpiration: TalerProtocolDuration | undefined; } export interface ExchangeDetailsPointer { diff --git a/packages/taler-wallet-core/src/exchanges.ts b/packages/taler-wallet-core/src/exchanges.ts @@ -533,6 +533,7 @@ export interface ExchangeDetails { auditors: ExchangeAuditor[]; globalFees: ExchangeGlobalFees[]; reserveClosingDelay: TalerProtocolDuration; + defaultPeerPushExpiration: TalerProtocolDuration | undefined; shoppingUrl: string | undefined; } @@ -553,6 +554,7 @@ export async function getExchangeDetailsInTx( globalFees: det.globalFees, reserveClosingDelay: det.reserveClosingDelay, shoppingUrl: det.shoppingUrl, + defaultPeerPushExpiration: det.defaultPeerPushExpiration, }; } @@ -1990,6 +1992,7 @@ export async function updateExchangeFromUrlHandler( zeroLimits: keysInfo.zero_limits, bankComplianceLanguage: keysInfo.bank_compliance_language, shoppingUrl: keysInfo.shopping_url, + defaultPeerPushExpiration: keysInfo.default_p2p_push_expiration, }; r.noFees = noFees; r.peerPaymentsDisabled = peerPaymentsDisabled; diff --git a/packages/taler-wallet-core/src/pay-peer-push-debit.ts b/packages/taler-wallet-core/src/pay-peer-push-debit.ts @@ -21,6 +21,7 @@ import { CheckPeerPushDebitResponse, CoinRefreshRequest, ContractTermsUtil, + Duration, ExchangePurseDeposits, HostPortPath, HttpStatusCode, @@ -36,6 +37,7 @@ import { TalerErrorCode, TalerErrorDetail, TalerPreciseTimestamp, + TalerProtocolDuration, TalerProtocolTimestamp, Transaction, TransactionAction, @@ -79,6 +81,7 @@ import { } from "./db.js"; import { fetchFreshExchange, + getExchangeDetailsInTx, getPreferredExchangeForCurrency, getScopeForAllExchanges, } from "./exchanges.js"; @@ -407,6 +410,17 @@ export async function checkPeerPushDebitV2( ); } +async function getDefaultPeerPushExpiration( + wex: WalletExecutionContext, + exchangeBaseUrl: string, +): Promise<TalerProtocolDuration> { + const d = Duration.toTalerProtocolDuration(Duration.fromSpec({ days: 1 })); + return await wex.runLegacyWalletDbTx(async (tx) => { + const ex = await getExchangeDetailsInTx(tx, exchangeBaseUrl); + return ex?.defaultPeerPushExpiration ?? d; + }); +} + async function internalCheckPeerPushDebit( wex: WalletExecutionContext, req: CheckPeerPushDebitRequest, @@ -435,12 +449,17 @@ async function internalCheckPeerPushDebit( if (!exchangeBaseUrl) { throw Error("no exchange found for payment"); } + return { type: "ok", amountEffective: req.amount, amountRaw: req.amount, exchangeBaseUrl, maxExpirationDate: TalerProtocolTimestamp.never(), + defaultExpiration: await getDefaultPeerPushExpiration( + wex, + exchangeBaseUrl, + ), }; } const coinSelRes = await selectPeerCoins(wex, { @@ -470,12 +489,14 @@ async function internalCheckPeerPushDebit( await fetchFreshExchange(wex, coinSelRes.result.exchangeBaseUrl); const totalAmount = await getTotalPeerPaymentCost(wex, coins); logger.trace("computed total peer payment cost"); + const exchangeBaseUrl = coinSelRes.result.exchangeBaseUrl; return { type: "ok", - exchangeBaseUrl: coinSelRes.result.exchangeBaseUrl, + exchangeBaseUrl, amountEffective: Amounts.stringify(totalAmount), amountRaw: req.amount, maxExpirationDate: coinSelRes.result.maxExpirationDate, + defaultExpiration: await getDefaultPeerPushExpiration(wex, exchangeBaseUrl), }; }