taler-typescript-core

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

commit 26d56707db71c6bbce527e817f4ecfef29ccb916
parent 3c9ddf6e764aa5da62ea5deff35ac215510e455d
Author: Florian Dold <dold@taler.net>
Date:   Sun, 19 Jul 2026 02:22:06 +0200

db: retire the legacy transaction handle

Diffstat:
Mpackages/taler-wallet-core/src/coinSelection.ts | 88+++++++++++++++++++++++++++++++++++--------------------------------------------
Mpackages/taler-wallet-core/src/common.ts | 20++++++++------------
Mpackages/taler-wallet-core/src/db-common.ts | 27+++++++++++++++++++++++++++
Mpackages/taler-wallet-core/src/db-indexeddb.ts | 30++----------------------------
Mpackages/taler-wallet-core/src/dbtx-indexeddb.ts | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mpackages/taler-wallet-core/src/dbtx.ts | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mpackages/taler-wallet-core/src/deposits.ts | 162++++++++++++++++++++++++++++++++++++++-----------------------------------------
Mpackages/taler-wallet-core/src/donau.ts | 52+++++++++++++++++++++++++---------------------------
Mpackages/taler-wallet-core/src/exchanges.ts | 465++++++++++++++++++++++++++++++++++++++-----------------------------------------
Mpackages/taler-wallet-core/src/instructedAmountConversion.ts | 16++++++----------
Mpackages/taler-wallet-core/src/pay-merchant.ts | 349+++++++++++++++++++++++++++++++++++++++----------------------------------------
Mpackages/taler-wallet-core/src/pay-peer-common.ts | 25+++++++++++--------------
Mpackages/taler-wallet-core/src/pay-peer-pull-credit.ts | 94++++++++++++++++++++++++++++++++++++++-----------------------------------------
Mpackages/taler-wallet-core/src/pay-peer-pull-debit.ts | 89+++++++++++++++++++++++++++++++++++++------------------------------------------
Mpackages/taler-wallet-core/src/pay-peer-push-credit.ts | 130+++++++++++++++++++++++++++++++++++++------------------------------------------
Mpackages/taler-wallet-core/src/pay-peer-push-debit.ts | 82++++++++++++++++++++++++++++++++++++++-----------------------------------------
Mpackages/taler-wallet-core/src/preset-exchanges.ts | 6+++---
Mpackages/taler-wallet-core/src/recoup.ts | 82++++++++++++++++++++++++++++++++++++++-----------------------------------------
Mpackages/taler-wallet-core/src/refresh.ts | 213+++++++++++++++++++++++++++++++++++++++----------------------------------------
Mpackages/taler-wallet-core/src/shepherd.ts | 5++---
Mpackages/taler-wallet-core/src/transactions.ts | 34+++++++++++++++++-----------------
Mpackages/taler-wallet-core/src/wallet.ts | 196+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Mpackages/taler-wallet-core/src/withdraw.ts | 261++++++++++++++++++++++++++++++++++++++-----------------------------------------
23 files changed, 1292 insertions(+), 1256 deletions(-)

