diff options
author | Florian Dold <florian@dold.me> | 2022-09-16 16:20:47 +0200 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2022-09-16 16:32:21 +0200 |
commit | b91caf977fad8da11e523ca3a39064dd86e04c64 (patch) | |
tree | 732e1543d2555094d7f9a9ca242309847c1a33a3 /packages/taler-wallet-core/src/wallet.ts | |
parent | 2747bc260bc05418974570d04d7f999dfc988cda (diff) | |
download | wallet-core-b91caf977fad8da11e523ca3a39064dd86e04c64.tar.xz |
wallet-core: support age restrictions in new coin selection
Diffstat (limited to 'packages/taler-wallet-core/src/wallet.ts')
-rw-r--r-- | packages/taler-wallet-core/src/wallet.ts | 74 |
1 files changed, 52 insertions, 22 deletions
diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index 4751f7976..812106c7a 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -802,6 +802,7 @@ export async function makeCoinAvailable( ws: InternalWalletState, tx: GetReadWriteAccess<{ coins: typeof WalletStoresV1.coins; + coinAvailability: typeof WalletStoresV1.coinAvailability; denominations: typeof WalletStoresV1.denominations; }>, coinRecord: CoinRecord, @@ -811,12 +812,26 @@ export async function makeCoinAvailable( coinRecord.denomPubHash, ]); checkDbInvariant(!!denom); - if (!denom.freshCoinCount) { - denom.freshCoinCount = 0; + const ageRestriction = coinRecord.maxAge; + let car = await tx.coinAvailability.get([ + coinRecord.exchangeBaseUrl, + coinRecord.denomPubHash, + ageRestriction, + ]); + if (!car) { + car = { + maxAge: ageRestriction, + amountFrac: denom.amountFrac, + amountVal: denom.amountVal, + currency: denom.currency, + denomPubHash: denom.denomPubHash, + exchangeBaseUrl: denom.exchangeBaseUrl, + freshCoinCount: 0, + }; } - denom.freshCoinCount++; + car.freshCoinCount++; await tx.coins.put(coinRecord); - await tx.denominations.put(denom); + await tx.coinAvailability.put(car); } export interface CoinsSpendInfo { @@ -833,6 +848,7 @@ export async function spendCoins( ws: InternalWalletState, tx: GetReadWriteAccess<{ coins: typeof WalletStoresV1.coins; + coinAvailability: typeof WalletStoresV1.coinAvailability; refreshGroups: typeof WalletStoresV1.refreshGroups; denominations: typeof WalletStoresV1.denominations; }>, @@ -843,11 +859,12 @@ export async function spendCoins( if (!coin) { throw Error("coin allocated for payment doesn't exist anymore"); } - const denom = await tx.denominations.get([ + const coinAvailability = await tx.coinAvailability.get([ coin.exchangeBaseUrl, coin.denomPubHash, + coin.maxAge, ]); - checkDbInvariant(!!denom); + checkDbInvariant(!!coinAvailability); const contrib = csi.contributions[i]; if (coin.status !== CoinStatus.Fresh) { const alloc = coin.allocation; @@ -874,13 +891,15 @@ export async function spendCoins( throw Error("not enough remaining balance on coin for payment"); } coin.currentAmount = remaining.amount; - checkDbInvariant(!!denom); - if (denom.freshCoinCount == null || denom.freshCoinCount === 0) { - throw Error(`invalid coin count ${denom.freshCoinCount} in DB`); + checkDbInvariant(!!coinAvailability); + if (coinAvailability.freshCoinCount === 0) { + throw Error( + `invalid coin count ${coinAvailability.freshCoinCount} in DB`, + ); } - denom.freshCoinCount--; + coinAvailability.freshCoinCount--; await tx.coins.put(coin); - await tx.denominations.put(denom); + await tx.coinAvailability.put(coinAvailability); } const refreshCoinPubs = csi.coinPubs.map((x) => ({ coinPub: x, @@ -894,39 +913,45 @@ async function setCoinSuspended( suspended: boolean, ): Promise<void> { await ws.db - .mktx((x) => [x.coins, x.denominations]) + .mktx((x) => [x.coins, x.coinAvailability]) .runReadWrite(async (tx) => { const c = await tx.coins.get(coinPub); if (!c) { logger.warn(`coin ${coinPub} not found, won't suspend`); return; } - const denom = await tx.denominations.get([ + const coinAvailability = await tx.coinAvailability.get([ c.exchangeBaseUrl, c.denomPubHash, + c.maxAge, ]); - checkDbInvariant(!!denom); + checkDbInvariant(!!coinAvailability); if (suspended) { if (c.status !== CoinStatus.Fresh) { return; } - if (denom.freshCoinCount == null || denom.freshCoinCount === 0) { - throw Error(`invalid coin count ${denom.freshCoinCount} in DB`); + if ( + coinAvailability.freshCoinCount == null || + coinAvailability.freshCoinCount === 0 + ) { + throw Error( + `invalid coin count ${coinAvailability.freshCoinCount} in DB`, + ); } - denom.freshCoinCount--; + coinAvailability.freshCoinCount--; c.status = CoinStatus.FreshSuspended; } else { if (c.status == CoinStatus.Dormant) { return; } - if (denom.freshCoinCount == null) { - denom.freshCoinCount = 0; + if (coinAvailability.freshCoinCount == null) { + coinAvailability.freshCoinCount = 0; } - denom.freshCoinCount++; + coinAvailability.freshCoinCount++; c.status = CoinStatus.Fresh; } await tx.coins.put(c); - await tx.denominations.put(denom); + await tx.coinAvailability.put(coinAvailability); }); } @@ -1195,7 +1220,12 @@ async function dispatchRequestInternal( const req = codecForForceRefreshRequest().decode(payload); const coinPubs = req.coinPubList.map((x) => ({ coinPub: x })); const refreshGroupId = await ws.db - .mktx((x) => [x.refreshGroups, x.denominations, x.coins]) + .mktx((x) => [ + x.refreshGroups, + x.coinAvailability, + x.denominations, + x.coins, + ]) .runReadWrite(async (tx) => { return await createRefreshGroup( ws, |