aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/operations/refresh.ts
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2023-05-05 19:03:44 +0200
committerFlorian Dold <florian@dold.me>2023-05-07 21:51:02 +0200
commit7f0edb6a783d9a50f94f65c815c1280baecaac89 (patch)
treeb4f3bc24fece1f651e8c2f69fc0fcf52e1d6f330 /packages/taler-wallet-core/src/operations/refresh.ts
parenta0bf83fbb5db026389cc7d203adcff050d5a1b28 (diff)
downloadwallet-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.ts111
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),
),