taler-typescript-core

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

commit 375c75212cc6e04f3c9c024b7e08c09b4bdb505d
parent 9060502019fccb872af1d62347b84cc2cbc02e81
Author: Florian Dold <dold@taler.net>
Date:   Sun, 19 Jul 2026 22:20:28 +0200

wallet: remove runLegacyWalletDbTx and its raw-handle siblings

The remaining callers wanted the fixups store.  They now reach it through
wex.db.

Diffstat:
Mpackages/taler-wallet-core/src/requests.ts | 46+++++++++++++++++++++++++++++++---------------
Mpackages/taler-wallet-core/src/wallet.ts | 56+++-----------------------------------------------------
2 files changed, 34 insertions(+), 68 deletions(-)

diff --git a/packages/taler-wallet-core/src/requests.ts b/packages/taler-wallet-core/src/requests.ts @@ -681,13 +681,13 @@ async function recoverStoredBackup( }); } else { await importDb(wex.db.idbHandle(), bd); - await wex.runLegacyWalletDbTx(async (tx) => { - await rematerializeTransactions(wex, tx.wtx); - // Clear fixups. Okay since they are idempotent. - const fixups = await tx.fixups.getAll(); - for (const f of fixups) { - await tx.fixups.delete(f.fixupName); - } + // Same order as handleImportDb, and for the same reason: clearing the + // log only schedules the repairs, so they have to be re-run here, and + // the transaction view has to be built from repaired records. + await clearFixupLog(wex); + await applyFixups(wex.db); + await wex.runWalletDbTx(async (tx) => { + await rematerializeTransactions(wex, tx); }); } logger.info(`import done`); @@ -1616,6 +1616,23 @@ async function handleExportDbToFile( }; } +/** + * Mark every fixup as not applied. + * + * Goes through the IndexedDB handle rather than the DAL on purpose: the + * fixup log is part of that backend. The native sqlite schema has no + * equivalent -- it starts clean and evolves through schemaMigrations -- so + * there is nothing here for the DAL to abstract over. + */ +async function clearFixupLog(wex: WalletExecutionContext): Promise<void> { + await wex.db.runAllStoresReadWriteTx({}, async (tx) => { + const fixups = await tx.fixups.getAll(); + for (const f of fixups) { + await tx.fixups.delete(f.fixupName); + } + }); +} + async function handleImportDb( wex: WalletExecutionContext, req: ImportDbRequest, @@ -1626,12 +1643,7 @@ async function handleImportDb( // Clear the fixup log: the records that just arrived may predate any of // the fixups, whatever this database had applied before the import. They // are idempotent, so re-running them is safe. - await wex.runLegacyWalletDbTx(async (tx) => { - const fixups = await tx.fixups.getAll(); - for (const f of fixups) { - await tx.fixups.delete(f.fixupName); - } - }); + await clearFixupLog(wex); // Then actually re-run them. Clearing the log alone only schedules the // repairs for the next time the database is opened, which for a running @@ -1755,9 +1767,13 @@ export async function handleTestingRunFixup( if (fixup.name != req.id) { continue; } - await wex.runLegacyWalletDbTx(async (tx) => { + // fixup.fn takes the raw IndexedDB transaction: fixups repair that + // backend's records and are not expressible through the DAL. + await wex.db.runAllStoresReadWriteTx({}, async (tx) => { await fixup.fn(tx); - await rematerializeTransactions(wex, tx.wtx); + }); + await wex.runWalletDbTx(async (tx) => { + await rematerializeTransactions(wex, tx); }); return {}; } diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts @@ -133,13 +133,6 @@ const logger = new Logger("wallet.ts"); export interface WalletExecutionContext { /** * Start a database transaction. - * Uses the legacy transaction that only works with IndexedDB. - */ - runLegacyWalletDbTx<T>( - f: (tx: LegacyWalletTxHandle) => Promise<T>, - ): Promise<T>; - /** - * Start a database transaction. * Uses the database abstraction layer. */ runWalletDbTx<T>(f: (tx: WalletDbTransaction) => Promise<T>): Promise<T>; @@ -227,16 +220,13 @@ export async function migrateMaterializedTransactions( export async function getDenomInfo( wex: WalletExecutionContext, - tx: WalletDbTransaction | LegacyWalletTxHandle, + tx: WalletDbTransaction, exchangeBaseUrl: string, denomPubHash: string, ): Promise<DenominationInfo | undefined> { const key = `${exchangeBaseUrl}:${denomPubHash}`; return wex.ws.denomInfoCache.getOrPut(key, async () => { - const d = - "getDenomination" in tx - ? await tx.getDenomination(exchangeBaseUrl, denomPubHash) - : await tx.wtx.getDenomination(exchangeBaseUrl, denomPubHash); + const d = await tx.getDenomination(exchangeBaseUrl, denomPubHash); if (d != null) { return WalletDenomination.toDenomInfo(d); } else { @@ -317,9 +307,6 @@ export function getObservedWalletExecutionContext( async runWalletDbTx(f) { return await runWalletDbTx(wex, f); }, - async runLegacyWalletDbTx(f) { - return await runLegacyWalletDbTx(wex, f); - }, ws, cancellationToken, cts, @@ -404,10 +391,6 @@ async function handleTxRetries<T>( throw Error("not reached"); } -export type LegacyWalletTxHandle = WalletIndexedDbTransaction & { - wtx: WalletDbTransaction; -}; - async function runWalletDbTx<T>( wex: WalletExecutionContext, f: (tx: WalletDbTransaction) => Promise<T>, @@ -464,19 +447,6 @@ async function runWalletDbTx<T>( }); } -async function runLegacyWalletDbTx<T>( - wex: WalletExecutionContext, - f: (tx: LegacyWalletTxHandle) => Promise<T>, -): Promise<T> { - return await handleTxRetries(wex, async () => { - return await wex.db.runAllStoresReadWriteTx({}, async (tx) => { - const wtx = new IdbWalletTransaction(tx); - (tx as any).wtx = wtx; - return await f(tx as LegacyWalletTxHandle); - }); - }); -} - export function getNormalWalletExecutionContext( ws: InternalWalletState, cancellationToken: CancellationToken, @@ -488,9 +458,6 @@ export function getNormalWalletExecutionContext( async runWalletDbTx(f) { return await runWalletDbTx(wex, f); }, - async runLegacyWalletDbTx(f) { - return await runLegacyWalletDbTx(wex, f); - }, ws, cancellationToken, cts, @@ -822,7 +789,7 @@ export class InternalWalletState { * Run f in a transaction outside any WalletExecutionContext. * * Dispatches to the native backend when one is configured, which - * runStandaloneLegacyWalletDbTx cannot do: that one hands out the raw + * the older legacy helper could not do: that one handed out the raw * IndexedDB handle. Background work (the task shepherd) must go through * here, or it reads a different database than the one the wallet writes. */ @@ -848,23 +815,6 @@ export class InternalWalletState { ); } - async runStandaloneLegacyWalletDbTx<T>( - f: (tx: WalletIndexedDbTransaction, wtx: WalletDbTransaction) => Promise<T>, - ): Promise<T> { - if (!this._dbAccessHandle) { - this._dbAccessHandle = this.createDbAccessHandle( - CancellationToken.CONTINUE, - ); - } - return await this._dbAccessHandle.runAllStoresReadWriteTx( - {}, - async (mytx) => { - const tx = new IdbWalletTransaction(mytx); - return await f(mytx, tx); - }, - ); - } - /** * When set to false, all tasks that require network will be stopped and * retried until connection is restored.