diff options
Diffstat (limited to 'packages')
-rw-r--r-- | packages/taler-util/src/wallet-types.ts | 10 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/operations/pay-peer-push-debit.ts | 1 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/operations/refresh.ts | 21 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/util/coinSelection.test.ts | 7 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/util/coinSelection.ts | 26 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/versions.ts | 14 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/wallet.ts | 4 |
7 files changed, 70 insertions, 13 deletions
diff --git a/packages/taler-util/src/wallet-types.ts b/packages/taler-util/src/wallet-types.ts index b54ee8c0a..3b4bc6a29 100644 --- a/packages/taler-util/src/wallet-types.ts +++ b/packages/taler-util/src/wallet-types.ts @@ -2483,6 +2483,16 @@ export interface CheckPeerPushDebitResponse { amountRaw: AmountString; amountEffective: AmountString; exchangeBaseUrl: string; + /** + * Maximum expiration date, based on how close the coins + * used for the payment are to expiry. + * + * The value is based on when the wallet would typically + * automatically refresh the coins on its own, leaving enough + * time to get a refund for the push payment and refresh the + * coin. + */ + maxExpirationDate: TalerProtocolTimestamp; } export interface InitiatePeerPushDebitRequest { diff --git a/packages/taler-wallet-core/src/operations/pay-peer-push-debit.ts b/packages/taler-wallet-core/src/operations/pay-peer-push-debit.ts index 0608ec763..534114ed8 100644 --- a/packages/taler-wallet-core/src/operations/pay-peer-push-debit.ts +++ b/packages/taler-wallet-core/src/operations/pay-peer-push-debit.ts @@ -106,6 +106,7 @@ export async function checkPeerPushDebit( exchangeBaseUrl: coinSelRes.result.exchangeBaseUrl, amountEffective: Amounts.stringify(totalAmount), amountRaw: req.amount, + maxExpirationDate: coinSelRes.result.maxExpirationDate, }; } diff --git a/packages/taler-wallet-core/src/operations/refresh.ts b/packages/taler-wallet-core/src/operations/refresh.ts index 51dd9adac..e5bc3277d 100644 --- a/packages/taler-wallet-core/src/operations/refresh.ts +++ b/packages/taler-wallet-core/src/operations/refresh.ts @@ -50,6 +50,7 @@ import { TalerErrorCode, TalerErrorDetail, TalerPreciseTimestamp, + TalerProtocolTimestamp, TransactionAction, TransactionMajorState, TransactionState, @@ -1141,18 +1142,30 @@ function getAutoRefreshCheckThreshold(d: DenominationRecord): AbsoluteTime { /** * Timestamp after which the wallet would do an auto-refresh. */ -function getAutoRefreshExecuteThreshold(d: DenominationRecord): AbsoluteTime { +export function getAutoRefreshExecuteThreshold(d: { + stampExpireWithdraw: TalerProtocolTimestamp; + stampExpireDeposit: TalerProtocolTimestamp; +}): AbsoluteTime { const expireWithdraw = AbsoluteTime.fromProtocolTimestamp( - timestampProtocolFromDb(d.stampExpireWithdraw), + d.stampExpireWithdraw, ); const expireDeposit = AbsoluteTime.fromProtocolTimestamp( - timestampProtocolFromDb(d.stampExpireDeposit), + d.stampExpireDeposit, ); const delta = AbsoluteTime.difference(expireWithdraw, expireDeposit); const deltaDiv = durationMul(delta, 0.5); return AbsoluteTime.addDuration(expireWithdraw, deltaDiv); } +function getAutoRefreshExecuteThresholdForDenom( + d: DenominationRecord, +): AbsoluteTime { + return getAutoRefreshExecuteThreshold({ + stampExpireWithdraw: timestampProtocolFromDb(d.stampExpireWithdraw), + stampExpireDeposit: timestampProtocolFromDb(d.stampExpireDeposit), + }); +} + export async function autoRefresh( ws: InternalWalletState, exchangeBaseUrl: string, @@ -1196,7 +1209,7 @@ export async function autoRefresh( logger.warn("denomination not in database"); continue; } - const executeThreshold = getAutoRefreshExecuteThreshold(denom); + const executeThreshold = getAutoRefreshExecuteThresholdForDenom(denom); if (AbsoluteTime.isExpired(executeThreshold)) { refreshCoins.push({ coinPub: coin.coinPub, diff --git a/packages/taler-wallet-core/src/util/coinSelection.test.ts b/packages/taler-wallet-core/src/util/coinSelection.test.ts index 69c25a2fa..055c42902 100644 --- a/packages/taler-wallet-core/src/util/coinSelection.test.ts +++ b/packages/taler-wallet-core/src/util/coinSelection.test.ts @@ -19,6 +19,7 @@ import { Amounts, DenomKeyType, Duration, + TalerProtocolTimestamp, j2s, } from "@gnu-taler/taler-util"; import test, { ExecutionContext } from "ava"; @@ -66,6 +67,8 @@ test("p2p: should select the coin", (t) => { denomPubHash: "hash0", maxAge: 32, contributions: [Amounts.parseOrThrow("LOCAL:2.1")], + expireDeposit: TalerProtocolTimestamp.fromSeconds(1702412542), + expireWithdraw: TalerProtocolTimestamp.fromSeconds(1702412542), }, }); @@ -106,6 +109,8 @@ test("p2p: should select 3 coins", (t) => { Amounts.parseOrThrow("LOCAL:9.9"), Amounts.parseOrThrow("LOCAL:0.5"), ], + expireDeposit: TalerProtocolTimestamp.fromSeconds(1702412542), + expireWithdraw: TalerProtocolTimestamp.fromSeconds(1702412542), }, }); @@ -192,6 +197,8 @@ test("pay: select one coin to pay with fee", (t) => { denomPubHash: "hash0", maxAge: 32, contributions: [Amounts.parseOrThrow("LOCAL:2.2")], + expireDeposit: TalerProtocolTimestamp.fromSeconds(1702412542), + expireWithdraw: TalerProtocolTimestamp.fromSeconds(1702412542), }, }); diff --git a/packages/taler-wallet-core/src/util/coinSelection.ts b/packages/taler-wallet-core/src/util/coinSelection.ts index 5928cd19b..e3fbffe98 100644 --- a/packages/taler-wallet-core/src/util/coinSelection.ts +++ b/packages/taler-wallet-core/src/util/coinSelection.ts @@ -51,10 +51,12 @@ import { PayMerchantInsufficientBalanceDetails, PayPeerInsufficientBalanceDetails, strcmp, + TalerProtocolTimestamp, UnblindedSignature, } from "@gnu-taler/taler-util"; import { DenominationRecord } from "../db.js"; import { + getAutoRefreshExecuteThreshold, getExchangeDetails, isWithdrawableDenom, WalletDbReadOnlyTransaction, @@ -416,6 +418,8 @@ interface SelResult { [avKey: string]: { exchangeBaseUrl: string; denomPubHash: string; + expireWithdraw: TalerProtocolTimestamp; + expireDeposit: TalerProtocolTimestamp; maxAge: number; contributions: AmountJson[]; }; @@ -426,6 +430,7 @@ export function testing_selectGreedy( ): ReturnType<typeof selectGreedy> { return selectGreedy(...args); } + function selectGreedy( req: SelectPayCoinRequestNg, candidateDenoms: AvailableDenom[], @@ -483,6 +488,8 @@ function selectGreedy( denomPubHash: denom.denomPubHash, exchangeBaseUrl: denom.exchangeBaseUrl, maxAge: denom.maxAge, + expireDeposit: denom.stampExpireDeposit, + expireWithdraw: denom.stampExpireWithdraw, }; } sd.contributions.push(...contributions); @@ -521,6 +528,8 @@ function selectForced( denomPubHash: aci.denomPubHash, exchangeBaseUrl: aci.exchangeBaseUrl, maxAge: aci.maxAge, + expireDeposit: aci.stampExpireDeposit, + expireWithdraw: aci.stampExpireWithdraw, }; } sd.contributions.push(Amounts.parseOrThrow(forcedCoin.value)); @@ -870,6 +879,8 @@ export interface PeerCoinSelectionDetails { * How much of the deposit fees is the customer paying? */ depositFees: AmountJson; + + maxExpirationDate: TalerProtocolTimestamp; } export type SelectPeerCoinsResult = @@ -1009,6 +1020,8 @@ function greedySelectPeer( denomPubHash: denom.denomPubHash, exchangeBaseUrl: denom.exchangeBaseUrl, maxAge: denom.maxAge, + expireDeposit: denom.stampExpireDeposit, + expireWithdraw: denom.stampExpireWithdraw, }; } sd.contributions.push(...contributions); @@ -1114,8 +1127,20 @@ export async function selectPeerCoins( ); if (selectedDenom) { + let minAutorefreshExecuteThreshold = TalerProtocolTimestamp.never(); for (const dph of Object.keys(selectedDenom)) { const selInfo = selectedDenom[dph]; + // Compute earliest time that a selected denom + // would have its coins auto-refreshed. + minAutorefreshExecuteThreshold = TalerProtocolTimestamp.min( + minAutorefreshExecuteThreshold, + AbsoluteTime.toProtocolTimestamp( + getAutoRefreshExecuteThreshold({ + stampExpireDeposit: selInfo.expireDeposit, + stampExpireWithdraw: selInfo.expireWithdraw, + }), + ), + ); const numRequested = selInfo.contributions.length; const query = [ selInfo.exchangeBaseUrl, @@ -1150,6 +1175,7 @@ export async function selectPeerCoins( exchangeBaseUrl: exch.baseUrl, coins: resCoins, depositFees: tally.depositFeesAcc, + maxExpirationDate: minAutorefreshExecuteThreshold, }; return { type: "success", result: res }; } diff --git a/packages/taler-wallet-core/src/versions.ts b/packages/taler-wallet-core/src/versions.ts index 8e0e5561b..ba6fdfaaa 100644 --- a/packages/taler-wallet-core/src/versions.ts +++ b/packages/taler-wallet-core/src/versions.ts @@ -36,21 +36,21 @@ export const WALLET_MERCHANT_PROTOCOL_VERSION = "5:0:1"; export const WALLET_BANK_INTEGRATION_PROTOCOL_VERSION = "0:0:0"; /** - * Semver of the wallet-core implementation. + * Semver of the wallet-core API implementation. * Will be replaced with the value from package.json in a * post-compilation step (inside lib/). */ -export const WALLET_CORE_IMPLEMENTATION_VERSION = "1:0:0"; +export const WALLET_CORE_API_IMPLEMENTATION_VERSION = "2:0:1"; /** * Libtool rules: - * - * If the library source code has changed at all since the last update, + * + * If the library source code has changed at all since the last update, * then increment revision (‘c:r:a’ becomes ‘c:r+1:a’). * If any interfaces have been added, removed, or changed since the last * update, increment current, and set revision to 0. - * If any interfaces have been added since the last public release, then + * If any interfaces have been added since the last public release, then * increment age. - * If any interfaces have been removed or changed since the last public + * If any interfaces have been removed or changed since the last public * release, then set age to 0. - */
\ No newline at end of file + */ diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index fc4ae832d..580b30864 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -310,7 +310,7 @@ import { import { TimerAPI, TimerGroup } from "./util/timer.js"; import { WALLET_BANK_INTEGRATION_PROTOCOL_VERSION, - WALLET_CORE_IMPLEMENTATION_VERSION, + WALLET_CORE_API_IMPLEMENTATION_VERSION, WALLET_EXCHANGE_PROTOCOL_VERSION, WALLET_MERCHANT_PROTOCOL_VERSION, } from "./versions.js"; @@ -1519,7 +1519,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>( export function getVersion(ws: InternalWalletState): WalletCoreVersion { const result: WalletCoreVersion = { hash: undefined, - version: WALLET_CORE_IMPLEMENTATION_VERSION, + version: WALLET_CORE_API_IMPLEMENTATION_VERSION, exchange: WALLET_EXCHANGE_PROTOCOL_VERSION, merchant: WALLET_MERCHANT_PROTOCOL_VERSION, bank: WALLET_BANK_INTEGRATION_PROTOCOL_VERSION, |