diff options
author | Florian Dold <florian@dold.me> | 2023-05-05 19:03:44 +0200 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2023-05-07 21:51:02 +0200 |
commit | 7f0edb6a783d9a50f94f65c815c1280baecaac89 (patch) | |
tree | b4f3bc24fece1f651e8c2f69fc0fcf52e1d6f330 /packages/taler-wallet-core/src/operations/refresh.ts | |
parent | a0bf83fbb5db026389cc7d203adcff050d5a1b28 (diff) | |
download | wallet-core-7f0edb6a783d9a50f94f65c815c1280baecaac89.tar.xz |
wallet-core: refund DD37 refactoring
Diffstat (limited to 'packages/taler-wallet-core/src/operations/refresh.ts')
-rw-r--r-- | packages/taler-wallet-core/src/operations/refresh.ts | 111 |
1 files changed, 81 insertions, 30 deletions
diff --git a/packages/taler-wallet-core/src/operations/refresh.ts b/packages/taler-wallet-core/src/operations/refresh.ts index fda9a886a..843f37c8e 100644 --- a/packages/taler-wallet-core/src/operations/refresh.ts +++ b/packages/taler-wallet-core/src/operations/refresh.ts @@ -81,7 +81,7 @@ import { readUnexpectedResponseDetails, } from "@gnu-taler/taler-util/http"; import { checkDbInvariant } from "../util/invariants.js"; -import { GetReadWriteAccess } from "../util/query.js"; +import { GetReadOnlyAccess, GetReadWriteAccess } from "../util/query.js"; import { constructTaskIdentifier, OperationAttemptResult, @@ -874,18 +874,13 @@ async function processRefreshSession( await refreshReveal(ws, refreshGroupId, coinIndex); } -/** - * Create a refresh group for a list of coins. - * - * Refreshes the remaining amount on the coin, effectively capturing the remaining - * value in the refresh group. - * - * The caller must also ensure that the coins that should be refreshed exist - * in the current database transaction. - */ -export async function createRefreshGroup( +export interface RefreshOutputInfo { + outputPerCoin: AmountJson[]; +} + +export async function calculateRefreshOutput( ws: InternalWalletState, - tx: GetReadWriteAccess<{ + tx: GetReadOnlyAccess<{ denominations: typeof WalletStoresV1.denominations; coins: typeof WalletStoresV1.coins; refreshGroups: typeof WalletStoresV1.refreshGroups; @@ -893,12 +888,7 @@ export async function createRefreshGroup( }>, currency: string, oldCoinPubs: CoinRefreshRequest[], - reason: RefreshReason, - reasonDetails?: RefreshReasonDetails, -): Promise<RefreshGroupId> { - const refreshGroupId = encodeCrock(getRandomBytes(32)); - - const inputPerCoin: AmountJson[] = []; +): Promise<RefreshOutputInfo> { const estimatedOutputPerCoin: AmountJson[] = []; const denomsPerExchange: Record<string, DenominationRecord[]> = {}; @@ -931,6 +921,47 @@ export async function createRefreshGroup( !!denom, "denomination for existing coin must be in database", ); + const refreshAmount = ocp.amount; + const denoms = await getDenoms(coin.exchangeBaseUrl); + const cost = getTotalRefreshCost( + denoms, + denom, + Amounts.parseOrThrow(refreshAmount), + ws.config.testing.denomselAllowLate, + ); + const output = Amounts.sub(refreshAmount, cost).amount; + estimatedOutputPerCoin.push(output); + } + + return { + outputPerCoin: estimatedOutputPerCoin, + } +} + +async function applyRefresh( + ws: InternalWalletState, + tx: GetReadWriteAccess<{ + denominations: typeof WalletStoresV1.denominations; + coins: typeof WalletStoresV1.coins; + refreshGroups: typeof WalletStoresV1.refreshGroups; + coinAvailability: typeof WalletStoresV1.coinAvailability; + }>, + oldCoinPubs: CoinRefreshRequest[], + refreshGroupId: string, +): Promise<void> { + for (const ocp of oldCoinPubs) { + const coin = await tx.coins.get(ocp.coinPub); + checkDbInvariant(!!coin, "coin must be in database"); + const denom = await ws.getDenomInfo( + ws, + tx, + coin.exchangeBaseUrl, + coin.denomPubHash, + ); + checkDbInvariant( + !!denom, + "denomination for existing coin must be in database", + ); switch (coin.status) { case CoinStatus.Dormant: break; @@ -962,19 +993,39 @@ export async function createRefreshGroup( id: `txn:refresh:${refreshGroupId}`, }; } - const refreshAmount = ocp.amount; - inputPerCoin.push(Amounts.parseOrThrow(refreshAmount)); await tx.coins.put(coin); - const denoms = await getDenoms(coin.exchangeBaseUrl); - const cost = getTotalRefreshCost( - denoms, - denom, - Amounts.parseOrThrow(refreshAmount), - ws.config.testing.denomselAllowLate, - ); - const output = Amounts.sub(refreshAmount, cost).amount; - estimatedOutputPerCoin.push(output); } +} + +/** + * Create a refresh group for a list of coins. + * + * Refreshes the remaining amount on the coin, effectively capturing the remaining + * value in the refresh group. + * + * The caller must also ensure that the coins that should be refreshed exist + * in the current database transaction. + */ +export async function createRefreshGroup( + ws: InternalWalletState, + tx: GetReadWriteAccess<{ + denominations: typeof WalletStoresV1.denominations; + coins: typeof WalletStoresV1.coins; + refreshGroups: typeof WalletStoresV1.refreshGroups; + coinAvailability: typeof WalletStoresV1.coinAvailability; + }>, + currency: string, + oldCoinPubs: CoinRefreshRequest[], + reason: RefreshReason, + reasonDetails?: RefreshReasonDetails, +): Promise<RefreshGroupId> { + const refreshGroupId = encodeCrock(getRandomBytes(32)); + + const outInfo = await calculateRefreshOutput(ws, tx, currency, oldCoinPubs); + + const estimatedOutputPerCoin = outInfo.outputPerCoin; + + await applyRefresh(ws, tx, oldCoinPubs, refreshGroupId); const refreshGroup: RefreshGroupRecord = { operationStatus: RefreshOperationStatus.Pending, @@ -987,7 +1038,7 @@ export async function createRefreshGroup( reason, refreshGroupId, refreshSessionPerCoin: oldCoinPubs.map(() => undefined), - inputPerCoin: inputPerCoin.map((x) => Amounts.stringify(x)), + inputPerCoin: oldCoinPubs.map((x) => x.amount), estimatedOutputPerCoin: estimatedOutputPerCoin.map((x) => Amounts.stringify(x), ), |