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:
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),
};
}