commit 3dc66c6c9731a07c843adb95802910a546799f38 parent 350ea196d6acad605cefbc3e18088eb773c93999 Author: Florian Dold <dold@taler.net> Date: Sat, 18 Jul 2026 20:21:08 +0200 db: add transactionsMeta, operationRetries and contractTerms accessors Diffstat:
16 files changed, 196 insertions(+), 95 deletions(-)
diff --git a/packages/taler-wallet-core/src/dbtx-indexeddb.ts b/packages/taler-wallet-core/src/dbtx-indexeddb.ts @@ -43,6 +43,9 @@ import { WalletPeerPullDebit, WalletToken, WalletDenomination, + WalletTransactionMeta, + WalletOperationRetry, + WalletContractTerms, DenominationVerificationStatus, OPERATION_STATUS_NONFINAL_FIRST, OPERATION_STATUS_NONFINAL_LAST, @@ -203,6 +206,58 @@ export class IdbWalletTransaction implements WalletDbTransaction { return await tx.purchases.get(proposalId); } + async upsertTransactionMeta(rec: WalletTransactionMeta): Promise<void> { + const tx = this.tx; + await tx.transactionsMeta.put({ + transactionId: rec.transactionId, + timestamp: rec.timestamp, + status: rec.status, + exchanges: rec.exchanges, + currency: rec.currency, + }); + } + + async deleteTransactionMeta(transactionId: string): Promise<void> { + const tx = this.tx; + await tx.transactionsMeta.delete(transactionId); + } + + async getOperationRetry( + taskId: string, + ): Promise<WalletOperationRetry | undefined> { + const tx = this.tx; + return await tx.operationRetries.get(taskId); + } + + async upsertOperationRetry(rec: WalletOperationRetry): Promise<void> { + const tx = this.tx; + await tx.operationRetries.put({ + id: rec.id, + lastError: rec.lastError, + retryInfo: rec.retryInfo, + }); + } + + async deleteOperationRetry(taskId: string): Promise<void> { + const tx = this.tx; + await tx.operationRetries.delete(taskId); + } + + async getContractTerms( + contractTermsHash: string, + ): Promise<WalletContractTerms | undefined> { + const tx = this.tx; + return await tx.contractTerms.get(contractTermsHash); + } + + async upsertContractTerms(rec: WalletContractTerms): Promise<void> { + const tx = this.tx; + await tx.contractTerms.put({ + h: rec.h, + contractTermsRaw: rec.contractTermsRaw, + }); + } + async listTokens(): Promise<WalletToken[]> { const tx = this.tx; const records = await tx.tokens.getAll(); diff --git a/packages/taler-wallet-core/src/dbtx.ts b/packages/taler-wallet-core/src/dbtx.ts @@ -50,6 +50,9 @@ import { WalletPeerPullDebit, WalletToken, WalletDenomination, + WalletTransactionMeta, + WalletOperationRetry, + WalletContractTerms, DenominationVerificationStatus, } from "./db-common.js"; import type { @@ -128,6 +131,48 @@ export interface WalletDbTransaction { getPurchase(proposalId: string): Promise<PurchaseRecord | undefined>; /** + * Create or update the transaction metadata for a transaction. + * + * The transactionsMeta store is a materialized view over the individual + * transaction stores, used to list transactions efficiently. + */ + upsertTransactionMeta(rec: WalletTransactionMeta): Promise<void>; + + /** + * Delete the transaction metadata for a transaction. + * + * Called when the underlying transaction record no longer exists. + */ + deleteTransactionMeta(transactionId: string): Promise<void>; + + /** + * Get the retry state of a task, if the task has been retried before. + */ + getOperationRetry(taskId: string): Promise<WalletOperationRetry | undefined>; + + /** + * Create or update the retry state of a task. + */ + upsertOperationRetry(rec: WalletOperationRetry): Promise<void>; + + /** + * Clear the retry state of a task. + */ + deleteOperationRetry(taskId: string): Promise<void>; + + /** + * Get downloaded contract terms by their hash. + */ + getContractTerms( + contractTermsHash: string, + ): Promise<WalletContractTerms | undefined>; + + /** + * Store downloaded contract terms. + */ + upsertContractTerms(rec: WalletContractTerms): Promise<void>; + + /** * List all stored wallet tokens. */ listTokens(): Promise<WalletToken[]>; diff --git a/packages/taler-wallet-core/src/deposits.ts b/packages/taler-wallet-core/src/deposits.ts @@ -202,7 +202,7 @@ export class DepositTransactionContext implements TransactionContext { if (!dg) { return undefined; } - const ort = await tx.operationRetries.get(this.taskId); + const ort = await tx.wtx.getOperationRetry(this.taskId); let deposited = true; if (dg.statusPerCoin) { @@ -336,10 +336,10 @@ export class DepositTransactionContext implements TransactionContext { async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { const depositRec = await tx.depositGroups.get(this.depositGroupId); if (!depositRec) { - await tx.transactionsMeta.delete(this.transactionId); + await tx.wtx.deleteTransactionMeta(this.transactionId); return; } - await tx.transactionsMeta.put({ + await tx.wtx.upsertTransactionMeta({ transactionId: this.transactionId, status: depositRec.operationStatus, timestamp: depositRec.timestampCreated, @@ -1615,7 +1615,7 @@ async function doCoinSelection( return false; } - const contractTermsRec = tx.contractTerms.get( + const contractTermsRec = tx.wtx.getContractTerms( depositGroup.contractTermsHash, ); if (!contractTermsRec) { @@ -1808,7 +1808,7 @@ async function processDepositGroupPendingDeposit( logger.info("processing deposit group in pending(deposit)"); const depositGroupId = depositGroup.depositGroupId; const contractTermsRec = await wex.runLegacyWalletDbTx(async (tx) => { - return tx.contractTerms.get(depositGroup.contractTermsHash); + return tx.wtx.getContractTerms(depositGroup.contractTermsHash); }); if (!contractTermsRec) { throw Error("contract terms for deposit not found in database"); @@ -2344,7 +2344,7 @@ export async function createDepositGroup( refreshReason: RefreshReason.PayDeposit, }); } - await tx.contractTerms.put({ + await tx.wtx.upsertContractTerms({ contractTermsRaw: contractTerms, h: contractTermsHash, }); diff --git a/packages/taler-wallet-core/src/dev-experiments.ts b/packages/taler-wallet-core/src/dev-experiments.ts @@ -662,7 +662,7 @@ async function addFakeTx( }; const contractTermsHash = ContractTermsUtil.hashContractTerms(ct); await wex.runLegacyWalletDbTx(async (tx) => { - await tx.contractTerms.put({ + await tx.wtx.upsertContractTerms({ contractTermsRaw: ct, h: contractTermsHash, }); @@ -744,7 +744,7 @@ async function addFakeTx( const contractPair = await wex.cryptoApi.createEddsaKeypair({}); const mergePair = await wex.cryptoApi.createEddsaKeypair({}); await wex.runLegacyWalletDbTx(async (tx) => { - await tx.contractTerms.put({ + await tx.wtx.upsertContractTerms({ contractTermsRaw: ct, h: contractTermsHash, }); @@ -807,7 +807,7 @@ async function addFakeTx( const contractPair = await wex.cryptoApi.createEddsaKeypair({}); const mergePair = await wex.cryptoApi.createEddsaKeypair({}); await wex.runLegacyWalletDbTx(async (tx) => { - await tx.contractTerms.put({ + await tx.wtx.upsertContractTerms({ contractTermsRaw: ct, h: contractTermsHash, }); diff --git a/packages/taler-wallet-core/src/exchanges.ts b/packages/taler-wallet-core/src/exchanges.ts @@ -516,7 +516,7 @@ export async function lookupExchangeByUri( tx, exchangeRec.baseUrl, ); - const opRetryRecord = await tx.operationRetries.get( + const opRetryRecord = await tx.wtx.getOperationRetry( TaskIdentifiers.forExchangeUpdate(exchangeRec), ); let reserveRec: ReserveRecord | undefined = undefined; @@ -1331,7 +1331,7 @@ export async function waitReadyExchange( tx, exchangeBaseUrl, ); - const retryInfo = await tx.operationRetries.get(operationId); + const retryInfo = await tx.wtx.getOperationRetry(operationId); let scopeInfo: ScopeInfo | undefined = undefined; if (exchange && exchangeDetails) { scopeInfo = await internalGetExchangeScopeInfo(tx, exchangeDetails); @@ -2540,10 +2540,10 @@ export class DenomLossTransactionContext implements TransactionContext { async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { const denomLossRec = await tx.denomLossEvents.get(this.denomLossEventId); if (!denomLossRec) { - await tx.transactionsMeta.delete(this.transactionId); + await tx.wtx.deleteTransactionMeta(this.transactionId); return; } - await tx.transactionsMeta.put({ + await tx.wtx.upsertTransactionMeta({ transactionId: this.transactionId, status: denomLossRec.status, timestamp: denomLossRec.timestampCreated, @@ -2904,7 +2904,7 @@ export async function listExchanges( tx, exchangeRec.baseUrl, ); - const opRetryRecord = await tx.operationRetries.get(taskId); + const opRetryRecord = await tx.wtx.getOperationRetry(taskId); let reserveRec: ReserveRecord | undefined = undefined; if (exchangeRec.currentMergeReserveRowId != null) { reserveRec = await tx.reserves.get( diff --git a/packages/taler-wallet-core/src/pay-merchant.ts b/packages/taler-wallet-core/src/pay-merchant.ts @@ -193,6 +193,7 @@ import { WalletExecutionContext, walletMerchantClient, } from "./wallet.js"; +import { WalletDbTransaction } from "./dbtx.js"; /** * Logger. @@ -230,16 +231,16 @@ export class PayMerchantTransactionContext implements TransactionContext { async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { const purchaseRec = await tx.purchases.get(this.proposalId); if (!purchaseRec) { - await tx.transactionsMeta.delete(this.transactionId); + await tx.wtx.deleteTransactionMeta(this.transactionId); return; } if (!purchaseRec.download) { // Not ready yet. - await tx.transactionsMeta.delete(this.transactionId); + await tx.wtx.deleteTransactionMeta(this.transactionId); return; } - await tx.transactionsMeta.put({ + await tx.wtx.upsertTransactionMeta({ transactionId: this.transactionId, status: purchaseRec.purchaseStatus, timestamp: purchaseRec.timestamp, @@ -260,7 +261,7 @@ export class PayMerchantTransactionContext implements TransactionContext { const txState = computePayMerchantTransactionState(purchaseRec); const payOpId = TaskIdentifiers.forPay(purchaseRec); - const payRetryRec = await tx.operationRetries.get(payOpId); + const payRetryRec = await tx.wtx.getOperationRetry(payOpId); const unk = "UNKNOWN:0"; if (!purchaseRec.download) { return { @@ -295,7 +296,7 @@ export class PayMerchantTransactionContext implements TransactionContext { const download = await expectProposalDownloadInTx( this.wex, - tx, + tx.wtx, purchaseRec, ); const contractData = download.contractTerms; @@ -590,7 +591,7 @@ async function computePayMerchantExchangesInTx( if (purchaseRecord?.exchanges) { return purchaseRecord.exchanges; } else if (purchaseRecord != null && purchaseRecord.download != null) { - const contractTermsRec = await tx.contractTerms.get( + const contractTermsRec = await tx.wtx.getContractTerms( purchaseRecord.download.contractTermsHash, ); if (contractTermsRec) { @@ -617,7 +618,7 @@ async function computePayMerchantTransactionScopesInTx( : purchaseRec.payInfo.payCoinSelection.coinPubs; return await getScopeForAllCoins(tx, coinList); } else if (purchaseRec.download != null) { - const contractTermsRec = await tx.contractTerms.get( + const contractTermsRec = await tx.wtx.getContractTerms( purchaseRec.download.contractTermsHash, ); if (contractTermsRec) { @@ -658,7 +659,7 @@ export class RefundTransactionContext implements TransactionContext { async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { const refundRec = await tx.refundGroups.get(this.refundGroupId); if (!refundRec) { - await tx.transactionsMeta.delete(this.transactionId); + await tx.wtx.deleteTransactionMeta(this.transactionId); return; } const purchaseRecord = await tx.purchases.get(refundRec.proposalId); @@ -666,7 +667,7 @@ export class RefundTransactionContext implements TransactionContext { if (purchaseRecord) { exchanges = await computePayMerchantExchangesInTx(tx, purchaseRecord); } - await tx.transactionsMeta.put({ + await tx.wtx.upsertTransactionMeta({ transactionId: this.transactionId, status: refundRec.status, timestamp: refundRec.timestampCreated, @@ -795,7 +796,7 @@ async function lookupMaybeContractData( const purchaseTx = await tx.purchases.get(proposalId); if (purchaseTx && purchaseTx.download) { const download = purchaseTx.download; - const contractTermsRecord = await tx.contractTerms.get( + const contractTermsRecord = await tx.wtx.getContractTerms( download.contractTermsHash, ); if (!contractTermsRecord) { @@ -894,12 +895,12 @@ export async function expectProposalDownloadByIdInTx( if (!rec) { throw Error("purchase record not found"); } - return await expectProposalDownloadInTx(wex, tx, rec); + return await expectProposalDownloadInTx(wex, tx.wtx, rec); } export async function expectProposalDownloadInTx( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, p: PurchaseRecord, ): Promise<DownloadedContractData> { if (!p.download) { @@ -907,7 +908,7 @@ export async function expectProposalDownloadInTx( } const download = p.download; - const contractTermsRec = await tx.contractTerms.get( + const contractTermsRec = await tx.getContractTerms( download.contractTermsHash, ); if (!contractTermsRec) { @@ -930,7 +931,7 @@ async function expectProposalDownload( wex: WalletExecutionContext, p: PurchaseRecord, ): Promise<DownloadedContractData> { - return await wex.runLegacyWalletDbTx(async (tx) => { + return await wex.runWalletDbTx(async (tx) => { return expectProposalDownloadInTx(wex, tx, p); }); } @@ -1187,7 +1188,7 @@ async function processDownloadProposal( currency, fulfillmentUrl: contractData.contractTerms.fulfillment_url, }; - await tx.contractTerms.put({ + await tx.wtx.upsertContractTerms({ h: contractTermsHash, contractTermsRaw: proposalResp.contract_terms, }); @@ -1548,7 +1549,7 @@ async function storeFirstPaySuccess( !!dl, `purchase ${purchase.orderId} without ct downloaded`, ); - const contractTermsRecord = await tx.contractTerms.get( + const contractTermsRecord = await tx.wtx.getContractTerms( dl.contractTermsHash, ); checkDbInvariant( @@ -2249,7 +2250,7 @@ async function waitProposalDownloaded( async (tx) => { return { purchase: await tx.purchases.get(ctx.proposalId), - retryInfo: await tx.operationRetries.get(ctx.taskId), + retryInfo: await tx.wtx.getOperationRetry(ctx.taskId), }; }, ); @@ -2382,7 +2383,7 @@ async function waitPaymentResult( async checkState() { const txRes = await ctx.wex.runLegacyWalletDbTx(async (tx) => { const purchase = await tx.purchases.get(ctx.proposalId); - const retryRecord = await tx.operationRetries.get(ctx.taskId); + const retryRecord = await tx.wtx.getOperationRetry(ctx.taskId); return { purchase, retryRecord }; }); @@ -2455,7 +2456,7 @@ export async function getChoicesForPayment( if (!download) { return { proposal }; } - const contractTermsRec = await tx.contractTerms.get( + const contractTermsRec = await tx.wtx.getContractTerms( download.contractTermsHash, ); if (contractTermsRec) { diff --git a/packages/taler-wallet-core/src/pay-peer-pull-credit.ts b/packages/taler-wallet-core/src/pay-peer-pull-credit.ts @@ -130,9 +130,9 @@ export class PeerPullCreditTransactionContext implements TransactionContext { async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { const rec = await tx.wtx.getPeerPullCredit(this.pursePub); if (rec == null) { - await tx.transactionsMeta.delete(this.transactionId); + await tx.wtx.deleteTransactionMeta(this.transactionId); } else { - await tx.transactionsMeta.put({ + await tx.wtx.upsertTransactionMeta({ currency: Amounts.currencyOf(rec.estimatedAmountEffective), exchanges: [rec.exchangeBaseUrl], status: rec.status, @@ -171,7 +171,7 @@ export class PeerPullCreditTransactionContext implements TransactionContext { if (!pullCredit) { return undefined; } - const ct = await tx.contractTerms.get(pullCredit.contractTermsHash); + const ct = await tx.wtx.getContractTerms(pullCredit.contractTermsHash); checkDbInvariant(!!ct, `no contract terms for p2p push ${this.pursePub}`); const peerContractTerms = ct.contractTermsRaw; @@ -182,12 +182,12 @@ export class PeerPullCreditTransactionContext implements TransactionContext { wsr = await tx.withdrawalGroups.get(pullCredit.withdrawalGroupId); if (wsr) { const withdrawalOpId = TaskIdentifiers.forWithdrawal(wsr); - wsrOrt = await tx.operationRetries.get(withdrawalOpId); + wsrOrt = await tx.wtx.getOperationRetry(withdrawalOpId); } } const pullCreditOpId = TaskIdentifiers.forPeerPullPaymentInitiation(pullCredit); - let pullCreditOrt = await tx.operationRetries.get(pullCreditOpId); + let pullCreditOrt = await tx.wtx.getOperationRetry(pullCreditOpId); let kycUrl: string | undefined = undefined; if (pullCredit.kycAccessToken) { @@ -797,7 +797,7 @@ async function processPeerPullCreditCreatePurse( } const contractTermsRecord = await wex.runLegacyWalletDbTx(async (tx) => - tx.contractTerms.get(pullIni.contractTermsHash), + tx.wtx.getContractTerms(pullIni.contractTermsHash), ); if (!contractTermsRecord) { throw Error("contract terms for peer pull payment not found in database"); @@ -1212,7 +1212,7 @@ export async function initiatePeerPullPayment( const ctx = new PeerPullCreditTransactionContext(wex, pursePair.pub); await wex.runLegacyWalletDbTx(async (tx) => { - await tx.contractTerms.put({ + await tx.wtx.upsertContractTerms({ contractTermsRaw: contractTerms, h: hContractTerms, }); diff --git a/packages/taler-wallet-core/src/pay-peer-pull-debit.ts b/packages/taler-wallet-core/src/pay-peer-pull-debit.ts @@ -124,9 +124,9 @@ export class PeerPullDebitTransactionContext implements TransactionContext { async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { const rec = await tx.wtx.getPeerPullDebit(this.peerPullDebitId); if (rec == null) { - await tx.transactionsMeta.delete(this.transactionId); + await tx.wtx.deleteTransactionMeta(this.transactionId); } else { - await tx.transactionsMeta.put({ + await tx.wtx.upsertTransactionMeta({ currency: Amounts.currencyOf(rec.amount), exchanges: [rec.exchangeBaseUrl], status: rec.status, @@ -149,9 +149,9 @@ export class PeerPullDebitTransactionContext implements TransactionContext { if (!pi) { return undefined; } - const ort = await tx.operationRetries.get(this.taskId); + const ort = await tx.wtx.getOperationRetry(this.taskId); const txState = computePeerPullDebitTransactionState(pi); - const ctRec = await tx.contractTerms.get(pi.contractTermsHash); + const ctRec = await tx.wtx.getContractTerms(pi.contractTermsHash); checkDbInvariant(!!ctRec, `no contract terms for ${this.transactionId}`); const contractTerms = ctRec.contractTermsRaw; return { @@ -844,7 +844,7 @@ export async function preparePeerPullDebit( if (!peerPullDebitRecord) { return; } - const contractTerms = await tx.contractTerms.get( + const contractTerms = await tx.wtx.getContractTerms( peerPullDebitRecord.contractTermsHash, ); if (!contractTerms) { @@ -984,7 +984,7 @@ export async function preparePeerPullDebit( const ctx = new PeerPullDebitTransactionContext(wex, peerPullDebitId); const ret = await wex.runLegacyWalletDbTx(async (tx) => { - await tx.contractTerms.put({ + await tx.wtx.upsertContractTerms({ h: contractTermsHash, contractTermsRaw: contractTerms, }); diff --git a/packages/taler-wallet-core/src/pay-peer-push-credit.ts b/packages/taler-wallet-core/src/pay-peer-push-credit.ts @@ -137,9 +137,9 @@ export class PeerPushCreditTransactionContext implements TransactionContext { async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { const rec = await tx.wtx.getPeerPushCredit(this.peerPushCreditId); if (rec == null) { - await tx.transactionsMeta.delete(this.transactionId); + await tx.wtx.deleteTransactionMeta(this.transactionId); } else { - await tx.transactionsMeta.put({ + await tx.wtx.upsertTransactionMeta({ currency: Amounts.currencyOf(rec.estimatedAmountEffective), exchanges: [rec.exchangeBaseUrl], status: rec.status, @@ -169,13 +169,13 @@ export class PeerPushCreditTransactionContext implements TransactionContext { wg = await tx.withdrawalGroups.get(pushInc.withdrawalGroupId); if (wg) { const withdrawalOpId = TaskIdentifiers.forWithdrawal(wg); - wgRetryRecord = await tx.operationRetries.get(withdrawalOpId); + wgRetryRecord = await tx.wtx.getOperationRetry(withdrawalOpId); } } const pushIncOpId = TaskIdentifiers.forPeerPushCredit(pushInc); - const pushRetryRecord = await tx.operationRetries.get(pushIncOpId); + const pushRetryRecord = await tx.wtx.getOperationRetry(pushIncOpId); - const ct = await tx.contractTerms.get(pushInc.contractTermsHash); + const ct = await tx.wtx.getContractTerms(pushInc.contractTermsHash); if (!ct) { throw Error("contract terms for P2P payment not found"); @@ -514,7 +514,7 @@ export async function preparePeerPushCredit( if (!existingPushInc) { return; } - const existingContractTermsRec = await tx.contractTerms.get( + const existingContractTermsRec = await tx.wtx.getContractTerms( existingPushInc.contractTermsHash, ); if (!existingContractTermsRec) { @@ -633,7 +633,7 @@ export async function preparePeerPushCredit( const ctx = new PeerPushCreditTransactionContext(wex, peerPushCreditId); const res = await wex.runLegacyWalletDbTx(async (tx) => { - await tx.contractTerms.put({ + await tx.wtx.upsertContractTerms({ h: contractTermsHash, contractTermsRaw: dec.contractTerms, }); @@ -1103,7 +1103,7 @@ export async function processPeerPushCredit( const rec = await tx.wtx.getPeerPushCredit(peerPushCreditId); let contractTerms = null; if (rec != null) { - const contract = await tx.contractTerms.get(rec.contractTermsHash); + const contract = await tx.wtx.getContractTerms(rec.contractTermsHash); if (contract != null) { contractTerms = contract.contractTermsRaw; } @@ -1254,7 +1254,7 @@ export async function confirmPeerPushCredit( if (!rec) { return; } - const ct = await tx.contractTerms.get(rec.contractTermsHash); + const ct = await tx.wtx.getContractTerms(rec.contractTermsHash); if (!ct) { return undefined; } diff --git a/packages/taler-wallet-core/src/pay-peer-push-debit.ts b/packages/taler-wallet-core/src/pay-peer-push-debit.ts @@ -131,9 +131,9 @@ export class PeerPushDebitTransactionContext implements TransactionContext { const rec = await tx.wtx.getPeerPushDebit(this.pursePub); logger.info(`updating peer-push-debit meta for ${j2s(rec)}`); if (rec == null) { - await tx.transactionsMeta.delete(this.transactionId); + await tx.wtx.deleteTransactionMeta(this.transactionId); } else { - await tx.transactionsMeta.put({ + await tx.wtx.upsertTransactionMeta({ currency: Amounts.currencyOf(rec.amount), exchanges: [rec.exchangeBaseUrl], status: rec.status, @@ -156,9 +156,9 @@ export class PeerPushDebitTransactionContext implements TransactionContext { if (pushDebitRec == null) { return undefined; } - const retryRec = await tx.operationRetries.get(this.taskId); + const retryRec = await tx.wtx.getOperationRetry(this.taskId); - const ctRec = await tx.contractTerms.get(pushDebitRec.contractTermsHash); + const ctRec = await tx.wtx.getContractTerms(pushDebitRec.contractTermsHash); checkDbInvariant( !!ctRec, `no contract terms for p2p push ${this.pursePub}`, @@ -615,7 +615,7 @@ async function processPeerPushDebitCreateReserve( logger.trace(`processing ${ctx.transactionId} pending(create-reserve)`); const contractTermsRecord = await wex.runLegacyWalletDbTx(async (tx) => { - return tx.contractTerms.get(contractTermsHash); + return tx.wtx.getContractTerms(contractTermsHash); }); if (!contractTermsRecord) { @@ -1189,7 +1189,7 @@ export async function initiatePeerPushDebit( refreshReason: RefreshReason.PayPeerPush, }); } - await tx.contractTerms.put({ + await tx.wtx.upsertContractTerms({ h: hContractTerms, contractTermsRaw: contractTerms, }); diff --git a/packages/taler-wallet-core/src/recoup.ts b/packages/taler-wallet-core/src/recoup.ts @@ -426,15 +426,15 @@ export class RecoupTransactionContext implements TransactionContext { async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { const recoupRec = await tx.recoupGroups.get(this.recoupGroupId); if (!recoupRec) { - await tx.transactionsMeta.delete(this.transactionId); + await tx.wtx.deleteTransactionMeta(this.transactionId); return; } const exch = await tx.exchanges.get(recoupRec.exchangeBaseUrl); if (!exch || !exch.detailsPointer) { - await tx.transactionsMeta.delete(this.transactionId); + await tx.wtx.deleteTransactionMeta(this.transactionId); return; } - await tx.transactionsMeta.put({ + await tx.wtx.upsertTransactionMeta({ transactionId: this.transactionId, status: recoupRec.operationStatus, timestamp: recoupRec.timestampStarted, diff --git a/packages/taler-wallet-core/src/refresh.ts b/packages/taler-wallet-core/src/refresh.ts @@ -153,10 +153,10 @@ export class RefreshTransactionContext implements TransactionContext { async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { const rgRec = await tx.refreshGroups.get(this.refreshGroupId); if (!rgRec) { - await tx.transactionsMeta.delete(this.transactionId); + await tx.wtx.deleteTransactionMeta(this.transactionId); return; } - await tx.transactionsMeta.put({ + await tx.wtx.upsertTransactionMeta({ transactionId: this.transactionId, status: rgRec.operationStatus, timestamp: rgRec.timestampCreated, @@ -178,7 +178,7 @@ export class RefreshTransactionContext implements TransactionContext { if (!refreshGroupRecord) { return undefined; } - const ort = await tx.operationRetries.get(this.taskId); + const ort = await tx.wtx.getOperationRetry(this.taskId); const inputAmount = Amounts.sumOrZero( refreshGroupRecord.currency, refreshGroupRecord.inputPerCoin, diff --git a/packages/taler-wallet-core/src/shepherd.ts b/packages/taler-wallet-core/src/shepherd.ts @@ -424,9 +424,9 @@ export class TaskSchedulerImpl implements TaskScheduler { } async resetTask(taskId: TaskIdStr): Promise<void> { - await this.ws.runStandaloneLegacyWalletDbTx(async (tx) => { + await this.ws.runStandaloneLegacyWalletDbTx(async (tx, wtx) => { logger.trace(`storing task [reset] for ${taskId}`); - await tx.operationRetries.delete(taskId); + await wtx.deleteOperationRetry(taskId); const notif = await taskToRetryNotification( this.ws, tx, @@ -621,8 +621,8 @@ async function storePendingTaskError( e: TalerErrorDetail, ): Promise<WalletOperationRetry> { logger.trace(`storing task [pending] with ERROR for ${pendingTaskId}`); - const res = await ws.runStandaloneLegacyWalletDbTx(async (tx) => { - let retryRecord = await tx.operationRetries.get(pendingTaskId); + const res = await ws.runStandaloneLegacyWalletDbTx(async (tx, wtx) => { + let retryRecord = await wtx.getOperationRetry(pendingTaskId); if (!retryRecord) { retryRecord = { id: pendingTaskId, @@ -633,7 +633,7 @@ async function storePendingTaskError( retryRecord.lastError = e; retryRecord.retryInfo = DbRetryInfo.increment(retryRecord.retryInfo); } - await tx.operationRetries.put(retryRecord); + await wtx.upsertOperationRetry(retryRecord); return { notification: await taskToRetryNotification(ws, tx, pendingTaskId, e), retryRecord, @@ -653,8 +653,8 @@ async function storeTaskProgress( pendingTaskId: string, ): Promise<void> { logger.trace(`storing task [progress] for ${pendingTaskId}`); - await ws.runStandaloneLegacyWalletDbTx(async (tx) => { - await tx.operationRetries.delete(pendingTaskId); + await ws.runStandaloneLegacyWalletDbTx(async (tx, wtx) => { + await wtx.deleteOperationRetry(pendingTaskId); }); } @@ -664,8 +664,8 @@ async function storePendingTaskPending( schedTime?: AbsoluteTime, ): Promise<WalletOperationRetry> { logger.trace(`storing task [pending] for ${pendingTaskId}`); - const res = await ws.runStandaloneLegacyWalletDbTx(async (tx) => { - let retryRecord = await tx.operationRetries.get(pendingTaskId); + const res = await ws.runStandaloneLegacyWalletDbTx(async (tx, wtx) => { + let retryRecord = await wtx.getOperationRetry(pendingTaskId); let hadError = false; if (!retryRecord) { retryRecord = { @@ -684,7 +684,7 @@ async function storePendingTaskPending( AbsoluteTime.toPreciseTimestamp(schedTime), ); } - await tx.operationRetries.put(retryRecord); + await wtx.upsertOperationRetry(retryRecord); if (hadError) { const notif = await taskToRetryNotification( ws, @@ -708,8 +708,8 @@ async function storePendingTaskFinished( pendingTaskId: string, ): Promise<void> { logger.trace(`storing task [finished] for ${pendingTaskId}`); - await ws.runStandaloneLegacyWalletDbTx(async (tx) => { - await tx.operationRetries.delete(pendingTaskId); + await ws.runStandaloneLegacyWalletDbTx(async (tx, wtx) => { + await wtx.deleteOperationRetry(pendingTaskId); }); } diff --git a/packages/taler-wallet-core/src/tokenFamilies.ts b/packages/taler-wallet-core/src/tokenFamilies.ts @@ -133,10 +133,10 @@ async function getMerchantInfos( tokens: WalletToken[], ): Promise<MerchantInfos> { const merchantInfos: MerchantInfos = {}; - await wex.runLegacyWalletDbTx(async (tx) => { + await wex.runWalletDbTx(async (tx) => { for (const t of tokens) { if (t.purchaseId in merchantInfos) continue; - const purchase = await tx.wtx.getPurchase(t.purchaseId); + const purchase = await tx.getPurchase(t.purchaseId); if (!purchase) continue; const download = await expectProposalDownloadInTx(wex, tx, purchase); const contractData = download.contractTerms; @@ -151,8 +151,8 @@ export async function listDiscounts( tokenIssuePubHash?: string, merchantBaseUrl?: string, ): Promise<ListDiscountsResponse> { - const tokens: WalletToken[] = await wex.runLegacyWalletDbTx(async (tx) => { - return (await tx.wtx.listTokens()) + const tokens: WalletToken[] = await wex.runWalletDbTx(async (tx) => { + return (await tx.listTokens()) .filter((t) => isTokenValid(t)) .filter((t) => t.kind === MerchantContractTokenKind.Discount) .filter( @@ -175,8 +175,8 @@ export async function listSubscriptions( tokenIssuePubHash?: string, merchantBaseUrl?: string, ): Promise<ListSubscriptionsResponse> { - const tokens: WalletToken[] = await wex.runLegacyWalletDbTx(async (tx) => { - return (await tx.wtx.listTokens()) + const tokens: WalletToken[] = await wex.runWalletDbTx(async (tx) => { + return (await tx.listTokens()) .filter((t) => isTokenValid(t)) .filter((t) => t.kind === MerchantContractTokenKind.Subscription) .filter( @@ -201,8 +201,8 @@ export async function deleteDiscount( wex: WalletExecutionContext, tokenFamilyHash: string, ): Promise<EmptyObject> { - await wex.runLegacyWalletDbTx(async (tx) => { - const tokens = (await tx.wtx.listTokens()) + await wex.runWalletDbTx(async (tx) => { + const tokens = (await tx.listTokens()) .filter((t) => t.kind === MerchantContractTokenKind.Discount) .filter((t) => t.tokenFamilyHash === tokenFamilyHash); @@ -225,7 +225,7 @@ export async function deleteDiscount( `deleting token in ${token.tokenIssuePubHash} token family`, ); } - await tx.wtx.deleteToken(token.tokenUsePub); + await tx.deleteToken(token.tokenUsePub); } }); @@ -236,8 +236,8 @@ export async function deleteSubscription( wex: WalletExecutionContext, tokenFamilyHash: string, ): Promise<EmptyObject> { - await wex.runLegacyWalletDbTx(async (tx) => { - const tokens = (await tx.wtx.listTokens()) + await wex.runWalletDbTx(async (tx) => { + const tokens = (await tx.listTokens()) .filter((t) => t.kind === MerchantContractTokenKind.Subscription) .filter((t) => t.tokenFamilyHash === tokenFamilyHash) .sort((a, b) => a.validBefore - b.validBefore); @@ -261,7 +261,7 @@ export async function deleteSubscription( `deleting token in ${token.tokenIssuePubHash} token family`, ); } - await tx.wtx.deleteToken(token.tokenUsePub); + await tx.deleteToken(token.tokenUsePub); } }); diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts @@ -1441,7 +1441,7 @@ async function handleGetActiveTasks( const tasksInfo = await Promise.all( allTasksId.map(async (id) => { return await wex.runLegacyWalletDbTx(async (tx) => { - return tx.operationRetries.get(id); + return tx.wtx.getOperationRetry(id); }); }), ); diff --git a/packages/taler-wallet-core/src/withdraw.ts b/packages/taler-wallet-core/src/withdraw.ts @@ -408,7 +408,7 @@ export class WithdrawTransactionContext implements TransactionContext { } } - const ort = await tx.operationRetries.get(this.taskId); + const ort = await tx.wtx.getOperationRetry(this.taskId); switch (withdrawalGroupRecord.wgInfo.withdrawalType) { case WithdrawalRecordType.BankIntegrated: @@ -445,7 +445,7 @@ export class WithdrawTransactionContext implements TransactionContext { const ctx = this; const wgRecord = await tx.withdrawalGroups.get(ctx.withdrawalGroupId); if (!wgRecord) { - await tx.transactionsMeta.delete(ctx.transactionId); + await tx.wtx.deleteTransactionMeta(ctx.transactionId); return; } @@ -474,7 +474,7 @@ export class WithdrawTransactionContext implements TransactionContext { if (!currency) { return; } - await tx.transactionsMeta.put({ + await tx.wtx.upsertTransactionMeta({ transactionId: ctx.transactionId, status: wgRecord.status, timestamp: wgRecord.timestampStart,