taler-typescript-core

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

commit 3ae43d6cd81ce62d112c9352f91c35afe3fd09ac
parent 5229ac4a43c0c6e4f75249aef730edc7065de2e9
Author: Florian Dold <dold@taler.net>
Date:   Sun, 19 Jul 2026 00:35:35 +0200

db: narrow TransactionContext methods to WalletDbTransaction

Diffstat:
Mpackages/taler-wallet-core/src/coinSelection.ts | 17+++++++++--------
Mpackages/taler-wallet-core/src/common.ts | 2+-
Mpackages/taler-wallet-core/src/deposits.ts | 63++++++++++++++++++++++++++++++++-------------------------------
Mpackages/taler-wallet-core/src/dev-experiments.ts | 12++++++------
Mpackages/taler-wallet-core/src/exchanges.ts | 95++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Mpackages/taler-wallet-core/src/instructedAmountConversion.ts | 5++++-
Mpackages/taler-wallet-core/src/pay-merchant.ts | 156+++++++++++++++++++++++++++++++++++++++----------------------------------------
Mpackages/taler-wallet-core/src/pay-peer-pull-credit.ts | 70+++++++++++++++++++++++++++++++++++-----------------------------------
Mpackages/taler-wallet-core/src/pay-peer-pull-debit.ts | 57+++++++++++++++++++++++++++++----------------------------
Mpackages/taler-wallet-core/src/pay-peer-push-credit.ts | 75+++++++++++++++++++++++++++++++++++++--------------------------------------
Mpackages/taler-wallet-core/src/pay-peer-push-debit.ts | 63++++++++++++++++++++++++++++++++-------------------------------
Mpackages/taler-wallet-core/src/recoup.ts | 29+++++++++++++++--------------
Mpackages/taler-wallet-core/src/refresh.ts | 61++++++++++++++++++++++++++++++-------------------------------
Mpackages/taler-wallet-core/src/transactions.ts | 26+++++++++++++-------------
Mpackages/taler-wallet-core/src/wallet.ts | 4++--
Mpackages/taler-wallet-core/src/withdraw.ts | 77+++++++++++++++++++++++++++++++++++++++--------------------------------------
16 files changed, 412 insertions(+), 400 deletions(-)

