taler-typescript-core

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

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

db: move the coin cluster behind the DAL

Diffstat:
Mpackages/taler-wallet-core/src/coinSelection.ts | 7+++++--
Mpackages/taler-wallet-core/src/common.ts | 14+++++++-------
Mpackages/taler-wallet-core/src/db-common.ts | 9++++-----
Mpackages/taler-wallet-core/src/dbtx-indexeddb.ts | 12+++---------
Mpackages/taler-wallet-core/src/dbtx.ts | 9+++++----
Mpackages/taler-wallet-core/src/deposits.ts | 19++++++++++++-------
Mpackages/taler-wallet-core/src/dev-experiments.ts | 3+--
Mpackages/taler-wallet-core/src/exchanges.ts | 93+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Mpackages/taler-wallet-core/src/instructedAmountConversion.ts | 10+++++-----
Mpackages/taler-wallet-core/src/pay-merchant.ts | 47+++++++++++++++++++++++++++--------------------
Mpackages/taler-wallet-core/src/pay-peer-common.ts | 6++----
Mpackages/taler-wallet-core/src/recoup.ts | 24+++++++++++-------------
Mpackages/taler-wallet-core/src/refresh.ts | 58+++++++++++++++++++++++++++-------------------------------
Mpackages/taler-wallet-core/src/wallet.ts | 14++++++++------
Mpackages/taler-wallet-core/src/withdraw.ts | 34++++++++++++----------------------
15 files changed, 187 insertions(+), 172 deletions(-)

