taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit 71134277d046dad960d5d3223a45045bd0be49ac
parent df1e6cc2ad3203c7464ddc170ce3d7ff37b2821f
Author: Florian Dold <dold@taler.net>
Date:   Sun, 19 Jul 2026 01:37:03 +0200

db: move transaction re-materialization behind the DAL

Diffstat:
Mpackages/taler-wallet-core/src/dbtx-indexeddb.ts | 12++++++++++++
Mpackages/taler-wallet-core/src/dbtx.ts | 6++++++
Mpackages/taler-wallet-core/src/dev-experiments.ts | 2+-
Mpackages/taler-wallet-core/src/exchanges.ts | 2+-
Mpackages/taler-wallet-core/src/transactions.ts | 65+++++++++++++++++++++++++++++++++--------------------------------
Mpackages/taler-wallet-core/src/wallet.ts | 10+++++-----
6 files changed, 58 insertions(+), 39 deletions(-)

diff --git a/packages/taler-wallet-core/src/dbtx-indexeddb.ts b/packages/taler-wallet-core/src/dbtx-indexeddb.ts @@ -464,6 +464,18 @@ export class IdbWalletTransaction implements WalletDbTransaction { return await tx.depositGroups.iter().toArray(); } + async listAllRefundGroups(): Promise<WalletRefundGroup[]> { + return await this.tx.refundGroups.iter().toArray(); + } + + async listAllWithdrawalGroups(): Promise<WalletWithdrawalGroup[]> { + return await this.tx.withdrawalGroups.iter().toArray(); + } + + async listAllPurchases(): Promise<WalletPurchase[]> { + return await this.tx.purchases.iter().toArray(); + } + async listAllPeerPullCredits(): Promise<WalletPeerPullCredit[]> { const tx = this.tx; return await tx.peerPullCredit.iter().toArray(); diff --git a/packages/taler-wallet-core/src/dbtx.ts b/packages/taler-wallet-core/src/dbtx.ts @@ -312,6 +312,12 @@ export interface WalletDbTransaction { */ listAllDepositGroups(): Promise<WalletDepositGroup[]>; + listAllRefundGroups(): Promise<WalletRefundGroup[]>; + + listAllWithdrawalGroups(): Promise<WalletWithdrawalGroup[]>; + + listAllPurchases(): Promise<WalletPurchase[]>; + listAllPeerPullCredits(): Promise<WalletPeerPullCredit[]>; listAllPeerPullDebits(): Promise<WalletPeerPullDebit[]>; diff --git a/packages/taler-wallet-core/src/dev-experiments.ts b/packages/taler-wallet-core/src/dev-experiments.ts @@ -364,7 +364,7 @@ export async function applyDevExperiment( await tx.wtx.upsertPurchase(rec); } }); - await rematerializeTransactions(wex, tx); + await rematerializeTransactions(wex, tx.wtx); }); return; } diff --git a/packages/taler-wallet-core/src/exchanges.ts b/packages/taler-wallet-core/src/exchanges.ts @@ -3336,7 +3336,7 @@ async function purgeExchange( } // FIXME: Is this even necessary? Each deletion should already do it. - await rematerializeTransactions(wex, tx); + await rematerializeTransactions(wex, tx.wtx); } export async function deleteExchange( diff --git a/packages/taler-wallet-core/src/transactions.ts b/packages/taler-wallet-core/src/transactions.ts @@ -67,6 +67,7 @@ import { PeerPushDebitTransactionContext } from "./pay-peer-push-debit.js"; import { RefreshTransactionContext } from "./refresh.js"; import type { LegacyWalletTxHandle, WalletExecutionContext } from "./wallet.js"; import { WithdrawTransactionContext } from "./withdraw.js"; +import { WalletDbTransaction } from "./dbtx.js"; const logger = new Logger("taler-wallet-core:transactions.ts"); @@ -538,61 +539,61 @@ export async function getTransactions( */ export async function rematerializeTransactions( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, ): Promise<void> { logger.trace("re-materializing transactions"); - await tx.wtx.deleteAllTransactionMeta(); + await tx.deleteAllTransactionMeta(); - await tx.peerPushDebit.iter().forEachAsync(async (x) => { + for (const x of await tx.listAllPeerPushDebits()) { const ctx = new PeerPushDebitTransactionContext(wex, x.pursePub); - await ctx.updateTransactionMeta(tx.wtx); - }); + await ctx.updateTransactionMeta(tx); + } - await tx.peerPushCredit.iter().forEachAsync(async (x) => { + for (const x of await tx.listAllPeerPushCredits()) { const ctx = new PeerPushCreditTransactionContext(wex, x.peerPushCreditId); - await ctx.updateTransactionMeta(tx.wtx); - }); + await ctx.updateTransactionMeta(tx); + } - await tx.peerPullCredit.iter().forEachAsync(async (x) => { + for (const x of await tx.listAllPeerPullCredits()) { const ctx = new PeerPullCreditTransactionContext(wex, x.pursePub); - await ctx.updateTransactionMeta(tx.wtx); - }); + await ctx.updateTransactionMeta(tx); + } - await tx.peerPullDebit.iter().forEachAsync(async (x) => { + for (const x of await tx.listAllPeerPullDebits()) { const ctx = new PeerPullDebitTransactionContext(wex, x.peerPullDebitId); - await ctx.updateTransactionMeta(tx.wtx); - }); + await ctx.updateTransactionMeta(tx); + } - await tx.refundGroups.iter().forEachAsync(async (x) => { + for (const x of await tx.listAllRefundGroups()) { const ctx = new RefundTransactionContext(wex, x.refundGroupId); - await ctx.updateTransactionMeta(tx.wtx); - }); + await ctx.updateTransactionMeta(tx); + } - await tx.refreshGroups.iter().forEachAsync(async (x) => { + for (const x of await tx.listAllRefreshGroups()) { const ctx = new RefreshTransactionContext(wex, x.refreshGroupId); - await ctx.updateTransactionMeta(tx.wtx); - }); + await ctx.updateTransactionMeta(tx); + } - await tx.withdrawalGroups.iter().forEachAsync(async (x) => { + for (const x of await tx.listAllWithdrawalGroups()) { const ctx = new WithdrawTransactionContext(wex, x.withdrawalGroupId); - await ctx.updateTransactionMeta(tx.wtx); - }); + await ctx.updateTransactionMeta(tx); + } - await tx.denomLossEvents.iter().forEachAsync(async (x) => { + for (const x of await tx.listAllDenomLossEvents()) { const ctx = new DenomLossTransactionContext(wex, x.denomLossEventId); - await ctx.updateTransactionMeta(tx.wtx); - }); + await ctx.updateTransactionMeta(tx); + } - await tx.depositGroups.iter().forEachAsync(async (x) => { + for (const x of await tx.listAllDepositGroups()) { const ctx = new DepositTransactionContext(wex, x.depositGroupId); - await ctx.updateTransactionMeta(tx.wtx); - }); + await ctx.updateTransactionMeta(tx); + } - await tx.purchases.iter().forEachAsync(async (x) => { + for (const x of await tx.listAllPurchases()) { const ctx = new PayMerchantTransactionContext(wex, x.proposalId); - await ctx.updateTransactionMeta(tx.wtx); - }); + await ctx.updateTransactionMeta(tx); + } } export type ParsedTransactionIdentifier = diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts @@ -595,7 +595,7 @@ async function migrateMaterializedTransactions( } } - await rematerializeTransactions(wex, tx); + await rematerializeTransactions(wex, tx.wtx); await tx.config.put({ key: ConfigRecordKey.MaterializedTransactionsVersion, @@ -913,7 +913,7 @@ async function recoverStoredBackup( logger.info(`backup found, now importing`); await importDb(wex.db.idbHandle(), bd); await wex.runLegacyWalletDbTx(async (tx) => { - await rematerializeTransactions(wex, tx); + await rematerializeTransactions(wex, tx.wtx); // Clear fixups. Okay since they are idempotent. const fixups = await tx.fixups.getAll(); for (const f of fixups) { @@ -1842,7 +1842,7 @@ async function handleImportDb( // FIXME: This should atomically re-materialize transactions! await importDb(wex.db.idbHandle(), req.dump); await wex.runLegacyWalletDbTx(async (tx) => { - await rematerializeTransactions(wex, tx); + await rematerializeTransactions(wex, tx.wtx); // Clear fixups. Okay since they are idempotent. const fixups = await tx.fixups.getAll(); for (const f of fixups) { @@ -1960,7 +1960,7 @@ export async function handleTestingRunFixup( } await wex.runLegacyWalletDbTx(async (tx) => { await fixup.fn(tx); - await rematerializeTransactions(wex, tx); + await rematerializeTransactions(wex, tx.wtx); }); return {}; } @@ -3565,7 +3565,7 @@ export class InternalWalletState { oc, ); await wex.runLegacyWalletDbTx(async (tx) => { - await rematerializeTransactions(wex, tx); + await rematerializeTransactions(wex, tx.wtx); }); } } catch (e) {