summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/exchanges.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-core/src/exchanges.ts')
-rw-r--r--packages/taler-wallet-core/src/exchanges.ts142
1 files changed, 69 insertions, 73 deletions
diff --git a/packages/taler-wallet-core/src/exchanges.ts b/packages/taler-wallet-core/src/exchanges.ts
index 932df721d..a26b3f5ca 100644
--- a/packages/taler-wallet-core/src/exchanges.ts
+++ b/packages/taler-wallet-core/src/exchanges.ts
@@ -128,7 +128,7 @@ import { DbReadOnlyTransaction } from "./query.js";
import { createRecoupGroup } from "./recoup.js";
import { createRefreshGroup } from "./refresh.js";
import { WALLET_EXCHANGE_PROTOCOL_VERSION } from "./versions.js";
-import { InternalWalletState } from "./wallet.js";
+import { InternalWalletState, WalletExecutionContext } from "./wallet.js";
const logger = new Logger("exchanges.ts");
@@ -147,10 +147,10 @@ interface ExchangeTosDownloadResult {
}
async function downloadExchangeWithTermsOfService(
+ wex: WalletExecutionContext,
exchangeBaseUrl: string,
http: HttpRequestLibrary,
timeout: Duration,
- cancellationToken: CancellationToken,
acceptFormat: string,
acceptLanguage: string | undefined,
): Promise<ExchangeTosDownloadResult> {
@@ -170,7 +170,7 @@ async function downloadExchangeWithTermsOfService(
const resp = await http.fetch(reqUrl.href, {
headers,
timeout,
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
const tosText = await readSuccessResponseTextOrThrow(resp);
const tosEtag = resp.headers.get("etag") || "unknown";
@@ -344,10 +344,10 @@ export async function getExchangeWireDetailsInTx(
}
export async function lookupExchangeByUri(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: GetExchangeEntryByUrlRequest,
): Promise<ExchangeListItem> {
- return await ws.db.runReadOnlyTx(
+ return await wex.db.runReadOnlyTx(
[
"exchanges",
"exchangeDetails",
@@ -381,10 +381,10 @@ export async function lookupExchangeByUri(
* Mark the current ToS version as accepted by the user.
*/
export async function acceptExchangeTermsOfService(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
exchangeBaseUrl: string,
): Promise<void> {
- const notif = await ws.db.runReadWriteTx(
+ const notif = await wex.db.runReadWriteTx(
["exchangeDetails", "exchanges"],
async (tx) => {
const exch = await tx.exchanges.get(exchangeBaseUrl);
@@ -407,7 +407,7 @@ export async function acceptExchangeTermsOfService(
},
);
if (notif) {
- ws.notify(notif);
+ wex.ws.notify(notif);
}
}
@@ -449,7 +449,7 @@ export async function forgetExchangeTermsOfService(
* Throw an exception if they are invalid.
*/
async function validateWireInfo(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
versionCurrent: number,
wireInfo: ExchangeKeysDownloadResult,
masterPublicKey: string,
@@ -457,10 +457,10 @@ async function validateWireInfo(
for (const a of wireInfo.accounts) {
logger.trace("validating exchange acct");
let isValid = false;
- if (ws.config.testing.insecureTrustExchange) {
+ if (wex.ws.config.testing.insecureTrustExchange) {
isValid = true;
} else {
- const { valid: v } = await ws.cryptoApi.isValidWireAccount({
+ const { valid: v } = await wex.ws.cryptoApi.isValidWireAccount({
masterPub: masterPublicKey,
paytoUri: a.payto_uri,
sig: a.master_sig,
@@ -490,10 +490,10 @@ async function validateWireInfo(
wireFee: Amounts.stringify(x.wire_fee),
};
let isValid = false;
- if (ws.config.testing.insecureTrustExchange) {
+ if (wex.ws.config.testing.insecureTrustExchange) {
isValid = true;
} else {
- const { valid: v } = await ws.cryptoApi.isValidWireFee({
+ const { valid: v } = await wex.ws.cryptoApi.isValidWireFee({
masterPub: masterPublicKey,
type: wireMethod,
wf: fee,
@@ -520,7 +520,7 @@ async function validateWireInfo(
* Throw an exception if they are invalid.
*/
async function validateGlobalFees(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
fees: GlobalFees[],
masterPub: string,
): Promise<ExchangeGlobalFees[]> {
@@ -528,10 +528,10 @@ async function validateGlobalFees(
for (const gf of fees) {
logger.trace("validating exchange global fees");
let isValid = false;
- if (ws.config.testing.insecureTrustExchange) {
+ if (wex.ws.config.testing.insecureTrustExchange) {
isValid = true;
} else {
- const { valid: v } = await ws.cryptoApi.isValidGlobalFees({
+ const { valid: v } = await wex.cryptoApi.isValidGlobalFees({
masterPub,
gf,
});
@@ -832,10 +832,9 @@ async function downloadExchangeKeysInfo(
}
async function downloadTosFromAcceptedFormat(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
baseUrl: string,
timeout: Duration,
- cancellationToken: CancellationToken,
acceptedFormat?: string[],
acceptLanguage?: string,
): Promise<ExchangeTosDownloadResult> {
@@ -844,10 +843,10 @@ async function downloadTosFromAcceptedFormat(
if (acceptedFormat)
for (const format of acceptedFormat) {
const resp = await downloadExchangeWithTermsOfService(
+ wex,
baseUrl,
- ws.http,
+ wex.http,
timeout,
- cancellationToken,
format,
acceptLanguage,
);
@@ -861,10 +860,10 @@ async function downloadTosFromAcceptedFormat(
}
// If none of the specified format was found try text/plain
return await downloadExchangeWithTermsOfService(
+ wex,
baseUrl,
- ws.http,
+ wex.http,
timeout,
- cancellationToken,
"text/plain",
acceptLanguage,
);
@@ -880,7 +879,7 @@ async function downloadTosFromAcceptedFormat(
* a new ephemeral entry is created.
*/
async function startUpdateExchangeEntry(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
exchangeBaseUrl: string,
options: { forceUpdate?: boolean } = {},
): Promise<void> {
@@ -892,19 +891,19 @@ async function startUpdateExchangeEntry(
}`,
);
- const { notification } = await ws.db.runReadWriteTx(
+ const { notification } = await wex.db.runReadWriteTx(
["exchanges", "exchangeDetails"],
async (tx) => {
- return provideExchangeRecordInTx(ws, tx, exchangeBaseUrl);
+ return provideExchangeRecordInTx(wex.ws, tx, exchangeBaseUrl);
},
);
if (notification) {
- ws.notify(notification);
+ wex.ws.notify(notification);
}
const { oldExchangeState, newExchangeState, taskId } =
- await ws.db.runReadWriteTx(
+ await wex.db.runReadWriteTx(
["exchanges", "operationRetries"],
async (tx) => {
const r = await tx.exchanges.get(canonBaseUrl);
@@ -952,13 +951,13 @@ async function startUpdateExchangeEntry(
return { oldExchangeState, newExchangeState, taskId };
},
);
- ws.notify({
+ wex.ws.notify({
type: NotificationType.ExchangeStateTransition,
exchangeBaseUrl: canonBaseUrl,
newExchangeState: newExchangeState,
oldExchangeState: oldExchangeState,
});
- await ws.taskScheduler.resetTaskRetries(taskId);
+ await wex.ws.taskScheduler.resetTaskRetries(taskId);
}
/**
@@ -978,7 +977,7 @@ export interface ReadyExchangeSummary {
}
async function internalWaitReadyExchange(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
canonUrl: string,
exchangeNotifFlag: AsyncFlag,
options: {
@@ -994,7 +993,7 @@ async function internalWaitReadyExchange(
while (true) {
logger.info(`waiting for ready exchange ${canonUrl}`);
const { exchange, exchangeDetails, retryInfo, scopeInfo } =
- await ws.db.runReadOnlyTx(
+ await wex.db.runReadOnlyTx(
[
"exchanges",
"exchangeDetails",
@@ -1105,7 +1104,7 @@ async function internalWaitReadyExchange(
* will still have been added as an ephemeral exchange entry.
*/
export async function fetchFreshExchange(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
baseUrl: string,
options: {
cancellationToken?: CancellationToken;
@@ -1115,17 +1114,17 @@ export async function fetchFreshExchange(
): Promise<ReadyExchangeSummary> {
const canonUrl = canonicalizeBaseUrl(baseUrl);
- ws.taskScheduler.ensureRunning();
+ wex.ws.taskScheduler.ensureRunning();
- await startUpdateExchangeEntry(ws, canonUrl, {
+ await startUpdateExchangeEntry(wex, canonUrl, {
forceUpdate: options.forceUpdate,
});
- return waitReadyExchange(ws, canonUrl, options);
+ return waitReadyExchange(wex, canonUrl, options);
}
async function waitReadyExchange(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
canonUrl: string,
options: {
cancellationToken?: CancellationToken;
@@ -1138,7 +1137,7 @@ async function waitReadyExchange(
const exchangeNotifFlag = new AsyncFlag();
// Raise exchangeNotifFlag whenever we get a notification
// about our exchange.
- const cancelNotif = ws.addNotificationListener((notif) => {
+ const cancelNotif = wex.ws.addNotificationListener((notif) => {
if (
notif.type === NotificationType.ExchangeStateTransition &&
notif.exchangeBaseUrl === canonUrl
@@ -1150,7 +1149,7 @@ async function waitReadyExchange(
try {
const res = await internalWaitReadyExchange(
- ws,
+ wex,
canonUrl,
exchangeNotifFlag,
options,
@@ -1169,14 +1168,13 @@ async function waitReadyExchange(
* exchange entry in then DB.
*/
export async function updateExchangeFromUrlHandler(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
exchangeBaseUrl: string,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
logger.trace(`updating exchange info for ${exchangeBaseUrl}`);
exchangeBaseUrl = canonicalizeBaseUrl(exchangeBaseUrl);
- const oldExchangeRec = await ws.db.runReadOnlyTx(
+ const oldExchangeRec = await wex.db.runReadOnlyTx(
["exchanges"],
async (tx) => {
return tx.exchanges.get(exchangeBaseUrl);
@@ -1264,9 +1262,9 @@ export async function updateExchangeFromUrlHandler(
const keysInfo = await downloadExchangeKeysInfo(
exchangeBaseUrl,
- ws.http,
+ wex.http,
timeout,
- cancellationToken,
+ wex.cancellationToken,
oldExchangeRec.cachebreakNextUpdate ?? false,
);
@@ -1279,14 +1277,14 @@ export async function updateExchangeFromUrlHandler(
}
const wireInfo = await validateWireInfo(
- ws,
+ wex,
version.current,
keysInfo,
keysInfo.masterPublicKey,
);
const globalFees = await validateGlobalFees(
- ws,
+ wex,
keysInfo.globalFees,
keysInfo.masterPublicKey,
);
@@ -1311,10 +1309,9 @@ export async function updateExchangeFromUrlHandler(
// because that one needs to exist, and we
// will get the current etag from the response.
const tosDownload = await downloadTosFromAcceptedFormat(
- ws,
+ wex,
exchangeBaseUrl,
timeout,
- cancellationToken,
["text/plain"],
);
@@ -1327,7 +1324,7 @@ export async function updateExchangeFromUrlHandler(
let ageMask = 0;
for (const x of keysInfo.currentDenominations) {
if (
- isWithdrawableDenom(x, ws.config.testing.denomselAllowLate) &&
+ isWithdrawableDenom(x, wex.ws.config.testing.denomselAllowLate) &&
x.denomPub.age_mask != 0
) {
ageMask = x.denomPub.age_mask;
@@ -1335,7 +1332,7 @@ export async function updateExchangeFromUrlHandler(
}
}
- const updated = await ws.db.runReadWriteTx(
+ const updated = await wex.db.runReadWriteTx(
[
"exchanges",
"exchangeDetails",
@@ -1492,7 +1489,7 @@ export async function updateExchangeFromUrlHandler(
if (newlyRevokedCoinPubs.length != 0) {
logger.info("recouping coins", newlyRevokedCoinPubs);
recoupGroupId = await createRecoupGroup(
- ws,
+ wex,
tx,
exchangeBaseUrl,
newlyRevokedCoinPubs,
@@ -1517,7 +1514,7 @@ export async function updateExchangeFromUrlHandler(
});
// Asynchronously start recoup. This doesn't need to finish
// for the exchange update to be considered finished.
- ws.taskScheduler.startShepherdTask(recoupTaskId);
+ wex.ws.taskScheduler.startShepherdTask(recoupTaskId);
}
if (!updated) {
@@ -1535,7 +1532,7 @@ export async function updateExchangeFromUrlHandler(
if (refreshCheckNecessary) {
// Do auto-refresh.
- await ws.db.runReadWriteTx(
+ await wex.db.runReadWriteTx(
[
"coins",
"denominations",
@@ -1581,7 +1578,7 @@ export async function updateExchangeFromUrlHandler(
}
if (refreshCoins.length > 0) {
const res = await createRefreshGroup(
- ws,
+ wex,
tx,
exchange.detailsPointer?.currency,
refreshCoins,
@@ -1605,7 +1602,7 @@ export async function updateExchangeFromUrlHandler(
);
}
- ws.notify({
+ wex.ws.notify({
type: NotificationType.ExchangeStateTransition,
exchangeBaseUrl,
newExchangeState: updated.newExchangeState,
@@ -1648,13 +1645,13 @@ function getAutoRefreshCheckThreshold(d: DenominationRecord): AbsoluteTime {
* Throws if no matching account was found.
*/
export async function getExchangePaytoUri(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
exchangeBaseUrl: string,
supportedTargetTypes: string[],
): Promise<string> {
// We do the update here, since the exchange might not even exist
// yet in our database.
- const details = await ws.db.runReadOnlyTx(
+ const details = await wex.db.runReadOnlyTx(
["exchanges", "exchangeDetails"],
async (tx) => {
return getExchangeRecordsInternal(tx, exchangeBaseUrl);
@@ -1682,23 +1679,22 @@ export async function getExchangePaytoUri(
* Try to download in the accepted format not cached.
*/
export async function getExchangeTos(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
exchangeBaseUrl: string,
acceptedFormat?: string[],
acceptLanguage?: string,
): Promise<GetExchangeTosResult> {
- const exch = await fetchFreshExchange(ws, exchangeBaseUrl);
+ const exch = await fetchFreshExchange(wex, exchangeBaseUrl);
const tosDownload = await downloadTosFromAcceptedFormat(
- ws,
+ wex,
exchangeBaseUrl,
getExchangeRequestTimeout(),
- CancellationToken.CONTINUE,
acceptedFormat,
acceptLanguage,
);
- await ws.db.runReadWriteTx(["exchanges"], async (tx) => {
+ await wex.db.runReadWriteTx(["exchanges"], async (tx) => {
const updateExchangeEntry = await tx.exchanges.get(exchangeBaseUrl);
if (updateExchangeEntry) {
updateExchangeEntry.tosCurrentEtag = tosDownload.tosEtag;
@@ -1750,10 +1746,10 @@ export async function downloadExchangeInfo(
* List all exchange entries known to the wallet.
*/
export async function listExchanges(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
): Promise<ExchangesListResponse> {
const exchanges: ExchangeListItem[] = [];
- await ws.db.runReadOnlyTx(
+ await wex.db.runReadOnlyTx(
[
"exchanges",
"operationRetries",
@@ -1793,7 +1789,7 @@ export async function listExchanges(
* succeeded.
*/
export async function markExchangeUsed(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
tx: WalletDbReadWriteTransaction<["exchanges"]>,
exchangeBaseUrl: string,
): Promise<{ notif: WalletNotification | undefined }> {
@@ -1833,10 +1829,10 @@ export async function markExchangeUsed(
* for the fees charged by the exchange.
*/
export async function getExchangeDetailedInfo(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
exchangeBaseurl: string,
): Promise<ExchangeDetailedResponse> {
- const exchange = await ws.db.runReadOnlyTx(
+ const exchange = await wex.db.runReadOnlyTx(
["exchanges", "exchangeDetails", "denominations"],
async (tx) => {
const ex = await tx.exchanges.get(exchangeBaseurl);
@@ -1986,7 +1982,7 @@ export async function getExchangeDetailedInfo(
}
async function internalGetExchangeResources(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
tx: DbReadOnlyTransaction<
typeof WalletStoresV1,
["exchanges", "coins", "withdrawalGroups"]
@@ -2005,12 +2001,12 @@ async function internalGetExchangeResources(
}
export async function deleteExchange(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: DeleteExchangeRequest,
): Promise<void> {
let inUse: boolean = false;
const exchangeBaseUrl = canonicalizeBaseUrl(req.exchangeBaseUrl);
- await ws.db.runReadWriteTx(
+ await wex.db.runReadWriteTx(
["exchanges", "coins", "withdrawalGroups", "exchangeDetails"],
async (tx) => {
const exchangeRec = await tx.exchanges.get(exchangeBaseUrl);
@@ -2019,7 +2015,7 @@ export async function deleteExchange(
logger.info("no exchange found to delete");
return;
}
- const res = await internalGetExchangeResources(ws, tx, exchangeBaseUrl);
+ const res = await internalGetExchangeResources(wex, tx, exchangeBaseUrl);
if (res.hasResources) {
if (req.purge) {
const detRecs =
@@ -2050,18 +2046,18 @@ export async function deleteExchange(
}
export async function getExchangeResources(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
exchangeBaseUrl: string,
): Promise<GetExchangeResourcesResponse> {
// Withdrawals include internal withdrawals from peer transactions
- const res = await ws.db.runReadOnlyTx(
+ const res = await wex.db.runReadOnlyTx(
["exchanges", "withdrawalGroups", "coins"],
async (tx) => {
const exchangeRecord = await tx.exchanges.get(exchangeBaseUrl);
if (!exchangeRecord) {
return undefined;
}
- return internalGetExchangeResources(ws, tx, exchangeBaseUrl);
+ return internalGetExchangeResources(wex, tx, exchangeBaseUrl);
},
);
if (!res) {