diff options
Diffstat (limited to 'packages/taler-wallet-core/src/operations/withdraw.ts')
-rw-r--r-- | packages/taler-wallet-core/src/operations/withdraw.ts | 91 |
1 files changed, 43 insertions, 48 deletions
diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts index cf4e9a1d5..49c0e4a14 100644 --- a/packages/taler-wallet-core/src/operations/withdraw.ts +++ b/packages/taler-wallet-core/src/operations/withdraw.ts @@ -57,6 +57,7 @@ import { TransactionType, URL, UnblindedSignature, + WalletNotification, WithdrawUriInfoResponse, WithdrawalExchangeAccountDetails, addPaytoQueryParams, @@ -133,8 +134,10 @@ import { import { ReadyExchangeSummary, fetchFreshExchange, - getExchangeDetails, getExchangePaytoUri, + getExchangeWireDetailsInTx, + listExchanges, + markExchangeUsed, } from "./exchanges.js"; import { TransitionInfo, @@ -1191,7 +1194,7 @@ export async function updateWithdrawalDenoms( const exchangeDetails = await ws.db .mktx((x) => [x.exchanges, x.exchangeDetails]) .runReadOnly(async (tx) => { - return ws.exchangeOps.getExchangeDetails(tx, exchangeBaseUrl); + return getExchangeWireDetailsInTx(tx, exchangeBaseUrl); }); if (!exchangeDetails) { logger.error("exchange details not available"); @@ -1521,7 +1524,7 @@ async function processWithdrawalGroupPendingReady( withdrawalGroupId, }); - await ws.exchangeOps.fetchFreshExchange(ws, withdrawalGroup.exchangeBaseUrl); + await fetchFreshExchange(ws, withdrawalGroup.exchangeBaseUrl); if (withdrawalGroup.denomsSel.selectedDenoms.length === 0) { logger.warn("Finishing empty withdrawal group (no denoms)"); @@ -1768,7 +1771,7 @@ export async function getExchangeWithdrawalInfo( ageRestricted: number | undefined, ): Promise<ExchangeWithdrawalDetails> { logger.trace("updating exchange"); - const exchange = await ws.exchangeOps.fetchFreshExchange(ws, exchangeBaseUrl); + const exchange = await fetchFreshExchange(ws, exchangeBaseUrl); if (exchange.currency != instructedAmount.currency) { // Specifiying the amount in the conversion input currency is not yet supported. @@ -1917,7 +1920,7 @@ export interface GetWithdrawalDetailsForUriOpts { * Get more information about a taler://withdraw URI. * * As side effects, the bank (via the bank integration API) is queried - * and the exchange suggested by the bank is permanently added + * and the exchange suggested by the bank is ephemerally added * to the wallet's list of known exchanges. */ export async function getWithdrawalDetailsForUri( @@ -1929,10 +1932,10 @@ export async function getWithdrawalDetailsForUri( const info = await getBankWithdrawalInfo(ws.http, talerWithdrawUri); logger.trace(`got bank info`); if (info.suggestedExchange) { - // FIXME: right now the exchange gets permanently added, - // we might want to only temporarily add it. try { - await ws.exchangeOps.fetchFreshExchange(ws, info.suggestedExchange); + // If the exchange entry doesn't exist yet, + // it'll be created as an ephemeral entry. + await fetchFreshExchange(ws, info.suggestedExchange); } catch (e) { // We still continued if it failed, as other exchanges might be available. // We don't want to fail if the bank-suggested exchange is broken/offline. @@ -1942,40 +1945,12 @@ export async function getWithdrawalDetailsForUri( } } - // Extract information about possible exchanges for the withdrawal - // operation from the database. - - const exchanges: ExchangeListItem[] = []; - - await ws.db - .mktx((x) => [ - x.exchanges, - x.exchangeDetails, - x.denominations, - x.operationRetries, - ]) - .runReadOnly(async (tx) => { - const exchangeRecords = await tx.exchanges.iter().toArray(); - for (const r of exchangeRecords) { - const exchangeDetails = await ws.exchangeOps.getExchangeDetails( - tx, - r.baseUrl, - ); - const retryRecord = await tx.operationRetries.get( - TaskIdentifiers.forExchangeUpdate(r), - ); - if (exchangeDetails) { - exchanges.push( - makeExchangeListItem(r, exchangeDetails, retryRecord?.lastError), - ); - } - } - }); + const possibleExchangesResp = await listExchanges(ws); return { amount: Amounts.stringify(info.amount), defaultExchangeBaseUrl: info.suggestedExchange, - possibleExchanges: exchanges, + possibleExchanges: possibleExchangesResp.exchanges, }; } @@ -2005,7 +1980,7 @@ export async function getFundingPaytoUris( ): Promise<string[]> { const withdrawalGroup = await tx.withdrawalGroups.get(withdrawalGroupId); checkDbInvariant(!!withdrawalGroup); - const exchangeDetails = await getExchangeDetails( + const exchangeDetails = await getExchangeWireDetailsInTx( tx, withdrawalGroup.exchangeBaseUrl, ); @@ -2385,7 +2360,7 @@ export async function internalPrepareCreateWithdrawalGroup( wgInfo: args.wgInfo, }; - const exchangeInfo = await fetchFreshExchange(ws, canonExchange); + await fetchFreshExchange(ws, canonExchange); const transactionId = constructTransactionIdentifier({ tag: TransactionType.Withdrawal, withdrawalGroupId: withdrawalGroup.withdrawalGroupId, @@ -2404,6 +2379,13 @@ export async function internalPrepareCreateWithdrawalGroup( export interface PerformCreateWithdrawalGroupResult { withdrawalGroup: WithdrawalGroupRecord; transitionInfo: TransitionInfo | undefined; + + /** + * Notification for the exchange state transition. + * + * Should be emitted after the transaction has succeeded. + */ + exchangeNotif: WalletNotification | undefined; } export async function internalPerformCreateWithdrawalGroup( @@ -2417,7 +2399,11 @@ export async function internalPerformCreateWithdrawalGroup( ): Promise<PerformCreateWithdrawalGroupResult> { const { withdrawalGroup } = prep; if (!prep.creationInfo) { - return { withdrawalGroup, transitionInfo: undefined }; + return { + withdrawalGroup, + transitionInfo: undefined, + exchangeNotif: undefined, + }; } await tx.withdrawalGroups.add(withdrawalGroup); await tx.reserves.put({ @@ -2428,7 +2414,6 @@ export async function internalPerformCreateWithdrawalGroup( const exchange = await tx.exchanges.get(withdrawalGroup.exchangeBaseUrl); if (exchange) { exchange.lastWithdrawal = timestampPreciseToDb(TalerPreciseTimestamp.now()); - exchange.entryStatus = ExchangeEntryDbRecordStatus.Used; await tx.exchanges.put(exchange); } @@ -2442,7 +2427,17 @@ export async function internalPerformCreateWithdrawalGroup( newTxState, }; - return { withdrawalGroup, transitionInfo }; + const exchangeUsedRes = await markExchangeUsed( + ws, + tx, + prep.withdrawalGroup.exchangeBaseUrl, + ); + + return { + withdrawalGroup, + transitionInfo, + exchangeNotif: exchangeUsedRes.notif, + }; } /** @@ -2481,6 +2476,9 @@ export async function internalCreateWithdrawalGroup( .runReadWrite(async (tx) => { return await internalPerformCreateWithdrawalGroup(ws, tx, prep); }); + if (res.exchangeNotif) { + ws.notify(res.exchangeNotif); + } notifyTransition(ws, transactionId, res.transitionInfo); return res.withdrawalGroup; } @@ -2535,10 +2533,7 @@ export async function acceptWithdrawalFromUri( withdrawInfo.wireTypes, ); - const exchange = await ws.exchangeOps.fetchFreshExchange( - ws, - selectedExchange, - ); + const exchange = await fetchFreshExchange(ws, selectedExchange); const withdrawalAccountList = await fetchWithdrawalAccountInfo(ws, { exchange, @@ -2710,7 +2705,7 @@ export async function createManualWithdrawal( ): Promise<AcceptManualWithdrawalResult> { const { exchangeBaseUrl } = req; const amount = Amounts.parseOrThrow(req.amount); - const exchange = await ws.exchangeOps.fetchFreshExchange(ws, exchangeBaseUrl); + const exchange = await fetchFreshExchange(ws, exchangeBaseUrl); if (exchange.currency != amount.currency) { throw Error( |