aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/operations/withdraw.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-core/src/operations/withdraw.ts')
-rw-r--r--packages/taler-wallet-core/src/operations/withdraw.ts91
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(