diff --git a/packages/taler-wallet-core/src/coinSelection.ts b/packages/taler-wallet-core/src/coinSelection.ts @@ -366,7 +366,7 @@ async function maybeRepairCoinSelection( ): Promise<void> { // Look at existing pay coin selection and tally up for (const prev of prevPayCoins) { - const coin = await tx.coins.get(prev.coinPub); + const coin = await tx.wtx.getCoin(prev.coinPub); if (!coin) { continue; } @@ -1048,7 +1048,10 @@ async function selectPayCandidates( // FIXME: Should we exclude denominations that are // not spendable anymore? for (const coinAvail of myExchangeCoins) { - const denom = await tx.wtx.getDenomination(coinAvail.exchangeBaseUrl, coinAvail.denomPubHash); + const denom = await tx.wtx.getDenomination( + coinAvail.exchangeBaseUrl, + coinAvail.denomPubHash, + ); checkDbInvariant( !!denom, `denomination of a coin is missing hash: ${coinAvail.denomPubHash}`, diff --git a/packages/taler-wallet-core/src/common.ts b/packages/taler-wallet-core/src/common.ts @@ -193,7 +193,7 @@ export async function spendCoins( } let refreshCoinPubs: CoinRefreshRequest[] = []; for (let i = 0; i < csi.coinPubs.length; i++) { - const coin = await tx.coins.get(csi.coinPubs[i]); + const coin = await tx.wtx.getCoin(csi.coinPubs[i]); if (!coin) { throw Error("coin allocated for payment doesn't exist anymore"); } @@ -207,11 +207,11 @@ export async function spendCoins( !!denom, `denomination of a coin is missing hash: ${coin.denomPubHash}`, ); - const coinAvailability = await tx.coinAvailability.get([ + const coinAvailability = await tx.wtx.getCoinAvailability( coin.exchangeBaseUrl, coin.denomPubHash, coin.maxAge, - ]); + ); checkDbInvariant( !!coinAvailability, `age denom info is missing for ${coin.maxAge}`, @@ -239,7 +239,7 @@ export async function spendCoins( coinAvailability.visibleCoinCount--; } } - let histEntry: WalletCoinHistory | undefined = await tx.coinHistory.get( + let histEntry: WalletCoinHistory | undefined = await tx.wtx.getCoinHistory( coin.coinPub, ); if (!histEntry) { @@ -253,9 +253,9 @@ export async function spendCoins( transactionId: csi.transactionId, amount: Amounts.stringify(contrib), }); - await tx.coinHistory.put(histEntry); - await tx.coins.put(coin); - await tx.coinAvailability.put(coinAvailability); + await tx.wtx.upsertCoinHistory(histEntry); + await tx.wtx.upsertCoin(coin); + await tx.wtx.upsertCoinAvailability(coinAvailability); } await createRefreshGroup( diff --git a/packages/taler-wallet-core/src/db-common.ts b/packages/taler-wallet-core/src/db-common.ts @@ -2520,7 +2520,6 @@ export interface TokenFamilyInfo { * read-modify-write round trip through it is lossless. */ export interface WalletToken extends TokenFamilyInfo { - /** * Source purchase of the token. */ @@ -2613,7 +2612,8 @@ export interface WalletToken extends TokenFamilyInfo { /** * Blinding secret for token. */ - blindingKey: string;} + blindingKey: string; +} /** * A slate as stored in the "slates" object store. @@ -2623,7 +2623,6 @@ export interface WalletToken extends TokenFamilyInfo { * WalletToken so that each store has its own record type. */ export interface WalletSlate extends TokenFamilyInfo { - /** * Source purchase of the token. */ @@ -2683,7 +2682,6 @@ export interface WalletSlate extends TokenFamilyInfo { */ validBefore: DbProtocolTimestamp; - /** * Token use public key used to confirm usage of tokens. */ @@ -2712,7 +2710,8 @@ export interface WalletSlate extends TokenFamilyInfo { /** * Blinding secret for token. */ - blindingKey: string;} + blindingKey: string; +} export namespace WalletToken { export function hashInfo(r: WalletToken | WalletSlate): string { diff --git a/packages/taler-wallet-core/src/dbtx-indexeddb.ts b/packages/taler-wallet-core/src/dbtx-indexeddb.ts @@ -82,18 +82,14 @@ import { WalletGlobalCurrencyAuditor, WalletExchangeDetails, } from "./db-common.js"; -import type { -} from "./db-indexeddb.js"; -import { - WalletIndexedDbTransaction, -} from "./db-indexeddb.js"; +import type {} from "./db-indexeddb.js"; +import { WalletIndexedDbTransaction } from "./db-indexeddb.js"; import type { GetCurrencyInfoDbResult, StoreCurrencyInfoDbRequest, WalletDbTransaction, } from "./dbtx.js"; - function getActiveKeyRange() { return GlobalIDB.KeyRange.bound( OPERATION_STATUS_NONFINAL_FIRST, @@ -657,9 +653,7 @@ export class IdbWalletTransaction implements WalletDbTransaction { await tx.denomLossEvents.delete(denomLossEventId); } - async getExchange( - baseUrl: string, - ): Promise<WalletExchangeEntry | undefined> { + async getExchange(baseUrl: string): Promise<WalletExchangeEntry | undefined> { const tx = this.tx; return await tx.exchanges.get(baseUrl); } diff --git a/packages/taler-wallet-core/src/dbtx.ts b/packages/taler-wallet-core/src/dbtx.ts @@ -566,15 +566,16 @@ export interface WalletDbTransaction { upsertRefreshSession(rec: WalletRefreshSession): Promise<void>; - deleteRefreshSession(refreshGroupId: string, coinIndex: number): Promise<void>; + deleteRefreshSession( + refreshGroupId: string, + coinIndex: number, + ): Promise<void>; getRefreshSessionsByGroup( refreshGroupId: string, ): Promise<WalletRefreshSession[]>; - getRecoupGroup( - recoupGroupId: string, - ): Promise<WalletRecoupGroup | undefined>; + getRecoupGroup(recoupGroupId: string): Promise<WalletRecoupGroup | undefined>; upsertRecoupGroup(rec: WalletRecoupGroup): Promise<void>; diff --git a/packages/taler-wallet-core/src/deposits.ts b/packages/taler-wallet-core/src/deposits.ts @@ -122,8 +122,7 @@ import { WalletWithdrawalGroup, WithdrawalRecordType, } from "./db-common.js"; -import { -} from "./db-indexeddb.js"; +import {} from "./db-indexeddb.js"; import { ReadyExchangeSummary, fetchFreshExchange, @@ -850,7 +849,7 @@ async function refundDepositGroup( default: { const coinPub = payCoinSelection.coinPubs[i]; const coinExchange = await wex.runLegacyWalletDbTx(async (tx) => { - const coinRecord = await tx.coins.get(coinPub); + const coinRecord = await tx.wtx.getCoin(coinPub); checkDbInvariant(!!coinRecord, `coin ${coinPub} not found in DB`); return coinRecord.exchangeBaseUrl; }); @@ -899,7 +898,9 @@ 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); + const newDg = await tx.wtx.getDepositGroup( + depositGroup.depositGroupId, + ); if (!newDg || !newDg.statusPerCoin) { return; } @@ -1459,7 +1460,7 @@ async function processDepositGroupTrack( 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.coins.get(coinPub); + const coinRecord = await tx.wtx.getCoin(coinPub); checkDbInvariant(!!coinRecord, `coin ${coinPub} not found in DB`); return coinRecord.exchangeBaseUrl; }); @@ -1498,7 +1499,9 @@ async function processDepositGroupTrack( } else if (track.type === "wired") { updatedTxStatus = DepositElementStatus.Wired; - const payto = Result.orUndefined(Paytos.fromString(depositGroup.wire.payto_uri)); + const payto = Result.orUndefined( + Paytos.fromString(depositGroup.wire.payto_uri), + ); if (!payto) { throw Error(`unparsable payto: ${depositGroup.wire.payto_uri}`); } @@ -2110,7 +2113,9 @@ export async function createDepositGroup( wex: WalletExecutionContext, req: CreateDepositGroupRequest, ): Promise<CreateDepositGroupResponse> { - const depositPayto = Result.orUndefined(Paytos.fromString(req.depositPaytoUri)); + const depositPayto = Result.orUndefined( + Paytos.fromString(req.depositPaytoUri), + ); if (!depositPayto) { throw Error("invalid payto URI"); } diff --git a/packages/taler-wallet-core/src/dev-experiments.ts b/packages/taler-wallet-core/src/dev-experiments.ts @@ -67,8 +67,7 @@ import { WithdrawalRecordType, WalletDenomLossEvent, } from "./db-common.js"; -import { -} from "./db-indexeddb.js"; +import {} from "./db-indexeddb.js"; import { DenomLossTransactionContext, fetchFreshExchange, diff --git a/packages/taler-wallet-core/src/exchanges.ts b/packages/taler-wallet-core/src/exchanges.ts @@ -156,9 +156,7 @@ import { WalletDenomFamilyParams, WalletDenominationFamily, } from "./db-common.js"; -import { - ExchangeMigrationReason, -} from "./db-indexeddb.js"; +import { ExchangeMigrationReason } from "./db-indexeddb.js"; import { createTimeline, isCandidateWithdrawableDenomRec, @@ -246,7 +244,11 @@ async function getExchangeRecordsInternal( return; } const { currency, masterPublicKey } = dp; - const details = await tx.wtx.getExchangeDetailsByPointer(r.baseUrl, currency, masterPublicKey); + const details = await tx.wtx.getExchangeDetailsByPointer( + r.baseUrl, + currency, + masterPublicKey, + ); if (!details) { logger.warn( `no exchange details with pointer ${j2s(dp)} for ${exchangeBaseUrl}`, @@ -325,8 +327,11 @@ async function internalGetExchangeScopeInfo( tx: LegacyWalletTxHandle, exchangeDetails: WalletExchangeDetails, ): Promise<ScopeInfo> { - const globalExchangeRec = - await tx.wtx.getGlobalCurrencyExchange(exchangeDetails.currency, exchangeDetails.exchangeBaseUrl, exchangeDetails.masterPublicKey); + const globalExchangeRec = await tx.wtx.getGlobalCurrencyExchange( + exchangeDetails.currency, + exchangeDetails.exchangeBaseUrl, + exchangeDetails.masterPublicKey, + ); if (globalExchangeRec) { return { currency: exchangeDetails.currency, @@ -334,8 +339,11 @@ async function internalGetExchangeScopeInfo( }; } else { for (const aud of exchangeDetails.auditors) { - const globalAuditorRec = - await tx.wtx.getGlobalCurrencyAuditor(exchangeDetails.currency, aud.auditor_url, aud.auditor_pub); + const globalAuditorRec = await tx.wtx.getGlobalCurrencyAuditor( + exchangeDetails.currency, + aud.auditor_url, + aud.auditor_pub, + ); if (globalAuditorRec) { return { currency: exchangeDetails.currency, @@ -509,7 +517,9 @@ export async function lookupExchangeByUri( ); let reserveRec: WalletReserve | undefined = undefined; if (exchangeRec.currentMergeReserveRowId != null) { - reserveRec = await tx.wtx.getReserve(exchangeRec.currentMergeReserveRowId); + reserveRec = await tx.wtx.getReserve( + exchangeRec.currentMergeReserveRowId, + ); checkDbInvariant(!!reserveRec, "reserve record not found"); } return await makeExchangeListItem( @@ -959,8 +969,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.wtx.getDenominationsByExchange(exchangeBaseUrl); logger.trace(`exchange entry has ${denoms.length} denominations`); for (const denom of denoms) { const denomOkay = isCandidateWithdrawableDenomRec(denom); @@ -2057,8 +2066,7 @@ export async function updateExchangeFromUrlHandler( fpRec = { familyParams: fp, }; - denominationFamilySerial = - await tx.wtx.upsertDenominationFamily(fpRec); + denominationFamilySerial = await tx.wtx.upsertDenominationFamily(fpRec); } else { denominationFamilySerial = fpRec.denominationFamilySerial; } @@ -2209,7 +2217,10 @@ async function doExchangeAutoRefresh( if (coin.status !== CoinStatus.Fresh) { continue; } - const denom = await tx.wtx.getDenomination(exchangeBaseUrl, coin.denomPubHash); + const denom = await tx.wtx.getDenomination( + exchangeBaseUrl, + coin.denomPubHash, + ); if (!denom) { logger.warn("denomination not in database"); continue; @@ -2326,7 +2337,10 @@ async function handleDenomLoss( continue; } const n = coinAv.freshCoinCount; - const denom = await tx.wtx.getDenomination(coinAv.exchangeBaseUrl, coinAv.denomPubHash); + const denom = await tx.wtx.getDenomination( + coinAv.exchangeBaseUrl, + coinAv.denomPubHash, + ); const timestampExpireDeposit = !denom ? undefined : timestampAbsoluteFromDb(denom.stampExpireDeposit); @@ -2605,7 +2619,10 @@ async function handleRecoup( const newlyRevokedCoinPubs: string[] = []; logger.trace("recoup list from exchange", recoupDenomList); for (const recoupInfo of recoupDenomList) { - const oldDenom = await tx.wtx.getDenomination(exchangeBaseUrl, recoupInfo.h_denom_pub); + const oldDenom = await tx.wtx.getDenomination( + exchangeBaseUrl, + recoupInfo.h_denom_pub, + ); if (!oldDenom) { // We never even knew about the revoked denomination, all good. continue; @@ -2619,7 +2636,9 @@ 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(recoupInfo.h_denom_pub); + const affectedCoins = await tx.wtx.getCoinsByDenomPubHash( + recoupInfo.h_denom_pub, + ); for (const ac of affectedCoins) { newlyRevokedCoinPubs.push(ac.coinPub); } @@ -2973,8 +2992,9 @@ export async function getExchangeDetailedInfo( if (!exchangeDetails) { return; } - const denominationRecords = - await tx.wtx.getDenominationsByExchange(ex.baseUrl); + const denominationRecords = await tx.wtx.getDenominationsByExchange( + ex.baseUrl, + ); if (!denominationRecords) { return; @@ -3147,8 +3167,7 @@ async function purgeExchange( continue; } await tx.wtx.deleteExchangeDetails(r.rowId); - const signkeyRecs = - await tx.wtx.getExchangeSignKeysByDetailsRowId(r.rowId); + const signkeyRecs = await tx.wtx.getExchangeSignKeysByDetailsRowId(r.rowId); for (const rec of signkeyRecs) { await tx.wtx.deleteExchangeSignKey(r.rowId, rec.signkeyPub); } @@ -3186,8 +3205,7 @@ async function purgeExchange( } { - const denomRecs = - await tx.wtx.getDenominationsByExchange(exchangeBaseUrl); + const denomRecs = await tx.wtx.getDenominationsByExchange(exchangeBaseUrl); for (const rec of denomRecs) { await tx.wtx.deleteDenomination(rec.exchangeBaseUrl, rec.denomPubHash); } @@ -3195,9 +3213,7 @@ async function purgeExchange( { const denomFamilyRecs = - await tx.wtx.getDenominationFamiliesByExchange( - exchangeBaseUrl, - ); + await tx.wtx.getDenominationFamiliesByExchange(exchangeBaseUrl); for (const rec of denomFamilyRecs) { checkDbInvariant( rec.denominationFamilySerial != null, @@ -3211,9 +3227,7 @@ async function purgeExchange( // transaction deletion was requested. { const withdrawalGroupRecs = - await tx.wtx.getWithdrawalGroupsByExchange( - exchangeBaseUrl, - ); + await tx.wtx.getWithdrawalGroupsByExchange(exchangeBaseUrl); for (const wg of withdrawalGroupRecs) { const ctx = new WithdrawTransactionContext(wex, wg.withdrawalGroupId); await ctx.deleteTransactionInTx(tx); @@ -3253,8 +3267,7 @@ async function purgeExchange( } // Remove from purchases, refundGroups, refundItems { - const purchases = - await tx.wtx.getPurchasesByExchange(exchangeBaseUrl); + const purchases = await tx.wtx.getPurchasesByExchange(exchangeBaseUrl); for (const purch of purchases) { const refunds = await tx.wtx.getRefundGroupsByProposal( purch.proposalId, @@ -3380,7 +3393,11 @@ export async function getExchangeWireFee( const exchangeDetails = await wex.runLegacyWalletDbTx(async (tx) => { const ex = await tx.wtx.getExchange(baseUrl); if (!ex || !ex.detailsPointer) return undefined; - return await tx.wtx.getExchangeDetailsByPointer(baseUrl, ex.detailsPointer.currency, ex.detailsPointer.masterPublicKey); + return await tx.wtx.getExchangeDetailsByPointer( + baseUrl, + ex.detailsPointer.currency, + ex.detailsPointer.masterPublicKey, + ); }); if (!exchangeDetails) { @@ -4049,8 +4066,11 @@ export async function checkExchangeInScopeTx( logger.trace(`no details for ${exchangeBaseUrl}`); return false; } - const gr = - await tx.wtx.getGlobalCurrencyExchange(exchangeDetails.currency, exchangeBaseUrl, exchangeDetails.masterPublicKey); + const gr = await tx.wtx.getGlobalCurrencyExchange( + exchangeDetails.currency, + exchangeBaseUrl, + exchangeDetails.masterPublicKey, + ); logger.trace(`global currency record: ${j2s(gr)}`); return gr != null; } @@ -4138,7 +4158,10 @@ export async function migrateExchange( req: MigrateExchangeRequest, ): Promise<void> { await wex.runLegacyWalletDbTx(async (tx) => { - const migrationRec = await tx.wtx.getExchangeMigrationLog(req.oldExchangeBaseUrl, req.newExchangeBaseUrl); + const migrationRec = await tx.wtx.getExchangeMigrationLog( + req.oldExchangeBaseUrl, + req.newExchangeBaseUrl, + ); if (migrationRec) { logger.warn( `exchange ${migrationRec.oldExchangeBaseUrl} already migrated`, diff --git a/packages/taler-wallet-core/src/instructedAmountConversion.ts b/packages/taler-wallet-core/src/instructedAmountConversion.ts @@ -202,10 +202,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.wtx.getDenominationsByExchange(exchangeBaseUrl); for (const denom of ds) { const expiresWithdraw = AbsoluteTime.fromProtocolTimestamp( timestampProtocolFromDb(denom.stampExpireWithdraw), @@ -245,7 +242,10 @@ async function getAvailableCoins( // FIXME: Should we exclude denominations that are // not spendable anymore? for (const coinAvail of myExchangeCoins) { - const denom = await tx.wtx.getDenomination(coinAvail.exchangeBaseUrl, coinAvail.denomPubHash); + const denom = await tx.wtx.getDenomination( + coinAvail.exchangeBaseUrl, + coinAvail.denomPubHash, + ); checkDbInvariant( !!denom, `denomination of a coin is missing hash: ${coinAvail.denomPubHash}`, diff --git a/packages/taler-wallet-core/src/pay-merchant.ts b/packages/taler-wallet-core/src/pay-merchant.ts @@ -160,9 +160,7 @@ import { WalletSlate, WalletToken, } from "./db-common.js"; -import { - RefundReason, -} from "./db-indexeddb.js"; +import { RefundReason } from "./db-indexeddb.js"; import { acceptDonauBlindSigs, generateDonauPlanchets } from "./donau.js"; import { getExchangeScopeInfoOrUndefined, @@ -433,10 +431,9 @@ export class PayMerchantTransactionContext implements TransactionContext { rec.download?.fulfillmentUrl && rec.purchaseStatus !== PurchaseStatus.DoneRepurchaseDetected ) { - const otherTransactions = - await tx.wtx.getPurchasesByFulfillmentUrl( - rec.download.fulfillmentUrl, - ); + const otherTransactions = await tx.wtx.getPurchasesByFulfillmentUrl( + rec.download.fulfillmentUrl, + ); for (const otx of otherTransactions) { if ( otx.purchaseStatus === PurchaseStatus.DoneRepurchaseDetected && @@ -760,7 +757,9 @@ export class RefundTransactionContext implements TransactionContext { await tx.wtx.deleteRefundGroup(this.refundGroupId); await this.updateTransactionMeta(tx); await tx.wtx.upsertTombstone({ id: this.transactionId }); - const items = await tx.wtx.getRefundItemsByGroup(refundRecord.refundGroupId); + const items = await tx.wtx.getRefundItemsByGroup( + refundRecord.refundGroupId, + ); for (const item of items) { if (item.id != null) { await tx.wtx.deleteRefundItem(item.id); @@ -2316,11 +2315,14 @@ export async function generateDepositPermissions( }> = []; await wex.runLegacyWalletDbTx(async (tx) => { for (let i = 0; i < payCoinSel.coinContributions.length; i++) { - const coin = await tx.coins.get(payCoinSel.coinPubs[i]); + const coin = await tx.wtx.getCoin(payCoinSel.coinPubs[i]); if (!coin) { throw Error("can't pay, allocated coin not found anymore"); } - const denom = await tx.wtx.getDenomination(coin.exchangeBaseUrl, coin.denomPubHash); + const denom = await tx.wtx.getDenomination( + coin.exchangeBaseUrl, + coin.denomPubHash, + ); if (!denom) { throw Error( "can't pay, denomination of allocated coin not found anymore", @@ -3297,8 +3299,7 @@ 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 recs = await tx.wtx.getDonationPlanchetsByProposal(proposalId); for (const rec of recs) { budikeypairs.push({ blinded_udi: rec.blindedUdi, @@ -4263,9 +4264,7 @@ async function processPurchaseAutoRefund( ); const totalKnownRefund = await wex.runLegacyWalletDbTx(async (tx) => { - const refunds = await tx.wtx.getRefundGroupsByProposal( - purchase.proposalId, - ); + const refunds = await tx.wtx.getRefundGroupsByProposal(purchase.proposalId); const am = Amounts.parseOrThrow(amountRaw); return refunds.reduce((prev, cur) => { if ( @@ -4396,7 +4395,7 @@ async function processPurchaseAbortingRefund( for (let i = 0; i < payCoinSelection.coinPubs.length; i++) { const coinPub = payCoinSelection.coinPubs[i]; - const coin = await tx.coins.get(coinPub); + const coin = await tx.wtx.getCoin(coinPub); checkDbInvariant(!!coin, `coin not found for ${coinPub}`); abortingCoins.push({ coin_pub: coinPub, @@ -4570,7 +4569,10 @@ export async function startRefundQueryForUri( throw Error("expected taler://refund URI"); } const purchaseRecord = await wex.runLegacyWalletDbTx(async (tx) => { - return tx.wtx.getPurchaseByUrlAndOrderId(parsedUri.merchantBaseUrl, parsedUri.orderId); + return tx.wtx.getPurchaseByUrlAndOrderId( + parsedUri.merchantBaseUrl, + parsedUri.orderId, + ); }); if (!purchaseRecord) { logger.error( @@ -4616,7 +4618,7 @@ async function computeRefreshRequest( ): Promise<CoinRefreshRequest[]> { const refreshCoins: CoinRefreshRequest[] = []; for (const item of items) { - const coin = await tx.coins.get(item.coinPub); + const coin = await tx.wtx.getCoin(item.coinPub); if (!coin) { throw Error("coin not found"); } @@ -4710,7 +4712,10 @@ async function storeRefunds( const newGroupRefunds: WalletRefundItem[] = []; for (const rf of refunds) { - const oldItem = await tx.wtx.getRefundItemByCoinAndRtxid(rf.coin_pub, rf.rtransaction_id); + const oldItem = await tx.wtx.getRefundItemByCoinAndRtxid( + rf.coin_pub, + rf.rtransaction_id, + ); if (oldItem) { logger.info("already have refund in database"); if (oldItem.status === RefundItemStatus.Done) { @@ -4815,7 +4820,9 @@ async function storeRefunds( default: assertUnreachable(refundGroup.status); } - const items = await tx.wtx.getRefundItemsByGroup(refundGroup.refundGroupId); + const items = await tx.wtx.getRefundItemsByGroup( + refundGroup.refundGroupId, + ); let numPending = 0; let numFailed = 0; for (const item of items) { diff --git a/packages/taler-wallet-core/src/pay-peer-common.ts b/packages/taler-wallet-core/src/pay-peer-common.ts @@ -25,9 +25,7 @@ import { } from "@gnu-taler/taler-util"; import { WalletReserve } from "./db-common.js"; import { SpendCoinDetails } from "./crypto/cryptoImplementation.js"; -import { - DbPeerPushPaymentCoinSelection, -} from "./db-indexeddb.js"; +import { DbPeerPushPaymentCoinSelection } from "./db-indexeddb.js"; import { getTotalRefreshCost } from "./refresh.js"; import { LegacyWalletTxHandle, @@ -46,7 +44,7 @@ export async function queryCoinInfosForSelection( let infos: SpendCoinDetails[] = []; await wex.runLegacyWalletDbTx(async (tx) => { for (let i = 0; i < csel.coinPubs.length; i++) { - const coin = await tx.coins.get(csel.coinPubs[i]); + const coin = await tx.wtx.getCoin(csel.coinPubs[i]); if (!coin) { throw Error("coin not found anymore"); } diff --git a/packages/taler-wallet-core/src/recoup.ts b/packages/taler-wallet-core/src/recoup.ts @@ -61,9 +61,7 @@ import { WalletRecoupGroup, WithdrawalRecordType, } from "./db-common.js"; -import { - CoinSourceType, -} from "./db-indexeddb.js"; +import { CoinSourceType } from "./db-indexeddb.js"; import { createRefreshGroup } from "./refresh.js"; import { constructTransactionIdentifier } from "./transactions.js"; import { @@ -177,8 +175,8 @@ async function recoupRefreshCoin( if (recoupGroup.recoupFinishedPerCoin[coinIdx]) { return; } - const oldCoin = await tx.coins.get(cs.oldCoinPub); - const revokedCoin = await tx.coins.get(coin.coinPub); + const oldCoin = await tx.wtx.getCoin(cs.oldCoinPub); + const revokedCoin = await tx.wtx.getCoin(coin.coinPub); if (!revokedCoin) { logger.warn("revoked coin for recoup not found"); return; @@ -213,8 +211,8 @@ async function recoupRefreshCoin( // coinPub: oldCoin.coinPub, // amount: Amounts.stringify(refreshAmount), // }); - await tx.coins.put(revokedCoin); - await tx.coins.put(oldCoin); + await tx.wtx.upsertCoin(revokedCoin); + await tx.wtx.upsertCoin(oldCoin); await putGroupAsFinished(wex, tx, recoupGroup, coinIdx); }); } @@ -275,12 +273,12 @@ export async function recoupWithdrawCoin( if (recoupGroup.recoupFinishedPerCoin[coinIdx]) { return; } - const updatedCoin = await tx.coins.get(coin.coinPub); + const updatedCoin = await tx.wtx.getCoin(coin.coinPub); if (!updatedCoin) { return; } updatedCoin.status = CoinStatus.Dormant; - await tx.coins.put(updatedCoin); + await tx.wtx.upsertCoin(updatedCoin); await putGroupAsFinished(wex, tx, recoupGroup, coinIdx); }); } @@ -333,7 +331,7 @@ export async function processRecoupGroup( for (let i = 0; i < recoupGroup.coinPubs.length; i++) { const coinPub = recoupGroup.coinPubs[i]; await wex.runLegacyWalletDbTx(async (tx) => { - const coin = await tx.coins.get(coinPub); + const coin = await tx.wtx.getCoin(coinPub); if (!coin) { throw Error(`Coin ${coinPub} not found, can't request recoup`); } @@ -518,12 +516,12 @@ export async function createRecoupGroup( for (let coinIdx = 0; coinIdx < coinPubs.length; coinIdx++) { const coinPub = coinPubs[coinIdx]; - const coin = await tx.coins.get(coinPub); + const coin = await tx.wtx.getCoin(coinPub); if (!coin) { await putGroupAsFinished(wex, tx, recoupGroup, coinIdx); continue; } - await tx.coins.put(coin); + await tx.wtx.upsertCoin(coin); } await tx.wtx.upsertRecoupGroup(recoupGroup); @@ -556,7 +554,7 @@ async function processRecoupForCoin( const coinPub = recoupGroup.coinPubs[coinIdx]; - const coin = await tx.coins.get(coinPub); + const coin = await tx.wtx.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 @@ -103,9 +103,7 @@ import { WalletRefreshGroup, WalletRefreshSession, } from "./db-common.js"; -import { - CoinSourceType, -} from "./db-indexeddb.js"; +import { CoinSourceType } from "./db-indexeddb.js"; import { selectWithdrawalDenominations } from "./denomSelection.js"; import { fetchFreshExchange, @@ -174,7 +172,9 @@ export class RefreshTransactionContext implements TransactionContext { async lookupFullTransaction( tx: LegacyWalletTxHandle, ): Promise<Transaction | undefined> { - const refreshGroupRecord = await tx.wtx.getRefreshGroup(this.refreshGroupId); + const refreshGroupRecord = await tx.wtx.getRefreshGroup( + this.refreshGroupId, + ); if (!refreshGroupRecord) { return undefined; } @@ -252,9 +252,7 @@ export class RefreshTransactionContext implements TransactionContext { ); return; } - const sessions = await tx.wtx.getRefreshSessionsByGroup( - rg.refreshGroupId, - ); + const sessions = await tx.wtx.getRefreshSessionsByGroup(rg.refreshGroupId); for (const s of sessions) { await tx.wtx.deleteRefreshSession(s.refreshGroupId, s.coinIndex); } @@ -422,11 +420,11 @@ async function getCoinAvailabilityForDenom( denom: DenominationInfo, ageRestriction: number, ): Promise<WalletCoinAvailability> { - let car = await tx.coinAvailability.get([ + let car = await tx.wtx.getCoinAvailability( denom.exchangeBaseUrl, denom.denomPubHash, ageRestriction, - ]); + ); if (!car) { car = { maxAge: ageRestriction, @@ -456,7 +454,7 @@ async function initRefreshSession( `creating refresh session for coin ${coinIndex} in refresh group ${refreshGroupId}`, ); const oldCoinPub = refreshGroup.oldCoinPubs[coinIndex]; - const oldCoin = await tx.coins.get(oldCoinPub); + const oldCoin = await tx.wtx.getCoin(oldCoinPub); if (!oldCoin) { throw Error("Can't refresh, coin not found"); } @@ -522,7 +520,7 @@ async function initRefreshSession( car.pendingRefreshOutputCount = (car.pendingRefreshOutputCount ?? 0) + newCoinDenoms.selectedDenoms[i].count; - await tx.coinAvailability.put(car); + await tx.wtx.upsertCoinAvailability(car); } const newSession: WalletRefreshSession = { @@ -550,7 +548,7 @@ async function destroyRefreshSession( refreshSession: WalletRefreshSession, ): Promise<void> { for (let i = 0; i < refreshSession.newDenoms.length; i++) { - const oldCoin = await tx.coins.get( + const oldCoin = await tx.wtx.getCoin( refreshGroup.oldCoinPubs[refreshSession.coinIndex], ); if (!oldCoin) { @@ -574,7 +572,7 @@ async function destroyRefreshSession( ); car.pendingRefreshOutputCount = car.pendingRefreshOutputCount - refreshSession.newDenoms[i].count; - await tx.coinAvailability.put(car); + await tx.wtx.upsertCoinAvailability(car); } } @@ -614,7 +612,7 @@ async function refreshMelt( return; } - const oldCoin = await tx.coins.get(refreshGroup.oldCoinPubs[coinIndex]); + const oldCoin = await tx.wtx.getCoin(refreshGroup.oldCoinPubs[coinIndex]); checkDbInvariant(!!oldCoin, "melt coin doesn't exist"); const oldDenom = await getDenomInfo( wex, @@ -1029,7 +1027,7 @@ async function refreshReveal( throw Error("can't reveal without melting first"); } - const oldCoin = await tx.coins.get(refreshGroup.oldCoinPubs[coinIndex]); + const oldCoin = await tx.wtx.getCoin(refreshGroup.oldCoinPubs[coinIndex]); checkDbInvariant(!!oldCoin, "melt coin doesn't exist"); const oldDenom = await getDenomInfo( wex, @@ -1192,11 +1190,11 @@ async function refreshReveal( } rg.statusPerCoin[coinIndex] = RefreshCoinStatus.Finished; for (const coin of coins) { - const existingCoin = await tx.coins.get(coin.coinPub); + const existingCoin = await tx.wtx.getCoin(coin.coinPub); if (existingCoin) { continue; } - await tx.coins.add(coin); + await tx.wtx.upsertCoin(coin); const denomInfo = await getDenomInfo( wex, tx, @@ -1217,7 +1215,7 @@ async function refreshReveal( ); car.pendingRefreshOutputCount--; car.freshCoinCount++; - await tx.coinAvailability.put(car); + await tx.wtx.upsertCoinAvailability(car); } await h.update(rg); }); @@ -1471,7 +1469,7 @@ export async function calculateRefreshOutput( const infoPerExchange: Record<string, WalletRefreshGroupPerExchangeInfo> = {}; for (const ocp of oldCoinPubs) { - const coin = await tx.coins.get(ocp.coinPub); + const coin = await tx.wtx.getCoin(ocp.coinPub); checkDbInvariant(!!coin, "coin must be in database"); const denom = await getDenomInfo( wex, @@ -1516,7 +1514,7 @@ async function applyRefreshToOldCoins( refreshGroupId: string, ): Promise<void> { for (const ocp of oldCoinPubs) { - const coin = await tx.coins.get(ocp.coinPub); + const coin = await tx.wtx.getCoin(ocp.coinPub); checkDbInvariant(!!coin, "coin must be in database"); const denom = await getDenomInfo( wex, @@ -1533,11 +1531,11 @@ async function applyRefreshToOldCoins( break; case CoinStatus.Fresh: { coin.status = CoinStatus.Dormant; - const coinAv = await tx.coinAvailability.get([ + const coinAv = await tx.wtx.getCoinAvailability( coin.exchangeBaseUrl, coin.denomPubHash, coin.maxAge, - ]); + ); checkDbInvariant( !!coinAv, `no denom info for ${coin.denomPubHash} age ${coin.maxAge}`, @@ -1554,7 +1552,7 @@ async function applyRefreshToOldCoins( coinAv.visibleCoinCount--; } } - await tx.coinAvailability.put(coinAv); + await tx.wtx.upsertCoinAvailability(coinAv); break; } case CoinStatus.FreshSuspended: { @@ -1568,7 +1566,7 @@ async function applyRefreshToOldCoins( default: assertUnreachable(coin.status); } - let histEntry: WalletCoinHistory | undefined = await tx.coinHistory.get( + let histEntry: WalletCoinHistory | undefined = await tx.wtx.getCoinHistory( coin.coinPub, ); if (!histEntry) { @@ -1585,8 +1583,8 @@ async function applyRefreshToOldCoins( }), amount: Amounts.stringify(ocp.amount), }); - await tx.coinHistory.put(histEntry); - await tx.coins.put(coin); + await tx.wtx.upsertCoinHistory(histEntry); + await tx.wtx.upsertCoin(coin); } } @@ -1614,7 +1612,7 @@ export async function createRefreshGroup( const exchanges: Set<string> = new Set(); for (const x of oldCoinPubs) { - const rec = await tx.coins.get(x.coinPub); + const rec = await tx.wtx.getCoin(x.coinPub); if (!rec) { continue; } @@ -1839,9 +1837,7 @@ export function getRefreshesForTransaction( ): Promise<string[]> { return wex.runLegacyWalletDbTx(async (tx) => { const groups = - await tx.wtx.getRefreshGroupsByOriginatingTransaction( - transactionId, - ); + await tx.wtx.getRefreshGroupsByOriginatingTransaction(transactionId); return groups.map((x) => constructTransactionIdentifier({ tag: TransactionType.Refresh, @@ -1861,7 +1857,7 @@ export async function forceRefresh( const res = await wex.runLegacyWalletDbTx(async (tx) => { const coinPubs: CoinRefreshRequest[] = []; for (const c of req.refreshCoinSpecs) { - const coin = await tx.coins.get(c.coinPub); + const coin = await tx.wtx.getCoin(c.coinPub); if (!coin) { throw Error(`coin (pubkey ${c}) not found`); } diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts @@ -741,7 +741,10 @@ async function dumpCoins(wex: WalletExecutionContext): Promise<CoinDumpJson> { await wex.runLegacyWalletDbTx(async (tx) => { const coins = await tx.coins.iter().toArray(); for (const c of coins) { - const denom = await tx.wtx.getDenomination(c.exchangeBaseUrl, c.denomPubHash); + const denom = await tx.wtx.getDenomination( + c.exchangeBaseUrl, + c.denomPubHash, + ); if (!denom) { logger.warn("no denom found for coin"); continue; @@ -1183,9 +1186,7 @@ async function handleTestingGetDenomStats( numOffered: 0, }; await wex.runLegacyWalletDbTx(async (tx) => { - const denoms = await tx.wtx.getDenominationsByExchange( - req.exchangeBaseUrl, - ); + const denoms = await tx.wtx.getDenominationsByExchange(req.exchangeBaseUrl); for (const d of denoms) { denomStats.numKnown++; if (d.isOffered) { @@ -2150,8 +2151,9 @@ export async function handleGetDiagnostics( cnt["exchangeSignKeys"] = await tx.exchangeSignKeys.count(); cnt["exchanges"] = await tx.exchanges.count(); for (const exch of await tx.exchanges.getAll()) { - const denoms = - await tx.denominations.indexes.byExchangeBaseUrl.getAll(exch.baseUrl); + const denoms = await tx.denominations.indexes.byExchangeBaseUrl.getAll( + exch.baseUrl, + ); let numWithdrawableDenoms = 0; let numCandidateWithdrawableDenoms = 0; for (let i = 0; i < denoms.length; i++) { diff --git a/packages/taler-wallet-core/src/withdraw.ts b/packages/taler-wallet-core/src/withdraw.ts @@ -152,9 +152,7 @@ import { WalletWithdrawalGroup, WithdrawalRecordType, } from "./db-common.js"; -import { - CoinSourceType, -} from "./db-indexeddb.js"; +import { CoinSourceType } from "./db-indexeddb.js"; import { selectForcedWithdrawalDenominations, selectWithdrawalDenominations, @@ -515,9 +513,7 @@ export class WithdrawTransactionContext implements TransactionContext { if (!rec) { return; } - const planchets = await tx.wtx.getPlanchetsByGroup( - rec.withdrawalGroupId, - ); + const planchets = await tx.wtx.getPlanchetsByGroup(rec.withdrawalGroupId); for (const p of planchets) { await tx.wtx.deletePlanchet(p.coinPub); } @@ -1279,9 +1275,7 @@ export async function getWithdrawableDenomsTx( ): Promise<WalletDenomination[]> { const dbNow = timestampProtocolToDb(TalerProtocolTimestamp.now()); const allFamilies = - await tx.wtx.getDenominationFamiliesByExchange( - exchangeBaseUrl, - ); + await tx.wtx.getDenominationFamiliesByExchange(exchangeBaseUrl); if (logger.shouldLogTrace()) { const maxStr = maxAmount ? Amounts.stringify(maxAmount) : "<unknown>"; logger.trace( @@ -2012,9 +2006,7 @@ export async function updateWithdrawalDenomsForExchange( const denoms = await wex.runLegacyWalletDbTx(async (tx) => { const allFamilies = - await tx.wtx.getDenominationFamiliesByExchange( - exchangeBaseUrl, - ); + await tx.wtx.getDenominationFamiliesByExchange(exchangeBaseUrl); const denominations: WalletDenomination[] | undefined = []; for (const fam of allFamilies) { const fpSerial = fam.denominationFamilySerial; @@ -2417,7 +2409,10 @@ 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.wtx.getDenomination( + exchangeBaseUrl, + sel.denomPubHash, + ); let denomOkay: boolean = false; @@ -2596,8 +2591,7 @@ async function processWithdrawalGroupPendingReady( }; await wex.runLegacyWalletDbTx(async (tx) => { - const planchets = - await tx.wtx.getPlanchetsByGroup(withdrawalGroupId); + const planchets = await tx.wtx.getPlanchetsByGroup(withdrawalGroupId); for (const p of planchets) { if (p.planchetStatus === PlanchetStatus.WithdrawalDone) { wgContext.planchetsFinished.add(p.coinPub); @@ -2672,8 +2666,7 @@ async function processWithdrawalGroupPendingReady( let redenomRequired = false; await wex.runLegacyWalletDbTx(async (tx) => { - const planchets = - await tx.wtx.getPlanchetsByGroup(withdrawalGroupId); + const planchets = await tx.wtx.getPlanchetsByGroup(withdrawalGroupId); for (const p of planchets) { if (p.planchetStatus !== PlanchetStatus.Pending) { continue; @@ -2712,8 +2705,7 @@ async function processWithdrawalGroupPendingReady( return; } - const groupPlanchets = - await tx.wtx.getPlanchetsByGroup(withdrawalGroupId); + const groupPlanchets = await tx.wtx.getPlanchetsByGroup(withdrawalGroupId); for (const x of groupPlanchets) { switch (x.planchetStatus) { case PlanchetStatus.KycRequired: @@ -4139,9 +4131,7 @@ export async function acceptBankIntegratedWithdrawal( const newWithdrawralGroup = await wex.runLegacyWalletDbTx( async (tx) => - await tx.wtx.getWithdrawalGroupByTalerWithdrawUri( - req.talerWithdrawUri, - ), + await tx.wtx.getWithdrawalGroupByTalerWithdrawUri(req.talerWithdrawUri), ); checkDbInvariant(