taler-typescript-core

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

commit a5a96dd347c95adce76ee2180c57f52fe0c406a6
parent c9aa8f116c0b1cba330908e501d279f85153b0a0
Author: Antoine A <>
Date:   Wed, 23 Apr 2025 16:53:54 +0200

wallet-core: clean code and format

Diffstat:
Mpackages/taler-wallet-core/src/coinSelection.ts | 6++----
Mpackages/taler-wallet-core/src/db.ts | 73+++++++++++++++++++++++++++++++++++--------------------------------------
Mpackages/taler-wallet-core/src/deposits.ts | 2--
Mpackages/taler-wallet-core/src/exchanges.ts | 38++++++++++++++------------------------
Mpackages/taler-wallet-core/src/pay-merchant.ts | 34+++++++++++++++-------------------
Mpackages/taler-wallet-core/src/wallet.ts | 2+-
Mpackages/taler-wallet-core/src/withdraw.ts | 104+++++++++++++++++++++++--------------------------------------------------------
7 files changed, 97 insertions(+), 162 deletions(-)

diff --git a/packages/taler-wallet-core/src/coinSelection.ts b/packages/taler-wallet-core/src/coinSelection.ts @@ -1,6 +1,6 @@ /* This file is part of GNU Taler - (C) 2021-2024 Taler Systems S.A. + (C) 2021-2025 Taler Systems S.A. GNU Taler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1018,7 +1018,6 @@ async function selectPayCandidates( const isInScope = req.restrictScope ? await checkExchangeInScopeTx( - wex, tx, exchange.baseUrl, req.restrictScope, @@ -1349,7 +1348,7 @@ export async function selectPeerCoinsInTx( continue; } const isInScope = req.restrictScope - ? await checkExchangeInScopeTx(wex, tx, exch.baseUrl, req.restrictScope) + ? await checkExchangeInScopeTx(tx, exch.baseUrl, req.restrictScope) : true; if (!isInScope) { continue; @@ -1613,7 +1612,6 @@ export async function getMaxPeerPushDebitAmount( } const isInScope = req.restrictScope ? await checkExchangeInScopeTx( - wex, tx, exch.baseUrl, req.restrictScope, diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts @@ -1,6 +1,6 @@ /* This file is part of GNU Taler - (C) 2021-2024 Taler Systems S.A. + (C) 2021-2025 Taler Systems S.A. GNU Taler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1079,29 +1079,29 @@ export type SlateRecord = Omit<TokenRecord, "tokenIssueSig">; */ export type DbWalletCoinHistoryItem = | { - type: "withdraw"; - transactionId: TransactionIdStr; - } + type: "withdraw"; + transactionId: TransactionIdStr; + } | { - type: "spend"; - transactionId: TransactionIdStr; - amount: AmountString; - } + type: "spend"; + transactionId: TransactionIdStr; + amount: AmountString; + } | { - type: "refresh"; - transactionId: TransactionIdStr; - amount: AmountString; - } + type: "refresh"; + transactionId: TransactionIdStr; + amount: AmountString; + } | { - type: "recoup"; - transactionId: TransactionIdStr; - amount: AmountString; - } + type: "recoup"; + transactionId: TransactionIdStr; + amount: AmountString; + } | { - type: "refund"; - transactionId: TransactionIdStr; - amount: AmountString; - }; + type: "refund"; + transactionId: TransactionIdStr; + amount: AmountString; + }; /** * History event for a coin from the wallet's perspective. @@ -1573,9 +1573,9 @@ export enum ConfigRecordKey { */ export type ConfigRecord = | { - key: ConfigRecordKey.WalletBackupState; - value: WalletBackupConfState; - } + key: ConfigRecordKey.WalletBackupState; + value: WalletBackupConfState; + } | { key: ConfigRecordKey.CurrencyDefaultsApplied; value: boolean } | { key: ConfigRecordKey.TestLoopTx; value: number } | { key: ConfigRecordKey.LastInitInfo; value: DbProtocolTimestamp } @@ -1863,15 +1863,15 @@ export enum BackupProviderStateTag { export type BackupProviderState = | { - tag: BackupProviderStateTag.Provisional; - } + tag: BackupProviderStateTag.Provisional; + } | { - tag: BackupProviderStateTag.Ready; - nextBackupTimestamp: DbPreciseTimestamp; - } + tag: BackupProviderStateTag.Ready; + nextBackupTimestamp: DbPreciseTimestamp; + } | { - tag: BackupProviderStateTag.Retrying; - }; + tag: BackupProviderStateTag.Retrying; + }; export interface BackupProviderRecord { /** @@ -3263,12 +3263,12 @@ export type WalletDbReadWriteTransaction<StoresArr extends WalletDbStoresArr> = export type WalletDbReadOnlyTransaction<StoresArr extends WalletDbStoresArr> = DbReadOnlyTransaction<typeof WalletStoresV1, StoresArr>; -export type WalletDbAllStoresReadOnlyTransaction<> = DbReadOnlyTransaction< +export type WalletDbAllStoresReadOnlyTransaction = DbReadOnlyTransaction< typeof WalletStoresV1, WalletDbStoresArr >; -export type WalletDbAllStoresReadWriteTransaction<> = DbReadWriteTransaction< +export type WalletDbAllStoresReadWriteTransaction = DbReadWriteTransaction< typeof WalletStoresV1, WalletDbStoresArr >; @@ -3501,10 +3501,7 @@ export async function importDb(db: IDBDatabase, dumpJson: any): Promise<void> { export interface FixupDescription { name: string; fn( - tx: DbReadWriteTransaction< - typeof WalletStoresV1, - Array<StoreNames<typeof WalletStoresV1>> - >, + tx: WalletDbReadOnlyTransaction<WalletDbStoresArr> ): Promise<void>; } @@ -3721,7 +3718,7 @@ export async function openStoredBackupsDatabase( idbFactory, TALER_WALLET_STORED_BACKUPS_DB_NAME, 1, - () => {}, + () => { }, onStoredBackupsDbUpgradeNeeded, ); @@ -3749,7 +3746,7 @@ export async function openTalerDatabase( idbFactory, TALER_WALLET_META_DB_NAME, 1, - () => {}, + () => { }, onMetaDbUpgradeNeeded, ); diff --git a/packages/taler-wallet-core/src/deposits.ts b/packages/taler-wallet-core/src/deposits.ts @@ -1877,7 +1877,6 @@ async function getExchangesForDeposit( } if (req.restrictScope) { const inScope = await checkExchangeInScopeTx( - wex, tx, e.baseUrl, req.restrictScope, @@ -2021,7 +2020,6 @@ export async function createDepositGroup( } if (req.restrictScope) { const inScope = await checkExchangeInScopeTx( - wex, tx, e.baseUrl, req.restrictScope, diff --git a/packages/taler-wallet-core/src/exchanges.ts b/packages/taler-wallet-core/src/exchanges.ts @@ -21,9 +21,6 @@ * The details of exchange entry management are specified in DD48. */ -/** - * Imports. - */ import { AbsoluteTime, AccountKycStatus, @@ -156,7 +153,6 @@ import { WalletDbHelpers, WalletDbReadOnlyTransaction, WalletDbReadWriteTransaction, - WalletStoresV1, timestampAbsoluteFromDb, timestampOptionalPreciseFromDb, timestampPreciseFromDb, @@ -480,8 +476,8 @@ async function makeExchangeListItem( ): Promise<ExchangeListItem> { const lastUpdateErrorInfo: OperationErrorInfo | undefined = lastError ? { - error: lastError, - } + error: lastError, + } : undefined; let scopeInfo: ScopeInfo | undefined = undefined; @@ -1189,8 +1185,7 @@ async function startUpdateExchangeEntry( options: { forceUpdate?: boolean } = {}, ): Promise<void> { logger.trace( - `starting update of exchange entry ${exchangeBaseUrl}, forced=${ - options.forceUpdate ?? false + `starting update of exchange entry ${exchangeBaseUrl}, forced=${options.forceUpdate ?? false }`, ); @@ -2598,7 +2593,6 @@ export async function listExchanges( } if (req.filterByScope) { const inScope = await checkExchangeInScopeTx( - wex, tx, exchangeRec.baseUrl, req.filterByScope, @@ -2635,7 +2629,6 @@ export async function listExchanges( * succeeded. */ export async function markExchangeUsed( - wex: WalletExecutionContext, tx: WalletDbReadWriteTransaction<["exchanges"]>, exchangeBaseUrl: string, ): Promise<{ notif: WalletNotification | undefined }> { @@ -2829,9 +2822,7 @@ export async function getExchangeDetailedInfo( } async function internalGetExchangeResources( - wex: WalletExecutionContext, - tx: DbReadOnlyTransaction< - typeof WalletStoresV1, + tx: WalletDbReadOnlyTransaction< ["exchanges", "coins", "withdrawalGroups"] >, exchangeBaseUrl: string, @@ -3050,7 +3041,7 @@ export async function deleteExchange( logger.info("no exchange found to delete"); return; } - const res = await internalGetExchangeResources(wex, tx, exchangeBaseUrl); + const res = await internalGetExchangeResources(tx, exchangeBaseUrl); if (res.hasResources && !req.purge) { inUse = true; return; @@ -3088,7 +3079,7 @@ export async function getExchangeResources( if (!exchangeRecord) { return undefined; } - return internalGetExchangeResources(wex, tx, exchangeBaseUrl); + return internalGetExchangeResources(tx, exchangeBaseUrl); }, ); if (!res) { @@ -3147,14 +3138,14 @@ export async function getExchangeWireFee( export type BalanceThresholdCheckResult = | { - result: "ok"; - } + result: "ok"; + } | { - result: "violation"; - nextThreshold: AmountString; - walletKycStatus: ExchangeWalletKycStatus | undefined; - walletKycAccessToken: string | undefined; - }; + result: "violation"; + nextThreshold: AmountString; + walletKycStatus: ExchangeWalletKycStatus | undefined; + walletKycAccessToken: string | undefined; + }; export async function checkIncomingAmountLegalUnderKycBalanceThreshold( wex: WalletExecutionContext, @@ -3749,7 +3740,6 @@ export async function processExchangeKyc( } export async function checkExchangeInScopeTx( - wex: WalletExecutionContext, tx: WalletDbReadOnlyTransaction< [ "globalCurrencyExchanges", @@ -3831,7 +3821,7 @@ export async function getPreferredExchangeForCurrency( } const inScope = !restrictScope || - (await checkExchangeInScopeTx(wex, tx, e.baseUrl, restrictScope)); + (await checkExchangeInScopeTx(tx, e.baseUrl, restrictScope)); if (!inScope) { logger.trace("not in scope"); continue; diff --git a/packages/taler-wallet-core/src/pay-merchant.ts b/packages/taler-wallet-core/src/pay-merchant.ts @@ -163,6 +163,7 @@ import { WalletDbAllStoresReadOnlyTransaction, WalletDbReadOnlyTransaction, WalletDbReadWriteTransaction, + WalletDbStoresArr, WalletStoresV1, } from "./db.js"; import { getScopeForAllCoins, getScopeForAllExchanges } from "./exchanges.js"; @@ -376,13 +377,12 @@ export class PayMerchantTransactionContext implements TransactionContext { * Extra object stores may be accessed during the transition. */ async transitionExtra< - StoreNameArray extends Array<StoreNames<typeof WalletStoresV1>> = [], + StoreNameArray extends WalletDbStoresArr = [], >( opts: { extraStores: StoreNameArray }, f: ( rec: PurchaseRecord, - tx: DbReadWriteTransaction< - typeof WalletStoresV1, + tx: WalletDbReadWriteTransaction< ["purchases", "transactionsMeta", ...StoreNameArray] >, ) => Promise<TransitionResultType>, @@ -1004,8 +1004,7 @@ async function processDownloadProposal( if (proposal.purchaseStatus != PurchaseStatus.PendingDownloadingProposal) { logger.error( - `unexpected state ${proposal.purchaseStatus}/${ - PurchaseStatus[proposal.purchaseStatus] + `unexpected state ${proposal.purchaseStatus}/${PurchaseStatus[proposal.purchaseStatus] } for ${ctx.transactionId} in processDownloadProposal`, ); return TaskRunResult.finished(); @@ -1274,7 +1273,7 @@ async function generateSlate( "can't process slates without secretSeed", ); - let slate = await wex.db.runReadOnlyTx({ storeNames: ["slates"]}, async (tx) => { + let slate = await wex.db.runReadOnlyTx({ storeNames: ["slates"] }, async (tx) => { return await tx.slates.indexes.byPurchaseIdAndChoiceIndexAndOutputIndex.get([ purchase.proposalId, choiceIndex, @@ -1380,8 +1379,7 @@ async function createOrReusePurchase( oldProposal.claimToken === claimToken ) { logger.info( - `Found old proposal (status=${ - PurchaseStatus[oldProposal.purchaseStatus] + `Found old proposal (status=${PurchaseStatus[oldProposal.purchaseStatus] }) for order ${orderId} at ${merchantBaseUrl}`, ); const ctx = new PayMerchantTransactionContext( @@ -2655,8 +2653,8 @@ async function calculateDefaultChoice( const details = choiceDetails[i]; if (details.status === ChoiceSelectionDetailType.PaymentPossible && choice.amount < cheapestPayableChoice.amount) { - cheapestPayableIndex = i; - cheapestPayableChoice = choice; + cheapestPayableIndex = i; + cheapestPayableChoice = choice; } } @@ -2675,7 +2673,7 @@ async function calculateDefaultChoice( (cheapestPayableChoice.inputs[0].count ?? 1) === 1 && (cheapestPayableChoice.outputs[0].count ?? 1) === 1 && cheapestPayableChoice.inputs[0].token_family_slug === - cheapestPayableChoice.inputs[0].token_family_slug; + cheapestPayableChoice.inputs[0].token_family_slug; break; default: assertUnreachable(contractTerms); @@ -2906,7 +2904,7 @@ export async function confirmPay( transactionId: transactionId as TransactionIdStr, coinPubs: sel.coinPubs, contributions: sel.coinContributions.map((x) => - Amounts.parseOrThrow(x), + Amounts.parseOrThrow(x), ), refreshReason: RefreshReason.PayMerchant, }); @@ -3241,11 +3239,9 @@ async function processPurchasePay( }); if (slates.length !== contractData.choices[index].outputs.length) { - throw Error(`number of slates ${ - slates.length - } doesn't match number of outputs ${ - contractData.choices[index].outputs.length - }`); + throw Error(`number of slates ${slates.length + } doesn't match number of outputs ${contractData.choices[index].outputs.length + }`); } } @@ -3420,7 +3416,7 @@ export async function validateAndStoreToken( slate: SlateRecord, blindedEv: SignedTokenEnvelope, ): Promise<void> { - const {tokenIssuePub, tokenUsePub, blindingKey} = slate; + const { tokenIssuePub, tokenUsePub, blindingKey } = slate; const tokenIssueSig = await wex.cryptoApi.unblindTokenIssueSignature({ slate: { tokenIssuePub, @@ -3429,7 +3425,7 @@ export async function validateAndStoreToken( evSig: blindedEv.blind_sig, }); - const {valid} = await wex.cryptoApi.isValidTokenIssueSignature({ + const { valid } = await wex.cryptoApi.isValidTokenIssueSignature({ sig: tokenIssueSig, tokenUsePub, tokenIssuePub, diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts @@ -971,7 +971,7 @@ async function handleAddExchange( // Thus, we mark it as "used". if (!req.ephemeral) { await wex.db.runAllStoresReadWriteTx({}, async (tx) => { - await markExchangeUsed(wex, tx, exchangeBaseUrl); + await markExchangeUsed(tx, exchangeBaseUrl); }); } return { diff --git a/packages/taler-wallet-core/src/withdraw.ts b/packages/taler-wallet-core/src/withdraw.ts @@ -19,9 +19,6 @@ * bank-integrated and manual. */ -/** - * Imports. - */ import { AbsoluteTime, AcceptManualWithdrawalResult, @@ -1041,7 +1038,7 @@ async function processWithdrawalGroupBalanceKyc( } if ( withdrawalGroup.status === - WithdrawalGroupStatus.PendingBalanceKycInit && + WithdrawalGroupStatus.PendingBalanceKycInit && checkRes.walletKycStatus === ExchangeWalletKycStatus.Legi ) { return checkRes; @@ -2064,8 +2061,7 @@ export async function updateWithdrawalDenomsForExchange( denom.verificationStatus === DenominationVerificationStatus.Unverified ) { logger.trace( - `Validating denomination (${current + 1}/${ - denominations.length + `Validating denomination (${current + 1}/${denominations.length }) signature of ${denom.denomPubHash}`, ); let valid = false; @@ -2756,9 +2752,7 @@ export async function processWithdrawalGroup( logger.trace("processing withdrawal group", withdrawalGroupId); const withdrawalGroup = await wex.db.runReadOnlyTx( { storeNames: ["withdrawalGroups"] }, - async (tx) => { - return tx.withdrawalGroups.get(withdrawalGroupId); - }, + (tx) => tx.withdrawalGroups.get(withdrawalGroupId) ); if (!withdrawalGroup) { @@ -2879,7 +2873,7 @@ export async function getExchangeWithdrawalInfo( ) { logger.warn( `wallet's support for exchange protocol version ${WALLET_EXCHANGE_PROTOCOL_VERSION} might be outdated ` + - `(exchange has ${exchange.protocolVersionRange}), checking for updates`, + `(exchange has ${exchange.protocolVersionRange}), checking for updates`, ); } } @@ -3067,9 +3061,7 @@ async function getWithdrawalGroupRecordTx( ): Promise<WithdrawalGroupRecord | undefined> { return await db.runReadOnlyTx( { storeNames: ["withdrawalGroups"] }, - async (tx) => { - return tx.withdrawalGroups.get(req.withdrawalGroupId); - }, + (tx) => tx.withdrawalGroups.get(req.withdrawalGroupId) ); } @@ -3108,9 +3100,7 @@ async function registerReserveWithBank( ): Promise<TaskRunResult> { const withdrawalGroup = await wex.db.runReadOnlyTx( { storeNames: ["withdrawalGroups"] }, - async (tx) => { - return await tx.withdrawalGroups.get(withdrawalGroupId); - }, + (tx) => tx.withdrawalGroups.get(withdrawalGroupId) ); const ctx = new WithdrawTransactionContext(wex, withdrawalGroupId); switch (withdrawalGroup?.status) { @@ -3436,15 +3426,13 @@ async function getInitialDenomsSelection( if (forcedDenoms) { logger.warn("using forced denom selection"); - const initialDenomSel = selectForcedWithdrawalDenominations( + return selectForcedWithdrawalDenominations( amount, denoms, forcedDenoms, ); - return initialDenomSel; } else { - const initialDenomSel = selectWithdrawalDenominations(amount, denoms); - return initialDenomSel; + return selectWithdrawalDenominations(amount, denoms); } } @@ -3476,9 +3464,7 @@ export async function internalPrepareCreateWithdrawalGroup( const wgId = withdrawalGroupId; const existingWg = await wex.db.runReadOnlyTx( { storeNames: ["withdrawalGroups"] }, - async (tx) => { - return tx.withdrawalGroups.get(wgId); - }, + (tx) => tx.withdrawalGroups.get(wgId), ); if (existingWg) { @@ -3542,9 +3528,9 @@ export async function internalPrepareCreateWithdrawalGroup( !amount || !exchangeBaseUrl ? undefined : { - amount, - canonExchange: exchangeBaseUrl, - }, + amount, + canonExchange: exchangeBaseUrl, + }, }; } @@ -3622,7 +3608,7 @@ async function internalPerformExchangeWasUsed( balanceEffect: BalanceEffect.Any, }; - const exchangeUsedRes = await markExchangeUsed(wex, tx, canonExchange); + const exchangeUsedRes = await markExchangeUsed(tx, canonExchange); const ctx = new WithdrawTransactionContext( wex, @@ -3702,11 +3688,7 @@ export async function prepareBankIntegratedWithdrawal( ): Promise<PrepareBankIntegratedWithdrawalResponse> { const existingWithdrawalGroup = await wex.db.runReadOnlyTx( { storeNames: ["withdrawalGroups"] }, - async (tx) => { - return await tx.withdrawalGroups.indexes.byTalerWithdrawUri.get( - req.talerWithdrawUri, - ); - }, + (tx) => tx.withdrawalGroups.indexes.byTalerWithdrawUri.get(req.talerWithdrawUri) ); const parsedUri = parseTalerUri(req.talerWithdrawUri); @@ -3825,9 +3807,7 @@ export async function confirmWithdrawal( } const withdrawalGroup = await wex.db.runReadOnlyTx( { storeNames: ["withdrawalGroups"] }, - async (tx) => { - return await tx.withdrawalGroups.get(parsedTx.withdrawalGroupId); - }, + (tx) => tx.withdrawalGroups.get(parsedTx.withdrawalGroupId) ); if (!withdrawalGroup) { @@ -3935,12 +3915,8 @@ export async function confirmWithdrawal( logger.info(`adding account ${senderWire} to know bank accounts`); const bankAccountId = await wex.db.runReadWriteTx( - { - storeNames: ["bankAccountsV2"], - }, - async (tx) => { - return await storeKnownBankAccount(tx, instructedCurrency, senderWire); - }, + { storeNames: ["bankAccountsV2"] }, + (tx) => storeKnownBankAccount(tx, instructedCurrency, senderWire) ); if (bankAccountId) { @@ -4027,18 +4003,13 @@ export async function confirmWithdrawal( // FIXME: Merge with transaction above! const res = await wex.db.runReadWriteTx( - { - storeNames: ["exchanges"], - }, - async (tx) => { - const r = await internalPerformExchangeWasUsed( - wex, - tx, - exchange.exchangeBaseUrl, - withdrawalGroup, - ); - return r; - }, + { storeNames: ["exchanges"] }, + (tx) => internalPerformExchangeWasUsed( + wex, + tx, + exchange.exchangeBaseUrl, + withdrawalGroup, + ) ); if (res.exchangeNotif) { wex.ws.notify(res.exchangeNotif); @@ -4135,11 +4106,7 @@ export async function acceptBankIntegratedWithdrawal( const newWithdrawralGroup = await wex.db.runReadOnlyTx( { storeNames: ["withdrawalGroups"] }, - async (tx) => { - return await tx.withdrawalGroups.indexes.byTalerWithdrawUri.get( - req.talerWithdrawUri, - ); - }, + (tx) => tx.withdrawalGroups.indexes.byTalerWithdrawUri.get(req.talerWithdrawUri) ); checkDbInvariant( @@ -4205,12 +4172,8 @@ async function fetchAccount( // fetch currency specification from DB const resp = await wex.db.runReadOnlyTx( - { - storeNames: ["currencyInfo"], - }, - async (tx) => { - return WalletDbHelpers.getCurrencyInfo(tx, scopeInfo); - }, + { storeNames: ["currencyInfo"] }, + (tx) => WalletDbHelpers.getCurrencyInfo(tx, scopeInfo) ); if (resp) { @@ -4344,9 +4307,7 @@ export async function createManualWithdrawal( const exchangePaytoUris = await wex.db.runReadOnlyTx( { storeNames: ["withdrawalGroups", "exchanges", "exchangeDetails"] }, - async (tx) => { - return await getFundingPaytoUris(tx, withdrawalGroup.withdrawalGroupId); - }, + (tx) => getFundingPaytoUris(tx, withdrawalGroup.withdrawalGroupId) ); wex.ws.notify({ @@ -4383,15 +4344,10 @@ export async function waitWithdrawalFinal( }, async checkState() { // Check if withdrawal is final - const res = await ctx.wex.db.runReadOnlyTx( + const wg = await ctx.wex.db.runReadOnlyTx( { storeNames: ["withdrawalGroups"] }, - async (tx) => { - return { - wg: await tx.withdrawalGroups.get(ctx.withdrawalGroupId), - }; - }, + (tx) => tx.withdrawalGroups.get(ctx.withdrawalGroupId) ); - const { wg } = res; if (!wg) { // Must've been deleted, we consider that final. return true;