diff --git a/packages/taler-wallet-core/src/coinSelection.ts b/packages/taler-wallet-core/src/coinSelection.ts @@ -23,7 +23,6 @@ /** * Imports. */ -import { GlobalIDB } from "@gnu-taler/idb-bridge"; import { AbsoluteTime, AccountRestriction, @@ -69,11 +68,8 @@ import { ExchangeDetails, getExchangeDetailsInTx, } from "./exchanges.js"; -import { - getDenomInfo, - LegacyWalletTxHandle, - WalletExecutionContext, -} from "./wallet.js"; +import { getDenomInfo, WalletExecutionContext } from "./wallet.js"; +import { WalletDbTransaction } from "./dbtx.js"; const logger = new Logger("coinSelection.ts"); @@ -193,7 +189,7 @@ export type SelectPayCoinsResult = async function internalSelectPayCoins( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, req: SelectPayCoinRequestNg, includePendingCoins: boolean, ): Promise< @@ -282,7 +278,7 @@ async function internalSelectPayCoins( export async function selectPayCoinsInTx( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, req: SelectPayCoinRequestNg, ): Promise<SelectPayCoinsResult> { if (logger.shouldLogTrace()) { @@ -349,14 +345,14 @@ export async function selectPayCoins( wex: WalletExecutionContext, req: SelectPayCoinRequestNg, ): Promise<SelectPayCoinsResult> { - return await wex.runLegacyWalletDbTx(async (tx) => { + return await wex.runWalletDbTx(async (tx) => { return selectPayCoinsInTx(wex, tx, req); }); } async function maybeRepairCoinSelection( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, prevPayCoins: PreviousPayCoins, coinRes: SelectedCoin[], tally: CoinSelectionTally, @@ -366,7 +362,7 @@ async function maybeRepairCoinSelection( ): Promise<void> { // Look at existing pay coin selection and tally up for (const prev of prevPayCoins) { - const coin = await tx.wtx.getCoin(prev.coinPub); + const coin = await tx.getCoin(prev.coinPub); if (!coin) { continue; } @@ -404,7 +400,7 @@ async function maybeRepairCoinSelection( * as not enough coins are actually available. */ async function assembleSelectPayCoinsSuccessResult( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, finalSel: SelResult, coinRes: SelectedCoin[], tally: CoinSelectionTally, @@ -412,7 +408,7 @@ async function assembleSelectPayCoinsSuccessResult( for (const dph of Object.keys(finalSel)) { const selInfo = finalSel[dph]; const numRequested = selInfo.contributions.length; - const coins = await tx.wtx.getFreshCoinsByDenomAndAge( + const coins = await tx.getFreshCoinsByDenomAndAge( selInfo.exchangeBaseUrl, selInfo.denomPubHash, selInfo.maxAge, @@ -494,11 +490,11 @@ function getHint( export async function reportInsufficientBalanceDetails( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, req: ReportInsufficientBalanceRequest, ): Promise<PaymentInsufficientBalanceDetails> { const currency = Amounts.currencyOf(req.instructedAmount); - const details = await getPaymentBalanceDetailsInTx(wex, tx.wtx, { + const details = await getPaymentBalanceDetailsInTx(wex, tx, { restrictSenderScope: undefined, restrictReceiverExchanges: req.restrictExchanges, restrictWireMethods: req.wireMethod ? [req.wireMethod] : undefined, @@ -507,14 +503,14 @@ export async function reportInsufficientBalanceDetails( depositPaytoUri: req.depositPaytoUri, }); const perExchange: PaymentInsufficientBalanceDetails["perExchange"] = {}; - const exchanges = await tx.wtx.getExchanges(); + const exchanges = await tx.getExchanges(); for (const exch of exchanges) { if (!exch.detailsPointer) { continue; } let missingGlobalFees = false; - const exchWire = await getExchangeDetailsInTx(tx.wtx, exch.baseUrl); + const exchWire = await getExchangeDetailsInTx(tx, exch.baseUrl); if (!exchWire) { // No wire details about the exchange known, skip! continue; @@ -527,7 +523,7 @@ export async function reportInsufficientBalanceDetails( // Do not report anything for an exchange with a different currency. continue; } - const exchDet = await getPaymentBalanceDetailsInTx(wex, tx.wtx, { + const exchDet = await getPaymentBalanceDetailsInTx(wex, tx, { restrictSenderScope: { type: ScopeType.Exchange, currency, @@ -948,7 +944,7 @@ export interface PayCoinCandidates { async function selectPayCandidates( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, req: SelectPayCandidatesRequest, ): Promise<PayCoinCandidates> { // FIXME: Use the existing helper (from balance.ts) to @@ -956,17 +952,14 @@ async function selectPayCandidates( logger.shouldLogTrace() && logger.trace(`selecting available coin candidates for ${j2s(req)}`); const denoms: AvailableCoinsOfDenom[] = []; - const exchanges = await tx.wtx.getExchanges(); + const exchanges = await tx.getExchanges(); const wfPerExchange: Record<string, AmountJson> = {}; const depositRestrictions: Record< string, Record<string, AccountRestriction[]> > = {}; for (const exchange of exchanges) { - const exchangeDetails = await getExchangeDetailsInTx( - tx.wtx, - exchange.baseUrl, - ); + const exchangeDetails = await getExchangeDetailsInTx(tx, exchange.baseUrl); // Exchange has same currency if (exchangeDetails?.currency !== req.currency) { logger.shouldLogTrace() && @@ -1023,12 +1016,11 @@ async function selectPayCandidates( ageLower = req.requiredMinimumAge; } - const myExchangeCoins = - await tx.wtx.getCoinAvailabilityByExchangeAndAgeRange( - exchangeDetails.exchangeBaseUrl, - ageLower, - ageUpper, - ); + const myExchangeCoins = await tx.getCoinAvailabilityByExchangeAndAgeRange( + exchangeDetails.exchangeBaseUrl, + ageLower, + ageUpper, + ); if (logger.shouldLogTrace()) { logger.trace( @@ -1043,7 +1035,7 @@ async function selectPayCandidates( // FIXME: Should we exclude denominations that are // not spendable anymore? for (const coinAvail of myExchangeCoins) { - const denom = await tx.wtx.getDenomination( + const denom = await tx.getDenomination( coinAvail.exchangeBaseUrl, coinAvail.denomPubHash, ); @@ -1143,7 +1135,7 @@ export interface PeerCoinSelectionRequest { export async function computeCoinSelMaxExpirationDate( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, selectedDenom: SelResult, ): Promise<TalerProtocolTimestamp> { let minAutorefreshExecuteThreshold = TalerProtocolTimestamp.never(); @@ -1211,7 +1203,7 @@ function getGlobalFees( async function internalSelectPeerCoins( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, req: PeerCoinSelectionRequest, exch: ExchangeDetails, includePendingCoins: boolean, @@ -1264,7 +1256,7 @@ async function internalSelectPeerCoins( export async function selectPeerCoinsInTx( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, req: PeerCoinSelectionRequest, ): Promise<SelectPeerCoinsResult> { const instructedAmount = req.instructedAmount; @@ -1276,13 +1268,13 @@ export async function selectPeerCoinsInTx( ); } - const exchanges = await tx.wtx.getExchanges(); + const exchanges = await tx.getExchanges(); const currency = Amounts.currencyOf(instructedAmount); for (const exch of exchanges) { if (exch.detailsPointer?.currency !== currency) { continue; } - const exchWire = await getExchangeDetailsInTx(tx.wtx, exch.baseUrl); + const exchWire = await getExchangeDetailsInTx(tx, exch.baseUrl); if (!exchWire) { continue; } @@ -1353,11 +1345,9 @@ export async function selectPeerCoins( wex: WalletExecutionContext, req: PeerCoinSelectionRequest, ): Promise<SelectPeerCoinsResult> { - return await wex.runLegacyWalletDbTx( - async (tx): Promise<SelectPeerCoinsResult> => { - return selectPeerCoinsInTx(wex, tx, req); - }, - ); + return await wex.runWalletDbTx(async (tx): Promise<SelectPeerCoinsResult> => { + return selectPeerCoinsInTx(wex, tx, req); + }); } function getMaxDepositAmountForAvailableCoins( @@ -1400,14 +1390,14 @@ function getMaxDepositAmountForAvailableCoins( export async function getExchangesForDepositInTx( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, req: { restrictScope?: ScopeInfo; currency: string }, ): Promise<Exchange[]> { logger.trace(`getting exchanges for deposit ${j2s(req)}`); const exchangeInfos: Exchange[] = []; - const allExchanges = await tx.wtx.getExchanges(); + const allExchanges = await tx.getExchanges(); for (const e of allExchanges) { - const details = await getExchangeDetailsInTx(tx.wtx, e.baseUrl); + const details = await getExchangeDetailsInTx(tx, e.baseUrl); if (!details) { logger.trace(`skipping ${e.baseUrl}, no details`); continue; @@ -1443,7 +1433,7 @@ export async function getExchangesForDeposit( wex: WalletExecutionContext, req: { restrictScope?: ScopeInfo; currency: string }, ): Promise<Exchange[]> { - return await wex.runLegacyWalletDbTx(async (tx) => { + return await wex.runWalletDbTx(async (tx) => { return await getExchangesForDepositInTx(wex, tx, req); }); } @@ -1459,7 +1449,7 @@ export async function getMaxDepositAmount( req: GetMaxDepositAmountRequest, ): Promise<GetMaxDepositAmountResponse> { logger.trace(`getting max deposit amount for: ${j2s(req)}`); - return await wex.runLegacyWalletDbTx( + return await wex.runWalletDbTx( async (tx): Promise<GetMaxDepositAmountResponse> => { let restrictWireMethod: string | undefined = undefined; const exchangeInfos: Exchange[] = await getExchangesForDepositInTx( @@ -1532,16 +1522,16 @@ export async function getMaxPeerPushDebitAmount( ): Promise<GetMaxPeerPushDebitAmountResponse> { logger.trace(`getting max deposit amount for: ${j2s(req)}`); - return await wex.runLegacyWalletDbTx( + return await wex.runWalletDbTx( async (tx): Promise<GetMaxPeerPushDebitAmountResponse> => { let result: GetMaxDepositAmountResponse | undefined = undefined; const currency = req.currency; - const exchanges = await tx.wtx.getExchanges(); + const exchanges = await tx.getExchanges(); for (const exch of exchanges) { if (exch.detailsPointer?.currency !== currency) { continue; } - const exchWire = await getExchangeDetailsInTx(tx.wtx, exch.baseUrl); + const exchWire = await getExchangeDetailsInTx(tx, exch.baseUrl); if (!exchWire) { continue; } diff --git a/packages/taler-wallet-core/src/common.ts b/packages/taler-wallet-core/src/common.ts @@ -85,11 +85,7 @@ import { WalletDbTransaction } from "./dbtx.js"; import { ReadyExchangeSummary } from "./exchanges.js"; import { createRefreshGroup } from "./refresh.js"; import { BalanceEffect, applyNotifyTransition } from "./transactions.js"; -import { - LegacyWalletTxHandle, - WalletExecutionContext, - getDenomInfo, -} from "./wallet.js"; +import { WalletExecutionContext, getDenomInfo } from "./wallet.js"; const logger = new Logger("operations/common.ts"); @@ -182,7 +178,7 @@ export async function makeCoinAvailable( */ export async function spendCoins( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, csi: CoinsSpendInfo, ): Promise<void> { if (csi.coinPubs.length != csi.contributions.length) { @@ -193,7 +189,7 @@ export async function spendCoins( } let refreshCoinPubs: CoinRefreshRequest[] = []; for (let i = 0; i < csi.coinPubs.length; i++) { - const coin = await tx.wtx.getCoin(csi.coinPubs[i]); + const coin = await tx.getCoin(csi.coinPubs[i]); if (!coin) { throw Error("coin allocated for payment doesn't exist anymore"); } @@ -207,7 +203,7 @@ export async function spendCoins( !!denom, `denomination of a coin is missing hash: ${coin.denomPubHash}`, ); - const coinAvailability = await tx.wtx.getCoinAvailability( + const coinAvailability = await tx.getCoinAvailability( coin.exchangeBaseUrl, coin.denomPubHash, coin.maxAge, @@ -239,7 +235,7 @@ export async function spendCoins( coinAvailability.visibleCoinCount--; } } - let histEntry: WalletCoinHistory | undefined = await tx.wtx.getCoinHistory( + let histEntry: WalletCoinHistory | undefined = await tx.getCoinHistory( coin.coinPub, ); if (!histEntry) { @@ -253,9 +249,9 @@ export async function spendCoins( transactionId: csi.transactionId, amount: Amounts.stringify(contrib), }); - await tx.wtx.upsertCoinHistory(histEntry); - await tx.wtx.upsertCoin(coin); - await tx.wtx.upsertCoinAvailability(coinAvailability); + await tx.upsertCoinHistory(histEntry); + await tx.upsertCoin(coin); + await tx.upsertCoinAvailability(coinAvailability); } await createRefreshGroup( diff --git a/packages/taler-wallet-core/src/db-common.ts b/packages/taler-wallet-core/src/db-common.ts @@ -1394,6 +1394,33 @@ export interface WalletGlobalCurrencyExchange { exchangeMasterPub: string; } +/** + * User accounts + */ +export interface WalletBankAccount { + /** + * Opaque identifier for the bank account. + */ + bankAccountId: string; + + /** + * Payto URI of the bank account. + */ + paytoUri: string; + + /** + * User-defined label for the account. + */ + label: string | undefined; + + currencies: string[] | undefined; + + /** + * FIXME: Provide more info here. + */ + kycCompleted: boolean; +} + export interface WalletWithdrawCoinSource { type: CoinSourceType.Withdraw; diff --git a/packages/taler-wallet-core/src/db-indexeddb.ts b/packages/taler-wallet-core/src/db-indexeddb.ts @@ -149,6 +149,7 @@ import { WalletExchangeBaseUrlFixup, WalletExchangeMigrationLog, WalletGlobalCurrencyAuditor, + WalletBankAccount, WalletGlobalCurrencyExchange, WalletToken, TokenFamilyInfo, @@ -1148,7 +1149,7 @@ export const WalletIndexedDbStoresV1 = { ), bankAccountsV2: describeStore( "bankAccountsV2", - describeContents<BankAccountsRecord>({ + describeContents<WalletBankAccount>({ keyPath: "bankAccountId", versionAdded: 14, }), @@ -1271,33 +1272,6 @@ export interface FixupRecord { fixupName: string; } -/** - * User accounts - */ -export interface BankAccountsRecord { - /** - * Opaque identifier for the bank account. - */ - bankAccountId: string; - - /** - * Payto URI of the bank account. - */ - paytoUri: string; - - /** - * User-defined label for the account. - */ - label: string | undefined; - - currencies: string[] | undefined; - - /** - * FIXME: Provide more info here. - */ - kycCompleted: boolean; -} - export interface MetaConfigRecord { key: string; value: any; diff --git a/packages/taler-wallet-core/src/dbtx-indexeddb.ts b/packages/taler-wallet-core/src/dbtx-indexeddb.ts @@ -83,6 +83,7 @@ import { WalletExchangeMigrationLog, WalletGlobalCurrencyExchange, WalletGlobalCurrencyAuditor, + WalletBankAccount, WalletExchangeDetails, } from "./db-common.js"; import type {} from "./db-indexeddb.js"; @@ -106,6 +107,10 @@ export class IdbWalletTransaction implements WalletDbTransaction { this.tx = tx; } + scheduleOnCommit(f: () => void): void { + this.tx._util.scheduleOnCommit(f); + } + /** * Bound as an instance property, not a prototype method: call sites pass * this around unbound (e.g. applyNotifyTransition(tx.notify, ...)), which @@ -373,6 +378,38 @@ export class IdbWalletTransaction implements WalletDbTransaction { ); } + async listGlobalCurrencyExchanges(): Promise<WalletGlobalCurrencyExchange[]> { + return await this.tx.globalCurrencyExchanges.iter().toArray(); + } + + async addGlobalCurrencyExchange( + rec: WalletGlobalCurrencyExchange, + ): Promise<void> { + await this.tx.globalCurrencyExchanges.put(rec); + } + + async deleteGlobalCurrencyExchange(id: number): Promise<void> { + await this.tx.globalCurrencyExchanges.delete(id); + } + + async listGlobalCurrencyAuditors(): Promise<WalletGlobalCurrencyAuditor[]> { + return await this.tx.globalCurrencyAuditors.iter().toArray(); + } + + async addGlobalCurrencyAuditor( + rec: WalletGlobalCurrencyAuditor, + ): Promise<void> { + await this.tx.globalCurrencyAuditors.put(rec); + } + + async deleteGlobalCurrencyAuditor(id: number): Promise<void> { + await this.tx.globalCurrencyAuditors.delete(id); + } + + async deleteCurrencyInfo(scopeInfo: ScopeInfo): Promise<void> { + await this.tx.currencyInfo.delete(stringifyScopeInfo(scopeInfo)); + } + async getGlobalCurrencyExchange( currency: string, exchangeBaseUrl: string, @@ -433,6 +470,34 @@ export class IdbWalletTransaction implements WalletDbTransaction { ); } + async listBankAccounts(): Promise<WalletBankAccount[]> { + return await this.tx.bankAccountsV2.iter().toArray(); + } + + async getBankAccount( + bankAccountId: string, + ): Promise<WalletBankAccount | undefined> { + return await this.tx.bankAccountsV2.get(bankAccountId); + } + + async deleteBankAccount(bankAccountId: string): Promise<void> { + await this.tx.bankAccountsV2.delete(bankAccountId); + } + + async getBankAccountByPaytoUri( + paytoUri: string, + ): Promise<WalletBankAccount | undefined> { + return await this.tx.bankAccountsV2.indexes.byPaytoUri.get(paytoUri); + } + + async upsertBankAccount(rec: WalletBankAccount): Promise<void> { + await this.tx.bankAccountsV2.put(rec); + } + + async listAllCoins(): Promise<WalletCoin[]> { + return await this.tx.coins.iter().toArray(); + } + async getCoinsByExchange(exchangeBaseUrl: string): Promise<WalletCoin[]> { const tx = this.tx; return await tx.coins.indexes.byBaseUrl.getAll(exchangeBaseUrl); diff --git a/packages/taler-wallet-core/src/dbtx.ts b/packages/taler-wallet-core/src/dbtx.ts @@ -82,6 +82,7 @@ import { WalletExchangeMigrationLog, WalletGlobalCurrencyExchange, WalletGlobalCurrencyAuditor, + WalletBankAccount, WalletExchangeDetails, } from "./db-common.js"; export interface GetCurrencyInfoDbResult { @@ -261,6 +262,28 @@ export interface WalletDbTransaction { exchangeBaseUrl: string, ): Promise<WalletWithdrawalGroup[]>; + /** List every globally-trusted exchange entry. */ + listGlobalCurrencyExchanges(): Promise<WalletGlobalCurrencyExchange[]>; + + /** Add a globally-trusted exchange entry. The row id is generated. */ + addGlobalCurrencyExchange(rec: WalletGlobalCurrencyExchange): Promise<void>; + + /** Remove a globally-trusted exchange entry by row id. */ + deleteGlobalCurrencyExchange(id: number): Promise<void>; + + /** List every globally-trusted auditor entry. */ + listGlobalCurrencyAuditors(): Promise<WalletGlobalCurrencyAuditor[]>; + + /** Add a globally-trusted auditor entry. The row id is generated. */ + addGlobalCurrencyAuditor(rec: WalletGlobalCurrencyAuditor): Promise<void>; + + /** Remove a globally-trusted auditor entry by row id. */ + deleteGlobalCurrencyAuditor(id: number): Promise<void>; + + /** Delete the currency info stored for a scope. */ + deleteCurrencyInfo(scopeInfo: ScopeInfo): Promise<void>; + + /** Get the global-currency entry for an exchange, if it is trusted globally. */ getGlobalCurrencyExchange( currency: string, exchangeBaseUrl: string, @@ -295,6 +318,27 @@ export interface WalletDbTransaction { ageUpper: number, ): Promise<WalletCoinAvailability[]>; + /** List every known bank account. */ + listBankAccounts(): Promise<WalletBankAccount[]>; + + /** Get a known bank account by its ID. */ + getBankAccount(bankAccountId: string): Promise<WalletBankAccount | undefined>; + + /** Delete a known bank account by its ID. */ + deleteBankAccount(bankAccountId: string): Promise<void>; + + /** Get a known bank account by its payto URI. */ + getBankAccountByPaytoUri( + paytoUri: string, + ): Promise<WalletBankAccount | undefined>; + + /** Create or update a known bank account. */ + upsertBankAccount(rec: WalletBankAccount): Promise<void>; + + /** List every coin in the wallet. */ + listAllCoins(): Promise<WalletCoin[]>; + + /** Get all coins issued by an exchange. */ getCoinsByExchange(exchangeBaseUrl: string): Promise<WalletCoin[]>; countCoinsByExchange(exchangeBaseUrl: string): Promise<number>; @@ -847,5 +891,18 @@ export interface WalletDbTransaction { currency: string, ): Promise<ScopeInfo>; + /** + * Run a callback once this transaction has committed. + * + * Used to trigger work that must not run inside the transaction, such as + * starting or stopping a shepherd task. + */ + scheduleOnCommit(f: () => void): void; + + /** + * Emit a wallet notification. + * + * Bound to the instance, so it is safe to pass around unbound. + */ notify(notif: WalletNotification): void; } diff --git a/packages/taler-wallet-core/src/deposits.ts b/packages/taler-wallet-core/src/deposits.ts @@ -158,11 +158,7 @@ import { isUnsuccessfulTransaction, parseTransactionIdentifier, } from "./transactions.js"; -import { - LegacyWalletTxHandle, - WalletExecutionContext, - getDenomInfo, -} from "./wallet.js"; +import { WalletExecutionContext, getDenomInfo } from "./wallet.js"; import { augmentPaytoUrisForKycTransfer } from "./withdraw.js"; import { WalletDbTransaction } from "./dbtx.js"; @@ -368,8 +364,8 @@ export class DepositTransactionContext implements TransactionContext { } async userDeleteTransaction(): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - await this.deleteTransactionInTx(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + await this.deleteTransactionInTx(tx); }); } @@ -383,8 +379,8 @@ 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.wtx); + await wex.runWalletDbTx(async (tx) => { + const [dg, h] = await this.getRecordHandle(tx); if (!dg) { logger.warn( `can't suspend deposit group, depositGroupId=${depositGroupId} not found`, @@ -440,8 +436,8 @@ export class DepositTransactionContext implements TransactionContext { async userAbortTransaction(reason?: TalerErrorDetail): Promise<void> { const { wex, depositGroupId, transactionId, taskId: retryTag } = this; - await wex.runLegacyWalletDbTx(async (tx) => { - const dg = await tx.wtx.getDepositGroup(depositGroupId); + await wex.runWalletDbTx(async (tx) => { + const dg = await tx.getDepositGroup(depositGroupId); if (!dg) { logger.warn( `can't suspend deposit group, depositGroupId=${depositGroupId} not found`, @@ -459,8 +455,8 @@ export class DepositTransactionContext implements TransactionContext { case DepositOperationStatus.SuspendedDeposit: { dg.operationStatus = DepositOperationStatus.Aborting; dg.abortReason = reason; - await tx.wtx.upsertDepositGroup(dg); - await this.updateTransactionMeta(tx.wtx); + await tx.upsertDepositGroup(dg); + await this.updateTransactionMeta(tx); applyNotifyTransition(tx.notify, transactionId, { oldTxState: oldState, newTxState: computeDepositTransactionStatus(dg), @@ -493,8 +489,8 @@ export class DepositTransactionContext implements TransactionContext { async userResumeTransaction(): Promise<void> { const { wex, depositGroupId, transactionId, taskId: retryTag } = this; - await wex.runLegacyWalletDbTx(async (tx) => { - const dg = await tx.wtx.getDepositGroup(depositGroupId); + await wex.runWalletDbTx(async (tx) => { + const dg = await tx.getDepositGroup(depositGroupId); if (!dg) { logger.warn( `can't resume deposit group, depositGroupId=${depositGroupId} not found`, @@ -545,8 +541,8 @@ export class DepositTransactionContext implements TransactionContext { return undefined; } dg.operationStatus = newOpStatus; - await tx.wtx.upsertDepositGroup(dg); - await this.updateTransactionMeta(tx.wtx); + await tx.upsertDepositGroup(dg); + await this.updateTransactionMeta(tx); applyNotifyTransition(tx.notify, transactionId, { oldTxState: oldState, newTxState: computeDepositTransactionStatus(dg), @@ -560,8 +556,8 @@ export class DepositTransactionContext implements TransactionContext { async userFailTransaction(reason?: TalerErrorDetail): Promise<void> { const { wex, depositGroupId, transactionId, taskId } = this; - await wex.runLegacyWalletDbTx(async (tx) => { - const dg = await tx.wtx.getDepositGroup(depositGroupId); + await wex.runWalletDbTx(async (tx) => { + const dg = await tx.getDepositGroup(depositGroupId); if (!dg) { logger.warn( `can't cancel aborting deposit group, depositGroupId=${depositGroupId} not found`, @@ -602,8 +598,8 @@ export class DepositTransactionContext implements TransactionContext { } dg.operationStatus = newState; dg.failReason = reason; - await tx.wtx.upsertDepositGroup(dg); - await this.updateTransactionMeta(tx.wtx); + await tx.upsertDepositGroup(dg); + await this.updateTransactionMeta(tx); applyNotifyTransition(tx.notify, transactionId, { oldTxState: oldState, newTxState: computeDepositTransactionStatus(dg), @@ -849,8 +845,8 @@ async function refundDepositGroup( break; default: { const coinPub = payCoinSelection.coinPubs[i]; - const coinExchange = await wex.runLegacyWalletDbTx(async (tx) => { - const coinRecord = await tx.wtx.getCoin(coinPub); + const coinExchange = await wex.runWalletDbTx(async (tx) => { + const coinRecord = await tx.getCoin(coinPub); checkDbInvariant(!!coinRecord, `coin ${coinPub} not found in DB`); return coinRecord.exchangeBaseUrl; }); @@ -898,15 +894,13 @@ async function refundDepositGroup( } // FIXME: Handle case where refund request needs to be tried again newTxPerCoin[i] = newStatus; - await wex.runLegacyWalletDbTx(async (tx) => { - const newDg = await tx.wtx.getDepositGroup( - depositGroup.depositGroupId, - ); + await wex.runWalletDbTx(async (tx) => { + const newDg = await tx.getDepositGroup(depositGroup.depositGroupId); if (!newDg || !newDg.statusPerCoin) { return; } newDg.statusPerCoin[i] = newStatus; - await tx.wtx.upsertDepositGroup(newDg); + await tx.upsertDepositGroup(newDg); newTxPerCoin = [...newDg.statusPerCoin]; }); break; @@ -916,8 +910,8 @@ async function refundDepositGroup( // Check if we are done trying to refund. - const res = await wex.runLegacyWalletDbTx(async (tx) => { - const newDg = await tx.wtx.getDepositGroup(depositGroup.depositGroupId); + const res = await wex.runWalletDbTx(async (tx) => { + const newDg = await tx.getDepositGroup(depositGroup.depositGroupId); if (!newDg || !newDg.statusPerCoin) { return; } @@ -956,8 +950,8 @@ async function refundDepositGroup( }), ); newDg.abortRefreshGroupId = refreshRes.refreshGroupId; - await tx.wtx.upsertDepositGroup(newDg); - await ctx.updateTransactionMeta(tx.wtx); + await tx.upsertDepositGroup(newDg); + await ctx.updateTransactionMeta(tx); return { refreshRes }; }); @@ -989,8 +983,8 @@ async function waitForRefreshOnDepositGroup( // Wait for the refresh transaction to be in a final state. await genericWaitForState(wex, { async checkState() { - return await wex.runLegacyWalletDbTx(async (tx) => { - const refreshGroup = await tx.wtx.getRefreshGroup(abortRefreshGroupId); + return await wex.runWalletDbTx(async (tx) => { + const refreshGroup = await tx.getRefreshGroup(abortRefreshGroupId); switch (refreshGroup?.operationStatus) { case undefined: case RefreshOperationStatus.Failed: @@ -1008,8 +1002,8 @@ async function waitForRefreshOnDepositGroup( }, }); - const didTransition = await wex.runLegacyWalletDbTx(async (tx) => { - const refreshGroup = await tx.wtx.getRefreshGroup(abortRefreshGroupId); + const didTransition = await wex.runWalletDbTx(async (tx) => { + const refreshGroup = await tx.getRefreshGroup(abortRefreshGroupId); let newOpState: DepositOperationStatus | undefined; switch (refreshGroup?.operationStatus) { case undefined: { @@ -1027,7 +1021,7 @@ async function waitForRefreshOnDepositGroup( default: return false; } - const [newDg, h] = await ctx.getRecordHandle(tx.wtx); + const [newDg, h] = await ctx.getRecordHandle(tx); if (!newDg) { return false; } @@ -1187,8 +1181,8 @@ async function processDepositGroupPendingKyc( // Now store the result. - return await wex.runLegacyWalletDbTx(async (tx) => { - const [newDg, h] = await ctx.getRecordHandle(tx.wtx); + return await wex.runWalletDbTx(async (tx) => { + const [newDg, h] = await ctx.getRecordHandle(tx); if (!newDg) { return TaskRunResult.finished(); } @@ -1223,13 +1217,13 @@ async function processDepositGroupPendingKyc( } async function tryFindAccountKeypair( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, exchangeBaseUrl: string, ): Promise<EddsaKeyPairStrings | undefined> { let candidateTimestamp: AbsoluteTime | undefined = undefined; let candidateRes: EddsaKeyPairStrings | undefined = undefined; const allWithdrawalRecs = - await tx.wtx.getWithdrawalGroupsByExchange(exchangeBaseUrl); + await tx.getWithdrawalGroupsByExchange(exchangeBaseUrl); // We only consider withdrawals that were actual // withdrawals from a bank account. const withdrawalRecs: WalletWithdrawalGroup[] = []; @@ -1310,8 +1304,8 @@ async function provideDepositAccountKeypair( wex: WalletExecutionContext, exchangeBaseUrl: string, ): Promise<EddsaKeyPairStrings> { - const existingPair = await wex.runLegacyWalletDbTx(async (tx) => { - const exchange = await tx.wtx.getExchange(exchangeBaseUrl); + const existingPair = await wex.runWalletDbTx(async (tx) => { + const exchange = await tx.getExchange(exchangeBaseUrl); if (!exchange) { throw Error("exchange for deposit not found anymore"); } @@ -1325,7 +1319,7 @@ async function provideDepositAccountKeypair( if (res != null) { exchange.currentAccountPriv = res.priv; exchange.currentAccountPub = res.pub; - await tx.wtx.upsertExchange(exchange); + await tx.upsertExchange(exchange); } return res; }); @@ -1333,14 +1327,14 @@ async function provideDepositAccountKeypair( return existingPair; } const newPair = await wex.cryptoApi.createEddsaKeypair({}); - await wex.runLegacyWalletDbTx(async (tx) => { - const exchange = await tx.wtx.getExchange(exchangeBaseUrl); + await wex.runWalletDbTx(async (tx) => { + const exchange = await tx.getExchange(exchangeBaseUrl); if (!exchange) { throw Error("exchange for deposit not found anymore"); } exchange.currentAccountPriv = newPair.priv; exchange.currentAccountPub = newPair.pub; - await tx.wtx.upsertExchange(exchange); + await tx.upsertExchange(exchange); }); return newPair; } @@ -1375,8 +1369,8 @@ async function transitionToKycRequired( transferExpiry = res.transferExpiry; } - await wex.runLegacyWalletDbTx(async (tx) => { - const [dg, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [dg, h] = await ctx.getRecordHandle(tx); if (!dg) { return undefined; } @@ -1460,8 +1454,8 @@ async function processDepositGroupTrack( for (let i = 0; i < statusPerCoin.length; i++) { const coinPub = payCoinSelection.coinPubs[i]; // FIXME: Make the URL part of the coin selection? - const exchangeBaseUrl = await wex.runLegacyWalletDbTx(async (tx) => { - const coinRecord = await tx.wtx.getCoin(coinPub); + const exchangeBaseUrl = await wex.runWalletDbTx(async (tx) => { + const coinRecord = await tx.getCoin(coinPub); checkDbInvariant(!!coinRecord, `coin ${coinPub} not found in DB`); return coinRecord.exchangeBaseUrl; }); @@ -1532,8 +1526,8 @@ async function processDepositGroupTrack( } if (updatedTxStatus !== undefined) { - await wex.runLegacyWalletDbTx(async (tx) => { - const dg = await tx.wtx.getDepositGroup(depositGroupId); + await wex.runWalletDbTx(async (tx) => { + const dg = await tx.getDepositGroup(depositGroupId); if (!dg) { return; } @@ -1558,16 +1552,16 @@ async function processDepositGroupTrack( dg.trackingState[newWiredCoin.id] = newWiredCoin.value; } - await tx.wtx.upsertDepositGroup(dg); - await ctx.updateTransactionMeta(tx.wtx); + await tx.upsertDepositGroup(dg); + await ctx.updateTransactionMeta(tx); }); } } let allWired = true; - await wex.runLegacyWalletDbTx(async (tx) => { - const [dg, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [dg, h] = await ctx.getRecordHandle(tx); if (!dg) { return undefined; } @@ -1583,8 +1577,8 @@ async function processDepositGroupTrack( if (allWired) { dg.timestampFinished = timestampPreciseToDb(TalerPreciseTimestamp.now()); dg.operationStatus = DepositOperationStatus.Finished; - await tx.wtx.upsertDepositGroup(dg); - await ctx.updateTransactionMeta(tx.wtx); + await tx.upsertDepositGroup(dg); + await ctx.updateTransactionMeta(tx); } await h.update(dg); }); @@ -1610,8 +1604,8 @@ async function doCoinSelection( throw Error("assertion failed"); } - const transitionDone = await wex.runLegacyWalletDbTx(async (tx) => { - const dg = await tx.wtx.getDepositGroup(depositGroupId); + const transitionDone = await wex.runWalletDbTx(async (tx) => { + const dg = await tx.getDepositGroup(depositGroupId); if (!dg) { return false; } @@ -1619,7 +1613,7 @@ async function doCoinSelection( return false; } - const contractTermsRec = tx.wtx.getContractTerms( + const contractTermsRec = tx.getContractTerms( depositGroup.contractTermsHash, ); if (!contractTermsRec) { @@ -1665,8 +1659,8 @@ async function doCoinSelection( dg.statusPerCoin = payCoinSel.coinSel.coins.map( () => DepositElementStatus.DepositPending, ); - await tx.wtx.upsertDepositGroup(dg); - await ctx.updateTransactionMeta(tx.wtx); + await tx.upsertDepositGroup(dg); + await ctx.updateTransactionMeta(tx); await spendCoins(wex, tx, { transactionId: ctx.transactionId, coinPubs: dg.payCoinSelection.coinPubs, @@ -1775,8 +1769,8 @@ async function submitDepositBatch( await readSuccessResponseJsonOrThrow(httpResp, codecForBatchDepositSuccess()); - await wex.runLegacyWalletDbTx(async (tx) => { - const dg = await tx.wtx.getDepositGroup(depositGroupId); + await wex.runWalletDbTx(async (tx) => { + const dg = await tx.getDepositGroup(depositGroupId); if (!dg) { return; } @@ -1788,10 +1782,10 @@ async function submitDepositBatch( switch (coinStatus) { case DepositElementStatus.DepositPending: dg.statusPerCoin[batchIndex] = DepositElementStatus.Tracking; - await tx.wtx.upsertDepositGroup(dg); + await tx.upsertDepositGroup(dg); } } - await ctx.updateTransactionMeta(tx.wtx); + await ctx.updateTransactionMeta(tx); }); return null; @@ -1811,8 +1805,8 @@ async function processDepositGroupPendingDeposit( ): Promise<TaskRunResult> { logger.info("processing deposit group in pending(deposit)"); const depositGroupId = depositGroup.depositGroupId; - const contractTermsRec = await wex.runLegacyWalletDbTx(async (tx) => { - return tx.wtx.getContractTerms(depositGroup.contractTermsHash); + const contractTermsRec = await wex.runWalletDbTx(async (tx) => { + return tx.getContractTerms(depositGroup.contractTermsHash); }); if (!contractTermsRec) { throw Error("contract terms for deposit not found in database"); @@ -1831,8 +1825,8 @@ async function processDepositGroupPendingDeposit( return await doCoinSelection(ctx, depositGroup, contractTerms); } - await wex.runLegacyWalletDbTx(async (tx) => { - const dg = await tx.wtx.getDepositGroup(depositGroup.depositGroupId); + await wex.runWalletDbTx(async (tx) => { + const dg = await tx.getDepositGroup(depositGroup.depositGroupId); if (!dg) { logger.warn(`deposit group ${depositGroup.depositGroupId} not found`); return; @@ -1840,7 +1834,7 @@ async function processDepositGroupPendingDeposit( dg.timestampLastDepositAttempt = timestampPreciseToDb( TalerPreciseTimestamp.now(), ); - await tx.wtx.upsertDepositGroup(dg); + await tx.upsertDepositGroup(dg); }); // FIXME: Cache these! @@ -1897,8 +1891,8 @@ async function processDepositGroupPendingDeposit( } } - await wex.runLegacyWalletDbTx(async (tx) => { - const [dg, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [dg, h] = await ctx.getRecordHandle(tx); if (!dg) { return undefined; } @@ -1919,8 +1913,8 @@ export async function processDepositGroup( return TaskRunResult.networkRequired(); } - const depositGroup = await wex.runLegacyWalletDbTx(async (tx) => { - return await tx.wtx.getDepositGroup(depositGroupId); + const depositGroup = await wex.runWalletDbTx(async (tx) => { + return await tx.getDepositGroup(depositGroupId); }); if (!depositGroup) { logger.warn(`deposit group ${depositGroupId} not found`); @@ -2335,8 +2329,8 @@ export async function createDepositGroup( const ctx = new DepositTransactionContext(wex, depositGroupId); const transactionId = ctx.transactionId; - const newTxState = await wex.runLegacyWalletDbTx(async (tx) => { - const [oldDg, h] = await ctx.getRecordHandle(tx.wtx); + const newTxState = await wex.runWalletDbTx(async (tx) => { + const [oldDg, h] = await ctx.getRecordHandle(tx); if (oldDg != null) { throw Error("deposit group already exists"); } @@ -2350,7 +2344,7 @@ export async function createDepositGroup( refreshReason: RefreshReason.PayDeposit, }); } - await tx.wtx.upsertContractTerms({ + await tx.upsertContractTerms({ contractTermsRaw: contractTerms, h: contractTermsHash, }); @@ -2380,7 +2374,7 @@ async function getCounterpartyEffectiveDepositAmount( const fees: AmountJson[] = []; const exchangeSet: Set<string> = new Set(); - await wex.runLegacyWalletDbTx(async (tx) => { + await wex.runWalletDbTx(async (tx) => { for (let i = 0; i < pcs.length; i++) { const denom = await getDenomInfo( wex, @@ -2397,7 +2391,7 @@ async function getCounterpartyEffectiveDepositAmount( } for (const exchangeUrl of exchangeSet.values()) { - const exchangeDetails = await getExchangeDetailsInTx(tx.wtx, exchangeUrl); + const exchangeDetails = await getExchangeDetailsInTx(tx, exchangeUrl); if (!exchangeDetails) { continue; } @@ -2435,7 +2429,7 @@ async function getTotalFeesForDepositAmount( const refreshFee: AmountJson[] = []; const exchangeSet: Set<string> = new Set(); - await wex.runLegacyWalletDbTx(async (tx) => { + await wex.runWalletDbTx(async (tx) => { for (let i = 0; i < pcs.length; i++) { const denom = await getDenomInfo( wex, @@ -2454,7 +2448,7 @@ async function getTotalFeesForDepositAmount( } for (const exchangeUrl of exchangeSet.values()) { - const exchangeDetails = await getExchangeDetailsInTx(tx.wtx, exchangeUrl); + const exchangeDetails = await getExchangeDetailsInTx(tx, exchangeUrl); if (!exchangeDetails) { continue; } diff --git a/packages/taler-wallet-core/src/donau.ts b/packages/taler-wallet-core/src/donau.ts @@ -94,15 +94,15 @@ async function submitDonationReceipts( wex: WalletExecutionContext, donauBaseUrl?: string, ): Promise<void> { - const receipts = await wex.runLegacyWalletDbTx(async (tx) => { + const receipts = await wex.runWalletDbTx(async (tx) => { let receipts; if (donauBaseUrl) { - receipts = await tx.wtx.getDonationReceiptsByStatusAndDonau( + receipts = await tx.getDonationReceiptsByStatusAndDonau( DonationReceiptStatus.Pending, donauBaseUrl, ); } else { - receipts = await tx.wtx.getDonationReceiptsByStatus( + receipts = await tx.getDonationReceiptsByStatus( DonationReceiptStatus.Pending, ); } @@ -129,8 +129,8 @@ async function submitDonationReceipts( }), ); - await wex.runLegacyWalletDbTx(async (tx) => { - let donauSummary = await tx.wtx.getDonationSummary( + await wex.runWalletDbTx(async (tx) => { + let donauSummary = await tx.getDonationSummary( group.donauBaseUrl, group.year, group.currency, @@ -145,14 +145,14 @@ async function submitDonationReceipts( donauSummary.legalDomain = conf.legal_domain; for (const bi of group.receipts) { - const receipt = await tx.wtx.getDonationReceipt(bi.udiNonce); + const receipt = await tx.getDonationReceipt(bi.udiNonce); if (!receipt) { continue; } switch (receipt.status) { case DonationReceiptStatus.Pending: { receipt.status = DonationReceiptStatus.DoneSubmitted; - await tx.wtx.upsertDonationReceipt(receipt); + await tx.upsertDonationReceipt(receipt); donauSummary.amountReceiptsSubmitted = Amounts.stringify( Amounts.add(donauSummary.amountReceiptsSubmitted, receipt.value) .amount, @@ -162,7 +162,7 @@ async function submitDonationReceipts( } } - await tx.wtx.upsertDonationSummary(donauSummary); + await tx.upsertDonationSummary(donauSummary); tx.notify({ type: NotificationType.BalanceChange, hintTransactionId: "donau", @@ -175,15 +175,15 @@ async function fetchDonauStatements( wex: WalletExecutionContext, donauBaseUrl?: string, ): Promise<DonauStatementItem[]> { - const receipts = await wex.runLegacyWalletDbTx(async (tx) => { + const receipts = await wex.runWalletDbTx(async (tx) => { let receipts; if (donauBaseUrl) { - receipts = await tx.wtx.getDonationReceiptsByStatusAndDonau( + receipts = await tx.getDonationReceiptsByStatusAndDonau( DonationReceiptStatus.DoneSubmitted, donauBaseUrl, ); } else { - receipts = await tx.wtx.getDonationReceiptsByStatus( + receipts = await tx.getDonationReceiptsByStatus( DonationReceiptStatus.DoneSubmitted, ); } @@ -281,8 +281,8 @@ export async function handleSetDonau( idHasher.update(stringToBytes(req.taxPayerId + "\0")); idHasher.update(stringToBytes(encodeCrock(salt) + "\0")); const saltedId = idHasher.finish(); - await wex.runLegacyWalletDbTx(async (tx) => { - const oldRec = await tx.wtx.getConfig(ConfigRecordKey.DonauConfig); + await wex.runWalletDbTx(async (tx) => { + const oldRec = await tx.getConfig(ConfigRecordKey.DonauConfig); if ( oldRec && oldRec.value.donauBaseUrl === req.donauBaseUrl && @@ -291,7 +291,7 @@ export async function handleSetDonau( // Be idempotent, reuse old salt. return; } - await tx.wtx.upsertConfig({ + await tx.upsertConfig({ key: ConfigRecordKey.DonauConfig, value: { donauBaseUrl: req.donauBaseUrl, @@ -394,8 +394,8 @@ export async function generateDonauPlanchets( wex: WalletExecutionContext, proposalId: string, ): Promise<void> { - const res = await wex.runLegacyWalletDbTx(async (tx) => { - const rec = await tx.wtx.getPurchase(proposalId); + const res = await wex.runWalletDbTx(async (tx) => { + const rec = await tx.getPurchase(proposalId); if (!rec) { return undefined; } @@ -519,19 +519,19 @@ export async function generateDonauPlanchets( logger.trace(`donau planchets: ${j2s(donauPlanchets)}`); - await wex.runLegacyWalletDbTx(async (tx) => { - const rec = await tx.wtx.getPurchase(proposalId); + await wex.runWalletDbTx(async (tx) => { + const rec = await tx.getPurchase(proposalId); if (!rec) { return undefined; } - const existingPlanchets = await tx.wtx.countDonationPlanchetsByProposal( + const existingPlanchets = await tx.countDonationPlanchetsByProposal( rec.proposalId, ); if (existingPlanchets > 0) { return; } for (const dp of donauPlanchets) { - await tx.wtx.upsertDonationPlanchet(dp); + await tx.upsertDonationPlanchet(dp); } }); } @@ -612,18 +612,16 @@ export async function acceptDonauBlindSigs( }); } - await wex.runLegacyWalletDbTx(async (tx) => { + await wex.runWalletDbTx(async (tx) => { for (let i = 0; i < donauBlindedSigs.length; i++) { const myPlanchet = donauPlanchets[i]; - const existingReceipt = await tx.wtx.getDonationReceipt( - myPlanchet.udiNonce, - ); + const existingReceipt = await tx.getDonationReceipt(myPlanchet.udiNonce); if (existingReceipt) { continue; } const year = myPlanchet.donationYear; const currency = Amounts.currencyOf(myPlanchet.value); - let donauSummary = await tx.wtx.getDonationSummary( + let donauSummary = await tx.getDonationSummary( donauBaseUrl, year, Amounts.currencyOf(myPlanchet.value), @@ -642,7 +640,7 @@ export async function acceptDonauBlindSigs( Amounts.add(donauSummary.amountReceiptsAvailable, myPlanchet.value) .amount, ); - await tx.wtx.upsertDonationReceipt({ + await tx.upsertDonationReceipt({ donationUnitSig: sigs[i], donationUnitPubHash: myPlanchet.donationUnitPubHash, donauBaseUrl: myPlanchet.donauBaseUrl, @@ -657,7 +655,7 @@ export async function acceptDonauBlindSigs( value: myPlanchet.value, }); donauSummary.legalDomain = conf.legal_domain; - await tx.wtx.upsertDonationSummary(donauSummary); + await tx.upsertDonationSummary(donauSummary); tx.notify({ type: NotificationType.BalanceChange, hintTransactionId: "donau", diff --git a/packages/taler-wallet-core/src/exchanges.ts b/packages/taler-wallet-core/src/exchanges.ts @@ -184,7 +184,6 @@ import { import { WALLET_EXCHANGE_PROTOCOL_VERSION } from "./versions.js"; import { InternalWalletState, - LegacyWalletTxHandle, WalletExecutionContext, walletExchangeClient, } from "./wallet.js"; @@ -309,11 +308,11 @@ export async function getExchangeScopeInfoOrUndefined( } export async function getExchangeScopeInfo( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, exchangeBaseUrl: string, currency: string, ): Promise<ScopeInfo> { - const det = await getExchangeRecordsInternal(tx.wtx, exchangeBaseUrl); + const det = await getExchangeRecordsInternal(tx, exchangeBaseUrl); if (!det) { return { type: ScopeType.Exchange, @@ -321,7 +320,7 @@ export async function getExchangeScopeInfo( url: exchangeBaseUrl, }; } - return internalGetExchangeScopeInfo(tx.wtx, det); + return internalGetExchangeScopeInfo(tx, det); } async function internalGetExchangeScopeInfo( @@ -380,7 +379,7 @@ function getKycStatusFromReserveStatus( async function makeExchangeListItem( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, r: WalletExchangeEntry, exchangeDetails: WalletExchangeDetails | undefined, reserveRec: WalletReserve | undefined, @@ -389,7 +388,7 @@ async function makeExchangeListItem( let scopeInfo: ScopeInfo | undefined = undefined; if (exchangeDetails) { - scopeInfo = await internalGetExchangeScopeInfo(tx.wtx, exchangeDetails); + scopeInfo = await internalGetExchangeScopeInfo(tx, exchangeDetails); } const currency = @@ -401,7 +400,7 @@ async function makeExchangeListItem( url: r.baseUrl, }; - let currencySpec = (await tx.wtx.getCurrencyInfo(scopeInfo))?.currencySpec; + let currencySpec = (await tx.getCurrencyInfo(scopeInfo))?.currencySpec; currencySpec = currencySpec ?? r.presetCurrencySpec ?? { @@ -504,23 +503,21 @@ export async function lookupExchangeByUri( wex: WalletExecutionContext, req: GetExchangeEntryByUrlRequest, ): Promise<ExchangeListItem> { - const res = await wex.runLegacyWalletDbTx(async (tx) => { - const exchangeRec = await tx.wtx.getExchange(req.exchangeBaseUrl); + const res = await wex.runWalletDbTx(async (tx) => { + const exchangeRec = await tx.getExchange(req.exchangeBaseUrl); if (!exchangeRec) { return undefined; } const exchangeDetails = await getExchangeRecordsInternal( - tx.wtx, + tx, exchangeRec.baseUrl, ); - const opRetryRecord = await tx.wtx.getOperationRetry( + const opRetryRecord = await tx.getOperationRetry( TaskIdentifiers.forExchangeUpdate(exchangeRec), ); let reserveRec: WalletReserve | undefined = undefined; if (exchangeRec.currentMergeReserveRowId != null) { - reserveRec = await tx.wtx.getReserve( - exchangeRec.currentMergeReserveRowId, - ); + reserveRec = await tx.getReserve(exchangeRec.currentMergeReserveRowId); checkDbInvariant(!!reserveRec, "reserve record not found"); } return await makeExchangeListItem( @@ -548,15 +545,15 @@ export async function acceptExchangeTermsOfService( wex: WalletExecutionContext, exchangeBaseUrl: string, ): Promise<void> { - await wex.runLegacyWalletDbTx(async (tx) => { - const exch = await tx.wtx.getExchange(exchangeBaseUrl); + await wex.runWalletDbTx(async (tx) => { + const exch = await tx.getExchange(exchangeBaseUrl); if (exch && exch.tosCurrentEtag) { const oldExchangeState = getExchangeState(exch); exch.tosAcceptedEtag = exch.tosCurrentEtag; exch.tosAcceptedTimestamp = timestampPreciseToDb( TalerPreciseTimestamp.now(), ); - await tx.wtx.upsertExchange(exch); + await tx.upsertExchange(exch); const newExchangeState = getExchangeState(exch); wex.ws.exchangeCache.clear(); tx.notify({ @@ -577,15 +574,15 @@ export async function forgetExchangeTermsOfService( wex: WalletExecutionContext, exchangeBaseUrl: string, ): Promise<void> { - await wex.runLegacyWalletDbTx(async (tx) => { - const exch = await tx.wtx.getExchange(exchangeBaseUrl); + await wex.runWalletDbTx(async (tx) => { + const exch = await tx.getExchange(exchangeBaseUrl); if (!exch) { return; } const oldExchangeState = getExchangeState(exch); exch.tosAcceptedEtag = undefined; exch.tosAcceptedTimestamp = undefined; - await tx.wtx.upsertExchange(exch); + await tx.upsertExchange(exch); const newExchangeState = getExchangeState(exch); wex.ws.exchangeCache.clear(); tx.notify({ @@ -722,13 +719,13 @@ async function validateGlobalFees( * if the DB transaction succeeds. */ export async function putPresetExchangeEntry( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, exchangeBaseUrl: string, exchangeType: string, currencyHint?: string, currencySpec?: CurrencySpecification, ): Promise<void> { - let exchange = await tx.wtx.getExchange(exchangeBaseUrl); + let exchange = await tx.getExchange(exchangeBaseUrl); if (!exchange) { const r: WalletExchangeEntry = { entryStatus: ExchangeEntryDbRecordStatus.Preset, @@ -750,7 +747,7 @@ export async function putPresetExchangeEntry( tosAcceptedTimestamp: undefined, tosCurrentEtag: undefined, }; - await tx.wtx.upsertExchange(r); + await tx.upsertExchange(r); tx.notify({ type: NotificationType.ExchangeStateTransition, exchangeBaseUrl: exchangeBaseUrl, @@ -763,19 +760,19 @@ export async function putPresetExchangeEntry( exchange.presetCurrencySpec = currencySpec; exchange.presetCurrencyHint = currencyHint; exchange.presetType = exchangeType; - await tx.wtx.upsertExchange(exchange); + await tx.upsertExchange(exchange); } } async function provideExchangeRecordInTx( ws: InternalWalletState, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, baseUrl: string, ): Promise<{ exchange: WalletExchangeEntry; exchangeDetails: WalletExchangeDetails | undefined; }> { - let exchange = await tx.wtx.getExchange(baseUrl); + let exchange = await tx.getExchange(baseUrl); if (!exchange) { const r: WalletExchangeEntry = { entryStatus: ExchangeEntryDbRecordStatus.Ephemeral, @@ -798,7 +795,7 @@ async function provideExchangeRecordInTx( tosAcceptedTimestamp: undefined, tosCurrentEtag: undefined, }; - await tx.wtx.upsertExchange(r); + await tx.upsertExchange(r); exchange = r; tx.notify({ type: NotificationType.ExchangeStateTransition, @@ -808,7 +805,7 @@ async function provideExchangeRecordInTx( newExchangeState: getExchangeState(r), }); } - const exchangeDetails = await getExchangeRecordsInternal(tx.wtx, baseUrl); + const exchangeDetails = await getExchangeRecordsInternal(tx, baseUrl); return { exchange, exchangeDetails }; } @@ -962,7 +959,7 @@ async function downloadTosMeta( */ async function checkExchangeEntryOutdated( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, exchangeBaseUrl: string, ): Promise<boolean> { // We currently consider the exchange outdated when no @@ -970,7 +967,7 @@ async function checkExchangeEntryOutdated( logger.trace(`checking if exchange entry for ${exchangeBaseUrl} is outdated`); let numOkay = 0; - let denoms = await tx.wtx.getDenominationsByExchange(exchangeBaseUrl); + let denoms = await tx.getDenominationsByExchange(exchangeBaseUrl); logger.trace(`exchange entry has ${denoms.length} denominations`); for (const denom of denoms) { const denomOkay = isCandidateWithdrawableDenomRec(denom); @@ -1016,8 +1013,8 @@ export async function startUpdateExchangeEntry( }`, ); - await wex.runLegacyWalletDbTx(async (tx) => { - const rec = await tx.wtx.getExchangeBaseUrlFixup(exchangeBaseUrl); + await wex.runWalletDbTx(async (tx) => { + const rec = await tx.getExchangeBaseUrlFixup(exchangeBaseUrl); if (rec) { logger.warn( `using replacement ${rec.replacement} for ${exchangeBaseUrl}`, @@ -1026,7 +1023,7 @@ export async function startUpdateExchangeEntry( } }); - await wex.runLegacyWalletDbTx(async (tx) => { + await wex.runWalletDbTx(async (tx) => { wex.ws.exchangeCache.clear(); return provideExchangeRecordInTx(wex.ws, tx, exchangeBaseUrl); }); @@ -1042,8 +1039,8 @@ export async function startUpdateExchangeEntry( let readySummary: ReadyExchangeSummary | undefined = undefined; - const res = await wex.runLegacyWalletDbTx(async (tx) => { - const r = await tx.wtx.getExchange(exchangeBaseUrl); + const res = await wex.runWalletDbTx(async (tx) => { + const r = await tx.getExchange(exchangeBaseUrl); if (!r) { throw Error("exchange not found"); } @@ -1123,7 +1120,7 @@ export async function startUpdateExchangeEntry( } } wex.ws.exchangeCache.clear(); - await tx.wtx.upsertExchange(r); + await tx.upsertExchange(r); const newExchangeState = getExchangeState(r); tx.notify({ type: NotificationType.ExchangeStateTransition, @@ -1199,10 +1196,10 @@ export class OutdatedExchangeError extends Error { */ export async function requireExchangeReadyTx( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, exchangeBaseUrl: string, ): Promise<void> { - const exchange = await tx.wtx.getExchange(exchangeBaseUrl); + const exchange = await tx.getExchange(exchangeBaseUrl); if (!exchange) { // This is fatal, outer transaction will not be retried. throw Error("exchange does not exist in database"); @@ -1297,8 +1294,8 @@ export async function waitReadyExchange( ): Promise<ReadyExchangeSummary> { logger.trace(`waiting for exchange ${exchangeBaseUrl} to become ready`); - await wex.runLegacyWalletDbTx(async (tx) => { - const rec = await tx.wtx.getExchangeBaseUrlFixup(exchangeBaseUrl); + await wex.runWalletDbTx(async (tx) => { + const rec = await tx.getExchangeBaseUrlFixup(exchangeBaseUrl); if (rec) { logger.warn( `using replacement ${rec.replacement} for ${exchangeBaseUrl}`, @@ -1323,19 +1320,16 @@ export async function waitReadyExchange( }, async checkState(): Promise<boolean> { const { exchange, exchangeDetails, retryInfo, scopeInfo } = - await wex.runLegacyWalletDbTx(async (tx) => { - const exchange = await tx.wtx.getExchange(exchangeBaseUrl); + await wex.runWalletDbTx(async (tx) => { + const exchange = await tx.getExchange(exchangeBaseUrl); const exchangeDetails = await getExchangeRecordsInternal( - tx.wtx, + tx, exchangeBaseUrl, ); - const retryInfo = await tx.wtx.getOperationRetry(operationId); + const retryInfo = await tx.getOperationRetry(operationId); let scopeInfo: ScopeInfo | undefined = undefined; if (exchange && exchangeDetails) { - scopeInfo = await internalGetExchangeScopeInfo( - tx.wtx, - exchangeDetails, - ); + scopeInfo = await internalGetExchangeScopeInfo(tx, exchangeDetails); } return { exchange, exchangeDetails, retryInfo, scopeInfo }; }); @@ -1507,17 +1501,17 @@ function constructReadyExchangeSummary( } async function loadReadyExchangeSummary( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, exchangeRec: WalletExchangeEntry, ): Promise<ReadyExchangeSummary | undefined> { const exchangeDetails = await getExchangeRecordsInternal( - tx.wtx, + tx, exchangeRec.baseUrl, ); if (!exchangeDetails) { return undefined; } - const scopeInfo = await internalGetExchangeScopeInfo(tx.wtx, exchangeDetails); + const scopeInfo = await internalGetExchangeScopeInfo(tx, exchangeDetails); if (!scopeInfo) { return undefined; } @@ -1582,8 +1576,8 @@ async function handleExchageUpdateIncompatible( exchangeBaseUrl: string, exchangeProtocolVersion: string, ): Promise<TaskRunResult> { - await wex.runLegacyWalletDbTx(async (tx) => { - const r = await tx.wtx.getExchange(exchangeBaseUrl); + await wex.runWalletDbTx(async (tx) => { + const r = await tx.getExchange(exchangeBaseUrl); if (!r) { logger.warn(`exchange ${exchangeBaseUrl} no longer present`); return; @@ -1607,7 +1601,7 @@ async function handleExchageUpdateIncompatible( }, ); const newExchangeState = getExchangeState(r); - await tx.wtx.upsertExchange(r); + await tx.upsertExchange(r); tx.notify({ type: NotificationType.ExchangeStateTransition, exchangeBaseUrl, @@ -1635,8 +1629,8 @@ export async function updateExchangeFromUrlHandler( logger.trace(`updating exchange info for ${exchangeBaseUrl}`); - const oldExchangeRec = await wex.runLegacyWalletDbTx(async (tx) => { - return await tx.wtx.getExchange(exchangeBaseUrl); + const oldExchangeRec = await wex.runWalletDbTx(async (tx) => { + return await tx.getExchange(exchangeBaseUrl); }); if (!oldExchangeRec) { @@ -1890,8 +1884,8 @@ export async function updateExchangeFromUrlHandler( } } - const taskRes = await wex.runLegacyWalletDbTx(async (tx) => { - const r = await tx.wtx.getExchange(exchangeBaseUrl); + const taskRes = await wex.runWalletDbTx(async (tx) => { + const r = await tx.getExchange(exchangeBaseUrl); if (!r) { logger.warn(`exchange ${exchangeBaseUrl} no longer present`); return TaskRunResult.progress(); @@ -1900,7 +1894,7 @@ export async function updateExchangeFromUrlHandler( wex.ws.clearAllCaches(); const oldExchangeState = getExchangeState(r); - const existingDetails = await getExchangeRecordsInternal(tx.wtx, r.baseUrl); + const existingDetails = await getExchangeRecordsInternal(tx, r.baseUrl); let detailsPointerChanged = false; if (!existingDetails) { detailsPointerChanged = true; @@ -1936,7 +1930,7 @@ export async function updateExchangeFromUrlHandler( AbsoluteTime.toPreciseTimestamp(AbsoluteTime.never()), ); r.cachebreakNextUpdate = true; - await tx.wtx.upsertExchange(r); + await tx.upsertExchange(r); tx.notify({ type: NotificationType.ExchangeStateTransition, exchangeBaseUrl, @@ -2004,12 +1998,12 @@ export async function updateExchangeFromUrlHandler( r.updateStatus = ExchangeEntryDbUpdateStatus.Ready; r.cachebreakNextUpdate = false; - await tx.wtx.upsertExchange(r); + await tx.upsertExchange(r); if (keysInfo.currency_specification) { // Since this is the per-exchange currency info, // we update it when the exchange changes it. - await tx.wtx.upsertCurrencyInfo({ + await tx.upsertCurrencyInfo({ currencySpec: keysInfo.currency_specification, scopeInfo: { type: ScopeType.Exchange, @@ -2020,11 +2014,11 @@ export async function updateExchangeFromUrlHandler( }); } - const drRowId = await tx.wtx.upsertExchangeDetails(newDetails); + const drRowId = await tx.upsertExchangeDetails(newDetails); for (const sk of keysInfo.signkeys) { // FIXME: validate signing keys before inserting them - await tx.wtx.upsertExchangeSignKey({ + await tx.upsertExchangeSignKey({ exchangeDetailsRowId: drRowId, masterSig: sk.master_sig, signkeyPub: sk.key, @@ -2035,8 +2029,7 @@ export async function updateExchangeFromUrlHandler( } // In the future: Filter out old denominations by index - const allOldDenoms = - await tx.wtx.getDenominationsByExchange(exchangeBaseUrl); + const allOldDenoms = await tx.getDenominationsByExchange(exchangeBaseUrl); const oldDenomByDph = new Map<string, WalletDenomination>(); for (const denom of allOldDenoms) { oldDenomByDph.set(denom.denomPubHash, denom); @@ -2047,7 +2040,7 @@ export async function updateExchangeFromUrlHandler( for (const currentDenom of denomInfos) { // FIXME: Check if we really already need the denomination. let fpRec: WalletDenominationFamily | undefined = - await tx.wtx.getDenominationFamilyByParams({ + await tx.getDenominationFamilyByParams({ exchangeBaseUrl: currentDenom.exchangeBaseUrl, exchangeMasterPub: currentDenom.exchangeMasterPub, value: currentDenom.value, @@ -2070,7 +2063,7 @@ export async function updateExchangeFromUrlHandler( fpRec = { familyParams: fp, }; - denominationFamilySerial = await tx.wtx.upsertDenominationFamily(fpRec); + denominationFamilySerial = await tx.upsertDenominationFamily(fpRec); } else { denominationFamilySerial = fpRec.denominationFamilySerial; } @@ -2133,10 +2126,10 @@ export async function updateExchangeFromUrlHandler( changed = true; } if (changed) { - await tx.wtx.upsertDenomination(oldDenom); + await tx.upsertDenomination(oldDenom); } } else { - await tx.wtx.upsertDenomination(denomRec); + await tx.upsertDenomination(denomRec); } } @@ -2151,13 +2144,13 @@ export async function updateExchangeFromUrlHandler( logger.info( `setting denomination ${x.denomPubHash} to offered=false`, ); - await tx.wtx.upsertDenomination(x); + await tx.upsertDenomination(x); } } else { if (!x.isOffered) { x.isOffered = true; logger.info(`setting denomination ${x.denomPubHash} to offered=true`); - await tx.wtx.upsertDenomination(x); + await tx.upsertDenomination(x); } } } @@ -2210,18 +2203,18 @@ async function doExchangeAutoRefresh( Duration.fromSpec({ days: 1 }), ); - await wex.runLegacyWalletDbTx(async (tx) => { - const exchange = await tx.wtx.getExchange(exchangeBaseUrl); + await wex.runWalletDbTx(async (tx) => { + const exchange = await tx.getExchange(exchangeBaseUrl); if (!exchange || !exchange.detailsPointer) { return; } - const coins = await tx.wtx.getCoinsByExchange(exchangeBaseUrl); + const coins = await tx.getCoinsByExchange(exchangeBaseUrl); const refreshCoins: CoinRefreshRequest[] = []; for (const coin of coins) { if (coin.status !== CoinStatus.Fresh) { continue; } - const denom = await tx.wtx.getDenomination( + const denom = await tx.getDenomination( exchangeBaseUrl, coin.denomPubHash, ); @@ -2260,7 +2253,7 @@ async function doExchangeAutoRefresh( AbsoluteTime.toPreciseTimestamp(minCheckThreshold), ); wex.ws.exchangeCache.clear(); - await tx.wtx.upsertExchange(exchange); + await tx.upsertExchange(exchange); const st = getExchangeState(exchange); tx.notify({ type: NotificationType.ExchangeStateTransition, @@ -2278,8 +2271,8 @@ export async function processTaskExchangeAutoRefresh( ): Promise<TaskRunResult> { logger.trace(`doing auto-refresh check for '${exchangeBaseUrl}'`); - const oldExchangeRec = await wex.runLegacyWalletDbTx(async (tx) => { - return await tx.wtx.getExchange(exchangeBaseUrl); + const oldExchangeRec = await wex.runWalletDbTx(async (tx) => { + return await tx.getExchange(exchangeBaseUrl); }); if (!oldExchangeRec) { @@ -2323,12 +2316,12 @@ export async function processTaskExchangeAutoRefresh( async function handleDenomLoss( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, currency: string, exchangeBaseUrl: string, ): Promise<void> { const coinAvailabilityRecs = - await tx.wtx.getCoinAvailabilityByExchange(exchangeBaseUrl); + await tx.getCoinAvailabilityByExchange(exchangeBaseUrl); const denomsVanished: string[] = []; const denomsUnoffered: string[] = []; const denomsExpired: string[] = []; @@ -2341,7 +2334,7 @@ async function handleDenomLoss( continue; } const n = coinAv.freshCoinCount; - const denom = await tx.wtx.getDenomination( + const denom = await tx.getDenomination( coinAv.exchangeBaseUrl, coinAv.denomPubHash, ); @@ -2352,7 +2345,7 @@ async function handleDenomLoss( // Remove availability coinAv.freshCoinCount = 0; coinAv.visibleCoinCount = 0; - await tx.wtx.upsertCoinAvailability(coinAv); + await tx.upsertCoinAvailability(coinAv); denomsVanished.push(coinAv.denomPubHash); const total = Amount.from(coinAv.value).mult(n); amountVanished = amountVanished.add(total); @@ -2360,7 +2353,7 @@ async function handleDenomLoss( // Remove availability coinAv.freshCoinCount = 0; coinAv.visibleCoinCount = 0; - await tx.wtx.upsertCoinAvailability(coinAv); + await tx.upsertCoinAvailability(coinAv); denomsUnoffered.push(coinAv.denomPubHash); const total = Amount.from(coinAv.value).mult(n); amountUnoffered = amountUnoffered.add(total); @@ -2371,7 +2364,7 @@ async function handleDenomLoss( // Remove availability coinAv.freshCoinCount = 0; coinAv.visibleCoinCount = 0; - await tx.wtx.upsertCoinAvailability(coinAv); + await tx.upsertCoinAvailability(coinAv); denomsExpired.push(coinAv.denomPubHash); const total = Amount.from(coinAv.value).mult(n); amountExpired = amountExpired.add(total); @@ -2382,13 +2375,13 @@ async function handleDenomLoss( logger.warn(`denomination ${coinAv.denomPubHash} is a loss`); - const coins = await tx.wtx.getCoinsByDenomPubHash(coinAv.denomPubHash); + const coins = await tx.getCoinsByDenomPubHash(coinAv.denomPubHash); for (const coin of coins) { switch (coin.status) { case CoinStatus.Fresh: case CoinStatus.FreshSuspended: { coin.status = CoinStatus.DenomLoss; - await tx.wtx.upsertCoin(coin); + await tx.upsertCoin(coin); break; } } @@ -2407,9 +2400,9 @@ async function handleDenomLoss( status: DenomLossStatus.Done, timestampCreated: timestampPreciseToDb(TalerPreciseTimestamp.now()), }; - await tx.wtx.upsertDenomLossEvent(rec); + await tx.upsertDenomLossEvent(rec); const ctx = new DenomLossTransactionContext(wex, denomLossEventId); - await ctx.updateTransactionMeta(tx.wtx); + await ctx.updateTransactionMeta(tx); tx.notify({ type: NotificationType.TransactionStateTransition, transactionId: ctx.transactionId, @@ -2439,9 +2432,9 @@ async function handleDenomLoss( status: DenomLossStatus.Done, timestampCreated: timestampPreciseToDb(TalerPreciseTimestamp.now()), }; - await tx.wtx.upsertDenomLossEvent(rec); + await tx.upsertDenomLossEvent(rec); const ctx = new DenomLossTransactionContext(wex, denomLossEventId); - await ctx.updateTransactionMeta(tx.wtx); + await ctx.updateTransactionMeta(tx); tx.notify({ type: NotificationType.TransactionStateTransition, transactionId: ctx.transactionId, @@ -2471,7 +2464,7 @@ async function handleDenomLoss( status: DenomLossStatus.Done, timestampCreated: timestampPreciseToDb(TalerPreciseTimestamp.now()), }; - await tx.wtx.upsertDenomLossEvent(rec); + await tx.upsertDenomLossEvent(rec); const transactionId = constructTransactionIdentifier({ tag: TransactionType.DenomLoss, denomLossEventId, @@ -2566,13 +2559,13 @@ export class DenomLossTransactionContext implements TransactionContext { } async userDeleteTransaction(): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - const rec = await tx.wtx.getDenomLossEvent(this.denomLossEventId); + await this.wex.runWalletDbTx(async (tx) => { + const rec = await tx.getDenomLossEvent(this.denomLossEventId); if (!rec) { return; } const oldTxState = computeDenomLossTransactionStatus(rec); - await tx.wtx.deleteDenomLossEvent(this.denomLossEventId); + await tx.deleteDenomLossEvent(this.denomLossEventId); applyNotifyTransition(tx.notify, this.transactionId, { oldTxState, newTxState: { @@ -2614,7 +2607,7 @@ export class DenomLossTransactionContext implements TransactionContext { async function handleRecoup( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, exchangeBaseUrl: string, recoup: Recoup[], ): Promise<void> { @@ -2623,7 +2616,7 @@ async function handleRecoup( const newlyRevokedCoinPubs: string[] = []; logger.trace("recoup list from exchange", recoupDenomList); for (const recoupInfo of recoupDenomList) { - const oldDenom = await tx.wtx.getDenomination( + const oldDenom = await tx.getDenomination( exchangeBaseUrl, recoupInfo.h_denom_pub, ); @@ -2639,8 +2632,8 @@ async function handleRecoup( } logger.info("revoking denom", recoupInfo.h_denom_pub); oldDenom.isRevoked = true; - await tx.wtx.upsertDenomination(oldDenom); - const affectedCoins = await tx.wtx.getCoinsByDenomPubHash( + await tx.upsertDenomination(oldDenom); + const affectedCoins = await tx.getCoinsByDenomPubHash( recoupInfo.h_denom_pub, ); for (const ac of affectedCoins) { @@ -2690,8 +2683,8 @@ export async function getExchangePaytoUri( ): Promise<string> { // 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.wtx, exchangeBaseUrl); + const details = await wex.runWalletDbTx(async (tx) => { + return getExchangeRecordsInternal(tx, exchangeBaseUrl); }); const accounts = details?.wireInfo.accounts ?? []; for (const account of accounts) { @@ -2822,12 +2815,12 @@ export async function getExchangeTos( checkLogicInvariant(!!tosDownload); - await wex.runLegacyWalletDbTx(async (tx) => { - const updateExchangeEntry = await tx.wtx.getExchange(exchangeBaseUrl); + await wex.runWalletDbTx(async (tx) => { + const updateExchangeEntry = await tx.getExchange(exchangeBaseUrl); if (updateExchangeEntry) { updateExchangeEntry.tosCurrentEtag = tosDownload.tosEtag; wex.ws.exchangeCache.clear(); - await tx.wtx.upsertExchange(updateExchangeEntry); + await tx.upsertExchange(updateExchangeEntry); } }); @@ -2882,23 +2875,21 @@ export async function listExchanges( req: ListExchangesRequest, ): Promise<ExchangesListResponse> { const exchanges: ExchangeListItem[] = []; - await wex.runLegacyWalletDbTx(async (tx) => { - const exchangeRecords = await tx.wtx.getExchanges(); + await wex.runWalletDbTx(async (tx) => { + const exchangeRecords = await tx.getExchanges(); for (const exchangeRec of exchangeRecords) { const taskId = constructTaskIdentifier({ tag: PendingTaskType.ExchangeUpdate, exchangeBaseUrl: exchangeRec.baseUrl, }); const exchangeDetails = await getExchangeRecordsInternal( - tx.wtx, + tx, exchangeRec.baseUrl, ); - const opRetryRecord = await tx.wtx.getOperationRetry(taskId); + const opRetryRecord = await tx.getOperationRetry(taskId); let reserveRec: WalletReserve | undefined = undefined; if (exchangeRec.currentMergeReserveRowId != null) { - reserveRec = await tx.wtx.getReserve( - exchangeRec.currentMergeReserveRowId, - ); + reserveRec = await tx.getReserve(exchangeRec.currentMergeReserveRowId); checkDbInvariant(!!reserveRec, "reserve record not found"); } if ( @@ -2946,11 +2937,11 @@ export async function listExchanges( * succeeded. */ export async function markExchangeUsed( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, exchangeBaseUrl: string, ): Promise<void> { logger.trace(`marking exchange ${exchangeBaseUrl} as used`); - const exch = await tx.wtx.getExchange(exchangeBaseUrl); + const exch = await tx.getExchange(exchangeBaseUrl); if (!exch) { logger.info(`exchange ${exchangeBaseUrl} NOT found`); return; @@ -2961,7 +2952,7 @@ export async function markExchangeUsed( case ExchangeEntryDbRecordStatus.Ephemeral: case ExchangeEntryDbRecordStatus.Preset: { exch.entryStatus = ExchangeEntryDbRecordStatus.Used; - await tx.wtx.upsertExchange(exch); + await tx.upsertExchange(exch); const newExchangeState = getExchangeState(exch); tx.notify({ type: NotificationType.ExchangeStateTransition, @@ -2985,23 +2976,18 @@ export async function getExchangeDetailedInfo( wex: WalletExecutionContext, exchangeBaseurl: string, ): Promise<ExchangeDetailedResponse> { - const exchange = await wex.runLegacyWalletDbTx(async (tx) => { - const ex = await tx.wtx.getExchange(exchangeBaseurl); + const exchange = await wex.runWalletDbTx(async (tx) => { + const ex = await tx.getExchange(exchangeBaseurl); const dp = ex?.detailsPointer; if (!dp) { return; } const { currency } = dp; - const exchangeDetails = await getExchangeRecordsInternal( - tx.wtx, - ex.baseUrl, - ); + const exchangeDetails = await getExchangeRecordsInternal(tx, ex.baseUrl); if (!exchangeDetails) { return; } - const denominationRecords = await tx.wtx.getDenominationsByExchange( - ex.baseUrl, - ); + const denominationRecords = await tx.getDenominationsByExchange(ex.baseUrl); if (!denominationRecords) { return; @@ -3136,14 +3122,13 @@ export async function getExchangeDetailedInfo( } async function internalGetExchangeResources( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, exchangeBaseUrl: string, ): Promise<GetExchangeResourcesResponse> { let numWithdrawals = 0; let numCoins = 0; - numCoins = await tx.wtx.countCoinsByExchange(exchangeBaseUrl); - numWithdrawals = - await tx.wtx.countWithdrawalGroupsByExchange(exchangeBaseUrl); + numCoins = await tx.countCoinsByExchange(exchangeBaseUrl); + numWithdrawals = await tx.countWithdrawalGroupsByExchange(exchangeBaseUrl); const total = numWithdrawals + numCoins; return { hasResources: total != 0, @@ -3158,12 +3143,12 @@ async function internalGetExchangeResources( */ async function purgeExchange( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, exchangeRec: WalletExchangeEntry, purgeTransactions?: boolean, ): Promise<void> { const exchangeBaseUrl = exchangeRec.baseUrl; - const detRecs = await tx.wtx.listAllExchangeDetails(); + const detRecs = await tx.listAllExchangeDetails(); // Remove all exchange detail records for that exchange for (const r of detRecs) { if (r.rowId == null) { @@ -3173,16 +3158,16 @@ async function purgeExchange( if (r.exchangeBaseUrl !== exchangeBaseUrl) { continue; } - await tx.wtx.deleteExchangeDetails(r.rowId); - const signkeyRecs = await tx.wtx.getExchangeSignKeysByDetailsRowId(r.rowId); + await tx.deleteExchangeDetails(r.rowId); + const signkeyRecs = await tx.getExchangeSignKeysByDetailsRowId(r.rowId); for (const rec of signkeyRecs) { - await tx.wtx.deleteExchangeSignKey(r.rowId, rec.signkeyPub); + await tx.deleteExchangeSignKey(r.rowId, rec.signkeyPub); } } const oldExchangeState = getExchangeState(exchangeRec); - await tx.wtx.deleteExchange(exchangeBaseUrl); + await tx.deleteExchange(exchangeBaseUrl); tx.notify({ type: NotificationType.ExchangeStateTransition, oldExchangeState, @@ -3193,9 +3178,9 @@ async function purgeExchange( { const coinAvailabilityRecs = - await tx.wtx.getCoinAvailabilityByExchange(exchangeBaseUrl); + await tx.getCoinAvailabilityByExchange(exchangeBaseUrl); for (const rec of coinAvailabilityRecs) { - await tx.wtx.deleteCoinAvailability( + await tx.deleteCoinAvailability( exchangeBaseUrl, rec.denomPubHash, rec.maxAge, @@ -3204,29 +3189,29 @@ async function purgeExchange( } { - const coinRecs = await tx.wtx.getCoinsByExchange(exchangeBaseUrl); + const coinRecs = await tx.getCoinsByExchange(exchangeBaseUrl); for (const rec of coinRecs) { - await tx.wtx.deleteCoin(rec.coinPub); - await tx.wtx.deleteCoinHistory(rec.coinPub); + await tx.deleteCoin(rec.coinPub); + await tx.deleteCoinHistory(rec.coinPub); } } { - const denomRecs = await tx.wtx.getDenominationsByExchange(exchangeBaseUrl); + const denomRecs = await tx.getDenominationsByExchange(exchangeBaseUrl); for (const rec of denomRecs) { - await tx.wtx.deleteDenomination(rec.exchangeBaseUrl, rec.denomPubHash); + await tx.deleteDenomination(rec.exchangeBaseUrl, rec.denomPubHash); } } { const denomFamilyRecs = - await tx.wtx.getDenominationFamiliesByExchange(exchangeBaseUrl); + await tx.getDenominationFamiliesByExchange(exchangeBaseUrl); for (const rec of denomFamilyRecs) { checkDbInvariant( rec.denominationFamilySerial != null, "denominationFamilySerial", ); - await tx.wtx.deleteDenominationFamily(rec.denominationFamilySerial); + await tx.deleteDenominationFamily(rec.denominationFamilySerial); } } @@ -3234,109 +3219,106 @@ async function purgeExchange( // transaction deletion was requested. { const withdrawalGroupRecs = - await tx.wtx.getWithdrawalGroupsByExchange(exchangeBaseUrl); + await tx.getWithdrawalGroupsByExchange(exchangeBaseUrl); for (const wg of withdrawalGroupRecs) { const ctx = new WithdrawTransactionContext(wex, wg.withdrawalGroupId); - await ctx.deleteTransactionInTx(tx.wtx); + await ctx.deleteTransactionInTx(tx); } } if (purgeTransactions) { // Remove from refreshGroups and refreshSessions { - const refreshGroups = await tx.wtx.listAllRefreshGroups(); + const refreshGroups = await tx.listAllRefreshGroups(); for (const rg of refreshGroups) { if (rg.infoPerExchange && rg.infoPerExchange[exchangeBaseUrl] != null) { const ctx = new RefreshTransactionContext(wex, rg.refreshGroupId); - await ctx.deleteTransactionInTx(tx.wtx); + await ctx.deleteTransactionInTx(tx); } } } // Remove from recoupGroups { - const recoupGroups = - await tx.wtx.getRecoupGroupsByExchange(exchangeBaseUrl); + const recoupGroups = await tx.getRecoupGroupsByExchange(exchangeBaseUrl); for (const rg of recoupGroups) { const ctx = new RecoupTransactionContext(wex, rg.recoupGroupId); - await ctx.deleteTransactionInTx(tx.wtx); + await ctx.deleteTransactionInTx(tx); } } // Remove from deposits { // FIXME: Index would be useful here - const depositGroups = await tx.wtx.listAllDepositGroups(); + const depositGroups = await tx.listAllDepositGroups(); for (const dg of depositGroups) { if (dg.infoPerExchange && dg.infoPerExchange[exchangeBaseUrl]) { const ctx = new DepositTransactionContext(wex, dg.depositGroupId); - await ctx.deleteTransactionInTx(tx.wtx); + await ctx.deleteTransactionInTx(tx); } } } // Remove from purchases, refundGroups, refundItems { - const purchases = await tx.wtx.getPurchasesByExchange(exchangeBaseUrl); + const purchases = await tx.getPurchasesByExchange(exchangeBaseUrl); for (const purch of purchases) { - const refunds = await tx.wtx.getRefundGroupsByProposal( - purch.proposalId, - ); + const refunds = await tx.getRefundGroupsByProposal(purch.proposalId); for (const r of refunds) { const refundCtx = new RefundTransactionContext(wex, r.refundGroupId); - await refundCtx.deleteTransactionInTx(tx.wtx); + await refundCtx.deleteTransactionInTx(tx); } const payCtx = new PayMerchantTransactionContext(wex, purch.proposalId); - const res = await payCtx.deleteTransactionInTx(tx.wtx); + const res = await payCtx.deleteTransactionInTx(tx); } } // Remove from peerPullCredit { - const recs = await tx.wtx.listAllPeerPullCredits(); + const recs = await tx.listAllPeerPullCredits(); for (const rec of recs) { if (rec.exchangeBaseUrl === exchangeBaseUrl) { const ctx = new PeerPullCreditTransactionContext(wex, rec.pursePub); - await ctx.deleteTransactionInTx(tx.wtx); + await ctx.deleteTransactionInTx(tx); } } } // Remove from peerPullDebit { - const recs = await tx.wtx.listAllPeerPullDebits(); + const recs = await tx.listAllPeerPullDebits(); for (const rec of recs) { if (rec.exchangeBaseUrl === exchangeBaseUrl) { const ctx = new PeerPullDebitTransactionContext( wex, rec.peerPullDebitId, ); - await ctx.deleteTransactionInTx(tx.wtx); + await ctx.deleteTransactionInTx(tx); } } } // Remove from peerPushCredit { - const recs = await tx.wtx.listAllPeerPushCredits(); + const recs = await tx.listAllPeerPushCredits(); for (const rec of recs) { if (rec.exchangeBaseUrl === exchangeBaseUrl) { const ctx = new PeerPushCreditTransactionContext( wex, rec.peerPushCreditId, ); - await ctx.deleteTransactionInTx(tx.wtx); + await ctx.deleteTransactionInTx(tx); } } } // Remove from peerPushDebit { - const recs = await tx.wtx.listAllPeerPushDebits(); + const recs = await tx.listAllPeerPushDebits(); for (const rec of recs) { if (rec.exchangeBaseUrl === exchangeBaseUrl) { const ctx = new PeerPushDebitTransactionContext(wex, rec.pursePub); - await ctx.deleteTransactionInTx(tx.wtx); + await ctx.deleteTransactionInTx(tx); } } } } // FIXME: Is this even necessary? Each deletion should already do it. - await rematerializeTransactions(wex, tx.wtx); + await rematerializeTransactions(wex, tx); } export async function deleteExchange( @@ -3345,8 +3327,8 @@ export async function deleteExchange( ): Promise<void> { let inUse: boolean = false; const exchangeBaseUrl = req.exchangeBaseUrl; - await wex.runLegacyWalletDbTx(async (tx) => { - const exchangeRec = await tx.wtx.getExchange(exchangeBaseUrl); + await wex.runWalletDbTx(async (tx) => { + const exchangeRec = await tx.getExchange(exchangeBaseUrl); if (!exchangeRec) { // Nothing to delete! logger.info("no exchange found to delete"); @@ -3375,8 +3357,8 @@ export async function getExchangeResources( exchangeBaseUrl: string, ): Promise<GetExchangeResourcesResponse> { // Withdrawals include internal withdrawals from peer transactions - const res = await wex.runLegacyWalletDbTx(async (tx) => { - const exchangeRecord = await tx.wtx.getExchange(exchangeBaseUrl); + const res = await wex.runWalletDbTx(async (tx) => { + const exchangeRecord = await tx.getExchange(exchangeBaseUrl); if (!exchangeRecord) { return undefined; } @@ -3397,10 +3379,10 @@ export async function getExchangeWireFee( baseUrl: string, time: TalerProtocolTimestamp, ): Promise<WireFee> { - const exchangeDetails = await wex.runLegacyWalletDbTx(async (tx) => { - const ex = await tx.wtx.getExchange(baseUrl); + const exchangeDetails = await wex.runWalletDbTx(async (tx) => { + const ex = await tx.getExchange(baseUrl); if (!ex || !ex.detailsPointer) return undefined; - return await tx.wtx.getExchangeDetailsByPointer( + return await tx.getExchangeDetailsByPointer( baseUrl, ex.detailsPointer.currency, ex.detailsPointer.masterPublicKey, @@ -3451,18 +3433,18 @@ export async function checkIncomingAmountLegalUnderKycBalanceThreshold( amountIncoming: AmountLike, ): Promise<BalanceThresholdCheckResult> { logger.trace(`checking ${exchangeBaseUrl} +${amountIncoming} for KYC`); - return await wex.runLegacyWalletDbTx( + return await wex.runWalletDbTx( async (tx): Promise<BalanceThresholdCheckResult> => { - const exchangeRec = await tx.wtx.getExchange(exchangeBaseUrl); + const exchangeRec = await tx.getExchange(exchangeBaseUrl); if (!exchangeRec) { throw Error("exchange not found"); } - const det = await getExchangeRecordsInternal(tx.wtx, exchangeBaseUrl); + const det = await getExchangeRecordsInternal(tx, exchangeBaseUrl); if (!det) { throw Error("exchange not found"); } const coinAvRecs = - await tx.wtx.getCoinAvailabilityByExchange(exchangeBaseUrl); + await tx.getCoinAvailabilityByExchange(exchangeBaseUrl); let balAmount = Amounts.zeroOfCurrency(det.currency); for (const av of coinAvRecs) { const n = av.freshCoinCount + (av.pendingRefreshOutputCount ?? 0); @@ -3478,7 +3460,7 @@ export async function checkIncomingAmountLegalUnderKycBalanceThreshold( const reserveId = exchangeRec.currentMergeReserveRowId; let reserveRec: WalletReserve | undefined; if (reserveId) { - reserveRec = await tx.wtx.getReserve(reserveId); + reserveRec = await tx.getReserve(reserveId); checkDbInvariant(!!reserveRec, "reserve"); // FIXME: also consider KYC expiration! if (reserveRec.thresholdNext) { @@ -3566,8 +3548,8 @@ export async function waitExchangeWalletKyc( ): Promise<void> { await genericWaitForState(wex, { async checkState(): Promise<boolean> { - return await wex.runLegacyWalletDbTx(async (tx) => { - const exchange = await tx.wtx.getExchange(exchangeBaseUrl); + return await wex.runWalletDbTx(async (tx) => { + const exchange = await tx.getExchange(exchangeBaseUrl); if (!exchange) { throw new Error("exchange not found"); } @@ -3576,7 +3558,7 @@ export async function waitExchangeWalletKyc( logger.warn("KYC does not exist yet"); return false; } - const reserve = await tx.wtx.getReserve(reserveId); + const reserve = await tx.getReserve(reserveId); if (!reserve) { throw Error("reserve not found"); } @@ -3665,22 +3647,22 @@ export async function handleStartExchangeWalletKyc( req: StartExchangeWalletKycRequest, ): Promise<EmptyObject> { const newReservePair = await wex.cryptoApi.createEddsaKeypair({}); - await wex.runLegacyWalletDbTx(async (tx) => { - const exchange = await tx.wtx.getExchange(req.exchangeBaseUrl); + await wex.runWalletDbTx(async (tx) => { + const exchange = await tx.getExchange(req.exchangeBaseUrl); if (!exchange) { throw Error("exchange not found"); } const oldExchangeState = getExchangeState(exchange); let mergeReserveRowId = exchange.currentMergeReserveRowId; if (mergeReserveRowId == null) { - mergeReserveRowId = await tx.wtx.upsertReserve({ + mergeReserveRowId = await tx.upsertReserve({ reservePriv: newReservePair.priv, reservePub: newReservePair.pub, }); exchange.currentMergeReserveRowId = mergeReserveRowId; - await tx.wtx.upsertExchange(exchange); + await tx.upsertExchange(exchange); } - const reserveRec = await tx.wtx.getReserve(mergeReserveRowId); + const reserveRec = await tx.getReserve(mergeReserveRowId); checkDbInvariant(reserveRec != null, "reserve record exists"); if ( reserveRec.thresholdGranted == null || @@ -3692,7 +3674,7 @@ export async function handleStartExchangeWalletKyc( ) { reserveRec.thresholdRequested = req.amount; reserveRec.status = ReserveRecordStatus.PendingLegiInit; - await tx.wtx.upsertReserve(reserveRec); + await tx.upsertReserve(reserveRec); tx.notify({ type: NotificationType.ExchangeStateTransition, exchangeBaseUrl: exchange.baseUrl, @@ -3790,8 +3772,8 @@ async function handleExchangeKycSuccess( nextThreshold: AmountLike | undefined, ): Promise<TaskRunResult> { logger.info(`kyc check for ${exchangeBaseUrl} satisfied`); - await wex.runLegacyWalletDbTx(async (tx) => { - const exchange = await tx.wtx.getExchange(exchangeBaseUrl); + await wex.runWalletDbTx(async (tx) => { + const exchange = await tx.getExchange(exchangeBaseUrl); if (!exchange) { throw Error("exchange not found"); } @@ -3800,7 +3782,7 @@ async function handleExchangeKycSuccess( if (reserveId == null) { throw Error("expected exchange to have reserve ID"); } - const reserve = await tx.wtx.getReserve(reserveId); + const reserve = await tx.getReserve(reserveId); checkDbInvariant(!!reserve, "merge reserve should exist"); switch (reserve.status) { case ReserveRecordStatus.PendingLegiInit: @@ -3818,7 +3800,7 @@ async function handleExchangeKycSuccess( reserve.thresholdNext = Amounts.stringify(nextThreshold); } - await tx.wtx.upsertReserve(reserve); + await tx.upsertReserve(reserve); logger.info(`newly granted threshold: ${reserve.thresholdGranted}`); tx.notify({ type: NotificationType.ExchangeStateTransition, @@ -3904,8 +3886,8 @@ async function handleExchangeKycRespLegi( codecForAccountKycStatus(), ); - await wex.runLegacyWalletDbTx(async (tx) => { - const exchange = await tx.wtx.getExchange(exchangeBaseUrl); + await wex.runWalletDbTx(async (tx) => { + const exchange = await tx.getExchange(exchangeBaseUrl); if (!exchange) { throw Error("exchange not found"); } @@ -3914,7 +3896,7 @@ async function handleExchangeKycRespLegi( if (reserveId == null) { throw Error("expected exchange to have reserve ID"); } - const reserve = await tx.wtx.getReserve(reserveId); + const reserve = await tx.getReserve(reserveId); checkDbInvariant(!!reserve, "merge reserve should exist"); switch (reserve.status) { case ReserveRecordStatus.PendingLegiInit: @@ -3927,7 +3909,7 @@ async function handleExchangeKycRespLegi( reserve.amlReview = accountKycStatusResp.aml_review; reserve.kycAccessToken = accountKycStatusResp.access_token; - await tx.wtx.upsertReserve(reserve); + await tx.upsertReserve(reserve); tx.notify({ type: NotificationType.ExchangeStateTransition, exchangeBaseUrl: exchange.baseUrl, @@ -4013,15 +3995,15 @@ export async function processExchangeKyc( wex: WalletExecutionContext, exchangeBaseUrl: string, ): Promise<TaskRunResult> { - const res = await wex.runLegacyWalletDbTx(async (tx) => { - const exchange = await tx.wtx.getExchange(exchangeBaseUrl); + const res = await wex.runWalletDbTx(async (tx) => { + const exchange = await tx.getExchange(exchangeBaseUrl); if (!exchange) { return undefined; } const reserveId = exchange.currentMergeReserveRowId; let reserve: WalletReserve | undefined = undefined; if (reserveId != null) { - reserve = await tx.wtx.getReserve(reserveId); + reserve = await tx.getReserve(reserveId); } return { exchange, reserve }; }); @@ -4053,7 +4035,7 @@ export async function processExchangeKyc( } export async function checkExchangeInScopeTx( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, exchangeBaseUrl: string, scope: ScopeInfo, ): Promise<boolean> { @@ -4066,14 +4048,14 @@ export async function checkExchangeInScopeTx( } case ScopeType.Global: { const exchangeDetails = await getExchangeRecordsInternal( - tx.wtx, + tx, exchangeBaseUrl, ); if (!exchangeDetails) { logger.trace(`no details for ${exchangeBaseUrl}`); return false; } - const gr = await tx.wtx.getGlobalCurrencyExchange( + const gr = await tx.getGlobalCurrencyExchange( exchangeDetails.currency, exchangeBaseUrl, exchangeDetails.masterPublicKey, @@ -4106,8 +4088,8 @@ export async function getPreferredExchangeForCurrency( } // Find an exchange with the matching currency. // Prefer exchanges with the most recent withdrawal. - const url = await wex.runLegacyWalletDbTx(async (tx) => { - const exchanges = await tx.wtx.getExchanges(); + const url = await wex.runWalletDbTx(async (tx) => { + const exchanges = await tx.getExchanges(); logger.trace(`have ${exchanges.length} exchanges`); let candidate = undefined; for (const e of exchanges) { @@ -4164,8 +4146,8 @@ export async function migrateExchange( wex: WalletExecutionContext, req: MigrateExchangeRequest, ): Promise<void> { - await wex.runLegacyWalletDbTx(async (tx) => { - const migrationRec = await tx.wtx.getExchangeMigrationLog( + await wex.runWalletDbTx(async (tx) => { + const migrationRec = await tx.getExchangeMigrationLog( req.oldExchangeBaseUrl, req.newExchangeBaseUrl, ); @@ -4176,7 +4158,7 @@ export async function migrateExchange( return; } - const exch = await tx.wtx.getExchange(req.oldExchangeBaseUrl); + const exch = await tx.getExchange(req.oldExchangeBaseUrl); if (!exch) { logger.warn(`exchange ${req.oldExchangeBaseUrl} does not exist anymore`); return; @@ -4184,65 +4166,64 @@ export async function migrateExchange( let existingNewExchangeSt: ExchangeEntryState | undefined = undefined; - await tx.wtx.upsertExchangeMigrationLog({ + await tx.upsertExchangeMigrationLog({ oldExchangeBaseUrl: req.oldExchangeBaseUrl, newExchangeBaseUrl: req.newExchangeBaseUrl, timestamp: timestampPreciseToDb(TalerPreciseTimestamp.now()), reason: req.trigger, }); - await tx.wtx.upsertExchangeBaseUrlFixup({ + await tx.upsertExchangeBaseUrlFixup({ exchangeBaseUrl: req.oldExchangeBaseUrl, replacement: req.newExchangeBaseUrl, }); { - const denoms = await tx.wtx.getDenominationsByExchange( + const denoms = await tx.getDenominationsByExchange( req.oldExchangeBaseUrl, ); for (const rec of denoms) { rec.exchangeBaseUrl = req.newExchangeBaseUrl; - await tx.wtx.upsertDenomination(rec); + await tx.upsertDenomination(rec); } } { - const recs = await tx.wtx.listAllDenomLossEvents(); + const recs = await tx.listAllDenomLossEvents(); for (const rec of recs) { if (rec.exchangeBaseUrl === req.oldExchangeBaseUrl) { rec.exchangeBaseUrl = req.newExchangeBaseUrl; - await tx.wtx.upsertDenomLossEvent(rec); + await tx.upsertDenomLossEvent(rec); } } } { - const recs = await tx.wtx.getRecoupGroupsByExchange( - req.oldExchangeBaseUrl, - ); + const recs = await tx.getRecoupGroupsByExchange(req.oldExchangeBaseUrl); for (const rec of recs) { rec.exchangeBaseUrl = req.newExchangeBaseUrl; - await tx.wtx.upsertRecoupGroup(rec); + await tx.upsertRecoupGroup(rec); } } { - const existingNewExchangeDetails = - await tx.wtx.getExchangeDetailsByBaseUrl(req.newExchangeBaseUrl); + const existingNewExchangeDetails = await tx.getExchangeDetailsByBaseUrl( + req.newExchangeBaseUrl, + ); if (!existingNewExchangeDetails) { - const oldDetails = await tx.wtx.listExchangeDetailsByBaseUrl( + const oldDetails = await tx.listExchangeDetailsByBaseUrl( req.oldExchangeBaseUrl, ); for (const rec of oldDetails) { rec.exchangeBaseUrl = req.newExchangeBaseUrl; - await tx.wtx.upsertExchangeDetails(rec); + await tx.upsertExchangeDetails(rec); } } } { - const rec = await tx.wtx.getExchange(req.oldExchangeBaseUrl); + const rec = await tx.getExchange(req.oldExchangeBaseUrl); if (rec) { existingNewExchangeSt = { exchangeEntryStatus: getExchangeEntryStatusFromRecord(rec), @@ -4250,86 +4231,86 @@ export async function migrateExchange( tosStatus: getExchangeTosStatusFromRecord(rec), }; rec.baseUrl = req.newExchangeBaseUrl; - await tx.wtx.deleteExchange(req.oldExchangeBaseUrl); - await tx.wtx.upsertExchange(rec); + await tx.deleteExchange(req.oldExchangeBaseUrl); + await tx.upsertExchange(rec); } } { - const recs = await tx.wtx.getCoinsByExchange(req.oldExchangeBaseUrl); + const recs = await tx.getCoinsByExchange(req.oldExchangeBaseUrl); for (const rec of recs) { rec.exchangeBaseUrl = req.newExchangeBaseUrl; - await tx.wtx.upsertCoin(rec); + await tx.upsertCoin(rec); } } { - const recs = await tx.wtx.getCoinAvailabilityByExchange( + const recs = await tx.getCoinAvailabilityByExchange( req.oldExchangeBaseUrl, ); for (const rec of recs) { - await tx.wtx.deleteCoinAvailability( + await tx.deleteCoinAvailability( rec.exchangeBaseUrl, rec.denomPubHash, rec.maxAge, ); rec.exchangeBaseUrl = req.newExchangeBaseUrl; - await tx.wtx.upsertCoinAvailability(rec); + await tx.upsertCoinAvailability(rec); } } { - const recs = await tx.wtx.listAllPeerPullCredits(); + const recs = await tx.listAllPeerPullCredits(); for (const rec of recs) { if (rec.exchangeBaseUrl === req.oldExchangeBaseUrl) { rec.exchangeBaseUrl = req.newExchangeBaseUrl; - await tx.wtx.upsertPeerPullCredit(rec); + await tx.upsertPeerPullCredit(rec); } } } { - const recs = await tx.wtx.listAllPeerPullDebits(); + const recs = await tx.listAllPeerPullDebits(); for (const rec of recs) { if (rec.exchangeBaseUrl === req.oldExchangeBaseUrl) { rec.exchangeBaseUrl = req.newExchangeBaseUrl; - await tx.wtx.upsertPeerPullDebit(rec); + await tx.upsertPeerPullDebit(rec); } } } { - const recs = await tx.wtx.listAllPeerPushCredits(); + const recs = await tx.listAllPeerPushCredits(); for (const rec of recs) { if (rec.exchangeBaseUrl === req.oldExchangeBaseUrl) { rec.exchangeBaseUrl = req.newExchangeBaseUrl; - await tx.wtx.upsertPeerPushCredit(rec); + await tx.upsertPeerPushCredit(rec); } } } { - const recs = await tx.wtx.listAllPeerPushDebits(); + const recs = await tx.listAllPeerPushDebits(); for (const rec of recs) { if (rec.exchangeBaseUrl === req.oldExchangeBaseUrl) { rec.exchangeBaseUrl = req.newExchangeBaseUrl; - await tx.wtx.upsertPeerPushDebit(rec); + await tx.upsertPeerPushDebit(rec); } } } { - const recs = await tx.wtx.getWithdrawalGroupsByExchangeForRekey( + const recs = await tx.getWithdrawalGroupsByExchangeForRekey( req.oldExchangeBaseUrl, ); for (const rec of recs) { rec.exchangeBaseUrl = req.newExchangeBaseUrl; - await tx.wtx.upsertWithdrawalGroup(rec); + await tx.upsertWithdrawalGroup(rec); } } { - const recs = await tx.wtx.listAllRefreshGroups(); + const recs = await tx.listAllRefreshGroups(); for (const rec of recs) { if ( rec.infoPerExchange && @@ -4338,13 +4319,13 @@ export async function migrateExchange( rec.infoPerExchange[req.newExchangeBaseUrl] = rec.infoPerExchange[req.oldExchangeBaseUrl]; delete rec.infoPerExchange[req.oldExchangeBaseUrl]; - await tx.wtx.upsertRefreshGroup(rec); + await tx.upsertRefreshGroup(rec); } } } { - const recs = await tx.wtx.listAllDepositGroups(); + const recs = await tx.listAllDepositGroups(); for (const rec of recs) { if ( rec.infoPerExchange && @@ -4353,7 +4334,7 @@ export async function migrateExchange( rec.infoPerExchange[req.newExchangeBaseUrl] = rec.infoPerExchange[req.oldExchangeBaseUrl]; delete rec.infoPerExchange[req.oldExchangeBaseUrl]; - await tx.wtx.upsertDepositGroup(rec); + await tx.upsertDepositGroup(rec); } } } diff --git a/packages/taler-wallet-core/src/instructedAmountConversion.ts b/packages/taler-wallet-core/src/instructedAmountConversion.ts @@ -14,7 +14,6 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -import { GlobalIDB } from "@gnu-taler/idb-bridge"; import { AbsoluteTime, AgeRestriction, @@ -127,19 +126,16 @@ async function getAvailableCoins( ): Promise<AvailableCoins> { const operationType = getOperationType(op); - return await wex.runLegacyWalletDbTx(async (tx) => { + return await wex.runWalletDbTx(async (tx) => { const list: CoinInfo[] = []; const exchanges: Record<string, ExchangeInfo> = {}; - const databaseExchanges = await tx.wtx.getExchanges(); + const databaseExchanges = await tx.getExchanges(); const filteredExchanges = filters.exchanges ?? databaseExchanges.map((e) => e.baseUrl); for (const exchangeBaseUrl of filteredExchanges) { - const exchangeDetails = await getExchangeDetailsInTx( - tx.wtx, - exchangeBaseUrl, - ); + const exchangeDetails = await getExchangeDetailsInTx(tx, exchangeBaseUrl); // 1.- exchange has same currency if (exchangeDetails?.currency !== currency) { continue; @@ -205,7 +201,7 @@ async function getAvailableCoins( //4.- filter coins restricted by age if (operationType === OperationType.Credit) { // FIXME: Use denom groups instead of querying all denominations! - const ds = await tx.wtx.getDenominationsByExchange(exchangeBaseUrl); + const ds = await tx.getDenominationsByExchange(exchangeBaseUrl); for (const denom of ds) { const expiresWithdraw = AbsoluteTime.fromProtocolTimestamp( timestampProtocolFromDb(denom.stampExpireWithdraw), @@ -230,7 +226,7 @@ async function getAvailableCoins( const ageUpper = AgeRestriction.AGE_UNRESTRICTED; const myExchangeCoins = - await tx.wtx.getCoinAvailabilityByExchangeAndAgeRange( + await tx.getCoinAvailabilityByExchangeAndAgeRange( exchangeDetails.exchangeBaseUrl, ageLower, ageUpper, @@ -240,7 +236,7 @@ async function getAvailableCoins( // FIXME: Should we exclude denominations that are // not spendable anymore? for (const coinAvail of myExchangeCoins) { - const denom = await tx.wtx.getDenomination( + const denom = await tx.getDenomination( coinAvail.exchangeBaseUrl, coinAvail.denomPubHash, ); diff --git a/packages/taler-wallet-core/src/pay-merchant.ts b/packages/taler-wallet-core/src/pay-merchant.ts @@ -187,7 +187,6 @@ import { import { EXCHANGE_COINS_LOCK, getDenomInfo, - LegacyWalletTxHandle, WalletExecutionContext, walletMerchantClient, } from "./wallet.js"; @@ -410,8 +409,8 @@ export class PayMerchantTransactionContext implements TransactionContext { } async userDeleteTransaction(): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - return this.deleteTransactionInTx(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + return this.deleteTransactionInTx(tx); }); } @@ -456,8 +455,8 @@ export class PayMerchantTransactionContext implements TransactionContext { async userSuspendTransaction(): Promise<void> { const { wex } = this; wex.taskScheduler.stopShepherdTask(this.taskId); - await wex.runLegacyWalletDbTx(async (tx) => { - const [purchase, h] = await this.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [purchase, h] = await this.getRecordHandle(tx); if (!purchase) { throw Error("purchase not found"); } @@ -475,8 +474,8 @@ export class PayMerchantTransactionContext implements TransactionContext { reason?: TalerErrorDetail, ): Promise<void> { const { wex } = this; - await wex.runLegacyWalletDbTx(async (tx) => { - const [purchase, h] = await this.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [purchase, h] = await this.getRecordHandle(tx); if (purchase?.purchaseStatus != fromSt) { return; } @@ -488,8 +487,8 @@ 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.wtx); + await wex.runWalletDbTx(async (tx) => { + const [purchase, h] = await this.getRecordHandle(tx); if (!purchase) { throw Error("purchase not found"); } @@ -526,8 +525,8 @@ export class PayMerchantTransactionContext implements TransactionContext { async userResumeTransaction(): Promise<void> { const { wex } = this; - await wex.runLegacyWalletDbTx(async (tx) => { - const [purchase, h] = await this.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [purchase, h] = await this.getRecordHandle(tx); if (!purchase) { throw Error("purchase not found"); } @@ -543,8 +542,8 @@ 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.wtx); + await wex.runWalletDbTx(async (tx) => { + const [purchase, h] = await this.getRecordHandle(tx); if (!purchase) { throw Error("purchase not found"); } @@ -557,7 +556,7 @@ export class PayMerchantTransactionContext implements TransactionContext { return; } await h.update(purchase, BalanceEffect.Any); - tx._util.scheduleOnCommit(() => + tx.scheduleOnCommit(() => wex.taskScheduler.stopShepherdTask(this.taskId), ); }); @@ -738,8 +737,8 @@ export class RefundTransactionContext implements TransactionContext { async userDeleteTransaction(): Promise<void> { const { wex } = this; - const res = await wex.runLegacyWalletDbTx(async (tx) => { - return await this.deleteTransactionInTx(tx.wtx); + const res = await wex.runWalletDbTx(async (tx) => { + return await this.deleteTransactionInTx(tx); }); for (const notif of res.notifs) { this.wex.ws.notify(notif); @@ -821,20 +820,20 @@ export async function getTotalPaymentCost( currency: string, pcs: SelectedProspectiveCoin[], ): Promise<AmountJson> { - return await wex.runLegacyWalletDbTx(async (tx) => { + return await wex.runWalletDbTx(async (tx) => { return await getTotalPaymentCostInTx(wex, tx, currency, pcs); }); } export async function getTotalPaymentCostInTx( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, currency: string, pcs: SelectedProspectiveCoin[], ): Promise<AmountJson> { const costs: AmountJson[] = []; for (let i = 0; i < pcs.length; i++) { - const denom = await tx.wtx.getDenomination( + const denom = await tx.getDenomination( pcs[i].exchangeBaseUrl, pcs[i].denomPubHash, ); @@ -863,8 +862,8 @@ async function failProposalClaimPermanently( err: TalerErrorDetail, ): Promise<void> { const ctx = new PayMerchantTransactionContext(wex, proposalId); - await wex.runLegacyWalletDbTx(async (tx) => { - const [p, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [p, h] = await ctx.getRecordHandle(tx); if (!p) { return; } @@ -883,14 +882,14 @@ function getPayRequestTimeout(purchase: WalletPurchase): Duration { export async function expectProposalDownloadByIdInTx( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, proposalId: string, ): Promise<DownloadedContractData> { - const rec = await tx.wtx.getPurchase(proposalId); + const rec = await tx.getPurchase(proposalId); if (!rec) { throw Error("purchase record not found"); } - return await expectProposalDownloadInTx(wex, tx.wtx, rec); + return await expectProposalDownloadInTx(wex, tx, rec); } export async function expectProposalDownloadInTx( @@ -935,8 +934,8 @@ async function processDownloadProposal( wex: WalletExecutionContext, proposalId: string, ): Promise<TaskRunResult> { - const proposal = await wex.runLegacyWalletDbTx(async (tx) => { - return await tx.wtx.getPurchase(proposalId); + const proposal = await wex.runWalletDbTx(async (tx) => { + return await tx.getPurchase(proposalId); }); if (!proposal) { @@ -1134,8 +1133,8 @@ async function processDownloadProposal( logger.trace(`extracted contract data: ${j2s(contractData)}`); - await wex.runLegacyWalletDbTx(async (tx) => { - const [p, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [p, h] = await ctx.getRecordHandle(tx); if (!p) { return; } @@ -1183,7 +1182,7 @@ async function processDownloadProposal( currency, fulfillmentUrl: contractData.contractTerms.fulfillment_url, }; - await tx.wtx.upsertContractTerms({ + await tx.upsertContractTerms({ h: contractTermsHash, contractTermsRaw: proposalResp.contract_terms, }); @@ -1196,7 +1195,7 @@ async function processDownloadProposal( // fulfillmentUrl is set. Previously this passed undefined straight to // the index, which scans the whole store for a result that is then unused. const otherPurchases = fulfillmentUrl - ? await tx.wtx.getPurchasesByFulfillmentUrl(fulfillmentUrl) + ? await tx.getPurchasesByFulfillmentUrl(fulfillmentUrl) : []; if (isResourceFulfillmentUrl) { for (const otherPurchase of otherPurchases) { @@ -1231,19 +1230,19 @@ async function processDownloadProposal( async function startPayReplay( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, proposalId: string, sessionId: string | undefined, ): Promise<void> { logger.info(`starting pay replay of ${proposalId} under ${sessionId}`); const ctx = new PayMerchantTransactionContext(wex, proposalId); - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + const [rec, h] = await ctx.getRecordHandle(tx); if (rec && rec.purchaseStatus === PurchaseStatus.Done) { rec.purchaseStatus = PurchaseStatus.PendingPayingReplay; rec.lastSessionId = sessionId; } await h.update(rec); - tx._util.scheduleOnCommit(() => { + tx.scheduleOnCommit(() => { wex.taskScheduler.resetTask(ctx.taskId).catch((e) => { logger.error(safeStringifyException(e)); }); @@ -1268,8 +1267,8 @@ async function generateSlate( `generating slate (${choiceIndex}, ${outputIndex}, ${repeatIndex}) for purchase ${purchase.proposalId}`, ); - let slate = await wex.runLegacyWalletDbTx(async (tx) => { - return await tx.wtx.getSlate( + let slate = await wex.runWalletDbTx(async (tx) => { + return await tx.getSlate( purchase.proposalId, choiceIndex, outputIndex, @@ -1325,8 +1324,8 @@ async function generateSlate( newSlate.tokenFamilyHash = WalletToken.hashInfo(newSlate); - await wex.runLegacyWalletDbTx(async (tx) => { - const s = await tx.wtx.getSlate( + await wex.runWalletDbTx(async (tx) => { + const s = await tx.getSlate( purchase.proposalId, choiceIndex, outputIndex, @@ -1335,7 +1334,7 @@ async function generateSlate( if (s) { return; } - await tx.wtx.upsertSlate(newSlate); + await tx.upsertSlate(newSlate); }); } @@ -1357,8 +1356,8 @@ async function createOrReusePurchase( }> { // Find existing proposals from the same merchant // with the same order ID. - const oldProposals = await wex.runLegacyWalletDbTx(async (tx) => { - return tx.wtx.getPurchasesByUrlAndOrderId(merchantBaseUrl, orderId); + const oldProposals = await wex.runWalletDbTx(async (tx) => { + return tx.getPurchasesByUrlAndOrderId(merchantBaseUrl, orderId); }); if (oldProposals.length > 1) { @@ -1398,7 +1397,7 @@ async function createOrReusePurchase( case PurchaseStatus.Done: case PurchaseStatus.PendingPayingReplay: case PurchaseStatus.SuspendedPayingReplay: - await wex.runLegacyWalletDbTx(async (tx) => { + await wex.runWalletDbTx(async (tx) => { await startPayReplay(wex, tx, oldProposal.proposalId, sessionId); }); break; @@ -1406,7 +1405,7 @@ async function createOrReusePurchase( // Trigger replay on *old* payment const repId = oldProposal.repurchaseProposalId; if (repId != null) { - await wex.runLegacyWalletDbTx(async (tx) => { + await wex.runWalletDbTx(async (tx) => { await startPayReplay(wex, tx, repId, sessionId); }); } @@ -1420,8 +1419,8 @@ async function createOrReusePurchase( // if this transaction was shared and the order is paid then it // means that another wallet already paid the proposal if (paid) { - await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await oldCtx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await oldCtx.getRecordHandle(tx); // 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. @@ -1493,9 +1492,9 @@ async function createOrReusePurchase( const ctx = new PayMerchantTransactionContext(wex, proposalId); - await wex.runLegacyWalletDbTx(async (tx) => { - await tx.wtx.upsertPurchase(proposalRecord); - await ctx.updateTransactionMeta(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + await tx.upsertPurchase(proposalRecord); + await ctx.updateTransactionMeta(tx); const oldTxState: TransactionState = { major: TransactionMajorState.None, }; @@ -1507,7 +1506,7 @@ async function createOrReusePurchase( oldStId: 0, newStId: proposalRecord.purchaseStatus, }); - tx._util.scheduleOnCommit(() => { + tx.scheduleOnCommit(() => { wex.taskScheduler.resetTask(ctx.taskId).catch((e) => { logger.error(safeStringifyException(e)); }); @@ -1528,8 +1527,8 @@ async function storeFirstPaySuccess( ): Promise<void> { const ctx = new PayMerchantTransactionContext(wex, proposalId); const now = AbsoluteTime.toPreciseTimestamp(AbsoluteTime.now()); - await wex.runLegacyWalletDbTx(async (tx) => { - const [purchase, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [purchase, h] = await ctx.getRecordHandle(tx); if (!purchase) { return; } @@ -1550,9 +1549,7 @@ async function storeFirstPaySuccess( !!dl, `purchase ${purchase.orderId} without ct downloaded`, ); - const contractTermsRecord = await tx.wtx.getContractTerms( - dl.contractTermsHash, - ); + const contractTermsRecord = await tx.getContractTerms(dl.contractTermsHash); checkDbInvariant( !!contractTermsRecord, `no contract terms found for purchase ${purchase.orderId}`, @@ -1581,8 +1578,8 @@ async function storePayReplaySuccess( sessionId: string | undefined, ): Promise<void> { const ctx = new PayMerchantTransactionContext(wex, proposalId); - await wex.runLegacyWalletDbTx(async (tx) => { - const [purchase, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [purchase, h] = await ctx.getRecordHandle(tx); if (!purchase) { return; } @@ -1613,11 +1610,11 @@ function setCoinSel(rec: WalletPurchase, coinSel: PayCoinSelection): void { } async function reselectCoinsTx( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, ctx: PayMerchantTransactionContext, excludeCoinPub?: string, ): Promise<void> { - const p = await tx.wtx.getPurchase(ctx.proposalId); + const p = await tx.getPurchase(ctx.proposalId); if (!p) { return; } @@ -1696,7 +1693,7 @@ async function reselectCoinsTx( if (contractData.contractTerms.version !== MerchantContractVersion.V1) throw Error("assertion failed"); - const res = await selectPayTokensInTx(tx.wtx, { + const res = await selectPayTokensInTx(tx, { proposalId: p.proposalId, choiceIndex: p.choiceIndex, contractTerms: contractData.contractTerms, @@ -1718,8 +1715,8 @@ async function reselectCoinsTx( }; } - await tx.wtx.upsertPurchase(p); - await ctx.updateTransactionMeta(tx.wtx); + await tx.upsertPurchase(p); + await ctx.updateTransactionMeta(tx); if (p.payInfo.payCoinSelection) { await spendCoins(ctx.wex, tx, { @@ -1733,7 +1730,7 @@ async function reselectCoinsTx( } if (p.payInfo.payTokenSelection) { - await spendTokens(tx.wtx, { + await spendTokens(tx, { transactionId: ctx.transactionId, tokenPubs: p.payInfo.payTokenSelection.tokenPubs, }); @@ -1757,8 +1754,8 @@ async function handleInsufficientFunds( const ctx = new PayMerchantTransactionContext(wex, proposalId); - const proposal = await wex.runLegacyWalletDbTx(async (tx) => { - return tx.wtx.getPurchase(proposalId); + const proposal = await wex.runWalletDbTx(async (tx) => { + return tx.getPurchase(proposalId); }); if (!proposal) { return TaskRunResult.finished(); @@ -1821,7 +1818,7 @@ async function handleInsufficientFunds( // FIXME: Above code should go into the transaction. // TODO: also do token re-selection. - await wex.runLegacyWalletDbTx(async (tx) => { + await wex.runWalletDbTx(async (tx) => { await reselectCoinsTx(tx, ctx, brokenCoinPub); }); @@ -1851,8 +1848,8 @@ async function lookupProposalOrRepurchase( } | undefined > { - return await wex.runLegacyWalletDbTx(async (tx) => { - let purchaseRec = await tx.wtx.getPurchase(proposalId); + return await wex.runWalletDbTx(async (tx) => { + let purchaseRec = await tx.getPurchase(proposalId); if (!purchaseRec) { return undefined; @@ -1862,7 +1859,7 @@ async function lookupProposalOrRepurchase( const existingProposalId = purchaseRec.repurchaseProposalId; if (existingProposalId) { logger.trace("using existing purchase for same product"); - const oldProposal = await tx.wtx.getPurchase(existingProposalId); + const oldProposal = await tx.getPurchase(existingProposalId); if (oldProposal) { purchaseRec = oldProposal; } @@ -1921,9 +1918,9 @@ async function checkPaymentByProposalId( claimToken: purchaseRec.claimToken, }); - const scopes = await wex.runLegacyWalletDbTx(async (tx) => { + const scopes = await wex.runWalletDbTx(async (tx) => { let exchangeUrls = contractTerms.exchanges.map((x) => x.url); - return await getScopeForAllExchanges(tx.wtx, exchangeUrls); + return await getScopeForAllExchanges(tx, exchangeUrls); }); const handleUnconfirmed = async (): Promise<PreparePayResult> => { @@ -1966,8 +1963,8 @@ async function checkPaymentByProposalId( res.insufficientBalanceDetails, )}`, ); - let scopes = await wex.runLegacyWalletDbTx(async (tx) => { - return getScopeForAllExchanges(tx.wtx, allowedExchangeUrls); + let scopes = await wex.runWalletDbTx(async (tx) => { + return getScopeForAllExchanges(tx, allowedExchangeUrls); }); return { status: PreparePayResultType.InsufficientBalance, @@ -1993,8 +1990,8 @@ async function checkPaymentByProposalId( const exchanges = new Set<string>(coins.map((x) => x.exchangeBaseUrl)); - const scopes = await wex.runLegacyWalletDbTx(async (tx) => { - return await getScopeForAllExchanges(tx.wtx, [...exchanges]); + const scopes = await wex.runWalletDbTx(async (tx) => { + return await getScopeForAllExchanges(tx, [...exchanges]); }); return { @@ -2014,8 +2011,8 @@ async function checkPaymentByProposalId( "automatically re-submitting payment with different session ID", ); logger.trace(`last: ${purchaseRec.lastSessionId}, current: ${sessionId}`); - await wex.runLegacyWalletDbTx(async (tx) => { - const [p, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [p, h] = await ctx.getRecordHandle(tx); if (!p) { return; } @@ -2247,11 +2244,11 @@ async function waitProposalDownloaded( ); }, async checkState() { - const { purchase, retryInfo } = await ctx.wex.runLegacyWalletDbTx( + const { purchase, retryInfo } = await ctx.wex.runWalletDbTx( async (tx) => { return { - purchase: await tx.wtx.getPurchase(ctx.proposalId), - retryInfo: await tx.wtx.getOperationRetry(ctx.taskId), + purchase: await tx.getPurchase(ctx.proposalId), + retryInfo: await tx.getOperationRetry(ctx.taskId), }; }, ); @@ -2311,13 +2308,13 @@ export async function generateDepositPermissions( coin: WalletCoin; denom: WalletDenomination; }> = []; - await wex.runLegacyWalletDbTx(async (tx) => { + await wex.runWalletDbTx(async (tx) => { for (let i = 0; i < payCoinSel.coinContributions.length; i++) { - const coin = await tx.wtx.getCoin(payCoinSel.coinPubs[i]); + const coin = await tx.getCoin(payCoinSel.coinPubs[i]); if (!coin) { throw Error("can't pay, allocated coin not found anymore"); } - const denom = await tx.wtx.getDenomination( + const denom = await tx.getDenomination( coin.exchangeBaseUrl, coin.denomPubHash, ); @@ -2382,9 +2379,9 @@ async function waitPaymentResult( ); }, async checkState() { - const txRes = await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const purchase = await tx.wtx.getPurchase(ctx.proposalId); - const retryRecord = await tx.wtx.getOperationRetry(ctx.taskId); + const txRes = await ctx.wex.runWalletDbTx(async (tx) => { + const purchase = await tx.getPurchase(ctx.proposalId); + const retryRecord = await tx.getOperationRetry(ctx.taskId); return { purchase, retryRecord }; }); @@ -2449,15 +2446,15 @@ export async function getChoicesForPayment( throw Error("expected payment transaction ID"); } const proposalId = parsedTx.proposalId; - const { proposal, d } = await wex.runLegacyWalletDbTx(async (tx) => { - const proposal = await tx.wtx.getPurchase(proposalId); + const { proposal, d } = await wex.runWalletDbTx(async (tx) => { + const proposal = await tx.getPurchase(proposalId); let d: DownloadedContractData | undefined = undefined; if (proposal) { const download = proposal.download; if (!download) { return { proposal }; } - const contractTermsRec = await tx.wtx.getContractTerms( + const contractTermsRec = await tx.getContractTerms( download.contractTermsHash, ); if (contractTermsRec) { @@ -2488,7 +2485,7 @@ export async function getChoicesForPayment( } const choices: ChoiceSelectionDetail[] = []; - await wex.runLegacyWalletDbTx(async (tx) => { + await wex.runWalletDbTx(async (tx) => { const tokenSels: SelectPayTokensResult[] = []; const contractTerms: MerchantContractTerms = d.contractTerms; switch (contractTerms.version) { @@ -2509,7 +2506,7 @@ export async function getChoicesForPayment( case MerchantContractVersion.V1: for (let i = 0; i < contractTerms.choices.length; i++) { tokenSels.push( - await selectPayTokensInTx(tx.wtx, { + await selectPayTokensInTx(tx, { proposalId, choiceIndex: i, contractTerms: contractTerms, @@ -2598,7 +2595,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.wtx, exch); + const s = await getExchangeScopeInfoOrUndefined(tx, exch); if (s != null) { scopeInfo = s; break; @@ -2739,8 +2736,8 @@ export async function confirmPay( logger.trace( `executing confirmPay with proposalId ${proposalId} and sessionIdOverride ${sessionIdOverride}`, ); - const proposal = await wex.runLegacyWalletDbTx(async (tx) => { - return tx.wtx.getPurchase(proposalId); + const proposal = await wex.runWalletDbTx(async (tx) => { + return tx.getPurchase(proposalId); }); if (!proposal) { @@ -2752,8 +2749,8 @@ export async function confirmPay( throw Error("proposal is in invalid state"); } - const existingPurchase = await wex.runLegacyWalletDbTx(async (tx) => { - const purchase = await tx.wtx.getPurchase(proposalId); + const existingPurchase = await wex.runWalletDbTx(async (tx) => { + const purchase = await tx.getPurchase(proposalId); if ( purchase && sessionIdOverride !== undefined && @@ -2764,8 +2761,8 @@ export async function confirmPay( if (purchase.purchaseStatus === PurchaseStatus.Done) { purchase.purchaseStatus = PurchaseStatus.PendingPayingReplay; } - await tx.wtx.upsertPurchase(purchase); - await ctx.updateTransactionMeta(tx.wtx); + await tx.upsertPurchase(purchase); + await ctx.updateTransactionMeta(tx); } return purchase; }); @@ -2819,8 +2816,8 @@ export async function confirmPay( `recording payment on ${proposal.orderId} with session ID ${sessionId}`, ); - await wex.runLegacyWalletDbTx(async (tx) => { - const [p, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [p, h] = await ctx.getRecordHandle(tx); if (!p) { return; } @@ -2828,7 +2825,7 @@ export async function confirmPay( let selectTokensResult: SelectPayTokensResult | undefined; if (contractTerms.version === MerchantContractVersion.V1) { - selectTokensResult = await selectPayTokensInTx(tx.wtx, { + selectTokensResult = await selectPayTokensInTx(tx, { proposalId, choiceIndex: choiceIndex!, contractTerms, @@ -2894,7 +2891,7 @@ export async function confirmPay( p.download.currency = Amounts.currencyOf(amount); } - const confRes = await tx.wtx.getConfig(ConfigRecordKey.DonauConfig); + const confRes = await tx.getConfig(ConfigRecordKey.DonauConfig); logger.info( `donau conf: ${j2s(confRes)}, useDonau: ${ @@ -2954,7 +2951,7 @@ export async function confirmPay( p.purchaseStatus = PurchaseStatus.PendingPaying; await h.update(p); if (p.payInfo.payTokenSelection) { - await spendTokens(tx.wtx, { + await spendTokens(tx, { tokenPubs: p.payInfo.payTokenSelection.tokenPubs, transactionId: ctx.transactionId, }); @@ -3031,8 +3028,8 @@ export async function processPurchase( wex: WalletExecutionContext, proposalId: string, ): Promise<TaskRunResult> { - const purchase = await wex.runLegacyWalletDbTx(async (tx) => { - return tx.wtx.getPurchase(proposalId); + const purchase = await wex.runWalletDbTx(async (tx) => { + return tx.getPurchase(proposalId); }); if (!purchase) { return { @@ -3099,8 +3096,8 @@ async function processPurchasePay( wex: WalletExecutionContext, proposalId: string, ): Promise<TaskRunResult> { - const purchase = await wex.runLegacyWalletDbTx(async (tx) => { - return tx.wtx.getPurchase(proposalId); + const purchase = await wex.runWalletDbTx(async (tx) => { + return tx.getPurchase(proposalId); }); if (!purchase) { return { @@ -3137,8 +3134,8 @@ async function processPurchasePay( const paid = await checkIfOrderIsAlreadyPaid(wex, download, false); if (paid) { - await wex.runLegacyWalletDbTx(async (tx) => { - const [p, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [p, h] = await ctx.getRecordHandle(tx); if (!p) { return; } @@ -3206,8 +3203,8 @@ async function processPurchasePay( selectCoinsResult.coinSel.coins, ); - const transitionDone = await wex.runLegacyWalletDbTx(async (tx) => { - const p = await tx.wtx.getPurchase(proposalId); + const transitionDone = await wex.runWalletDbTx(async (tx) => { + const p = await tx.getPurchase(proposalId); if (!p) { return false; } @@ -3229,8 +3226,8 @@ async function processPurchasePay( }; p.payInfo.payCoinSelectionUid = encodeCrock(getRandomBytes(16)); p.purchaseStatus = PurchaseStatus.PendingPaying; - await tx.wtx.upsertPurchase(p); - await ctx.updateTransactionMeta(tx.wtx); + await tx.upsertPurchase(p); + await ctx.updateTransactionMeta(tx); await spendCoins(wex, tx, { transactionId: ctx.transactionId, coinPubs: selectCoinsResult.coinSel.coins.map((x) => x.coinPub), @@ -3272,10 +3269,10 @@ async function processPurchasePay( const index = purchase.choiceIndex; slates = []; wallet_data = { choice_index: index, tokens_evs: [] }; - await wex.runLegacyWalletDbTx(async (tx) => { - const allSlateRes = await tx.wtx.listSlates(); + await wex.runWalletDbTx(async (tx) => { + const allSlateRes = await tx.listSlates(); logger.info(`all slates: ${j2s(allSlateRes)}`); - const slateRes = await tx.wtx.getSlatesByPurchaseAndChoice( + const slateRes = await tx.getSlatesByPurchaseAndChoice( purchase.proposalId, index, ); @@ -3296,8 +3293,8 @@ async function processPurchasePay( } const budikeypairs: BlindedDonationReceiptKeyPair[] = []; // FIXME: Merge with transaction above - const res = await wex.runLegacyWalletDbTx(async (tx) => { - const recs = await tx.wtx.getDonationPlanchetsByProposal(proposalId); + const res = await wex.runWalletDbTx(async (tx) => { + const recs = await tx.getDonationPlanchetsByProposal(proposalId); for (const rec of recs) { budikeypairs.push({ blinded_udi: rec.blindedUdi, @@ -3489,12 +3486,12 @@ async function processPurchasePay( } if (tokenSigs) { - await wex.runLegacyWalletDbTx(async (tx) => { + await wex.runWalletDbTx(async (tx) => { if (!purchase.payInfo) { return; } purchase.payInfo.slateTokenSigs = tokenSigs; - tx.wtx.upsertPurchase(purchase); + tx.upsertPurchase(purchase); }); } @@ -3615,9 +3612,9 @@ export async function validateAndStoreToken( }; // insert token and delete slate - await wex.runLegacyWalletDbTx(async (tx) => { - await tx.wtx.upsertToken(token); - await tx.wtx.deleteSlate(slate.tokenUsePub); + await wex.runWalletDbTx(async (tx) => { + await tx.upsertToken(token); + await tx.deleteSlate(slate.tokenUsePub); }); } @@ -3630,9 +3627,9 @@ export async function generateTokenSigs( ): Promise<TokenUseSig[]> { const tokens: WalletToken[] = []; const sigs: TokenUseSig[] = []; - await wex.runLegacyWalletDbTx(async (tx) => { + await wex.runWalletDbTx(async (tx) => { for (const pub of tokenPubs) { - const token = await tx.wtx.getToken(pub); + const token = await tx.getToken(pub); checkDbInvariant(!!token, `token not found for ${pub}`); tokens.push(token); } @@ -3658,12 +3655,12 @@ export async function generateTokenSigs( }); } - await wex.runLegacyWalletDbTx(async (tx) => { + await wex.runWalletDbTx(async (tx) => { for (let i = 0; i < sigs.length; i++) { const token = tokens[i]; const sig = sigs[i]; token.tokenUseSig = sig; - await tx.wtx.upsertToken(token); + await tx.upsertToken(token); } }); @@ -3674,10 +3671,10 @@ export async function cleanupUsedTokens( wex: WalletExecutionContext, tokenPubs: string[], ): Promise<void> { - await wex.runLegacyWalletDbTx(async (tx) => { + await wex.runWalletDbTx(async (tx) => { for (const pub of tokenPubs) { logger.trace(`cleaning up used token ${pub}`); - await tx.wtx.deleteToken(pub); + await tx.deleteToken(pub); } }); } @@ -3687,8 +3684,8 @@ export async function refuseProposal( proposalId: string, ): Promise<void> { const ctx = new PayMerchantTransactionContext(wex, proposalId); - await wex.runLegacyWalletDbTx(async (tx) => { - const [proposal, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [proposal, h] = await ctx.getRecordHandle(tx); switch (proposal?.purchaseStatus) { case PurchaseStatus.DialogProposed: case PurchaseStatus.DialogShared: @@ -4024,8 +4021,8 @@ export async function sharePayment( orderId: string, ): Promise<SharePaymentResult> { // First, translate the order ID into a proposal ID - const proposalId = await wex.runLegacyWalletDbTx(async (tx) => { - const p = await tx.wtx.getPurchaseByUrlAndOrderId(merchantBaseUrl, orderId); + const proposalId = await wex.runWalletDbTx(async (tx) => { + const p = await tx.getPurchaseByUrlAndOrderId(merchantBaseUrl, orderId); return p?.proposalId; }); @@ -4035,8 +4032,8 @@ export async function sharePayment( const ctx = new PayMerchantTransactionContext(wex, proposalId); - const result = await wex.runLegacyWalletDbTx(async (tx) => { - const [p, h] = await ctx.getRecordHandle(tx.wtx); + const result = await wex.runWalletDbTx(async (tx) => { + const [p, h] = await ctx.getRecordHandle(tx); if (!p) { logger.warn("purchase does not exist anymore"); return undefined; @@ -4118,8 +4115,8 @@ async function processPurchaseDialogProposed( ): Promise<TaskRunResult> { const proposalId = purchase.proposalId; const ctx = new PayMerchantTransactionContext(wex, proposalId); - const txRes = await wex.runLegacyWalletDbTx(async (tx) => { - const rec = await tx.wtx.getPurchase(proposalId); + const txRes = await wex.runWalletDbTx(async (tx) => { + const rec = await tx.getPurchase(proposalId); if (!rec) { return undefined; } @@ -4140,8 +4137,8 @@ async function processPurchaseDialogProposed( ); if (AbsoluteTime.isExpired(expiry)) { - await wex.runLegacyWalletDbTx(async (tx) => { - const [r2, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [r2, h] = await ctx.getRecordHandle(tx); if (r2?.purchaseStatus !== PurchaseStatus.DialogProposed) { return; } @@ -4166,8 +4163,8 @@ async function processPurchaseDialogShared( const proposalId = purchase.proposalId; logger.trace(`processing dialog-shared for proposal ${proposalId}`); const ctx = new PayMerchantTransactionContext(wex, proposalId); - const txRes = await wex.runLegacyWalletDbTx(async (tx) => { - const rec = await tx.wtx.getPurchase(proposalId); + const txRes = await wex.runWalletDbTx(async (tx) => { + const rec = await tx.getPurchase(proposalId); if (!rec) { return undefined; } @@ -4221,8 +4218,8 @@ async function processPurchaseDialogShared( return TaskRunResult.backoff(); } - await wex.runLegacyWalletDbTx(async (tx) => { - const [p, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [p, h] = await ctx.getRecordHandle(tx); switch (p?.purchaseStatus) { case PurchaseStatus.DialogShared: p.purchaseStatus = PurchaseStatus.FailedPaidByOther; @@ -4261,8 +4258,8 @@ async function processPurchaseAutoRefund( ), ); - const totalKnownRefund = await wex.runLegacyWalletDbTx(async (tx) => { - const refunds = await tx.wtx.getRefundGroupsByProposal(purchase.proposalId); + const totalKnownRefund = await wex.runWalletDbTx(async (tx) => { + const refunds = await tx.getRefundGroupsByProposal(purchase.proposalId); const am = Amounts.parseOrThrow(amountRaw); return refunds.reduce((prev, cur) => { if ( @@ -4281,8 +4278,8 @@ async function processPurchaseAutoRefund( // is over or the product is already fully refunded. if (noAutoRefundOrExpired || fullyRefunded) { - await wex.runLegacyWalletDbTx(async (tx) => { - const [p, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [p, h] = await ctx.getRecordHandle(tx); switch (p?.purchaseStatus) { case PurchaseStatus.PendingQueryingAutoRefund: case PurchaseStatus.FinalizingQueryingAutoRefund: @@ -4318,8 +4315,8 @@ async function processPurchaseAutoRefund( return TaskRunResult.longpollReturnedPending(); } - await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); switch (rec?.purchaseStatus) { case PurchaseStatus.PendingQueryingAutoRefund: case PurchaseStatus.FinalizingQueryingAutoRefund: @@ -4350,8 +4347,8 @@ async function processPurchaseAbortingRefund( const payCoinSelection = purchase.payInfo?.payCoinSelection; if (!payCoinSelection) { - await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (rec?.purchaseStatus !== PurchaseStatus.AbortingWithRefund) { return; } @@ -4364,8 +4361,8 @@ async function processPurchaseAbortingRefund( return TaskRunResult.finished(); } - await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -4393,7 +4390,7 @@ async function processPurchaseAbortingRefund( for (let i = 0; i < payCoinSelection.coinPubs.length; i++) { const coinPub = payCoinSelection.coinPubs[i]; - const coin = await tx.wtx.getCoin(coinPub); + const coin = await tx.getCoin(coinPub); checkDbInvariant(!!coin, `coin not found for ${coinPub}`); abortingCoins.push({ coin_pub: coinPub, @@ -4422,8 +4419,8 @@ async function processPurchaseAbortingRefund( err.code === TalerErrorCode.MERCHANT_POST_ORDERS_ID_ABORT_CONTRACT_NOT_FOUND ) { - await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (rec?.purchaseStatus !== PurchaseStatus.AbortingWithRefund) { return; } @@ -4495,8 +4492,8 @@ async function processPurchaseQueryRefund( const ctx = new PayMerchantTransactionContext(wex, proposalId); if (!orderStatus.refund_pending) { - await wex.runLegacyWalletDbTx(async (tx) => { - const [p, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [p, h] = await ctx.getRecordHandle(tx); if (p?.purchaseStatus !== PurchaseStatus.PendingQueryingRefund) { return; } @@ -4510,8 +4507,8 @@ async function processPurchaseQueryRefund( Amounts.parseOrThrow(orderStatus.refund_taken), ).amount; - await wex.runLegacyWalletDbTx(async (tx) => { - const [p, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [p, h] = await ctx.getRecordHandle(tx); if (p?.purchaseStatus !== PurchaseStatus.PendingQueryingRefund) { return; } @@ -4566,8 +4563,8 @@ export async function startRefundQueryForUri( if (parsedUri.type !== TalerUriAction.Refund) { throw Error("expected taler://refund URI"); } - const purchaseRecord = await wex.runLegacyWalletDbTx(async (tx) => { - return tx.wtx.getPurchaseByUrlAndOrderId( + const purchaseRecord = await wex.runWalletDbTx(async (tx) => { + return tx.getPurchaseByUrlAndOrderId( parsedUri.merchantBaseUrl, parsedUri.orderId, ); @@ -4594,8 +4591,8 @@ export async function startQueryRefund( proposalId: string, ): Promise<void> { const ctx = new PayMerchantTransactionContext(wex, proposalId); - await wex.runLegacyWalletDbTx(async (tx) => { - const [p, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [p, h] = await ctx.getRecordHandle(tx); if (!p) { logger.warn(`purchase ${proposalId} does not exist anymore`); return; @@ -4611,12 +4608,12 @@ export async function startQueryRefund( async function computeRefreshRequest( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, items: WalletRefundItem[], ): Promise<CoinRefreshRequest[]> { const refreshCoins: CoinRefreshRequest[] = []; for (const item of items) { - const coin = await tx.wtx.getCoin(item.coinPub); + const coin = await tx.getCoin(item.coinPub); if (!coin) { throw Error("coin not found"); } @@ -4685,8 +4682,8 @@ async function storeRefunds( const currency = Amounts.currencyOf(amountRaw); - const result = await wex.runLegacyWalletDbTx(async (tx) => { - const [myPurchase, h] = await ctx.getRecordHandle(tx.wtx); + const result = await wex.runWalletDbTx(async (tx) => { + const [myPurchase, h] = await ctx.getRecordHandle(tx); if (!myPurchase) { logger.warn("purchase group not found anymore"); return; @@ -4710,7 +4707,7 @@ async function storeRefunds( const newGroupRefunds: WalletRefundItem[] = []; for (const rf of refunds) { - const oldItem = await tx.wtx.getRefundItemByCoinAndRtxid( + const oldItem = await tx.getRefundItemByCoinAndRtxid( rf.coin_pub, rf.rtransaction_id, ); @@ -4729,7 +4726,7 @@ async function storeRefunds( oldItem.status = RefundItemStatus.Failed; } } - await tx.wtx.upsertRefundItem(oldItem); + await tx.upsertRefundItem(oldItem); } else { // Put refund item into a new group! if (!newGroup) { @@ -4758,7 +4755,7 @@ async function storeRefunds( numPendingItemsTotal += 1; } newGroupRefunds.push(newItem); - await tx.wtx.upsertRefundItem(newItem); + await tx.upsertRefundItem(newItem); } } @@ -4787,8 +4784,8 @@ async function storeRefunds( wex, newGroup.refundGroupId, ); - await tx.wtx.upsertRefundGroup(newGroup); - await refundCtx.updateTransactionMeta(tx.wtx); + await tx.upsertRefundGroup(newGroup); + await refundCtx.updateTransactionMeta(tx); applyNotifyTransition(tx.notify, refundCtx.transactionId, { oldTxState: { major: TransactionMajorState.None }, newTxState: computeRefundTransactionState(newGroup), @@ -4798,7 +4795,7 @@ async function storeRefunds( }); } - const refundGroups = await tx.wtx.getRefundGroupsByProposal( + const refundGroups = await tx.getRefundGroupsByProposal( myPurchase.proposalId, ); @@ -4818,9 +4815,7 @@ async function storeRefunds( default: assertUnreachable(refundGroup.status); } - const items = await tx.wtx.getRefundItemsByGroup( - refundGroup.refundGroupId, - ); + const items = await tx.getRefundItemsByGroup(refundGroup.refundGroupId); let numPending = 0; let numFailed = 0; for (const item of items) { @@ -4841,8 +4836,8 @@ async function storeRefunds( } else { refundGroup.status = RefundGroupStatus.Failed; } - await tx.wtx.upsertRefundGroup(refundGroup); - await refundCtx.updateTransactionMeta(tx.wtx); + await tx.upsertRefundGroup(refundGroup); + await refundCtx.updateTransactionMeta(tx); const refreshCoins = await computeRefreshRequest(wex, tx, items); const newTxState: TransactionState = computeRefundTransactionState(refundGroup); diff --git a/packages/taler-wallet-core/src/pay-peer-common.ts b/packages/taler-wallet-core/src/pay-peer-common.ts @@ -27,12 +27,9 @@ import { WalletReserve } from "./db-common.js"; import { SpendCoinDetails } from "./crypto/cryptoImplementation.js"; import { DbPeerPushPaymentCoinSelection } from "./db-indexeddb.js"; import { getTotalRefreshCost } from "./refresh.js"; -import { - LegacyWalletTxHandle, - WalletExecutionContext, - getDenomInfo, -} from "./wallet.js"; +import { WalletExecutionContext, getDenomInfo } from "./wallet.js"; import { updateWithdrawalDenomsForExchange } from "./withdraw.js"; +import { WalletDbTransaction } from "./dbtx.js"; /** * Get information about the coin selected for signatures. @@ -42,9 +39,9 @@ export async function queryCoinInfosForSelection( csel: DbPeerPushPaymentCoinSelection, ): Promise<SpendCoinDetails[]> { let infos: SpendCoinDetails[] = []; - await wex.runLegacyWalletDbTx(async (tx) => { + await wex.runWalletDbTx(async (tx) => { for (let i = 0; i < csel.coinPubs.length; i++) { - const coin = await tx.wtx.getCoin(csel.coinPubs[i]); + const coin = await tx.getCoin(csel.coinPubs[i]); if (!coin) { throw Error("coin not found anymore"); } @@ -73,7 +70,7 @@ export async function queryCoinInfosForSelection( export async function getTotalPeerPaymentCostInTx( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, pcs: SelectedProspectiveCoin[], ): Promise<AmountJson> { const costs: AmountJson[] = []; @@ -115,7 +112,7 @@ export async function getTotalPeerPaymentCost( const exchangeBaseUrl = pcs[0].exchangeBaseUrl; await updateWithdrawalDenomsForExchange(wex, exchangeBaseUrl); } - return await wex.runLegacyWalletDbTx(async (tx) => { + return await wex.runWalletDbTx(async (tx) => { return await getTotalPeerPaymentCostInTx(wex, tx, pcs); }); } @@ -130,12 +127,12 @@ export async function getMergeReserveInfo( // due to the async crypto API. const newReservePair = await wex.cryptoApi.createEddsaKeypair({}); - const mergeReserveRecord: WalletReserve = await wex.runLegacyWalletDbTx( + const mergeReserveRecord: WalletReserve = await wex.runWalletDbTx( async (tx) => { - const ex = await tx.wtx.getExchange(req.exchangeBaseUrl); + const ex = await tx.getExchange(req.exchangeBaseUrl); checkDbInvariant(!!ex, `no exchange record for ${req.exchangeBaseUrl}`); if (ex.currentMergeReserveRowId != null) { - const reserve = await tx.wtx.getReserve(ex.currentMergeReserveRowId); + const reserve = await tx.getReserve(ex.currentMergeReserveRowId); checkDbInvariant( !!reserve, `reserver ${ex.currentMergeReserveRowId} missing in db`, @@ -146,9 +143,9 @@ export async function getMergeReserveInfo( reservePriv: newReservePair.priv, reservePub: newReservePair.pub, }; - reserve.rowId = await tx.wtx.upsertReserve(reserve); + reserve.rowId = await tx.upsertReserve(reserve); ex.currentMergeReserveRowId = reserve.rowId; - await tx.wtx.upsertExchange(ex); + await tx.upsertExchange(ex); return reserve; }, ); diff --git a/packages/taler-wallet-core/src/pay-peer-pull-credit.ts b/packages/taler-wallet-core/src/pay-peer-pull-credit.ts @@ -94,11 +94,7 @@ import { constructTransactionIdentifier, isUnsuccessfulTransaction, } from "./transactions.js"; -import { - LegacyWalletTxHandle, - WalletExecutionContext, - walletExchangeClient, -} from "./wallet.js"; +import { WalletExecutionContext, walletExchangeClient } from "./wallet.js"; import { WithdrawTransactionContext, getExchangeWithdrawalInfo, @@ -310,14 +306,14 @@ export class PeerPullCreditTransactionContext implements TransactionContext { } async userDeleteTransaction(): Promise<void> { - const res = await this.wex.runLegacyWalletDbTx(async (tx) => { - await this.deleteTransactionInTx(tx.wtx); + const res = await this.wex.runWalletDbTx(async (tx) => { + await this.deleteTransactionInTx(tx); }); } async userSuspendTransaction(): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; } @@ -368,8 +364,8 @@ export class PeerPullCreditTransactionContext implements TransactionContext { reason?: TalerErrorDetail, ): Promise<void> { const { wex } = this; - await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await this.getRecordHandle(tx); if (rec?.status != fromSt) { return; } @@ -380,8 +376,8 @@ export class PeerPullCreditTransactionContext implements TransactionContext { } async userFailTransaction(reason?: TalerErrorDetail): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; } @@ -417,8 +413,8 @@ export class PeerPullCreditTransactionContext implements TransactionContext { } async userResumeTransaction(): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; } @@ -465,8 +461,8 @@ export class PeerPullCreditTransactionContext implements TransactionContext { } async userAbortTransaction(reason?: TalerErrorDetail): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; } @@ -522,8 +518,8 @@ async function processPendingReady( break; case HttpStatusCode.Gone: // Exchange says that purse doesn't exist anymore => expired! - await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -549,8 +545,8 @@ async function processPendingReady( return TaskRunResult.longpollReturnedPending(); } - const reserve = await wex.runLegacyWalletDbTx((tx) => - tx.wtx.getReserve(pullIni.mergeReserveRowId), + const reserve = await wex.runWalletDbTx((tx) => + tx.getReserve(pullIni.mergeReserveRowId), ); if (!reserve) { @@ -571,8 +567,8 @@ async function processPendingReady( pub: reserve.reservePub, }, }); - await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -637,8 +633,8 @@ async function processPendingMergeKycRequired( checkProtocolInvariant(algoRes.requiresAuth != true); - await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -668,8 +664,8 @@ async function processPeerPullCreditAbortingDeletePurse( switch (resp.case) { case "ok": case HttpStatusCode.NotFound: - await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -705,12 +701,12 @@ async function processPeerPullCreditWithdrawing( const ctx = new PeerPullCreditTransactionContext(wex, pullIni.pursePub); const wgId = pullIni.withdrawalGroupId; - return await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + return await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (rec?.status !== PeerPullPaymentCreditStatus.PendingWithdrawing) { return TaskRunResult.backoff(); } - const wg = await tx.wtx.getWithdrawalGroup(wgId); + const wg = await tx.getWithdrawalGroup(wgId); if (!wg) { // FIXME: Fail the operation instead? return TaskRunResult.backoff(); @@ -770,8 +766,8 @@ async function processPeerPullCreditCreatePurse( amount: kycCheckRes.nextThreshold, exchangeBaseUrl: pullIni.exchangeBaseUrl, }); - await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -789,15 +785,15 @@ async function processPeerPullCreditCreatePurse( const purseFee = Amounts.stringify(Amounts.zeroOfAmount(pullIni.amount)); - const mergeReserve = await wex.runLegacyWalletDbTx(async (tx) => - tx.wtx.getReserve(pullIni.mergeReserveRowId), + const mergeReserve = await wex.runWalletDbTx(async (tx) => + tx.getReserve(pullIni.mergeReserveRowId), ); if (!mergeReserve) { throw Error("merge reserve for peer pull payment not found in database"); } - const contractTermsRecord = await wex.runLegacyWalletDbTx(async (tx) => - tx.wtx.getContractTerms(pullIni.contractTermsHash), + const contractTermsRecord = await wex.runWalletDbTx(async (tx) => + tx.getContractTerms(pullIni.contractTermsHash), ); if (!contractTermsRecord) { throw Error("contract terms for peer pull payment not found in database"); @@ -886,8 +882,8 @@ async function processPeerPullCreditCreatePurse( assertUnreachable(resp); } - await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -905,8 +901,8 @@ export async function processPeerPullCredit( return TaskRunResult.networkRequired(); } - const pullIni = await wex.runLegacyWalletDbTx(async (tx) => - tx.wtx.getPeerPullCredit(pursePub), + const pullIni = await wex.runWalletDbTx(async (tx) => + tx.getPeerPullCredit(pursePub), ); if (!pullIni) { throw Error("peer pull payment initiation not found in database"); @@ -991,8 +987,8 @@ async function processPeerPullCreditBalanceKyc( }); if (ret.result === "ok") { - await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -1011,8 +1007,8 @@ async function processPeerPullCreditBalanceKyc( peerInc.status === PeerPullPaymentCreditStatus.PendingBalanceKycInit && ret.walletKycStatus === ExchangeWalletKycStatus.Legi ) { - await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -1039,8 +1035,8 @@ async function handlePeerPullCreditKycRequired( ): Promise<TaskRunResult> { const ctx = new PeerPullCreditTransactionContext(wex, peerIni.pursePub); - await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -1211,12 +1207,12 @@ export async function initiatePeerPullPayment( const ctx = new PeerPullCreditTransactionContext(wex, pursePair.pub); - await wex.runLegacyWalletDbTx(async (tx) => { - await tx.wtx.upsertContractTerms({ + await wex.runWalletDbTx(async (tx) => { + await tx.upsertContractTerms({ contractTermsRaw: contractTerms, h: hContractTerms, }); - const [oldRec, h] = await ctx.getRecordHandle(tx.wtx); + const [oldRec, h] = await ctx.getRecordHandle(tx); 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 @@ -92,11 +92,7 @@ import { isUnsuccessfulTransaction, parseTransactionIdentifier, } from "./transactions.js"; -import { - LegacyWalletTxHandle, - WalletExecutionContext, - walletExchangeClient, -} from "./wallet.js"; +import { WalletExecutionContext, walletExchangeClient } from "./wallet.js"; import { WalletDbTransaction } from "./dbtx.js"; const logger = new Logger("pay-peer-pull-debit.ts"); @@ -205,8 +201,8 @@ export class PeerPullDebitTransactionContext implements TransactionContext { reason?: TalerErrorDetail, ): Promise<void> { const { wex } = this; - await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await this.getRecordHandle(tx); if (rec?.status != fromSt) { return; } @@ -218,8 +214,8 @@ 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.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await this.getRecordHandle(tx); if (rec?.status != fromSt) { return; } @@ -229,8 +225,8 @@ export class PeerPullDebitTransactionContext implements TransactionContext { } async userDeleteTransaction(): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - await this.deleteTransactionInTx(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + await this.deleteTransactionInTx(tx); }); } @@ -243,8 +239,8 @@ export class PeerPullDebitTransactionContext implements TransactionContext { } async userSuspendTransaction(): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; } @@ -272,8 +268,8 @@ export class PeerPullDebitTransactionContext implements TransactionContext { } async userResumeTransaction(): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; } @@ -298,8 +294,8 @@ export class PeerPullDebitTransactionContext implements TransactionContext { } async userFailTransaction(reason?: TalerErrorDetail): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; } @@ -321,8 +317,8 @@ export class PeerPullDebitTransactionContext implements TransactionContext { } async userAbortTransaction(reason?: TalerErrorDetail): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - const [pi, h] = await this.getRecordHandle(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + const [pi, h] = await this.getRecordHandle(tx); if (!pi) { return; } @@ -428,8 +424,8 @@ async function handlePurseCreationConflict( coinSelRes.result.coins, ); - await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -479,8 +475,8 @@ 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.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); switch (rec?.status) { case PeerPullDebitRecordStatus.DialogProposed: rec.status = PeerPullDebitRecordStatus.Aborted; @@ -543,8 +539,8 @@ async function processPeerPullDebitPendingDeposit( } const totalAmount = await getTotalPeerPaymentCost(wex, coins); - return await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + return await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return TaskRunResult.finished(); } @@ -623,8 +619,8 @@ async function processPeerPullDebitPendingDeposit( } } // All batches succeeded, we can transition! - await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); switch (rec?.status) { case PeerPullDebitRecordStatus.PendingDeposit: rec.status = PeerPullDebitRecordStatus.Done; @@ -645,9 +641,9 @@ async function processPeerPullDebitAbortingRefresh( const abortRefreshGroupId = peerPullInc.abortRefreshGroupId; checkLogicInvariant(!!abortRefreshGroupId); 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.wtx); + await wex.runWalletDbTx(async (tx) => { + const refreshGroup = await tx.getRefreshGroup(abortRefreshGroupId); + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -683,8 +679,8 @@ export async function processPeerPullDebit( return TaskRunResult.networkRequired(); } - const peerPullInc = await wex.runLegacyWalletDbTx(async (tx) => - tx.wtx.getPeerPullDebit(peerPullDebitId), + const peerPullInc = await wex.runWalletDbTx(async (tx) => + tx.getPeerPullDebit(peerPullDebitId), ); if (!peerPullInc) { throw Error("peer pull debit not found"); @@ -718,8 +714,8 @@ export async function confirmPeerPullDebit( throw Error("invalid peer-pull-debit transaction identifier"); } - const peerPullInc = await wex.runLegacyWalletDbTx(async (tx) => - tx.wtx.getPeerPullDebit(parsed.peerPullDebitId), + const peerPullInc = await wex.runWalletDbTx(async (tx) => + tx.getPeerPullDebit(parsed.peerPullDebitId), ); if (peerPullInc == null) { @@ -766,8 +762,8 @@ export async function confirmPeerPullDebit( const totalAmount = await getTotalPeerPaymentCost(wex, coins); - await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -831,21 +827,20 @@ export async function preparePeerPullDebit( parsedTxId = parsedRes.peerPullDebitId; } - const existing = await wex.runLegacyWalletDbTx(async (tx) => { + const existing = await wex.runWalletDbTx(async (tx) => { let peerPullDebitRecord: WalletPeerPullDebit | undefined; if (uri) { - peerPullDebitRecord = - await tx.wtx.getPeerPullDebitByExchangeAndContractPriv( - uri.exchangeBaseUrl, - uri.contractPriv, - ); + peerPullDebitRecord = await tx.getPeerPullDebitByExchangeAndContractPriv( + uri.exchangeBaseUrl, + uri.contractPriv, + ); } else if (parsedTxId) { - peerPullDebitRecord = await tx.wtx.getPeerPullDebit(parsedTxId); + peerPullDebitRecord = await tx.getPeerPullDebit(parsedTxId); } if (!peerPullDebitRecord) { return; } - const contractTerms = await tx.wtx.getContractTerms( + const contractTerms = await tx.getContractTerms( peerPullDebitRecord.contractTermsHash, ); if (!contractTerms) { @@ -984,12 +979,12 @@ export async function preparePeerPullDebit( const ctx = new PeerPullDebitTransactionContext(wex, peerPullDebitId); - const ret = await wex.runLegacyWalletDbTx(async (tx) => { - await tx.wtx.upsertContractTerms({ + const ret = await wex.runWalletDbTx(async (tx) => { + await tx.upsertContractTerms({ h: contractTermsHash, contractTermsRaw: contractTerms, }); - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + const [rec, h] = await ctx.getRecordHandle(tx); 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 @@ -98,11 +98,7 @@ import { isUnsuccessfulTransaction, parseTransactionIdentifier, } from "./transactions.js"; -import { - LegacyWalletTxHandle, - WalletExecutionContext, - walletExchangeClient, -} from "./wallet.js"; +import { WalletExecutionContext, walletExchangeClient } from "./wallet.js"; import { PerformCreateWithdrawalGroupResult, WithdrawTransactionContext, @@ -283,9 +279,7 @@ export class PeerPushCreditTransactionContext implements TransactionContext { } async userDeleteTransaction(): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => - this.deleteTransactionInTx(tx.wtx), - ); + await this.wex.runWalletDbTx(async (tx) => this.deleteTransactionInTx(tx)); } async deleteTransactionInTx(tx: WalletDbTransaction): Promise<void> { @@ -305,8 +299,8 @@ export class PeerPushCreditTransactionContext implements TransactionContext { } async userSuspendTransaction(): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; } @@ -347,8 +341,8 @@ export class PeerPushCreditTransactionContext implements TransactionContext { } async userAbortTransaction(): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; } @@ -380,8 +374,8 @@ export class PeerPushCreditTransactionContext implements TransactionContext { } async userResumeTransaction(): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; } @@ -426,8 +420,8 @@ export class PeerPushCreditTransactionContext implements TransactionContext { reason?: TalerErrorDetail, ): Promise<void> { const { wex } = this; - await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await this.getRecordHandle(tx); if (rec?.status != fromSt) { return; } @@ -438,8 +432,8 @@ export class PeerPushCreditTransactionContext implements TransactionContext { } async userFailTransaction(reason?: TalerErrorDetail): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; } @@ -500,20 +494,20 @@ export async function preparePeerPushCredit( parsedTxId = parsedRes.peerPushCreditId; } - const existing = await wex.runLegacyWalletDbTx(async (tx) => { + const existing = await wex.runWalletDbTx(async (tx) => { let existingPushInc: WalletPeerPushCredit | undefined; if (uri) { - existingPushInc = await tx.wtx.getPeerPushCreditByExchangeAndContractPriv( + existingPushInc = await tx.getPeerPushCreditByExchangeAndContractPriv( uri.exchangeBaseUrl, uri.contractPriv, ); } else if (parsedTxId) { - existingPushInc = await tx.wtx.getPeerPushCredit(parsedTxId); + existingPushInc = await tx.getPeerPushCredit(parsedTxId); } if (!existingPushInc) { return; } - const existingContractTermsRec = await tx.wtx.getContractTerms( + const existingContractTermsRec = await tx.getContractTerms( existingPushInc.contractTermsHash, ); if (!existingContractTermsRec) { @@ -534,7 +528,7 @@ export async function preparePeerPushCredit( ); const currency = Amounts.currencyOf(existing.existingContractTerms.amount); const exchangeBaseUrl = existing.existingPushInc.exchangeBaseUrl; - const scopeInfo = await wex.runLegacyWalletDbTx( + const scopeInfo = await wex.runWalletDbTx( async (tx) => await getExchangeScopeInfo(tx, exchangeBaseUrl, currency), ); return { @@ -631,13 +625,13 @@ export async function preparePeerPushCredit( const ctx = new PeerPushCreditTransactionContext(wex, peerPushCreditId); - const res = await wex.runLegacyWalletDbTx(async (tx) => { - await tx.wtx.upsertContractTerms({ + const res = await wex.runWalletDbTx(async (tx) => { + await tx.upsertContractTerms({ h: contractTermsHash, contractTermsRaw: dec.contractTerms, }); - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + const [rec, h] = await ctx.getRecordHandle(tx); if (rec) { throw Error("record already exists"); } @@ -728,8 +722,8 @@ async function processPeerPushDebitMergeKyc( checkProtocolInvariant(algoRes.requiresAuth != true); - await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -755,8 +749,8 @@ async function transitionPeerPushCreditKycRequired( peerInc.peerPushCreditId, ); - return await wex.runLegacyWalletDbTx(async (tx) => { - const [peerInc, h] = await ctx.getRecordHandle(tx.wtx); + return await wex.runWalletDbTx(async (tx) => { + const [peerInc, h] = await ctx.getRecordHandle(tx); if (!peerInc) { return TaskRunResult.finished(); } @@ -788,8 +782,8 @@ async function processPendingMerge( amount: kycCheckRes.nextThreshold, exchangeBaseUrl: peerInc.exchangeBaseUrl, }); - await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -867,8 +861,8 @@ async function processPendingMerge( ); case HttpStatusCode.Conflict: // FIXME: Check signature. - await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -886,8 +880,8 @@ async function processPendingMerge( }); return TaskRunResult.finished(); case HttpStatusCode.Gone: - await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -928,8 +922,8 @@ async function processPendingMerge( }, }); - await wex.runLegacyWalletDbTx(async (tx) => { - const [peerInc, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [peerInc, h] = await ctx.getRecordHandle(tx); if (!peerInc) { return undefined; } @@ -966,15 +960,15 @@ async function processPendingWithdrawing( peerInc.peerPushCreditId, ); const wgId = peerInc.withdrawalGroupId; - return await wex.runLegacyWalletDbTx(async (tx) => { - const [ppi, h] = await ctx.getRecordHandle(tx.wtx); + return await wex.runWalletDbTx(async (tx) => { + const [ppi, h] = await ctx.getRecordHandle(tx); if (!ppi) { return TaskRunResult.finished(); } if (ppi.status !== PeerPushCreditStatus.PendingWithdrawing) { return TaskRunResult.finished(); } - const wg = await tx.wtx.getWithdrawalGroup(wgId); + const wg = await tx.getWithdrawalGroup(wgId); if (!wg) { ppi.status = PeerPushCreditStatus.Failed; await h.update(ppi); @@ -1042,8 +1036,8 @@ async function processPeerPushDebitDialogProposed( break; 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.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -1067,8 +1061,8 @@ 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.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -1097,22 +1091,20 @@ export async function processPeerPushCredit( } const ctx = new PeerPushCreditTransactionContext(wex, peerPushCreditId); - const { peerInc, contractTerms } = await wex.runLegacyWalletDbTx( - async (tx) => { - const rec = await tx.wtx.getPeerPushCredit(peerPushCreditId); - let contractTerms = null; - if (rec != null) { - const contract = await tx.wtx.getContractTerms(rec.contractTermsHash); - if (contract != null) { - contractTerms = contract.contractTermsRaw; - } + const { peerInc, contractTerms } = await wex.runWalletDbTx(async (tx) => { + const rec = await tx.getPeerPushCredit(peerPushCreditId); + let contractTerms = null; + if (rec != null) { + const contract = await tx.getContractTerms(rec.contractTermsHash); + if (contract != null) { + contractTerms = contract.contractTermsRaw; } - return { - peerInc: rec, - contractTerms, - }; - }, - ); + } + return { + peerInc: rec, + contractTerms, + }; + }); if (!peerInc) { throw Error( @@ -1193,8 +1185,8 @@ async function processPeerPushCreditBalanceKyc( }); if (ret.result === "ok") { - await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -1211,8 +1203,8 @@ async function processPeerPushCreditBalanceKyc( peerInc.status === PeerPushCreditStatus.PendingBalanceKycInit && ret.walletKycStatus === ExchangeWalletKycStatus.Legi ) { - await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -1248,12 +1240,12 @@ export async function confirmPeerPushCredit( logger.trace(`confirming peer-push-credit ${ctx.peerPushCreditId}`); - const res = await wex.runLegacyWalletDbTx(async (tx) => { - const rec = await tx.wtx.getPeerPushCredit(ctx.peerPushCreditId); + const res = await wex.runWalletDbTx(async (tx) => { + const rec = await tx.getPeerPushCredit(ctx.peerPushCreditId); if (!rec) { return; } - const ct = await tx.wtx.getContractTerms(rec.contractTermsHash); + const ct = await tx.getContractTerms(rec.contractTermsHash); if (!ct) { return undefined; } @@ -1278,8 +1270,8 @@ export async function confirmPeerPushCredit( throw Error("peer credit would exceed hard KYC limit"); } - await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); 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 @@ -100,11 +100,7 @@ import { constructTransactionIdentifier, isUnsuccessfulTransaction, } from "./transactions.js"; -import { - LegacyWalletTxHandle, - WalletExecutionContext, - walletExchangeClient, -} from "./wallet.js"; +import { WalletExecutionContext, walletExchangeClient } from "./wallet.js"; import { updateWithdrawalDenomsForCurrency } from "./withdraw.js"; import { WalletDbTransaction } from "./dbtx.js"; @@ -226,8 +222,8 @@ export class PeerPushDebitTransactionContext implements TransactionContext { } async userDeleteTransaction(): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - await this.deleteTransactionInTx(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + await this.deleteTransactionInTx(tx); }); } @@ -240,8 +236,8 @@ export class PeerPushDebitTransactionContext implements TransactionContext { } async userSuspendTransaction(): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; } @@ -273,8 +269,8 @@ export class PeerPushDebitTransactionContext implements TransactionContext { } async userAbortTransaction(reason?: TalerErrorDetail): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; } @@ -307,8 +303,8 @@ export class PeerPushDebitTransactionContext implements TransactionContext { } async userResumeTransaction(): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; } @@ -344,8 +340,8 @@ export class PeerPushDebitTransactionContext implements TransactionContext { reason?: TalerErrorDetail, ): Promise<void> { const { wex } = this; - await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await this.getRecordHandle(tx); if (rec?.status != fromSt) { return; } @@ -356,8 +352,8 @@ export class PeerPushDebitTransactionContext implements TransactionContext { } async userFailTransaction(reason?: TalerErrorDetail): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; } @@ -429,8 +425,8 @@ async function getDefaultPeerPushExpiration( wex: WalletExecutionContext, exchangeBaseUrl: string, ): Promise<TalerProtocolDuration> { - return await wex.runLegacyWalletDbTx(async (tx) => { - const ex = await getExchangeDetailsInTx(tx.wtx, exchangeBaseUrl); + return await wex.runWalletDbTx(async (tx) => { + const ex = await getExchangeDetailsInTx(tx, exchangeBaseUrl); return ex?.defaultPeerPushExpiration ?? fallbackDefaultPeerPushExpiration; }); } @@ -585,8 +581,8 @@ async function handlePurseCreationConflict( assertUnreachable(coinSelRes); } - await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -615,8 +611,8 @@ async function processPeerPushDebitCreateReserve( logger.trace(`processing ${ctx.transactionId} pending(create-reserve)`); - const contractTermsRecord = await wex.runLegacyWalletDbTx(async (tx) => { - return tx.wtx.getContractTerms(contractTermsHash); + const contractTermsRecord = await wex.runWalletDbTx(async (tx) => { + return tx.getContractTerms(contractTermsHash); }); if (!contractTermsRecord) { @@ -653,8 +649,8 @@ async function processPeerPushDebitCreateReserve( assertUnreachable(coinSelRes); } - return await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + return await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return TaskRunResult.backoff(); } @@ -778,8 +774,8 @@ async function processPeerPushDebitCreateReserve( continue; case HttpStatusCode.Gone: // FIXME we need PeerPushDebitStatus.ExpiredDeletePurse - await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -815,8 +811,8 @@ async function processPeerPushDebitCreateReserve( const resp = await exchangeClient.getPurseStatusAtDeposit(pursePub); switch (resp.case) { case "ok": - await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -833,8 +829,8 @@ async function processPeerPushDebitCreateReserve( return TaskRunResult.progress(); case HttpStatusCode.Gone: // FIXME we need PeerPushDebitStatus.ExpiredDeletePurse - await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -891,8 +887,8 @@ async function processPeerPushDebitAbortingDeletePurse( throwUnexpectedResponse(resp); } - await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -952,8 +948,8 @@ async function processPeerPushDebitReady( if (!isPurseMerged(resp.body)) { return TaskRunResult.longpollReturnedPending(); } else { - await wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -972,8 +968,8 @@ 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.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -1021,8 +1017,8 @@ export async function processPeerPushDebit( return TaskRunResult.networkRequired(); } - const peerPushInitiation = await wex.runLegacyWalletDbTx(async (tx) => { - return tx.wtx.getPeerPushDebit(pursePub); + const peerPushInitiation = await wex.runWalletDbTx(async (tx) => { + return tx.getPeerPushDebit(pursePub); }); if (!peerPushInitiation) { return TaskRunResult.finished(); @@ -1091,7 +1087,7 @@ export async function initiatePeerPushDebit( let exchangeBaseUrl: string | undefined; - await wex.runLegacyWalletDbTx(async (tx) => { + await wex.runWalletDbTx(async (tx) => { const coinSelRes = await selectPeerCoinsInTx(wex, tx, { instructedAmount, restrictScope: restrictScope, @@ -1133,7 +1129,7 @@ export async function initiatePeerPushDebit( exchangeBaseUrl = coinSelRes.result.exchangeBaseUrl; - const ex = await getExchangeDetailsInTx(tx.wtx, exchangeBaseUrl); + const ex = await getExchangeDetailsInTx(tx, exchangeBaseUrl); const myExpiration = req.partialContractTerms.purse_expiration ?? AbsoluteTime.toProtocolTimestamp( @@ -1190,11 +1186,11 @@ export async function initiatePeerPushDebit( refreshReason: RefreshReason.PayPeerPush, }); } - await tx.wtx.upsertContractTerms({ + await tx.upsertContractTerms({ h: hContractTerms, contractTermsRaw: contractTerms, }); - const [oldRec, h] = await ctx.getRecordHandle(tx.wtx); + const [oldRec, h] = await ctx.getRecordHandle(tx); if (oldRec) { throw Error("record for peer-push-debit already exists"); } diff --git a/packages/taler-wallet-core/src/preset-exchanges.ts b/packages/taler-wallet-core/src/preset-exchanges.ts @@ -72,8 +72,8 @@ const builtinExchanges: BuiltinExchange[] = [ * already been applied. */ export async function fillDefaults(wex: WalletExecutionContext): Promise<void> { - await wex.runLegacyWalletDbTx(async (tx) => { - let appliedRec = await tx.wtx.getConfig( + await wex.runWalletDbTx(async (tx) => { + let appliedRec = await tx.getConfig( ConfigRecordKey.CurrencyDefaultsApplied, ); let appliedVersion = appliedRec ? !!appliedRec.value : 0; @@ -103,7 +103,7 @@ export async function fillDefaults(wex: WalletExecutionContext): Promise<void> { exch.currencySpec, ); } - await tx.wtx.upsertConfig({ + await tx.upsertConfig({ key: ConfigRecordKey.CurrencyDefaultsApplied, value: currentDefaultsVersion, }); diff --git a/packages/taler-wallet-core/src/recoup.ts b/packages/taler-wallet-core/src/recoup.ts @@ -64,11 +64,7 @@ import { import { CoinSourceType } from "./db-indexeddb.js"; import { createRefreshGroup } from "./refresh.js"; import { constructTransactionIdentifier } from "./transactions.js"; -import { - LegacyWalletTxHandle, - WalletExecutionContext, - getDenomInfo, -} from "./wallet.js"; +import { WalletExecutionContext, getDenomInfo } from "./wallet.js"; import { internalCreateWithdrawalGroup } from "./withdraw.js"; import { WalletDbTransaction } from "./dbtx.js"; @@ -80,7 +76,7 @@ const logger = new Logger("operations/recoup.ts"); */ export async function putGroupAsFinished( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, recoupGroup: WalletRecoupGroup, coinIdx: number, ): Promise<void> { @@ -92,8 +88,8 @@ export async function putGroupAsFinished( return; } recoupGroup.recoupFinishedPerCoin[coinIdx] = true; - await tx.wtx.upsertRecoupGroup(recoupGroup); - await ctx.updateTransactionMeta(tx.wtx); + await tx.upsertRecoupGroup(recoupGroup); + await ctx.updateTransactionMeta(tx); } async function recoupRewardCoin( @@ -105,8 +101,8 @@ async function recoupRewardCoin( // We can't really recoup a coin we got via tipping. // Thus we just put the coin to sleep. // FIXME: somehow report this to the user - await wex.runLegacyWalletDbTx(async (tx) => { - const recoupGroup = await tx.wtx.getRecoupGroup(recoupGroupId); + await wex.runWalletDbTx(async (tx) => { + const recoupGroup = await tx.getRecoupGroup(recoupGroupId); if (!recoupGroup) { return; } @@ -124,7 +120,7 @@ async function recoupRefreshCoin( coin: WalletCoin, cs: WalletRefreshCoinSource, ): Promise<void> { - const d = await wex.runLegacyWalletDbTx(async (tx) => { + const d = await wex.runWalletDbTx(async (tx) => { const denomInfo = await getDenomInfo( wex, tx, @@ -168,16 +164,16 @@ async function recoupRefreshCoin( throw Error(`Coin's oldCoinPub doesn't match reserve on recoup`); } - await wex.runLegacyWalletDbTx(async (tx) => { - const recoupGroup = await tx.wtx.getRecoupGroup(recoupGroupId); + await wex.runWalletDbTx(async (tx) => { + const recoupGroup = await tx.getRecoupGroup(recoupGroupId); if (!recoupGroup) { return; } if (recoupGroup.recoupFinishedPerCoin[coinIdx]) { return; } - const oldCoin = await tx.wtx.getCoin(cs.oldCoinPub); - const revokedCoin = await tx.wtx.getCoin(coin.coinPub); + const oldCoin = await tx.getCoin(cs.oldCoinPub); + const revokedCoin = await tx.getCoin(coin.coinPub); if (!revokedCoin) { logger.warn("revoked coin for recoup not found"); return; @@ -212,8 +208,8 @@ async function recoupRefreshCoin( // coinPub: oldCoin.coinPub, // amount: Amounts.stringify(refreshAmount), // }); - await tx.wtx.upsertCoin(revokedCoin); - await tx.wtx.upsertCoin(oldCoin); + await tx.upsertCoin(revokedCoin); + await tx.upsertCoin(oldCoin); await putGroupAsFinished(wex, tx, recoupGroup, coinIdx); }); } @@ -226,7 +222,7 @@ export async function recoupWithdrawCoin( cs: WalletWithdrawCoinSource, ): Promise<void> { const reservePub = cs.reservePub; - const denomInfo = await wex.runLegacyWalletDbTx(async (tx) => { + const denomInfo = await wex.runWalletDbTx(async (tx) => { const denomInfo = await getDenomInfo( wex, tx, @@ -266,20 +262,20 @@ export async function recoupWithdrawCoin( } // FIXME: verify that our expectations about the amount match - await wex.runLegacyWalletDbTx(async (tx) => { - const recoupGroup = await tx.wtx.getRecoupGroup(recoupGroupId); + await wex.runWalletDbTx(async (tx) => { + const recoupGroup = await tx.getRecoupGroup(recoupGroupId); if (!recoupGroup) { return; } if (recoupGroup.recoupFinishedPerCoin[coinIdx]) { return; } - const updatedCoin = await tx.wtx.getCoin(coin.coinPub); + const updatedCoin = await tx.getCoin(coin.coinPub); if (!updatedCoin) { return; } updatedCoin.status = CoinStatus.Dormant; - await tx.wtx.upsertCoin(updatedCoin); + await tx.upsertCoin(updatedCoin); await putGroupAsFinished(wex, tx, recoupGroup, coinIdx); }); } @@ -292,8 +288,8 @@ export async function processRecoupGroup( return TaskRunResult.networkRequired(); } - let recoupGroup = await wex.runLegacyWalletDbTx(async (tx) => { - return tx.wtx.getRecoupGroup(recoupGroupId); + let recoupGroup = await wex.runWalletDbTx(async (tx) => { + return tx.getRecoupGroup(recoupGroupId); }); if (!recoupGroup) { return TaskRunResult.finished(); @@ -312,8 +308,8 @@ export async function processRecoupGroup( }); await Promise.all(ps); - recoupGroup = await wex.runLegacyWalletDbTx(async (tx) => { - return tx.wtx.getRecoupGroup(recoupGroupId); + recoupGroup = await wex.runWalletDbTx(async (tx) => { + return tx.getRecoupGroup(recoupGroupId); }); if (!recoupGroup) { return TaskRunResult.finished(); @@ -331,13 +327,13 @@ export async function processRecoupGroup( const reservePrivMap: Record<string, string> = {}; for (let i = 0; i < recoupGroup.coinPubs.length; i++) { const coinPub = recoupGroup.coinPubs[i]; - await wex.runLegacyWalletDbTx(async (tx) => { - const coin = await tx.wtx.getCoin(coinPub); + await wex.runWalletDbTx(async (tx) => { + const coin = await tx.getCoin(coinPub); if (!coin) { throw Error(`Coin ${coinPub} not found, can't request recoup`); } if (coin.coinSource.type === CoinSourceType.Withdraw) { - const reserve = await tx.wtx.getReserveByReservePub( + const reserve = await tx.getReserveByReservePub( coin.coinSource.reservePub, ); if (!reserve) { @@ -378,8 +374,8 @@ export async function processRecoupGroup( const ctx = new RecoupTransactionContext(wex, recoupGroupId); - await wex.runLegacyWalletDbTx(async (tx) => { - const rg2 = await tx.wtx.getRecoupGroup(recoupGroupId); + await wex.runWalletDbTx(async (tx) => { + const rg2 = await tx.getRecoupGroup(recoupGroupId); if (!rg2) { return; } @@ -398,8 +394,8 @@ export async function processRecoupGroup( }), ); } - await tx.wtx.upsertRecoupGroup(rg2); - await ctx.updateTransactionMeta(tx.wtx); + await tx.upsertRecoupGroup(rg2); + await ctx.updateTransactionMeta(tx); }); return TaskRunResult.finished(); } @@ -467,8 +463,8 @@ export class RecoupTransactionContext implements TransactionContext { } async userDeleteTransaction(): Promise<void> { - const res = await this.wex.runLegacyWalletDbTx(async (tx) => { - return this.deleteTransactionInTx(tx.wtx); + const res = await this.wex.runWalletDbTx(async (tx) => { + return this.deleteTransactionInTx(tx); }); for (const notif of res.notifs) { this.wex.ws.notify(notif); @@ -497,7 +493,7 @@ export class RecoupTransactionContext implements TransactionContext { export async function createRecoupGroup( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, exchangeBaseUrl: string, coinPubs: string[], ): Promise<string> { @@ -517,16 +513,16 @@ export async function createRecoupGroup( for (let coinIdx = 0; coinIdx < coinPubs.length; coinIdx++) { const coinPub = coinPubs[coinIdx]; - const coin = await tx.wtx.getCoin(coinPub); + const coin = await tx.getCoin(coinPub); if (!coin) { await putGroupAsFinished(wex, tx, recoupGroup, coinIdx); continue; } - await tx.wtx.upsertCoin(coin); + await tx.upsertCoin(coin); } - await tx.wtx.upsertRecoupGroup(recoupGroup); - await ctx.updateTransactionMeta(tx.wtx); + await tx.upsertRecoupGroup(recoupGroup); + await ctx.updateTransactionMeta(tx); wex.taskScheduler.startShepherdTask(ctx.taskId); @@ -541,8 +537,8 @@ async function processRecoupForCoin( recoupGroupId: string, coinIdx: number, ): Promise<void> { - const coin = await wex.runLegacyWalletDbTx(async (tx) => { - const recoupGroup = await tx.wtx.getRecoupGroup(recoupGroupId); + const coin = await wex.runWalletDbTx(async (tx) => { + const recoupGroup = await tx.getRecoupGroup(recoupGroupId); if (!recoupGroup) { return; } @@ -555,7 +551,7 @@ async function processRecoupForCoin( const coinPub = recoupGroup.coinPubs[coinIdx]; - const coin = await tx.wtx.getCoin(coinPub); + const coin = await tx.getCoin(coinPub); if (!coin) { throw Error(`Coin ${coinPub} not found, can't request recoup`); } diff --git a/packages/taler-wallet-core/src/refresh.ts b/packages/taler-wallet-core/src/refresh.ts @@ -117,7 +117,6 @@ import { import { EXCHANGE_COINS_LOCK, getDenomInfo, - LegacyWalletTxHandle, WalletExecutionContext, } from "./wallet.js"; import { @@ -238,8 +237,8 @@ export class RefreshTransactionContext implements TransactionContext { } async userDeleteTransaction(): Promise<void> { - const res = await this.wex.runLegacyWalletDbTx(async (tx) => { - return this.deleteTransactionInTx(tx.wtx); + const res = await this.wex.runWalletDbTx(async (tx) => { + return this.deleteTransactionInTx(tx); }); } @@ -260,8 +259,8 @@ export class RefreshTransactionContext implements TransactionContext { } async userSuspendTransaction(): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; } @@ -293,8 +292,8 @@ export class RefreshTransactionContext implements TransactionContext { } async userResumeTransaction(): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; } @@ -321,8 +320,8 @@ export class RefreshTransactionContext implements TransactionContext { } async userFailTransaction(reason?: TalerErrorDetail): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await this.getRecordHandle(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; } @@ -348,7 +347,7 @@ export class RefreshTransactionContext implements TransactionContext { export async function getTotalRefreshCost( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, refreshedDenom: DenominationInfo, amountLeft: AmountJson, ): Promise<AmountJson> { @@ -415,11 +414,11 @@ function getTotalRefreshCostInternal( async function getCoinAvailabilityForDenom( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, denom: DenominationInfo, ageRestriction: number, ): Promise<WalletCoinAvailability> { - let car = await tx.wtx.getCoinAvailability( + let car = await tx.getCoinAvailability( denom.exchangeBaseUrl, denom.denomPubHash, ageRestriction, @@ -444,7 +443,7 @@ async function getCoinAvailabilityForDenom( */ async function initRefreshSession( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, refreshGroup: WalletRefreshGroup, coinIndex: number, ): Promise<void> { @@ -453,7 +452,7 @@ async function initRefreshSession( `creating refresh session for coin ${coinIndex} in refresh group ${refreshGroupId}`, ); const oldCoinPub = refreshGroup.oldCoinPubs[coinIndex]; - const oldCoin = await tx.wtx.getCoin(oldCoinPub); + const oldCoin = await tx.getCoin(oldCoinPub); if (!oldCoin) { throw Error("Can't refresh, coin not found"); } @@ -519,7 +518,7 @@ async function initRefreshSession( car.pendingRefreshOutputCount = (car.pendingRefreshOutputCount ?? 0) + newCoinDenoms.selectedDenoms[i].count; - await tx.wtx.upsertCoinAvailability(car); + await tx.upsertCoinAvailability(car); } const newSession: WalletRefreshSession = { @@ -532,7 +531,7 @@ async function initRefreshSession( })), amountRefreshOutput: Amounts.stringify(newCoinDenoms.totalCoinValue), }; - await tx.wtx.upsertRefreshSession(newSession); + await tx.upsertRefreshSession(newSession); } /** @@ -542,12 +541,12 @@ async function initRefreshSession( */ async function destroyRefreshSession( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, refreshGroup: WalletRefreshGroup, refreshSession: WalletRefreshSession, ): Promise<void> { for (let i = 0; i < refreshSession.newDenoms.length; i++) { - const oldCoin = await tx.wtx.getCoin( + const oldCoin = await tx.getCoin( refreshGroup.oldCoinPubs[refreshSession.coinIndex], ); if (!oldCoin) { @@ -571,7 +570,7 @@ async function destroyRefreshSession( ); car.pendingRefreshOutputCount = car.pendingRefreshOutputCount - refreshSession.newDenoms[i].count; - await tx.wtx.upsertCoinAvailability(car); + await tx.upsertCoinAvailability(car); } } @@ -595,12 +594,12 @@ async function refreshMelt( coinIndex: number, ): Promise<void> { const ctx = new RefreshTransactionContext(wex, refreshGroupId); - const d = await wex.runLegacyWalletDbTx(async (tx) => { - const refreshGroup = await tx.wtx.getRefreshGroup(refreshGroupId); + const d = await wex.runWalletDbTx(async (tx) => { + const refreshGroup = await tx.getRefreshGroup(refreshGroupId); if (!refreshGroup) { return; } - const refreshSession = await tx.wtx.getRefreshSession( + const refreshSession = await tx.getRefreshSession( refreshGroupId, coinIndex, ); @@ -611,7 +610,7 @@ async function refreshMelt( return; } - const oldCoin = await tx.wtx.getCoin(refreshGroup.oldCoinPubs[coinIndex]); + const oldCoin = await tx.getCoin(refreshGroup.oldCoinPubs[coinIndex]); checkDbInvariant(!!oldCoin, "melt coin doesn't exist"); const oldDenom = await getDenomInfo( wex, @@ -660,8 +659,8 @@ async function refreshMelt( throw Error("unsupported exchange version"); } const seed = encodeCrock(getRandomBytes(64)); - const updatedSession = await wex.runLegacyWalletDbTx(async (tx) => { - const refreshSession = await tx.wtx.getRefreshSession( + const updatedSession = await wex.runWalletDbTx(async (tx) => { + const refreshSession = await tx.getRefreshSession( refreshGroupId, coinIndex, ); @@ -672,7 +671,7 @@ async function refreshMelt( return refreshSession; } refreshSession.sessionPublicSeed = seed; - await tx.wtx.upsertRefreshSession(refreshSession); + await tx.upsertRefreshSession(refreshSession); return refreshSession; }); if (!updatedSession) { @@ -780,15 +779,15 @@ async function refreshMelt( refreshSession.norevealIndex = norevealIndex; - await wex.runLegacyWalletDbTx(async (tx) => { - const rg = await tx.wtx.getRefreshGroup(refreshGroupId); + await wex.runWalletDbTx(async (tx) => { + const rg = await tx.getRefreshGroup(refreshGroupId); if (!rg) { return; } if (rg.timestampFinished) { return; } - const rs = await tx.wtx.getRefreshSession(refreshGroupId, coinIndex); + const rs = await tx.getRefreshSession(refreshGroupId, coinIndex); if (!rs) { return; } @@ -796,7 +795,7 @@ async function refreshMelt( return; } rs.norevealIndex = norevealIndex; - await tx.wtx.upsertRefreshSession(rs); + await tx.upsertRefreshSession(rs); }); } @@ -819,8 +818,8 @@ async function handleRefreshMeltGone( target: ctx.transactionId, }); - await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rg, h] = await ctx.getRecordHandle(tx.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rg, h] = await ctx.getRecordHandle(tx); if (!rg) { return; } @@ -831,7 +830,7 @@ async function handleRefreshMeltGone( return; } rg.statusPerCoin[coinIndex] = RefreshCoinStatus.PendingRedenominate; - const refreshSession = await tx.wtx.getRefreshSession( + const refreshSession = await tx.getRefreshSession( ctx.refreshGroupId, coinIndex, ); @@ -839,7 +838,7 @@ async function handleRefreshMeltGone( throw Error("db invariant failed: missing refresh session in database"); } refreshSession.lastError = errDetails; - await tx.wtx.upsertRefreshSession(refreshSession); + await tx.upsertRefreshSession(refreshSession); await h.update(rg); }); } @@ -873,13 +872,13 @@ async function handleRefreshMeltConflict( }); switch (httpResp.status) { case HttpStatusCode.Ok: - await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const rg = await tx.wtx.getRefreshGroup(refreshGroup.refreshGroupId); + await ctx.wex.runWalletDbTx(async (tx) => { + const rg = await tx.getRefreshGroup(refreshGroup.refreshGroupId); if (!rg || rg.operationStatus != RefreshOperationStatus.Pending) { return; } delete rg.refundRequests[coinIndex]; - await tx.wtx.upsertRefreshGroup(rg); + await tx.upsertRefreshGroup(rg); }); break; default: @@ -919,8 +918,8 @@ 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.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rg, h] = await ctx.getRecordHandle(tx); if (!rg) { return; } @@ -932,7 +931,7 @@ async function handleRefreshMeltConflict( } if (Amounts.isZero(historyJson.balance)) { rg.statusPerCoin[coinIndex] = RefreshCoinStatus.Failed; - const refreshSession = await tx.wtx.getRefreshSession( + const refreshSession = await tx.getRefreshSession( ctx.refreshGroupId, coinIndex, ); @@ -940,12 +939,12 @@ async function handleRefreshMeltConflict( throw Error("db invariant failed: missing refresh session in database"); } refreshSession.lastError = errDetails; - await tx.wtx.upsertRefreshSession(refreshSession); + await tx.upsertRefreshSession(refreshSession); await h.update(rg); } else { // Try again with new denoms! rg.inputPerCoin[coinIndex] = historyJson.balance; - const refreshSession = await tx.wtx.getRefreshSession( + const refreshSession = await tx.getRefreshSession( ctx.refreshGroupId, coinIndex, ); @@ -953,7 +952,7 @@ async function handleRefreshMeltConflict( throw Error("db invariant failed: missing refresh session in database"); } await destroyRefreshSession(ctx.wex, tx, rg, refreshSession); - await tx.wtx.deleteRefreshSession(ctx.refreshGroupId, coinIndex); + await tx.deleteRefreshSession(ctx.refreshGroupId, coinIndex); await initRefreshSession(ctx.wex, tx, rg, coinIndex); } }); @@ -974,8 +973,8 @@ async function handleRefreshMeltNotFound( default: throwUnexpectedRequestError(resp, errDetails); } - await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rg, h] = await ctx.getRecordHandle(tx.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rg, h] = await ctx.getRecordHandle(tx); if (!rg) { return; } @@ -986,7 +985,7 @@ async function handleRefreshMeltNotFound( return; } rg.statusPerCoin[coinIndex] = RefreshCoinStatus.Failed; - const refreshSession = await tx.wtx.getRefreshSession( + const refreshSession = await tx.getRefreshSession( ctx.refreshGroupId, coinIndex, ); @@ -994,7 +993,7 @@ async function handleRefreshMeltNotFound( throw Error("db invariant failed: missing refresh session in database"); } refreshSession.lastError = errDetails; - await tx.wtx.upsertRefreshSession(refreshSession); + await tx.upsertRefreshSession(refreshSession); await destroyRefreshSession(ctx.wex, tx, rg, refreshSession); await h.update(rg); }); @@ -1009,12 +1008,12 @@ async function refreshReveal( `doing refresh reveal for ${refreshGroupId} (old coin ${coinIndex})`, ); const ctx = new RefreshTransactionContext(wex, refreshGroupId); - const d = await wex.runLegacyWalletDbTx(async (tx) => { - const refreshGroup = await tx.wtx.getRefreshGroup(refreshGroupId); + const d = await wex.runWalletDbTx(async (tx) => { + const refreshGroup = await tx.getRefreshGroup(refreshGroupId); if (!refreshGroup) { return; } - const refreshSession = await tx.wtx.getRefreshSession( + const refreshSession = await tx.getRefreshSession( refreshGroupId, coinIndex, ); @@ -1026,7 +1025,7 @@ async function refreshReveal( throw Error("can't reveal without melting first"); } - const oldCoin = await tx.wtx.getCoin(refreshGroup.oldCoinPubs[coinIndex]); + const oldCoin = await tx.getCoin(refreshGroup.oldCoinPubs[coinIndex]); checkDbInvariant(!!oldCoin, "melt coin doesn't exist"); const oldDenom = await getDenomInfo( wex, @@ -1174,8 +1173,8 @@ async function refreshReveal( } } - await wex.runLegacyWalletDbTx(async (tx) => { - const [rg, h] = await ctx.getRecordHandle(tx.wtx); + await wex.runWalletDbTx(async (tx) => { + const [rg, h] = await ctx.getRecordHandle(tx); if (!rg) { logger.warn("no refresh session found"); return; @@ -1183,17 +1182,17 @@ async function refreshReveal( if (rg.statusPerCoin[coinIndex] !== RefreshCoinStatus.Pending) { return; } - const rs = await tx.wtx.getRefreshSession(refreshGroupId, coinIndex); + const rs = await tx.getRefreshSession(refreshGroupId, coinIndex); if (!rs) { return; } rg.statusPerCoin[coinIndex] = RefreshCoinStatus.Finished; for (const coin of coins) { - const existingCoin = await tx.wtx.getCoin(coin.coinPub); + const existingCoin = await tx.getCoin(coin.coinPub); if (existingCoin) { continue; } - await tx.wtx.upsertCoin(coin); + await tx.upsertCoin(coin); const denomInfo = await getDenomInfo( wex, tx, @@ -1214,7 +1213,7 @@ async function refreshReveal( ); car.pendingRefreshOutputCount--; car.freshCoinCount++; - await tx.wtx.upsertCoinAvailability(car); + await tx.upsertCoinAvailability(car); } await h.update(rg); }); @@ -1226,8 +1225,8 @@ async function handleRefreshRevealError( coinIndex: number, errDetails: TalerErrorDetail, ): Promise<void> { - await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rg, h] = await ctx.getRecordHandle(tx.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rg, h] = await ctx.getRecordHandle(tx); if (!rg) { return; } @@ -1238,7 +1237,7 @@ async function handleRefreshRevealError( return; } rg.statusPerCoin[coinIndex] = RefreshCoinStatus.Failed; - const refreshSession = await tx.wtx.getRefreshSession( + const refreshSession = await tx.getRefreshSession( ctx.refreshGroupId, coinIndex, ); @@ -1247,7 +1246,7 @@ async function handleRefreshRevealError( } refreshSession.lastError = errDetails; await destroyRefreshSession(ctx.wex, tx, rg, refreshSession); - await tx.wtx.upsertRefreshSession(refreshSession); + await tx.upsertRefreshSession(refreshSession); await h.update(rg); }); } @@ -1262,8 +1261,8 @@ export async function processRefreshGroup( logger.trace(`processing refresh group ${refreshGroupId}`); - const refreshGroup = await wex.runLegacyWalletDbTx(async (tx) => - tx.wtx.getRefreshGroup(refreshGroupId), + const refreshGroup = await wex.runWalletDbTx(async (tx) => + tx.getRefreshGroup(refreshGroupId), ); if (!refreshGroup) { return TaskRunResult.finished(); @@ -1349,8 +1348,8 @@ export async function processRefreshGroup( // We've processed all refresh session and can now update the // status of the whole refresh group. - const didTransition: boolean = await wex.runLegacyWalletDbTx(async (tx) => { - const [rg, h] = await ctx.getRecordHandle(tx.wtx); + const didTransition: boolean = await wex.runWalletDbTx(async (tx) => { + const [rg, h] = await ctx.getRecordHandle(tx); if (!rg) { return false; } @@ -1380,7 +1379,7 @@ export async function processRefreshGroup( ); rg.operationStatus = RefreshOperationStatus.Finished; } - await makeCoinsVisible(wex, tx.wtx, ctx.transactionId); + await makeCoinsVisible(wex, tx, ctx.transactionId); await h.update(rg); return true; } @@ -1415,27 +1414,25 @@ async function processRefreshSession( logger.trace( `processing refresh session for coin ${coinIndex} of group ${refreshGroupId}`, ); - let { refreshGroup, refreshSession } = await wex.runLegacyWalletDbTx( - async (tx) => { - const rg = await tx.wtx.getRefreshGroup(refreshGroupId); - const rs = await tx.wtx.getRefreshSession(refreshGroupId, coinIndex); + let { refreshGroup, refreshSession } = await wex.runWalletDbTx(async (tx) => { + const rg = await tx.getRefreshGroup(refreshGroupId); + const rs = await tx.getRefreshSession(refreshGroupId, coinIndex); - if ( - rg != null && - rg.statusPerCoin[coinIndex] === RefreshCoinStatus.PendingRedenominate - ) { - await tx.wtx.deleteRefreshSession(refreshGroupId, coinIndex); - await initRefreshSession(wex, tx, rg, coinIndex); - rg.statusPerCoin[coinIndex] = RefreshCoinStatus.Pending; - await tx.wtx.upsertRefreshGroup(rg); - } + if ( + rg != null && + rg.statusPerCoin[coinIndex] === RefreshCoinStatus.PendingRedenominate + ) { + await tx.deleteRefreshSession(refreshGroupId, coinIndex); + await initRefreshSession(wex, tx, rg, coinIndex); + rg.statusPerCoin[coinIndex] = RefreshCoinStatus.Pending; + await tx.upsertRefreshGroup(rg); + } - return { - refreshGroup: rg, - refreshSession: rs, - }; - }, - ); + return { + refreshGroup: rg, + refreshSession: rs, + }; + }); if (!refreshGroup) { return; } @@ -1459,7 +1456,7 @@ export interface RefreshOutputInfo { export async function calculateRefreshOutput( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, currency: string, oldCoinPubs: CoinRefreshRequest[], ): Promise<RefreshOutputInfo> { @@ -1468,7 +1465,7 @@ export async function calculateRefreshOutput( const infoPerExchange: Record<string, WalletRefreshGroupPerExchangeInfo> = {}; for (const ocp of oldCoinPubs) { - const coin = await tx.wtx.getCoin(ocp.coinPub); + const coin = await tx.getCoin(ocp.coinPub); checkDbInvariant(!!coin, "coin must be in database"); const denom = await getDenomInfo( wex, @@ -1508,12 +1505,12 @@ export async function calculateRefreshOutput( async function applyRefreshToOldCoins( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, oldCoinPubs: CoinRefreshRequest[], refreshGroupId: string, ): Promise<void> { for (const ocp of oldCoinPubs) { - const coin = await tx.wtx.getCoin(ocp.coinPub); + const coin = await tx.getCoin(ocp.coinPub); checkDbInvariant(!!coin, "coin must be in database"); const denom = await getDenomInfo( wex, @@ -1530,7 +1527,7 @@ async function applyRefreshToOldCoins( break; case CoinStatus.Fresh: { coin.status = CoinStatus.Dormant; - const coinAv = await tx.wtx.getCoinAvailability( + const coinAv = await tx.getCoinAvailability( coin.exchangeBaseUrl, coin.denomPubHash, coin.maxAge, @@ -1551,7 +1548,7 @@ async function applyRefreshToOldCoins( coinAv.visibleCoinCount--; } } - await tx.wtx.upsertCoinAvailability(coinAv); + await tx.upsertCoinAvailability(coinAv); break; } case CoinStatus.FreshSuspended: { @@ -1565,7 +1562,7 @@ async function applyRefreshToOldCoins( default: assertUnreachable(coin.status); } - let histEntry: WalletCoinHistory | undefined = await tx.wtx.getCoinHistory( + let histEntry: WalletCoinHistory | undefined = await tx.getCoinHistory( coin.coinPub, ); if (!histEntry) { @@ -1582,8 +1579,8 @@ async function applyRefreshToOldCoins( }), amount: Amounts.stringify(ocp.amount), }); - await tx.wtx.upsertCoinHistory(histEntry); - await tx.wtx.upsertCoin(coin); + await tx.upsertCoinHistory(histEntry); + await tx.upsertCoin(coin); } } @@ -1602,7 +1599,7 @@ export interface CreateRefreshGroupResult { */ export async function createRefreshGroup( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, currency: string, oldCoinPubs: CoinRefreshRequest[], refreshReason: RefreshReason, @@ -1611,7 +1608,7 @@ export async function createRefreshGroup( const exchanges: Set<string> = new Set(); for (const x of oldCoinPubs) { - const rec = await tx.wtx.getCoin(x.coinPub); + const rec = await tx.getCoin(x.coinPub); if (!rec) { continue; } @@ -1677,8 +1674,8 @@ export async function createRefreshGroup( const ctx = new RefreshTransactionContext(wex, refreshGroupId); - await tx.wtx.upsertRefreshGroup(refreshGroup); - await ctx.updateTransactionMeta(tx.wtx); + await tx.upsertRefreshGroup(refreshGroup); + await ctx.updateTransactionMeta(tx); const newTxState = computeRefreshTransactionState(refreshGroup); @@ -1711,8 +1708,8 @@ async function redenominateRefresh( const ctx = new RefreshTransactionContext(wex, refreshGroupId); logger.info(`re-denominating refresh group ${refreshGroupId}`); - const exchanges = await wex.runLegacyWalletDbTx(async (tx) => { - const [rg, _] = await ctx.getRecordHandle(tx.wtx); + const exchanges = await wex.runWalletDbTx(async (tx) => { + const [rg, _] = await ctx.getRecordHandle(tx); if (rg?.infoPerExchange) { return Object.keys(rg.infoPerExchange); } @@ -1724,8 +1721,8 @@ async function redenominateRefresh( await updateWithdrawalDenomsForExchange(wex, e); } - return await wex.runLegacyWalletDbTx(async (tx) => { - const [refreshGroup, h] = await ctx.getRecordHandle(tx.wtx); + return await wex.runWalletDbTx(async (tx) => { + const [refreshGroup, h] = await ctx.getRecordHandle(tx); if (!refreshGroup) { return TaskRunResult.finished(); } @@ -1834,9 +1831,9 @@ export function getRefreshesForTransaction( wex: WalletExecutionContext, transactionId: string, ): Promise<string[]> { - return wex.runLegacyWalletDbTx(async (tx) => { + return wex.runWalletDbTx(async (tx) => { const groups = - await tx.wtx.getRefreshGroupsByOriginatingTransaction(transactionId); + await tx.getRefreshGroupsByOriginatingTransaction(transactionId); return groups.map((x) => constructTransactionIdentifier({ tag: TransactionType.Refresh, @@ -1853,10 +1850,10 @@ export async function forceRefresh( if (req.refreshCoinSpecs.length == 0) { throw Error("refusing to create empty refresh group"); } - const res = await wex.runLegacyWalletDbTx(async (tx) => { + const res = await wex.runWalletDbTx(async (tx) => { const coinPubs: CoinRefreshRequest[] = []; for (const c of req.refreshCoinSpecs) { - const coin = await tx.wtx.getCoin(c.coinPub); + const coin = await tx.getCoin(c.coinPub); if (!coin) { throw Error(`coin (pubkey ${c}) not found`); } @@ -1900,9 +1897,9 @@ export async function waitRefreshFinal( await genericWaitForState(wex, { async checkState(): Promise<boolean> { // Check if refresh is final - const res = await ctx.wex.runLegacyWalletDbTx(async (tx) => { + const res = await ctx.wex.runWalletDbTx(async (tx) => { return { - rg: await tx.wtx.getRefreshGroup(ctx.refreshGroupId), + rg: await tx.getRefreshGroup(ctx.refreshGroupId), }; }); const { rg } = res; diff --git a/packages/taler-wallet-core/src/shepherd.ts b/packages/taler-wallet-core/src/shepherd.ts @@ -17,7 +17,6 @@ /** * Imports. */ -import { GlobalIDB } from "@gnu-taler/idb-bridge"; import { AbsoluteTime, AsyncCondition, @@ -1258,8 +1257,8 @@ export async function getActiveTaskIds( export async function processCleanupExpiredTransactions( wex: WalletExecutionContext, ): Promise<TaskRunResult> { - await wex.runLegacyWalletDbTx(async (tx) => { - const expired = await tx.wtx.getPurchasesByStatus(PurchaseStatus.Expired); + await wex.runWalletDbTx(async (tx) => { + const expired = await tx.getPurchasesByStatus(PurchaseStatus.Expired); for (const exp of expired) { if (!exp.timestampExpired) { continue; diff --git a/packages/taler-wallet-core/src/transactions.ts b/packages/taler-wallet-core/src/transactions.ts @@ -65,7 +65,7 @@ import { PeerPullDebitTransactionContext } from "./pay-peer-pull-debit.js"; import { PeerPushCreditTransactionContext } from "./pay-peer-push-credit.js"; import { PeerPushDebitTransactionContext } from "./pay-peer-push-debit.js"; import { RefreshTransactionContext } from "./refresh.js"; -import type { LegacyWalletTxHandle, WalletExecutionContext } from "./wallet.js"; +import type { WalletExecutionContext } from "./wallet.js"; import { WithdrawTransactionContext } from "./withdraw.js"; import { WalletDbTransaction } from "./dbtx.js"; @@ -153,8 +153,8 @@ export async function getTransactionById( case TransactionType.PeerPullDebit: case TransactionType.Refund: { const ctx = await getContextForTransaction(wex, req.transactionId); - const txDetails = await wex.runLegacyWalletDbTx(async (tx) => - ctx.lookupFullTransaction(tx.wtx, { + const txDetails = await wex.runWalletDbTx(async (tx) => + ctx.lookupFullTransaction(tx, { includeContractTerms: req.includeContractTerms, }), ); @@ -247,7 +247,7 @@ function checkFilterIncludes( async function addFiltered( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, req: GetTransactionsV2Request | undefined, target: Transaction[], source: WalletTransactionMeta[], @@ -259,7 +259,7 @@ async function addFiltered( } if (checkFilterIncludes(req, mtx)) { const ctx = await getContextForTransaction(wex, mtx.transactionId); - const txDetails = await ctx.lookupFullTransaction(tx.wtx); + const txDetails = await ctx.lookupFullTransaction(tx); // FIXME: This means that in some cases we can return fewer transactions // than requested. if (!txDetails) { @@ -304,13 +304,13 @@ function sortTransactions( } async function findOffsetTransaction( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, req?: GetTransactionsV2Request, ): Promise<WalletTransactionMeta | undefined> { let forwards = req?.limit == null || req.limit >= 0; let closestTimestamp: DbPreciseTimestamp | undefined = undefined; if (req?.offsetTransactionId) { - const res = await tx.wtx.getTransactionMeta(req.offsetTransactionId); + const res = await tx.getTransactionMeta(req.offsetTransactionId); if (res) { return res; } @@ -323,7 +323,7 @@ async function findOffsetTransaction( } } else if (req?.offsetTimestamp) { const dbStamp = timestampPreciseToDb(req.offsetTimestamp); - const res = await tx.wtx.getTransactionMetaAtTimestamp(dbStamp); + const res = await tx.getTransactionMetaAtTimestamp(dbStamp); if (res) { return res; } @@ -341,10 +341,10 @@ async function findOffsetTransaction( // We don't want to skip transactions in pagination, // so get the transaction before the timestamp - return await tx.wtx.getTransactionMetaBefore(closestTimestamp); + return await tx.getTransactionMetaBefore(closestTimestamp); } else { // Likewise, get the transaction after the timestamp - return await tx.wtx.getTransactionMetaAfter(closestTimestamp); + return await tx.getTransactionMetaAfter(closestTimestamp); } } @@ -360,7 +360,7 @@ export async function getTransactionsV2( const resultTransactions: Transaction[] = []; - await wex.runLegacyWalletDbTx(async (tx) => { + await wex.runWalletDbTx(async (tx) => { let forwards = transactionsRequest?.limit == null || transactionsRequest.limit >= 0; let limit = @@ -372,7 +372,7 @@ export async function getTransactionsV2( if (limit == null && offsetMtx == null) { // Fast path for returning *everything* that matches the filter. // FIXME: We could use the DB for filtering here - const res = await tx.wtx.listTransactionMetaByStatus({ + const res = await tx.listTransactionMetaByStatus({ onlyActive: false, }); await addFiltered(wex, tx, transactionsRequest, resultTransactions, res); @@ -380,7 +380,7 @@ export async function getTransactionsV2( // Descending, backwards request. // Slow implementation. Doing it properly would require using cursors, // which are also slow in IndexedDB. - const res = await tx.wtx.listTransactionMetaByTimestamp({}); + const res = await tx.listTransactionMetaByTimestamp({}); res.reverse(); let start: number; if (offsetMtx != null) { @@ -405,7 +405,7 @@ export async function getTransactionsV2( let afterTimestamp: DbPreciseTimestamp | undefined = offsetMtx != null ? offsetMtx.timestamp : undefined; while (true) { - const res = await tx.wtx.listTransactionMetaByTimestamp({ + const res = await tx.listTransactionMetaByTimestamp({ afterTimestamp, limit, }); @@ -446,8 +446,8 @@ export async function getTransactions( const onlyActive = transactionsRequest?.filterByState === "nonfinal"; - await wex.runLegacyWalletDbTx(async (tx) => { - const allMetaTransactions = await tx.wtx.listTransactionMetaByStatus({ + await wex.runWalletDbTx(async (tx) => { + const allMetaTransactions = await tx.listTransactionMetaByStatus({ onlyActive, }); for (const metaTx of allMetaTransactions) { @@ -470,7 +470,7 @@ export async function getTransactions( } const ctx = await getContextForTransaction(wex, metaTx.transactionId); - const txDetails = await ctx.lookupFullTransaction(tx.wtx); + const txDetails = await ctx.lookupFullTransaction(tx); if (!txDetails) { continue; } diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts @@ -577,13 +577,11 @@ const MATERIALIZED_TRANSACTIONS_VERSION = 4; async function migrateMaterializedTransactions( wex: WalletExecutionContext, ): Promise<void> { - await wex.runLegacyWalletDbTx(async (tx) => { - const ver = await tx.config.get("materializedTransactionsVersion"); + await wex.runWalletDbTx(async (tx) => { + const ver = await tx.getConfig( + ConfigRecordKey.MaterializedTransactionsVersion, + ); if (ver) { - if (ver.key !== ConfigRecordKey.MaterializedTransactionsVersion) { - logger.error("invalid configuration (materializedTransactionsVersion)"); - return; - } if (ver.value == MATERIALIZED_TRANSACTIONS_VERSION) { return; } @@ -595,9 +593,9 @@ async function migrateMaterializedTransactions( } } - await rematerializeTransactions(wex, tx.wtx); + await rematerializeTransactions(wex, tx); - await tx.config.put({ + await tx.upsertConfig({ key: ConfigRecordKey.MaterializedTransactionsVersion, value: MATERIALIZED_TRANSACTIONS_VERSION, }); @@ -634,8 +632,8 @@ async function handleListBankAccounts( ): Promise<ListBankAccountsResponse> { const accounts: WalletBankAccountInfo[] = []; const currency = req.currency; - await wex.runLegacyWalletDbTx(async (tx) => { - const knownAccounts = await tx.bankAccountsV2.iter().toArray(); + await wex.runWalletDbTx(async (tx) => { + const knownAccounts = await tx.listBankAccounts(); for (const r of knownAccounts) { if (currency && r.currencies && !r.currencies.includes(currency)) { continue; @@ -659,8 +657,8 @@ async function handleGetBankAccountById( wex: WalletExecutionContext, req: GetBankAccountByIdRequest, ): Promise<GetBankAccountByIdResponse> { - const acct = await wex.runLegacyWalletDbTx(async (tx) => { - return tx.bankAccountsV2.get(req.bankAccountId); + const acct = await wex.runWalletDbTx(async (tx) => { + return tx.getBankAccount(req.bankAccountId); }); if (!acct) { throw Error(`bank account ${req.bankAccountId} not found`); @@ -675,12 +673,12 @@ async function forgetBankAccount( wex: WalletExecutionContext, bankAccountId: string, ): Promise<void> { - await wex.runLegacyWalletDbTx(async (tx) => { - const account = await tx.bankAccountsV2.get(bankAccountId); + await wex.runWalletDbTx(async (tx) => { + const account = await tx.getBankAccount(bankAccountId); if (!account) { throw Error(`account not found: ${bankAccountId}`); } - tx.bankAccountsV2.delete(account.bankAccountId); + await tx.deleteBankAccount(account.bankAccountId); }); wex.ws.notify({ type: NotificationType.BankAccountChange, @@ -694,17 +692,17 @@ async function setCoinSuspended( coinPub: string, suspended: boolean, ): Promise<void> { - await wex.runLegacyWalletDbTx(async (tx) => { - const c = await tx.coins.get(coinPub); + await wex.runWalletDbTx(async (tx) => { + const c = await tx.getCoin(coinPub); if (!c) { logger.warn(`coin ${coinPub} not found, won't suspend`); return; } - const coinAvailability = await tx.coinAvailability.get([ + const coinAvailability = await tx.getCoinAvailability( c.exchangeBaseUrl, c.denomPubHash, c.maxAge, - ]); + ); checkDbInvariant( !!coinAvailability, `no denom info for ${c.denomPubHash} age ${c.maxAge}`, @@ -727,8 +725,8 @@ async function setCoinSuspended( coinAvailability.freshCoinCount++; c.status = CoinStatus.Fresh; } - await tx.coins.put(c); - await tx.coinAvailability.put(coinAvailability); + await tx.upsertCoin(c); + await tx.upsertCoinAvailability(coinAvailability); }); } @@ -738,13 +736,10 @@ async function setCoinSuspended( async function dumpCoins(wex: WalletExecutionContext): Promise<CoinDumpJson> { const coinsJson: CoinDumpJson = { coins: [] }; logger.info("dumping coins"); - await wex.runLegacyWalletDbTx(async (tx) => { - const coins = await tx.coins.iter().toArray(); + await wex.runWalletDbTx(async (tx) => { + const coins = await tx.listAllCoins(); for (const c of coins) { - const denom = await tx.wtx.getDenomination( - c.exchangeBaseUrl, - c.denomPubHash, - ); + const denom = await tx.getDenomination(c.exchangeBaseUrl, c.denomPubHash); if (!denom) { logger.warn("no denom found for coin"); continue; @@ -768,7 +763,7 @@ async function dumpCoins(wex: WalletExecutionContext): Promise<CoinDumpJson> { logger.warn("no denomination found for coin"); continue; } - const historyRec = await tx.coinHistory.get(c.coinPub); + const historyRec = await tx.getCoinHistory(c.coinPub); coinsJson.coins.push({ coinPub: c.coinPub, denomPub: denom.denomPub, @@ -1022,8 +1017,8 @@ async function handleSetWalletRunConfig( // Write to the DB to make sure that we're failing early in // case the DB is not writeable. try { - await wex.runLegacyWalletDbTx(async (tx) => { - tx.config.put({ + await wex.runWalletDbTx(async (tx) => { + tx.upsertConfig({ key: ConfigRecordKey.LastInitInfo, value: timestampProtocolToDb(TalerProtocolTimestamp.now()), }); @@ -1156,7 +1151,7 @@ async function handleAddExchange( // Exchange has been explicitly added upon user request. // Thus, we mark it as "used". if (!req.ephemeral) { - await wex.runLegacyWalletDbTx(async (tx) => { + await wex.runWalletDbTx(async (tx) => { await markExchangeUsed(tx, exchangeBaseUrl); }); } @@ -1185,8 +1180,8 @@ async function handleTestingGetDenomStats( numLost: 0, numOffered: 0, }; - await wex.runLegacyWalletDbTx(async (tx) => { - const denoms = await tx.wtx.getDenominationsByExchange(req.exchangeBaseUrl); + await wex.runWalletDbTx(async (tx) => { + const denoms = await tx.getDenominationsByExchange(req.exchangeBaseUrl); for (const d of denoms) { denomStats.numKnown++; if (d.isOffered) { @@ -1207,12 +1202,10 @@ async function handleAddBankAccount( if (Result.isError(Paytos.fromString(req.paytoUri))) { throw Error("invalid payto"); } - const acctId = await wex.runLegacyWalletDbTx(async (tx) => { + const acctId = await wex.runWalletDbTx(async (tx) => { let currencies = req.currencies; let myId: string; - const oldAcct = await tx.bankAccountsV2.indexes.byPaytoUri.get( - req.paytoUri, - ); + const oldAcct = await tx.getBankAccountByPaytoUri(req.paytoUri); if (req.replaceBankAccountId) { myId = req.replaceBankAccountId; } else if (oldAcct) { @@ -1225,7 +1218,7 @@ async function handleAddBankAccount( // New Account! myId = `acct:${encodeCrock(getRandomBytes(32))}`; } - await tx.bankAccountsV2.put({ + await tx.upsertBankAccount({ bankAccountId: myId, paytoUri: req.paytoUri, label: req.label, @@ -1256,8 +1249,8 @@ async function handleTestingGetReserveHistory( wex: WalletExecutionContext, req: TestingGetReserveHistoryRequest, ): Promise<any> { - const reserve = await wex.runLegacyWalletDbTx(async (tx) => { - return tx.wtx.getReserveByReservePub(req.reservePub); + const reserve = await wex.runWalletDbTx(async (tx) => { + return tx.getReserveByReservePub(req.reservePub); }); if (!reserve) { throw Error("no reserve pub found"); @@ -1438,8 +1431,8 @@ async function handleGetActiveTasks( const tasksInfo = await Promise.all( allTasksId.map(async (id) => { - return await wex.runLegacyWalletDbTx(async (tx) => { - return tx.wtx.getOperationRetry(id); + return await wex.runWalletDbTx(async (tx) => { + return tx.getOperationRetry(id); }); }), ); @@ -1526,10 +1519,10 @@ async function handleGetDepositWireTypes( const wtSet: Set<string> = new Set(); const wireTypeDetails: WireTypeDetails[] = []; const talerBankHostnames: string[] = []; - await wex.runLegacyWalletDbTx(async (tx) => { - const exchanges = await tx.exchanges.getAll(); + await wex.runWalletDbTx(async (tx) => { + const exchanges = await tx.getExchanges(); for (const exchange of exchanges) { - const det = await getExchangeDetailsInTx(tx.wtx, exchange.baseUrl); + const det = await getExchangeDetailsInTx(tx, exchange.baseUrl); if (!det) { continue; } @@ -1591,10 +1584,10 @@ async function handleGetDepositWireTypesForCurrency( const wtSet: Set<string> = new Set(); const wireTypeDetails: WireTypeDetails[] = []; const talerBankHostnames: string[] = []; - await wex.runLegacyWalletDbTx(async (tx) => { - const exchanges = await tx.exchanges.getAll(); + await wex.runWalletDbTx(async (tx) => { + const exchanges = await tx.getExchanges(); for (const exchange of exchanges) { - const det = await getExchangeDetailsInTx(tx.wtx, exchange.baseUrl); + const det = await getExchangeDetailsInTx(tx, exchange.baseUrl); if (!det) { continue; } @@ -1648,8 +1641,8 @@ async function handleListGlobalCurrencyExchanges( const resp: ListGlobalCurrencyExchangesResponse = { exchanges: [], }; - await wex.runLegacyWalletDbTx(async (tx) => { - const gceList = await tx.globalCurrencyExchanges.iter().toArray(); + await wex.runWalletDbTx(async (tx) => { + const gceList = await tx.listGlobalCurrencyExchanges(); for (const gce of gceList) { resp.exchanges.push({ currency: gce.currency, @@ -1668,8 +1661,8 @@ async function handleListGlobalCurrencyAuditors( const resp: ListGlobalCurrencyAuditorsResponse = { auditors: [], }; - await wex.runLegacyWalletDbTx(async (tx) => { - const gcaList = await tx.globalCurrencyAuditors.iter().toArray(); + await wex.runWalletDbTx(async (tx) => { + const gcaList = await tx.listGlobalCurrencyAuditors(); for (const gca of gcaList) { resp.auditors.push({ currency: gca.currency, @@ -1685,29 +1678,32 @@ export async function handleAddGlobalCurrencyExchange( wex: WalletExecutionContext, req: AddGlobalCurrencyExchangeRequest, ): Promise<EmptyObject> { - await wex.runLegacyWalletDbTx(async (tx) => { - const key = [req.currency, req.exchangeBaseUrl, req.exchangeMasterPub]; - const existingRec = - await tx.globalCurrencyExchanges.indexes.byCurrencyAndUrlAndPub.get(key); + await wex.runWalletDbTx(async (tx) => { + const existingRec = await tx.getGlobalCurrencyExchange( + req.currency, + req.exchangeBaseUrl, + req.exchangeMasterPub, + ); if (existingRec) { return; } wex.ws.exchangeCache.clear(); - const infoRec = await tx.currencyInfo.get( - stringifyScopeInfo({ - type: ScopeType.Exchange, - currency: req.currency, - url: req.exchangeBaseUrl, - }), - ); + // Re-scope currency info from exchange scope to global scope. The scope + // string is the primary key, so this writes a new record and leaves the + // exchange-scoped one, as it did before. + const infoRec = await tx.getCurrencyInfo({ + type: ScopeType.Exchange, + currency: req.currency, + url: req.exchangeBaseUrl, + }); if (infoRec) { - infoRec.scopeInfoStr = stringifyScopeInfo({ - type: ScopeType.Global, - currency: req.currency, + await tx.upsertCurrencyInfo({ + scopeInfo: { type: ScopeType.Global, currency: req.currency }, + currencySpec: infoRec.currencySpec, + source: infoRec.source, }); - await tx.currencyInfo.put(infoRec); } - await tx.globalCurrencyExchanges.add({ + await tx.addGlobalCurrencyExchange({ currency: req.currency, exchangeBaseUrl: req.exchangeBaseUrl, exchangeMasterPub: req.exchangeMasterPub, @@ -1720,15 +1716,20 @@ async function handleRemoveGlobalCurrencyAuditor( wex: WalletExecutionContext, req: RemoveGlobalCurrencyAuditorRequest, ): Promise<EmptyObject> { - await wex.runLegacyWalletDbTx(async (tx) => { - const key = [req.currency, req.auditorBaseUrl, req.auditorPub]; - const existingRec = - await tx.globalCurrencyAuditors.indexes.byCurrencyAndUrlAndPub.get(key); + await wex.runWalletDbTx(async (tx) => { + const existingRec = await tx.getGlobalCurrencyAuditor( + req.currency, + req.auditorBaseUrl, + req.auditorPub, + ); if (!existingRec) { return; } - checkDbInvariant(!!existingRec.id, `no global currency for ${j2s(key)}`); - await tx.globalCurrencyAuditors.delete(existingRec.id); + checkDbInvariant( + !!existingRec.id, + `no global currency for ${req.currency}`, + ); + await tx.deleteGlobalCurrencyAuditor(existingRec.id); wex.ws.exchangeCache.clear(); }); return {}; @@ -1738,22 +1739,25 @@ export async function handleRemoveGlobalCurrencyExchange( wex: WalletExecutionContext, req: RemoveGlobalCurrencyExchangeRequest, ): Promise<EmptyObject> { - await wex.runLegacyWalletDbTx(async (tx) => { - const key = [req.currency, req.exchangeBaseUrl, req.exchangeMasterPub]; - const existingRec = - await tx.globalCurrencyExchanges.indexes.byCurrencyAndUrlAndPub.get(key); + await wex.runWalletDbTx(async (tx) => { + const existingRec = await tx.getGlobalCurrencyExchange( + req.currency, + req.exchangeBaseUrl, + req.exchangeMasterPub, + ); if (!existingRec) { return; } wex.ws.exchangeCache.clear(); - checkDbInvariant(!!existingRec.id, `no global exchange for ${j2s(key)}`); - await tx.currencyInfo.delete( - stringifyScopeInfo({ - type: ScopeType.Global, - currency: req.currency, - }), + checkDbInvariant( + !!existingRec.id, + `no global exchange for ${req.currency}`, ); - await tx.globalCurrencyExchanges.delete(existingRec.id); + await tx.deleteCurrencyInfo({ + type: ScopeType.Global, + currency: req.currency, + }); + await tx.deleteGlobalCurrencyExchange(existingRec.id); }); return {}; } @@ -1762,14 +1766,16 @@ async function handleAddGlobalCurrencyAuditor( wex: WalletExecutionContext, req: AddGlobalCurrencyAuditorRequest, ): Promise<EmptyObject> { - await wex.runLegacyWalletDbTx(async (tx) => { - const key = [req.currency, req.auditorBaseUrl, req.auditorPub]; - const existingRec = - await tx.globalCurrencyAuditors.indexes.byCurrencyAndUrlAndPub.get(key); + await wex.runWalletDbTx(async (tx) => { + const existingRec = await tx.getGlobalCurrencyAuditor( + req.currency, + req.auditorBaseUrl, + req.auditorPub, + ); if (existingRec) { return; } - await tx.globalCurrencyAuditors.add({ + await tx.addGlobalCurrencyAuditor({ currency: req.currency, auditorBaseUrl: req.auditorBaseUrl, auditorPub: req.auditorPub, @@ -2121,8 +2127,8 @@ export async function handleTestingCorruptWithdrawalCoinSel( if (txId?.tag !== TransactionType.Withdrawal) { throw Error("expected withdrawal transaction ID"); } - await wex.runLegacyWalletDbTx(async (tx) => { - const wg = await tx.wtx.getWithdrawalGroup(txId.withdrawalGroupId); + await wex.runWalletDbTx(async (tx) => { + const wg = await tx.getWithdrawalGroup(txId.withdrawalGroupId); if (!wg) { return; } @@ -2130,7 +2136,7 @@ export async function handleTestingCorruptWithdrawalCoinSel( wg.denomsSel.selectedDenoms[0].denomPubHash = encodeCrock( getRandomBytes(64), ); - await tx.wtx.upsertWithdrawalGroup(wg); + await tx.upsertWithdrawalGroup(wg); } }); return {}; @@ -3564,8 +3570,8 @@ export class InternalWalletState { undefined, oc, ); - await wex.runLegacyWalletDbTx(async (tx) => { - await rematerializeTransactions(wex, tx.wtx); + await wex.runWalletDbTx(async (tx) => { + await rematerializeTransactions(wex, tx); }); } } catch (e) { diff --git a/packages/taler-wallet-core/src/withdraw.ts b/packages/taler-wallet-core/src/withdraw.ts @@ -191,11 +191,7 @@ import { parseTransactionIdentifier, } from "./transactions.js"; import { WALLET_EXCHANGE_PROTOCOL_VERSION } from "./versions.js"; -import { - LegacyWalletTxHandle, - WalletExecutionContext, - getDenomInfo, -} from "./wallet.js"; +import { WalletExecutionContext, getDenomInfo } from "./wallet.js"; import { WalletDbTransaction } from "./dbtx.js"; /** @@ -504,8 +500,8 @@ export class WithdrawTransactionContext implements TransactionContext { } async userDeleteTransaction(): Promise<void> { - await this.wex.runLegacyWalletDbTx(async (tx) => { - return this.deleteTransactionInTx(tx.wtx); + await this.wex.runWalletDbTx(async (tx) => { + return this.deleteTransactionInTx(tx); }); } @@ -523,8 +519,8 @@ 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.wtx); + await this.wex.runWalletDbTx(async (tx) => { + const [wg, h] = await this.getRecordHandle(tx); if (!wg) { logger.warn(`withdrawal group ${withdrawalGroupId} not found`); return; @@ -562,8 +558,8 @@ 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.wtx); + await this.wex.runWalletDbTx(async (tx) => { + const [wg, h] = await this.getRecordHandle(tx); if (!wg) { logger.warn(`withdrawal group ${withdrawalGroupId} not found`); return; @@ -619,8 +615,8 @@ 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.wtx); + await this.wex.runWalletDbTx(async (tx) => { + const [wg, h] = await this.getRecordHandle(tx); if (!wg) { logger.warn(`withdrawal group ${withdrawalGroupId} not found`); return; @@ -658,8 +654,8 @@ 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.wtx); + await this.wex.runWalletDbTx(async (tx) => { + const [wg, h] = await this.getRecordHandle(tx); if (!wg) { logger.warn(`withdrawal group ${withdrawalGroupId} not found`); return; @@ -957,8 +953,8 @@ async function processWithdrawalGroupRedenominate( exchangeBaseUrl, withdrawalGroup.withdrawalGroupId, ); - return await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + return await ctx.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); switch (rec?.status) { case WithdrawalGroupStatus.PendingRedenominate: break; @@ -1034,8 +1030,8 @@ async function processWithdrawalGroupBalanceKyc( }); if (ret.result === "ok") { - return await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [wg, h] = await ctx.getRecordHandle(tx.wtx); + return await ctx.wex.runWalletDbTx(async (tx) => { + const [wg, h] = await ctx.getRecordHandle(tx); if (!wg) { return TaskRunResult.finished(); } @@ -1055,8 +1051,8 @@ async function processWithdrawalGroupBalanceKyc( withdrawalGroup.status === WithdrawalGroupStatus.PendingBalanceKycInit && ret.walletKycStatus === ExchangeWalletKycStatus.Legi ) { - return await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [wg, h] = await ctx.getRecordHandle(tx.wtx); + return await ctx.wex.runWalletDbTx(async (tx) => { + const [wg, h] = await ctx.getRecordHandle(tx); if (!wg) { return TaskRunResult.finished(); } @@ -1085,8 +1081,8 @@ async function transitionSimple( from: WithdrawalGroupStatus, to: WithdrawalGroupStatus, ): Promise<void> { - await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); switch (rec?.status) { case from: { rec.status = to; @@ -1255,7 +1251,7 @@ async function getWithdrawableDenoms( exchangeBaseUrl: string, currency: string, ): Promise<WalletDenomination[]> { - return await wex.runLegacyWalletDbTx(async (tx) => { + return await wex.runWalletDbTx(async (tx) => { return getWithdrawableDenomsTx(wex, tx, exchangeBaseUrl, currency); }); } @@ -1269,14 +1265,14 @@ async function getWithdrawableDenoms( */ export async function getWithdrawableDenomsTx( _wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, exchangeBaseUrl: string, currency: string, maxAmount?: AmountLike, ): Promise<WalletDenomination[]> { const dbNow = timestampProtocolToDb(TalerProtocolTimestamp.now()); const allFamilies = - await tx.wtx.getDenominationFamiliesByExchange(exchangeBaseUrl); + await tx.getDenominationFamiliesByExchange(exchangeBaseUrl); if (logger.shouldLogTrace()) { const maxStr = maxAmount ? Amounts.stringify(maxAmount) : "<unknown>"; logger.trace( @@ -1303,7 +1299,7 @@ export async function getWithdrawableDenomsTx( const fpSerial = fam.denominationFamilySerial; checkDbInvariant(typeof fpSerial === "number", "denominationFamilySerial"); // Now we need to find a representative denom for the family. - const denom = await tx.wtx.findDenominationByFamilyFromExpiry( + const denom = await tx.findDenominationByFamilyFromExpiry( fpSerial, dbNow, isCandidateWithdrawableDenomRec, @@ -1347,8 +1343,8 @@ async function processPlanchetGenerate( "can't get funding uri from uninitialized wg", ); const exchangeBaseUrl = withdrawalGroup.exchangeBaseUrl; - let planchet = await wex.runLegacyWalletDbTx(async (tx) => { - return tx.wtx.getPlanchetByGroupAndIndex( + let planchet = await wex.runWalletDbTx(async (tx) => { + return tx.getPlanchetByGroupAndIndex( withdrawalGroup.withdrawalGroupId, coinIdx, ); @@ -1378,7 +1374,7 @@ async function processPlanchetGenerate( } const denomPubHash = maybeDenomPubHash; - const denom = await wex.runLegacyWalletDbTx(async (tx) => { + const denom = await wex.runWalletDbTx(async (tx) => { return getDenomInfo(wex, tx, exchangeBaseUrl, denomPubHash); }); if (!denom) { @@ -1409,8 +1405,8 @@ async function processPlanchetGenerate( ageCommitmentProof: r.ageCommitmentProof, lastError: undefined, }; - await wex.runLegacyWalletDbTx(async (tx) => { - const p = await tx.wtx.getPlanchetByGroupAndIndex( + await wex.runWalletDbTx(async (tx) => { + const p = await tx.getPlanchetByGroupAndIndex( withdrawalGroup.withdrawalGroupId, coinIdx, ); @@ -1418,7 +1414,7 @@ async function processPlanchetGenerate( planchet = p; return; } - await tx.wtx.upsertPlanchet(newPlanchet); + await tx.upsertPlanchet(newPlanchet); planchet = newPlanchet; }); return {}; @@ -1453,13 +1449,13 @@ async function transitionKycRequired( const withdrawalGroupId = withdrawalGroup.withdrawalGroupId; const ctx = new WithdrawTransactionContext(wex, withdrawalGroupId); - await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [wg2, h] = await ctx.getRecordHandle(tx.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [wg2, h] = await ctx.getRecordHandle(tx); if (!wg2) { return; } for (let i = startIdx; i < requestCoinIdxs.length; i++) { - const planchet = await tx.wtx.getPlanchetByGroupAndIndex( + const planchet = await tx.getPlanchetByGroupAndIndex( withdrawalGroup.withdrawalGroupId, requestCoinIdxs[i], ); @@ -1467,7 +1463,7 @@ async function transitionKycRequired( continue; } planchet.planchetStatus = PlanchetStatus.KycRequired; - await tx.wtx.upsertPlanchet(planchet); + await tx.upsertPlanchet(planchet); } switch (wg2.status) { case WithdrawalGroupStatus.PendingReady: @@ -1507,14 +1503,14 @@ async function processPlanchetExchangeLegacyBatchRequest( // Indices of coins that are included in the batch request const requestCoinIdxs: number[] = []; - await wex.runLegacyWalletDbTx(async (tx) => { + await wex.runWalletDbTx(async (tx) => { for ( let coinIdx = args.coinStartIndex; coinIdx < args.coinStartIndex + args.batchSize && coinIdx < wgContext.numPlanchets; coinIdx++ ) { - const planchet = await tx.wtx.getPlanchetByGroupAndIndex( + const planchet = await tx.getPlanchetByGroupAndIndex( withdrawalGroup.withdrawalGroupId, coinIdx, ); @@ -1563,8 +1559,8 @@ async function processPlanchetExchangeLegacyBatchRequest( coinIdx: number, ): Promise<void> { logger.trace(`withdrawal request failed: ${j2s(errDetail)}`); - await wex.runLegacyWalletDbTx(async (tx) => { - const planchet = await tx.wtx.getPlanchetByGroupAndIndex( + await wex.runWalletDbTx(async (tx) => { + const planchet = await tx.getPlanchetByGroupAndIndex( withdrawalGroup.withdrawalGroupId, coinIdx, ); @@ -1572,7 +1568,7 @@ async function processPlanchetExchangeLegacyBatchRequest( return; } planchet.lastError = errDetail; - await tx.wtx.upsertPlanchet(planchet); + await tx.upsertPlanchet(planchet); }); } @@ -1664,14 +1660,14 @@ async function processPlanchetExchangeBatchRequest( ); let accAmount = Amounts.zeroOfAmount(withdrawalGroup.instructedAmount); let accFee = Amounts.zeroOfAmount(withdrawalGroup.instructedAmount); - await wex.runLegacyWalletDbTx(async (tx) => { + await wex.runWalletDbTx(async (tx) => { for ( let coinIdx = args.coinStartIndex; coinIdx < args.coinStartIndex + args.batchSize && coinIdx < wgContext.numPlanchets; coinIdx++ ) { - const planchet = await tx.wtx.getPlanchetByGroupAndIndex( + const planchet = await tx.getPlanchetByGroupAndIndex( withdrawalGroup.withdrawalGroupId, coinIdx, ); @@ -1717,8 +1713,8 @@ async function processPlanchetExchangeBatchRequest( coinIdx: number, ): Promise<void> { logger.trace(`withdrawal request failed: ${j2s(errDetail)}`); - await wex.runLegacyWalletDbTx(async (tx) => { - const planchet = await tx.wtx.getPlanchetByGroupAndIndex( + await wex.runWalletDbTx(async (tx) => { + const planchet = await tx.getPlanchetByGroupAndIndex( withdrawalGroup.withdrawalGroupId, coinIdx, ); @@ -1726,7 +1722,7 @@ async function processPlanchetExchangeBatchRequest( return; } planchet.lastError = errDetail; - await tx.wtx.upsertPlanchet(planchet); + await tx.upsertPlanchet(planchet); }); } @@ -1821,8 +1817,8 @@ async function processPlanchetVerifyAndStoreCoin( const exchangeBaseUrl = withdrawalGroup.exchangeBaseUrl; logger.trace(`checking and storing planchet idx=${coinIdx}`); - const d = await wex.runLegacyWalletDbTx(async (tx) => { - const planchet = await tx.wtx.getPlanchetByGroupAndIndex( + const d = await wex.runWalletDbTx(async (tx) => { + const planchet = await tx.getPlanchetByGroupAndIndex( withdrawalGroup.withdrawalGroupId, coinIdx, ); @@ -1883,8 +1879,8 @@ async function processPlanchetVerifyAndStoreCoin( }); if (!rsaVerifyResp.valid) { - await wex.runLegacyWalletDbTx(async (tx) => { - const planchet = await tx.wtx.getPlanchetByGroupAndIndex( + await wex.runWalletDbTx(async (tx) => { + const planchet = await tx.getPlanchetByGroupAndIndex( withdrawalGroup.withdrawalGroupId, coinIdx, ); @@ -1896,7 +1892,7 @@ async function processPlanchetVerifyAndStoreCoin( {}, "invalid signature from the exchange after unblinding", ); - await tx.wtx.upsertPlanchet(planchet); + await tx.upsertPlanchet(planchet); }); return; } @@ -1935,15 +1931,15 @@ async function processPlanchetVerifyAndStoreCoin( wgContext.planchetsFinished.add(planchet.coinPub); - await wex.runLegacyWalletDbTx(async (tx) => { - const p = await tx.wtx.getPlanchet(planchetCoinPub); + await wex.runWalletDbTx(async (tx) => { + const p = await tx.getPlanchet(planchetCoinPub); if (!p || p.planchetStatus === PlanchetStatus.WithdrawalDone) { return; } p.planchetStatus = PlanchetStatus.WithdrawalDone; p.lastError = undefined; - await tx.wtx.upsertPlanchet(p); - await makeCoinAvailable(wex, tx.wtx, coin); + await tx.upsertPlanchet(p); + await makeCoinAvailable(wex, tx, coin); }); } @@ -1955,8 +1951,8 @@ export async function updateWithdrawalDenomsForCurrency( wex: WalletExecutionContext, currency: string, ): Promise<void> { - const res = await wex.runLegacyWalletDbTx(async (tx) => { - return await tx.wtx.getExchanges(); + const res = await wex.runWalletDbTx(async (tx) => { + return await tx.getExchanges(); }); for (const exch of res) { if (exch.detailsPointer?.currency === currency) { @@ -1979,9 +1975,9 @@ export async function updateWithdrawalDenomsForExchange( const dbNow = timestampProtocolToDb(TalerProtocolTimestamp.now()); - const denoms = await wex.runLegacyWalletDbTx(async (tx) => { + const denoms = await wex.runWalletDbTx(async (tx) => { const allFamilies = - await tx.wtx.getDenominationFamiliesByExchange(exchangeBaseUrl); + await tx.getDenominationFamiliesByExchange(exchangeBaseUrl); const denominations: WalletDenomination[] | undefined = []; for (const fam of allFamilies) { const fpSerial = fam.denominationFamilySerial; @@ -1991,7 +1987,7 @@ export async function updateWithdrawalDenomsForExchange( ); // Take the first withdrawable denomination of the family, and queue it // for validation only if it has not been verified yet. - const dv = await tx.wtx.findDenominationByFamilyFromExpiry( + const dv = await tx.findDenominationByFamilyFromExpiry( fpSerial, dbNow, isCandidateWithdrawableDenomRec, @@ -2020,7 +2016,7 @@ async function getWithdrawalCandidateDenoms( amount: AmountString, ): Promise<WalletDenomination[]> { await updateWithdrawalDenomsForExchange(wex, exchangeBaseUrl); - return await wex.runLegacyWalletDbTx(async (tx) => { + return await wex.runWalletDbTx(async (tx) => { return await getWithdrawableDenomsTx( wex, tx, @@ -2137,8 +2133,8 @@ async function processQueryReserve( ); } - return await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [wg, h] = await ctx.getRecordHandle(tx.wtx); + return await ctx.wex.runWalletDbTx(async (tx) => { + const [wg, h] = await ctx.getRecordHandle(tx); if (!wg) { logger.warn(`withdrawal group ${withdrawalGroupId} not found`); return TaskRunResult.finished(); @@ -2156,7 +2152,7 @@ async function processQueryReserve( await storeKnownBankAccount(tx, currency, lastOrigin); } if (redoSelection) { - await tx.wtx.deletePlanchetsByGroup(wg.withdrawalGroupId); + await tx.deletePlanchetsByGroup(wg.withdrawalGroupId); const candidates = await getWithdrawableDenomsTx( wex, tx, @@ -2211,8 +2207,8 @@ async function processWithdrawalGroupAbortingBank( }); logger.info(`abort response status: ${abortResp.status}`); - await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [wg, h] = await ctx.getRecordHandle(tx.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [wg, h] = await ctx.getRecordHandle(tx); if (!wg) { return; } @@ -2281,8 +2277,8 @@ async function processWithdrawalGroupPendingKyc( checkProtocolInvariant(algoRes.requiresAuth != true); - await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -2311,8 +2307,8 @@ async function redenominateWithdrawal( await updateWithdrawalDenomsForExchange(wex, exchangeBaseUrl); logger.trace(`redenominating withdrawal group ${withdrawalGroupId}`); - await wex.runLegacyWalletDbTx(async (tx) => { - const wg = await tx.wtx.getWithdrawalGroup(withdrawalGroupId); + await wex.runWalletDbTx(async (tx) => { + const wg = await tx.getWithdrawalGroup(withdrawalGroupId); if (!wg) { return; } @@ -2356,10 +2352,7 @@ async function redenominateWithdrawal( let coinIndex = 0; for (let i = 0; i < oldSel.selectedDenoms.length; i++) { const sel = wg.denomsSel.selectedDenoms[i]; - const denom = await tx.wtx.getDenomination( - exchangeBaseUrl, - sel.denomPubHash, - ); + const denom = await tx.getDenomination(exchangeBaseUrl, sel.denomPubHash); let denomOkay: boolean = false; @@ -2402,10 +2395,7 @@ async function redenominateWithdrawal( for (let j = 0; j < sel.count; j++) { const ci = coinIndex + j; - const p = await tx.wtx.getPlanchetByGroupAndIndex( - withdrawalGroupId, - ci, - ); + const p = await tx.getPlanchetByGroupAndIndex(withdrawalGroupId, ci); if (!p) { // Maybe planchet wasn't yet generated. // No problem! @@ -2419,7 +2409,7 @@ async function redenominateWithdrawal( // re-denomination later. logger.info(`aborting planchet #${coinIndex}`); p.planchetStatus = PlanchetStatus.AbortedReplaced; - await tx.wtx.upsertPlanchet(p); + await tx.upsertPlanchet(p); } } @@ -2450,7 +2440,7 @@ async function redenominateWithdrawal( if (logger.shouldLogTrace()) { logger.trace(`merged denom sel: ${j2s(mergedSel)}`); } - await tx.wtx.upsertWithdrawalGroup(wg); + await tx.upsertWithdrawalGroup(wg); }); } @@ -2481,8 +2471,8 @@ 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.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -2516,8 +2506,8 @@ async function processWithdrawalGroupPendingReady( amount: kycCheckRes.nextThreshold, exchangeBaseUrl, }); - await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [wg, h] = await ctx.getRecordHandle(tx.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [wg, h] = await ctx.getRecordHandle(tx); if (!wg) { return; } @@ -2537,8 +2527,8 @@ async function processWithdrawalGroupPendingReady( wgRecord: withdrawalGroup, }; - await wex.runLegacyWalletDbTx(async (tx) => { - const planchets = await tx.wtx.getPlanchetsByGroup(withdrawalGroupId); + await wex.runWalletDbTx(async (tx) => { + const planchets = await tx.getPlanchetsByGroup(withdrawalGroupId); for (const p of planchets) { if (p.planchetStatus === PlanchetStatus.WithdrawalDone) { wgContext.planchetsFinished.add(p.coinPub); @@ -2612,8 +2602,8 @@ async function processWithdrawalGroupPendingReady( let redenomRequired = false; - await wex.runLegacyWalletDbTx(async (tx) => { - const planchets = await tx.wtx.getPlanchetsByGroup(withdrawalGroupId); + await wex.runWalletDbTx(async (tx) => { + const planchets = await tx.getPlanchetsByGroup(withdrawalGroupId); for (const p of planchets) { if (p.planchetStatus !== PlanchetStatus.Pending) { continue; @@ -2646,13 +2636,13 @@ async function processWithdrawalGroupPendingReady( let numActive = 0; const maxReportedErrors = 5; - const res = await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [wg, h] = await ctx.getRecordHandle(tx.wtx); + const res = await ctx.wex.runWalletDbTx(async (tx) => { + const [wg, h] = await ctx.getRecordHandle(tx); if (!wg) { return; } - const groupPlanchets = await tx.wtx.getPlanchetsByGroup(withdrawalGroupId); + const groupPlanchets = await tx.getPlanchetsByGroup(withdrawalGroupId); for (const x of groupPlanchets) { switch (x.planchetStatus) { case PlanchetStatus.KycRequired: @@ -2677,7 +2667,7 @@ async function processWithdrawalGroupPendingReady( ) { wg.timestampFinish = timestampPreciseToDb(TalerPreciseTimestamp.now()); wg.status = WithdrawalGroupStatus.Done; - await makeCoinsVisible(wex, tx.wtx, ctx.transactionId); + await makeCoinsVisible(wex, tx, ctx.transactionId); } await h.update(wg); return wg; @@ -2712,8 +2702,8 @@ async function startRedenomination( await startUpdateExchangeEntry(ctx.wex, exchangeBaseUrl, { forceUnavailable: true, }); - return await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + return await ctx.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); switch (rec?.status) { case WithdrawalGroupStatus.PendingReady: break; @@ -2735,8 +2725,8 @@ export async function processWithdrawalGroup( } logger.trace("processing withdrawal group", withdrawalGroupId); - const withdrawalGroup = await wex.runLegacyWalletDbTx((tx) => - tx.wtx.getWithdrawalGroup(withdrawalGroupId), + const withdrawalGroup = await wex.runWalletDbTx((tx) => + tx.getWithdrawalGroup(withdrawalGroupId), ); if (!withdrawalGroup) { @@ -3012,8 +3002,8 @@ async function getWithdrawalGroupRecordTx( withdrawalGroupId: string; }, ): Promise<WalletWithdrawalGroup | undefined> { - return await wex.runLegacyWalletDbTx((tx) => - tx.wtx.getWithdrawalGroup(req.withdrawalGroupId), + return await wex.runWalletDbTx((tx) => + tx.getWithdrawalGroup(req.withdrawalGroupId), ); } @@ -3054,8 +3044,8 @@ async function registerReserveWithBank( withdrawalGroupId: string, isFlexibleAmount: boolean, ): Promise<TaskRunResult> { - const withdrawalGroup = await wex.runLegacyWalletDbTx((tx) => - tx.wtx.getWithdrawalGroup(withdrawalGroupId), + const withdrawalGroup = await wex.runWalletDbTx((tx) => + tx.getWithdrawalGroup(withdrawalGroupId), ); const ctx = new WithdrawTransactionContext(wex, withdrawalGroupId); switch (withdrawalGroup?.status) { @@ -3131,8 +3121,8 @@ async function registerReserveWithBank( codecForBankWithdrawalOperationPostResponse(), ); - return await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [r, h] = await ctx.getRecordHandle(tx.wtx); + return await ctx.wex.runWalletDbTx(async (tx) => { + const [r, h] = await ctx.getRecordHandle(tx); if (!r) { return TaskRunResult.finished(); } @@ -3172,8 +3162,8 @@ async function transitionBankAborted( ctx: WithdrawTransactionContext, ): Promise<TaskRunResult> { logger.info("bank aborted the withdrawal"); - return await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [r, h] = await ctx.getRecordHandle(tx.wtx); + return await ctx.wex.runWalletDbTx(async (tx) => { + const [r, h] = await ctx.getRecordHandle(tx); if (!r) { return TaskRunResult.finished(); } @@ -3360,8 +3350,8 @@ async function processReserveBankStatus( ); } - return await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [r, h] = await ctx.getRecordHandle(tx.wtx); + return await ctx.wex.runWalletDbTx(async (tx) => { + const [r, h] = await ctx.getRecordHandle(tx); if (!r) { return TaskRunResult.finished(); } @@ -3450,8 +3440,8 @@ export async function internalPrepareCreateWithdrawalGroup( if (args.forcedWithdrawalGroupId) { withdrawalGroupId = args.forcedWithdrawalGroupId; const wgId = withdrawalGroupId; - const existingWg = await wex.runLegacyWalletDbTx((tx) => - tx.wtx.getWithdrawalGroup(wgId), + const existingWg = await wex.runWalletDbTx((tx) => + tx.getWithdrawalGroup(wgId), ); if (existingWg) { @@ -3525,7 +3515,7 @@ export interface PerformCreateWithdrawalGroupResult { export async function internalPerformCreateWithdrawalGroup( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, prep: PrepareCreateWithdrawalGroupResult, ): Promise<PerformCreateWithdrawalGroupResult> { const { withdrawalGroup } = prep; @@ -3533,14 +3523,14 @@ export async function internalPerformCreateWithdrawalGroup( wex, withdrawalGroup.withdrawalGroupId, ); - const [existingWg, h] = await ctx.getRecordHandle(tx.wtx); + const [existingWg, h] = await ctx.getRecordHandle(tx); if (existingWg) { return { withdrawalGroup: existingWg, }; } - await tx.wtx.upsertWithdrawalGroup(withdrawalGroup); - await tx.wtx.upsertReserve({ + await tx.upsertWithdrawalGroup(withdrawalGroup); + await tx.upsertReserve({ reservePub: withdrawalGroup.reservePub, reservePriv: withdrawalGroup.reservePriv, }); @@ -3564,13 +3554,13 @@ export async function internalPerformCreateWithdrawalGroup( */ async function internalPerformExchangeWasUsed( wex: WalletExecutionContext, - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, canonExchange: string, ): Promise<void> { - const exchange = await tx.wtx.getExchange(canonExchange); + const exchange = await tx.getExchange(canonExchange); if (exchange) { exchange.lastWithdrawal = timestampPreciseToDb(TalerPreciseTimestamp.now()); - await tx.wtx.upsertExchange(exchange); + await tx.upsertExchange(exchange); } await markExchangeUsed(tx, canonExchange); @@ -3603,9 +3593,9 @@ export async function internalCreateWithdrawalGroup( wex, prep.withdrawalGroup.withdrawalGroupId, ); - const res = await wex.runLegacyWalletDbTx(async (tx) => { + const res = await wex.runWalletDbTx(async (tx) => { const res = await internalPerformCreateWithdrawalGroup(wex, tx, prep); - await ctx.updateTransactionMeta(tx.wtx); + await ctx.updateTransactionMeta(tx); return res; }); return res.withdrawalGroup; @@ -3618,8 +3608,8 @@ export async function prepareBankIntegratedWithdrawal( isForeignAccount?: boolean; }, ): Promise<PrepareBankIntegratedWithdrawalResponse> { - const existingWithdrawalGroup = await wex.runLegacyWalletDbTx((tx) => - tx.wtx.getWithdrawalGroupByTalerWithdrawUri(req.talerWithdrawUri), + const existingWithdrawalGroup = await wex.runWalletDbTx((tx) => + tx.getWithdrawalGroupByTalerWithdrawUri(req.talerWithdrawUri), ); const parsedUri = Result.orUndefined( @@ -3709,12 +3699,11 @@ export async function prepareBankIntegratedWithdrawal( * if the account already exists. */ async function storeKnownBankAccount( - tx: LegacyWalletTxHandle, + tx: WalletDbTransaction, instructedCurrency: string, senderWire: string, ): Promise<string | undefined> { - const existingAccount = - await tx.bankAccountsV2.indexes.byPaytoUri.get(senderWire); + const existingAccount = await tx.getBankAccountByPaytoUri(senderWire); if (existingAccount) { // Add currency for existing known bank account if necessary if (existingAccount.currencies?.includes(instructedCurrency)) { @@ -3723,13 +3712,13 @@ async function storeKnownBankAccount( ...(existingAccount.currencies ?? []), ]; existingAccount.currencies.sort(); - await tx.bankAccountsV2.put(existingAccount); + await tx.upsertBankAccount(existingAccount); } return undefined; } const myId = `acct:${encodeCrock(getRandomBytes(32))}`; - await tx.bankAccountsV2.put({ + await tx.upsertBankAccount({ currencies: [instructedCurrency], kycCompleted: false, paytoUri: senderWire, @@ -3751,8 +3740,8 @@ export async function confirmWithdrawal( if (parsedTx?.tag !== TransactionType.Withdrawal) { throw Error("invalid withdrawal transaction ID"); } - const withdrawalGroup = await wex.runLegacyWalletDbTx((tx) => - tx.wtx.getWithdrawalGroup(parsedTx.withdrawalGroupId), + const withdrawalGroup = await wex.runWalletDbTx((tx) => + tx.getWithdrawalGroup(parsedTx.withdrawalGroupId), ); if (!withdrawalGroup) { @@ -3766,8 +3755,8 @@ export async function confirmWithdrawal( throw Error("not a bank integrated withdrawal"); } - await wex.runLegacyWalletDbTx(async (tx) => { - const rec = await tx.wtx.getExchangeBaseUrlFixup(selectedExchange); + await wex.runWalletDbTx(async (tx) => { + const rec = await tx.getExchangeBaseUrlFixup(selectedExchange); if (rec) { selectedExchange = rec.replacement; } @@ -3882,7 +3871,7 @@ export async function confirmWithdrawal( logger.info(`adding account ${senderWire} to know bank accounts`); - const bankAccountId = await wex.runLegacyWalletDbTx( + const bankAccountId = await wex.runWalletDbTx( async (tx) => await storeKnownBankAccount(tx, instructedCurrency, senderWire), ); @@ -3927,8 +3916,8 @@ export async function confirmWithdrawal( } } - await ctx.wex.runLegacyWalletDbTx(async (tx) => { - const [rec, h] = await ctx.getRecordHandle(tx.wtx); + await ctx.wex.runWalletDbTx(async (tx) => { + const [rec, h] = await ctx.getRecordHandle(tx); if (!rec) { return; } @@ -4076,9 +4065,9 @@ export async function acceptBankIntegratedWithdrawal( contents: "confirmed acceptBankIntegratedWithdrawal", }); - const newWithdrawralGroup = await wex.runLegacyWalletDbTx( + const newWithdrawralGroup = await wex.runWalletDbTx( async (tx) => - await tx.wtx.getWithdrawalGroupByTalerWithdrawUri(req.talerWithdrawUri), + await tx.getWithdrawalGroupByTalerWithdrawUri(req.talerWithdrawUri), ); checkDbInvariant( @@ -4327,8 +4316,8 @@ export async function waitWithdrawalFinal( }, async checkState() { // Check if withdrawal is final - const wg = await ctx.wex.runLegacyWalletDbTx( - async (tx) => await tx.wtx.getWithdrawalGroup(ctx.withdrawalGroupId), + const wg = await ctx.wex.runWalletDbTx( + async (tx) => await tx.getWithdrawalGroup(ctx.withdrawalGroupId), ); if (!wg) { // Must've been deleted, we consider that final.