diff --git a/packages/taler-wallet-core/src/coinSelection.ts b/packages/taler-wallet-core/src/coinSelection.ts @@ -519,7 +519,7 @@ export async function reportInsufficientBalanceDetails( continue; } let missingGlobalFees = false; - const exchWire = await getExchangeDetailsInTx(tx, exch.baseUrl); + const exchWire = await getExchangeDetailsInTx(tx.wtx, exch.baseUrl); if (!exchWire) { // No wire details about the exchange known, skip! continue; @@ -850,9 +850,7 @@ export function findMatchingWire( for (const acc of exchangeWireDetails.wireInfo.accounts) { const ppRes = Paytos.fromString(acc.payto_uri); if (Result.isError(ppRes)) { - throw Error( - `failed to parse payto ${acc.payto_uri}`, - ); + throw Error(`failed to parse payto ${acc.payto_uri}`); } const pp = ppRes.value; checkLogicInvariant(!!pp); @@ -970,7 +968,10 @@ async function selectPayCandidates( Record<string, AccountRestriction[]> > = {}; for (const exchange of exchanges) { - const exchangeDetails = await getExchangeDetailsInTx(tx, exchange.baseUrl); + const exchangeDetails = await getExchangeDetailsInTx( + tx.wtx, + exchange.baseUrl, + ); // Exchange has same currency if (exchangeDetails?.currency !== req.currency) { logger.shouldLogTrace() && @@ -1287,7 +1288,7 @@ export async function selectPeerCoinsInTx( if (exch.detailsPointer?.currency !== currency) { continue; } - const exchWire = await getExchangeDetailsInTx(tx, exch.baseUrl); + const exchWire = await getExchangeDetailsInTx(tx.wtx, exch.baseUrl); if (!exchWire) { continue; } @@ -1412,7 +1413,7 @@ export async function getExchangesForDepositInTx( const exchangeInfos: Exchange[] = []; const allExchanges = await tx.wtx.getExchanges(); for (const e of allExchanges) { - const details = await getExchangeDetailsInTx(tx, e.baseUrl); + const details = await getExchangeDetailsInTx(tx.wtx, e.baseUrl); if (!details) { logger.trace(`skipping ${e.baseUrl}, no details`); continue; @@ -1546,7 +1547,7 @@ export async function getMaxPeerPushDebitAmount( if (exch.detailsPointer?.currency !== currency) { continue; } - const exchWire = await getExchangeDetailsInTx(tx, exch.baseUrl); + const exchWire = await getExchangeDetailsInTx(tx.wtx, exch.baseUrl); if (!exchWire) { continue; } diff --git a/packages/taler-wallet-core/src/common.ts b/packages/taler-wallet-core/src/common.ts @@ -894,7 +894,7 @@ export interface TransactionContext { */ userDeleteTransaction(): Promise<void>; lookupFullTransaction( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, args?: LookupFullTransactionOpts, ): Promise<Transaction | undefined>; } diff --git a/packages/taler-wallet-core/src/deposits.ts b/packages/taler-wallet-core/src/deposits.ts @@ -164,6 +164,7 @@ import { getDenomInfo, } from "./wallet.js"; import { augmentPaytoUrisForKycTransfer } from "./withdraw.js"; +import { WalletDbTransaction } from "./dbtx.js"; /** * Logger. @@ -195,13 +196,13 @@ export class DepositTransactionContext implements TransactionContext { * transaction item (e.g. if it was deleted). */ async lookupFullTransaction( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, ): Promise<Transaction | undefined> { - const dg = await tx.wtx.getDepositGroup(this.depositGroupId); + const dg = await tx.getDepositGroup(this.depositGroupId); if (!dg) { return undefined; } - const ort = await tx.wtx.getOperationRetry(this.taskId); + const ort = await tx.getOperationRetry(this.taskId); let deposited = true; if (dg.statusPerCoin) { @@ -332,13 +333,13 @@ export class DepositTransactionContext implements TransactionContext { /** * Update the metadata of the transaction in the database. */ - async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { - const depositRec = await tx.wtx.getDepositGroup(this.depositGroupId); + async updateTransactionMeta(tx: WalletDbTransaction): Promise<void> { + const depositRec = await tx.getDepositGroup(this.depositGroupId); if (!depositRec) { - await tx.wtx.deleteTransactionMeta(this.transactionId); + await tx.deleteTransactionMeta(this.transactionId); return; } - await tx.wtx.upsertTransactionMeta({ + await tx.upsertTransactionMeta({ transactionId: this.transactionId, status: depositRec.operationStatus, timestamp: depositRec.timestampCreated, @@ -348,18 +349,18 @@ export class DepositTransactionContext implements TransactionContext { } async getRecordHandle( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, ): Promise< [WalletDepositGroup | undefined, RecordHandle<WalletDepositGroup>] > { return getGenericRecordHandle<WalletDepositGroup>( this, - tx.wtx, - async () => tx.wtx.getDepositGroup(this.depositGroupId), + tx, + async () => tx.getDepositGroup(this.depositGroupId), async (r) => { - await tx.wtx.upsertDepositGroup(r); + await tx.upsertDepositGroup(r); }, - async () => tx.wtx.deleteDepositGroup(this.depositGroupId), + async () => tx.deleteDepositGroup(this.depositGroupId), (r) => computeDepositTransactionStatus(r), (r) => r.operationStatus, () => this.updateTransactionMeta(tx), @@ -368,11 +369,11 @@ export class DepositTransactionContext implements TransactionContext { async userDeleteTransaction(): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - await this.deleteTransactionInTx(tx); + await this.deleteTransactionInTx(tx.wtx); }); } - async deleteTransactionInTx(tx: LegacyWalletTxHandle): Promise<void> { + async deleteTransactionInTx(tx: WalletDbTransaction): Promise<void> { const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; @@ -383,7 +384,7 @@ export class DepositTransactionContext implements TransactionContext { async userSuspendTransaction(): Promise<void> { const { wex, depositGroupId, transactionId, taskId: retryTag } = this; await wex.runLegacyWalletDbTx(async (tx) => { - const [dg, h] = await this.getRecordHandle(tx); + const [dg, h] = await this.getRecordHandle(tx.wtx); if (!dg) { logger.warn( `can't suspend deposit group, depositGroupId=${depositGroupId} not found`, @@ -459,7 +460,7 @@ export class DepositTransactionContext implements TransactionContext { dg.operationStatus = DepositOperationStatus.Aborting; dg.abortReason = reason; await tx.wtx.upsertDepositGroup(dg); - await this.updateTransactionMeta(tx); + await this.updateTransactionMeta(tx.wtx); applyNotifyTransition(tx.notify, transactionId, { oldTxState: oldState, newTxState: computeDepositTransactionStatus(dg), @@ -545,7 +546,7 @@ export class DepositTransactionContext implements TransactionContext { } dg.operationStatus = newOpStatus; await tx.wtx.upsertDepositGroup(dg); - await this.updateTransactionMeta(tx); + await this.updateTransactionMeta(tx.wtx); applyNotifyTransition(tx.notify, transactionId, { oldTxState: oldState, newTxState: computeDepositTransactionStatus(dg), @@ -602,7 +603,7 @@ export class DepositTransactionContext implements TransactionContext { dg.operationStatus = newState; dg.failReason = reason; await tx.wtx.upsertDepositGroup(dg); - await this.updateTransactionMeta(tx); + await this.updateTransactionMeta(tx.wtx); applyNotifyTransition(tx.notify, transactionId, { oldTxState: oldState, newTxState: computeDepositTransactionStatus(dg), @@ -956,7 +957,7 @@ async function refundDepositGroup( ); newDg.abortRefreshGroupId = refreshRes.refreshGroupId; await tx.wtx.upsertDepositGroup(newDg); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); return { refreshRes }; }); @@ -1026,7 +1027,7 @@ async function waitForRefreshOnDepositGroup( default: return false; } - const [newDg, h] = await ctx.getRecordHandle(tx); + const [newDg, h] = await ctx.getRecordHandle(tx.wtx); if (!newDg) { return false; } @@ -1187,7 +1188,7 @@ async function processDepositGroupPendingKyc( // Now store the result. return await wex.runLegacyWalletDbTx(async (tx) => { - const [newDg, h] = await ctx.getRecordHandle(tx); + const [newDg, h] = await ctx.getRecordHandle(tx.wtx); if (!newDg) { return TaskRunResult.finished(); } @@ -1375,7 +1376,7 @@ async function transitionToKycRequired( } await wex.runLegacyWalletDbTx(async (tx) => { - const [dg, h] = await ctx.getRecordHandle(tx); + const [dg, h] = await ctx.getRecordHandle(tx.wtx); if (!dg) { return undefined; } @@ -1558,7 +1559,7 @@ async function processDepositGroupTrack( dg.trackingState[newWiredCoin.id] = newWiredCoin.value; } await tx.wtx.upsertDepositGroup(dg); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); }); } } @@ -1566,7 +1567,7 @@ async function processDepositGroupTrack( let allWired = true; await wex.runLegacyWalletDbTx(async (tx) => { - const [dg, h] = await ctx.getRecordHandle(tx); + const [dg, h] = await ctx.getRecordHandle(tx.wtx); if (!dg) { return undefined; } @@ -1583,7 +1584,7 @@ async function processDepositGroupTrack( dg.timestampFinished = timestampPreciseToDb(TalerPreciseTimestamp.now()); dg.operationStatus = DepositOperationStatus.Finished; await tx.wtx.upsertDepositGroup(dg); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); } await h.update(dg); }); @@ -1665,7 +1666,7 @@ async function doCoinSelection( () => DepositElementStatus.DepositPending, ); await tx.wtx.upsertDepositGroup(dg); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); await spendCoins(wex, tx, { transactionId: ctx.transactionId, coinPubs: dg.payCoinSelection.coinPubs, @@ -1790,7 +1791,7 @@ async function submitDepositBatch( await tx.wtx.upsertDepositGroup(dg); } } - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); }); return null; @@ -1897,7 +1898,7 @@ async function processDepositGroupPendingDeposit( } await wex.runLegacyWalletDbTx(async (tx) => { - const [dg, h] = await ctx.getRecordHandle(tx); + const [dg, h] = await ctx.getRecordHandle(tx.wtx); if (!dg) { return undefined; } @@ -2335,7 +2336,7 @@ export async function createDepositGroup( const transactionId = ctx.transactionId; const newTxState = await wex.runLegacyWalletDbTx(async (tx) => { - const [oldDg, h] = await ctx.getRecordHandle(tx); + const [oldDg, h] = await ctx.getRecordHandle(tx.wtx); if (oldDg != null) { throw Error("deposit group already exists"); } @@ -2396,7 +2397,7 @@ async function getCounterpartyEffectiveDepositAmount( } for (const exchangeUrl of exchangeSet.values()) { - const exchangeDetails = await getExchangeDetailsInTx(tx, exchangeUrl); + const exchangeDetails = await getExchangeDetailsInTx(tx.wtx, exchangeUrl); if (!exchangeDetails) { continue; } @@ -2453,7 +2454,7 @@ async function getTotalFeesForDepositAmount( } for (const exchangeUrl of exchangeSet.values()) { - const exchangeDetails = await getExchangeDetailsInTx(tx, exchangeUrl); + const exchangeDetails = await getExchangeDetailsInTx(tx.wtx, exchangeUrl); if (!exchangeDetails) { continue; } diff --git a/packages/taler-wallet-core/src/dev-experiments.ts b/packages/taler-wallet-core/src/dev-experiments.ts @@ -201,7 +201,7 @@ export async function applyDevExperiment( }; await tx.wtx.upsertRefreshGroup(newRg); const ctx = new RefreshTransactionContext(wex, refreshGroupId); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); }); wex.taskScheduler.startShepherdTask( constructTaskIdentifier({ @@ -232,7 +232,7 @@ export async function applyDevExperiment( wex, newRg.denomLossEventId, ); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); }); return; } @@ -600,7 +600,7 @@ async function addFakeTx( effectiveWithdrawalAmount: Amounts.stringify(amountEffective), rawWithdrawalAmount: Amounts.stringify(amountEffective), }); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); }); break; } @@ -703,7 +703,7 @@ async function addFakeTx( ), refundAmountAwaiting: undefined, }); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); }); break; } @@ -765,7 +765,7 @@ async function addFakeTx( ), totalCost: Amounts.stringify(amountEffective), }); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); }); break; } @@ -825,7 +825,7 @@ async function addFakeTx( ), withdrawalGroupId: undefined, }); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); }); break; } diff --git a/packages/taler-wallet-core/src/exchanges.ts b/packages/taler-wallet-core/src/exchanges.ts @@ -192,6 +192,7 @@ import { WithdrawTransactionContext, updateWithdrawalDenomsForExchange, } from "./withdraw.js"; +import { WalletDbTransaction } from "./dbtx.js"; const logger = new Logger("exchanges.ts"); @@ -213,10 +214,10 @@ interface ExchangeTosDownloadResult { * Get exchange details from the database. */ async function getExchangeRecordsInternal( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, exchangeBaseUrl: string, ): Promise<WalletExchangeDetails | undefined> { - const r = await tx.wtx.getExchange(exchangeBaseUrl); + const r = await tx.getExchange(exchangeBaseUrl); if (!r) { logger.warn(`no exchange found for ${exchangeBaseUrl}`); return; @@ -244,7 +245,7 @@ async function getExchangeRecordsInternal( return; } const { currency, masterPublicKey } = dp; - const details = await tx.wtx.getExchangeDetailsByPointer( + const details = await tx.getExchangeDetailsByPointer( r.baseUrl, currency, masterPublicKey, @@ -258,12 +259,12 @@ async function getExchangeRecordsInternal( } export async function getScopeForAllCoins( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, coinPubs: string[], ): Promise<ScopeInfo[]> { let exchangeSet = new Set<string>(); for (const pub of coinPubs) { - const coin = await tx.wtx.getCoin(pub); + const coin = await tx.getCoin(pub); if (!coin) { logger.warn(`coin ${coinPubs} not found, unable to compute full scope`); continue; @@ -277,7 +278,7 @@ export async function getScopeForAllCoins( * Get a list of scope infos applicable to a list of exchanges. */ export async function getScopeForAllExchanges( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, exs: string[], ): Promise<ScopeInfo[]> { const scopes: ScopeInfo[] = []; @@ -297,7 +298,7 @@ export async function getScopeForAllExchanges( } export async function getExchangeScopeInfoOrUndefined( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, exchangeBaseUrl: string, ): Promise<ScopeInfo | undefined> { const det = await getExchangeRecordsInternal(tx, exchangeBaseUrl); @@ -312,7 +313,7 @@ export async function getExchangeScopeInfo( exchangeBaseUrl: string, currency: string, ): Promise<ScopeInfo> { - const det = await getExchangeRecordsInternal(tx, exchangeBaseUrl); + const det = await getExchangeRecordsInternal(tx.wtx, exchangeBaseUrl); if (!det) { return { type: ScopeType.Exchange, @@ -320,14 +321,14 @@ export async function getExchangeScopeInfo( url: exchangeBaseUrl, }; } - return internalGetExchangeScopeInfo(tx, det); + return internalGetExchangeScopeInfo(tx.wtx, det); } async function internalGetExchangeScopeInfo( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, exchangeDetails: WalletExchangeDetails, ): Promise<ScopeInfo> { - const globalExchangeRec = await tx.wtx.getGlobalCurrencyExchange( + const globalExchangeRec = await tx.getGlobalCurrencyExchange( exchangeDetails.currency, exchangeDetails.exchangeBaseUrl, exchangeDetails.masterPublicKey, @@ -339,7 +340,7 @@ async function internalGetExchangeScopeInfo( }; } else { for (const aud of exchangeDetails.auditors) { - const globalAuditorRec = await tx.wtx.getGlobalCurrencyAuditor( + const globalAuditorRec = await tx.getGlobalCurrencyAuditor( exchangeDetails.currency, aud.auditor_url, aud.auditor_pub, @@ -388,7 +389,7 @@ async function makeExchangeListItem( let scopeInfo: ScopeInfo | undefined = undefined; if (exchangeDetails) { - scopeInfo = await internalGetExchangeScopeInfo(tx, exchangeDetails); + scopeInfo = await internalGetExchangeScopeInfo(tx.wtx, exchangeDetails); } const currency = @@ -479,7 +480,7 @@ export interface ExchangeDetails { } export async function getExchangeDetailsInTx( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, exchangeBaseUrl: string, ): Promise<ExchangeDetails | undefined> { const det = await getExchangeRecordsInternal(tx, exchangeBaseUrl); @@ -509,7 +510,7 @@ export async function lookupExchangeByUri( return undefined; } const exchangeDetails = await getExchangeRecordsInternal( - tx, + tx.wtx, exchangeRec.baseUrl, ); const opRetryRecord = await tx.wtx.getOperationRetry( @@ -807,7 +808,7 @@ async function provideExchangeRecordInTx( newExchangeState: getExchangeState(r), }); } - const exchangeDetails = await getExchangeRecordsInternal(tx, baseUrl); + const exchangeDetails = await getExchangeRecordsInternal(tx.wtx, baseUrl); return { exchange, exchangeDetails }; } @@ -1325,13 +1326,16 @@ export async function waitReadyExchange( await wex.runLegacyWalletDbTx(async (tx) => { const exchange = await tx.wtx.getExchange(exchangeBaseUrl); const exchangeDetails = await getExchangeRecordsInternal( - tx, + tx.wtx, exchangeBaseUrl, ); const retryInfo = await tx.wtx.getOperationRetry(operationId); let scopeInfo: ScopeInfo | undefined = undefined; if (exchange && exchangeDetails) { - scopeInfo = await internalGetExchangeScopeInfo(tx, exchangeDetails); + scopeInfo = await internalGetExchangeScopeInfo( + tx.wtx, + exchangeDetails, + ); } return { exchange, exchangeDetails, retryInfo, scopeInfo }; }); @@ -1507,13 +1511,13 @@ async function loadReadyExchangeSummary( exchangeRec: WalletExchangeEntry, ): Promise<ReadyExchangeSummary | undefined> { const exchangeDetails = await getExchangeRecordsInternal( - tx, + tx.wtx, exchangeRec.baseUrl, ); if (!exchangeDetails) { return undefined; } - const scopeInfo = await internalGetExchangeScopeInfo(tx, exchangeDetails); + const scopeInfo = await internalGetExchangeScopeInfo(tx.wtx, exchangeDetails); if (!scopeInfo) { return undefined; } @@ -1896,7 +1900,7 @@ export async function updateExchangeFromUrlHandler( wex.ws.clearAllCaches(); const oldExchangeState = getExchangeState(r); - const existingDetails = await getExchangeRecordsInternal(tx, r.baseUrl); + const existingDetails = await getExchangeRecordsInternal(tx.wtx, r.baseUrl); let detailsPointerChanged = false; if (!existingDetails) { detailsPointerChanged = true; @@ -2405,7 +2409,7 @@ async function handleDenomLoss( }; await tx.wtx.upsertDenomLossEvent(rec); const ctx = new DenomLossTransactionContext(wex, denomLossEventId); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); tx.notify({ type: NotificationType.TransactionStateTransition, transactionId: ctx.transactionId, @@ -2437,7 +2441,7 @@ async function handleDenomLoss( }; await tx.wtx.upsertDenomLossEvent(rec); const ctx = new DenomLossTransactionContext(wex, denomLossEventId); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); tx.notify({ type: NotificationType.TransactionStateTransition, transactionId: ctx.transactionId, @@ -2522,13 +2526,13 @@ export class DenomLossTransactionContext implements TransactionContext { return undefined; } - async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { - const denomLossRec = await tx.wtx.getDenomLossEvent(this.denomLossEventId); + async updateTransactionMeta(tx: WalletDbTransaction): Promise<void> { + const denomLossRec = await tx.getDenomLossEvent(this.denomLossEventId); if (!denomLossRec) { - await tx.wtx.deleteTransactionMeta(this.transactionId); + await tx.deleteTransactionMeta(this.transactionId); return; } - await tx.wtx.upsertTransactionMeta({ + await tx.upsertTransactionMeta({ transactionId: this.transactionId, status: denomLossRec.status, timestamp: denomLossRec.timestampCreated, @@ -2582,9 +2586,9 @@ export class DenomLossTransactionContext implements TransactionContext { } async lookupFullTransaction( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, ): Promise<Transaction | undefined> { - const rec = await tx.wtx.getDenomLossEvent(this.denomLossEventId); + const rec = await tx.getDenomLossEvent(this.denomLossEventId); if (!rec) { return undefined; } @@ -2687,7 +2691,7 @@ export async function getExchangePaytoUri( // We do the update here, since the exchange might not even exist // yet in our database. const details = await wex.runLegacyWalletDbTx(async (tx) => { - return getExchangeRecordsInternal(tx, exchangeBaseUrl); + return getExchangeRecordsInternal(tx.wtx, exchangeBaseUrl); }); const accounts = details?.wireInfo.accounts ?? []; for (const account of accounts) { @@ -2886,7 +2890,7 @@ export async function listExchanges( exchangeBaseUrl: exchangeRec.baseUrl, }); const exchangeDetails = await getExchangeRecordsInternal( - tx, + tx.wtx, exchangeRec.baseUrl, ); const opRetryRecord = await tx.wtx.getOperationRetry(taskId); @@ -2988,7 +2992,10 @@ export async function getExchangeDetailedInfo( return; } const { currency } = dp; - const exchangeDetails = await getExchangeRecordsInternal(tx, ex.baseUrl); + const exchangeDetails = await getExchangeRecordsInternal( + tx.wtx, + ex.baseUrl, + ); if (!exchangeDetails) { return; } @@ -3230,7 +3237,7 @@ async function purgeExchange( await tx.wtx.getWithdrawalGroupsByExchange(exchangeBaseUrl); for (const wg of withdrawalGroupRecs) { const ctx = new WithdrawTransactionContext(wex, wg.withdrawalGroupId); - await ctx.deleteTransactionInTx(tx); + await ctx.deleteTransactionInTx(tx.wtx); } } @@ -3241,7 +3248,7 @@ async function purgeExchange( for (const rg of refreshGroups) { if (rg.infoPerExchange && rg.infoPerExchange[exchangeBaseUrl] != null) { const ctx = new RefreshTransactionContext(wex, rg.refreshGroupId); - await ctx.deleteTransactionInTx(tx); + await ctx.deleteTransactionInTx(tx.wtx); } } } @@ -3251,7 +3258,7 @@ async function purgeExchange( await tx.wtx.getRecoupGroupsByExchange(exchangeBaseUrl); for (const rg of recoupGroups) { const ctx = new RecoupTransactionContext(wex, rg.recoupGroupId); - await ctx.deleteTransactionInTx(tx); + await ctx.deleteTransactionInTx(tx.wtx); } } // Remove from deposits @@ -3261,7 +3268,7 @@ async function purgeExchange( for (const dg of depositGroups) { if (dg.infoPerExchange && dg.infoPerExchange[exchangeBaseUrl]) { const ctx = new DepositTransactionContext(wex, dg.depositGroupId); - await ctx.deleteTransactionInTx(tx); + await ctx.deleteTransactionInTx(tx.wtx); } } } @@ -3274,10 +3281,10 @@ async function purgeExchange( ); for (const r of refunds) { const refundCtx = new RefundTransactionContext(wex, r.refundGroupId); - await refundCtx.deleteTransactionInTx(tx); + await refundCtx.deleteTransactionInTx(tx.wtx); } const payCtx = new PayMerchantTransactionContext(wex, purch.proposalId); - const res = await payCtx.deleteTransactionInTx(tx); + const res = await payCtx.deleteTransactionInTx(tx.wtx); } } // Remove from peerPullCredit @@ -3286,7 +3293,7 @@ async function purgeExchange( for (const rec of recs) { if (rec.exchangeBaseUrl === exchangeBaseUrl) { const ctx = new PeerPullCreditTransactionContext(wex, rec.pursePub); - await ctx.deleteTransactionInTx(tx); + await ctx.deleteTransactionInTx(tx.wtx); } } } @@ -3299,7 +3306,7 @@ async function purgeExchange( wex, rec.peerPullDebitId, ); - await ctx.deleteTransactionInTx(tx); + await ctx.deleteTransactionInTx(tx.wtx); } } } @@ -3312,7 +3319,7 @@ async function purgeExchange( wex, rec.peerPushCreditId, ); - await ctx.deleteTransactionInTx(tx); + await ctx.deleteTransactionInTx(tx.wtx); } } } @@ -3322,7 +3329,7 @@ async function purgeExchange( for (const rec of recs) { if (rec.exchangeBaseUrl === exchangeBaseUrl) { const ctx = new PeerPushDebitTransactionContext(wex, rec.pursePub); - await ctx.deleteTransactionInTx(tx); + await ctx.deleteTransactionInTx(tx.wtx); } } } @@ -3450,7 +3457,7 @@ export async function checkIncomingAmountLegalUnderKycBalanceThreshold( if (!exchangeRec) { throw Error("exchange not found"); } - const det = await getExchangeRecordsInternal(tx, exchangeBaseUrl); + const det = await getExchangeRecordsInternal(tx.wtx, exchangeBaseUrl); if (!det) { throw Error("exchange not found"); } @@ -4059,7 +4066,7 @@ export async function checkExchangeInScopeTx( } case ScopeType.Global: { const exchangeDetails = await getExchangeRecordsInternal( - tx, + tx.wtx, exchangeBaseUrl, ); if (!exchangeDetails) { diff --git a/packages/taler-wallet-core/src/instructedAmountConversion.ts b/packages/taler-wallet-core/src/instructedAmountConversion.ts @@ -136,7 +136,10 @@ async function getAvailableCoins( filters.exchanges ?? databaseExchanges.map((e) => e.baseUrl); for (const exchangeBaseUrl of filteredExchanges) { - const exchangeDetails = await getExchangeDetailsInTx(tx, exchangeBaseUrl); + const exchangeDetails = await getExchangeDetailsInTx( + tx.wtx, + exchangeBaseUrl, + ); // 1.- exchange has same currency if (exchangeDetails?.currency !== currency) { continue; diff --git a/packages/taler-wallet-core/src/pay-merchant.ts b/packages/taler-wallet-core/src/pay-merchant.ts @@ -226,19 +226,19 @@ export class PayMerchantTransactionContext implements TransactionContext { * * Must be called each time the DB record for the transaction is updated. */ - async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { - const purchaseRec = await tx.wtx.getPurchase(this.proposalId); + async updateTransactionMeta(tx: WalletDbTransaction): Promise<void> { + const purchaseRec = await tx.getPurchase(this.proposalId); if (!purchaseRec) { - await tx.wtx.deleteTransactionMeta(this.transactionId); + await tx.deleteTransactionMeta(this.transactionId); return; } if (!purchaseRec.download) { // Not ready yet. - await tx.wtx.deleteTransactionMeta(this.transactionId); + await tx.deleteTransactionMeta(this.transactionId); return; } - await tx.wtx.upsertTransactionMeta({ + await tx.upsertTransactionMeta({ transactionId: this.transactionId, status: purchaseRec.purchaseStatus, timestamp: purchaseRec.timestamp, @@ -248,18 +248,18 @@ export class PayMerchantTransactionContext implements TransactionContext { } async lookupFullTransaction( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, req?: LookupFullTransactionOpts, ): Promise<Transaction | undefined> { const proposalId = this.proposalId; - const purchaseRec = await tx.wtx.getPurchase(proposalId); + const purchaseRec = await tx.getPurchase(proposalId); if (!purchaseRec) { throw Error("not found"); } const txState = computePayMerchantTransactionState(purchaseRec); const payOpId = TaskIdentifiers.forPay(purchaseRec); - const payRetryRec = await tx.wtx.getOperationRetry(payOpId); + const payRetryRec = await tx.getOperationRetry(payOpId); const unk = "UNKNOWN:0"; if (!purchaseRec.download) { return { @@ -294,12 +294,12 @@ export class PayMerchantTransactionContext implements TransactionContext { const download = await expectProposalDownloadInTx( this.wex, - tx.wtx, + tx, purchaseRec, ); const contractData = download.contractTerms; - const refundsInfo = await tx.wtx.getRefundGroupsByProposal( + const refundsInfo = await tx.getRefundGroupsByProposal( purchaseRec.proposalId, ); @@ -411,12 +411,12 @@ export class PayMerchantTransactionContext implements TransactionContext { async userDeleteTransaction(): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - return this.deleteTransactionInTx(tx); + return this.deleteTransactionInTx(tx.wtx); }); } async deleteTransactionInTx( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, opts: { keepRelated?: boolean } = {}, ): Promise<void> { const [rec, h] = await this.getRecordHandle(tx); @@ -431,7 +431,7 @@ export class PayMerchantTransactionContext implements TransactionContext { rec.download?.fulfillmentUrl && rec.purchaseStatus !== PurchaseStatus.DoneRepurchaseDetected ) { - const otherTransactions = await tx.wtx.getPurchasesByFulfillmentUrl( + const otherTransactions = await tx.getPurchasesByFulfillmentUrl( rec.download.fulfillmentUrl, ); for (const otx of otherTransactions) { @@ -457,7 +457,7 @@ export class PayMerchantTransactionContext implements TransactionContext { const { wex } = this; wex.taskScheduler.stopShepherdTask(this.taskId); await wex.runLegacyWalletDbTx(async (tx) => { - const [purchase, h] = await this.getRecordHandle(tx); + const [purchase, h] = await this.getRecordHandle(tx.wtx); if (!purchase) { throw Error("purchase not found"); } @@ -476,7 +476,7 @@ export class PayMerchantTransactionContext implements TransactionContext { ): Promise<void> { const { wex } = this; await wex.runLegacyWalletDbTx(async (tx) => { - const [purchase, h] = await this.getRecordHandle(tx); + const [purchase, h] = await this.getRecordHandle(tx.wtx); if (purchase?.purchaseStatus != fromSt) { return; } @@ -489,7 +489,7 @@ export class PayMerchantTransactionContext implements TransactionContext { async userAbortTransaction(reason?: TalerErrorDetail): Promise<void> { const { wex } = this; await wex.runLegacyWalletDbTx(async (tx) => { - const [purchase, h] = await this.getRecordHandle(tx); + const [purchase, h] = await this.getRecordHandle(tx.wtx); if (!purchase) { throw Error("purchase not found"); } @@ -527,7 +527,7 @@ export class PayMerchantTransactionContext implements TransactionContext { async userResumeTransaction(): Promise<void> { const { wex } = this; await wex.runLegacyWalletDbTx(async (tx) => { - const [purchase, h] = await this.getRecordHandle(tx); + const [purchase, h] = await this.getRecordHandle(tx.wtx); if (!purchase) { throw Error("purchase not found"); } @@ -544,7 +544,7 @@ export class PayMerchantTransactionContext implements TransactionContext { async userFailTransaction(reason?: TalerErrorDetail): Promise<void> { const { wex } = this; await wex.runLegacyWalletDbTx(async (tx) => { - const [purchase, h] = await this.getRecordHandle(tx); + const [purchase, h] = await this.getRecordHandle(tx.wtx); if (!purchase) { throw Error("purchase not found"); } @@ -564,16 +564,16 @@ export class PayMerchantTransactionContext implements TransactionContext { } async getRecordHandle( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, ): Promise<[WalletPurchase | undefined, RecordHandle<WalletPurchase>]> { return getGenericRecordHandle<WalletPurchase>( this, - tx.wtx, - async () => tx.wtx.getPurchase(this.proposalId), + tx, + async () => tx.getPurchase(this.proposalId), async (r) => { - await tx.wtx.upsertPurchase(r); + await tx.upsertPurchase(r); }, - async () => tx.wtx.deletePurchase(this.proposalId), + async () => tx.deletePurchase(this.proposalId), (r) => computePayMerchantTransactionState(r), (r) => r.purchaseStatus, () => this.updateTransactionMeta(tx), @@ -582,13 +582,13 @@ export class PayMerchantTransactionContext implements TransactionContext { } async function computePayMerchantExchangesInTx( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, purchaseRecord: WalletPurchase, ): Promise<string[]> { if (purchaseRecord?.exchanges) { return purchaseRecord.exchanges; } else if (purchaseRecord != null && purchaseRecord.download != null) { - const contractTermsRec = await tx.wtx.getContractTerms( + const contractTermsRec = await tx.getContractTerms( purchaseRecord.download.contractTermsHash, ); if (contractTermsRec) { @@ -602,7 +602,7 @@ async function computePayMerchantExchangesInTx( } async function computePayMerchantTransactionScopesInTx( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, purchaseRec: WalletPurchase, ): Promise<ScopeInfo[]> { if (purchaseRec.exchanges && purchaseRec.exchanges.length > 0) { @@ -615,7 +615,7 @@ async function computePayMerchantTransactionScopesInTx( : purchaseRec.payInfo.payCoinSelection.coinPubs; return await getScopeForAllCoins(tx, coinList); } else if (purchaseRec.download != null) { - const contractTermsRec = await tx.wtx.getContractTerms( + const contractTermsRec = await tx.getContractTerms( purchaseRec.download.contractTermsHash, ); if (contractTermsRec) { @@ -653,18 +653,18 @@ export class RefundTransactionContext implements TransactionContext { * * Must be called each time the DB record for the transaction is updated. */ - async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { - const refundRec = await tx.wtx.getRefundGroup(this.refundGroupId); + async updateTransactionMeta(tx: WalletDbTransaction): Promise<void> { + const refundRec = await tx.getRefundGroup(this.refundGroupId); if (!refundRec) { - await tx.wtx.deleteTransactionMeta(this.transactionId); + await tx.deleteTransactionMeta(this.transactionId); return; } - const purchaseRecord = await tx.wtx.getPurchase(refundRec.proposalId); + const purchaseRecord = await tx.getPurchase(refundRec.proposalId); let exchanges: string[] = []; if (purchaseRecord) { exchanges = await computePayMerchantExchangesInTx(tx, purchaseRecord); } - await tx.wtx.upsertTransactionMeta({ + await tx.upsertTransactionMeta({ transactionId: this.transactionId, status: refundRec.status, timestamp: refundRec.timestampCreated, @@ -674,9 +674,9 @@ export class RefundTransactionContext implements TransactionContext { } async lookupFullTransaction( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, ): Promise<Transaction | undefined> { - const refundRecord = await tx.wtx.getRefundGroup(this.refundGroupId); + const refundRecord = await tx.getRefundGroup(this.refundGroupId); if (!refundRecord) { throw Error("not found"); } @@ -694,7 +694,7 @@ export class RefundTransactionContext implements TransactionContext { summary_i18n: maybeContractData.contractTerms.summary_i18n, }; } - const purchaseRecord = await tx.wtx.getPurchase(refundRecord.proposalId); + const purchaseRecord = await tx.getPurchase(refundRecord.proposalId); let scopes: ScopeInfo[]; if (purchaseRecord) { @@ -739,7 +739,7 @@ export class RefundTransactionContext implements TransactionContext { const { wex } = this; const res = await wex.runLegacyWalletDbTx(async (tx) => { - return await this.deleteTransactionInTx(tx); + return await this.deleteTransactionInTx(tx.wtx); }); for (const notif of res.notifs) { this.wex.ws.notify(notif); @@ -747,22 +747,20 @@ export class RefundTransactionContext implements TransactionContext { } async deleteTransactionInTx( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, ): Promise<{ notifs: WalletNotification[] }> { const notifs: WalletNotification[] = []; - const refundRecord = await tx.wtx.getRefundGroup(this.refundGroupId); + const refundRecord = await tx.getRefundGroup(this.refundGroupId); if (!refundRecord) { return { notifs }; } - await tx.wtx.deleteRefundGroup(this.refundGroupId); + await tx.deleteRefundGroup(this.refundGroupId); await this.updateTransactionMeta(tx); - await tx.wtx.upsertTombstone({ id: this.transactionId }); - const items = await tx.wtx.getRefundItemsByGroup( - refundRecord.refundGroupId, - ); + await tx.upsertTombstone({ id: this.transactionId }); + const items = await tx.getRefundItemsByGroup(refundRecord.refundGroupId); for (const item of items) { if (item.id != null) { - await tx.wtx.deleteRefundItem(item.id); + await tx.deleteRefundItem(item.id); } } return { notifs }; @@ -786,14 +784,14 @@ export class RefundTransactionContext implements TransactionContext { } async function lookupMaybeContractData( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, proposalId: string, ): Promise<DownloadedContractData | undefined> { let contractData: DownloadedContractData | undefined = undefined; - const purchaseTx = await tx.wtx.getPurchase(proposalId); + const purchaseTx = await tx.getPurchase(proposalId); if (purchaseTx && purchaseTx.download) { const download = purchaseTx.download; - const contractTermsRecord = await tx.wtx.getContractTerms( + const contractTermsRecord = await tx.getContractTerms( download.contractTermsHash, ); if (!contractTermsRecord) { @@ -866,7 +864,7 @@ async function failProposalClaimPermanently( ): Promise<void> { const ctx = new PayMerchantTransactionContext(wex, proposalId); await wex.runLegacyWalletDbTx(async (tx) => { - const [p, h] = await ctx.getRecordHandle(tx); + const [p, h] = await ctx.getRecordHandle(tx.wtx); if (!p) { return; } @@ -1137,7 +1135,7 @@ async function processDownloadProposal( logger.trace(`extracted contract data: ${j2s(contractData)}`); await wex.runLegacyWalletDbTx(async (tx) => { - const [p, h] = await ctx.getRecordHandle(tx); + const [p, h] = await ctx.getRecordHandle(tx.wtx); if (!p) { return; } @@ -1239,7 +1237,7 @@ async function startPayReplay( ): Promise<void> { logger.info(`starting pay replay of ${proposalId} under ${sessionId}`); const ctx = new PayMerchantTransactionContext(wex, proposalId); - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (rec && rec.purchaseStatus === PurchaseStatus.Done) { rec.purchaseStatus = PurchaseStatus.PendingPayingReplay; rec.lastSessionId = sessionId; @@ -1423,7 +1421,7 @@ async function createOrReusePurchase( // means that another wallet already paid the proposal if (paid) { await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await oldCtx.getRecordHandle(tx); + const [rec, h] = await oldCtx.getRecordHandle(tx.wtx); // The order is only paid by another wallet // if the merchant says it's paid but the local // wallet is still in a dialog state. @@ -1497,7 +1495,7 @@ async function createOrReusePurchase( await wex.runLegacyWalletDbTx(async (tx) => { await tx.wtx.upsertPurchase(proposalRecord); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); const oldTxState: TransactionState = { major: TransactionMajorState.None, }; @@ -1531,7 +1529,7 @@ async function storeFirstPaySuccess( const ctx = new PayMerchantTransactionContext(wex, proposalId); const now = AbsoluteTime.toPreciseTimestamp(AbsoluteTime.now()); await wex.runLegacyWalletDbTx(async (tx) => { - const [purchase, h] = await ctx.getRecordHandle(tx); + const [purchase, h] = await ctx.getRecordHandle(tx.wtx); if (!purchase) { return; } @@ -1584,7 +1582,7 @@ async function storePayReplaySuccess( ): Promise<void> { const ctx = new PayMerchantTransactionContext(wex, proposalId); await wex.runLegacyWalletDbTx(async (tx) => { - const [purchase, h] = await ctx.getRecordHandle(tx); + const [purchase, h] = await ctx.getRecordHandle(tx.wtx); if (!purchase) { return; } @@ -1721,7 +1719,7 @@ async function reselectCoinsTx( } await tx.wtx.upsertPurchase(p); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); if (p.payInfo.payCoinSelection) { await spendCoins(ctx.wex, tx, { @@ -1925,7 +1923,7 @@ async function checkPaymentByProposalId( const scopes = await wex.runLegacyWalletDbTx(async (tx) => { let exchangeUrls = contractTerms.exchanges.map((x) => x.url); - return await getScopeForAllExchanges(tx, exchangeUrls); + return await getScopeForAllExchanges(tx.wtx, exchangeUrls); }); const handleUnconfirmed = async (): Promise<PreparePayResult> => { @@ -1969,7 +1967,7 @@ async function checkPaymentByProposalId( )}`, ); let scopes = await wex.runLegacyWalletDbTx(async (tx) => { - return getScopeForAllExchanges(tx, allowedExchangeUrls); + return getScopeForAllExchanges(tx.wtx, allowedExchangeUrls); }); return { status: PreparePayResultType.InsufficientBalance, @@ -1996,7 +1994,7 @@ async function checkPaymentByProposalId( const exchanges = new Set<string>(coins.map((x) => x.exchangeBaseUrl)); const scopes = await wex.runLegacyWalletDbTx(async (tx) => { - return await getScopeForAllExchanges(tx, [...exchanges]); + return await getScopeForAllExchanges(tx.wtx, [...exchanges]); }); return { @@ -2017,7 +2015,7 @@ async function checkPaymentByProposalId( ); logger.trace(`last: ${purchaseRec.lastSessionId}, current: ${sessionId}`); await wex.runLegacyWalletDbTx(async (tx) => { - const [p, h] = await ctx.getRecordHandle(tx); + const [p, h] = await ctx.getRecordHandle(tx.wtx); if (!p) { return; } @@ -2600,7 +2598,7 @@ export async function getChoicesForPayment( // exchanges of the selected coins. let scopeInfo: ScopeInfo | undefined = undefined; for (const exch of exchanges) { - const s = await getExchangeScopeInfoOrUndefined(tx, exch); + const s = await getExchangeScopeInfoOrUndefined(tx.wtx, exch); if (s != null) { scopeInfo = s; break; @@ -2767,7 +2765,7 @@ export async function confirmPay( purchase.purchaseStatus = PurchaseStatus.PendingPayingReplay; } await tx.wtx.upsertPurchase(purchase); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); } return purchase; }); @@ -2822,7 +2820,7 @@ export async function confirmPay( ); await wex.runLegacyWalletDbTx(async (tx) => { - const [p, h] = await ctx.getRecordHandle(tx); + const [p, h] = await ctx.getRecordHandle(tx.wtx); if (!p) { return; } @@ -3140,7 +3138,7 @@ async function processPurchasePay( if (paid) { await wex.runLegacyWalletDbTx(async (tx) => { - const [p, h] = await ctx.getRecordHandle(tx); + const [p, h] = await ctx.getRecordHandle(tx.wtx); if (!p) { return; } @@ -3232,7 +3230,7 @@ async function processPurchasePay( p.payInfo.payCoinSelectionUid = encodeCrock(getRandomBytes(16)); p.purchaseStatus = PurchaseStatus.PendingPaying; await tx.wtx.upsertPurchase(p); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); await spendCoins(wex, tx, { transactionId: ctx.transactionId, coinPubs: selectCoinsResult.coinSel.coins.map((x) => x.coinPub), @@ -3690,7 +3688,7 @@ export async function refuseProposal( ): Promise<void> { const ctx = new PayMerchantTransactionContext(wex, proposalId); await wex.runLegacyWalletDbTx(async (tx) => { - const [proposal, h] = await ctx.getRecordHandle(tx); + const [proposal, h] = await ctx.getRecordHandle(tx.wtx); switch (proposal?.purchaseStatus) { case PurchaseStatus.DialogProposed: case PurchaseStatus.DialogShared: @@ -4038,7 +4036,7 @@ export async function sharePayment( const ctx = new PayMerchantTransactionContext(wex, proposalId); const result = await wex.runLegacyWalletDbTx(async (tx) => { - const [p, h] = await ctx.getRecordHandle(tx); + const [p, h] = await ctx.getRecordHandle(tx.wtx); if (!p) { logger.warn("purchase does not exist anymore"); return undefined; @@ -4143,7 +4141,7 @@ async function processPurchaseDialogProposed( if (AbsoluteTime.isExpired(expiry)) { await wex.runLegacyWalletDbTx(async (tx) => { - const [r2, h] = await ctx.getRecordHandle(tx); + const [r2, h] = await ctx.getRecordHandle(tx.wtx); if (r2?.purchaseStatus !== PurchaseStatus.DialogProposed) { return; } @@ -4224,7 +4222,7 @@ async function processPurchaseDialogShared( } await wex.runLegacyWalletDbTx(async (tx) => { - const [p, h] = await ctx.getRecordHandle(tx); + const [p, h] = await ctx.getRecordHandle(tx.wtx); switch (p?.purchaseStatus) { case PurchaseStatus.DialogShared: p.purchaseStatus = PurchaseStatus.FailedPaidByOther; @@ -4284,7 +4282,7 @@ async function processPurchaseAutoRefund( if (noAutoRefundOrExpired || fullyRefunded) { await wex.runLegacyWalletDbTx(async (tx) => { - const [p, h] = await ctx.getRecordHandle(tx); + const [p, h] = await ctx.getRecordHandle(tx.wtx); switch (p?.purchaseStatus) { case PurchaseStatus.PendingQueryingAutoRefund: case PurchaseStatus.FinalizingQueryingAutoRefund: @@ -4321,7 +4319,7 @@ async function processPurchaseAutoRefund( } await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); switch (rec?.purchaseStatus) { case PurchaseStatus.PendingQueryingAutoRefund: case PurchaseStatus.FinalizingQueryingAutoRefund: @@ -4353,7 +4351,7 @@ async function processPurchaseAbortingRefund( const payCoinSelection = purchase.payInfo?.payCoinSelection; if (!payCoinSelection) { await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (rec?.purchaseStatus !== PurchaseStatus.AbortingWithRefund) { return; } @@ -4367,7 +4365,7 @@ async function processPurchaseAbortingRefund( } await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -4425,7 +4423,7 @@ async function processPurchaseAbortingRefund( TalerErrorCode.MERCHANT_POST_ORDERS_ID_ABORT_CONTRACT_NOT_FOUND ) { await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (rec?.purchaseStatus !== PurchaseStatus.AbortingWithRefund) { return; } @@ -4498,7 +4496,7 @@ async function processPurchaseQueryRefund( if (!orderStatus.refund_pending) { await wex.runLegacyWalletDbTx(async (tx) => { - const [p, h] = await ctx.getRecordHandle(tx); + const [p, h] = await ctx.getRecordHandle(tx.wtx); if (p?.purchaseStatus !== PurchaseStatus.PendingQueryingRefund) { return; } @@ -4513,7 +4511,7 @@ async function processPurchaseQueryRefund( ).amount; await wex.runLegacyWalletDbTx(async (tx) => { - const [p, h] = await ctx.getRecordHandle(tx); + const [p, h] = await ctx.getRecordHandle(tx.wtx); if (p?.purchaseStatus !== PurchaseStatus.PendingQueryingRefund) { return; } @@ -4597,7 +4595,7 @@ export async function startQueryRefund( ): Promise<void> { const ctx = new PayMerchantTransactionContext(wex, proposalId); await wex.runLegacyWalletDbTx(async (tx) => { - const [p, h] = await ctx.getRecordHandle(tx); + const [p, h] = await ctx.getRecordHandle(tx.wtx); if (!p) { logger.warn(`purchase ${proposalId} does not exist anymore`); return; @@ -4688,7 +4686,7 @@ async function storeRefunds( const currency = Amounts.currencyOf(amountRaw); const result = await wex.runLegacyWalletDbTx(async (tx) => { - const [myPurchase, h] = await ctx.getRecordHandle(tx); + const [myPurchase, h] = await ctx.getRecordHandle(tx.wtx); if (!myPurchase) { logger.warn("purchase group not found anymore"); return; @@ -4790,7 +4788,7 @@ async function storeRefunds( newGroup.refundGroupId, ); await tx.wtx.upsertRefundGroup(newGroup); - await refundCtx.updateTransactionMeta(tx); + await refundCtx.updateTransactionMeta(tx.wtx); applyNotifyTransition(tx.notify, refundCtx.transactionId, { oldTxState: { major: TransactionMajorState.None }, newTxState: computeRefundTransactionState(newGroup), @@ -4844,7 +4842,7 @@ async function storeRefunds( refundGroup.status = RefundGroupStatus.Failed; } await tx.wtx.upsertRefundGroup(refundGroup); - await refundCtx.updateTransactionMeta(tx); + await refundCtx.updateTransactionMeta(tx.wtx); const refreshCoins = await computeRefreshRequest(wex, tx, items); const newTxState: TransactionState = computeRefundTransactionState(refundGroup); diff --git a/packages/taler-wallet-core/src/pay-peer-pull-credit.ts b/packages/taler-wallet-core/src/pay-peer-pull-credit.ts @@ -74,8 +74,7 @@ import { WalletWithdrawalGroup, WithdrawalRecordType, } from "./db-common.js"; -import { -} from "./db-indexeddb.js"; +import {} from "./db-indexeddb.js"; import { BalanceThresholdCheckResult, checkIncomingAmountLegalUnderKycBalanceThreshold, @@ -106,6 +105,7 @@ import { internalCreateWithdrawalGroup, waitWithdrawalFinal, } from "./withdraw.js"; +import { WalletDbTransaction } from "./dbtx.js"; const logger = new Logger("pay-peer-pull-credit.ts"); @@ -127,12 +127,12 @@ export class PeerPullCreditTransactionContext implements TransactionContext { }); } - async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { - const rec = await tx.wtx.getPeerPullCredit(this.pursePub); + async updateTransactionMeta(tx: WalletDbTransaction): Promise<void> { + const rec = await tx.getPeerPullCredit(this.pursePub); if (rec == null) { - await tx.wtx.deleteTransactionMeta(this.transactionId); + await tx.deleteTransactionMeta(this.transactionId); } else { - await tx.wtx.upsertTransactionMeta({ + await tx.upsertTransactionMeta({ currency: Amounts.currencyOf(rec.estimatedAmountEffective), exchanges: [rec.exchangeBaseUrl], status: rec.status, @@ -142,7 +142,7 @@ export class PeerPullCreditTransactionContext implements TransactionContext { } } - async deleteTransactionInTx(tx: LegacyWalletTxHandle): Promise<void> { + async deleteTransactionInTx(tx: WalletDbTransaction): Promise<void> { const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; @@ -165,13 +165,13 @@ export class PeerPullCreditTransactionContext implements TransactionContext { * transaction item (e.g. if it was deleted). */ async lookupFullTransaction( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, ): Promise<Transaction | undefined> { - const pullCredit = await tx.wtx.getPeerPullCredit(this.pursePub); + const pullCredit = await tx.getPeerPullCredit(this.pursePub); if (!pullCredit) { return undefined; } - const ct = await tx.wtx.getContractTerms(pullCredit.contractTermsHash); + const ct = await tx.getContractTerms(pullCredit.contractTermsHash); checkDbInvariant(!!ct, `no contract terms for p2p push ${this.pursePub}`); const peerContractTerms = ct.contractTermsRaw; @@ -179,15 +179,15 @@ export class PeerPullCreditTransactionContext implements TransactionContext { let wsr: WalletWithdrawalGroup | undefined = undefined; let wsrOrt: WalletOperationRetry | undefined = undefined; if (pullCredit.withdrawalGroupId) { - wsr = await tx.wtx.getWithdrawalGroup(pullCredit.withdrawalGroupId); + wsr = await tx.getWithdrawalGroup(pullCredit.withdrawalGroupId); if (wsr) { const withdrawalOpId = TaskIdentifiers.forWithdrawal(wsr); - wsrOrt = await tx.wtx.getOperationRetry(withdrawalOpId); + wsrOrt = await tx.getOperationRetry(withdrawalOpId); } } const pullCreditOpId = TaskIdentifiers.forPeerPullPaymentInitiation(pullCredit); - let pullCreditOrt = await tx.wtx.getOperationRetry(pullCreditOpId); + let pullCreditOrt = await tx.getOperationRetry(pullCreditOpId); let kycUrl: string | undefined = undefined; if (pullCredit.kycAccessToken) { @@ -291,18 +291,18 @@ export class PeerPullCreditTransactionContext implements TransactionContext { } async getRecordHandle( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, ): Promise< [WalletPeerPullCredit | undefined, RecordHandle<WalletPeerPullCredit>] > { return getGenericRecordHandle<WalletPeerPullCredit>( this, - tx.wtx, - async () => tx.wtx.getPeerPullCredit(this.pursePub), + tx, + async () => tx.getPeerPullCredit(this.pursePub), async (r) => { - await tx.wtx.upsertPeerPullCredit(r); + await tx.upsertPeerPullCredit(r); }, - async () => tx.wtx.deletePeerPullCredit(this.pursePub), + async () => tx.deletePeerPullCredit(this.pursePub), (r) => computePeerPullCreditTransactionState(r), (r) => r.status, () => this.updateTransactionMeta(tx), @@ -311,13 +311,13 @@ export class PeerPullCreditTransactionContext implements TransactionContext { async userDeleteTransaction(): Promise<void> { const res = await this.wex.runLegacyWalletDbTx(async (tx) => { - await this.deleteTransactionInTx(tx); + await this.deleteTransactionInTx(tx.wtx); }); } async userSuspendTransaction(): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx); + const [rec, h] = await this.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -369,7 +369,7 @@ export class PeerPullCreditTransactionContext implements TransactionContext { ): Promise<void> { const { wex } = this; await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx); + const [rec, h] = await this.getRecordHandle(tx.wtx); if (rec?.status != fromSt) { return; } @@ -381,7 +381,7 @@ export class PeerPullCreditTransactionContext implements TransactionContext { async userFailTransaction(reason?: TalerErrorDetail): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx); + const [rec, h] = await this.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -418,7 +418,7 @@ export class PeerPullCreditTransactionContext implements TransactionContext { async userResumeTransaction(): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx); + const [rec, h] = await this.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -466,7 +466,7 @@ export class PeerPullCreditTransactionContext implements TransactionContext { async userAbortTransaction(reason?: TalerErrorDetail): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx); + const [rec, h] = await this.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -523,7 +523,7 @@ async function processPendingReady( case HttpStatusCode.Gone: // Exchange says that purse doesn't exist anymore => expired! await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -572,7 +572,7 @@ async function processPendingReady( }, }); await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -638,7 +638,7 @@ async function processPendingMergeKycRequired( checkProtocolInvariant(algoRes.requiresAuth != true); await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -669,7 +669,7 @@ async function processPeerPullCreditAbortingDeletePurse( case "ok": case HttpStatusCode.NotFound: await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -706,7 +706,7 @@ async function processPeerPullCreditWithdrawing( const wgId = pullIni.withdrawalGroupId; return await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (rec?.status !== PeerPullPaymentCreditStatus.PendingWithdrawing) { return TaskRunResult.backoff(); } @@ -771,7 +771,7 @@ async function processPeerPullCreditCreatePurse( exchangeBaseUrl: pullIni.exchangeBaseUrl, }); await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -887,7 +887,7 @@ async function processPeerPullCreditCreatePurse( } await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -992,7 +992,7 @@ async function processPeerPullCreditBalanceKyc( if (ret.result === "ok") { await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -1012,7 +1012,7 @@ async function processPeerPullCreditBalanceKyc( ret.walletKycStatus === ExchangeWalletKycStatus.Legi ) { await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -1040,7 +1040,7 @@ async function handlePeerPullCreditKycRequired( const ctx = new PeerPullCreditTransactionContext(wex, peerIni.pursePub); await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -1216,7 +1216,7 @@ export async function initiatePeerPullPayment( contractTermsRaw: contractTerms, h: hContractTerms, }); - const [oldRec, h] = await ctx.getRecordHandle(tx); + const [oldRec, h] = await ctx.getRecordHandle(tx.wtx); if (oldRec) { throw Error("peer-pull-credit record already exists"); } diff --git a/packages/taler-wallet-core/src/pay-peer-pull-debit.ts b/packages/taler-wallet-core/src/pay-peer-pull-debit.ts @@ -97,6 +97,7 @@ import { WalletExecutionContext, walletExchangeClient, } from "./wallet.js"; +import { WalletDbTransaction } from "./dbtx.js"; const logger = new Logger("pay-peer-pull-debit.ts"); @@ -121,12 +122,12 @@ export class PeerPullDebitTransactionContext implements TransactionContext { }); } - async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { - const rec = await tx.wtx.getPeerPullDebit(this.peerPullDebitId); + async updateTransactionMeta(tx: WalletDbTransaction): Promise<void> { + const rec = await tx.getPeerPullDebit(this.peerPullDebitId); if (rec == null) { - await tx.wtx.deleteTransactionMeta(this.transactionId); + await tx.deleteTransactionMeta(this.transactionId); } else { - await tx.wtx.upsertTransactionMeta({ + await tx.upsertTransactionMeta({ currency: Amounts.currencyOf(rec.amount), exchanges: [rec.exchangeBaseUrl], status: rec.status, @@ -143,15 +144,15 @@ export class PeerPullDebitTransactionContext implements TransactionContext { * transaction item (e.g. if it was deleted). */ async lookupFullTransaction( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, ): Promise<Transaction | undefined> { - const pi = await tx.wtx.getPeerPullDebit(this.peerPullDebitId); + const pi = await tx.getPeerPullDebit(this.peerPullDebitId); if (!pi) { return undefined; } - const ort = await tx.wtx.getOperationRetry(this.taskId); + const ort = await tx.getOperationRetry(this.taskId); const txState = computePeerPullDebitTransactionState(pi); - const ctRec = await tx.wtx.getContractTerms(pi.contractTermsHash); + const ctRec = await tx.getContractTerms(pi.contractTermsHash); checkDbInvariant(!!ctRec, `no contract terms for ${this.transactionId}`); const contractTerms = ctRec.contractTermsRaw; return { @@ -181,18 +182,18 @@ export class PeerPullDebitTransactionContext implements TransactionContext { } async getRecordHandle( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, ): Promise< [WalletPeerPullDebit | undefined, RecordHandle<WalletPeerPullDebit>] > { return getGenericRecordHandle<WalletPeerPullDebit>( this, - tx.wtx, - async () => tx.wtx.getPeerPullDebit(this.peerPullDebitId), + tx, + async () => tx.getPeerPullDebit(this.peerPullDebitId), async (r) => { - await tx.wtx.upsertPeerPullDebit(r); + await tx.upsertPeerPullDebit(r); }, - async () => tx.wtx.deletePeerPullDebit(this.peerPullDebitId), + async () => tx.deletePeerPullDebit(this.peerPullDebitId), (r) => computePeerPullDebitTransactionState(r), (r) => r.status, () => this.updateTransactionMeta(tx), @@ -205,7 +206,7 @@ export class PeerPullDebitTransactionContext implements TransactionContext { ): Promise<void> { const { wex } = this; await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx); + const [rec, h] = await this.getRecordHandle(tx.wtx); if (rec?.status != fromSt) { return; } @@ -218,7 +219,7 @@ export class PeerPullDebitTransactionContext implements TransactionContext { async expireTransaction(fromSt: PeerPullDebitRecordStatus): Promise<void> { const { wex } = this; await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx); + const [rec, h] = await this.getRecordHandle(tx.wtx); if (rec?.status != fromSt) { return; } @@ -229,11 +230,11 @@ export class PeerPullDebitTransactionContext implements TransactionContext { async userDeleteTransaction(): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - await this.deleteTransactionInTx(tx); + await this.deleteTransactionInTx(tx.wtx); }); } - async deleteTransactionInTx(tx: LegacyWalletTxHandle): Promise<void> { + async deleteTransactionInTx(tx: WalletDbTransaction): Promise<void> { const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; @@ -243,7 +244,7 @@ export class PeerPullDebitTransactionContext implements TransactionContext { async userSuspendTransaction(): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx); + const [rec, h] = await this.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -272,7 +273,7 @@ export class PeerPullDebitTransactionContext implements TransactionContext { async userResumeTransaction(): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx); + const [rec, h] = await this.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -298,7 +299,7 @@ export class PeerPullDebitTransactionContext implements TransactionContext { async userFailTransaction(reason?: TalerErrorDetail): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx); + const [rec, h] = await this.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -321,7 +322,7 @@ export class PeerPullDebitTransactionContext implements TransactionContext { async userAbortTransaction(reason?: TalerErrorDetail): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - const [pi, h] = await this.getRecordHandle(tx); + const [pi, h] = await this.getRecordHandle(tx.wtx); if (!pi) { return; } @@ -428,7 +429,7 @@ async function handlePurseCreationConflict( ); await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -479,7 +480,7 @@ async function processPeerPullDebitDialogProposed( if (isPurseDeposited(resp.body)) { logger.info("purse completed by another wallet"); await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); switch (rec?.status) { case PeerPullDebitRecordStatus.DialogProposed: rec.status = PeerPullDebitRecordStatus.Aborted; @@ -543,7 +544,7 @@ async function processPeerPullDebitPendingDeposit( const totalAmount = await getTotalPeerPaymentCost(wex, coins); return await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return TaskRunResult.finished(); } @@ -623,7 +624,7 @@ async function processPeerPullDebitPendingDeposit( } // All batches succeeded, we can transition! await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); switch (rec?.status) { case PeerPullDebitRecordStatus.PendingDeposit: rec.status = PeerPullDebitRecordStatus.Done; @@ -646,7 +647,7 @@ async function processPeerPullDebitAbortingRefresh( const ctx = new PeerPullDebitTransactionContext(wex, peerPullDebitId); await wex.runLegacyWalletDbTx(async (tx) => { const refreshGroup = await tx.wtx.getRefreshGroup(abortRefreshGroupId); - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -766,7 +767,7 @@ export async function confirmPeerPullDebit( const totalAmount = await getTotalPeerPaymentCost(wex, coins); await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -988,7 +989,7 @@ export async function preparePeerPullDebit( h: contractTermsHash, contractTermsRaw: contractTerms, }); - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (rec) { throw Error("peer-pull-debit record already exists"); } diff --git a/packages/taler-wallet-core/src/pay-peer-push-credit.ts b/packages/taler-wallet-core/src/pay-peer-push-credit.ts @@ -76,9 +76,7 @@ import { WalletWithdrawalGroup, WithdrawalRecordType, } from "./db-common.js"; -import { - WalletIndexedDbTransaction, -} from "./db-indexeddb.js"; +import { WalletIndexedDbTransaction } from "./db-indexeddb.js"; import { BalanceThresholdCheckResult, checkIncomingAmountLegalUnderKycBalanceThreshold, @@ -113,6 +111,7 @@ import { internalPrepareCreateWithdrawalGroup, waitWithdrawalFinal, } from "./withdraw.js"; +import { WalletDbTransaction } from "./dbtx.js"; const logger = new Logger("pay-peer-push-credit.ts"); @@ -134,12 +133,12 @@ export class PeerPushCreditTransactionContext implements TransactionContext { }); } - async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { - const rec = await tx.wtx.getPeerPushCredit(this.peerPushCreditId); + async updateTransactionMeta(tx: WalletDbTransaction): Promise<void> { + const rec = await tx.getPeerPushCredit(this.peerPushCreditId); if (rec == null) { - await tx.wtx.deleteTransactionMeta(this.transactionId); + await tx.deleteTransactionMeta(this.transactionId); } else { - await tx.wtx.upsertTransactionMeta({ + await tx.upsertTransactionMeta({ currency: Amounts.currencyOf(rec.estimatedAmountEffective), exchanges: [rec.exchangeBaseUrl], status: rec.status, @@ -156,9 +155,9 @@ export class PeerPushCreditTransactionContext implements TransactionContext { * transaction item (e.g. if it was deleted). */ async lookupFullTransaction( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, ): Promise<Transaction | undefined> { - const pushInc = await tx.wtx.getPeerPushCredit(this.peerPushCreditId); + const pushInc = await tx.getPeerPushCredit(this.peerPushCreditId); if (!pushInc) { return undefined; } @@ -166,16 +165,16 @@ export class PeerPushCreditTransactionContext implements TransactionContext { let wg: WalletWithdrawalGroup | undefined = undefined; let wgRetryRecord: WalletOperationRetry | undefined = undefined; if (pushInc.withdrawalGroupId) { - wg = await tx.wtx.getWithdrawalGroup(pushInc.withdrawalGroupId); + wg = await tx.getWithdrawalGroup(pushInc.withdrawalGroupId); if (wg) { const withdrawalOpId = TaskIdentifiers.forWithdrawal(wg); - wgRetryRecord = await tx.wtx.getOperationRetry(withdrawalOpId); + wgRetryRecord = await tx.getOperationRetry(withdrawalOpId); } } const pushIncOpId = TaskIdentifiers.forPeerPushCredit(pushInc); - const pushRetryRecord = await tx.wtx.getOperationRetry(pushIncOpId); + const pushRetryRecord = await tx.getOperationRetry(pushIncOpId); - const ct = await tx.wtx.getContractTerms(pushInc.contractTermsHash); + const ct = await tx.getContractTerms(pushInc.contractTermsHash); if (!ct) { throw Error("contract terms for P2P payment not found"); @@ -265,18 +264,18 @@ export class PeerPushCreditTransactionContext implements TransactionContext { } async getRecordHandle( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, ): Promise< [WalletPeerPushCredit | undefined, RecordHandle<WalletPeerPushCredit>] > { return getGenericRecordHandle<WalletPeerPushCredit>( this, - tx.wtx, - async () => tx.wtx.getPeerPushCredit(this.peerPushCreditId), + tx, + async () => tx.getPeerPushCredit(this.peerPushCreditId), async (r) => { - await tx.wtx.upsertPeerPushCredit(r); + await tx.upsertPeerPushCredit(r); }, - async () => tx.wtx.deletePeerPushCredit(this.peerPushCreditId), + async () => tx.deletePeerPushCredit(this.peerPushCreditId), (r) => computePeerPushCreditTransactionState(r), (r) => r.status, () => this.updateTransactionMeta(tx), @@ -285,11 +284,11 @@ export class PeerPushCreditTransactionContext implements TransactionContext { async userDeleteTransaction(): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => - this.deleteTransactionInTx(tx), + this.deleteTransactionInTx(tx.wtx), ); } - async deleteTransactionInTx(tx: LegacyWalletTxHandle): Promise<void> { + async deleteTransactionInTx(tx: WalletDbTransaction): Promise<void> { const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; @@ -307,7 +306,7 @@ export class PeerPushCreditTransactionContext implements TransactionContext { async userSuspendTransaction(): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx); + const [rec, h] = await this.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -349,7 +348,7 @@ export class PeerPushCreditTransactionContext implements TransactionContext { async userAbortTransaction(): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx); + const [rec, h] = await this.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -382,7 +381,7 @@ export class PeerPushCreditTransactionContext implements TransactionContext { async userResumeTransaction(): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx); + const [rec, h] = await this.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -428,7 +427,7 @@ export class PeerPushCreditTransactionContext implements TransactionContext { ): Promise<void> { const { wex } = this; await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx); + const [rec, h] = await this.getRecordHandle(tx.wtx); if (rec?.status != fromSt) { return; } @@ -440,7 +439,7 @@ export class PeerPushCreditTransactionContext implements TransactionContext { async userFailTransaction(reason?: TalerErrorDetail): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx); + const [rec, h] = await this.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -638,7 +637,7 @@ export async function preparePeerPushCredit( contractTermsRaw: dec.contractTerms, }); - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (rec) { throw Error("record already exists"); } @@ -730,7 +729,7 @@ async function processPeerPushDebitMergeKyc( checkProtocolInvariant(algoRes.requiresAuth != true); await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -757,7 +756,7 @@ async function transitionPeerPushCreditKycRequired( ); return await wex.runLegacyWalletDbTx(async (tx) => { - const [peerInc, h] = await ctx.getRecordHandle(tx); + const [peerInc, h] = await ctx.getRecordHandle(tx.wtx); if (!peerInc) { return TaskRunResult.finished(); } @@ -790,7 +789,7 @@ async function processPendingMerge( exchangeBaseUrl: peerInc.exchangeBaseUrl, }); await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -869,7 +868,7 @@ async function processPendingMerge( case HttpStatusCode.Conflict: // FIXME: Check signature. await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -888,7 +887,7 @@ async function processPendingMerge( return TaskRunResult.finished(); case HttpStatusCode.Gone: await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -930,7 +929,7 @@ async function processPendingMerge( }); await wex.runLegacyWalletDbTx(async (tx) => { - const [peerInc, h] = await ctx.getRecordHandle(tx); + const [peerInc, h] = await ctx.getRecordHandle(tx.wtx); if (!peerInc) { return undefined; } @@ -968,7 +967,7 @@ async function processPendingWithdrawing( ); const wgId = peerInc.withdrawalGroupId; return await wex.runLegacyWalletDbTx(async (tx) => { - const [ppi, h] = await ctx.getRecordHandle(tx); + const [ppi, h] = await ctx.getRecordHandle(tx.wtx); if (!ppi) { return TaskRunResult.finished(); } @@ -1044,7 +1043,7 @@ async function processPeerPushDebitDialogProposed( case HttpStatusCode.Gone: // Exchange says that purse doesn't exist anymore => expired! await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -1069,7 +1068,7 @@ async function processPeerPushDebitDialogProposed( if (isPurseMerged(resp.body)) { logger.info("purse completed by another wallet"); await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -1195,7 +1194,7 @@ async function processPeerPushCreditBalanceKyc( if (ret.result === "ok") { await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -1213,7 +1212,7 @@ async function processPeerPushCreditBalanceKyc( ret.walletKycStatus === ExchangeWalletKycStatus.Legi ) { await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -1280,7 +1279,7 @@ export async function confirmPeerPushCredit( } await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } diff --git a/packages/taler-wallet-core/src/pay-peer-push-debit.ts b/packages/taler-wallet-core/src/pay-peer-push-debit.ts @@ -106,6 +106,7 @@ import { walletExchangeClient, } from "./wallet.js"; import { updateWithdrawalDenomsForCurrency } from "./withdraw.js"; +import { WalletDbTransaction } from "./dbtx.js"; const logger = new Logger("pay-peer-push-debit.ts"); @@ -127,13 +128,13 @@ export class PeerPushDebitTransactionContext implements TransactionContext { }); } - async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { - const rec = await tx.wtx.getPeerPushDebit(this.pursePub); + async updateTransactionMeta(tx: WalletDbTransaction): Promise<void> { + const rec = await tx.getPeerPushDebit(this.pursePub); logger.info(`updating peer-push-debit meta for ${j2s(rec)}`); if (rec == null) { - await tx.wtx.deleteTransactionMeta(this.transactionId); + await tx.deleteTransactionMeta(this.transactionId); } else { - await tx.wtx.upsertTransactionMeta({ + await tx.upsertTransactionMeta({ currency: Amounts.currencyOf(rec.amount), exchanges: [rec.exchangeBaseUrl], status: rec.status, @@ -150,15 +151,15 @@ export class PeerPushDebitTransactionContext implements TransactionContext { * transaction item (e.g. if it was deleted). */ async lookupFullTransaction( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, ): Promise<Transaction | undefined> { - const pushDebitRec = await tx.wtx.getPeerPushDebit(this.pursePub); + const pushDebitRec = await tx.getPeerPushDebit(this.pursePub); if (pushDebitRec == null) { return undefined; } - const retryRec = await tx.wtx.getOperationRetry(this.taskId); + const retryRec = await tx.getOperationRetry(this.taskId); - const ctRec = await tx.wtx.getContractTerms(pushDebitRec.contractTermsHash); + const ctRec = await tx.getContractTerms(pushDebitRec.contractTermsHash); checkDbInvariant( !!ctRec, `no contract terms for p2p push ${this.pursePub}`, @@ -206,18 +207,18 @@ export class PeerPushDebitTransactionContext implements TransactionContext { } async getRecordHandle( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, ): Promise< [WalletPeerPushDebit | undefined, RecordHandle<WalletPeerPushDebit>] > { return getGenericRecordHandle<WalletPeerPushDebit>( this, - tx.wtx, - async () => tx.wtx.getPeerPushDebit(this.pursePub), + tx, + async () => tx.getPeerPushDebit(this.pursePub), async (r) => { - await tx.wtx.upsertPeerPushDebit(r); + await tx.upsertPeerPushDebit(r); }, - async () => tx.wtx.deletePeerPushDebit(this.pursePub), + async () => tx.deletePeerPushDebit(this.pursePub), (r) => computePeerPushDebitTransactionState(r), (r) => r.status, () => this.updateTransactionMeta(tx), @@ -226,11 +227,11 @@ export class PeerPushDebitTransactionContext implements TransactionContext { async userDeleteTransaction(): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - await this.deleteTransactionInTx(tx); + await this.deleteTransactionInTx(tx.wtx); }); } - async deleteTransactionInTx(tx: LegacyWalletTxHandle): Promise<void> { + async deleteTransactionInTx(tx: WalletDbTransaction): Promise<void> { const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; @@ -240,7 +241,7 @@ export class PeerPushDebitTransactionContext implements TransactionContext { async userSuspendTransaction(): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx); + const [rec, h] = await this.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -273,7 +274,7 @@ export class PeerPushDebitTransactionContext implements TransactionContext { async userAbortTransaction(reason?: TalerErrorDetail): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx); + const [rec, h] = await this.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -307,7 +308,7 @@ export class PeerPushDebitTransactionContext implements TransactionContext { async userResumeTransaction(): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx); + const [rec, h] = await this.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -344,7 +345,7 @@ export class PeerPushDebitTransactionContext implements TransactionContext { ): Promise<void> { const { wex } = this; await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx); + const [rec, h] = await this.getRecordHandle(tx.wtx); if (rec?.status != fromSt) { return; } @@ -356,7 +357,7 @@ export class PeerPushDebitTransactionContext implements TransactionContext { async userFailTransaction(reason?: TalerErrorDetail): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx); + const [rec, h] = await this.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -429,7 +430,7 @@ async function getDefaultPeerPushExpiration( exchangeBaseUrl: string, ): Promise<TalerProtocolDuration> { return await wex.runLegacyWalletDbTx(async (tx) => { - const ex = await getExchangeDetailsInTx(tx, exchangeBaseUrl); + const ex = await getExchangeDetailsInTx(tx.wtx, exchangeBaseUrl); return ex?.defaultPeerPushExpiration ?? fallbackDefaultPeerPushExpiration; }); } @@ -585,7 +586,7 @@ async function handlePurseCreationConflict( } await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -653,7 +654,7 @@ async function processPeerPushDebitCreateReserve( } return await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return TaskRunResult.backoff(); } @@ -778,7 +779,7 @@ async function processPeerPushDebitCreateReserve( case HttpStatusCode.Gone: // FIXME we need PeerPushDebitStatus.ExpiredDeletePurse await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -815,7 +816,7 @@ async function processPeerPushDebitCreateReserve( switch (resp.case) { case "ok": await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -833,7 +834,7 @@ async function processPeerPushDebitCreateReserve( case HttpStatusCode.Gone: // FIXME we need PeerPushDebitStatus.ExpiredDeletePurse await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -891,7 +892,7 @@ async function processPeerPushDebitAbortingDeletePurse( } await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -952,7 +953,7 @@ async function processPeerPushDebitReady( return TaskRunResult.longpollReturnedPending(); } else { await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -972,7 +973,7 @@ async function processPeerPushDebitReady( case HttpStatusCode.Gone: logger.info(`purse ${pursePub} is gone, aborting peer-push-debit`); await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -1132,7 +1133,7 @@ export async function initiatePeerPushDebit( exchangeBaseUrl = coinSelRes.result.exchangeBaseUrl; - const ex = await getExchangeDetailsInTx(tx, exchangeBaseUrl); + const ex = await getExchangeDetailsInTx(tx.wtx, exchangeBaseUrl); const myExpiration = req.partialContractTerms.purse_expiration ?? AbsoluteTime.toProtocolTimestamp( @@ -1193,7 +1194,7 @@ export async function initiatePeerPushDebit( h: hContractTerms, contractTermsRaw: contractTerms, }); - const [oldRec, h] = await ctx.getRecordHandle(tx); + const [oldRec, h] = await ctx.getRecordHandle(tx.wtx); if (oldRec) { throw Error("record for peer-push-debit already exists"); } diff --git a/packages/taler-wallet-core/src/recoup.ts b/packages/taler-wallet-core/src/recoup.ts @@ -70,6 +70,7 @@ import { getDenomInfo, } from "./wallet.js"; import { internalCreateWithdrawalGroup } from "./withdraw.js"; +import { WalletDbTransaction } from "./dbtx.js"; const logger = new Logger("operations/recoup.ts"); @@ -92,7 +93,7 @@ export async function putGroupAsFinished( } recoupGroup.recoupFinishedPerCoin[coinIdx] = true; await tx.wtx.upsertRecoupGroup(recoupGroup); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); } async function recoupRewardCoin( @@ -398,7 +399,7 @@ export async function processRecoupGroup( ); } await tx.wtx.upsertRecoupGroup(rg2); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); }); return TaskRunResult.finished(); } @@ -421,18 +422,18 @@ export class RecoupTransactionContext implements TransactionContext { }); } - async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { - const recoupRec = await tx.wtx.getRecoupGroup(this.recoupGroupId); + async updateTransactionMeta(tx: WalletDbTransaction): Promise<void> { + const recoupRec = await tx.getRecoupGroup(this.recoupGroupId); if (!recoupRec) { - await tx.wtx.deleteTransactionMeta(this.transactionId); + await tx.deleteTransactionMeta(this.transactionId); return; } - const exch = await tx.wtx.getExchange(recoupRec.exchangeBaseUrl); + const exch = await tx.getExchange(recoupRec.exchangeBaseUrl); if (!exch || !exch.detailsPointer) { - await tx.wtx.deleteTransactionMeta(this.transactionId); + await tx.deleteTransactionMeta(this.transactionId); return; } - await tx.wtx.upsertTransactionMeta({ + await tx.upsertTransactionMeta({ transactionId: this.transactionId, status: recoupRec.operationStatus, timestamp: recoupRec.timestampStarted, @@ -467,7 +468,7 @@ export class RecoupTransactionContext implements TransactionContext { async userDeleteTransaction(): Promise<void> { const res = await this.wex.runLegacyWalletDbTx(async (tx) => { - return this.deleteTransactionInTx(tx); + return this.deleteTransactionInTx(tx.wtx); }); for (const notif of res.notifs) { this.wex.ws.notify(notif); @@ -475,20 +476,20 @@ export class RecoupTransactionContext implements TransactionContext { } async deleteTransactionInTx( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, ): Promise<{ notifs: WalletNotification[] }> { const notifs: WalletNotification[] = []; - const rec = await tx.wtx.getRecoupGroup(this.recoupGroupId); + const rec = await tx.getRecoupGroup(this.recoupGroupId); if (!rec) { return { notifs }; } - await tx.wtx.deleteRecoupGroup(this.recoupGroupId); + await tx.deleteRecoupGroup(this.recoupGroupId); await this.updateTransactionMeta(tx); return { notifs }; } lookupFullTransaction( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, ): Promise<Transaction | undefined> { throw new Error("Method not implemented."); } @@ -525,7 +526,7 @@ export async function createRecoupGroup( } await tx.wtx.upsertRecoupGroup(recoupGroup); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); wex.taskScheduler.startShepherdTask(ctx.taskId); diff --git a/packages/taler-wallet-core/src/refresh.ts b/packages/taler-wallet-core/src/refresh.ts @@ -124,6 +124,7 @@ import { getWithdrawableDenomsTx, updateWithdrawalDenomsForExchange, } from "./withdraw.js"; +import { WalletDbTransaction } from "./dbtx.js"; /** Maximum number of new coins. */ const maxRefreshSessionSize = 64; @@ -148,13 +149,13 @@ export class RefreshTransactionContext implements TransactionContext { }); } - async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { - const rgRec = await tx.wtx.getRefreshGroup(this.refreshGroupId); + async updateTransactionMeta(tx: WalletDbTransaction): Promise<void> { + const rgRec = await tx.getRefreshGroup(this.refreshGroupId); if (!rgRec) { - await tx.wtx.deleteTransactionMeta(this.transactionId); + await tx.deleteTransactionMeta(this.transactionId); return; } - await tx.wtx.upsertTransactionMeta({ + await tx.upsertTransactionMeta({ transactionId: this.transactionId, status: rgRec.operationStatus, timestamp: rgRec.timestampCreated, @@ -170,15 +171,13 @@ export class RefreshTransactionContext implements TransactionContext { * transaction item (e.g. if it was deleted). */ async lookupFullTransaction( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, ): Promise<Transaction | undefined> { - const refreshGroupRecord = await tx.wtx.getRefreshGroup( - this.refreshGroupId, - ); + const refreshGroupRecord = await tx.getRefreshGroup(this.refreshGroupId); if (!refreshGroupRecord) { return undefined; } - const ort = await tx.wtx.getOperationRetry(this.taskId); + const ort = await tx.getOperationRetry(this.taskId); const inputAmount = Amounts.sumOrZero( refreshGroupRecord.currency, refreshGroupRecord.inputPerCoin, @@ -220,18 +219,18 @@ export class RefreshTransactionContext implements TransactionContext { } async getRecordHandle( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, ): Promise< [WalletRefreshGroup | undefined, RecordHandle<WalletRefreshGroup>] > { return getGenericRecordHandle<WalletRefreshGroup>( this, - tx.wtx, - async () => tx.wtx.getRefreshGroup(this.refreshGroupId), + tx, + async () => tx.getRefreshGroup(this.refreshGroupId), async (r) => { - await tx.wtx.upsertRefreshGroup(r); + await tx.upsertRefreshGroup(r); }, - async () => tx.wtx.deleteRefreshGroup(this.refreshGroupId), + async () => tx.deleteRefreshGroup(this.refreshGroupId), (r) => computeRefreshTransactionState(r), (r) => r.operationStatus, () => this.updateTransactionMeta(tx), @@ -240,11 +239,11 @@ export class RefreshTransactionContext implements TransactionContext { async userDeleteTransaction(): Promise<void> { const res = await this.wex.runLegacyWalletDbTx(async (tx) => { - return this.deleteTransactionInTx(tx); + return this.deleteTransactionInTx(tx.wtx); }); } - async deleteTransactionInTx(tx: LegacyWalletTxHandle): Promise<void> { + async deleteTransactionInTx(tx: WalletDbTransaction): Promise<void> { const [rg, h] = await this.getRecordHandle(tx); if (!rg) { logger.warn( @@ -252,17 +251,17 @@ export class RefreshTransactionContext implements TransactionContext { ); return; } - const sessions = await tx.wtx.getRefreshSessionsByGroup(rg.refreshGroupId); + const sessions = await tx.getRefreshSessionsByGroup(rg.refreshGroupId); for (const s of sessions) { - await tx.wtx.deleteRefreshSession(s.refreshGroupId, s.coinIndex); + await tx.deleteRefreshSession(s.refreshGroupId, s.coinIndex); } await h.update(undefined); - await tx.wtx.deleteRefreshGroup(rg.refreshGroupId); + await tx.deleteRefreshGroup(rg.refreshGroupId); } async userSuspendTransaction(): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx); + const [rec, h] = await this.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -295,7 +294,7 @@ export class RefreshTransactionContext implements TransactionContext { async userResumeTransaction(): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx); + const [rec, h] = await this.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -323,7 +322,7 @@ export class RefreshTransactionContext implements TransactionContext { async userFailTransaction(reason?: TalerErrorDetail): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx); + const [rec, h] = await this.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -821,7 +820,7 @@ async function handleRefreshMeltGone( }); await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rg, h] = await ctx.getRecordHandle(tx); + const [rg, h] = await ctx.getRecordHandle(tx.wtx); if (!rg) { return; } @@ -921,7 +920,7 @@ async function handleRefreshMeltConflict( // FIXME: If response seems wrong, report to auditor (in the future!); await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rg, h] = await ctx.getRecordHandle(tx); + const [rg, h] = await ctx.getRecordHandle(tx.wtx); if (!rg) { return; } @@ -976,7 +975,7 @@ async function handleRefreshMeltNotFound( throwUnexpectedRequestError(resp, errDetails); } await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rg, h] = await ctx.getRecordHandle(tx); + const [rg, h] = await ctx.getRecordHandle(tx.wtx); if (!rg) { return; } @@ -1176,7 +1175,7 @@ async function refreshReveal( } await wex.runLegacyWalletDbTx(async (tx) => { - const [rg, h] = await ctx.getRecordHandle(tx); + const [rg, h] = await ctx.getRecordHandle(tx.wtx); if (!rg) { logger.warn("no refresh session found"); return; @@ -1228,7 +1227,7 @@ async function handleRefreshRevealError( errDetails: TalerErrorDetail, ): Promise<void> { await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rg, h] = await ctx.getRecordHandle(tx); + const [rg, h] = await ctx.getRecordHandle(tx.wtx); if (!rg) { return; } @@ -1351,7 +1350,7 @@ export async function processRefreshGroup( // status of the whole refresh group. const didTransition: boolean = await wex.runLegacyWalletDbTx(async (tx) => { - const [rg, h] = await ctx.getRecordHandle(tx); + const [rg, h] = await ctx.getRecordHandle(tx.wtx); if (!rg) { return false; } @@ -1679,7 +1678,7 @@ export async function createRefreshGroup( const ctx = new RefreshTransactionContext(wex, refreshGroupId); await tx.wtx.upsertRefreshGroup(refreshGroup); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); const newTxState = computeRefreshTransactionState(refreshGroup); @@ -1713,7 +1712,7 @@ async function redenominateRefresh( logger.info(`re-denominating refresh group ${refreshGroupId}`); const exchanges = await wex.runLegacyWalletDbTx(async (tx) => { - const [rg, _] = await ctx.getRecordHandle(tx); + const [rg, _] = await ctx.getRecordHandle(tx.wtx); if (rg?.infoPerExchange) { return Object.keys(rg.infoPerExchange); } @@ -1726,7 +1725,7 @@ async function redenominateRefresh( } return await wex.runLegacyWalletDbTx(async (tx) => { - const [refreshGroup, h] = await ctx.getRecordHandle(tx); + const [refreshGroup, h] = await ctx.getRecordHandle(tx.wtx); if (!refreshGroup) { return TaskRunResult.finished(); } diff --git a/packages/taler-wallet-core/src/transactions.ts b/packages/taler-wallet-core/src/transactions.ts @@ -153,7 +153,7 @@ export async function getTransactionById( case TransactionType.Refund: { const ctx = await getContextForTransaction(wex, req.transactionId); const txDetails = await wex.runLegacyWalletDbTx(async (tx) => - ctx.lookupFullTransaction(tx, { + ctx.lookupFullTransaction(tx.wtx, { includeContractTerms: req.includeContractTerms, }), ); @@ -258,7 +258,7 @@ async function addFiltered( } if (checkFilterIncludes(req, mtx)) { const ctx = await getContextForTransaction(wex, mtx.transactionId); - const txDetails = await ctx.lookupFullTransaction(tx); + const txDetails = await ctx.lookupFullTransaction(tx.wtx); // FIXME: This means that in some cases we can return fewer transactions // than requested. if (!txDetails) { @@ -469,7 +469,7 @@ export async function getTransactions( } const ctx = await getContextForTransaction(wex, metaTx.transactionId); - const txDetails = await ctx.lookupFullTransaction(tx); + const txDetails = await ctx.lookupFullTransaction(tx.wtx); if (!txDetails) { continue; } @@ -546,52 +546,52 @@ export async function rematerializeTransactions( await tx.peerPushDebit.iter().forEachAsync(async (x) => { const ctx = new PeerPushDebitTransactionContext(wex, x.pursePub); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); }); await tx.peerPushCredit.iter().forEachAsync(async (x) => { const ctx = new PeerPushCreditTransactionContext(wex, x.peerPushCreditId); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); }); await tx.peerPullCredit.iter().forEachAsync(async (x) => { const ctx = new PeerPullCreditTransactionContext(wex, x.pursePub); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); }); await tx.peerPullDebit.iter().forEachAsync(async (x) => { const ctx = new PeerPullDebitTransactionContext(wex, x.peerPullDebitId); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); }); await tx.refundGroups.iter().forEachAsync(async (x) => { const ctx = new RefundTransactionContext(wex, x.refundGroupId); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); }); await tx.refreshGroups.iter().forEachAsync(async (x) => { const ctx = new RefreshTransactionContext(wex, x.refreshGroupId); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); }); await tx.withdrawalGroups.iter().forEachAsync(async (x) => { const ctx = new WithdrawTransactionContext(wex, x.withdrawalGroupId); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); }); await tx.denomLossEvents.iter().forEachAsync(async (x) => { const ctx = new DenomLossTransactionContext(wex, x.denomLossEventId); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); }); await tx.depositGroups.iter().forEachAsync(async (x) => { const ctx = new DepositTransactionContext(wex, x.depositGroupId); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); }); await tx.purchases.iter().forEachAsync(async (x) => { const ctx = new PayMerchantTransactionContext(wex, x.proposalId); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); }); } diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts @@ -1529,7 +1529,7 @@ async function handleGetDepositWireTypes( await wex.runLegacyWalletDbTx(async (tx) => { const exchanges = await tx.exchanges.getAll(); for (const exchange of exchanges) { - const det = await getExchangeDetailsInTx(tx, exchange.baseUrl); + const det = await getExchangeDetailsInTx(tx.wtx, exchange.baseUrl); if (!det) { continue; } @@ -1594,7 +1594,7 @@ async function handleGetDepositWireTypesForCurrency( await wex.runLegacyWalletDbTx(async (tx) => { const exchanges = await tx.exchanges.getAll(); for (const exchange of exchanges) { - const det = await getExchangeDetailsInTx(tx, exchange.baseUrl); + const det = await getExchangeDetailsInTx(tx.wtx, exchange.baseUrl); if (!det) { continue; } diff --git a/packages/taler-wallet-core/src/withdraw.ts b/packages/taler-wallet-core/src/withdraw.ts @@ -196,6 +196,7 @@ import { WalletExecutionContext, getDenomInfo, } from "./wallet.js"; +import { WalletDbTransaction } from "./dbtx.js"; /** * Logger for this file. @@ -367,9 +368,9 @@ export class WithdrawTransactionContext implements TransactionContext { * transaction item (e.g. if it was deleted). */ async lookupFullTransaction( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, ): Promise<Transaction | undefined> { - const withdrawalGroupRecord = await tx.wtx.getWithdrawalGroup( + const withdrawalGroupRecord = await tx.getWithdrawalGroup( this.withdrawalGroupId, ); if (!withdrawalGroupRecord) { @@ -406,7 +407,7 @@ export class WithdrawTransactionContext implements TransactionContext { } } - const ort = await tx.wtx.getOperationRetry(this.taskId); + const ort = await tx.getOperationRetry(this.taskId); switch (withdrawalGroupRecord.wgInfo.withdrawalType) { case WithdrawalRecordType.BankIntegrated: @@ -439,11 +440,11 @@ export class WithdrawTransactionContext implements TransactionContext { /** * Update the metadata of the transaction in the database. */ - async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { + async updateTransactionMeta(tx: WalletDbTransaction): Promise<void> { const ctx = this; - const wgRecord = await tx.wtx.getWithdrawalGroup(ctx.withdrawalGroupId); + const wgRecord = await tx.getWithdrawalGroup(ctx.withdrawalGroupId); if (!wgRecord) { - await tx.wtx.deleteTransactionMeta(ctx.transactionId); + await tx.deleteTransactionMeta(ctx.transactionId); return; } @@ -472,7 +473,7 @@ export class WithdrawTransactionContext implements TransactionContext { if (!currency) { return; } - await tx.wtx.upsertTransactionMeta({ + await tx.upsertTransactionMeta({ transactionId: ctx.transactionId, status: wgRecord.status, timestamp: wgRecord.timestampStart, @@ -484,18 +485,18 @@ export class WithdrawTransactionContext implements TransactionContext { } async getRecordHandle( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, ): Promise< [WalletWithdrawalGroup | undefined, RecordHandle<WalletWithdrawalGroup>] > { return getGenericRecordHandle<WalletWithdrawalGroup>( this, - tx.wtx, - async () => tx.wtx.getWithdrawalGroup(this.withdrawalGroupId), + tx, + async () => tx.getWithdrawalGroup(this.withdrawalGroupId), async (r) => { - await tx.wtx.upsertWithdrawalGroup(r); + await tx.upsertWithdrawalGroup(r); }, - async () => tx.wtx.deleteWithdrawalGroup(this.withdrawalGroupId), + async () => tx.deleteWithdrawalGroup(this.withdrawalGroupId), (r) => computeWithdrawalTransactionStatus(r), (r) => r.status, () => this.updateTransactionMeta(tx), @@ -504,18 +505,18 @@ export class WithdrawTransactionContext implements TransactionContext { async userDeleteTransaction(): Promise<void> { await this.wex.runLegacyWalletDbTx(async (tx) => { - return this.deleteTransactionInTx(tx); + return this.deleteTransactionInTx(tx.wtx); }); } - async deleteTransactionInTx(tx: LegacyWalletTxHandle): Promise<void> { + async deleteTransactionInTx(tx: WalletDbTransaction): Promise<void> { const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; } - const planchets = await tx.wtx.getPlanchetsByGroup(rec.withdrawalGroupId); + const planchets = await tx.getPlanchetsByGroup(rec.withdrawalGroupId); for (const p of planchets) { - await tx.wtx.deletePlanchet(p.coinPub); + await tx.deletePlanchet(p.coinPub); } await h.update(undefined); } @@ -523,7 +524,7 @@ export class WithdrawTransactionContext implements TransactionContext { async userSuspendTransaction(): Promise<void> { const { withdrawalGroupId } = this; await this.wex.runLegacyWalletDbTx(async (tx) => { - const [wg, h] = await this.getRecordHandle(tx); + const [wg, h] = await this.getRecordHandle(tx.wtx); if (!wg) { logger.warn(`withdrawal group ${withdrawalGroupId} not found`); return; @@ -562,7 +563,7 @@ export class WithdrawTransactionContext implements TransactionContext { async userAbortTransaction(reason?: TalerErrorDetail): Promise<void> { const { withdrawalGroupId } = this; await this.wex.runLegacyWalletDbTx(async (tx) => { - const [wg, h] = await this.getRecordHandle(tx); + const [wg, h] = await this.getRecordHandle(tx.wtx); if (!wg) { logger.warn(`withdrawal group ${withdrawalGroupId} not found`); return; @@ -619,7 +620,7 @@ export class WithdrawTransactionContext implements TransactionContext { async userResumeTransaction(): Promise<void> { const { withdrawalGroupId } = this; await this.wex.runLegacyWalletDbTx(async (tx) => { - const [wg, h] = await this.getRecordHandle(tx); + const [wg, h] = await this.getRecordHandle(tx.wtx); if (!wg) { logger.warn(`withdrawal group ${withdrawalGroupId} not found`); return; @@ -658,7 +659,7 @@ export class WithdrawTransactionContext implements TransactionContext { async userFailTransaction(reason?: TalerErrorDetail): Promise<void> { const { withdrawalGroupId } = this; await this.wex.runLegacyWalletDbTx(async (tx) => { - const [wg, h] = await this.getRecordHandle(tx); + const [wg, h] = await this.getRecordHandle(tx.wtx); if (!wg) { logger.warn(`withdrawal group ${withdrawalGroupId} not found`); return; @@ -957,7 +958,7 @@ async function processWithdrawalGroupRedenominate( withdrawalGroup.withdrawalGroupId, ); return await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); switch (rec?.status) { case WithdrawalGroupStatus.PendingRedenominate: break; @@ -1034,7 +1035,7 @@ async function processWithdrawalGroupBalanceKyc( if (ret.result === "ok") { return await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [wg, h] = await ctx.getRecordHandle(tx); + const [wg, h] = await ctx.getRecordHandle(tx.wtx); if (!wg) { return TaskRunResult.finished(); } @@ -1055,7 +1056,7 @@ async function processWithdrawalGroupBalanceKyc( ret.walletKycStatus === ExchangeWalletKycStatus.Legi ) { return await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [wg, h] = await ctx.getRecordHandle(tx); + const [wg, h] = await ctx.getRecordHandle(tx.wtx); if (!wg) { return TaskRunResult.finished(); } @@ -1085,7 +1086,7 @@ async function transitionSimple( to: WithdrawalGroupStatus, ): Promise<void> { await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); switch (rec?.status) { case from: { rec.status = to; @@ -1479,7 +1480,7 @@ async function transitionKycRequired( const ctx = new WithdrawTransactionContext(wex, withdrawalGroupId); await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [wg2, h] = await ctx.getRecordHandle(tx); + const [wg2, h] = await ctx.getRecordHandle(tx.wtx); if (!wg2) { return; } @@ -2191,7 +2192,7 @@ async function processQueryReserve( } return await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [wg, h] = await ctx.getRecordHandle(tx); + const [wg, h] = await ctx.getRecordHandle(tx.wtx); if (!wg) { logger.warn(`withdrawal group ${withdrawalGroupId} not found`); return TaskRunResult.finished(); @@ -2265,7 +2266,7 @@ async function processWithdrawalGroupAbortingBank( logger.info(`abort response status: ${abortResp.status}`); await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [wg, h] = await ctx.getRecordHandle(tx); + const [wg, h] = await ctx.getRecordHandle(tx.wtx); if (!wg) { return; } @@ -2335,7 +2336,7 @@ async function processWithdrawalGroupPendingKyc( checkProtocolInvariant(algoRes.requiresAuth != true); await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -2535,7 +2536,7 @@ async function processWithdrawalGroupPendingReady( if (withdrawalGroup.denomsSel.selectedDenoms.length === 0) { logger.warn("Finishing empty withdrawal group (no denoms)"); await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; } @@ -2570,7 +2571,7 @@ async function processWithdrawalGroupPendingReady( exchangeBaseUrl, }); await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [wg, h] = await ctx.getRecordHandle(tx); + const [wg, h] = await ctx.getRecordHandle(tx.wtx); if (!wg) { return; } @@ -2700,7 +2701,7 @@ async function processWithdrawalGroupPendingReady( const maxReportedErrors = 5; const res = await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [wg, h] = await ctx.getRecordHandle(tx); + const [wg, h] = await ctx.getRecordHandle(tx.wtx); if (!wg) { return; } @@ -2766,7 +2767,7 @@ async function startRedenomination( forceUnavailable: true, }); return await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); switch (rec?.status) { case WithdrawalGroupStatus.PendingReady: break; @@ -3185,7 +3186,7 @@ async function registerReserveWithBank( ); return await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [r, h] = await ctx.getRecordHandle(tx); + const [r, h] = await ctx.getRecordHandle(tx.wtx); if (!r) { return TaskRunResult.finished(); } @@ -3226,7 +3227,7 @@ async function transitionBankAborted( ): Promise<TaskRunResult> { logger.info("bank aborted the withdrawal"); return await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [r, h] = await ctx.getRecordHandle(tx); + const [r, h] = await ctx.getRecordHandle(tx.wtx); if (!r) { return TaskRunResult.finished(); } @@ -3414,7 +3415,7 @@ async function processReserveBankStatus( } return await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [r, h] = await ctx.getRecordHandle(tx); + const [r, h] = await ctx.getRecordHandle(tx.wtx); if (!r) { return TaskRunResult.finished(); } @@ -3586,7 +3587,7 @@ export async function internalPerformCreateWithdrawalGroup( wex, withdrawalGroup.withdrawalGroupId, ); - const [existingWg, h] = await ctx.getRecordHandle(tx); + const [existingWg, h] = await ctx.getRecordHandle(tx.wtx); if (existingWg) { return { withdrawalGroup: existingWg, @@ -3658,7 +3659,7 @@ export async function internalCreateWithdrawalGroup( ); const res = await wex.runLegacyWalletDbTx(async (tx) => { const res = await internalPerformCreateWithdrawalGroup(wex, tx, prep); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx.wtx); return res; }); return res.withdrawalGroup; @@ -3981,7 +3982,7 @@ export async function confirmWithdrawal( } await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx); + const [rec, h] = await ctx.getRecordHandle(tx.wtx); if (!rec) { return; }