summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2024-02-27 17:39:58 +0100
committerFlorian Dold <florian@dold.me>2024-02-27 17:40:03 +0100
commit523280b3862b528512ff93c651bc0d9ed632fbf6 (patch)
treeb99f866db59b572685c8c7215136270e22210ca2
parent3a889c177dd35a114d2c95efd296274cd185ce52 (diff)
downloadwallet-core-523280b3862b528512ff93c651bc0d9ed632fbf6.tar.gz
wallet-core-523280b3862b528512ff93c651bc0d9ed632fbf6.tar.bz2
wallet-core-523280b3862b528512ff93c651bc0d9ed632fbf6.zip
wallet-core: thread through wallet execution context
-rw-r--r--packages/taler-wallet-core/src/attention.ts26
-rw-r--r--packages/taler-wallet-core/src/backup/index.ts117
-rw-r--r--packages/taler-wallet-core/src/balance.ts32
-rw-r--r--packages/taler-wallet-core/src/coinSelection.ts32
-rw-r--r--packages/taler-wallet-core/src/common.ts16
-rw-r--r--packages/taler-wallet-core/src/deposits.ts221
-rw-r--r--packages/taler-wallet-core/src/dev-experiments.ts8
-rw-r--r--packages/taler-wallet-core/src/exchanges.ts142
-rw-r--r--packages/taler-wallet-core/src/instructedAmountConversion.ts24
-rw-r--r--packages/taler-wallet-core/src/pay-merchant.ts428
-rw-r--r--packages/taler-wallet-core/src/pay-peer-common.ts24
-rw-r--r--packages/taler-wallet-core/src/pay-peer-pull-credit.ts157
-rw-r--r--packages/taler-wallet-core/src/pay-peer-pull-debit.ts93
-rw-r--r--packages/taler-wallet-core/src/pay-peer-push-credit.ts120
-rw-r--r--packages/taler-wallet-core/src/pay-peer-push-debit.ts177
-rw-r--r--packages/taler-wallet-core/src/recoup.ts79
-rw-r--r--packages/taler-wallet-core/src/refresh.ts222
-rw-r--r--packages/taler-wallet-core/src/reward.ts24
-rw-r--r--packages/taler-wallet-core/src/shepherd.ts71
-rw-r--r--packages/taler-wallet-core/src/testing.ts174
-rw-r--r--packages/taler-wallet-core/src/transactions.ts86
-rw-r--r--packages/taler-wallet-core/src/wallet.ts273
-rw-r--r--packages/taler-wallet-core/src/withdraw.ts414
23 files changed, 1430 insertions, 1530 deletions
diff --git a/packages/taler-wallet-core/src/attention.ts b/packages/taler-wallet-core/src/attention.ts
index 61f95350d..60d2117f1 100644
--- a/packages/taler-wallet-core/src/attention.ts
+++ b/packages/taler-wallet-core/src/attention.ts
@@ -29,15 +29,15 @@ import {
UserAttentionsResponse,
} from "@gnu-taler/taler-util";
import { timestampPreciseFromDb, timestampPreciseToDb } from "./db.js";
-import { InternalWalletState } from "./wallet.js";
+import { InternalWalletState, WalletExecutionContext } from "./wallet.js";
const logger = new Logger("operations/attention.ts");
export async function getUserAttentionsUnreadCount(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: UserAttentionsRequest,
): Promise<UserAttentionsCountResponse> {
- const total = await ws.db.runReadOnlyTx(["userAttention"], async (tx) => {
+ const total = await wex.db.runReadOnlyTx(["userAttention"], async (tx) => {
let count = 0;
await tx.userAttention.iter().forEach((x) => {
if (
@@ -56,10 +56,10 @@ export async function getUserAttentionsUnreadCount(
}
export async function getUserAttentions(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: UserAttentionsRequest,
): Promise<UserAttentionsResponse> {
- return await ws.db.runReadOnlyTx(["userAttention"], async (tx) => {
+ return await wex.db.runReadOnlyTx(["userAttention"], async (tx) => {
const pending: UserAttentionUnreadList = [];
await tx.userAttention.iter().forEach((x) => {
if (
@@ -79,10 +79,10 @@ export async function getUserAttentions(
}
export async function markAttentionRequestAsRead(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: UserAttentionByIdRequest,
): Promise<void> {
- await ws.db.runReadWriteTx(["userAttention"], async (tx) => {
+ await wex.db.runReadWriteTx(["userAttention"], async (tx) => {
const ua = await tx.userAttention.get([req.entityId, req.type]);
if (!ua) throw Error("attention request not found");
tx.userAttention.put({
@@ -96,15 +96,15 @@ export async function markAttentionRequestAsRead(
* the wallet need the user attention to complete a task
* internal API
*
- * @param ws
+ * @param wex
* @param info
*/
export async function addAttentionRequest(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
info: AttentionInfo,
entityId: string,
): Promise<void> {
- await ws.db.runReadWriteTx(["userAttention"], async (tx) => {
+ await wex.db.runReadWriteTx(["userAttention"], async (tx) => {
await tx.userAttention.put({
info,
entityId,
@@ -118,14 +118,14 @@ export async function addAttentionRequest(
* user completed the task, attention request is not needed
* internal API
*
- * @param ws
+ * @param wex
* @param created
*/
export async function removeAttentionRequest(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: UserAttentionByIdRequest,
): Promise<void> {
- await ws.db.runReadWriteTx(["userAttention"], async (tx) => {
+ await wex.db.runReadWriteTx(["userAttention"], async (tx) => {
const ua = await tx.userAttention.get([req.entityId, req.type]);
if (!ua) throw Error("attention request not found");
await tx.userAttention.delete([req.entityId, req.type]);
diff --git a/packages/taler-wallet-core/src/backup/index.ts b/packages/taler-wallet-core/src/backup/index.ts
index a5d7eee80..04c53526d 100644
--- a/packages/taler-wallet-core/src/backup/index.ts
+++ b/packages/taler-wallet-core/src/backup/index.ts
@@ -90,7 +90,7 @@ import {
timestampPreciseToDb,
} from "../db.js";
import { preparePayForUri } from "../pay-merchant.js";
-import { InternalWalletState } from "../wallet.js";
+import { InternalWalletState, WalletExecutionContext } from "../wallet.js";
const logger = new Logger("operations/backup.ts");
@@ -179,10 +179,10 @@ function getNextBackupTimestamp(): TalerPreciseTimestamp {
}
async function runBackupCycleForProvider(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
args: BackupForProviderArgs,
): Promise<TaskRunResult> {
- const provider = await ws.db.runReadOnlyTx(
+ const provider = await wex.db.runReadOnlyTx(
["backupProviders"],
async (tx) => {
return tx.backupProviders.get(args.backupProviderBaseUrl);
@@ -197,7 +197,7 @@ async function runBackupCycleForProvider(
//const backupJson = await exportBackup(ws);
// FIXME: re-implement backup
const backupJson = {};
- const backupConfig = await provideBackupState(ws);
+ const backupConfig = await provideBackupState(wex);
const encBackup = await encryptBackup(backupConfig, backupJson);
const currentBackupHash = hash(encBackup);
@@ -209,7 +209,7 @@ async function runBackupCycleForProvider(
logger.trace(`trying to upload backup to ${provider.baseUrl}`);
logger.trace(`old hash ${oldHash}, new hash ${newHash}`);
- const syncSigResp = await ws.cryptoApi.makeSyncSignature({
+ const syncSigResp = await wex.cryptoApi.makeSyncSignature({
newHash: encodeCrock(currentBackupHash),
oldHash: provider.lastBackupHash,
accountPriv: encodeCrock(accountKeyPair.eddsaPriv),
@@ -226,7 +226,7 @@ async function runBackupCycleForProvider(
accountBackupUrl.searchParams.set("fresh", "yes");
}
- const resp = await ws.http.fetch(accountBackupUrl.href, {
+ const resp = await wex.http.fetch(accountBackupUrl.href, {
method: "POST",
body: encBackup,
headers: {
@@ -244,7 +244,7 @@ async function runBackupCycleForProvider(
logger.trace(`sync response status: ${resp.status}`);
if (resp.status === HttpStatusCode.NotModified) {
- await ws.db.runReadWriteTx(["backupProviders"], async (tx) => {
+ await wex.db.runReadWriteTx(["backupProviders"], async (tx) => {
const prov = await tx.backupProviders.get(provider.baseUrl);
if (!prov) {
return;
@@ -259,7 +259,7 @@ async function runBackupCycleForProvider(
await tx.backupProviders.put(prov);
});
- removeAttentionRequest(ws, {
+ removeAttentionRequest(wex, {
entityId: provider.baseUrl,
type: AttentionType.BackupUnpaid,
});
@@ -279,7 +279,7 @@ async function runBackupCycleForProvider(
//FIXME: check download errors
let res: PreparePayResult | undefined = undefined;
try {
- res = await preparePayForUri(ws, talerUri);
+ res = await preparePayForUri(wex, talerUri);
} catch (e) {
const error = TalerError.fromException(e);
if (!error.hasErrorCode(TalerErrorCode.WALLET_ORDER_ALREADY_CLAIMED)) {
@@ -290,7 +290,7 @@ async function runBackupCycleForProvider(
if (res === undefined) {
//claimed
- await ws.db.runReadWriteTx(["backupProviders"], async (tx) => {
+ await wex.db.runReadWriteTx(["backupProviders"], async (tx) => {
const prov = await tx.backupProviders.get(provider.baseUrl);
if (!prov) {
logger.warn("backup provider not found anymore");
@@ -310,7 +310,7 @@ async function runBackupCycleForProvider(
}
const result = res;
- await ws.db.runReadWriteTx(["backupProviders"], async (tx) => {
+ await wex.db.runReadWriteTx(["backupProviders"], async (tx) => {
const prov = await tx.backupProviders.get(provider.baseUrl);
if (!prov) {
logger.warn("backup provider not found anymore");
@@ -327,7 +327,7 @@ async function runBackupCycleForProvider(
});
addAttentionRequest(
- ws,
+ wex,
{
type: AttentionType.BackupUnpaid,
provider_base_url: provider.baseUrl,
@@ -343,7 +343,7 @@ async function runBackupCycleForProvider(
}
if (resp.status === HttpStatusCode.NoContent) {
- await ws.db.runReadWriteTx(["backupProviders"], async (tx) => {
+ await wex.db.runReadWriteTx(["backupProviders"], async (tx) => {
const prov = await tx.backupProviders.get(provider.baseUrl);
if (!prov) {
return;
@@ -359,7 +359,7 @@ async function runBackupCycleForProvider(
await tx.backupProviders.put(prov);
});
- removeAttentionRequest(ws, {
+ removeAttentionRequest(wex, {
entityId: provider.baseUrl,
type: AttentionType.BackupUnpaid,
});
@@ -372,11 +372,11 @@ async function runBackupCycleForProvider(
if (resp.status === HttpStatusCode.Conflict) {
logger.info("conflicting backup found");
const backupEnc = new Uint8Array(await resp.bytes());
- const backupConfig = await provideBackupState(ws);
+ const backupConfig = await provideBackupState(wex);
// const blob = await decryptBackup(backupConfig, backupEnc);
// FIXME: Re-implement backup import with merging
// await importBackup(ws, blob, cryptoData);
- await ws.db.runReadWriteTx(["backupProviders"], async (tx) => {
+ await wex.db.runReadWriteTx(["backupProviders"], async (tx) => {
const prov = await tx.backupProviders.get(provider.baseUrl);
if (!prov) {
logger.warn("backup provider not found anymore");
@@ -394,7 +394,7 @@ async function runBackupCycleForProvider(
});
logger.info("processed existing backup");
// Now upload our own, merged backup.
- return await runBackupCycleForProvider(ws, args);
+ return await runBackupCycleForProvider(wex, args);
}
// Some other response that we did not expect!
@@ -410,10 +410,10 @@ async function runBackupCycleForProvider(
}
export async function processBackupForProvider(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
backupProviderBaseUrl: string,
): Promise<TaskRunResult> {
- const provider = await ws.db.runReadOnlyTx(
+ const provider = await wex.db.runReadOnlyTx(
["backupProviders"],
async (tx) => {
return await tx.backupProviders.get(backupProviderBaseUrl);
@@ -425,7 +425,7 @@ export async function processBackupForProvider(
logger.info(`running backup for provider ${backupProviderBaseUrl}`);
- return await runBackupCycleForProvider(ws, {
+ return await runBackupCycleForProvider(wex, {
backupProviderBaseUrl: provider.baseUrl,
});
}
@@ -441,10 +441,10 @@ export const codecForRemoveBackupProvider =
.build("RemoveBackupProviderRequest");
export async function removeBackupProvider(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: RemoveBackupProviderRequest,
): Promise<void> {
- await ws.db.runReadWriteTx(["backupProviders"], async (tx) => {
+ await wex.db.runReadWriteTx(["backupProviders"], async (tx) => {
await tx.backupProviders.delete(req.provider);
});
}
@@ -469,10 +469,10 @@ export const codecForRunBackupCycle = (): Codec<RunBackupCycleRequest> =>
* 3. Upload the updated backup blob.
*/
export async function runBackupCycle(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: RunBackupCycleRequest,
): Promise<void> {
- const providers = await ws.db.runReadOnlyTx(
+ const providers = await wex.db.runReadOnlyTx(
["backupProviders"],
async (tx) => {
if (req.providers) {
@@ -486,7 +486,7 @@ export async function runBackupCycle(
);
for (const provider of providers) {
- await runBackupCycleForProvider(ws, {
+ await runBackupCycleForProvider(wex, {
backupProviderBaseUrl: provider.baseUrl,
});
}
@@ -547,13 +547,13 @@ export const codecForAddBackupProviderResponse =
.build("AddBackupProviderResponse");
export async function addBackupProvider(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: AddBackupProviderRequest,
): Promise<AddBackupProviderResponse> {
logger.info(`adding backup provider ${j2s(req)}`);
- await provideBackupState(ws);
+ await provideBackupState(wex);
const canonUrl = canonicalizeBaseUrl(req.backupProviderBaseUrl);
- await ws.db.runReadWriteTx(["backupProviders"], async (tx) => {
+ await wex.db.runReadWriteTx(["backupProviders"], async (tx) => {
const oldProv = await tx.backupProviders.get(canonUrl);
if (oldProv) {
logger.info("old backup provider found");
@@ -571,12 +571,12 @@ export async function addBackupProvider(
}
});
const termsUrl = new URL("config", canonUrl);
- const resp = await ws.http.fetch(termsUrl.href);
+ const resp = await wex.http.fetch(termsUrl.href);
const terms = await readSuccessResponseJsonOrThrow(
resp,
codecForSyncTermsOfServiceResponse(),
);
- await ws.db.runReadWriteTx(["backupProviders"], async (tx) => {
+ await wex.db.runReadWriteTx(["backupProviders"], async (tx) => {
let state: BackupProviderState;
//FIXME: what is the difference provisional and ready?
if (req.activate) {
@@ -604,13 +604,13 @@ export async function addBackupProvider(
});
});
- return await runFirstBackupCycleForProvider(ws, {
+ return await runFirstBackupCycleForProvider(wex, {
backupProviderBaseUrl: canonUrl,
});
}
async function runFirstBackupCycleForProvider(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
args: BackupForProviderArgs,
): Promise<AddBackupProviderResponse> {
throw Error("not implemented");
@@ -647,7 +647,7 @@ export interface BackupInfo {
}
async function getProviderPaymentInfo(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
provider: BackupProviderRecord,
): Promise<ProviderPaymentStatus> {
throw Error("not implemented");
@@ -702,10 +702,10 @@ async function getProviderPaymentInfo(
* Get information about the current state of wallet backups.
*/
export async function getBackupInfo(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
): Promise<BackupInfo> {
- const backupConfig = await provideBackupState(ws);
- const providerRecords = await ws.db.runReadOnlyTx(
+ const backupConfig = await provideBackupState(wex);
+ const providerRecords = await wex.db.runReadOnlyTx(
["backupProviders", "operationRetries"],
async (tx) => {
return await tx.backupProviders.iter().mapAsync(async (bp) => {
@@ -731,7 +731,7 @@ export async function getBackupInfo(
x.provider.state.tag === BackupProviderStateTag.Retrying
? x.retryRecord?.lastError
: undefined,
- paymentStatus: await getProviderPaymentInfo(ws, x.provider),
+ paymentStatus: await getProviderPaymentInfo(wex, x.provider),
terms: x.provider.terms,
name: x.provider.name,
});
@@ -748,10 +748,10 @@ export async function getBackupInfo(
* private key.
*/
export async function getBackupRecovery(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
): Promise<BackupRecovery> {
- const bs = await provideBackupState(ws);
- const providers = await ws.db.runReadOnlyTx(
+ const bs = await provideBackupState(wex);
+ const providers = await wex.db.runReadOnlyTx(
["backupProviders"],
async (tx) => {
return await tx.backupProviders.iter().toArray();
@@ -771,10 +771,10 @@ export async function getBackupRecovery(
}
async function backupRecoveryTheirs(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
br: BackupRecovery,
) {
- await ws.db.runReadWriteTx(["backupProviders", "config"], async (tx) => {
+ await wex.db.runReadWriteTx(["backupProviders", "config"], async (tx) => {
let backupStateEntry: ConfigRecord | undefined = await tx.config.get(
ConfigRecordKey.WalletBackupState,
);
@@ -818,16 +818,19 @@ async function backupRecoveryTheirs(
});
}
-async function backupRecoveryOurs(ws: InternalWalletState, br: BackupRecovery) {
+async function backupRecoveryOurs(
+ wex: WalletExecutionContext,
+ br: BackupRecovery,
+) {
throw Error("not implemented");
}
export async function loadBackupRecovery(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
br: RecoveryLoadRequest,
): Promise<void> {
- const bs = await provideBackupState(ws);
- const providers = await ws.db.runReadOnlyTx(
+ const bs = await provideBackupState(wex);
+ const providers = await wex.db.runReadOnlyTx(
["backupProviders"],
async (tx) => {
return await tx.backupProviders.iter().toArray();
@@ -847,9 +850,9 @@ export async function loadBackupRecovery(
strategy = RecoveryMergeStrategy.Theirs;
}
if (strategy === RecoveryMergeStrategy.Theirs) {
- return backupRecoveryTheirs(ws, br.recovery);
+ return backupRecoveryTheirs(wex, br.recovery);
} else {
- return backupRecoveryOurs(ws, br.recovery);
+ return backupRecoveryOurs(wex, br.recovery);
}
}
@@ -873,9 +876,9 @@ export async function decryptBackup(
}
export async function provideBackupState(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
): Promise<WalletBackupConfState> {
- const bs: ConfigRecord | undefined = await ws.db.runReadOnlyTx(
+ const bs: ConfigRecord | undefined = await wex.db.runReadOnlyTx(
["config"],
async (tx) => {
return await tx.config.get(ConfigRecordKey.WalletBackupState);
@@ -887,12 +890,12 @@ export async function provideBackupState(
}
// We need to generate the key outside of the transaction
// due to how IndexedDB works.
- const k = await ws.cryptoApi.createEddsaKeypair({});
+ const k = await wex.cryptoApi.createEddsaKeypair({});
const d = getRandomBytes(5);
// FIXME: device ID should be configured when wallet is initialized
// and be based on hostname
const deviceId = `wallet-core-${encodeCrock(d)}`;
- return await ws.db.runReadWriteTx(["config"], async (tx) => {
+ return await wex.db.runReadWriteTx(["config"], async (tx) => {
let backupStateEntry: ConfigRecord | undefined = await tx.config.get(
ConfigRecordKey.WalletBackupState,
);
@@ -926,11 +929,11 @@ export async function getWalletBackupState(
}
export async function setWalletDeviceId(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
deviceId: string,
): Promise<void> {
- await provideBackupState(ws);
- await ws.db.runReadWriteTx(["config"], async (tx) => {
+ await provideBackupState(wex);
+ await wex.db.runReadWriteTx(["config"], async (tx) => {
let backupStateEntry: ConfigRecord | undefined = await tx.config.get(
ConfigRecordKey.WalletBackupState,
);
@@ -946,8 +949,8 @@ export async function setWalletDeviceId(
}
export async function getWalletDeviceId(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
): Promise<string> {
- const bs = await provideBackupState(ws);
+ const bs = await provideBackupState(wex);
return bs.deviceId;
}
diff --git a/packages/taler-wallet-core/src/balance.ts b/packages/taler-wallet-core/src/balance.ts
index a287748f1..3b53699ac 100644
--- a/packages/taler-wallet-core/src/balance.ts
+++ b/packages/taler-wallet-core/src/balance.ts
@@ -80,7 +80,7 @@ import {
getExchangeScopeInfo,
getExchangeWireDetailsInTx,
} from "./exchanges.js";
-import { InternalWalletState } from "./wallet.js";
+import { InternalWalletState, WalletExecutionContext } from "./wallet.js";
/**
* Logger.
@@ -131,7 +131,7 @@ class BalancesStore {
private balanceStore: Record<string, WalletBalance> = {};
constructor(
- private ws: InternalWalletState,
+ private wex: WalletExecutionContext,
private tx: WalletDbReadOnlyTransaction<
[
"globalCurrencyAuditors",
@@ -281,7 +281,7 @@ class BalancesStore {
* Get balance information.
*/
export async function getBalancesInsideTransaction(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
tx: WalletDbReadOnlyTransaction<
[
"exchanges",
@@ -295,7 +295,7 @@ export async function getBalancesInsideTransaction(
]
>,
): Promise<BalancesResponse> {
- const balanceStore: BalancesStore = new BalancesStore(ws, tx);
+ const balanceStore: BalancesStore = new BalancesStore(wex, tx);
const keyRangeActive = GlobalIDB.KeyRange.bound(
OPERATION_STATUS_ACTIVE_FIRST,
@@ -428,11 +428,11 @@ export async function getBalancesInsideTransaction(
* Get detailed balance information, sliced by exchange and by currency.
*/
export async function getBalances(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
): Promise<BalancesResponse> {
logger.trace("starting to compute balance");
- const wbal = await ws.db.runReadWriteTx(
+ const wbal = await wex.db.runReadWriteTx(
[
"coinAvailability",
"coins",
@@ -446,7 +446,7 @@ export async function getBalances(
"withdrawalGroups",
],
async (tx) => {
- return getBalancesInsideTransaction(ws, tx);
+ return getBalancesInsideTransaction(wex, tx);
},
);
@@ -488,12 +488,12 @@ export interface AcceptableExchanges {
* Get all exchanges that are acceptable for a particular payment.
*/
export async function getAcceptableExchangeBaseUrls(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: MerchantPaymentRestrictionsForBalance,
): Promise<AcceptableExchanges> {
const acceptableExchangeUrls = new Set<string>();
const depositableExchangeUrls = new Set<string>();
- await ws.db.runReadOnlyTx(["exchanges", "exchangeDetails"], async (tx) => {
+ await wex.db.runReadOnlyTx(["exchanges", "exchangeDetails"], async (tx) => {
// FIXME: We should have a DB index to look up all exchanges
// for a particular auditor ...
@@ -600,10 +600,10 @@ export interface MerchantPaymentBalanceDetails {
}
export async function getMerchantPaymentBalanceDetails(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: MerchantPaymentRestrictionsForBalance,
): Promise<MerchantPaymentBalanceDetails> {
- const acceptability = await getAcceptableExchangeBaseUrls(ws, req);
+ const acceptability = await getAcceptableExchangeBaseUrls(wex, req);
const d: MerchantPaymentBalanceDetails = {
balanceAvailable: Amounts.zeroOfCurrency(req.currency),
@@ -613,7 +613,7 @@ export async function getMerchantPaymentBalanceDetails(
balanceMerchantDepositable: Amounts.zeroOfCurrency(req.currency),
};
- await ws.db.runReadOnlyTx(
+ await wex.db.runReadOnlyTx(
["coinAvailability", "refreshGroups"],
async (tx) => {
await tx.coinAvailability.iter().forEach((ca) => {
@@ -665,12 +665,12 @@ export async function getMerchantPaymentBalanceDetails(
}
export async function getBalanceDetail(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: GetBalanceDetailRequest,
): Promise<MerchantPaymentBalanceDetails> {
const exchanges: { exchangeBaseUrl: string; exchangePub: string }[] = [];
const wires = new Array<string>();
- await ws.db.runReadOnlyTx(["exchanges", "exchangeDetails"], async (tx) => {
+ await wex.db.runReadOnlyTx(["exchanges", "exchangeDetails"], async (tx) => {
const allExchanges = await tx.exchanges.iter().toArray();
for (const e of allExchanges) {
const details = await getExchangeWireDetailsInTx(tx, e.baseUrl);
@@ -690,7 +690,7 @@ export async function getBalanceDetail(
}
});
- return await getMerchantPaymentBalanceDetails(ws, {
+ return await getMerchantPaymentBalanceDetails(wex, {
currency: req.currency,
acceptedAuditors: [],
acceptedExchanges: exchanges,
@@ -717,7 +717,7 @@ export interface PeerPaymentBalanceDetails {
}
export async function getPeerPaymentBalanceDetailsInTx(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
tx: WalletDbReadOnlyTransaction<["coinAvailability", "refreshGroups"]>,
req: PeerPaymentRestrictionsForBalance,
): Promise<PeerPaymentBalanceDetails> {
diff --git a/packages/taler-wallet-core/src/coinSelection.ts b/packages/taler-wallet-core/src/coinSelection.ts
index e1ae613bc..680e5faa1 100644
--- a/packages/taler-wallet-core/src/coinSelection.ts
+++ b/packages/taler-wallet-core/src/coinSelection.ts
@@ -64,7 +64,11 @@ import { getAutoRefreshExecuteThreshold } from "./common.js";
import { DenominationRecord, WalletDbReadOnlyTransaction } from "./db.js";
import { isWithdrawableDenom } from "./denominations.js";
import { getExchangeWireDetailsInTx } from "./exchanges.js";
-import { getDenomInfo, InternalWalletState } from "./wallet.js";
+import {
+ getDenomInfo,
+ InternalWalletState,
+ WalletExecutionContext,
+} from "./wallet.js";
const logger = new Logger("coinSelection.ts");
@@ -247,7 +251,7 @@ export type SelectPayCoinsResult =
* This function is only exported for the sake of unit tests.
*/
export async function selectPayCoinsNew(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: SelectPayCoinRequestNg,
): Promise<SelectPayCoinsResult> {
const {
@@ -259,7 +263,7 @@ export async function selectPayCoinsNew(
// FIXME: Why don't we do this in a transaction?
const [candidateDenoms, wireFeesPerExchange] =
- await selectPayMerchantCandidates(ws, req);
+ await selectPayMerchantCandidates(wex, req);
const coinPubs: string[] = [];
const coinContributions: AmountJson[] = [];
@@ -312,7 +316,7 @@ export async function selectPayCoinsNew(
}
if (!selectedDenom) {
- const details = await getMerchantPaymentBalanceDetails(ws, {
+ const details = await getMerchantPaymentBalanceDetails(wex, {
acceptedAuditors: req.auditors,
acceptedExchanges: req.exchanges,
acceptedWireMethods: [req.wireMethod],
@@ -357,7 +361,7 @@ export async function selectPayCoinsNew(
logger.trace(`coin selection request ${j2s(req)}`);
logger.trace(`selected coins (via denoms) for payment: ${j2s(finalSel)}`);
- await ws.db.runReadOnlyTx(["coins", "denominations"], async (tx) => {
+ await wex.db.runReadOnlyTx(["coins", "denominations"], async (tx) => {
for (const dph of Object.keys(finalSel)) {
const selInfo = finalSel[dph];
const numRequested = selInfo.contributions.length;
@@ -594,10 +598,10 @@ export type AvailableDenom = DenominationInfo & {
};
async function selectPayMerchantCandidates(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: SelectPayCoinRequestNg,
): Promise<[AvailableDenom[], Record<string, AmountJson>]> {
- return await ws.db.runReadOnlyTx(
+ return await wex.db.runReadOnlyTx(
["exchanges", "exchangeDetails", "denominations", "coinAvailability"],
async (tx) => {
// FIXME: Use the existing helper (from balance.ts) to
@@ -906,7 +910,7 @@ export interface PeerCoinSelectionRequest {
* Get coin availability information for a certain exchange.
*/
async function selectPayPeerCandidatesForExchange(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
tx: WalletDbReadOnlyTransaction<["coinAvailability", "denominations"]>,
exchangeBaseUrl: string,
): Promise<AvailableDenom[]> {
@@ -1035,7 +1039,7 @@ function greedySelectPeer(
}
export async function selectPeerCoins(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: PeerCoinSelectionRequest,
): Promise<SelectPeerCoinsResult> {
const instructedAmount = req.instructedAmount;
@@ -1044,7 +1048,7 @@ export async function selectPeerCoins(
// one coin to spend.
throw new Error("amount of zero not allowed");
}
- return await ws.db.runReadWriteTx(
+ return await wex.db.runReadWriteTx(
[
"exchanges",
"contractTerms",
@@ -1063,7 +1067,7 @@ export async function selectPeerCoins(
continue;
}
const candidates = await selectPayPeerCandidatesForExchange(
- ws,
+ wex,
tx,
exch.baseUrl,
);
@@ -1089,7 +1093,7 @@ export async function selectPeerCoins(
throw Error("repair not possible, coin not found");
}
const denom = await getDenomInfo(
- ws,
+ wex,
tx,
coin.exchangeBaseUrl,
coin.denomPubHash,
@@ -1188,7 +1192,7 @@ export async function selectPeerCoins(
// We were unable to select coins.
// Now we need to produce error details.
- const infoGeneral = await getPeerPaymentBalanceDetailsInTx(ws, tx, {
+ const infoGeneral = await getPeerPaymentBalanceDetailsInTx(wex, tx, {
currency,
});
@@ -1200,7 +1204,7 @@ export async function selectPeerCoins(
if (exch.detailsPointer?.currency !== currency) {
continue;
}
- const infoExchange = await getPeerPaymentBalanceDetailsInTx(ws, tx, {
+ const infoExchange = await getPeerPaymentBalanceDetailsInTx(wex, tx, {
currency,
restrictExchangeTo: exch.baseUrl,
});
diff --git a/packages/taler-wallet-core/src/common.ts b/packages/taler-wallet-core/src/common.ts
index 08adb2515..5acdeeba4 100644
--- a/packages/taler-wallet-core/src/common.ts
+++ b/packages/taler-wallet-core/src/common.ts
@@ -61,7 +61,11 @@ import {
timestampPreciseToDb,
} from "./db.js";
import { createRefreshGroup } from "./refresh.js";
-import { InternalWalletState, getDenomInfo } from "./wallet.js";
+import {
+ InternalWalletState,
+ WalletExecutionContext,
+ getDenomInfo,
+} from "./wallet.js";
const logger = new Logger("operations/common.ts");
@@ -76,7 +80,7 @@ export interface CoinsSpendInfo {
}
export async function makeCoinsVisible(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
tx: WalletDbReadWriteTransaction<["coins", "coinAvailability"]>,
transactionId: string,
): Promise<void> {
@@ -104,7 +108,7 @@ export async function makeCoinsVisible(
}
export async function makeCoinAvailable(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
tx: WalletDbReadWriteTransaction<
["coins", "coinAvailability", "denominations"]
>,
@@ -143,7 +147,7 @@ export async function makeCoinAvailable(
}
export async function spendCoins(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
tx: WalletDbReadWriteTransaction<
["coins", "coinAvailability", "refreshGroups", "denominations"]
>,
@@ -162,7 +166,7 @@ export async function spendCoins(
throw Error("coin allocated for payment doesn't exist anymore");
}
const denom = await getDenomInfo(
- ws,
+ wex,
tx,
coin.exchangeBaseUrl,
coin.denomPubHash,
@@ -224,7 +228,7 @@ export async function spendCoins(
}
await createRefreshGroup(
- ws,
+ wex,
tx,
Amounts.currencyOf(csi.contributions[0]),
refreshCoinPubs,
diff --git a/packages/taler-wallet-core/src/deposits.ts b/packages/taler-wallet-core/src/deposits.ts
index 9db8cfc27..3abb614bd 100644
--- a/packages/taler-wallet-core/src/deposits.ts
+++ b/packages/taler-wallet-core/src/deposits.ts
@@ -109,7 +109,11 @@ import {
notifyTransition,
parseTransactionIdentifier,
} from "./transactions.js";
-import { InternalWalletState, getDenomInfo } from "./wallet.js";
+import {
+ InternalWalletState,
+ WalletExecutionContext,
+ getDenomInfo,
+} from "./wallet.js";
import { getCandidateWithdrawalDenomsTx } from "./withdraw.js";
/**
@@ -122,7 +126,7 @@ export class DepositTransactionContext implements TransactionContext {
readonly taskId: TaskIdStr;
constructor(
- public ws: InternalWalletState,
+ public wex: WalletExecutionContext,
public depositGroupId: string,
) {
this.transactionId = constructTransactionIdentifier({
@@ -137,7 +141,7 @@ export class DepositTransactionContext implements TransactionContext {
async deleteTransaction(): Promise<void> {
const depositGroupId = this.depositGroupId;
- const ws = this.ws;
+ const ws = this.wex;
// FIXME: We should check first if we are in a final state
// where deletion is allowed.
await ws.db.runReadWriteTx(["depositGroups", "tombstones"], async (tx) => {
@@ -153,8 +157,8 @@ export class DepositTransactionContext implements TransactionContext {
}
async suspendTransaction(): Promise<void> {
- const { ws, depositGroupId, transactionId, taskId: retryTag } = this;
- const transitionInfo = await ws.db.runReadWriteTx(
+ const { wex, depositGroupId, transactionId, taskId: retryTag } = this;
+ const transitionInfo = await wex.db.runReadWriteTx(
["depositGroups"],
async (tx) => {
const dg = await tx.depositGroups.get(depositGroupId);
@@ -191,13 +195,13 @@ export class DepositTransactionContext implements TransactionContext {
};
},
);
- ws.taskScheduler.stopShepherdTask(retryTag);
- notifyTransition(ws, transactionId, transitionInfo);
+ wex.taskScheduler.stopShepherdTask(retryTag);
+ notifyTransition(wex, transactionId, transitionInfo);
}
async abortTransaction(): Promise<void> {
- const { ws, depositGroupId, transactionId, taskId: retryTag } = this;
- const transitionInfo = await ws.db.runReadWriteTx(
+ const { wex, depositGroupId, transactionId, taskId: retryTag } = this;
+ const transitionInfo = await wex.db.runReadWriteTx(
["depositGroups"],
async (tx) => {
const dg = await tx.depositGroups.get(depositGroupId);
@@ -224,17 +228,17 @@ export class DepositTransactionContext implements TransactionContext {
return undefined;
},
);
- ws.taskScheduler.stopShepherdTask(retryTag);
- notifyTransition(ws, transactionId, transitionInfo);
- ws.taskScheduler.startShepherdTask(retryTag);
- ws.notify({
+ wex.taskScheduler.stopShepherdTask(retryTag);
+ notifyTransition(wex, transactionId, transitionInfo);
+ wex.taskScheduler.startShepherdTask(retryTag);
+ wex.ws.notify({
type: NotificationType.BalanceChange,
hintTransactionId: transactionId,
});
}
async resumeTransaction(): Promise<void> {
- const { ws, depositGroupId, transactionId, taskId: retryTag } = this;
+ const { wex: ws, depositGroupId, transactionId, taskId: retryTag } = this;
const transitionInfo = await ws.db.runReadWriteTx(
["depositGroups"],
async (tx) => {
@@ -277,8 +281,8 @@ export class DepositTransactionContext implements TransactionContext {
}
async failTransaction(): Promise<void> {
- const { ws, depositGroupId, transactionId, taskId: retryTag } = this;
- const transitionInfo = await ws.db.runReadWriteTx(
+ const { wex, depositGroupId, transactionId, taskId } = this;
+ const transitionInfo = await wex.db.runReadWriteTx(
["depositGroups"],
async (tx) => {
const dg = await tx.depositGroups.get(depositGroupId);
@@ -303,9 +307,9 @@ export class DepositTransactionContext implements TransactionContext {
return undefined;
},
);
- ws.taskScheduler.stopShepherdTask(retryTag);
- notifyTransition(ws, transactionId, transitionInfo);
- ws.notify({
+ wex.taskScheduler.stopShepherdTask(taskId);
+ notifyTransition(wex, transactionId, transitionInfo);
+ wex.ws.notify({
type: NotificationType.BalanceChange,
hintTransactionId: transactionId,
});
@@ -410,9 +414,8 @@ export function computeDepositTransactionActions(
}
async function refundDepositGroup(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
depositGroup: DepositGroupRecord,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const newTxPerCoin = [...depositGroup.statusPerCoin];
logger.info(`status per coin: ${j2s(depositGroup.statusPerCoin)}`);
@@ -424,7 +427,7 @@ async function refundDepositGroup(
break;
default: {
const coinPub = depositGroup.payCoinSelection.coinPubs[i];
- const coinExchange = await ws.db.runReadOnlyTx(
+ const coinExchange = await wex.db.runReadOnlyTx(
["coins"],
async (tx) => {
const coinRecord = await tx.coins.get(coinPub);
@@ -436,7 +439,7 @@ async function refundDepositGroup(
// We use a constant refund transaction ID, since there can
// only be one refund.
const rtid = 1;
- const sig = await ws.cryptoApi.signRefund({
+ const sig = await wex.cryptoApi.signRefund({
coinPub,
contractTermsHash: depositGroup.contractTermsHash,
merchantPriv: depositGroup.merchantPriv,
@@ -452,10 +455,10 @@ async function refundDepositGroup(
rtransaction_id: rtid,
};
const refundUrl = new URL(`coins/${coinPub}/refund`, coinExchange);
- const httpResp = await ws.http.fetch(refundUrl.href, {
+ const httpResp = await wex.http.fetch(refundUrl.href, {
method: "POST",
body: refundReq,
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
logger.info(
`coin ${i} refund HTTP status for coin: ${httpResp.status}`,
@@ -486,7 +489,7 @@ async function refundDepositGroup(
const currency = Amounts.currencyOf(depositGroup.totalPayCost);
- const res = await ws.db.runReadWriteTx(
+ const res = await wex.db.runReadWriteTx(
[
"depositGroups",
"refreshGroups",
@@ -510,7 +513,7 @@ async function refundDepositGroup(
let refreshRes: CreateRefreshGroupResult | undefined = undefined;
if (isDone) {
refreshRes = await createRefreshGroup(
- ws,
+ wex,
tx,
currency,
refreshCoins,
@@ -529,7 +532,7 @@ async function refundDepositGroup(
if (res?.refreshRes) {
for (const notif of res.refreshRes.notifications) {
- ws.notify(notif);
+ wex.ws.notify(notif);
}
}
@@ -550,7 +553,7 @@ async function refundDepositGroup(
* transaction of processDepositGroup?
*/
async function waitForRefreshOnDepositGroup(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
depositGroup: DepositGroupRecord,
): Promise<TaskRunResult> {
const abortRefreshGroupId = depositGroup.abortRefreshGroupId;
@@ -559,7 +562,7 @@ async function waitForRefreshOnDepositGroup(
tag: TransactionType.Deposit,
depositGroupId: depositGroup.depositGroupId,
});
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["depositGroups", "refreshGroups"],
async (tx) => {
const refreshGroup = await tx.refreshGroups.get(abortRefreshGroupId);
@@ -593,8 +596,8 @@ async function waitForRefreshOnDepositGroup(
},
);
- notifyTransition(ws, transactionId, transitionInfo);
- ws.notify({
+ notifyTransition(wex, transactionId, transitionInfo);
+ wex.ws.notify({
type: NotificationType.BalanceChange,
hintTransactionId: transactionId,
});
@@ -602,24 +605,22 @@ async function waitForRefreshOnDepositGroup(
}
async function processDepositGroupAborting(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
depositGroup: DepositGroupRecord,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
logger.info("processing deposit tx in 'aborting'");
const abortRefreshGroupId = depositGroup.abortRefreshGroupId;
if (!abortRefreshGroupId) {
logger.info("refunding deposit group");
- return refundDepositGroup(ws, depositGroup, cancellationToken);
+ return refundDepositGroup(wex, depositGroup);
}
logger.info("waiting for refresh");
- return waitForRefreshOnDepositGroup(ws, depositGroup);
+ return waitForRefreshOnDepositGroup(wex, depositGroup);
}
async function processDepositGroupPendingKyc(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
depositGroup: DepositGroupRecord,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const { depositGroupId } = depositGroup;
const transactionId = constructTransactionIdentifier({
@@ -640,9 +641,9 @@ async function processDepositGroupPendingKyc(
);
url.searchParams.set("timeout_ms", "10000");
logger.info(`kyc url ${url.href}`);
- const kycStatusRes = await ws.http.fetch(url.href, {
+ const kycStatusRes = await wex.http.fetch(url.href, {
method: "GET",
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
if (
kycStatusRes.status === HttpStatusCode.Ok ||
@@ -650,7 +651,7 @@ async function processDepositGroupPendingKyc(
// remove after the exchange is fixed or clarified
kycStatusRes.status === HttpStatusCode.NoContent
) {
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["depositGroups"],
async (tx) => {
const newDg = await tx.depositGroups.get(depositGroupId);
@@ -667,7 +668,7 @@ async function processDepositGroupPendingKyc(
return { oldTxState, newTxState };
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
} else if (kycStatusRes.status === HttpStatusCode.Accepted) {
// FIXME: Do we have to update the URL here?
} else {
@@ -682,7 +683,7 @@ async function processDepositGroupPendingKyc(
* and transition the transaction to the KYC required state.
*/
async function transitionToKycRequired(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
depositGroup: DepositGroupRecord,
kycInfo: KycPendingInfo,
exchangeUrl: string,
@@ -700,7 +701,7 @@ async function transitionToKycRequired(
exchangeUrl,
);
logger.info(`kyc url ${url.href}`);
- const kycStatusReq = await ws.http.fetch(url.href, {
+ const kycStatusReq = await wex.http.fetch(url.href, {
method: "GET",
});
if (kycStatusReq.status === HttpStatusCode.Ok) {
@@ -709,7 +710,7 @@ async function transitionToKycRequired(
} else if (kycStatusReq.status === HttpStatusCode.Accepted) {
const kycStatus = await kycStatusReq.json();
logger.info(`kyc status: ${j2s(kycStatus)}`);
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["depositGroups"],
async (tx) => {
const dg = await tx.depositGroups.get(depositGroupId);
@@ -731,7 +732,7 @@ async function transitionToKycRequired(
return { oldTxState, newTxState };
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
return TaskRunResult.finished();
} else {
throw Error(`unexpected response from kyc-check (${kycStatusReq.status})`);
@@ -739,15 +740,14 @@ async function transitionToKycRequired(
}
async function processDepositGroupPendingTrack(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
depositGroup: DepositGroupRecord,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const { depositGroupId } = depositGroup;
for (let i = 0; i < depositGroup.statusPerCoin.length; i++) {
const coinPub = depositGroup.payCoinSelection.coinPubs[i];
// FIXME: Make the URL part of the coin selection?
- const exchangeBaseUrl = await ws.db.runReadWriteTx(
+ const exchangeBaseUrl = await wex.db.runReadWriteTx(
["coins"],
async (tx) => {
const coinRecord = await tx.coins.get(coinPub);
@@ -766,11 +766,10 @@ async function processDepositGroupPendingTrack(
if (depositGroup.statusPerCoin[i] !== DepositElementStatus.Wired) {
const track = await trackDeposit(
- ws,
+ wex,
depositGroup,
coinPub,
exchangeBaseUrl,
- cancellationToken,
);
if (track.type === "accepted") {
@@ -784,7 +783,7 @@ async function processDepositGroupPendingTrack(
requirementRow,
};
return transitionToKycRequired(
- ws,
+ wex,
depositGroup,
kycInfo,
exchangeBaseUrl,
@@ -801,7 +800,7 @@ async function processDepositGroupPendingTrack(
}
const fee = await getExchangeWireFee(
- ws,
+ wex,
payto.targetType,
exchangeBaseUrl,
track.execution_time,
@@ -825,7 +824,7 @@ async function processDepositGroupPendingTrack(
}
if (updatedTxStatus !== undefined) {
- await ws.db.runReadWriteTx(["depositGroups"], async (tx) => {
+ await wex.db.runReadWriteTx(["depositGroups"], async (tx) => {
const dg = await tx.depositGroups.get(depositGroupId);
if (!dg) {
return;
@@ -855,7 +854,7 @@ async function processDepositGroupPendingTrack(
let allWired = true;
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["depositGroups"],
async (tx) => {
const dg = await tx.depositGroups.get(depositGroupId);
@@ -884,9 +883,9 @@ async function processDepositGroupPendingTrack(
tag: TransactionType.Deposit,
depositGroupId,
});
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
if (allWired) {
- ws.notify({
+ wex.ws.notify({
type: NotificationType.BalanceChange,
hintTransactionId: transactionId,
});
@@ -899,13 +898,13 @@ async function processDepositGroupPendingTrack(
}
async function processDepositGroupPendingDeposit(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
depositGroup: DepositGroupRecord,
cancellationToken?: CancellationToken,
): Promise<TaskRunResult> {
logger.info("processing deposit group in pending(deposit)");
const depositGroupId = depositGroup.depositGroupId;
- const contractTermsRec = await ws.db.runReadOnlyTx(
+ const contractTermsRec = await wex.db.runReadOnlyTx(
["contractTerms"],
async (tx) => {
return tx.contractTerms.get(depositGroup.contractTermsHash);
@@ -932,7 +931,7 @@ async function processDepositGroupPendingDeposit(
// FIXME: Cache these!
const depositPermissions = await generateDepositPermissions(
- ws,
+ wex,
depositGroup.payCoinSelection,
contractData,
);
@@ -981,7 +980,7 @@ async function processDepositGroupPendingDeposit(
const url = new URL(`batch-deposit`, exchangeUrl);
logger.info(`depositing to ${url.href}`);
logger.trace(`deposit request: ${j2s(batchReq)}`);
- const httpResp = await ws.http.fetch(url.href, {
+ const httpResp = await wex.http.fetch(url.href, {
method: "POST",
body: batchReq,
cancellationToken: cancellationToken,
@@ -991,7 +990,7 @@ async function processDepositGroupPendingDeposit(
codecForBatchDepositSuccess(),
);
- await ws.db.runReadWriteTx(["depositGroups"], async (tx) => {
+ await wex.db.runReadWriteTx(["depositGroups"], async (tx) => {
const dg = await tx.depositGroups.get(depositGroupId);
if (!dg) {
return;
@@ -1007,7 +1006,7 @@ async function processDepositGroupPendingDeposit(
});
}
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["depositGroups"],
async (tx) => {
const dg = await tx.depositGroups.get(depositGroupId);
@@ -1022,7 +1021,7 @@ async function processDepositGroupPendingDeposit(
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
return TaskRunResult.progress();
}
@@ -1030,11 +1029,10 @@ async function processDepositGroupPendingDeposit(
* Process a deposit group that is not in its final state yet.
*/
export async function processDepositGroup(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
depositGroupId: string,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
- const depositGroup = await ws.db.runReadOnlyTx(
+ const depositGroup = await wex.db.runReadOnlyTx(
["depositGroups"],
async (tx) => {
return tx.depositGroups.get(depositGroupId);
@@ -1047,21 +1045,13 @@ export async function processDepositGroup(
switch (depositGroup.operationStatus) {
case DepositOperationStatus.PendingTrack:
- return processDepositGroupPendingTrack(
- ws,
- depositGroup,
- cancellationToken,
- );
+ return processDepositGroupPendingTrack(wex, depositGroup);
case DepositOperationStatus.PendingKyc:
- return processDepositGroupPendingKyc(ws, depositGroup, cancellationToken);
+ return processDepositGroupPendingKyc(wex, depositGroup);
case DepositOperationStatus.PendingDeposit:
- return processDepositGroupPendingDeposit(
- ws,
- depositGroup,
- cancellationToken,
- );
+ return processDepositGroupPendingDeposit(wex, depositGroup);
case DepositOperationStatus.Aborting:
- return processDepositGroupAborting(ws, depositGroup, cancellationToken);
+ return processDepositGroupAborting(wex, depositGroup);
}
return TaskRunResult.finished();
@@ -1071,12 +1061,12 @@ export async function processDepositGroup(
* FIXME: Consider moving this to exchanges.ts.
*/
async function getExchangeWireFee(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
wireType: string,
baseUrl: string,
time: TalerProtocolTimestamp,
): Promise<WireFee> {
- const exchangeDetails = await ws.db.runReadOnlyTx(
+ const exchangeDetails = await wex.db.runReadOnlyTx(
["exchangeDetails", "exchanges"],
async (tx) => {
const ex = await tx.exchanges.get(baseUrl);
@@ -1116,11 +1106,10 @@ async function getExchangeWireFee(
}
async function trackDeposit(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
depositGroup: DepositGroupRecord,
coinPub: string,
exchangeUrl: string,
- cancellationToken: CancellationToken,
): Promise<TrackTransaction> {
const wireHash = hashWire(
depositGroup.wire.payto_uri,
@@ -1131,7 +1120,7 @@ async function trackDeposit(
`deposits/${wireHash}/${depositGroup.merchantPub}/${depositGroup.contractTermsHash}/${coinPub}`,
exchangeUrl,
);
- const sigResp = await ws.cryptoApi.signTrackTransaction({
+ const sigResp = await wex.cryptoApi.signTrackTransaction({
coinPub,
contractTermsHash: depositGroup.contractTermsHash,
merchantPriv: depositGroup.merchantPriv,
@@ -1141,9 +1130,9 @@ async function trackDeposit(
url.searchParams.set("merchant_sig", sigResp.sig);
// Not doing long-polling yet as it looks like it's broken in the exchange (2024-02-20)
// url.searchParams.set("timeout_ms", "30000");
- const httpResp = await ws.http.fetch(url.href, {
+ const httpResp = await wex.http.fetch(url.href, {
method: "GET",
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
logger.trace(`deposits response status: ${httpResp.status}`);
switch (httpResp.status) {
@@ -1177,7 +1166,7 @@ async function trackDeposit(
* as it doesn't prepare anything
*/
export async function prepareDepositGroup(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: PrepareDepositRequest,
): Promise<PrepareDepositResponse> {
const p = parsePaytoUri(req.depositPaytoUri);
@@ -1188,7 +1177,7 @@ export async function prepareDepositGroup(
const exchangeInfos: { url: string; master_pub: string }[] = [];
- await ws.db.runReadOnlyTx(["exchangeDetails", "exchanges"], async (tx) => {
+ await wex.db.runReadOnlyTx(["exchangeDetails", "exchanges"], async (tx) => {
const allExchanges = await tx.exchanges.iter().toArray();
for (const e of allExchanges) {
const details = await getExchangeWireDetailsInTx(tx, e.baseUrl);
@@ -1227,7 +1216,7 @@ export async function prepareDepositGroup(
refund_deadline: TalerProtocolTimestamp.zero(),
};
- const { h: contractTermsHash } = await ws.cryptoApi.hashString({
+ const { h: contractTermsHash } = await wex.cryptoApi.hashString({
str: canonicalJson(contractTerms),
});
@@ -1237,7 +1226,7 @@ export async function prepareDepositGroup(
"",
);
- const payCoinSel = await selectPayCoinsNew(ws, {
+ const payCoinSel = await selectPayCoinsNew(wex, {
auditors: [],
exchanges: contractData.allowedExchanges,
wireMethod: contractData.wireMethod,
@@ -1257,16 +1246,16 @@ export async function prepareDepositGroup(
);
}
- const totalDepositCost = await getTotalPaymentCost(ws, payCoinSel.coinSel);
+ const totalDepositCost = await getTotalPaymentCost(wex, payCoinSel.coinSel);
const effectiveDepositAmount = await getCounterpartyEffectiveDepositAmount(
- ws,
+ wex,
p.targetType,
payCoinSel.coinSel,
);
const fees = await getTotalFeesForDepositAmount(
- ws,
+ wex,
p.targetType,
amount,
payCoinSel.coinSel,
@@ -1288,7 +1277,7 @@ export function generateDepositGroupTxId(): string {
}
export async function createDepositGroup(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: CreateDepositGroupRequest,
): Promise<CreateDepositGroupResponse> {
const p = parsePaytoUri(req.depositPaytoUri);
@@ -1300,7 +1289,7 @@ export async function createDepositGroup(
const exchangeInfos: { url: string; master_pub: string }[] = [];
- await ws.db.runReadOnlyTx(["exchanges", "exchangeDetails"], async (tx) => {
+ await wex.db.runReadOnlyTx(["exchanges", "exchangeDetails"], async (tx) => {
const allExchanges = await tx.exchanges.iter().toArray();
for (const e of allExchanges) {
const details = await getExchangeWireDetailsInTx(tx, e.baseUrl);
@@ -1319,8 +1308,8 @@ export async function createDepositGroup(
AbsoluteTime.addDuration(now, Duration.fromSpec({ minutes: 5 })),
);
const nowRounded = AbsoluteTime.toProtocolTimestamp(now);
- const noncePair = await ws.cryptoApi.createEddsaKeypair({});
- const merchantPair = await ws.cryptoApi.createEddsaKeypair({});
+ const noncePair = await wex.cryptoApi.createEddsaKeypair({});
+ const merchantPair = await wex.cryptoApi.createEddsaKeypair({});
const wireSalt = encodeCrock(getRandomBytes(16));
const wireHash = hashWire(req.depositPaytoUri, wireSalt);
const contractTerms: MerchantContractTerms = {
@@ -1346,7 +1335,7 @@ export async function createDepositGroup(
refund_deadline: TalerProtocolTimestamp.zero(),
};
- const { h: contractTermsHash } = await ws.cryptoApi.hashString({
+ const { h: contractTermsHash } = await wex.cryptoApi.hashString({
str: canonicalJson(contractTerms),
});
@@ -1356,7 +1345,7 @@ export async function createDepositGroup(
"",
);
- const payCoinSel = await selectPayCoinsNew(ws, {
+ const payCoinSel = await selectPayCoinsNew(wex, {
auditors: [],
exchanges: contractData.allowedExchanges,
wireMethod: contractData.wireMethod,
@@ -1376,7 +1365,7 @@ export async function createDepositGroup(
);
}
- const totalDepositCost = await getTotalPaymentCost(ws, payCoinSel.coinSel);
+ const totalDepositCost = await getTotalPaymentCost(wex, payCoinSel.coinSel);
let depositGroupId: string;
if (req.transactionId) {
@@ -1391,7 +1380,7 @@ export async function createDepositGroup(
const infoPerExchange: Record<string, DepositInfoPerExchange> = {};
- await ws.db.runReadOnlyTx(["coins"], async (tx) => {
+ await wex.db.runReadOnlyTx(["coins"], async (tx) => {
for (let i = 0; i < payCoinSel.coinSel.coinPubs.length; i++) {
const coin = await tx.coins.get(payCoinSel.coinSel.coinPubs[i]);
if (!coin) {
@@ -1415,7 +1404,7 @@ export async function createDepositGroup(
const counterpartyEffectiveDepositAmount =
await getCounterpartyEffectiveDepositAmount(
- ws,
+ wex,
p.targetType,
payCoinSel.coinSel,
);
@@ -1453,10 +1442,10 @@ export async function createDepositGroup(
infoPerExchange,
};
- const ctx = new DepositTransactionContext(ws, depositGroupId);
+ const ctx = new DepositTransactionContext(wex, depositGroupId);
const transactionId = ctx.transactionId;
- const newTxState = await ws.db.runReadWriteTx(
+ const newTxState = await wex.db.runReadWriteTx(
[
"depositGroups",
"coins",
@@ -1467,7 +1456,7 @@ export async function createDepositGroup(
"contractTerms",
],
async (tx) => {
- await spendCoins(ws, tx, {
+ await spendCoins(wex, tx, {
allocationId: transactionId,
coinPubs: payCoinSel.coinSel.coinPubs,
contributions: payCoinSel.coinSel.coinContributions.map((x) =>
@@ -1484,7 +1473,7 @@ export async function createDepositGroup(
},
);
- ws.notify({
+ wex.ws.notify({
type: NotificationType.TransactionStateTransition,
transactionId,
oldTxState: {
@@ -1493,12 +1482,12 @@ export async function createDepositGroup(
newTxState,
});
- ws.notify({
+ wex.ws.notify({
type: NotificationType.BalanceChange,
hintTransactionId: transactionId,
});
- ws.taskScheduler.startShepherdTask(ctx.taskId);
+ wex.taskScheduler.startShepherdTask(ctx.taskId);
return {
depositGroupId,
@@ -1511,7 +1500,7 @@ export async function createDepositGroup(
* account after depositing, not considering aggregation.
*/
export async function getCounterpartyEffectiveDepositAmount(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
wireType: string,
pcs: PayCoinSelection,
): Promise<AmountJson> {
@@ -1519,7 +1508,7 @@ export async function getCounterpartyEffectiveDepositAmount(
const fees: AmountJson[] = [];
const exchangeSet: Set<string> = new Set();
- await ws.db.runReadOnlyTx(
+ await wex.db.runReadOnlyTx(
["coins", "denominations", "exchangeDetails", "exchanges"],
async (tx) => {
for (let i = 0; i < pcs.coinPubs.length; i++) {
@@ -1528,7 +1517,7 @@ export async function getCounterpartyEffectiveDepositAmount(
throw Error("can't calculate deposit amount, coin not found");
}
const denom = await getDenomInfo(
- ws,
+ wex,
tx,
coin.exchangeBaseUrl,
coin.denomPubHash,
@@ -1574,7 +1563,7 @@ export async function getCounterpartyEffectiveDepositAmount(
* specified amount using the selected coins and the wire method.
*/
async function getTotalFeesForDepositAmount(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
wireType: string,
total: AmountJson,
pcs: PayCoinSelection,
@@ -1585,7 +1574,7 @@ async function getTotalFeesForDepositAmount(
const exchangeSet: Set<string> = new Set();
const currency = Amounts.currencyOf(total);
- await ws.db.runReadOnlyTx(
+ await wex.db.runReadOnlyTx(
["coins", "denominations", "exchanges", "exchangeDetails"],
async (tx) => {
for (let i = 0; i < pcs.coinPubs.length; i++) {
@@ -1594,7 +1583,7 @@ async function getTotalFeesForDepositAmount(
throw Error("can't calculate deposit amount, coin not found");
}
const denom = await getDenomInfo(
- ws,
+ wex,
tx,
coin.exchangeBaseUrl,
coin.denomPubHash,
@@ -1606,7 +1595,7 @@ async function getTotalFeesForDepositAmount(
exchangeSet.add(coin.exchangeBaseUrl);
const allDenoms = await getCandidateWithdrawalDenomsTx(
- ws,
+ wex,
tx,
coin.exchangeBaseUrl,
currency,
@@ -1619,7 +1608,7 @@ async function getTotalFeesForDepositAmount(
allDenoms,
denom,
amountLeft,
- ws.config.testing.denomselAllowLate,
+ wex.ws.config.testing.denomselAllowLate,
);
refreshFee.push(refreshCost);
}
diff --git a/packages/taler-wallet-core/src/dev-experiments.ts b/packages/taler-wallet-core/src/dev-experiments.ts
index b48aa716b..c94571ff8 100644
--- a/packages/taler-wallet-core/src/dev-experiments.ts
+++ b/packages/taler-wallet-core/src/dev-experiments.ts
@@ -43,7 +43,7 @@ import {
RefreshOperationStatus,
timestampPreciseToDb,
} from "./db.js";
-import { InternalWalletState } from "./wallet.js";
+import { WalletExecutionContext } from "./wallet.js";
const logger = new Logger("dev-experiments.ts");
@@ -51,7 +51,7 @@ const logger = new Logger("dev-experiments.ts");
* Apply a dev experiment to the wallet database / state.
*/
export async function applyDevExperiment(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
uri: string,
): Promise<void> {
logger.info(`applying dev experiment ${uri}`);
@@ -60,14 +60,14 @@ export async function applyDevExperiment(
logger.info("unable to parse dev experiment URI");
return;
}
- if (!ws.config.testing.devModeActive) {
+ if (!wex.ws.config.testing.devModeActive) {
throw Error(
"can't handle devmode URI (other than enable-devmode) unless devmode is active",
);
}
if (parsedUri.devExperimentId == "insert-pending-refresh") {
- await ws.db.runReadWriteTx(["refreshGroups"], async (tx) => {
+ await wex.db.runReadWriteTx(["refreshGroups"], async (tx) => {
const refreshGroupId = encodeCrock(getRandomBytes(32));
const newRg: RefreshGroupRecord = {
currency: "TESTKUDOS",
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) {
diff --git a/packages/taler-wallet-core/src/instructedAmountConversion.ts b/packages/taler-wallet-core/src/instructedAmountConversion.ts
index 2250188b7..ccad050bf 100644
--- a/packages/taler-wallet-core/src/instructedAmountConversion.ts
+++ b/packages/taler-wallet-core/src/instructedAmountConversion.ts
@@ -34,7 +34,7 @@ import {
import { CoinInfo } from "./coinSelection.js";
import { DenominationRecord, timestampProtocolFromDb } from "./db.js";
import { getExchangeWireDetailsInTx } from "./exchanges.js";
-import { InternalWalletState } from "./wallet.js";
+import { InternalWalletState, WalletExecutionContext } from "./wallet.js";
/**
* If the operation going to be plan subtracts
@@ -129,14 +129,14 @@ interface AvailableCoins {
* of being cached
*/
async function getAvailableDenoms(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
op: TransactionType,
currency: string,
filters: CoinsFilter = {},
): Promise<AvailableCoins> {
const operationType = getOperationType(TransactionType.Deposit);
- return await ws.db.runReadOnlyTx(
+ return await wex.db.runReadOnlyTx(
["exchanges", "exchangeDetails", "denominations", "coinAvailability"],
async (tx) => {
const list: CoinInfo[] = [];
@@ -328,14 +328,14 @@ function buildCoinInfoFromDenom(
}
export async function convertDepositAmount(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: ConvertAmountRequest,
): Promise<AmountResponse> {
const amount = Amounts.parseOrThrow(req.amount);
// const filter = getCoinsFilter(req);
const denoms = await getAvailableDenoms(
- ws,
+ wex,
TransactionType.Deposit,
amount.currency,
{},
@@ -430,13 +430,13 @@ export function convertDepositAmountForAvailableCoins(
}
export async function getMaxDepositAmount(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: GetAmountRequest,
): Promise<AmountResponse> {
// const filter = getCoinsFilter(req);
const denoms = await getAvailableDenoms(
- ws,
+ wex,
TransactionType.Deposit,
req.currency,
{},
@@ -473,25 +473,27 @@ export function getMaxDepositAmountForAvailableCoins(
}
export async function convertPeerPushAmount(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: ConvertAmountRequest,
): Promise<AmountResponse> {
throw Error("to be implemented after 1.0");
}
+
export async function getMaxPeerPushAmount(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: GetAmountRequest,
): Promise<AmountResponse> {
throw Error("to be implemented after 1.0");
}
+
export async function convertWithdrawalAmount(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: ConvertAmountRequest,
): Promise<AmountResponse> {
const amount = Amounts.parseOrThrow(req.amount);
const denoms = await getAvailableDenoms(
- ws,
+ wex,
TransactionType.Withdrawal,
amount.currency,
{},
diff --git a/packages/taler-wallet-core/src/pay-merchant.ts b/packages/taler-wallet-core/src/pay-merchant.ts
index 73dc59ba2..a576930ba 100644
--- a/packages/taler-wallet-core/src/pay-merchant.ts
+++ b/packages/taler-wallet-core/src/pay-merchant.ts
@@ -33,7 +33,6 @@ import {
AmountString,
assertUnreachable,
AsyncFlag,
- CancellationToken,
checkDbInvariant,
codecForAbortResponse,
codecForMerchantContractTerms,
@@ -142,6 +141,7 @@ import {
EXCHANGE_COINS_LOCK,
getDenomInfo,
InternalWalletState,
+ WalletExecutionContext,
} from "./wallet.js";
import { getCandidateWithdrawalDenomsTx } from "./withdraw.js";
@@ -155,7 +155,7 @@ export class PayMerchantTransactionContext implements TransactionContext {
readonly taskId: TaskIdStr;
constructor(
- public ws: InternalWalletState,
+ public wex: WalletExecutionContext,
public proposalId: string,
) {
this.transactionId = constructTransactionIdentifier({
@@ -198,7 +198,7 @@ export class PayMerchantTransactionContext implements TransactionContext {
>,
) => Promise<TransitionResult>,
): Promise<void> {
- const ws = this.ws;
+ const ws = this.wex;
const extraStores = opts.extraStores ?? [];
const transitionInfo = await ws.db.runReadWriteTx(
["purchases", ...extraStores],
@@ -227,7 +227,7 @@ export class PayMerchantTransactionContext implements TransactionContext {
}
async deleteTransaction(): Promise<void> {
- const { ws, proposalId } = this;
+ const { wex: ws, proposalId } = this;
await ws.db.runReadWriteTx(["purchases", "tombstones"], async (tx) => {
let found = false;
const purchase = await tx.purchases.get(proposalId);
@@ -244,7 +244,7 @@ export class PayMerchantTransactionContext implements TransactionContext {
}
async suspendTransaction(): Promise<void> {
- const { ws, proposalId, transactionId } = this;
+ const { wex: ws, proposalId, transactionId } = this;
ws.taskScheduler.stopShepherdTask(this.taskId);
const transitionInfo = await ws.db.runReadWriteTx(
["purchases"],
@@ -267,8 +267,8 @@ export class PayMerchantTransactionContext implements TransactionContext {
}
async abortTransaction(): Promise<void> {
- const { ws, proposalId, transactionId } = this;
- const transitionInfo = await ws.db.runReadWriteTx(
+ const { wex, proposalId, transactionId } = this;
+ const transitionInfo = await wex.db.runReadWriteTx(
[
"purchases",
"refreshGroups",
@@ -308,7 +308,7 @@ export class PayMerchantTransactionContext implements TransactionContext {
});
}
await createRefreshGroup(
- ws,
+ wex,
tx,
currency,
refreshCoins,
@@ -328,13 +328,13 @@ export class PayMerchantTransactionContext implements TransactionContext {
return { oldTxState, newTxState };
},
);
- ws.taskScheduler.stopShepherdTask(this.taskId);
- notifyTransition(ws, transactionId, transitionInfo);
- ws.taskScheduler.startShepherdTask(this.taskId);
+ wex.taskScheduler.stopShepherdTask(this.taskId);
+ notifyTransition(wex, transactionId, transitionInfo);
+ wex.taskScheduler.startShepherdTask(this.taskId);
}
async resumeTransaction(): Promise<void> {
- const { ws, proposalId, transactionId, taskId: retryTag } = this;
+ const { wex: ws, proposalId, transactionId, taskId: retryTag } = this;
const transitionInfo = await ws.db.runReadWriteTx(
["purchases"],
async (tx) => {
@@ -357,7 +357,7 @@ export class PayMerchantTransactionContext implements TransactionContext {
}
async failTransaction(): Promise<void> {
- const { ws, proposalId, transactionId } = this;
+ const { wex: ws, proposalId, transactionId } = this;
const transitionInfo = await ws.db.runReadWriteTx(
[
"purchases",
@@ -396,7 +396,7 @@ export class RefundTransactionContext implements TransactionContext {
public transactionId: TransactionIdStr;
public taskId: TaskIdStr | undefined = undefined;
constructor(
- public ws: InternalWalletState,
+ public wex: WalletExecutionContext,
public refundGroupId: string,
) {
this.transactionId = constructTransactionIdentifier({
@@ -406,8 +406,8 @@ export class RefundTransactionContext implements TransactionContext {
}
async deleteTransaction(): Promise<void> {
- const { ws, refundGroupId, transactionId } = this;
- await ws.db.runReadWriteTx(["refundGroups", "tombstones"], async (tx) => {
+ const { wex, refundGroupId, transactionId } = this;
+ await wex.db.runReadWriteTx(["refundGroups", "tombstones"], async (tx) => {
const refundRecord = await tx.refundGroups.get(refundGroupId);
if (!refundRecord) {
return;
@@ -443,11 +443,11 @@ export class RefundTransactionContext implements TransactionContext {
* of coins that are too small to spend.
*/
export async function getTotalPaymentCost(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
pcs: PayCoinSelection,
): Promise<AmountJson> {
const currency = Amounts.currencyOf(pcs.paymentAmount);
- return ws.db.runReadOnlyTx(["coins", "denominations"], async (tx) => {
+ return wex.db.runReadOnlyTx(["coins", "denominations"], async (tx) => {
const costs: AmountJson[] = [];
for (let i = 0; i < pcs.coinPubs.length; i++) {
const coin = await tx.coins.get(pcs.coinPubs[i]);
@@ -464,7 +464,7 @@ export async function getTotalPaymentCost(
);
}
const allDenoms = await getCandidateWithdrawalDenomsTx(
- ws,
+ wex,
tx,
coin.exchangeBaseUrl,
currency,
@@ -477,7 +477,7 @@ export async function getTotalPaymentCost(
allDenoms,
DenominationRecord.toDenomInfo(denom),
amountLeft,
- ws.config.testing.denomselAllowLate,
+ wex.ws.config.testing.denomselAllowLate,
);
costs.push(Amounts.parseOrThrow(pcs.coinContributions[i]));
costs.push(refreshCost);
@@ -488,7 +488,7 @@ export async function getTotalPaymentCost(
}
async function failProposalPermanently(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
proposalId: string,
err: TalerErrorDetail,
): Promise<void> {
@@ -496,7 +496,7 @@ async function failProposalPermanently(
tag: TransactionType.Payment,
proposalId,
});
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["purchases"],
async (tx) => {
const p = await tx.purchases.get(proposalId);
@@ -511,7 +511,7 @@ async function failProposalPermanently(
return { oldTxState, newTxState };
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
}
function getPayRequestTimeout(purchase: PurchaseRecord): Duration {
@@ -525,7 +525,7 @@ function getPayRequestTimeout(purchase: PurchaseRecord): Duration {
* Return the proposal download data for a purchase, throw if not available.
*/
export async function expectProposalDownload(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
p: PurchaseRecord,
parentTx?: WalletDbReadOnlyTransaction<["contractTerms"]>,
): Promise<{
@@ -559,7 +559,7 @@ export async function expectProposalDownload(
if (parentTx) {
return getFromTransaction(parentTx);
}
- return await ws.db.runReadOnlyTx(["contractTerms"], getFromTransaction);
+ return await wex.db.runReadOnlyTx(["contractTerms"], getFromTransaction);
}
export function extractContractData(
@@ -603,11 +603,10 @@ export function extractContractData(
}
async function processDownloadProposal(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
proposalId: string,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
- const proposal = await ws.db.runReadOnlyTx(["purchases"], async (tx) => {
+ const proposal = await wex.db.runReadOnlyTx(["purchases"], async (tx) => {
return await tx.purchases.get(proposalId);
});
@@ -615,7 +614,7 @@ async function processDownloadProposal(
return TaskRunResult.finished();
}
- const ctx = new PayMerchantTransactionContext(ws, proposalId);
+ const ctx = new PayMerchantTransactionContext(wex, proposalId);
if (proposal.purchaseStatus != PurchaseStatus.PendingDownloadingProposal) {
logger.error(
@@ -644,10 +643,10 @@ async function processDownloadProposal(
requestBody.token = proposal.claimToken;
}
- const httpResponse = await ws.http.fetch(orderClaimUrl, {
+ const httpResponse = await wex.http.fetch(orderClaimUrl, {
method: "POST",
body: requestBody,
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
const r = await readSuccessResponseJsonOrErrorCode(
httpResponse,
@@ -692,7 +691,7 @@ async function processDownloadProposal(
{},
"validation for well-formedness failed",
);
- await failProposalPermanently(ws, proposalId, err);
+ await failProposalPermanently(wex, proposalId, err);
throw makePendingOperationFailedError(
err,
TransactionType.Payment,
@@ -718,7 +717,7 @@ async function processDownloadProposal(
{},
`schema validation failed: ${e}`,
);
- await failProposalPermanently(ws, proposalId, err);
+ await failProposalPermanently(wex, proposalId, err);
throw makePendingOperationFailedError(
err,
TransactionType.Payment,
@@ -726,7 +725,7 @@ async function processDownloadProposal(
);
}
- const sigValid = await ws.cryptoApi.isValidContractTermsSignature({
+ const sigValid = await wex.cryptoApi.isValidContractTermsSignature({
contractTermsHash,
merchantPub: parsedContractTerms.merchant_pub,
sig: proposalResp.sig,
@@ -741,7 +740,7 @@ async function processDownloadProposal(
},
"merchant's signature on contract terms is invalid",
);
- await failProposalPermanently(ws, proposalId, err);
+ await failProposalPermanently(wex, proposalId, err);
throw makePendingOperationFailedError(
err,
TransactionType.Payment,
@@ -763,7 +762,7 @@ async function processDownloadProposal(
},
"merchant base URL mismatch",
);
- await failProposalPermanently(ws, proposalId, err);
+ await failProposalPermanently(wex, proposalId, err);
throw makePendingOperationFailedError(
err,
TransactionType.Payment,
@@ -779,7 +778,7 @@ async function processDownloadProposal(
logger.trace(`extracted contract data: ${j2s(contractData)}`);
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["purchases", "contractTerms"],
async (tx) => {
const p = await tx.purchases.get(proposalId);
@@ -835,7 +834,7 @@ async function processDownloadProposal(
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
return TaskRunResult.progress();
}
@@ -846,15 +845,14 @@ async function processDownloadProposal(
* return the old proposal ID.
*/
async function createOrReusePurchase(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
merchantBaseUrl: string,
orderId: string,
sessionId: string | undefined,
claimToken: string | undefined,
noncePriv: string | undefined,
- cancellationToken: CancellationToken,
): Promise<string> {
- const oldProposals = await ws.db.runReadOnlyTx(["purchases"], async (tx) => {
+ const oldProposals = await wex.db.runReadOnlyTx(["purchases"], async (tx) => {
return tx.purchases.indexes.byUrlAndOrderId.getAll([
merchantBaseUrl,
orderId,
@@ -882,17 +880,13 @@ async function createOrReusePurchase(
}) for order ${orderId} at ${merchantBaseUrl}`,
);
if (oldProposal.purchaseStatus === PurchaseStatus.DialogShared) {
- const download = await expectProposalDownload(ws, oldProposal);
- const paid = await checkIfOrderIsAlreadyPaid(
- ws,
- download.contractData,
- cancellationToken,
- );
+ const download = await expectProposalDownload(wex, oldProposal);
+ const paid = await checkIfOrderIsAlreadyPaid(wex, download.contractData);
logger.info(`old proposal paid: ${paid}`);
if (paid) {
// if this transaction was shared and the order is paid then it
// means that another wallet already paid the proposal
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["purchases"],
async (tx) => {
const p = await tx.purchases.get(oldProposal.proposalId);
@@ -912,7 +906,7 @@ async function createOrReusePurchase(
tag: TransactionType.Payment,
proposalId: oldProposal.proposalId,
});
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
}
}
return oldProposal.proposalId;
@@ -924,10 +918,10 @@ async function createOrReusePurchase(
shared = true;
noncePair = {
priv: noncePriv,
- pub: (await ws.cryptoApi.eddsaGetPublic({ priv: noncePriv })).pub,
+ pub: (await wex.cryptoApi.eddsaGetPublic({ priv: noncePriv })).pub,
};
} else {
- noncePair = await ws.cryptoApi.createEddsaKeypair({});
+ noncePair = await wex.cryptoApi.createEddsaKeypair({});
}
const { priv, pub } = noncePair;
@@ -958,7 +952,7 @@ async function createOrReusePurchase(
shared: shared,
};
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["purchases"],
async (tx) => {
await tx.purchases.put(proposalRecord);
@@ -977,12 +971,12 @@ async function createOrReusePurchase(
tag: TransactionType.Payment,
proposalId,
});
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
return proposalId;
}
async function storeFirstPaySuccess(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
proposalId: string,
sessionId: string | undefined,
payResponse: MerchantPayResponse,
@@ -992,7 +986,7 @@ async function storeFirstPaySuccess(
proposalId,
});
const now = AbsoluteTime.toPreciseTimestamp(AbsoluteTime.now());
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["contractTerms", "purchases"],
async (tx) => {
const purchase = await tx.purchases.get(proposalId);
@@ -1044,11 +1038,11 @@ async function storeFirstPaySuccess(
};
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
}
async function storePayReplaySuccess(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
proposalId: string,
sessionId: string | undefined,
): Promise<void> {
@@ -1056,7 +1050,7 @@ async function storePayReplaySuccess(
tag: TransactionType.Payment,
proposalId,
});
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["purchases"],
async (tx) => {
const purchase = await tx.purchases.get(proposalId);
@@ -1082,7 +1076,7 @@ async function storePayReplaySuccess(
return { oldTxState, newTxState };
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
}
/**
@@ -1094,13 +1088,13 @@ async function storePayReplaySuccess(
* (3) re-do coin selection with the bad coin removed
*/
async function handleInsufficientFunds(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
proposalId: string,
err: TalerErrorDetail,
): Promise<void> {
logger.trace("handling insufficient funds, trying to re-select coins");
- const proposal = await ws.db.runReadOnlyTx(["purchases"], async (tx) => {
+ const proposal = await wex.db.runReadOnlyTx(["purchases"], async (tx) => {
return tx.purchases.get(proposalId);
});
if (!proposal) {
@@ -1128,7 +1122,7 @@ async function handleInsufficientFunds(
throw new TalerProtocolViolationError();
}
- const { contractData } = await expectProposalDownload(ws, proposal);
+ const { contractData } = await expectProposalDownload(wex, proposal);
const prevPayCoins: PreviousPayCoins = [];
@@ -1139,7 +1133,7 @@ async function handleInsufficientFunds(
const payCoinSelection = payInfo.payCoinSelection;
- await ws.db.runReadOnlyTx(["coins", "denominations"], async (tx) => {
+ await wex.db.runReadOnlyTx(["coins", "denominations"], async (tx) => {
for (let i = 0; i < payCoinSelection.coinPubs.length; i++) {
const coinPub = payCoinSelection.coinPubs[i];
if (coinPub === brokenCoinPub) {
@@ -1166,7 +1160,7 @@ async function handleInsufficientFunds(
}
});
- const res = await selectPayCoinsNew(ws, {
+ const res = await selectPayCoinsNew(wex, {
auditors: [],
exchanges: contractData.allowedExchanges,
wireMethod: contractData.wireMethod,
@@ -1185,7 +1179,7 @@ async function handleInsufficientFunds(
logger.trace("re-selected coins");
- await ws.db.runReadWriteTx(
+ await wex.db.runReadWriteTx(
[
"purchases",
"coins",
@@ -1205,7 +1199,7 @@ async function handleInsufficientFunds(
payInfo.payCoinSelection = res.coinSel;
payInfo.payCoinSelectionUid = encodeCrock(getRandomBytes(32));
await tx.purchases.put(p);
- await spendCoins(ws, tx, {
+ await spendCoins(wex, tx, {
// allocationId: `txn:proposal:${p.proposalId}`,
allocationId: constructTransactionIdentifier({
tag: TransactionType.Payment,
@@ -1220,7 +1214,7 @@ async function handleInsufficientFunds(
},
);
- ws.notify({
+ wex.ws.notify({
type: NotificationType.BalanceChange,
hintTransactionId: constructTransactionIdentifier({
tag: TransactionType.Payment,
@@ -1233,11 +1227,11 @@ async function handleInsufficientFunds(
// FIXME: Does way more than checking the payment
// FIXME: Should return immediately.
async function checkPaymentByProposalId(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
proposalId: string,
sessionId?: string,
): Promise<PreparePayResult> {
- let proposal = await ws.db.runReadOnlyTx(["purchases"], async (tx) => {
+ let proposal = await wex.db.runReadOnlyTx(["purchases"], async (tx) => {
return tx.purchases.get(proposalId);
});
if (!proposal) {
@@ -1247,7 +1241,7 @@ async function checkPaymentByProposalId(
const existingProposalId = proposal.repurchaseProposalId;
if (existingProposalId) {
logger.trace("using existing purchase for same product");
- const oldProposal = await ws.db.runReadOnlyTx(
+ const oldProposal = await wex.db.runReadOnlyTx(
["purchases"],
async (tx) => {
return tx.purchases.get(existingProposalId);
@@ -1258,7 +1252,7 @@ async function checkPaymentByProposalId(
}
}
}
- const d = await expectProposalDownload(ws, proposal);
+ const d = await expectProposalDownload(wex, proposal);
const contractData = d.contractData;
const merchantSig = d.contractData.merchantSig;
if (!merchantSig) {
@@ -1267,7 +1261,7 @@ async function checkPaymentByProposalId(
proposalId = proposal.proposalId;
- const ctx = new PayMerchantTransactionContext(ws, proposalId);
+ const ctx = new PayMerchantTransactionContext(wex, proposalId);
const transactionId = ctx.transactionId;
@@ -1280,7 +1274,7 @@ async function checkPaymentByProposalId(
});
// First check if we already paid for it.
- const purchase = await ws.db.runReadOnlyTx(["purchases"], async (tx) => {
+ const purchase = await wex.db.runReadOnlyTx(["purchases"], async (tx) => {
return tx.purchases.get(proposalId);
});
@@ -1290,7 +1284,7 @@ async function checkPaymentByProposalId(
purchase.purchaseStatus === PurchaseStatus.DialogShared
) {
// If not already paid, check if we could pay for it.
- const res = await selectPayCoinsNew(ws, {
+ const res = await selectPayCoinsNew(wex, {
auditors: [],
exchanges: contractData.allowedExchanges,
contractTermsAmount: Amounts.parseOrThrow(contractData.amount),
@@ -1318,7 +1312,7 @@ async function checkPaymentByProposalId(
};
}
- const totalCost = await getTotalPaymentCost(ws, res.coinSel);
+ const totalCost = await getTotalPaymentCost(wex, res.coinSel);
logger.trace("costInfo", totalCost);
logger.trace("coinsForPayment", res);
@@ -1342,7 +1336,7 @@ async function checkPaymentByProposalId(
"automatically re-submitting payment with different session ID",
);
logger.trace(`last: ${purchase.lastSessionId}, current: ${sessionId}`);
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["purchases"],
async (tx) => {
const p = await tx.purchases.get(proposalId);
@@ -1357,14 +1351,14 @@ async function checkPaymentByProposalId(
return { oldTxState, newTxState };
},
);
- notifyTransition(ws, transactionId, transitionInfo);
- ws.taskScheduler.startShepherdTask(ctx.taskId);
+ notifyTransition(wex, transactionId, transitionInfo);
+ wex.taskScheduler.startShepherdTask(ctx.taskId);
// FIXME: Consider changing the API here so that we don't have to
// wait inline for the repurchase.
- await waitPaymentResult(ws, proposalId, sessionId);
- const download = await expectProposalDownload(ws, purchase);
+ await waitPaymentResult(wex, proposalId, sessionId);
+ const download = await expectProposalDownload(wex, purchase);
return {
status: PreparePayResultType.AlreadyConfirmed,
contractTerms: download.contractTermsRaw,
@@ -1379,7 +1373,7 @@ async function checkPaymentByProposalId(
talerUri,
};
} else if (!purchase.timestampFirstSuccessfulPay) {
- const download = await expectProposalDownload(ws, purchase);
+ const download = await expectProposalDownload(wex, purchase);
return {
status: PreparePayResultType.AlreadyConfirmed,
contractTerms: download.contractTermsRaw,
@@ -1398,7 +1392,7 @@ async function checkPaymentByProposalId(
purchase.purchaseStatus === PurchaseStatus.Done ||
purchase.purchaseStatus === PurchaseStatus.PendingQueryingRefund ||
purchase.purchaseStatus === PurchaseStatus.PendingQueryingAutoRefund;
- const download = await expectProposalDownload(ws, purchase);
+ const download = await expectProposalDownload(wex, purchase);
return {
status: PreparePayResultType.AlreadyConfirmed,
contractTerms: download.contractTermsRaw,
@@ -1417,10 +1411,10 @@ async function checkPaymentByProposalId(
}
export async function getContractTermsDetails(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
proposalId: string,
): Promise<WalletContractData> {
- const proposal = await ws.db.runReadOnlyTx(["purchases"], async (tx) => {
+ const proposal = await wex.db.runReadOnlyTx(["purchases"], async (tx) => {
return tx.purchases.get(proposalId);
});
@@ -1428,7 +1422,7 @@ export async function getContractTermsDetails(
throw Error(`proposal with id ${proposalId} not found`);
}
- const d = await expectProposalDownload(ws, proposal);
+ const d = await expectProposalDownload(wex, proposal);
return d.contractData;
}
@@ -1440,7 +1434,7 @@ export async function getContractTermsDetails(
* yet send to the merchant.
*/
export async function preparePayForUri(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
talerPayUri: string,
): Promise<PreparePayResult> {
const uriResult = parsePayUri(talerPayUri);
@@ -1456,39 +1450,38 @@ export async function preparePayForUri(
}
const proposalId = await createOrReusePurchase(
- ws,
+ wex,
uriResult.merchantBaseUrl,
uriResult.orderId,
uriResult.sessionId,
uriResult.claimToken,
uriResult.noncePriv,
- CancellationToken.CONTINUE,
);
- await waitProposalDownloaded(ws, proposalId);
+ await waitProposalDownloaded(wex, proposalId);
- return checkPaymentByProposalId(ws, proposalId, uriResult.sessionId);
+ return checkPaymentByProposalId(wex, proposalId, uriResult.sessionId);
}
/**
* Wait until a proposal is at least downloaded.
*/
async function waitProposalDownloaded(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
proposalId: string,
): Promise<void> {
- const ctx = new PayMerchantTransactionContext(ws, proposalId);
+ const ctx = new PayMerchantTransactionContext(wex, proposalId);
logger.info(`waiting for ${ctx.transactionId} to be downloaded`);
- ws.taskScheduler.startShepherdTask(ctx.taskId);
+ wex.taskScheduler.startShepherdTask(ctx.taskId);
// FIXME: We should use Symbol.dispose magic here for cleanup!
const payNotifFlag = 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.TransactionStateTransition &&
notif.transactionId === ctx.transactionId
@@ -1511,7 +1504,7 @@ async function internalWaitProposalDownloaded(
payNotifFlag: AsyncFlag,
): Promise<void> {
while (true) {
- const { purchase, retryInfo } = await ctx.ws.db.runReadOnlyTx(
+ const { purchase, retryInfo } = await ctx.wex.db.runReadOnlyTx(
["purchases", "operationRetries"],
async (tx) => {
return {
@@ -1539,7 +1532,7 @@ async function internalWaitProposalDownloaded(
}
export async function preparePayForTemplate(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: PreparePayTemplateRequest,
): Promise<PreparePayResult> {
const parsedUri = parsePayTemplateUri(req.talerPayTemplateUri);
@@ -1575,7 +1568,7 @@ export async function preparePayForTemplate(
`templates/${parsedUri.templateId}`,
parsedUri.merchantBaseUrl,
);
- const httpReq = await ws.http.fetch(reqUrl.href, {
+ const httpReq = await wex.http.fetch(reqUrl.href, {
method: "POST",
body: templateDetails,
});
@@ -1591,7 +1584,7 @@ export async function preparePayForTemplate(
claimToken: resp.token,
});
- return await preparePayForUri(ws, payUri);
+ return await preparePayForUri(wex, payUri);
}
/**
@@ -1600,7 +1593,7 @@ export async function preparePayForTemplate(
* Accesses the database and the crypto worker.
*/
export async function generateDepositPermissions(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
payCoinSel: PayCoinSelection,
contractData: WalletContractData,
): Promise<CoinDepositPermission[]> {
@@ -1609,7 +1602,7 @@ export async function generateDepositPermissions(
coin: CoinRecord;
denom: DenominationRecord;
}> = [];
- await ws.db.runReadOnlyTx(["coins", "denominations"], async (tx) => {
+ await wex.db.runReadOnlyTx(["coins", "denominations"], async (tx) => {
for (let i = 0; i < payCoinSel.coinPubs.length; i++) {
const coin = await tx.coins.get(payCoinSel.coinPubs[i]);
if (!coin) {
@@ -1637,7 +1630,7 @@ export async function generateDepositPermissions(
coin.ageCommitmentProof,
)}`,
);
- const dp = await ws.cryptoApi.signDepositPermission({
+ const dp = await wex.cryptoApi.signDepositPermission({
coinPriv: coin.coinPriv,
coinPub: coin.coinPub,
contractTermsHash: contractData.contractTermsHash,
@@ -1665,7 +1658,7 @@ async function internalWaitPaymentResult(
waitSessionId?: string,
): Promise<ConfirmPayResult> {
while (true) {
- const txRes = await ctx.ws.db.runReadOnlyTx(
+ const txRes = await ctx.wex.db.runReadOnlyTx(
["purchases", "operationRetries"],
async (tx) => {
const purchase = await tx.purchases.get(ctx.proposalId);
@@ -1684,7 +1677,7 @@ async function internalWaitPaymentResult(
`purchase is in state ${PurchaseStatus[purchase.purchaseStatus]}`,
);
- const d = await expectProposalDownload(ctx.ws, purchase);
+ const d = await expectProposalDownload(ctx.wex, purchase);
if (txRes.purchase.timestampFirstSuccessfulPay) {
if (
@@ -1726,20 +1719,20 @@ async function internalWaitPaymentResult(
* b) the attempt to pay failed (merchant unavailable, etc.)
*/
async function waitPaymentResult(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
proposalId: string,
waitSessionId?: string,
): Promise<ConfirmPayResult> {
- const ctx = new PayMerchantTransactionContext(ws, proposalId);
+ const ctx = new PayMerchantTransactionContext(wex, proposalId);
- ws.taskScheduler.ensureRunning();
- ws.taskScheduler.startShepherdTask(ctx.taskId);
+ wex.taskScheduler.ensureRunning();
+ wex.taskScheduler.startShepherdTask(ctx.taskId);
// FIXME: Clean up using the new JS "using" / Symbol.dispose syntax.
const purchaseNotifFlag = new AsyncFlag();
// Raise purchaseNotifFlag whenever we get a notification
// about our purchase.
- const cancelNotif = ws.addNotificationListener((notif) => {
+ const cancelNotif = wex.ws.addNotificationListener((notif) => {
if (
notif.type === NotificationType.TransactionStateTransition &&
notif.transactionId === ctx.transactionId
@@ -1768,7 +1761,7 @@ async function waitPaymentResult(
* Confirm payment for a proposal previously claimed by the wallet.
*/
export async function confirmPay(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
transactionId: string,
sessionIdOverride?: string,
forcedCoinSel?: ForcedCoinSel,
@@ -1781,7 +1774,7 @@ export async function confirmPay(
logger.trace(
`executing confirmPay with proposalId ${proposalId} and sessionIdOverride ${sessionIdOverride}`,
);
- const proposal = await ws.db.runReadOnlyTx(["purchases"], async (tx) => {
+ const proposal = await wex.db.runReadOnlyTx(["purchases"], async (tx) => {
return tx.purchases.get(proposalId);
});
@@ -1789,12 +1782,12 @@ export async function confirmPay(
throw Error(`proposal with id ${proposalId} not found`);
}
- const d = await expectProposalDownload(ws, proposal);
+ const d = await expectProposalDownload(wex, proposal);
if (!d) {
throw Error("proposal is in invalid state");
}
- const existingPurchase = await ws.db.runReadWriteTx(
+ const existingPurchase = await wex.db.runReadWriteTx(
["purchases"],
async (tx) => {
const purchase = await tx.purchases.get(proposalId);
@@ -1817,18 +1810,18 @@ export async function confirmPay(
if (existingPurchase && existingPurchase.payInfo) {
logger.trace("confirmPay: submitting payment for existing purchase");
const ctx = new PayMerchantTransactionContext(
- ws,
+ wex,
existingPurchase.proposalId,
);
- await ws.taskScheduler.resetTaskRetries(ctx.taskId);
- return waitPaymentResult(ws, proposalId);
+ await wex.taskScheduler.resetTaskRetries(ctx.taskId);
+ return waitPaymentResult(wex, proposalId);
}
logger.trace("confirmPay: purchase record does not exist yet");
const contractData = d.contractData;
- const selectCoinsResult = await selectPayCoinsNew(ws, {
+ const selectCoinsResult = await selectPayCoinsNew(wex, {
auditors: [],
exchanges: contractData.allowedExchanges,
wireMethod: contractData.wireMethod,
@@ -1852,7 +1845,7 @@ export async function confirmPay(
}
const coinSelection = selectCoinsResult.coinSel;
- const payCostInfo = await getTotalPaymentCost(ws, coinSelection);
+ const payCostInfo = await getTotalPaymentCost(wex, coinSelection);
let sessionId: string | undefined;
if (sessionIdOverride) {
@@ -1865,7 +1858,7 @@ export async function confirmPay(
`recording payment on ${proposal.orderId} with session ID ${sessionId}`,
);
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
[
"purchases",
"coins",
@@ -1891,7 +1884,7 @@ export async function confirmPay(
p.timestampAccept = timestampPreciseToDb(TalerPreciseTimestamp.now());
p.purchaseStatus = PurchaseStatus.PendingPaying;
await tx.purchases.put(p);
- await spendCoins(ws, tx, {
+ await spendCoins(wex, tx, {
//`txn:proposal:${p.proposalId}`
allocationId: constructTransactionIdentifier({
tag: TransactionType.Payment,
@@ -1914,22 +1907,21 @@ export async function confirmPay(
},
);
- notifyTransition(ws, transactionId, transitionInfo);
- ws.notify({
+ notifyTransition(wex, transactionId, transitionInfo);
+ wex.ws.notify({
type: NotificationType.BalanceChange,
hintTransactionId: transactionId,
});
// Wait until we have completed the first attempt to pay.
- return waitPaymentResult(ws, proposalId);
+ return waitPaymentResult(wex, proposalId);
}
export async function processPurchase(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
proposalId: string,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
- const purchase = await ws.db.runReadOnlyTx(["purchases"], async (tx) => {
+ const purchase = await wex.db.runReadOnlyTx(["purchases"], async (tx) => {
return tx.purchases.get(proposalId);
});
if (!purchase) {
@@ -1947,20 +1939,20 @@ export async function processPurchase(
switch (purchase.purchaseStatus) {
case PurchaseStatus.PendingDownloadingProposal:
- return processDownloadProposal(ws, proposalId, cancellationToken);
+ return processDownloadProposal(wex, proposalId);
case PurchaseStatus.PendingPaying:
case PurchaseStatus.PendingPayingReplay:
- return processPurchasePay(ws, proposalId, cancellationToken);
+ return processPurchasePay(wex, proposalId);
case PurchaseStatus.PendingQueryingRefund:
- return processPurchaseQueryRefund(ws, purchase, cancellationToken);
+ return processPurchaseQueryRefund(wex, purchase);
case PurchaseStatus.PendingQueryingAutoRefund:
- return processPurchaseAutoRefund(ws, purchase, cancellationToken);
+ return processPurchaseAutoRefund(wex, purchase);
case PurchaseStatus.AbortingWithRefund:
- return processPurchaseAbortingRefund(ws, purchase, cancellationToken);
+ return processPurchaseAbortingRefund(wex, purchase);
case PurchaseStatus.PendingAcceptRefund:
- return processPurchaseAcceptRefund(ws, purchase, cancellationToken);
+ return processPurchaseAcceptRefund(wex, purchase);
case PurchaseStatus.DialogShared:
- return processPurchaseDialogShared(ws, purchase, cancellationToken);
+ return processPurchaseDialogShared(wex, purchase);
case PurchaseStatus.FailedClaim:
case PurchaseStatus.Done:
case PurchaseStatus.DoneRepurchaseDetected:
@@ -1984,11 +1976,10 @@ export async function processPurchase(
}
async function processPurchasePay(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
proposalId: string,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
- const purchase = await ws.db.runReadOnlyTx(["purchases"], async (tx) => {
+ const purchase = await wex.db.runReadOnlyTx(["purchases"], async (tx) => {
return tx.purchases.get(proposalId);
});
if (!purchase) {
@@ -2018,17 +2009,13 @@ async function processPurchasePay(
const payInfo = purchase.payInfo;
checkDbInvariant(!!payInfo, "payInfo");
- const download = await expectProposalDownload(ws, purchase);
+ const download = await expectProposalDownload(wex, purchase);
if (purchase.shared) {
- const paid = await checkIfOrderIsAlreadyPaid(
- ws,
- download.contractData,
- cancellationToken,
- );
+ const paid = await checkIfOrderIsAlreadyPaid(wex, download.contractData);
if (paid) {
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["purchases"],
async (tx) => {
const p = await tx.purchases.get(purchase.proposalId);
@@ -2048,7 +2035,7 @@ async function processPurchasePay(
proposalId,
});
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
return {
type: TaskRunResultType.Error,
@@ -2069,7 +2056,7 @@ async function processPurchasePay(
let depositPermissions: CoinDepositPermission[];
// FIXME: Cache!
depositPermissions = await generateDepositPermissions(
- ws,
+ wex,
payInfo.payCoinSelection,
download.contractData,
);
@@ -2084,12 +2071,12 @@ async function processPurchasePay(
JSON.stringify(reqBody, undefined, 2),
);
- const resp = await ws.runSequentialized([EXCHANGE_COINS_LOCK], () =>
- ws.http.fetch(payUrl, {
+ const resp = await wex.ws.runSequentialized([EXCHANGE_COINS_LOCK], () =>
+ wex.http.fetch(payUrl, {
method: "POST",
body: reqBody,
timeout: getPayRequestTimeout(purchase),
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
}),
);
@@ -2115,7 +2102,7 @@ async function processPurchasePay(
TalerErrorCode.MERCHANT_POST_ORDERS_ID_PAY_INSUFFICIENT_FUNDS
) {
// Do this in the background, as it might take some time
- handleInsufficientFunds(ws, proposalId, err).catch(async (e) => {
+ handleInsufficientFunds(wex, proposalId, err).catch(async (e) => {
logger.error("handling insufficient funds failed");
logger.error(`${e.toString()}`);
});
@@ -2140,7 +2127,7 @@ async function processPurchasePay(
logger.trace("got success from pay URL", merchantResp);
const merchantPub = download.contractData.merchantPub;
- const { valid } = await ws.cryptoApi.isValidPaymentSignature({
+ const { valid } = await wex.cryptoApi.isValidPaymentSignature({
contractHash: download.contractData.contractTermsHash,
merchantPub,
sig: merchantResp.sig,
@@ -2152,7 +2139,7 @@ async function processPurchasePay(
throw Error("merchant payment signature invalid");
}
- await storeFirstPaySuccess(ws, proposalId, sessionId, merchantResp);
+ await storeFirstPaySuccess(wex, proposalId, sessionId, merchantResp);
} else {
const payAgainUrl = new URL(
`orders/${download.contractData.orderId}/paid`,
@@ -2164,11 +2151,11 @@ async function processPurchasePay(
session_id: sessionId ?? "",
};
logger.trace(`/paid request body: ${j2s(reqBody)}`);
- const resp = await ws.runSequentialized([EXCHANGE_COINS_LOCK], () =>
- ws.http.fetch(payAgainUrl, {
+ const resp = await wex.ws.runSequentialized([EXCHANGE_COINS_LOCK], () =>
+ wex.http.fetch(payAgainUrl, {
method: "POST",
body: reqBody,
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
}),
);
logger.trace(`/paid response status: ${resp.status}`);
@@ -2182,21 +2169,21 @@ async function processPurchasePay(
"/paid failed",
);
}
- await storePayReplaySuccess(ws, proposalId, sessionId);
+ await storePayReplaySuccess(wex, proposalId, sessionId);
}
return TaskRunResult.progress();
}
export async function refuseProposal(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
proposalId: string,
): Promise<void> {
const transactionId = constructTransactionIdentifier({
tag: TransactionType.Payment,
proposalId,
});
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["purchases"],
async (tx) => {
const proposal = await tx.purchases.get(proposalId);
@@ -2218,7 +2205,7 @@ export async function refuseProposal(
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
}
const transitionSuspend: {
@@ -2456,11 +2443,11 @@ export function computePayMerchantTransactionActions(
}
export async function sharePayment(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
merchantBaseUrl: string,
orderId: string,
): Promise<SharePaymentResult> {
- const result = await ws.db.runReadWriteTx(["purchases"], async (tx) => {
+ const result = await wex.db.runReadWriteTx(["purchases"], async (tx) => {
const p = await tx.purchases.indexes.byUrlAndOrderId.get([
merchantBaseUrl,
orderId,
@@ -2503,9 +2490,8 @@ export async function sharePayment(
}
async function checkIfOrderIsAlreadyPaid(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
contract: WalletContractData,
- cancellationToken: CancellationToken,
) {
const requestUrl = new URL(
`orders/${contract.orderId}`,
@@ -2515,8 +2501,8 @@ async function checkIfOrderIsAlreadyPaid(
requestUrl.searchParams.set("timeout_ms", "1000");
- const resp = await ws.http.fetch(requestUrl.href, {
- cancellationToken,
+ const resp = await wex.http.fetch(requestUrl.href, {
+ cancellationToken: wex.cancellationToken,
});
if (
resp.status === HttpStatusCode.Ok ||
@@ -2532,25 +2518,20 @@ async function checkIfOrderIsAlreadyPaid(
}
async function processPurchaseDialogShared(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
purchase: PurchaseRecord,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const proposalId = purchase.proposalId;
logger.trace(`processing dialog-shared for proposal ${proposalId}`);
- const download = await expectProposalDownload(ws, purchase);
+ const download = await expectProposalDownload(wex, purchase);
if (purchase.purchaseStatus !== PurchaseStatus.DialogShared) {
return TaskRunResult.finished();
}
- const paid = await checkIfOrderIsAlreadyPaid(
- ws,
- download.contractData,
- cancellationToken,
- );
+ const paid = await checkIfOrderIsAlreadyPaid(wex, download.contractData);
if (paid) {
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["purchases"],
async (tx) => {
const p = await tx.purchases.get(purchase.proposalId);
@@ -2570,31 +2551,25 @@ async function processPurchaseDialogShared(
proposalId,
});
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
}
return TaskRunResult.backoff();
}
async function processPurchaseAutoRefund(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
purchase: PurchaseRecord,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const proposalId = purchase.proposalId;
logger.trace(`processing auto-refund for proposal ${proposalId}`);
- const taskId = constructTaskIdentifier({
- tag: PendingTaskType.Purchase,
- proposalId,
- });
-
const transactionId = constructTransactionIdentifier({
tag: TransactionType.Payment,
proposalId,
});
- const download = await expectProposalDownload(ws, purchase);
+ const download = await expectProposalDownload(wex, purchase);
if (
!purchase.autoRefundDeadline ||
@@ -2604,7 +2579,7 @@ async function processPurchaseAutoRefund(
),
)
) {
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["purchases"],
async (tx) => {
const p = await tx.purchases.get(purchase.proposalId);
@@ -2623,7 +2598,7 @@ async function processPurchaseAutoRefund(
return { oldTxState, newTxState };
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
return TaskRunResult.finished();
}
@@ -2639,8 +2614,8 @@ async function processPurchaseAutoRefund(
requestUrl.searchParams.set("timeout_ms", "1000");
requestUrl.searchParams.set("await_refund_obtained", "yes");
- const resp = await ws.http.fetch(requestUrl.href, {
- cancellationToken,
+ const resp = await wex.http.fetch(requestUrl.href, {
+ cancellationToken: wex.cancellationToken,
});
// FIXME: Check other status codes!
@@ -2651,7 +2626,7 @@ async function processPurchaseAutoRefund(
);
if (orderStatus.refund_pending) {
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["purchases"],
async (tx) => {
const p = await tx.purchases.get(purchase.proposalId);
@@ -2669,19 +2644,18 @@ async function processPurchaseAutoRefund(
return { oldTxState, newTxState };
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
}
return TaskRunResult.backoff();
}
async function processPurchaseAbortingRefund(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
purchase: PurchaseRecord,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const proposalId = purchase.proposalId;
- const download = await expectProposalDownload(ws, purchase);
+ const download = await expectProposalDownload(wex, purchase);
logger.trace(`processing aborting-refund for proposal ${proposalId}`);
const requestUrl = new URL(
@@ -2696,7 +2670,7 @@ async function processPurchaseAbortingRefund(
throw Error("can't abort, no coins selected");
}
- await ws.db.runReadOnlyTx(["coins"], async (tx) => {
+ await wex.db.runReadOnlyTx(["coins"], async (tx) => {
for (let i = 0; i < payCoinSelection.coinPubs.length; i++) {
const coinPub = payCoinSelection.coinPubs[i];
const coin = await tx.coins.get(coinPub);
@@ -2716,10 +2690,10 @@ async function processPurchaseAbortingRefund(
logger.trace(`making order abort request to ${requestUrl.href}`);
- const abortHttpResp = await ws.http.fetch(requestUrl.href, {
+ const abortHttpResp = await wex.http.fetch(requestUrl.href, {
method: "POST",
body: abortReq,
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
if (abortHttpResp.status === HttpStatusCode.NotFound) {
@@ -2728,7 +2702,7 @@ async function processPurchaseAbortingRefund(
err.code ===
TalerErrorCode.MERCHANT_POST_ORDERS_ID_ABORT_CONTRACT_NOT_FOUND
) {
- const ctx = new PayMerchantTransactionContext(ws, proposalId);
+ const ctx = new PayMerchantTransactionContext(wex, proposalId);
await ctx.transition(async (rec) => {
if (rec.purchaseStatus === PurchaseStatus.AbortingWithRefund) {
rec.purchaseStatus = PurchaseStatus.AbortedOrderDeleted;
@@ -2766,18 +2740,17 @@ async function processPurchaseAbortingRefund(
),
});
}
- return await storeRefunds(ws, purchase, refunds, RefundReason.AbortRefund);
+ return await storeRefunds(wex, purchase, refunds, RefundReason.AbortRefund);
}
async function processPurchaseQueryRefund(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
purchase: PurchaseRecord,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const proposalId = purchase.proposalId;
logger.trace(`processing query-refund for proposal ${proposalId}`);
- const download = await expectProposalDownload(ws, purchase);
+ const download = await expectProposalDownload(wex, purchase);
const requestUrl = new URL(
`orders/${download.contractData.orderId}`,
@@ -2788,8 +2761,8 @@ async function processPurchaseQueryRefund(
download.contractData.contractTermsHash,
);
- const resp = await ws.http.fetch(requestUrl.href, {
- cancellationToken,
+ const resp = await wex.http.fetch(requestUrl.href, {
+ cancellationToken: wex.cancellationToken,
});
const orderStatus = await readSuccessResponseJsonOrThrow(
resp,
@@ -2802,7 +2775,7 @@ async function processPurchaseQueryRefund(
});
if (!orderStatus.refund_pending) {
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["purchases"],
async (tx) => {
const p = await tx.purchases.get(purchase.proposalId);
@@ -2821,7 +2794,7 @@ async function processPurchaseQueryRefund(
return { oldTxState, newTxState };
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
return TaskRunResult.progress();
} else {
const refundAwaiting = Amounts.sub(
@@ -2829,7 +2802,7 @@ async function processPurchaseQueryRefund(
Amounts.parseOrThrow(orderStatus.refund_taken),
).amount;
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["purchases"],
async (tx) => {
const p = await tx.purchases.get(purchase.proposalId);
@@ -2848,17 +2821,16 @@ async function processPurchaseQueryRefund(
return { oldTxState, newTxState };
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
return TaskRunResult.progress();
}
}
async function processPurchaseAcceptRefund(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
purchase: PurchaseRecord,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
- const download = await expectProposalDownload(ws, purchase);
+ const download = await expectProposalDownload(wex, purchase);
const requestUrl = new URL(
`orders/${download.contractData.orderId}/refund`,
@@ -2867,12 +2839,12 @@ async function processPurchaseAcceptRefund(
logger.trace(`making refund request to ${requestUrl.href}`);
- const request = await ws.http.fetch(requestUrl.href, {
+ const request = await wex.http.fetch(requestUrl.href, {
method: "POST",
body: {
h_contract: download.contractData.contractTermsHash,
},
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
const refundResponse = await readSuccessResponseJsonOrThrow(
@@ -2880,7 +2852,7 @@ async function processPurchaseAcceptRefund(
codecForMerchantOrderRefundPickupResponse(),
);
return await storeRefunds(
- ws,
+ wex,
purchase,
refundResponse.refunds,
RefundReason.AbortRefund,
@@ -2888,7 +2860,7 @@ async function processPurchaseAcceptRefund(
}
export async function startRefundQueryForUri(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
talerUri: string,
): Promise<StartRefundQueryForUriResponse> {
const parsedUri = parseTalerUri(talerUri);
@@ -2898,7 +2870,7 @@ export async function startRefundQueryForUri(
if (parsedUri.type !== TalerUriAction.Refund) {
throw Error("expected taler://refund URI");
}
- const purchaseRecord = await ws.db.runReadOnlyTx(
+ const purchaseRecord = await wex.db.runReadOnlyTx(
["purchases"],
async (tx) => {
return tx.purchases.indexes.byUrlAndOrderId.get([
@@ -2918,18 +2890,18 @@ export async function startRefundQueryForUri(
tag: TransactionType.Payment,
proposalId,
});
- await startQueryRefund(ws, proposalId);
+ await startQueryRefund(wex, proposalId);
return {
transactionId,
};
}
export async function startQueryRefund(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
proposalId: string,
): Promise<void> {
- const ctx = new PayMerchantTransactionContext(ws, proposalId);
- const transitionInfo = await ws.db.runReadWriteTx(
+ const ctx = new PayMerchantTransactionContext(wex, proposalId);
+ const transitionInfo = await wex.db.runReadWriteTx(
["purchases"],
async (tx) => {
const p = await tx.purchases.get(proposalId);
@@ -2947,12 +2919,12 @@ export async function startQueryRefund(
return { oldTxState, newTxState };
},
);
- notifyTransition(ws, ctx.transactionId, transitionInfo);
- ws.taskScheduler.startShepherdTask(ctx.taskId);
+ notifyTransition(wex, ctx.transactionId, transitionInfo);
+ wex.taskScheduler.startShepherdTask(ctx.taskId);
}
async function computeRefreshRequest(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
tx: WalletDbReadWriteTransaction<["coins", "denominations"]>,
items: RefundItemRecord[],
): Promise<CoinRefreshRequest[]> {
@@ -2963,7 +2935,7 @@ async function computeRefreshRequest(
throw Error("coin not found");
}
const denomInfo = await getDenomInfo(
- ws,
+ wex,
tx,
coin.exchangeBaseUrl,
coin.denomPubHash,
@@ -3004,7 +2976,7 @@ function getItemStatus(rf: MerchantCoinRefundStatus): RefundItemStatus {
* Store refunds, possibly creating a new refund group.
*/
async function storeRefunds(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
purchase: PurchaseRecord,
refunds: MerchantCoinRefundStatus[],
reason: RefundReason,
@@ -3019,10 +2991,10 @@ async function storeRefunds(
const newRefundGroupId = encodeCrock(randomBytes(32));
const now = TalerPreciseTimestamp.now();
- const download = await expectProposalDownload(ws, purchase);
+ const download = await expectProposalDownload(wex, purchase);
const currency = Amounts.currencyOf(download.contractData.amount);
- const result = await ws.db.runReadWriteTx(
+ const result = await wex.db.runReadWriteTx(
[
"coins",
"denominations",
@@ -3116,12 +3088,12 @@ async function storeRefunds(
if (newGroup) {
const amountsRaw = newGroupRefunds.map((x) => x.refundAmount);
const refreshCoins = await computeRefreshRequest(
- ws,
+ wex,
tx,
newGroupRefunds,
);
const outInfo = await calculateRefreshOutput(
- ws,
+ wex,
tx,
currency,
refreshCoins,
@@ -3172,9 +3144,9 @@ async function storeRefunds(
refundGroup.status = RefundGroupStatus.Failed;
}
await tx.refundGroups.put(refundGroup);
- const refreshCoins = await computeRefreshRequest(ws, tx, items);
+ const refreshCoins = await computeRefreshRequest(wex, tx, items);
await createRefreshGroup(
- ws,
+ wex,
tx,
Amounts.currencyOf(download.contractData.amount),
refreshCoins,
@@ -3215,7 +3187,7 @@ async function storeRefunds(
return TaskRunResult.finished();
}
- notifyTransition(ws, transactionId, result.transitionInfo);
+ notifyTransition(wex, transactionId, result.transitionInfo);
if (result.numPendingItemsTotal > 0) {
return TaskRunResult.backoff();
diff --git a/packages/taler-wallet-core/src/pay-peer-common.ts b/packages/taler-wallet-core/src/pay-peer-common.ts
index dbc3376b4..ff035d5e5 100644
--- a/packages/taler-wallet-core/src/pay-peer-common.ts
+++ b/packages/taler-wallet-core/src/pay-peer-common.ts
@@ -33,25 +33,25 @@ import type { SelectedPeerCoin } from "./coinSelection.js";
import { SpendCoinDetails } from "./crypto/cryptoImplementation.js";
import { PeerPushPaymentCoinSelection, ReserveRecord } from "./db.js";
import { getTotalRefreshCost } from "./refresh.js";
-import { InternalWalletState, getDenomInfo } from "./wallet.js";
+import { WalletExecutionContext, getDenomInfo } from "./wallet.js";
import { getCandidateWithdrawalDenomsTx } from "./withdraw.js";
/**
* Get information about the coin selected for signatures.
*/
export async function queryCoinInfosForSelection(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
csel: PeerPushPaymentCoinSelection,
): Promise<SpendCoinDetails[]> {
let infos: SpendCoinDetails[] = [];
- await ws.db.runReadOnlyTx(["coins", "denominations"], async (tx) => {
+ await wex.db.runReadOnlyTx(["coins", "denominations"], async (tx) => {
for (let i = 0; i < csel.coinPubs.length; i++) {
const coin = await tx.coins.get(csel.coinPubs[i]);
if (!coin) {
throw Error("coin not found anymore");
}
const denom = await getDenomInfo(
- ws,
+ wex,
tx,
coin.exchangeBaseUrl,
coin.denomPubHash,
@@ -73,11 +73,11 @@ export async function queryCoinInfosForSelection(
}
export async function getTotalPeerPaymentCost(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
pcs: SelectedPeerCoin[],
): Promise<AmountJson> {
const currency = Amounts.currencyOf(pcs[0].contribution);
- return ws.db.runReadOnlyTx(["coins", "denominations"], async (tx) => {
+ return wex.db.runReadOnlyTx(["coins", "denominations"], async (tx) => {
const costs: AmountJson[] = [];
for (let i = 0; i < pcs.length; i++) {
const coin = await tx.coins.get(pcs[i].coinPub);
@@ -85,7 +85,7 @@ export async function getTotalPeerPaymentCost(
throw Error("can't calculate payment cost, coin not found");
}
const denomInfo = await getDenomInfo(
- ws,
+ wex,
tx,
coin.exchangeBaseUrl,
coin.denomPubHash,
@@ -96,7 +96,7 @@ export async function getTotalPeerPaymentCost(
);
}
const allDenoms = await getCandidateWithdrawalDenomsTx(
- ws,
+ wex,
tx,
coin.exchangeBaseUrl,
currency,
@@ -109,7 +109,7 @@ export async function getTotalPeerPaymentCost(
allDenoms,
denomInfo,
amountLeft,
- ws.config.testing.denomselAllowLate,
+ wex.ws.config.testing.denomselAllowLate,
);
costs.push(Amounts.parseOrThrow(pcs[i].contribution));
costs.push(refreshCost);
@@ -133,16 +133,16 @@ export const codecForExchangePurseStatus = (): Codec<ExchangePurseStatus> =>
.build("ExchangePurseStatus");
export async function getMergeReserveInfo(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: {
exchangeBaseUrl: string;
},
): Promise<ReserveRecord> {
// We have to eagerly create the key pair outside of the transaction,
// due to the async crypto API.
- const newReservePair = await ws.cryptoApi.createEddsaKeypair({});
+ const newReservePair = await wex.cryptoApi.createEddsaKeypair({});
- const mergeReserveRecord: ReserveRecord = await ws.db.runReadWriteTx(
+ const mergeReserveRecord: ReserveRecord = await wex.db.runReadWriteTx(
["exchanges", "reserves"],
async (tx) => {
const ex = await tx.exchanges.get(req.exchangeBaseUrl);
diff --git a/packages/taler-wallet-core/src/pay-peer-pull-credit.ts b/packages/taler-wallet-core/src/pay-peer-pull-credit.ts
index 7774dfd5f..c999a8d1f 100644
--- a/packages/taler-wallet-core/src/pay-peer-pull-credit.ts
+++ b/packages/taler-wallet-core/src/pay-peer-pull-credit.ts
@@ -17,7 +17,6 @@
import {
AbsoluteTime,
Amounts,
- CancellationToken,
CheckPeerPullCreditRequest,
CheckPeerPullCreditResponse,
ContractTermsUtil,
@@ -81,7 +80,7 @@ import {
constructTransactionIdentifier,
notifyTransition,
} from "./transactions.js";
-import { InternalWalletState } from "./wallet.js";
+import { WalletExecutionContext } from "./wallet.js";
import {
getExchangeWithdrawalInfo,
internalCreateWithdrawalGroup,
@@ -94,7 +93,7 @@ export class PeerPullCreditTransactionContext implements TransactionContext {
readonly taskId: TaskIdStr;
constructor(
- public ws: InternalWalletState,
+ public wex: WalletExecutionContext,
public pursePub: string,
) {
this.taskId = constructTaskIdentifier({
@@ -108,7 +107,7 @@ export class PeerPullCreditTransactionContext implements TransactionContext {
}
async deleteTransaction(): Promise<void> {
- const { ws, pursePub } = this;
+ const { wex: ws, pursePub } = this;
await ws.db.runReadWriteTx(
["withdrawalGroups", "peerPullCredit", "tombstones"],
async (tx) => {
@@ -138,7 +137,7 @@ export class PeerPullCreditTransactionContext implements TransactionContext {
}
async suspendTransaction(): Promise<void> {
- const { ws, pursePub, taskId: retryTag, transactionId } = this;
+ const { wex: ws, pursePub, taskId: retryTag, transactionId } = this;
const transitionInfo = await ws.db.runReadWriteTx(
["peerPullCredit"],
async (tx) => {
@@ -198,7 +197,7 @@ export class PeerPullCreditTransactionContext implements TransactionContext {
}
async failTransaction(): Promise<void> {
- const { ws, pursePub, taskId: retryTag, transactionId } = this;
+ const { wex: ws, pursePub, taskId: retryTag, transactionId } = this;
const transitionInfo = await ws.db.runReadWriteTx(
["peerPullCredit"],
async (tx) => {
@@ -249,7 +248,7 @@ export class PeerPullCreditTransactionContext implements TransactionContext {
}
async resumeTransaction(): Promise<void> {
- const { ws, pursePub, taskId: retryTag, transactionId } = this;
+ const { wex: ws, pursePub, taskId: retryTag, transactionId } = this;
const transitionInfo = await ws.db.runReadWriteTx(
["peerPullCredit"],
async (tx) => {
@@ -308,7 +307,7 @@ export class PeerPullCreditTransactionContext implements TransactionContext {
}
async abortTransaction(): Promise<void> {
- const { ws, pursePub, taskId: retryTag, transactionId } = this;
+ const { wex: ws, pursePub, taskId: retryTag, transactionId } = this;
const transitionInfo = await ws.db.runReadWriteTx(
["peerPullCredit"],
async (tx) => {
@@ -364,9 +363,8 @@ export class PeerPullCreditTransactionContext implements TransactionContext {
}
async function queryPurseForPeerPullCredit(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
pullIni: PeerPullCreditRecord,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const purseDepositUrl = new URL(
`purses/${pullIni.pursePub}/deposit`,
@@ -374,9 +372,9 @@ async function queryPurseForPeerPullCredit(
);
purseDepositUrl.searchParams.set("timeout_ms", "30000");
logger.info(`querying purse status via ${purseDepositUrl.href}`);
- const resp = await ws.http.fetch(purseDepositUrl.href, {
+ const resp = await wex.http.fetch(purseDepositUrl.href, {
timeout: { d_ms: 60000 },
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
const transactionId = constructTransactionIdentifier({
tag: TransactionType.PeerPullCredit,
@@ -388,7 +386,7 @@ async function queryPurseForPeerPullCredit(
switch (resp.status) {
case HttpStatusCode.Gone: {
// Exchange says that purse doesn't exist anymore => expired!
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["peerPullCredit"],
async (tx) => {
const finPi = await tx.peerPullCredit.get(pullIni.pursePub);
@@ -405,7 +403,7 @@ async function queryPurseForPeerPullCredit(
return { oldTxState, newTxState };
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
return TaskRunResult.backoff();
}
case HttpStatusCode.NotFound:
@@ -427,7 +425,7 @@ async function queryPurseForPeerPullCredit(
return TaskRunResult.backoff();
}
- const reserve = await ws.db.runReadOnlyTx(["reserves"], async (tx) => {
+ const reserve = await wex.db.runReadOnlyTx(["reserves"], async (tx) => {
return await tx.reserves.get(pullIni.mergeReserveRowId);
});
@@ -435,7 +433,7 @@ async function queryPurseForPeerPullCredit(
throw Error("reserve for peer pull credit not found in wallet DB");
}
- await internalCreateWithdrawalGroup(ws, {
+ await internalCreateWithdrawalGroup(wex, {
amount: Amounts.parseOrThrow(pullIni.amount),
wgInfo: {
withdrawalType: WithdrawalRecordType.PeerPullCredit,
@@ -449,7 +447,7 @@ async function queryPurseForPeerPullCredit(
pub: reserve.reservePub,
},
});
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["peerPullCredit"],
async (tx) => {
const finPi = await tx.peerPullCredit.get(pullIni.pursePub);
@@ -466,17 +464,16 @@ async function queryPurseForPeerPullCredit(
return { oldTxState, newTxState };
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
return TaskRunResult.backoff();
}
async function longpollKycStatus(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
pursePub: string,
exchangeUrl: string,
kycInfo: KycPendingInfo,
userType: KycUserType,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const transactionId = constructTransactionIdentifier({
tag: TransactionType.PeerPullCredit,
@@ -488,9 +485,9 @@ async function longpollKycStatus(
);
url.searchParams.set("timeout_ms", "10000");
logger.info(`kyc url ${url.href}`);
- const kycStatusRes = await ws.http.fetch(url.href, {
+ const kycStatusRes = await wex.http.fetch(url.href, {
method: "GET",
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
if (
kycStatusRes.status === HttpStatusCode.Ok ||
@@ -498,7 +495,7 @@ async function longpollKycStatus(
// remove after the exchange is fixed or clarified
kycStatusRes.status === HttpStatusCode.NoContent
) {
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["peerPullCredit"],
async (tx) => {
const peerIni = await tx.peerPullCredit.get(pursePub);
@@ -517,7 +514,7 @@ async function longpollKycStatus(
return { oldTxState, newTxState };
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
return TaskRunResult.progress();
} else if (kycStatusRes.status === HttpStatusCode.Accepted) {
return TaskRunResult.longpollReturnedPending();
@@ -527,9 +524,8 @@ async function longpollKycStatus(
}
async function processPeerPullCreditAbortingDeletePurse(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
peerPullIni: PeerPullCreditRecord,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const { pursePub, pursePriv } = peerPullIni;
const transactionId = constructTransactionIdentifier({
@@ -537,20 +533,20 @@ async function processPeerPullCreditAbortingDeletePurse(
pursePub,
});
- const sigResp = await ws.cryptoApi.signDeletePurse({
+ const sigResp = await wex.cryptoApi.signDeletePurse({
pursePriv,
});
const purseUrl = new URL(`purses/${pursePub}`, peerPullIni.exchangeBaseUrl);
- const resp = await ws.http.fetch(purseUrl.href, {
+ const resp = await wex.http.fetch(purseUrl.href, {
method: "DELETE",
headers: {
"taler-purse-signature": sigResp.sig,
},
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
logger.info(`deleted purse with response status ${resp.status}`);
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
[
"peerPullCredit",
"refreshGroups",
@@ -576,13 +572,13 @@ async function processPeerPullCreditAbortingDeletePurse(
};
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
return TaskRunResult.backoff();
}
async function handlePeerPullCreditWithdrawing(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
pullIni: PeerPullCreditRecord,
): Promise<TaskRunResult> {
if (!pullIni.withdrawalGroupId) {
@@ -594,7 +590,7 @@ async function handlePeerPullCreditWithdrawing(
});
const wgId = pullIni.withdrawalGroupId;
let finished: boolean = false;
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["peerPullCredit", "withdrawalGroups"],
async (tx) => {
const ppi = await tx.peerPullCredit.get(pullIni.pursePub);
@@ -627,7 +623,7 @@ async function handlePeerPullCreditWithdrawing(
};
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
if (finished) {
return TaskRunResult.finished();
} else {
@@ -637,13 +633,12 @@ async function handlePeerPullCreditWithdrawing(
}
async function handlePeerPullCreditCreatePurse(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
pullIni: PeerPullCreditRecord,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const purseFee = Amounts.stringify(Amounts.zeroOfAmount(pullIni.amount));
const pursePub = pullIni.pursePub;
- const mergeReserve = await ws.db.runReadOnlyTx(["reserves"], async (tx) => {
+ const mergeReserve = await wex.db.runReadOnlyTx(["reserves"], async (tx) => {
return tx.reserves.get(pullIni.mergeReserveRowId);
});
@@ -651,7 +646,7 @@ async function handlePeerPullCreditCreatePurse(
throw Error("merge reserve for peer pull payment not found in database");
}
- const contractTermsRecord = await ws.db.runReadOnlyTx(
+ const contractTermsRecord = await wex.db.runReadOnlyTx(
["contractTerms"],
async (tx) => {
return tx.contractTerms.get(pullIni.contractTermsHash);
@@ -669,7 +664,7 @@ async function handlePeerPullCreditCreatePurse(
mergeReserve.reservePub,
);
- const econtractResp = await ws.cryptoApi.encryptContractForDeposit({
+ const econtractResp = await wex.cryptoApi.encryptContractForDeposit({
contractPriv: pullIni.contractPriv,
contractPub: pullIni.contractPub,
contractTerms: contractTermsRecord.contractTermsRaw,
@@ -681,7 +676,7 @@ async function handlePeerPullCreditCreatePurse(
const mergeTimestamp = timestampPreciseFromDb(pullIni.mergeTimestamp);
const purseExpiration = contractTerms.purse_expiration;
- const sigRes = await ws.cryptoApi.signReservePurseCreate({
+ const sigRes = await wex.cryptoApi.signReservePurseCreate({
contractTermsHash: pullIni.contractTermsHash,
flags: WalletAccountMergeFlags.CreateWithPurseFee,
mergePriv: pullIni.mergePriv,
@@ -717,22 +712,17 @@ async function handlePeerPullCreditCreatePurse(
pullIni.exchangeBaseUrl,
);
- const httpResp = await ws.http.fetch(reservePurseMergeUrl.href, {
+ const httpResp = await wex.http.fetch(reservePurseMergeUrl.href, {
method: "POST",
body: reservePurseReqBody,
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
if (httpResp.status === HttpStatusCode.UnavailableForLegalReasons) {
const respJson = await httpResp.json();
const kycPending = codecForWalletKycUuid().decode(respJson);
logger.info(`kyc uuid response: ${j2s(kycPending)}`);
- return processPeerPullCreditKycRequired(
- ws,
- pullIni,
- kycPending,
- cancellationToken,
- );
+ return processPeerPullCreditKycRequired(wex, pullIni, kycPending);
}
const resp = await readSuccessResponseJsonOrThrow(httpResp, codecForAny());
@@ -744,7 +734,7 @@ async function handlePeerPullCreditCreatePurse(
pursePub: pullIni.pursePub,
});
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["peerPullCredit"],
async (tx) => {
const pi2 = await tx.peerPullCredit.get(pursePub);
@@ -758,16 +748,15 @@ async function handlePeerPullCreditCreatePurse(
return { oldTxState, newTxState };
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
return TaskRunResult.backoff();
}
export async function processPeerPullCredit(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
pursePub: string,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
- const pullIni = await ws.db.runReadOnlyTx(["peerPullCredit"], async (tx) => {
+ const pullIni = await wex.db.runReadOnlyTx(["peerPullCredit"], async (tx) => {
return tx.peerPullCredit.get(pursePub);
});
if (!pullIni) {
@@ -786,30 +775,25 @@ export async function processPeerPullCredit(
return TaskRunResult.finished();
}
case PeerPullPaymentCreditStatus.PendingReady:
- return queryPurseForPeerPullCredit(ws, pullIni, cancellationToken);
+ return queryPurseForPeerPullCredit(wex, pullIni);
case PeerPullPaymentCreditStatus.PendingMergeKycRequired: {
if (!pullIni.kycInfo) {
throw Error("invalid state, kycInfo required");
}
return await longpollKycStatus(
- ws,
+ wex,
pursePub,
pullIni.exchangeBaseUrl,
pullIni.kycInfo,
"individual",
- cancellationToken,
);
}
case PeerPullPaymentCreditStatus.PendingCreatePurse:
- return handlePeerPullCreditCreatePurse(ws, pullIni, cancellationToken);
+ return handlePeerPullCreditCreatePurse(wex, pullIni);
case PeerPullPaymentCreditStatus.AbortingDeletePurse:
- return await processPeerPullCreditAbortingDeletePurse(
- ws,
- pullIni,
- cancellationToken,
- );
+ return await processPeerPullCreditAbortingDeletePurse(wex, pullIni);
case PeerPullPaymentCreditStatus.PendingWithdrawing:
- return handlePeerPullCreditWithdrawing(ws, pullIni);
+ return handlePeerPullCreditWithdrawing(wex, pullIni);
case PeerPullPaymentCreditStatus.Aborted:
case PeerPullPaymentCreditStatus.Failed:
case PeerPullPaymentCreditStatus.Expired:
@@ -827,10 +811,9 @@ export async function processPeerPullCredit(
}
async function processPeerPullCreditKycRequired(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
peerIni: PeerPullCreditRecord,
kycPending: WalletKycUuid,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const transactionId = constructTransactionIdentifier({
tag: TransactionType.PeerPullCredit,
@@ -845,9 +828,9 @@ async function processPeerPullCreditKycRequired(
);
logger.info(`kyc url ${url.href}`);
- const kycStatusRes = await ws.http.fetch(url.href, {
+ const kycStatusRes = await wex.http.fetch(url.href, {
method: "GET",
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
if (
@@ -861,7 +844,7 @@ async function processPeerPullCreditKycRequired(
} else if (kycStatusRes.status === HttpStatusCode.Accepted) {
const kycStatus = await kycStatusRes.json();
logger.info(`kyc status: ${j2s(kycStatus)}`);
- const { transitionInfo, result } = await ws.db.runReadWriteTx(
+ const { transitionInfo, result } = await wex.db.runReadWriteTx(
["peerPullCredit"],
async (tx) => {
const peerInc = await tx.peerPullCredit.get(pursePub);
@@ -897,7 +880,7 @@ async function processPeerPullCreditKycRequired(
};
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
return TaskRunResult.backoff();
} else {
throw Error(`unexpected response from kyc-check (${kycStatusRes.status})`);
@@ -908,7 +891,7 @@ async function processPeerPullCreditKycRequired(
* Check fees and available exchanges for a peer push payment initiation.
*/
export async function checkPeerPullPaymentInitiation(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: CheckPeerPullCreditRequest,
): Promise<CheckPeerPullCreditResponse> {
// FIXME: We don't support exchanges with purse fees yet.
@@ -922,7 +905,7 @@ export async function checkPeerPullPaymentInitiation(
if (req.exchangeBaseUrl) {
exchangeUrl = req.exchangeBaseUrl;
} else {
- exchangeUrl = await getPreferredExchangeForCurrency(ws, currency);
+ exchangeUrl = await getPreferredExchangeForCurrency(wex, currency);
}
if (!exchangeUrl) {
@@ -932,7 +915,7 @@ export async function checkPeerPullPaymentInitiation(
logger.trace(`found ${exchangeUrl} as preferred exchange`);
const wi = await getExchangeWithdrawalInfo(
- ws,
+ wex,
exchangeUrl,
Amounts.parseOrThrow(req.amount),
undefined,
@@ -957,12 +940,12 @@ export async function checkPeerPullPaymentInitiation(
* Find a preferred exchange based on when we withdrew last from this exchange.
*/
async function getPreferredExchangeForCurrency(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
currency: string,
): Promise<string | undefined> {
// Find an exchange with the matching currency.
// Prefer exchanges with the most recent withdrawal.
- const url = await ws.db.runReadOnlyTx(["exchanges"], async (tx) => {
+ const url = await wex.db.runReadOnlyTx(["exchanges"], async (tx) => {
const exchanges = await tx.exchanges.iter().toArray();
let candidate = undefined;
for (const e of exchanges) {
@@ -1005,7 +988,7 @@ async function getPreferredExchangeForCurrency(
* Initiate a peer pull payment.
*/
export async function initiatePeerPullPayment(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: InitiatePeerPullCreditRequest,
): Promise<InitiatePeerPullCreditResponse> {
const currency = Amounts.currencyOf(req.partialContractTerms.amount);
@@ -1013,7 +996,7 @@ export async function initiatePeerPullPayment(
if (req.exchangeBaseUrl) {
maybeExchangeBaseUrl = req.exchangeBaseUrl;
} else {
- maybeExchangeBaseUrl = await getPreferredExchangeForCurrency(ws, currency);
+ maybeExchangeBaseUrl = await getPreferredExchangeForCurrency(wex, currency);
}
if (!maybeExchangeBaseUrl) {
@@ -1022,20 +1005,20 @@ export async function initiatePeerPullPayment(
const exchangeBaseUrl = maybeExchangeBaseUrl;
- await fetchFreshExchange(ws, exchangeBaseUrl);
+ await fetchFreshExchange(wex, exchangeBaseUrl);
- const mergeReserveInfo = await getMergeReserveInfo(ws, {
+ const mergeReserveInfo = await getMergeReserveInfo(wex, {
exchangeBaseUrl: exchangeBaseUrl,
});
- const pursePair = await ws.cryptoApi.createEddsaKeypair({});
- const mergePair = await ws.cryptoApi.createEddsaKeypair({});
+ const pursePair = await wex.cryptoApi.createEddsaKeypair({});
+ const mergePair = await wex.cryptoApi.createEddsaKeypair({});
const contractTerms = req.partialContractTerms;
const hContractTerms = ContractTermsUtil.hashContractTerms(contractTerms);
- const contractKeyPair = await ws.cryptoApi.createEddsaKeypair({});
+ const contractKeyPair = await wex.cryptoApi.createEddsaKeypair({});
const withdrawalGroupId = encodeCrock(getRandomBytes(32));
@@ -1045,7 +1028,7 @@ export async function initiatePeerPullPayment(
const contractEncNonce = encodeCrock(getRandomBytes(24));
const wi = await getExchangeWithdrawalInfo(
- ws,
+ wex,
exchangeBaseUrl,
Amounts.parseOrThrow(req.partialContractTerms.amount),
undefined,
@@ -1053,7 +1036,7 @@ export async function initiatePeerPullPayment(
const mergeTimestamp = TalerPreciseTimestamp.now();
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["peerPullCredit", "contractTerms"],
async (tx) => {
const ppi: PeerPullCreditRecord = {
@@ -1086,16 +1069,16 @@ export async function initiatePeerPullPayment(
},
);
- const ctx = new PeerPullCreditTransactionContext(ws, pursePair.pub);
+ const ctx = new PeerPullCreditTransactionContext(wex, pursePair.pub);
// The pending-incoming balance has changed.
- ws.notify({
+ wex.ws.notify({
type: NotificationType.BalanceChange,
hintTransactionId: ctx.transactionId,
});
- notifyTransition(ws, ctx.transactionId, transitionInfo);
- ws.taskScheduler.startShepherdTask(ctx.taskId);
+ notifyTransition(wex, ctx.transactionId, transitionInfo);
+ wex.taskScheduler.startShepherdTask(ctx.taskId);
return {
talerUri: stringifyTalerUri({
diff --git a/packages/taler-wallet-core/src/pay-peer-pull-debit.ts b/packages/taler-wallet-core/src/pay-peer-pull-debit.ts
index 30bd1a2c8..828f68113 100644
--- a/packages/taler-wallet-core/src/pay-peer-pull-debit.ts
+++ b/packages/taler-wallet-core/src/pay-peer-pull-debit.ts
@@ -95,7 +95,7 @@ import {
notifyTransition,
parseTransactionIdentifier,
} from "./transactions.js";
-import { InternalWalletState } from "./wallet.js";
+import { InternalWalletState, WalletExecutionContext } from "./wallet.js";
const logger = new Logger("pay-peer-pull-debit.ts");
@@ -103,13 +103,13 @@ const logger = new Logger("pay-peer-pull-debit.ts");
* Common context for a peer-pull-debit transaction.
*/
export class PeerPullDebitTransactionContext implements TransactionContext {
- ws: InternalWalletState;
+ wex: WalletExecutionContext;
readonly transactionId: TransactionIdStr;
readonly taskId: TaskIdStr;
peerPullDebitId: string;
- constructor(ws: InternalWalletState, peerPullDebitId: string) {
- this.ws = ws;
+ constructor(wex: WalletExecutionContext, peerPullDebitId: string) {
+ this.wex = wex;
this.transactionId = constructTransactionIdentifier({
tag: TransactionType.PeerPullDebit,
peerPullDebitId,
@@ -123,7 +123,7 @@ export class PeerPullDebitTransactionContext implements TransactionContext {
async deleteTransaction(): Promise<void> {
const transactionId = this.transactionId;
- const ws = this.ws;
+ const ws = this.wex;
const peerPullDebitId = this.peerPullDebitId;
await ws.db.runReadWriteTx(["peerPullDebit", "tombstones"], async (tx) => {
const debit = await tx.peerPullDebit.get(peerPullDebitId);
@@ -137,9 +137,9 @@ export class PeerPullDebitTransactionContext implements TransactionContext {
async suspendTransaction(): Promise<void> {
const taskId = this.taskId;
const transactionId = this.transactionId;
- const ws = this.ws;
+ const wex = this.wex;
const peerPullDebitId = this.peerPullDebitId;
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["peerPullDebit"],
async (tx) => {
const pullDebitRec = await tx.peerPullDebit.get(peerPullDebitId);
@@ -183,8 +183,8 @@ export class PeerPullDebitTransactionContext implements TransactionContext {
return undefined;
},
);
- notifyTransition(ws, transactionId, transitionInfo);
- ws.taskScheduler.stopShepherdTask(taskId);
+ notifyTransition(wex, transactionId, transitionInfo);
+ wex.taskScheduler.stopShepherdTask(taskId);
}
async resumeTransaction(): Promise<void> {
@@ -206,7 +206,7 @@ export class PeerPullDebitTransactionContext implements TransactionContext {
return TransitionResult.Stay;
}
});
- this.ws.taskScheduler.startShepherdTask(this.taskId);
+ this.wex.taskScheduler.startShepherdTask(this.taskId);
}
async failTransaction(): Promise<void> {
@@ -224,7 +224,7 @@ export class PeerPullDebitTransactionContext implements TransactionContext {
return TransitionResult.Stay;
}
});
- this.ws.taskScheduler.stopShepherdTask(this.taskId);
+ this.wex.taskScheduler.stopShepherdTask(this.taskId);
}
async abortTransaction(): Promise<void> {
@@ -262,7 +262,7 @@ export class PeerPullDebitTransactionContext implements TransactionContext {
}
const refresh = await createRefreshGroup(
- ctx.ws,
+ ctx.wex,
tx,
currency,
coinPubs,
@@ -300,7 +300,7 @@ export class PeerPullDebitTransactionContext implements TransactionContext {
>,
) => Promise<TransitionResult>,
): Promise<void> {
- const ws = this.ws;
+ const ws = this.wex;
const extraStores = opts.extraStores ?? [];
const transitionInfo = await ws.db.runReadWriteTx(
["peerPullDebit", ...extraStores],
@@ -336,7 +336,7 @@ async function handlePurseCreationConflict(
peerPullInc: PeerPullPaymentIncomingRecord,
resp: HttpResponse,
): Promise<TaskRunResult> {
- const ws = ctx.ws;
+ const ws = ctx.wex;
const errResp = await readTalerErrorResponse(resp);
if (errResp.code !== TalerErrorCode.EXCHANGE_GENERIC_INSUFFICIENT_FUNDS) {
await ctx.failTransaction();
@@ -411,9 +411,8 @@ async function handlePurseCreationConflict(
}
async function processPeerPullDebitPendingDeposit(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
peerPullInc: PeerPullPaymentIncomingRecord,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const pursePub = peerPullInc.pursePub;
@@ -422,9 +421,9 @@ async function processPeerPullDebitPendingDeposit(
throw Error("invalid state, no coins selected");
}
- const coins = await queryCoinInfosForSelection(ws, coinSel);
+ const coins = await queryCoinInfosForSelection(wex, coinSel);
- const depositSigsResp = await ws.cryptoApi.signPurseDeposits({
+ const depositSigsResp = await wex.cryptoApi.signPurseDeposits({
exchangeBaseUrl: peerPullInc.exchangeBaseUrl,
pursePub: peerPullInc.pursePub,
coins,
@@ -443,14 +442,14 @@ async function processPeerPullDebitPendingDeposit(
logger.trace(`purse deposit payload: ${j2s(depositPayload)}`);
}
- const httpResp = await ws.http.fetch(purseDepositUrl.href, {
+ const httpResp = await wex.http.fetch(purseDepositUrl.href, {
method: "POST",
body: depositPayload,
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
const ctx = new PeerPullDebitTransactionContext(
- ws,
+ wex,
peerPullInc.peerPullDebitId,
);
@@ -489,9 +488,8 @@ async function processPeerPullDebitPendingDeposit(
}
async function processPeerPullDebitAbortingRefresh(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
peerPullInc: PeerPullPaymentIncomingRecord,
- _cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const peerPullDebitId = peerPullInc.peerPullDebitId;
const abortRefreshGroupId = peerPullInc.abortRefreshGroupId;
@@ -500,7 +498,7 @@ async function processPeerPullDebitAbortingRefresh(
tag: TransactionType.PeerPullDebit,
peerPullDebitId,
});
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["peerPullDebit", "refreshGroups"],
async (tx) => {
const refreshGroup = await tx.refreshGroups.get(abortRefreshGroupId);
@@ -533,17 +531,16 @@ async function processPeerPullDebitAbortingRefresh(
return undefined;
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
// FIXME: Shouldn't this be finished in some cases?!
return TaskRunResult.backoff();
}
export async function processPeerPullDebit(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
peerPullDebitId: string,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
- const peerPullInc = await ws.db.runReadOnlyTx(
+ const peerPullInc = await wex.db.runReadOnlyTx(
["peerPullDebit"],
async (tx) => {
return tx.peerPullDebit.get(peerPullDebitId);
@@ -556,22 +553,20 @@ export async function processPeerPullDebit(
switch (peerPullInc.status) {
case PeerPullDebitRecordStatus.PendingDeposit:
return await processPeerPullDebitPendingDeposit(
- ws,
+ wex,
peerPullInc,
- cancellationToken,
);
case PeerPullDebitRecordStatus.AbortingRefresh:
return await processPeerPullDebitAbortingRefresh(
- ws,
+ wex,
peerPullInc,
- cancellationToken,
);
}
return TaskRunResult.finished();
}
export async function confirmPeerPullDebit(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: ConfirmPeerPullDebitRequest,
): Promise<AcceptPeerPullPaymentResponse> {
let peerPullDebitId: string;
@@ -588,7 +583,7 @@ export async function confirmPeerPullDebit(
throw Error("invalid request, transactionId or peerPullDebitId required");
}
- const peerPullInc = await ws.db.runReadOnlyTx(
+ const peerPullInc = await wex.db.runReadOnlyTx(
["peerPullDebit"],
async (tx) => {
return tx.peerPullDebit.get(peerPullDebitId);
@@ -603,7 +598,7 @@ export async function confirmPeerPullDebit(
const instructedAmount = Amounts.parseOrThrow(peerPullInc.amount);
- const coinSelRes = await selectPeerCoins(ws, { instructedAmount });
+ const coinSelRes = await selectPeerCoins(wex, { instructedAmount });
if (logger.shouldLogTrace()) {
logger.trace(`selected p2p coins (pull): ${j2s(coinSelRes)}`);
}
@@ -620,11 +615,11 @@ export async function confirmPeerPullDebit(
const sel = coinSelRes.result;
const totalAmount = await getTotalPeerPaymentCost(
- ws,
+ wex,
coinSelRes.result.coins,
);
- await ws.db.runReadWriteTx(
+ await wex.db.runReadWriteTx(
[
"exchanges",
"coins",
@@ -634,7 +629,7 @@ export async function confirmPeerPullDebit(
"coinAvailability",
],
async (tx) => {
- await spendCoins(ws, tx, {
+ await spendCoins(wex, tx, {
// allocationId: `txn:peer-pull-debit:${req.peerPullDebitId}`,
allocationId: constructTransactionIdentifier({
tag: TransactionType.PeerPullDebit,
@@ -663,16 +658,16 @@ export async function confirmPeerPullDebit(
},
);
- const ctx = new PeerPullDebitTransactionContext(ws, peerPullDebitId);
+ const ctx = new PeerPullDebitTransactionContext(wex, peerPullDebitId);
const transactionId = ctx.transactionId;
- ws.notify({
+ wex.ws.notify({
type: NotificationType.BalanceChange,
hintTransactionId: transactionId,
});
- ws.taskScheduler.startShepherdTask(ctx.taskId);
+ wex.taskScheduler.startShepherdTask(ctx.taskId);
return {
transactionId,
@@ -684,7 +679,7 @@ export async function confirmPeerPullDebit(
* Store the results in the wallet DB.
*/
export async function preparePeerPullDebit(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: PreparePeerPullDebitRequest,
): Promise<PreparePeerPullDebitResponse> {
const uri = parsePayPullUri(req.talerUri);
@@ -693,7 +688,7 @@ export async function preparePeerPullDebit(
throw Error("got invalid taler://pay-pull URI");
}
- const existing = await ws.db.runReadOnlyTx(
+ const existing = await wex.db.runReadOnlyTx(
["peerPullDebit", "contractTerms"],
async (tx) => {
const peerPullDebitRecord =
@@ -734,7 +729,7 @@ export async function preparePeerPullDebit(
const getContractUrl = new URL(`contracts/${contractPub}`, exchangeBaseUrl);
- const contractHttpResp = await ws.http.fetch(getContractUrl.href);
+ const contractHttpResp = await wex.http.fetch(getContractUrl.href);
const contractResp = await readSuccessResponseJsonOrThrow(
contractHttpResp,
@@ -743,7 +738,7 @@ export async function preparePeerPullDebit(
const pursePub = contractResp.purse_pub;
- const dec = await ws.cryptoApi.decryptContractForDeposit({
+ const dec = await wex.cryptoApi.decryptContractForDeposit({
ciphertext: contractResp.econtract,
contractPriv: contractPriv,
pursePub: pursePub,
@@ -751,7 +746,7 @@ export async function preparePeerPullDebit(
const getPurseUrl = new URL(`purses/${pursePub}/merge`, exchangeBaseUrl);
- const purseHttpResp = await ws.http.fetch(getPurseUrl.href);
+ const purseHttpResp = await wex.http.fetch(getPurseUrl.href);
const purseStatus = await readSuccessResponseJsonOrThrow(
purseHttpResp,
@@ -777,7 +772,7 @@ export async function preparePeerPullDebit(
const instructedAmount = Amounts.parseOrThrow(contractTerms.amount);
- const coinSelRes = await selectPeerCoins(ws, { instructedAmount });
+ const coinSelRes = await selectPeerCoins(wex, { instructedAmount });
if (logger.shouldLogTrace()) {
logger.trace(`selected p2p coins (pull): ${j2s(coinSelRes)}`);
}
@@ -792,11 +787,11 @@ export async function preparePeerPullDebit(
}
const totalAmount = await getTotalPeerPaymentCost(
- ws,
+ wex,
coinSelRes.result.coins,
);
- await ws.db.runReadWriteTx(["peerPullDebit", "contractTerms"], async (tx) => {
+ await wex.db.runReadWriteTx(["peerPullDebit", "contractTerms"], async (tx) => {
await tx.contractTerms.put({
h: contractTermsHash,
contractTermsRaw: contractTerms,
diff --git a/packages/taler-wallet-core/src/pay-peer-push-credit.ts b/packages/taler-wallet-core/src/pay-peer-push-credit.ts
index e629bffe4..772007bb6 100644
--- a/packages/taler-wallet-core/src/pay-peer-push-credit.ts
+++ b/packages/taler-wallet-core/src/pay-peer-push-credit.ts
@@ -83,7 +83,7 @@ import {
notifyTransition,
parseTransactionIdentifier,
} from "./transactions.js";
-import { InternalWalletState } from "./wallet.js";
+import { InternalWalletState, WalletExecutionContext } from "./wallet.js";
import {
PerformCreateWithdrawalGroupResult,
getExchangeWithdrawalInfo,
@@ -98,7 +98,7 @@ export class PeerPushCreditTransactionContext implements TransactionContext {
readonly taskId: TaskIdStr;
constructor(
- public ws: InternalWalletState,
+ public wex: WalletExecutionContext,
public peerPushCreditId: string,
) {
this.transactionId = constructTransactionIdentifier({
@@ -112,8 +112,8 @@ export class PeerPushCreditTransactionContext implements TransactionContext {
}
async deleteTransaction(): Promise<void> {
- const { ws, peerPushCreditId } = this;
- await ws.db.runReadWriteTx(
+ const { wex, peerPushCreditId } = this;
+ await wex.db.runReadWriteTx(
["withdrawalGroups", "peerPushCredit", "tombstones"],
async (tx) => {
const pushInc = await tx.peerPushCredit.get(peerPushCreditId);
@@ -141,8 +141,8 @@ export class PeerPushCreditTransactionContext implements TransactionContext {
}
async suspendTransaction(): Promise<void> {
- const { ws, peerPushCreditId, taskId: retryTag, transactionId } = this;
- const transitionInfo = await ws.db.runReadWriteTx(
+ const { wex, peerPushCreditId, taskId: retryTag, transactionId } = this;
+ const transitionInfo = await wex.db.runReadWriteTx(
["peerPushCredit"],
async (tx) => {
const pushCreditRec = await tx.peerPushCredit.get(peerPushCreditId);
@@ -190,13 +190,13 @@ export class PeerPushCreditTransactionContext implements TransactionContext {
return undefined;
},
);
- notifyTransition(ws, transactionId, transitionInfo);
- ws.taskScheduler.stopShepherdTask(retryTag);
+ notifyTransition(wex, transactionId, transitionInfo);
+ wex.taskScheduler.stopShepherdTask(retryTag);
}
async abortTransaction(): Promise<void> {
- const { ws, peerPushCreditId, taskId: retryTag, transactionId } = this;
- const transitionInfo = await ws.db.runReadWriteTx(
+ const { wex, peerPushCreditId, taskId: retryTag, transactionId } = this;
+ const transitionInfo = await wex.db.runReadWriteTx(
["peerPushCredit"],
async (tx) => {
const pushCreditRec = await tx.peerPushCredit.get(peerPushCreditId);
@@ -247,12 +247,12 @@ export class PeerPushCreditTransactionContext implements TransactionContext {
return undefined;
},
);
- notifyTransition(ws, transactionId, transitionInfo);
- ws.taskScheduler.startShepherdTask(retryTag);
+ notifyTransition(wex, transactionId, transitionInfo);
+ wex.taskScheduler.startShepherdTask(retryTag);
}
async resumeTransaction(): Promise<void> {
- const { ws, peerPushCreditId, taskId: retryTag, transactionId } = this;
+ const { wex: ws, peerPushCreditId, taskId: retryTag, transactionId } = this;
const transitionInfo = await ws.db.runReadWriteTx(
["peerPushCredit"],
async (tx) => {
@@ -305,7 +305,7 @@ export class PeerPushCreditTransactionContext implements TransactionContext {
}
async failTransaction(): Promise<void> {
- const { ws, peerPushCreditId, taskId: retryTag, transactionId } = this;
+ const { wex: ws, peerPushCreditId, taskId: retryTag, transactionId } = this;
const transitionInfo = await ws.db.runReadWriteTx(
["peerPushCredit"],
async (tx) => {
@@ -355,7 +355,7 @@ export class PeerPushCreditTransactionContext implements TransactionContext {
}
export async function preparePeerPushCredit(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: PreparePeerPushCreditRequest,
): Promise<PreparePeerPushCreditResponse> {
const uri = parsePayPushUri(req.talerUri);
@@ -364,7 +364,7 @@ export async function preparePeerPushCredit(
throw Error("got invalid taler://pay-push URI");
}
- const existing = await ws.db.runReadOnlyTx(
+ const existing = await wex.db.runReadOnlyTx(
["contractTerms", "peerPushCredit"],
async (tx) => {
const existingPushInc =
@@ -407,14 +407,14 @@ export async function preparePeerPushCredit(
const exchangeBaseUrl = uri.exchangeBaseUrl;
- await fetchFreshExchange(ws, exchangeBaseUrl);
+ await fetchFreshExchange(wex, exchangeBaseUrl);
const contractPriv = uri.contractPriv;
const contractPub = encodeCrock(eddsaGetPublic(decodeCrock(contractPriv)));
const getContractUrl = new URL(`contracts/${contractPub}`, exchangeBaseUrl);
- const contractHttpResp = await ws.http.fetch(getContractUrl.href);
+ const contractHttpResp = await wex.http.fetch(getContractUrl.href);
const contractResp = await readSuccessResponseJsonOrThrow(
contractHttpResp,
@@ -423,7 +423,7 @@ export async function preparePeerPushCredit(
const pursePub = contractResp.purse_pub;
- const dec = await ws.cryptoApi.decryptContractForMerge({
+ const dec = await wex.cryptoApi.decryptContractForMerge({
ciphertext: contractResp.econtract,
contractPriv: contractPriv,
pursePub: pursePub,
@@ -431,7 +431,7 @@ export async function preparePeerPushCredit(
const getPurseUrl = new URL(`purses/${pursePub}/deposit`, exchangeBaseUrl);
- const purseHttpResp = await ws.http.fetch(getPurseUrl.href);
+ const purseHttpResp = await wex.http.fetch(getPurseUrl.href);
const contractTerms = codecForPeerContractTerms().decode(dec.contractTerms);
@@ -453,13 +453,13 @@ export async function preparePeerPushCredit(
const withdrawalGroupId = encodeCrock(getRandomBytes(32));
const wi = await getExchangeWithdrawalInfo(
- ws,
+ wex,
exchangeBaseUrl,
Amounts.parseOrThrow(purseStatus.balance),
undefined,
);
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["contractTerms", "peerPushCredit"],
async (tx) => {
const rec: PeerPushPaymentIncomingRecord = {
@@ -499,9 +499,9 @@ export async function preparePeerPushCredit(
peerPushCreditId,
});
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
- ws.notify({
+ wex.ws.notify({
type: NotificationType.BalanceChange,
hintTransactionId: transactionId,
});
@@ -518,12 +518,11 @@ export async function preparePeerPushCredit(
}
async function longpollKycStatus(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
peerPushCreditId: string,
exchangeUrl: string,
kycInfo: KycPendingInfo,
userType: KycUserType,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const transactionId = constructTransactionIdentifier({
tag: TransactionType.PeerPushCredit,
@@ -535,9 +534,9 @@ async function longpollKycStatus(
);
url.searchParams.set("timeout_ms", "30000");
logger.info(`kyc url ${url.href}`);
- const kycStatusRes = await ws.http.fetch(url.href, {
+ const kycStatusRes = await wex.http.fetch(url.href, {
method: "GET",
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
if (
kycStatusRes.status === HttpStatusCode.Ok ||
@@ -545,7 +544,7 @@ async function longpollKycStatus(
// remove after the exchange is fixed or clarified
kycStatusRes.status === HttpStatusCode.NoContent
) {
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["peerPushCredit"],
async (tx) => {
const peerInc = await tx.peerPushCredit.get(peerPushCreditId);
@@ -562,7 +561,7 @@ async function longpollKycStatus(
return { oldTxState, newTxState };
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
return TaskRunResult.progress();
} else if (kycStatusRes.status === HttpStatusCode.Accepted) {
// FIXME: Do we have to update the URL here?
@@ -573,10 +572,9 @@ async function longpollKycStatus(
}
async function processPeerPushCreditKycRequired(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
peerInc: PeerPushPaymentIncomingRecord,
kycPending: WalletKycUuid,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const transactionId = constructTransactionIdentifier({
tag: TransactionType.PeerPushCredit,
@@ -591,9 +589,9 @@ async function processPeerPushCreditKycRequired(
);
logger.info(`kyc url ${url.href}`);
- const kycStatusRes = await ws.http.fetch(url.href, {
+ const kycStatusRes = await wex.http.fetch(url.href, {
method: "GET",
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
if (
@@ -607,7 +605,7 @@ async function processPeerPushCreditKycRequired(
} else if (kycStatusRes.status === HttpStatusCode.Accepted) {
const kycStatus = await kycStatusRes.json();
logger.info(`kyc status: ${j2s(kycStatus)}`);
- const { transitionInfo, result } = await ws.db.runReadWriteTx(
+ const { transitionInfo, result } = await wex.db.runReadWriteTx(
["peerPushCredit"],
async (tx) => {
const peerInc = await tx.peerPushCredit.get(peerPushCreditId);
@@ -643,7 +641,7 @@ async function processPeerPushCreditKycRequired(
};
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
return result;
} else {
throw Error(`unexpected response from kyc-check (${kycStatusRes.status})`);
@@ -651,10 +649,9 @@ async function processPeerPushCreditKycRequired(
}
async function handlePendingMerge(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
peerInc: PeerPushPaymentIncomingRecord,
contractTerms: PeerContractTerms,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const { peerPushCreditId } = peerInc;
const transactionId = constructTransactionIdentifier({
@@ -664,7 +661,7 @@ async function handlePendingMerge(
const amount = Amounts.parseOrThrow(contractTerms.amount);
- const mergeReserveInfo = await getMergeReserveInfo(ws, {
+ const mergeReserveInfo = await getMergeReserveInfo(wex, {
exchangeBaseUrl: peerInc.exchangeBaseUrl,
});
@@ -675,7 +672,7 @@ async function handlePendingMerge(
mergeReserveInfo.reservePub,
);
- const sigRes = await ws.cryptoApi.signPurseMerge({
+ const sigRes = await wex.cryptoApi.signPurseMerge({
contractTermsHash: ContractTermsUtil.hashContractTerms(contractTerms),
flags: WalletAccountMergeFlags.MergeFullyPaidPurse,
mergePriv: peerInc.mergePriv,
@@ -700,7 +697,7 @@ async function handlePendingMerge(
reserve_sig: sigRes.accountSig,
};
- const mergeHttpResp = await ws.http.fetch(mergePurseUrl.href, {
+ const mergeHttpResp = await wex.http.fetch(mergePurseUrl.href, {
method: "POST",
body: mergeReq,
});
@@ -710,10 +707,9 @@ async function handlePendingMerge(
const kycPending = codecForWalletKycUuid().decode(respJson);
logger.info(`kyc uuid response: ${j2s(kycPending)}`);
return processPeerPushCreditKycRequired(
- ws,
+ wex,
peerInc,
kycPending,
- cancellationToken,
);
}
@@ -724,7 +720,7 @@ async function handlePendingMerge(
);
logger.trace(`merge response: ${j2s(res)}`);
- const withdrawalGroupPrep = await internalPrepareCreateWithdrawalGroup(ws, {
+ const withdrawalGroupPrep = await internalPrepareCreateWithdrawalGroup(wex, {
amount,
wgInfo: {
withdrawalType: WithdrawalRecordType.PeerPushCredit,
@@ -738,7 +734,7 @@ async function handlePendingMerge(
},
});
- const txRes = await ws.db.runReadWriteTx(
+ const txRes = await wex.db.runReadWriteTx(
[
"contractTerms",
"peerPushCredit",
@@ -760,7 +756,7 @@ async function handlePendingMerge(
case PeerPushCreditStatus.PendingMergeKycRequired: {
peerInc.status = PeerPushCreditStatus.PendingWithdrawing;
wgCreateRes = await internalPerformCreateWithdrawalGroup(
- ws,
+ wex,
tx,
withdrawalGroupPrep,
);
@@ -779,20 +775,20 @@ async function handlePendingMerge(
);
// Transaction was committed, now we can emit notifications.
if (txRes?.wgCreateRes?.exchangeNotif) {
- ws.notify(txRes.wgCreateRes.exchangeNotif);
+ wex.ws.notify(txRes.wgCreateRes.exchangeNotif);
}
notifyTransition(
- ws,
+ wex,
withdrawalGroupPrep.transactionId,
txRes?.wgCreateRes?.transitionInfo,
);
- notifyTransition(ws, transactionId, txRes?.peerPushCreditTransition);
+ notifyTransition(wex, transactionId, txRes?.peerPushCreditTransition);
return TaskRunResult.backoff();
}
async function handlePendingWithdrawing(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
peerInc: PeerPushPaymentIncomingRecord,
): Promise<TaskRunResult> {
if (!peerInc.withdrawalGroupId) {
@@ -804,7 +800,7 @@ async function handlePendingWithdrawing(
});
const wgId = peerInc.withdrawalGroupId;
let finished: boolean = false;
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["peerPushCredit", "withdrawalGroups"],
async (tx) => {
const ppi = await tx.peerPushCredit.get(peerInc.peerPushCreditId);
@@ -837,7 +833,7 @@ async function handlePendingWithdrawing(
};
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
if (finished) {
return TaskRunResult.finished();
} else {
@@ -847,13 +843,12 @@ async function handlePendingWithdrawing(
}
export async function processPeerPushCredit(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
peerPushCreditId: string,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
let peerInc: PeerPushPaymentIncomingRecord | undefined;
let contractTerms: PeerContractTerms | undefined;
- await ws.db.runReadWriteTx(
+ await wex.db.runReadWriteTx(
["contractTerms", "peerPushCredit"],
async (tx) => {
peerInc = await tx.peerPushCredit.get(peerPushCreditId);
@@ -886,20 +881,19 @@ export async function processPeerPushCredit(
throw Error("invalid state, kycInfo required");
}
return await longpollKycStatus(
- ws,
+ wex,
peerPushCreditId,
peerInc.exchangeBaseUrl,
peerInc.kycInfo,
"individual",
- cancellationToken,
);
}
case PeerPushCreditStatus.PendingMerge:
- return handlePendingMerge(ws, peerInc, contractTerms, cancellationToken);
+ return handlePendingMerge(wex, peerInc, contractTerms);
case PeerPushCreditStatus.PendingWithdrawing:
- return handlePendingWithdrawing(ws, peerInc);
+ return handlePendingWithdrawing(wex, peerInc);
default:
return TaskRunResult.finished();
@@ -907,7 +901,7 @@ export async function processPeerPushCredit(
}
export async function confirmPeerPushCredit(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: ConfirmPeerPushCreditRequest,
): Promise<AcceptPeerPushPaymentResponse> {
let peerInc: PeerPushPaymentIncomingRecord | undefined;
@@ -927,7 +921,7 @@ export async function confirmPeerPushCredit(
throw Error("no transaction ID (or deprecated peerPushCreditId) provided");
}
- await ws.db.runReadWriteTx(
+ await wex.db.runReadWriteTx(
["contractTerms", "peerPushCredit"],
async (tx) => {
peerInc = await tx.peerPushCredit.get(peerPushCreditId);
@@ -947,9 +941,9 @@ export async function confirmPeerPushCredit(
);
}
- const ctx = new PeerPushCreditTransactionContext(ws, peerPushCreditId);
+ const ctx = new PeerPushCreditTransactionContext(wex, peerPushCreditId);
- ws.taskScheduler.startShepherdTask(ctx.taskId);
+ wex.taskScheduler.startShepherdTask(ctx.taskId);
const transactionId = constructTransactionIdentifier({
tag: TransactionType.PeerPushCredit,
diff --git a/packages/taler-wallet-core/src/pay-peer-push-debit.ts b/packages/taler-wallet-core/src/pay-peer-push-debit.ts
index 40a5d97a4..5ee4d642b 100644
--- a/packages/taler-wallet-core/src/pay-peer-push-debit.ts
+++ b/packages/taler-wallet-core/src/pay-peer-push-debit.ts
@@ -16,7 +16,6 @@
import {
Amounts,
- CancellationToken,
CheckPeerPushDebitRequest,
CheckPeerPushDebitResponse,
CoinRefreshRequest,
@@ -78,7 +77,7 @@ import {
constructTransactionIdentifier,
notifyTransition,
} from "./transactions.js";
-import { InternalWalletState } from "./wallet.js";
+import { WalletExecutionContext } from "./wallet.js";
const logger = new Logger("pay-peer-push-debit.ts");
@@ -87,7 +86,7 @@ export class PeerPushDebitTransactionContext implements TransactionContext {
readonly taskId: TaskIdStr;
constructor(
- public ws: InternalWalletState,
+ public wex: WalletExecutionContext,
public pursePub: string,
) {
this.transactionId = constructTransactionIdentifier({
@@ -101,8 +100,8 @@ export class PeerPushDebitTransactionContext implements TransactionContext {
}
async deleteTransaction(): Promise<void> {
- const { ws, pursePub, transactionId } = this;
- await ws.db.runReadWriteTx(["peerPushDebit", "tombstones"], async (tx) => {
+ const { wex, pursePub, transactionId } = this;
+ await wex.db.runReadWriteTx(["peerPushDebit", "tombstones"], async (tx) => {
const debit = await tx.peerPushDebit.get(pursePub);
if (debit) {
await tx.peerPushDebit.delete(pursePub);
@@ -112,8 +111,8 @@ export class PeerPushDebitTransactionContext implements TransactionContext {
}
async suspendTransaction(): Promise<void> {
- const { ws, pursePub, transactionId, taskId: retryTag } = this;
- const transitionInfo = await ws.db.runReadWriteTx(
+ const { wex, pursePub, transactionId, taskId: retryTag } = this;
+ const transitionInfo = await wex.db.runReadWriteTx(
["peerPushDebit"],
async (tx) => {
const pushDebitRec = await tx.peerPushDebit.get(pursePub);
@@ -165,13 +164,13 @@ export class PeerPushDebitTransactionContext implements TransactionContext {
return undefined;
},
);
- ws.taskScheduler.stopShepherdTask(retryTag);
- notifyTransition(ws, transactionId, transitionInfo);
+ wex.taskScheduler.stopShepherdTask(retryTag);
+ notifyTransition(wex, transactionId, transitionInfo);
}
async abortTransaction(): Promise<void> {
- const { ws, pursePub, transactionId, taskId: retryTag } = this;
- const transitionInfo = await ws.db.runReadWriteTx(
+ const { wex, pursePub, transactionId, taskId: retryTag } = this;
+ const transitionInfo = await wex.db.runReadWriteTx(
["peerPushDebit"],
async (tx) => {
const pushDebitRec = await tx.peerPushDebit.get(pursePub);
@@ -218,14 +217,14 @@ export class PeerPushDebitTransactionContext implements TransactionContext {
return undefined;
},
);
- ws.taskScheduler.stopShepherdTask(retryTag);
- notifyTransition(ws, transactionId, transitionInfo);
- ws.taskScheduler.startShepherdTask(retryTag);
+ wex.taskScheduler.stopShepherdTask(retryTag);
+ notifyTransition(wex, transactionId, transitionInfo);
+ wex.taskScheduler.startShepherdTask(retryTag);
}
async resumeTransaction(): Promise<void> {
- const { ws, pursePub, transactionId, taskId: retryTag } = this;
- const transitionInfo = await ws.db.runReadWriteTx(
+ const { wex, pursePub, transactionId, taskId: retryTag } = this;
+ const transitionInfo = await wex.db.runReadWriteTx(
["peerPushDebit"],
async (tx) => {
const pushDebitRec = await tx.peerPushDebit.get(pursePub);
@@ -277,12 +276,12 @@ export class PeerPushDebitTransactionContext implements TransactionContext {
return undefined;
},
);
- ws.taskScheduler.startShepherdTask(retryTag);
- notifyTransition(ws, transactionId, transitionInfo);
+ wex.taskScheduler.startShepherdTask(retryTag);
+ notifyTransition(wex, transactionId, transitionInfo);
}
async failTransaction(): Promise<void> {
- const { ws, pursePub, transactionId, taskId: retryTag } = this;
+ const { wex: ws, pursePub, transactionId, taskId: retryTag } = this;
const transitionInfo = await ws.db.runReadWriteTx(
["peerPushDebit"],
async (tx) => {
@@ -337,14 +336,14 @@ export class PeerPushDebitTransactionContext implements TransactionContext {
}
export async function checkPeerPushDebit(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: CheckPeerPushDebitRequest,
): Promise<CheckPeerPushDebitResponse> {
const instructedAmount = Amounts.parseOrThrow(req.amount);
logger.trace(
`checking peer push debit for ${Amounts.stringify(instructedAmount)}`,
);
- const coinSelRes = await selectPeerCoins(ws, { instructedAmount });
+ const coinSelRes = await selectPeerCoins(wex, { instructedAmount });
if (coinSelRes.type === "failure") {
throw TalerError.fromDetail(
TalerErrorCode.WALLET_PEER_PUSH_PAYMENT_INSUFFICIENT_BALANCE,
@@ -355,7 +354,7 @@ export async function checkPeerPushDebit(
}
logger.trace(`selected peer coins (len=${coinSelRes.result.coins.length})`);
const totalAmount = await getTotalPeerPaymentCost(
- ws,
+ wex,
coinSelRes.result.coins,
);
logger.trace("computed total peer payment cost");
@@ -368,13 +367,13 @@ export async function checkPeerPushDebit(
}
async function handlePurseCreationConflict(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
peerPushInitiation: PeerPushDebitRecord,
resp: HttpResponse,
): Promise<TaskRunResult> {
const pursePub = peerPushInitiation.pursePub;
const errResp = await readTalerErrorResponse(resp);
- const ctx = new PeerPushDebitTransactionContext(ws, pursePub);
+ const ctx = new PeerPushDebitTransactionContext(wex, pursePub);
if (errResp.code !== TalerErrorCode.EXCHANGE_GENERIC_INSUFFICIENT_FUNDS) {
await ctx.failTransaction();
return TaskRunResult.finished();
@@ -405,7 +404,7 @@ async function handlePurseCreationConflict(
}
}
- const coinSelRes = await selectPeerCoins(ws, { instructedAmount, repair });
+ const coinSelRes = await selectPeerCoins(wex, { instructedAmount, repair });
if (coinSelRes.type == "failure") {
// FIXME: Details!
@@ -414,7 +413,7 @@ async function handlePurseCreationConflict(
);
}
- await ws.db.runReadWriteTx(["peerPushDebit"], async (tx) => {
+ await wex.db.runReadWriteTx(["peerPushDebit"], async (tx) => {
const myPpi = await tx.peerPushDebit.get(peerPushInitiation.pursePub);
if (!myPpi) {
return;
@@ -438,19 +437,18 @@ async function handlePurseCreationConflict(
}
async function processPeerPushDebitCreateReserve(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
peerPushInitiation: PeerPushDebitRecord,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const pursePub = peerPushInitiation.pursePub;
const purseExpiration = peerPushInitiation.purseExpiration;
const hContractTerms = peerPushInitiation.contractTermsHash;
- const ctx = new PeerPushDebitTransactionContext(ws, pursePub);
+ const ctx = new PeerPushDebitTransactionContext(wex, pursePub);
const transactionId = ctx.transactionId;
logger.trace(`processing ${transactionId} pending(create-reserve)`);
- const contractTermsRecord = await ws.db.runReadOnlyTx(
+ const contractTermsRecord = await wex.db.runReadOnlyTx(
["contractTerms"],
async (tx) => {
return tx.contractTerms.get(hContractTerms);
@@ -463,7 +461,7 @@ async function processPeerPushDebitCreateReserve(
);
}
- const purseSigResp = await ws.cryptoApi.signPurseCreation({
+ const purseSigResp = await wex.cryptoApi.signPurseCreation({
hContractTerms,
mergePub: peerPushInitiation.mergePub,
minAge: 0,
@@ -473,11 +471,11 @@ async function processPeerPushDebitCreateReserve(
});
const coins = await queryCoinInfosForSelection(
- ws,
+ wex,
peerPushInitiation.coinSel,
);
- const depositSigsResp = await ws.cryptoApi.signPurseDeposits({
+ const depositSigsResp = await wex.cryptoApi.signPurseDeposits({
exchangeBaseUrl: peerPushInitiation.exchangeBaseUrl,
pursePub: peerPushInitiation.pursePub,
coins,
@@ -495,7 +493,7 @@ async function processPeerPushDebitCreateReserve(
logger.trace(`encrypt contract request: ${j2s(encryptContractRequest)}`);
- const econtractResp = await ws.cryptoApi.encryptContractForMerge(
+ const econtractResp = await wex.cryptoApi.encryptContractForMerge(
encryptContractRequest,
);
@@ -517,10 +515,10 @@ async function processPeerPushDebitCreateReserve(
logger.trace(`request body: ${j2s(reqBody)}`);
- const httpResp = await ws.http.fetch(createPurseUrl.href, {
+ const httpResp = await wex.http.fetch(createPurseUrl.href, {
method: "POST",
body: reqBody,
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
{
@@ -538,7 +536,7 @@ async function processPeerPushDebitCreateReserve(
}
case HttpStatusCode.Conflict: {
// Handle double-spending
- return handlePurseCreationConflict(ws, peerPushInitiation, httpResp);
+ return handlePurseCreationConflict(wex, peerPushInitiation, httpResp);
}
default: {
const errResp = await readTalerErrorResponse(httpResp);
@@ -554,7 +552,7 @@ async function processPeerPushDebitCreateReserve(
throw Error("got error response from exchange");
}
- await transitionPeerPushDebitTransaction(ws, pursePub, {
+ await transitionPeerPushDebitTransaction(wex, pursePub, {
stFrom: PeerPushDebitStatus.PendingCreatePurse,
stTo: PeerPushDebitStatus.PendingReady,
});
@@ -563,9 +561,8 @@ async function processPeerPushDebitCreateReserve(
}
async function processPeerPushDebitAbortingDeletePurse(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
peerPushInitiation: PeerPushDebitRecord,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const { pursePub, pursePriv } = peerPushInitiation;
const transactionId = constructTransactionIdentifier({
@@ -573,23 +570,23 @@ async function processPeerPushDebitAbortingDeletePurse(
pursePub,
});
- const sigResp = await ws.cryptoApi.signDeletePurse({
+ const sigResp = await wex.cryptoApi.signDeletePurse({
pursePriv,
});
const purseUrl = new URL(
`purses/${pursePub}`,
peerPushInitiation.exchangeBaseUrl,
);
- const resp = await ws.http.fetch(purseUrl.href, {
+ const resp = await wex.http.fetch(purseUrl.href, {
method: "DELETE",
headers: {
"taler-purse-signature": sigResp.sig,
},
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
logger.info(`deleted purse with response status ${resp.status}`);
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
[
"peerPushDebit",
"refreshGroups",
@@ -617,7 +614,7 @@ async function processPeerPushDebitAbortingDeletePurse(
}
const refresh = await createRefreshGroup(
- ws,
+ wex,
tx,
currency,
coinPubs,
@@ -634,7 +631,7 @@ async function processPeerPushDebitAbortingDeletePurse(
};
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
return TaskRunResult.backoff();
}
@@ -645,7 +642,7 @@ interface SimpleTransition {
}
async function transitionPeerPushDebitTransaction(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
pursePub: string,
transitionSpec: SimpleTransition,
): Promise<void> {
@@ -653,7 +650,7 @@ async function transitionPeerPushDebitTransaction(
tag: TransactionType.PeerPushDebit,
pursePub,
});
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["peerPushDebit"],
async (tx) => {
const ppiRec = await tx.peerPushDebit.get(pursePub);
@@ -673,11 +670,11 @@ async function transitionPeerPushDebitTransaction(
};
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
}
async function processPeerPushDebitAbortingRefreshDeleted(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
peerPushInitiation: PeerPushDebitRecord,
): Promise<TaskRunResult> {
const pursePub = peerPushInitiation.pursePub;
@@ -687,7 +684,7 @@ async function processPeerPushDebitAbortingRefreshDeleted(
tag: TransactionType.PeerPushDebit,
pursePub: peerPushInitiation.pursePub,
});
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["refreshGroups", "peerPushDebit"],
async (tx) => {
const refreshGroup = await tx.refreshGroups.get(abortRefreshGroupId);
@@ -720,13 +717,13 @@ async function processPeerPushDebitAbortingRefreshDeleted(
return undefined;
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
// FIXME: Shouldn't this be finished in some cases?!
return TaskRunResult.backoff();
}
async function processPeerPushDebitAbortingRefreshExpired(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
peerPushInitiation: PeerPushDebitRecord,
): Promise<TaskRunResult> {
const pursePub = peerPushInitiation.pursePub;
@@ -736,7 +733,7 @@ async function processPeerPushDebitAbortingRefreshExpired(
tag: TransactionType.PeerPushDebit,
pursePub: peerPushInitiation.pursePub,
});
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["peerPushDebit", "refreshGroups"],
async (tx) => {
const refreshGroup = await tx.refreshGroups.get(abortRefreshGroupId);
@@ -769,7 +766,7 @@ async function processPeerPushDebitAbortingRefreshExpired(
return undefined;
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
// FIXME: Shouldn't this be finished in some cases?!
return TaskRunResult.backoff();
}
@@ -778,9 +775,8 @@ async function processPeerPushDebitAbortingRefreshExpired(
* Process the "pending(ready)" state of a peer-push-debit transaction.
*/
async function processPeerPushDebitReady(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
peerPushInitiation: PeerPushDebitRecord,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
logger.trace("processing peer-push-debit pending(ready)");
const pursePub = peerPushInitiation.pursePub;
@@ -794,9 +790,9 @@ async function processPeerPushDebitReady(
);
mergeUrl.searchParams.set("timeout_ms", "30000");
logger.info(`long-polling on purse status at ${mergeUrl.href}`);
- const resp = await ws.http.fetch(mergeUrl.href, {
+ const resp = await wex.http.fetch(mergeUrl.href, {
// timeout: getReserveRequestTimeout(withdrawalGroup),
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
if (resp.status === HttpStatusCode.Ok) {
const purseStatus = await readSuccessResponseJsonOrThrow(
@@ -809,7 +805,7 @@ async function processPeerPushDebitReady(
return TaskRunResult.backoff();
} else {
await transitionPeerPushDebitTransaction(
- ws,
+ wex,
peerPushInitiation.pursePub,
{
stFrom: PeerPushDebitStatus.PendingReady,
@@ -820,7 +816,7 @@ async function processPeerPushDebitReady(
}
} else if (resp.status === HttpStatusCode.Gone) {
logger.info(`purse ${pursePub} is gone, aborting peer-push-debit`);
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
[
"peerPushDebit",
"refreshGroups",
@@ -848,7 +844,7 @@ async function processPeerPushDebitReady(
}
const refresh = await createRefreshGroup(
- ws,
+ wex,
tx,
currency,
coinPubs,
@@ -865,7 +861,7 @@ async function processPeerPushDebitReady(
};
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
return TaskRunResult.backoff();
} else {
logger.warn(`unexpected HTTP status for purse: ${resp.status}`);
@@ -874,11 +870,10 @@ async function processPeerPushDebitReady(
}
export async function processPeerPushDebit(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
pursePub: string,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
- const peerPushInitiation = await ws.db.runReadOnlyTx(
+ const peerPushInitiation = await wex.db.runReadOnlyTx(
["peerPushDebit"],
async (tx) => {
return tx.peerPushDebit.get(pursePub);
@@ -890,27 +885,21 @@ export async function processPeerPushDebit(
switch (peerPushInitiation.status) {
case PeerPushDebitStatus.PendingCreatePurse:
- return processPeerPushDebitCreateReserve(
- ws,
- peerPushInitiation,
- cancellationToken,
- );
+ return processPeerPushDebitCreateReserve(wex, peerPushInitiation);
case PeerPushDebitStatus.PendingReady:
- return processPeerPushDebitReady(
- ws,
- peerPushInitiation,
- cancellationToken,
- );
+ return processPeerPushDebitReady(wex, peerPushInitiation);
case PeerPushDebitStatus.AbortingDeletePurse:
- return processPeerPushDebitAbortingDeletePurse(
- ws,
+ return processPeerPushDebitAbortingDeletePurse(wex, peerPushInitiation);
+ case PeerPushDebitStatus.AbortingRefreshDeleted:
+ return processPeerPushDebitAbortingRefreshDeleted(
+ wex,
peerPushInitiation,
- cancellationToken,
);
- case PeerPushDebitStatus.AbortingRefreshDeleted:
- return processPeerPushDebitAbortingRefreshDeleted(ws, peerPushInitiation);
case PeerPushDebitStatus.AbortingRefreshExpired:
- return processPeerPushDebitAbortingRefreshExpired(ws, peerPushInitiation);
+ return processPeerPushDebitAbortingRefreshExpired(
+ wex,
+ peerPushInitiation,
+ );
default: {
const txState = computePeerPushDebitTransactionState(peerPushInitiation);
logger.warn(
@@ -926,7 +915,7 @@ export async function processPeerPushDebit(
* Initiate sending a peer-to-peer push payment.
*/
export async function initiatePeerPushDebit(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: InitiatePeerPushDebitRequest,
): Promise<InitiatePeerPushDebitResponse> {
const instructedAmount = Amounts.parseOrThrow(
@@ -935,14 +924,14 @@ export async function initiatePeerPushDebit(
const purseExpiration = req.partialContractTerms.purse_expiration;
const contractTerms = req.partialContractTerms;
- const pursePair = await ws.cryptoApi.createEddsaKeypair({});
- const mergePair = await ws.cryptoApi.createEddsaKeypair({});
+ const pursePair = await wex.cryptoApi.createEddsaKeypair({});
+ const mergePair = await wex.cryptoApi.createEddsaKeypair({});
const hContractTerms = ContractTermsUtil.hashContractTerms(contractTerms);
- const contractKeyPair = await ws.cryptoApi.createEddsaKeypair({});
+ const contractKeyPair = await wex.cryptoApi.createEddsaKeypair({});
- const coinSelRes = await selectPeerCoins(ws, { instructedAmount });
+ const coinSelRes = await selectPeerCoins(wex, { instructedAmount });
if (coinSelRes.type !== "success") {
throw TalerError.fromDetail(
@@ -959,7 +948,7 @@ export async function initiatePeerPushDebit(
logger.trace(`${j2s(coinSelRes)}`);
const totalAmount = await getTotalPeerPaymentCost(
- ws,
+ wex,
coinSelRes.result.coins,
);
@@ -967,13 +956,13 @@ export async function initiatePeerPushDebit(
const pursePub = pursePair.pub;
- const ctx = new PeerPushDebitTransactionContext(ws, pursePub);
+ const ctx = new PeerPushDebitTransactionContext(wex, pursePub);
const transactionId = ctx.transactionId;
const contractEncNonce = encodeCrock(getRandomBytes(24));
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
[
"exchanges",
"contractTerms",
@@ -987,7 +976,7 @@ export async function initiatePeerPushDebit(
// FIXME: Instead of directly doing a spendCoin here,
// we might want to mark the coins as used and spend them
// after we've been able to create the purse.
- await spendCoins(ws, tx, {
+ await spendCoins(wex, tx, {
allocationId: constructTransactionIdentifier({
tag: TransactionType.PeerPushDebit,
pursePub: pursePair.pub,
@@ -1034,13 +1023,13 @@ export async function initiatePeerPushDebit(
};
},
);
- notifyTransition(ws, transactionId, transitionInfo);
- ws.notify({
+ notifyTransition(wex, transactionId, transitionInfo);
+ wex.ws.notify({
type: NotificationType.BalanceChange,
hintTransactionId: transactionId,
});
- ws.taskScheduler.startShepherdTask(ctx.taskId);
+ wex.taskScheduler.startShepherdTask(ctx.taskId);
return {
contractPriv: contractKeyPair.priv,
diff --git a/packages/taler-wallet-core/src/recoup.ts b/packages/taler-wallet-core/src/recoup.ts
index 3ef494c3a..8d5d3dd1f 100644
--- a/packages/taler-wallet-core/src/recoup.ts
+++ b/packages/taler-wallet-core/src/recoup.ts
@@ -63,7 +63,11 @@ import {
} from "./db.js";
import { createRefreshGroup } from "./refresh.js";
import { constructTransactionIdentifier } from "./transactions.js";
-import { getDenomInfo, type InternalWalletState } from "./wallet.js";
+import {
+ WalletExecutionContext,
+ getDenomInfo,
+ type InternalWalletState,
+} from "./wallet.js";
import { internalCreateWithdrawalGroup } from "./withdraw.js";
export const logger = new Logger("operations/recoup.ts");
@@ -73,7 +77,7 @@ export const logger = new Logger("operations/recoup.ts");
* a coin in the group as finished.
*/
export async function putGroupAsFinished(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
tx: WalletDbReadWriteTransaction<
["recoupGroups", "denominations", "refreshGroups", "coins"]
>,
@@ -91,7 +95,7 @@ export async function putGroupAsFinished(
}
async function recoupRewardCoin(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
recoupGroupId: string,
coinIdx: number,
coin: CoinRecord,
@@ -99,7 +103,7 @@ async function recoupRewardCoin(
// We can't really recoup a coin we got via tipping.
// Thus we just put the coin to sleep.
// FIXME: somehow report this to the user
- await ws.db.runReadWriteTx(
+ await wex.db.runReadWriteTx(
["recoupGroups", "denominations", "refreshGroups", "coins"],
async (tx) => {
const recoupGroup = await tx.recoupGroups.get(recoupGroupId);
@@ -109,23 +113,23 @@ async function recoupRewardCoin(
if (recoupGroup.recoupFinishedPerCoin[coinIdx]) {
return;
}
- await putGroupAsFinished(ws, tx, recoupGroup, coinIdx);
+ await putGroupAsFinished(wex, tx, recoupGroup, coinIdx);
},
);
}
async function recoupRefreshCoin(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
recoupGroupId: string,
coinIdx: number,
coin: CoinRecord,
cs: RefreshCoinSource,
): Promise<void> {
- const d = await ws.db.runReadOnlyTx(
+ const d = await wex.db.runReadOnlyTx(
["coins", "denominations"],
async (tx) => {
const denomInfo = await getDenomInfo(
- ws,
+ wex,
tx,
coin.exchangeBaseUrl,
coin.denomPubHash,
@@ -141,7 +145,7 @@ async function recoupRefreshCoin(
return;
}
- const recoupRequest = await ws.cryptoApi.createRecoupRefreshRequest({
+ const recoupRequest = await wex.cryptoApi.createRecoupRefreshRequest({
blindingKey: coin.blindingKey,
coinPriv: coin.coinPriv,
coinPub: coin.coinPub,
@@ -155,7 +159,7 @@ async function recoupRefreshCoin(
);
logger.trace(`making recoup request for ${coin.coinPub}`);
- const resp = await ws.http.fetch(reqUrl.href, {
+ const resp = await wex.http.fetch(reqUrl.href, {
method: "POST",
body: recoupRequest,
});
@@ -168,7 +172,7 @@ async function recoupRefreshCoin(
throw Error(`Coin's oldCoinPub doesn't match reserve on recoup`);
}
- await ws.db.runReadWriteTx(
+ await wex.db.runReadWriteTx(
["coins", "denominations", "recoupGroups", "refreshGroups"],
async (tx) => {
const recoupGroup = await tx.recoupGroups.get(recoupGroupId);
@@ -189,13 +193,13 @@ async function recoupRefreshCoin(
return;
}
const oldCoinDenom = await getDenomInfo(
- ws,
+ wex,
tx,
oldCoin.exchangeBaseUrl,
oldCoin.denomPubHash,
);
const revokedCoinDenom = await getDenomInfo(
- ws,
+ wex,
tx,
revokedCoin.exchangeBaseUrl,
revokedCoin.denomPubHash,
@@ -220,22 +224,22 @@ async function recoupRefreshCoin(
}
await tx.coins.put(revokedCoin);
await tx.coins.put(oldCoin);
- await putGroupAsFinished(ws, tx, recoupGroup, coinIdx);
+ await putGroupAsFinished(wex, tx, recoupGroup, coinIdx);
},
);
}
export async function recoupWithdrawCoin(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
recoupGroupId: string,
coinIdx: number,
coin: CoinRecord,
cs: WithdrawCoinSource,
): Promise<void> {
const reservePub = cs.reservePub;
- const denomInfo = await ws.db.runReadOnlyTx(["denominations"], async (tx) => {
+ const denomInfo = await wex.db.runReadOnlyTx(["denominations"], async (tx) => {
const denomInfo = await getDenomInfo(
- ws,
+ wex,
tx,
coin.exchangeBaseUrl,
coin.denomPubHash,
@@ -247,7 +251,7 @@ export async function recoupWithdrawCoin(
return;
}
- const recoupRequest = await ws.cryptoApi.createRecoupRequest({
+ const recoupRequest = await wex.cryptoApi.createRecoupRequest({
blindingKey: coin.blindingKey,
coinPriv: coin.coinPriv,
coinPub: coin.coinPub,
@@ -257,7 +261,7 @@ export async function recoupWithdrawCoin(
});
const reqUrl = new URL(`/coins/${coin.coinPub}/recoup`, coin.exchangeBaseUrl);
logger.trace(`requesting recoup via ${reqUrl.href}`);
- const resp = await ws.http.fetch(reqUrl.href, {
+ const resp = await wex.http.fetch(reqUrl.href, {
method: "POST",
body: recoupRequest,
});
@@ -273,7 +277,7 @@ export async function recoupWithdrawCoin(
}
// FIXME: verify that our expectations about the amount match
- await ws.db.runReadWriteTx(
+ await wex.db.runReadWriteTx(
["coins", "denominations", "recoupGroups", "refreshGroups"],
async (tx) => {
const recoupGroup = await tx.recoupGroups.get(recoupGroupId);
@@ -289,17 +293,16 @@ export async function recoupWithdrawCoin(
}
updatedCoin.status = CoinStatus.Dormant;
await tx.coins.put(updatedCoin);
- await putGroupAsFinished(ws, tx, recoupGroup, coinIdx);
+ await putGroupAsFinished(wex, tx, recoupGroup, coinIdx);
},
);
}
export async function processRecoupGroup(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
recoupGroupId: string,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
- let recoupGroup = await ws.db.runReadOnlyTx(["recoupGroups"], async (tx) => {
+ let recoupGroup = await wex.db.runReadOnlyTx(["recoupGroups"], async (tx) => {
return tx.recoupGroups.get(recoupGroupId);
});
if (!recoupGroup) {
@@ -311,7 +314,7 @@ export async function processRecoupGroup(
}
const ps = recoupGroup.coinPubs.map(async (x, i) => {
try {
- await processRecoupForCoin(ws, recoupGroupId, i);
+ await processRecoupForCoin(wex, recoupGroupId, i);
} catch (e) {
logger.warn(`processRecoup failed: ${e}`);
throw e;
@@ -319,7 +322,7 @@ export async function processRecoupGroup(
});
await Promise.all(ps);
- recoupGroup = await ws.db.runReadOnlyTx(["recoupGroups"], async (tx) => {
+ recoupGroup = await wex.db.runReadOnlyTx(["recoupGroups"], async (tx) => {
return tx.recoupGroups.get(recoupGroupId);
});
if (!recoupGroup) {
@@ -338,7 +341,7 @@ export async function processRecoupGroup(
const reservePrivMap: Record<string, string> = {};
for (let i = 0; i < recoupGroup.coinPubs.length; i++) {
const coinPub = recoupGroup.coinPubs[i];
- await ws.db.runReadOnlyTx(["coins", "reserves"], async (tx) => {
+ await wex.db.runReadOnlyTx(["coins", "reserves"], async (tx) => {
const coin = await tx.coins.get(coinPub);
if (!coin) {
throw Error(`Coin ${coinPub} not found, can't request recoup`);
@@ -363,13 +366,13 @@ export async function processRecoupGroup(
);
logger.info(`querying reserve status for recoup via ${reserveUrl}`);
- const resp = await ws.http.fetch(reserveUrl.href);
+ const resp = await wex.http.fetch(reserveUrl.href);
const result = await readSuccessResponseJsonOrThrow(
resp,
codecForReserveStatus(),
);
- await internalCreateWithdrawalGroup(ws, {
+ await internalCreateWithdrawalGroup(wex, {
amount: Amounts.parseOrThrow(result.balance),
exchangeBaseUrl: recoupGroup.exchangeBaseUrl,
reserveStatus: WithdrawalGroupStatus.PendingQueryingStatus,
@@ -383,7 +386,7 @@ export async function processRecoupGroup(
});
}
- await ws.db.runReadWriteTx(
+ await wex.db.runReadWriteTx(
[
"recoupGroups",
"coinAvailability",
@@ -400,7 +403,7 @@ export async function processRecoupGroup(
rg2.operationStatus = RecoupOperationStatus.Finished;
if (rg2.scheduleRefreshCoins.length > 0) {
await createRefreshGroup(
- ws,
+ wex,
tx,
Amounts.currencyOf(rg2.scheduleRefreshCoins[0].amount),
rg2.scheduleRefreshCoins,
@@ -452,7 +455,7 @@ export class RewardTransactionContext implements TransactionContext {
}
export async function createRecoupGroup(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
tx: WalletDbReadWriteTransaction<
["recoupGroups", "denominations", "refreshGroups", "coins"]
>,
@@ -476,7 +479,7 @@ export async function createRecoupGroup(
const coinPub = coinPubs[coinIdx];
const coin = await tx.coins.get(coinPub);
if (!coin) {
- await putGroupAsFinished(ws, tx, recoupGroup, coinIdx);
+ await putGroupAsFinished(wex, tx, recoupGroup, coinIdx);
continue;
}
await tx.coins.put(coin);
@@ -491,11 +494,11 @@ export async function createRecoupGroup(
* Run the recoup protocol for a single coin in a recoup group.
*/
async function processRecoupForCoin(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
recoupGroupId: string,
coinIdx: number,
): Promise<void> {
- const coin = await ws.db.runReadOnlyTx(
+ const coin = await wex.db.runReadOnlyTx(
["coins", "recoupGroups"],
async (tx) => {
const recoupGroup = await tx.recoupGroups.get(recoupGroupId);
@@ -527,11 +530,11 @@ async function processRecoupForCoin(
switch (cs.type) {
case CoinSourceType.Reward:
- return recoupRewardCoin(ws, recoupGroupId, coinIdx, coin);
+ return recoupRewardCoin(wex, recoupGroupId, coinIdx, coin);
case CoinSourceType.Refresh:
- return recoupRefreshCoin(ws, recoupGroupId, coinIdx, coin, cs);
+ return recoupRefreshCoin(wex, recoupGroupId, coinIdx, coin, cs);
case CoinSourceType.Withdraw:
- return recoupWithdrawCoin(ws, recoupGroupId, coinIdx, coin, cs);
+ return recoupWithdrawCoin(wex, recoupGroupId, coinIdx, coin, cs);
default:
throw Error("unknown coin source type");
}
diff --git a/packages/taler-wallet-core/src/refresh.ts b/packages/taler-wallet-core/src/refresh.ts
index cc5eff12c..b467a1c47 100644
--- a/packages/taler-wallet-core/src/refresh.ts
+++ b/packages/taler-wallet-core/src/refresh.ts
@@ -21,7 +21,6 @@ import {
Amounts,
amountToPretty,
assertUnreachable,
- CancellationToken,
checkDbInvariant,
codecForExchangeMeltResponse,
codecForExchangeRevealResponse,
@@ -103,6 +102,7 @@ import {
EXCHANGE_COINS_LOCK,
getDenomInfo,
InternalWalletState,
+ WalletExecutionContext,
} from "./wallet.js";
import { getCandidateWithdrawalDenomsTx } from "./withdraw.js";
@@ -113,7 +113,7 @@ export class RefreshTransactionContext implements TransactionContext {
readonly taskId: TaskIdStr;
constructor(
- public ws: InternalWalletState,
+ public wex: WalletExecutionContext,
public refreshGroupId: string,
) {
this.transactionId = constructTransactionIdentifier({
@@ -128,7 +128,7 @@ export class RefreshTransactionContext implements TransactionContext {
async deleteTransaction(): Promise<void> {
const refreshGroupId = this.refreshGroupId;
- const ws = this.ws;
+ const ws = this.wex;
await ws.db.runReadWriteTx(["refreshGroups", "tombstones"], async (tx) => {
const rg = await tx.refreshGroups.get(refreshGroupId);
if (rg) {
@@ -141,8 +141,8 @@ export class RefreshTransactionContext implements TransactionContext {
}
async suspendTransaction(): Promise<void> {
- const { ws, refreshGroupId, transactionId } = this;
- let res = await ws.db.runReadWriteTx(["refreshGroups"], async (tx) => {
+ const { wex, refreshGroupId, transactionId } = this;
+ let res = await wex.db.runReadWriteTx(["refreshGroups"], async (tx) => {
const dg = await tx.refreshGroups.get(refreshGroupId);
if (!dg) {
logger.warn(
@@ -168,7 +168,7 @@ export class RefreshTransactionContext implements TransactionContext {
return undefined;
});
if (res) {
- ws.notify({
+ wex.ws.notify({
type: NotificationType.TransactionStateTransition,
transactionId,
oldTxState: res.oldTxState,
@@ -183,7 +183,7 @@ export class RefreshTransactionContext implements TransactionContext {
}
async resumeTransaction(): Promise<void> {
- const { ws, refreshGroupId, transactionId } = this;
+ const { wex: ws, refreshGroupId, transactionId } = this;
const transitionInfo = await ws.db.runReadWriteTx(
["refreshGroups"],
async (tx) => {
@@ -217,7 +217,7 @@ export class RefreshTransactionContext implements TransactionContext {
}
async failTransaction(): Promise<void> {
- const { ws, refreshGroupId, transactionId } = this;
+ const { wex: ws, refreshGroupId, transactionId } = this;
const transitionInfo = await ws.db.runReadWriteTx(
["refreshGroups"],
async (tx) => {
@@ -331,7 +331,7 @@ function updateGroupStatus(rg: RefreshGroupRecord): { final: boolean } {
* finished), return undefined.
*/
async function provideRefreshSession(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
refreshGroupId: string,
coinIndex: number,
): Promise<RefreshSessionRecord | undefined> {
@@ -339,7 +339,7 @@ async function provideRefreshSession(
`creating refresh session for coin ${coinIndex} in refresh group ${refreshGroupId}`,
);
- const d = await ws.db.runReadWriteTx(
+ const d = await wex.db.runReadWriteTx(
["coins", "refreshGroups", "refreshSessions"],
async (tx) => {
const refreshGroup = await tx.refreshGroups.get(refreshGroupId);
@@ -374,16 +374,16 @@ async function provideRefreshSession(
const { refreshGroup, coin } = d;
- const exch = await fetchFreshExchange(ws, coin.exchangeBaseUrl);
+ const exch = await fetchFreshExchange(wex, coin.exchangeBaseUrl);
// FIXME: use helper functions from withdraw.ts
// to update and filter withdrawable denoms.
- const { availableAmount, availableDenoms } = await ws.db.runReadOnlyTx(
+ const { availableAmount, availableDenoms } = await wex.db.runReadOnlyTx(
["denominations"],
async (tx) => {
const oldDenom = await getDenomInfo(
- ws,
+ wex,
tx,
exch.exchangeBaseUrl,
coin.denomPubHash,
@@ -410,7 +410,7 @@ async function provideRefreshSession(
const newCoinDenoms = selectWithdrawalDenominations(
availableAmount,
availableDenoms,
- ws.config.testing.denomselAllowLate,
+ wex.ws.config.testing.denomselAllowLate,
);
const transactionId = constructTransactionIdentifier({
@@ -424,7 +424,7 @@ async function provideRefreshSession(
availableAmount,
)} too small`,
);
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["refreshGroups", "coins", "coinAvailability"],
async (tx) => {
const rg = await tx.refreshGroups.get(refreshGroupId);
@@ -435,25 +435,25 @@ async function provideRefreshSession(
rg.statusPerCoin[coinIndex] = RefreshCoinStatus.Finished;
const updateRes = updateGroupStatus(rg);
if (updateRes.final) {
- await makeCoinsVisible(ws, tx, transactionId);
+ await makeCoinsVisible(wex, tx, transactionId);
}
await tx.refreshGroups.put(rg);
const newTxState = computeRefreshTransactionState(rg);
return { oldTxState, newTxState };
},
);
- ws.notify({
+ wex.ws.notify({
type: NotificationType.BalanceChange,
hintTransactionId: transactionId,
});
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
return;
}
const sessionSecretSeed = encodeCrock(getRandomBytes(64));
// Store refresh session for this coin in the database.
- const mySession = await ws.db.runReadWriteTx(
+ const mySession = await wex.db.runReadWriteTx(
["refreshGroups", "refreshSessions"],
async (tx) => {
const rg = await tx.refreshGroups.get(refreshGroupId);
@@ -495,12 +495,11 @@ function getRefreshRequestTimeout(rg: RefreshGroupRecord): Duration {
}
async function refreshMelt(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
refreshGroupId: string,
coinIndex: number,
- cancellationToken: CancellationToken,
): Promise<void> {
- const d = await ws.db.runReadWriteTx(
+ const d = await wex.db.runReadWriteTx(
["refreshGroups", "refreshSessions", "coins", "denominations"],
async (tx) => {
const refreshGroup = await tx.refreshGroups.get(refreshGroupId);
@@ -521,7 +520,7 @@ async function refreshMelt(
const oldCoin = await tx.coins.get(refreshGroup.oldCoinPubs[coinIndex]);
checkDbInvariant(!!oldCoin, "melt coin doesn't exist");
const oldDenom = await getDenomInfo(
- ws,
+ wex,
tx,
oldCoin.exchangeBaseUrl,
oldCoin.denomPubHash,
@@ -535,7 +534,7 @@ async function refreshMelt(
for (const dh of refreshSession.newDenoms) {
const newDenom = await getDenomInfo(
- ws,
+ wex,
tx,
oldCoin.exchangeBaseUrl,
dh.denomPubHash,
@@ -572,7 +571,7 @@ async function refreshMelt(
throw Error("unsupported key type");
}
- const derived = await ws.cryptoApi.deriveRefreshSession({
+ const derived = await wex.cryptoApi.deriveRefreshSession({
exchangeProtocolVersion,
kappa: 3,
meltCoinDenomPubHash: oldCoin.denomPubHash,
@@ -607,14 +606,17 @@ async function refreshMelt(
age_commitment_hash: maybeAch,
};
- const resp = await ws.runSequentialized([EXCHANGE_COINS_LOCK], async () => {
- return await ws.http.fetch(reqUrl.href, {
- method: "POST",
- body: meltReqBody,
- timeout: getRefreshRequestTimeout(refreshGroup),
- cancellationToken,
- });
- });
+ const resp = await wex.ws.runSequentialized(
+ [EXCHANGE_COINS_LOCK],
+ async () => {
+ return await wex.http.fetch(reqUrl.href, {
+ method: "POST",
+ body: meltReqBody,
+ timeout: getRefreshRequestTimeout(refreshGroup),
+ cancellationToken: wex.cancellationToken,
+ });
+ },
+ );
const transactionId = constructTransactionIdentifier({
tag: TransactionType.Refresh,
@@ -623,7 +625,7 @@ async function refreshMelt(
if (resp.status === HttpStatusCode.NotFound) {
const errDetails = await readUnexpectedResponseDetails(resp);
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["refreshGroups", "refreshSessions", "coins", "coinAvailability"],
async (tx) => {
const rg = await tx.refreshGroups.get(refreshGroupId);
@@ -650,7 +652,7 @@ async function refreshMelt(
refreshSession.lastError = errDetails;
const updateRes = updateGroupStatus(rg);
if (updateRes.final) {
- await makeCoinsVisible(ws, tx, transactionId);
+ await makeCoinsVisible(wex, tx, transactionId);
}
await tx.refreshGroups.put(rg);
await tx.refreshSessions.put(refreshSession);
@@ -661,11 +663,11 @@ async function refreshMelt(
};
},
);
- ws.notify({
+ wex.ws.notify({
type: NotificationType.BalanceChange,
hintTransactionId: transactionId,
});
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
return;
}
@@ -678,7 +680,7 @@ async function refreshMelt(
)} failed in refresh group ${refreshGroupId} due to conflict`,
);
- const historySig = await ws.cryptoApi.signCoinHistoryRequest({
+ const historySig = await wex.cryptoApi.signCoinHistoryRequest({
coinPriv: oldCoin.coinPriv,
coinPub: oldCoin.coinPub,
startOffset: 0,
@@ -689,12 +691,12 @@ async function refreshMelt(
oldCoin.exchangeBaseUrl,
);
- const historyResp = await ws.http.fetch(historyUrl.href, {
+ const historyResp = await wex.http.fetch(historyUrl.href, {
method: "GET",
headers: {
"Taler-Coin-History-Signature": historySig.sig,
},
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
const historyJson = await historyResp.json();
@@ -712,7 +714,7 @@ async function refreshMelt(
refreshSession.norevealIndex = norevealIndex;
- await ws.db.runReadWriteTx(
+ await wex.db.runReadWriteTx(
["refreshGroups", "refreshSessions"],
async (tx) => {
const rg = await tx.refreshGroups.get(refreshGroupId);
@@ -794,15 +796,14 @@ export async function assembleRefreshRevealRequest(args: {
}
async function refreshReveal(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
refreshGroupId: string,
coinIndex: number,
- cancellationToken: CancellationToken,
): Promise<void> {
logger.trace(
`doing refresh reveal for ${refreshGroupId} (old coin ${coinIndex})`,
);
- const d = await ws.db.runReadOnlyTx(
+ const d = await wex.db.runReadOnlyTx(
["refreshGroups", "refreshSessions", "coins", "denominations"],
async (tx) => {
const refreshGroup = await tx.refreshGroups.get(refreshGroupId);
@@ -824,7 +825,7 @@ async function refreshReveal(
const oldCoin = await tx.coins.get(refreshGroup.oldCoinPubs[coinIndex]);
checkDbInvariant(!!oldCoin, "melt coin doesn't exist");
const oldDenom = await getDenomInfo(
- ws,
+ wex,
tx,
oldCoin.exchangeBaseUrl,
oldCoin.denomPubHash,
@@ -838,7 +839,7 @@ async function refreshReveal(
for (const dh of refreshSession.newDenoms) {
const newDenom = await getDenomInfo(
- ws,
+ wex,
tx,
oldCoin.exchangeBaseUrl,
dh.denomPubHash,
@@ -889,7 +890,7 @@ async function refreshReveal(
throw Error("unsupported key type");
}
- const derived = await ws.cryptoApi.deriveRefreshSession({
+ const derived = await wex.cryptoApi.deriveRefreshSession({
exchangeProtocolVersion,
kappa: 3,
meltCoinDenomPubHash: oldCoin.denomPubHash,
@@ -908,7 +909,7 @@ async function refreshReveal(
);
const req = await assembleRefreshRevealRequest({
- cryptoApi: ws.cryptoApi,
+ cryptoApi: wex.cryptoApi,
derived,
newDenoms: newCoinDenoms,
norevealIndex: norevealIndex,
@@ -917,14 +918,17 @@ async function refreshReveal(
oldAgeCommitment: oldCoin.ageCommitmentProof?.commitment,
});
- const resp = await ws.runSequentialized([EXCHANGE_COINS_LOCK], async () => {
- return await ws.http.fetch(reqUrl.href, {
- body: req,
- method: "POST",
- timeout: getRefreshRequestTimeout(refreshGroup),
- cancellationToken,
- });
- });
+ const resp = await wex.ws.runSequentialized(
+ [EXCHANGE_COINS_LOCK],
+ async () => {
+ return await wex.http.fetch(reqUrl.href, {
+ body: req,
+ method: "POST",
+ timeout: getRefreshRequestTimeout(refreshGroup),
+ cancellationToken: wex.cancellationToken,
+ });
+ },
+ );
const reveal = await readSuccessResponseJsonOrThrow(
resp,
@@ -947,7 +951,7 @@ async function refreshReveal(
throw Error("cipher unsupported");
}
const evSig = reveal.ev_sigs[newCoinIndex].ev_sig;
- const denomSig = await ws.cryptoApi.unblindDenominationSignature({
+ const denomSig = await wex.cryptoApi.unblindDenominationSignature({
planchet: {
blindingKey: pc.blindingKey,
denomPub: ncd.denomPub,
@@ -978,7 +982,7 @@ async function refreshReveal(
}
}
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
[
"coins",
"denominations",
@@ -1000,26 +1004,25 @@ async function refreshReveal(
rg.statusPerCoin[coinIndex] = RefreshCoinStatus.Finished;
updateGroupStatus(rg);
for (const coin of coins) {
- await makeCoinAvailable(ws, tx, coin);
+ await makeCoinAvailable(wex, tx, coin);
}
- await makeCoinsVisible(ws, tx, transactionId);
+ await makeCoinsVisible(wex, tx, transactionId);
await tx.refreshGroups.put(rg);
const newTxState = computeRefreshTransactionState(rg);
return { oldTxState, newTxState };
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
logger.trace("refresh finished (end of reveal)");
}
export async function processRefreshGroup(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
refreshGroupId: string,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
logger.trace(`processing refresh group ${refreshGroupId}`);
- const refreshGroup = await ws.db.runReadOnlyTx(
+ const refreshGroup = await wex.db.runReadOnlyTx(
["refreshGroups"],
async (tx) => tx.refreshGroups.get(refreshGroupId),
);
@@ -1036,28 +1039,26 @@ export async function processRefreshGroup(
let errors: TalerErrorDetail[] = [];
let inShutdown = false;
const ps = refreshGroup.oldCoinPubs.map((x, i) =>
- processRefreshSession(ws, refreshGroupId, i, cancellationToken).catch(
- (x) => {
- if (x instanceof CryptoApiStoppedError) {
- inShutdown = true;
- logger.info(
- "crypto API stopped while processing refresh group, probably the wallet is currently shutting down.",
- );
- return;
- }
- if (x instanceof TalerError) {
- logger.warn("process refresh session got exception (TalerError)");
- logger.warn(`exc ${x}`);
- logger.warn(`exc stack ${x.stack}`);
- logger.warn(`error detail: ${j2s(x.errorDetail)}`);
- } else {
- logger.warn("process refresh session got exception");
- logger.warn(`exc ${x}`);
- logger.warn(`exc stack ${x.stack}`);
- }
- errors.push(getErrorDetailFromException(x));
- },
- ),
+ processRefreshSession(wex, refreshGroupId, i).catch((x) => {
+ if (x instanceof CryptoApiStoppedError) {
+ inShutdown = true;
+ logger.info(
+ "crypto API stopped while processing refresh group, probably the wallet is currently shutting down.",
+ );
+ return;
+ }
+ if (x instanceof TalerError) {
+ logger.warn("process refresh session got exception (TalerError)");
+ logger.warn(`exc ${x}`);
+ logger.warn(`exc stack ${x.stack}`);
+ logger.warn(`error detail: ${j2s(x.errorDetail)}`);
+ } else {
+ logger.warn("process refresh session got exception");
+ logger.warn(`exc ${x}`);
+ logger.warn(`exc stack ${x.stack}`);
+ }
+ errors.push(getErrorDetailFromException(x));
+ }),
);
try {
logger.info("waiting for refreshes");
@@ -1087,15 +1088,14 @@ export async function processRefreshGroup(
}
async function processRefreshSession(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
refreshGroupId: string,
coinIndex: number,
- cancellationToken: CancellationToken,
): Promise<void> {
logger.trace(
`processing refresh session for coin ${coinIndex} of group ${refreshGroupId}`,
);
- let { refreshGroup, refreshSession } = await ws.db.runReadOnlyTx(
+ let { refreshGroup, refreshSession } = await wex.db.runReadOnlyTx(
["refreshGroups", "refreshSessions"],
async (tx) => {
const rg = await tx.refreshGroups.get(refreshGroupId);
@@ -1113,7 +1113,11 @@ async function processRefreshSession(
return;
}
if (!refreshSession) {
- refreshSession = await provideRefreshSession(ws, refreshGroupId, coinIndex);
+ refreshSession = await provideRefreshSession(
+ wex,
+ refreshGroupId,
+ coinIndex,
+ );
}
if (!refreshSession) {
// We tried to create the refresh session, but didn't get a result back.
@@ -1122,9 +1126,9 @@ async function processRefreshSession(
return;
}
if (refreshSession.norevealIndex === undefined) {
- await refreshMelt(ws, refreshGroupId, coinIndex, cancellationToken);
+ await refreshMelt(wex, refreshGroupId, coinIndex);
}
- await refreshReveal(ws, refreshGroupId, coinIndex, cancellationToken);
+ await refreshReveal(wex, refreshGroupId, coinIndex);
}
export interface RefreshOutputInfo {
@@ -1133,7 +1137,7 @@ export interface RefreshOutputInfo {
}
export async function calculateRefreshOutput(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
tx: WalletDbReadOnlyTransaction<
["denominations", "coins", "refreshGroups", "coinAvailability"]
>,
@@ -1154,7 +1158,7 @@ export async function calculateRefreshOutput(
return denomsPerExchange[exchangeBaseUrl];
}
const allDenoms = await getCandidateWithdrawalDenomsTx(
- ws,
+ wex,
tx,
exchangeBaseUrl,
currency,
@@ -1167,7 +1171,7 @@ export async function calculateRefreshOutput(
const coin = await tx.coins.get(ocp.coinPub);
checkDbInvariant(!!coin, "coin must be in database");
const denom = await getDenomInfo(
- ws,
+ wex,
tx,
coin.exchangeBaseUrl,
coin.denomPubHash,
@@ -1182,7 +1186,7 @@ export async function calculateRefreshOutput(
denoms,
denom,
Amounts.parseOrThrow(refreshAmount),
- ws.config.testing.denomselAllowLate,
+ wex.ws.config.testing.denomselAllowLate,
);
const output = Amounts.sub(refreshAmount, cost).amount;
let exchInfo = infoPerExchange[coin.exchangeBaseUrl];
@@ -1204,7 +1208,7 @@ export async function calculateRefreshOutput(
}
async function applyRefresh(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
tx: WalletDbReadWriteTransaction<
["denominations", "coins", "refreshGroups", "coinAvailability"]
>,
@@ -1215,7 +1219,7 @@ async function applyRefresh(
const coin = await tx.coins.get(ocp.coinPub);
checkDbInvariant(!!coin, "coin must be in database");
const denom = await getDenomInfo(
- ws,
+ wex,
tx,
coin.exchangeBaseUrl,
coin.denomPubHash,
@@ -1278,7 +1282,7 @@ export interface CreateRefreshGroupResult {
* in the current database transaction.
*/
export async function createRefreshGroup(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
tx: WalletDbReadWriteTransaction<
["denominations", "coins", "refreshGroups", "coinAvailability"]
>,
@@ -1289,11 +1293,11 @@ export async function createRefreshGroup(
): Promise<CreateRefreshGroupResult> {
const refreshGroupId = encodeCrock(getRandomBytes(32));
- const outInfo = await calculateRefreshOutput(ws, tx, currency, oldCoinPubs);
+ const outInfo = await calculateRefreshOutput(wex, tx, currency, oldCoinPubs);
const estimatedOutputPerCoin = outInfo.outputPerCoin;
- await applyRefresh(ws, tx, oldCoinPubs, refreshGroupId);
+ await applyRefresh(wex, tx, oldCoinPubs, refreshGroupId);
const refreshGroup: RefreshGroupRecord = {
operationStatus: RefreshOperationStatus.Pending,
@@ -1326,12 +1330,12 @@ export async function createRefreshGroup(
logger.trace(`created refresh group ${refreshGroupId}`);
- const ctx = new RefreshTransactionContext(ws, refreshGroupId);
+ const ctx = new RefreshTransactionContext(wex, refreshGroupId);
// Shepherd the task.
// If the current transaction fails to commit the refresh
// group to the DB, the shepherd will give up.
- ws.taskScheduler.startShepherdTask(ctx.taskId);
+ wex.taskScheduler.startShepherdTask(ctx.taskId);
return {
refreshGroupId,
@@ -1391,10 +1395,10 @@ export function computeRefreshTransactionActions(
}
export function getRefreshesForTransaction(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
transactionId: string,
): Promise<string[]> {
- return ws.db.runReadOnlyTx(["refreshGroups"], async (tx) => {
+ return wex.db.runReadOnlyTx(["refreshGroups"], async (tx) => {
const groups =
await tx.refreshGroups.indexes.byOriginatingTransactionId.getAll(
transactionId,
@@ -1409,13 +1413,13 @@ export function getRefreshesForTransaction(
}
export async function forceRefresh(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: ForceRefreshRequest,
): Promise<{ refreshGroupId: RefreshGroupId }> {
if (req.coinPubList.length == 0) {
throw Error("refusing to create empty refresh group");
}
- const refreshGroupId = await ws.db.runReadWriteTx(
+ const refreshGroupId = await wex.db.runReadWriteTx(
["refreshGroups", "coinAvailability", "denominations", "coins"],
async (tx) => {
let coinPubs: CoinRefreshRequest[] = [];
@@ -1425,7 +1429,7 @@ export async function forceRefresh(
throw Error(`coin (pubkey ${c}) not found`);
}
const denom = await getDenomInfo(
- ws,
+ wex,
tx,
coin.exchangeBaseUrl,
coin.denomPubHash,
@@ -1437,7 +1441,7 @@ export async function forceRefresh(
});
}
return await createRefreshGroup(
- ws,
+ wex,
tx,
Amounts.currencyOf(coinPubs[0].amount),
coinPubs,
diff --git a/packages/taler-wallet-core/src/reward.ts b/packages/taler-wallet-core/src/reward.ts
index 51eb0f5bd..b8cf41326 100644
--- a/packages/taler-wallet-core/src/reward.ts
+++ b/packages/taler-wallet-core/src/reward.ts
@@ -42,7 +42,7 @@ import {
constructTransactionIdentifier,
notifyTransition,
} from "./transactions.js";
-import { InternalWalletState } from "./wallet.js";
+import { InternalWalletState, WalletExecutionContext } from "./wallet.js";
const logger = new Logger("operations/tip.ts");
@@ -51,7 +51,7 @@ export class RewardTransactionContext implements TransactionContext {
public taskId: TaskIdStr;
constructor(
- public ws: InternalWalletState,
+ public wex: WalletExecutionContext,
public walletRewardId: string,
) {
this.transactionId = constructTransactionIdentifier({
@@ -65,8 +65,8 @@ export class RewardTransactionContext implements TransactionContext {
}
async deleteTransaction(): Promise<void> {
- const { ws, walletRewardId } = this;
- await ws.db.runReadWriteTx(["rewards", "tombstones"], async (tx) => {
+ const { wex, walletRewardId } = this;
+ await wex.db.runReadWriteTx(["rewards", "tombstones"], async (tx) => {
const tipRecord = await tx.rewards.get(walletRewardId);
if (tipRecord) {
await tx.rewards.delete(walletRewardId);
@@ -78,8 +78,8 @@ export class RewardTransactionContext implements TransactionContext {
}
async suspendTransaction(): Promise<void> {
- const { ws, walletRewardId, transactionId, taskId: retryTag } = this;
- const transitionInfo = await ws.db.runReadWriteTx(
+ const { wex, walletRewardId, transactionId, taskId } = this;
+ const transitionInfo = await wex.db.runReadWriteTx(
["rewards"],
async (tx) => {
const tipRec = await tx.rewards.get(walletRewardId);
@@ -115,12 +115,12 @@ export class RewardTransactionContext implements TransactionContext {
return undefined;
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
}
async abortTransaction(): Promise<void> {
- const { ws, walletRewardId, transactionId, taskId: retryTag } = this;
- const transitionInfo = await ws.db.runReadWriteTx(
+ const { wex, walletRewardId, transactionId } = this;
+ const transitionInfo = await wex.db.runReadWriteTx(
["rewards"],
async (tx) => {
const tipRec = await tx.rewards.get(walletRewardId);
@@ -155,11 +155,11 @@ export class RewardTransactionContext implements TransactionContext {
return undefined;
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
}
async resumeTransaction(): Promise<void> {
- const { ws, walletRewardId, transactionId, taskId: retryTag } = this;
+ const { wex: ws, walletRewardId, transactionId, taskId: retryTag } = this;
const transitionInfo = await ws.db.runReadWriteTx(
["rewards"],
async (tx) => {
@@ -199,7 +199,7 @@ export class RewardTransactionContext implements TransactionContext {
}
async failTransaction(): Promise<void> {
- const { ws, walletRewardId, transactionId, taskId: retryTag } = this;
+ const { wex: ws, walletRewardId, transactionId, taskId: retryTag } = this;
const transitionInfo = await ws.db.runReadWriteTx(
["rewards"],
async (tx) => {
diff --git a/packages/taler-wallet-core/src/shepherd.ts b/packages/taler-wallet-core/src/shepherd.ts
index ec0f6a76e..e3a0bd609 100644
--- a/packages/taler-wallet-core/src/shepherd.ts
+++ b/packages/taler-wallet-core/src/shepherd.ts
@@ -93,7 +93,7 @@ import {
constructTransactionIdentifier,
parseTransactionIdentifier,
} from "./transactions.js";
-import { InternalWalletState } from "./wallet.js";
+import { InternalWalletState, WalletExecutionContext } from "./wallet.js";
import {
computeWithdrawalTransactionStatus,
processWithdrawalGroup,
@@ -563,66 +563,41 @@ async function callOperationHandlerForTaskId(
taskId: TaskIdStr,
cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
+ const wex: WalletExecutionContext = {
+ ws,
+ cancellationToken,
+ cryptoApi: ws.cryptoApi,
+ db: ws.db,
+ http: ws.http,
+ taskScheduler: ws.taskScheduler,
+ oc: {
+ observe(event) {},
+ },
+ };
const pending = parseTaskIdentifier(taskId);
switch (pending.tag) {
case PendingTaskType.ExchangeUpdate:
- return await updateExchangeFromUrlHandler(
- ws,
- pending.exchangeBaseUrl,
- cancellationToken,
- );
+ return await updateExchangeFromUrlHandler(wex, pending.exchangeBaseUrl);
case PendingTaskType.Refresh:
- return await processRefreshGroup(
- ws,
- pending.refreshGroupId,
- cancellationToken,
- );
+ return await processRefreshGroup(wex, pending.refreshGroupId);
case PendingTaskType.Withdraw:
- return await processWithdrawalGroup(
- ws,
- pending.withdrawalGroupId,
- cancellationToken,
- );
+ return await processWithdrawalGroup(wex, pending.withdrawalGroupId);
case PendingTaskType.Purchase:
- return await processPurchase(ws, pending.proposalId, cancellationToken);
+ return await processPurchase(wex, pending.proposalId);
case PendingTaskType.Recoup:
- return await processRecoupGroup(
- ws,
- pending.recoupGroupId,
- cancellationToken,
- );
+ return await processRecoupGroup(wex, pending.recoupGroupId);
case PendingTaskType.Deposit:
- return await processDepositGroup(
- ws,
- pending.depositGroupId,
- cancellationToken,
- );
+ return await processDepositGroup(wex, pending.depositGroupId);
case PendingTaskType.Backup:
- return await processBackupForProvider(ws, pending.backupProviderBaseUrl);
+ return await processBackupForProvider(wex, pending.backupProviderBaseUrl);
case PendingTaskType.PeerPushDebit:
- return await processPeerPushDebit(
- ws,
- pending.pursePub,
- cancellationToken,
- );
+ return await processPeerPushDebit(wex, pending.pursePub);
case PendingTaskType.PeerPullCredit:
- return await processPeerPullCredit(
- ws,
- pending.pursePub,
- cancellationToken,
- );
+ return await processPeerPullCredit(wex, pending.pursePub);
case PendingTaskType.PeerPullDebit:
- return await processPeerPullDebit(
- ws,
- pending.peerPullDebitId,
- cancellationToken,
- );
+ return await processPeerPullDebit(wex, pending.peerPullDebitId);
case PendingTaskType.PeerPushCredit:
- return await processPeerPushCredit(
- ws,
- pending.peerPushCreditId,
- cancellationToken,
- );
+ return await processPeerPushCredit(wex, pending.peerPushCreditId);
case PendingTaskType.RewardPickup:
throw Error("not supported anymore");
default:
diff --git a/packages/taler-wallet-core/src/testing.ts b/packages/taler-wallet-core/src/testing.ts
index 22af816e5..45a29a6e3 100644
--- a/packages/taler-wallet-core/src/testing.ts
+++ b/packages/taler-wallet-core/src/testing.ts
@@ -77,7 +77,7 @@ import {
import { initiatePeerPushDebit } from "./pay-peer-push-debit.js";
import { getRefreshesForTransaction } from "./refresh.js";
import { getTransactionById, getTransactions } from "./transactions.js";
-import type { InternalWalletState } from "./wallet.js";
+import type { InternalWalletState, WalletExecutionContext } from "./wallet.js";
import { acceptWithdrawalFromUri } from "./withdraw.js";
const logger = new Logger("operations/testing.ts");
@@ -100,7 +100,7 @@ export interface WithdrawTestBalanceResult {
}
export async function withdrawTestBalance(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: WithdrawTestBalanceRequest,
): Promise<WithdrawTestBalanceResult> {
const amount = req.amount;
@@ -123,7 +123,7 @@ export async function withdrawTestBalance(
amount,
);
- const acceptResp = await acceptWithdrawalFromUri(ws, {
+ const acceptResp = await acceptWithdrawalFromUri(wex, {
talerWithdrawUri: wresp.taler_withdraw_uri,
selectedExchange: exchangeBaseUrl,
forcedDenomSel: req.forcedDenomSel,
@@ -239,13 +239,13 @@ interface MakePaymentResult {
}
async function makePayment(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
merchant: MerchantBackendInfo,
amount: string,
summary: string,
): Promise<MakePaymentResult> {
const orderResp = await createOrder(
- ws.http,
+ wex.http,
merchant,
amount,
summary,
@@ -254,7 +254,7 @@ async function makePayment(
logger.trace("created order with orderId", orderResp.orderId);
- let paymentStatus = await checkPayment(ws.http, merchant, orderResp.orderId);
+ let paymentStatus = await checkPayment(wex.http, merchant, orderResp.orderId);
logger.trace("payment status", paymentStatus);
@@ -263,7 +263,7 @@ async function makePayment(
throw Error("no taler://pay/ URI in payment response");
}
- const preparePayResult = await preparePayForUri(ws, talerPayUri);
+ const preparePayResult = await preparePayForUri(wex, talerPayUri);
logger.trace("prepare pay result", preparePayResult);
@@ -272,14 +272,14 @@ async function makePayment(
}
const confirmPayResult = await confirmPay(
- ws,
+ wex,
preparePayResult.transactionId,
undefined,
);
logger.trace("confirmPayResult", confirmPayResult);
- paymentStatus = await checkPayment(ws.http, merchant, orderResp.orderId);
+ paymentStatus = await checkPayment(wex.http, merchant, orderResp.orderId);
logger.trace("payment status after wallet payment:", paymentStatus);
@@ -294,7 +294,7 @@ async function makePayment(
}
export async function runIntegrationTest(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
args: IntegrationTestArgs,
): Promise<void> {
logger.info("running test with arguments", args);
@@ -303,15 +303,15 @@ export async function runIntegrationTest(
const currency = parsedSpendAmount.currency;
logger.info("withdrawing test balance");
- const withdrawRes1 = await withdrawTestBalance(ws, {
+ const withdrawRes1 = await withdrawTestBalance(wex, {
amount: args.amountToWithdraw,
corebankApiBaseUrl: args.corebankApiBaseUrl,
exchangeBaseUrl: args.exchangeBaseUrl,
});
- await waitUntilGivenTransactionsFinal(ws, [withdrawRes1.transactionId]);
+ await waitUntilGivenTransactionsFinal(wex, [withdrawRes1.transactionId]);
logger.info("done withdrawing test balance");
- const balance = await getBalances(ws);
+ const balance = await getBalances(wex);
logger.trace(JSON.stringify(balance, null, 2));
@@ -321,14 +321,14 @@ export async function runIntegrationTest(
};
const makePaymentRes = await makePayment(
- ws,
+ wex,
myMerchant,
args.amountToSpend,
"hello world",
);
await waitUntilTransactionWithAssociatedRefreshesFinal(
- ws,
+ wex,
makePaymentRes.paymentTransactionId,
);
@@ -338,23 +338,23 @@ export async function runIntegrationTest(
const refundAmount = Amounts.parseOrThrow(`${currency}:6`);
const spendAmountThree = Amounts.parseOrThrow(`${currency}:3`);
- const withdrawRes2 = await withdrawTestBalance(ws, {
+ const withdrawRes2 = await withdrawTestBalance(wex, {
amount: Amounts.stringify(withdrawAmountTwo),
corebankApiBaseUrl: args.corebankApiBaseUrl,
exchangeBaseUrl: args.exchangeBaseUrl,
});
- await waitUntilGivenTransactionsFinal(ws, [withdrawRes2.transactionId]);
+ await waitUntilGivenTransactionsFinal(wex, [withdrawRes2.transactionId]);
const { orderId: refundOrderId } = await makePayment(
- ws,
+ wex,
myMerchant,
Amounts.stringify(spendAmountTwo),
"order that will be refunded",
);
const refundUri = await refund(
- ws.http,
+ wex.http,
myMerchant,
refundOrderId,
"test refund",
@@ -363,20 +363,20 @@ export async function runIntegrationTest(
logger.trace("refund URI", refundUri);
- const refundResp = await startRefundQueryForUri(ws, refundUri);
+ const refundResp = await startRefundQueryForUri(wex, refundUri);
logger.trace("integration test: applied refund");
// Wait until the refund is done
await waitUntilTransactionWithAssociatedRefreshesFinal(
- ws,
+ wex,
refundResp.transactionId,
);
logger.trace("integration test: making payment after refund");
const paymentResp2 = await makePayment(
- ws,
+ wex,
myMerchant,
Amounts.stringify(spendAmountThree),
"payment after refund",
@@ -384,12 +384,12 @@ export async function runIntegrationTest(
logger.trace("integration test: make payment done");
- await waitUntilGivenTransactionsFinal(ws, [
+ await waitUntilGivenTransactionsFinal(wex, [
paymentResp2.paymentTransactionId,
]);
await waitUntilGivenTransactionsFinal(
- ws,
- await getRefreshesForTransaction(ws, paymentResp2.paymentTransactionId),
+ wex,
+ await getRefreshesForTransaction(wex, paymentResp2.paymentTransactionId),
);
logger.trace("integration test: all done!");
@@ -399,12 +399,12 @@ export async function runIntegrationTest(
* Wait until all transactions are in a final state.
*/
export async function waitUntilAllTransactionsFinal(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
): Promise<void> {
logger.info("waiting until all transactions are in a final state");
- ws.taskScheduler.ensureRunning();
+ wex.taskScheduler.ensureRunning();
let p: OpenedPromise<void> | undefined = undefined;
- const cancelNotifs = ws.addNotificationListener((notif) => {
+ const cancelNotifs = wex.ws.addNotificationListener((notif) => {
if (!p) {
return;
}
@@ -420,7 +420,7 @@ export async function waitUntilAllTransactionsFinal(
});
while (1) {
p = openPromise();
- const txs = await getTransactions(ws, {
+ const txs = await getTransactions(wex, {
includeRefreshes: true,
filterByState: "nonfinal",
});
@@ -452,7 +452,7 @@ export async function waitUntilAllTransactionsFinal(
* Wait until all chosen transactions are in a final state.
*/
export async function waitUntilGivenTransactionsFinal(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
transactionIds: string[],
): Promise<void> {
logger.info(
@@ -462,10 +462,10 @@ export async function waitUntilGivenTransactionsFinal(
if (transactionIds.length === 0) {
return;
}
- ws.taskScheduler.ensureRunning();
+ wex.taskScheduler.ensureRunning();
const txIdSet = new Set(transactionIds);
let p: OpenedPromise<void> | undefined = undefined;
- const cancelNotifs = ws.addNotificationListener((notif) => {
+ const cancelNotifs = wex.ws.addNotificationListener((notif) => {
if (!p) {
return;
}
@@ -486,7 +486,7 @@ export async function waitUntilGivenTransactionsFinal(
});
while (1) {
p = openPromise();
- const txs = await getTransactions(ws, {
+ const txs = await getTransactions(wex, {
includeRefreshes: true,
filterByState: "nonfinal",
});
@@ -519,12 +519,12 @@ export async function waitUntilGivenTransactionsFinal(
}
export async function waitUntilRefreshesDone(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
): Promise<void> {
logger.info("waiting until all refresh transactions are in a final state");
- ws.taskScheduler.ensureRunning();
+ wex.taskScheduler.ensureRunning();
let p: OpenedPromise<void> | undefined = undefined;
- const cancelNotifs = ws.addNotificationListener((notif) => {
+ const cancelNotifs = wex.ws.addNotificationListener((notif) => {
if (!p) {
return;
}
@@ -540,7 +540,7 @@ export async function waitUntilRefreshesDone(
});
while (1) {
p = openPromise();
- const txs = await getTransactions(ws, {
+ const txs = await getTransactions(wex, {
includeRefreshes: true,
filterByState: "nonfinal",
});
@@ -572,13 +572,13 @@ export async function waitUntilRefreshesDone(
}
async function waitUntilTransactionPendingReady(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
transactionId: string,
): Promise<void> {
logger.info(`starting waiting for ${transactionId} to be in pending(ready)`);
- ws.taskScheduler.ensureRunning();
+ wex.taskScheduler.ensureRunning();
let p: OpenedPromise<void> | undefined = undefined;
- const cancelNotifs = ws.addNotificationListener((notif) => {
+ const cancelNotifs = wex.ws.addNotificationListener((notif) => {
if (!p) {
return;
}
@@ -588,7 +588,7 @@ async function waitUntilTransactionPendingReady(
});
while (1) {
p = openPromise();
- const tx = await getTransactionById(ws, {
+ const tx = await getTransactionById(wex, {
transactionId,
});
if (
@@ -608,7 +608,7 @@ async function waitUntilTransactionPendingReady(
* Wait until a transaction is in a particular state.
*/
export async function waitTransactionState(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
transactionId: string,
txState: TransactionState,
): Promise<void> {
@@ -617,9 +617,9 @@ export async function waitTransactionState(
txState,
)})`,
);
- ws.taskScheduler.ensureRunning();
+ wex.taskScheduler.ensureRunning();
let p: OpenedPromise<void> | undefined = undefined;
- const cancelNotifs = ws.addNotificationListener((notif) => {
+ const cancelNotifs = wex.ws.addNotificationListener((notif) => {
if (!p) {
return;
}
@@ -629,7 +629,7 @@ export async function waitTransactionState(
});
while (1) {
p = openPromise();
- const tx = await getTransactionById(ws, {
+ const tx = await getTransactionById(wex, {
transactionId,
});
if (
@@ -648,31 +648,31 @@ export async function waitTransactionState(
}
export async function waitUntilTransactionWithAssociatedRefreshesFinal(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
transactionId: string,
): Promise<void> {
- await waitUntilGivenTransactionsFinal(ws, [transactionId]);
+ await waitUntilGivenTransactionsFinal(wex, [transactionId]);
await waitUntilGivenTransactionsFinal(
- ws,
- await getRefreshesForTransaction(ws, transactionId),
+ wex,
+ await getRefreshesForTransaction(wex, transactionId),
);
}
export async function waitUntilTransactionFinal(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
transactionId: string,
): Promise<void> {
- await waitUntilGivenTransactionsFinal(ws, [transactionId]);
+ await waitUntilGivenTransactionsFinal(wex, [transactionId]);
}
export async function runIntegrationTest2(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
args: IntegrationTestV2Args,
): Promise<void> {
- ws.taskScheduler.ensureRunning();
+ wex.taskScheduler.ensureRunning();
logger.info("running test with arguments", args);
- const exchangeInfo = await fetchFreshExchange(ws, args.exchangeBaseUrl);
+ const exchangeInfo = await fetchFreshExchange(wex, args.exchangeBaseUrl);
const currency = exchangeInfo.currency;
@@ -680,15 +680,15 @@ export async function runIntegrationTest2(
const amountToSpend = Amounts.parseOrThrow(`${currency}:2`);
logger.info("withdrawing test balance");
- const withdrawalRes = await withdrawTestBalance(ws, {
+ const withdrawalRes = await withdrawTestBalance(wex, {
amount: Amounts.stringify(amountToWithdraw),
corebankApiBaseUrl: args.corebankApiBaseUrl,
exchangeBaseUrl: args.exchangeBaseUrl,
});
- await waitUntilTransactionFinal(ws, withdrawalRes.transactionId);
+ await waitUntilTransactionFinal(wex, withdrawalRes.transactionId);
logger.info("done withdrawing test balance");
- const balance = await getBalances(ws);
+ const balance = await getBalances(wex);
logger.trace(JSON.stringify(balance, null, 2));
@@ -698,14 +698,14 @@ export async function runIntegrationTest2(
};
const makePaymentRes = await makePayment(
- ws,
+ wex,
myMerchant,
Amounts.stringify(amountToSpend),
"hello world",
);
await waitUntilTransactionWithAssociatedRefreshesFinal(
- ws,
+ wex,
makePaymentRes.paymentTransactionId,
);
@@ -715,24 +715,24 @@ export async function runIntegrationTest2(
const refundAmount = Amounts.parseOrThrow(`${currency}:6`);
const spendAmountThree = Amounts.parseOrThrow(`${currency}:3`);
- const withdrawalRes2 = await withdrawTestBalance(ws, {
+ const withdrawalRes2 = await withdrawTestBalance(wex, {
amount: Amounts.stringify(withdrawAmountTwo),
corebankApiBaseUrl: args.corebankApiBaseUrl,
exchangeBaseUrl: args.exchangeBaseUrl,
});
// Wait until the withdraw is done
- await waitUntilTransactionFinal(ws, withdrawalRes2.transactionId);
+ await waitUntilTransactionFinal(wex, withdrawalRes2.transactionId);
const { orderId: refundOrderId } = await makePayment(
- ws,
+ wex,
myMerchant,
Amounts.stringify(spendAmountTwo),
"order that will be refunded",
);
const refundUri = await refund(
- ws.http,
+ wex.http,
myMerchant,
refundOrderId,
"test refund",
@@ -741,33 +741,33 @@ export async function runIntegrationTest2(
logger.trace("refund URI", refundUri);
- const refundResp = await startRefundQueryForUri(ws, refundUri);
+ const refundResp = await startRefundQueryForUri(wex, refundUri);
logger.trace("integration test: applied refund");
// Wait until the refund is done
await waitUntilTransactionWithAssociatedRefreshesFinal(
- ws,
+ wex,
refundResp.transactionId,
);
logger.trace("integration test: making payment after refund");
const makePaymentRes2 = await makePayment(
- ws,
+ wex,
myMerchant,
Amounts.stringify(spendAmountThree),
"payment after refund",
);
await waitUntilTransactionWithAssociatedRefreshesFinal(
- ws,
+ wex,
makePaymentRes2.paymentTransactionId,
);
logger.trace("integration test: make payment done");
- const peerPushInit = await initiatePeerPushDebit(ws, {
+ const peerPushInit = await initiatePeerPushDebit(wex, {
partialContractTerms: {
amount: `${currency}:1` as AmountString,
summary: "Payment Peer Push Test",
@@ -780,8 +780,8 @@ export async function runIntegrationTest2(
},
});
- await waitUntilTransactionPendingReady(ws, peerPushInit.transactionId);
- const txDetails = await getTransactionById(ws, {
+ await waitUntilTransactionPendingReady(wex, peerPushInit.transactionId);
+ const txDetails = await getTransactionById(wex, {
transactionId: peerPushInit.transactionId,
});
@@ -793,15 +793,15 @@ export async function runIntegrationTest2(
throw Error("internal invariant failed");
}
- const peerPushCredit = await preparePeerPushCredit(ws, {
+ const peerPushCredit = await preparePeerPushCredit(wex, {
talerUri: txDetails.talerUri,
});
- await confirmPeerPushCredit(ws, {
+ await confirmPeerPushCredit(wex, {
transactionId: peerPushCredit.transactionId,
});
- const peerPullInit = await initiatePeerPullPayment(ws, {
+ const peerPullInit = await initiatePeerPullPayment(wex, {
partialContractTerms: {
amount: `${currency}:1` as AmountString,
summary: "Payment Peer Pull Test",
@@ -814,33 +814,33 @@ export async function runIntegrationTest2(
},
});
- await waitUntilTransactionPendingReady(ws, peerPullInit.transactionId);
+ await waitUntilTransactionPendingReady(wex, peerPullInit.transactionId);
- const peerPullInc = await preparePeerPullDebit(ws, {
+ const peerPullInc = await preparePeerPullDebit(wex, {
talerUri: peerPullInit.talerUri,
});
- await confirmPeerPullDebit(ws, {
+ await confirmPeerPullDebit(wex, {
peerPullDebitId: peerPullInc.peerPullDebitId,
});
await waitUntilTransactionWithAssociatedRefreshesFinal(
- ws,
+ wex,
peerPullInc.transactionId,
);
await waitUntilTransactionWithAssociatedRefreshesFinal(
- ws,
+ wex,
peerPullInit.transactionId,
);
await waitUntilTransactionWithAssociatedRefreshesFinal(
- ws,
+ wex,
peerPushCredit.transactionId,
);
await waitUntilTransactionWithAssociatedRefreshesFinal(
- ws,
+ wex,
peerPushInit.transactionId,
);
@@ -858,7 +858,7 @@ export async function runIntegrationTest2(
});
}
- await createDepositGroup(ws, {
+ await createDepositGroup(wex, {
amount: `${currency}:5` as AmountString,
depositPaytoUri: depositPayto,
});
@@ -867,7 +867,7 @@ export async function runIntegrationTest2(
}
export async function testPay(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
args: TestPayArgs,
): Promise<TestPayResult> {
logger.trace("creating order");
@@ -876,26 +876,26 @@ export async function testPay(
baseUrl: args.merchantBaseUrl,
};
const orderResp = await createOrder(
- ws.http,
+ wex.http,
merchant,
args.amount,
args.summary,
"taler://fulfillment-success/thank+you",
);
logger.trace("created new order with order ID", orderResp.orderId);
- const checkPayResp = await checkPayment(ws.http, merchant, orderResp.orderId);
+ const checkPayResp = await checkPayment(wex.http, merchant, orderResp.orderId);
const talerPayUri = checkPayResp.taler_pay_uri;
if (!talerPayUri) {
console.error("fatal: no taler pay URI received from backend");
process.exit(1);
}
logger.trace("taler pay URI:", talerPayUri);
- const result = await preparePayForUri(ws, talerPayUri);
+ const result = await preparePayForUri(wex, talerPayUri);
if (result.status !== PreparePayResultType.PaymentPossible) {
throw Error(`unexpected prepare pay status: ${result.status}`);
}
const r = await confirmPay(
- ws,
+ wex,
result.transactionId,
undefined,
args.forcedCoinSel,
@@ -903,7 +903,7 @@ export async function testPay(
if (r.type != ConfirmPayResultType.Done) {
throw Error("payment not done");
}
- const purchase = await ws.db.runReadOnlyTx(["purchases"], async (tx) => {
+ const purchase = await wex.db.runReadOnlyTx(["purchases"], async (tx) => {
return tx.purchases.get(result.proposalId);
});
checkLogicInvariant(!!purchase);
diff --git a/packages/taler-wallet-core/src/transactions.ts b/packages/taler-wallet-core/src/transactions.ts
index d7f0c0d18..3beb42187 100644
--- a/packages/taler-wallet-core/src/transactions.ts
+++ b/packages/taler-wallet-core/src/transactions.ts
@@ -132,7 +132,7 @@ import {
computeTipTransactionActions,
RewardTransactionContext,
} from "./reward.js";
-import type { InternalWalletState } from "./wallet.js";
+import type { InternalWalletState, WalletExecutionContext } from "./wallet.js";
import {
augmentPaytoUrisForWithdrawal,
computeWithdrawalTransactionActions,
@@ -215,7 +215,7 @@ const txOrder: { [t in TransactionType]: number } = {
};
export async function getTransactionById(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: TransactionByIdRequest,
): Promise<Transaction> {
const parsedTx = parseTransactionIdentifier(req.transactionId);
@@ -228,7 +228,7 @@ export async function getTransactionById(
case TransactionType.InternalWithdrawal:
case TransactionType.Withdrawal: {
const withdrawalGroupId = parsedTx.withdrawalGroupId;
- return await ws.db.runReadWriteTx(
+ return await wex.db.runReadWriteTx(
[
"withdrawalGroups",
"exchangeDetails",
@@ -273,7 +273,7 @@ export async function getTransactionById(
case TransactionType.Payment: {
const proposalId = parsedTx.proposalId;
- return await ws.db.runReadWriteTx(
+ return await wex.db.runReadWriteTx(
[
"purchases",
"tombstones",
@@ -284,7 +284,7 @@ export async function getTransactionById(
async (tx) => {
const purchase = await tx.purchases.get(proposalId);
if (!purchase) throw Error("not found");
- const download = await expectProposalDownload(ws, purchase, tx);
+ const download = await expectProposalDownload(wex, purchase, tx);
const contractData = download.contractData;
const payOpId = TaskIdentifiers.forPay(purchase);
const payRetryRecord = await tx.operationRetries.get(payOpId);
@@ -306,7 +306,7 @@ export async function getTransactionById(
case TransactionType.Refresh: {
// FIXME: We should return info about the refresh here!;
const refreshGroupId = parsedTx.refreshGroupId;
- return await ws.db.runReadOnlyTx(
+ return await wex.db.runReadOnlyTx(
["refreshGroups", "operationRetries"],
async (tx) => {
const refreshGroupRec = await tx.refreshGroups.get(refreshGroupId);
@@ -323,7 +323,7 @@ export async function getTransactionById(
case TransactionType.Reward: {
const tipId = parsedTx.walletRewardId;
- return await ws.db.runReadWriteTx(
+ return await wex.db.runReadWriteTx(
["rewards", "operationRetries"],
async (tx) => {
const tipRecord = await tx.rewards.get(tipId);
@@ -339,7 +339,7 @@ export async function getTransactionById(
case TransactionType.Deposit: {
const depositGroupId = parsedTx.depositGroupId;
- return await ws.db.runReadWriteTx(
+ return await wex.db.runReadWriteTx(
["depositGroups", "operationRetries"],
async (tx) => {
const depositRecord = await tx.depositGroups.get(depositGroupId);
@@ -354,7 +354,7 @@ export async function getTransactionById(
}
case TransactionType.Refund: {
- return await ws.db.runReadOnlyTx(
+ return await wex.db.runReadOnlyTx(
["refundGroups", "purchases", "operationRetries", "contractTerms"],
async (tx) => {
const refundRecord = await tx.refundGroups.get(
@@ -372,7 +372,7 @@ export async function getTransactionById(
);
}
case TransactionType.PeerPullDebit: {
- return await ws.db.runReadWriteTx(
+ return await wex.db.runReadWriteTx(
["peerPullDebit", "contractTerms"],
async (tx) => {
const debit = await tx.peerPullDebit.get(parsedTx.peerPullDebitId);
@@ -391,7 +391,7 @@ export async function getTransactionById(
}
case TransactionType.PeerPushDebit: {
- return await ws.db.runReadWriteTx(
+ return await wex.db.runReadWriteTx(
["peerPushDebit", "contractTerms"],
async (tx) => {
const debit = await tx.peerPushDebit.get(parsedTx.pursePub);
@@ -408,7 +408,7 @@ export async function getTransactionById(
case TransactionType.PeerPushCredit: {
const peerPushCreditId = parsedTx.peerPushCreditId;
- return await ws.db.runReadWriteTx(
+ return await wex.db.runReadWriteTx(
[
"peerPushCredit",
"contractTerms",
@@ -446,7 +446,7 @@ export async function getTransactionById(
case TransactionType.PeerPullCredit: {
const pursePub = parsedTx.pursePub;
- return await ws.db.runReadWriteTx(
+ return await wex.db.runReadWriteTx(
[
"peerPullCredit",
"contractTerms",
@@ -1039,10 +1039,10 @@ async function buildTransactionForPurchase(
}
export async function getWithdrawalTransactionByUri(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
request: WithdrawalTransactionByURIRequest,
): Promise<TransactionWithdrawal | undefined> {
- return await ws.db.runReadWriteTx(
+ return await wex.db.runReadWriteTx(
["withdrawalGroups", "exchangeDetails", "exchanges", "operationRetries"],
async (tx) => {
const withdrawalGroupRecord =
@@ -1085,7 +1085,7 @@ export async function getWithdrawalTransactionByUri(
* Retrieve the full event history for this wallet.
*/
export async function getTransactions(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
transactionsRequest?: TransactionsRequest,
): Promise<TransactionsResponse> {
const transactions: Transaction[] = [];
@@ -1095,7 +1095,7 @@ export async function getTransactions(
filter.onlyState = transactionsRequest.filterByState;
}
- await ws.db.runReadOnlyTx(
+ await wex.db.runReadOnlyTx(
[
"coins",
"denominations",
@@ -1698,18 +1698,18 @@ function maybeTaskFromTransaction(
* of a transaction.
*/
export async function retryTransaction(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
transactionId: string,
): Promise<void> {
logger.info(`resetting retry timeout for ${transactionId}`);
const taskId = maybeTaskFromTransaction(transactionId);
if (taskId) {
- ws.taskScheduler.resetTaskRetries(taskId);
+ wex.taskScheduler.resetTaskRetries(taskId);
}
}
async function getContextForTransaction(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
transactionId: string,
): Promise<TransactionContext> {
const tx = parseTransactionIdentifier(transactionId);
@@ -1718,26 +1718,26 @@ async function getContextForTransaction(
}
switch (tx.tag) {
case TransactionType.Deposit:
- return new DepositTransactionContext(ws, tx.depositGroupId);
+ return new DepositTransactionContext(wex, tx.depositGroupId);
case TransactionType.Refresh:
- return new RefreshTransactionContext(ws, tx.refreshGroupId);
+ return new RefreshTransactionContext(wex, tx.refreshGroupId);
case TransactionType.InternalWithdrawal:
case TransactionType.Withdrawal:
- return new WithdrawTransactionContext(ws, tx.withdrawalGroupId);
+ return new WithdrawTransactionContext(wex, tx.withdrawalGroupId);
case TransactionType.Payment:
- return new PayMerchantTransactionContext(ws, tx.proposalId);
+ return new PayMerchantTransactionContext(wex, tx.proposalId);
case TransactionType.PeerPullCredit:
- return new PeerPullCreditTransactionContext(ws, tx.pursePub);
+ return new PeerPullCreditTransactionContext(wex, tx.pursePub);
case TransactionType.PeerPushDebit:
- return new PeerPushDebitTransactionContext(ws, tx.pursePub);
+ return new PeerPushDebitTransactionContext(wex, tx.pursePub);
case TransactionType.PeerPullDebit:
- return new PeerPullDebitTransactionContext(ws, tx.peerPullDebitId);
+ return new PeerPullDebitTransactionContext(wex, tx.peerPullDebitId);
case TransactionType.PeerPushCredit:
- return new PeerPushCreditTransactionContext(ws, tx.peerPushCreditId);
+ return new PeerPushCreditTransactionContext(wex, tx.peerPushCreditId);
case TransactionType.Refund:
- return new RefundTransactionContext(ws, tx.refundGroupId);
+ return new RefundTransactionContext(wex, tx.refundGroupId);
case TransactionType.Reward:
- return new RewardTransactionContext(ws, tx.walletRewardId);
+ return new RewardTransactionContext(wex, tx.walletRewardId);
case TransactionType.Recoup:
throw new Error("not yet supported");
//return new RecoupTransactionContext(ws, tx.recoupGroupId);
@@ -1753,18 +1753,18 @@ async function getContextForTransaction(
* to take longer (such as a backup, recovery or very large withdrawal operation).
*/
export async function suspendTransaction(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
transactionId: string,
): Promise<void> {
- const ctx = await getContextForTransaction(ws, transactionId);
+ const ctx = await getContextForTransaction(wex, transactionId);
await ctx.suspendTransaction();
}
export async function failTransaction(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
transactionId: string,
): Promise<void> {
- const ctx = await getContextForTransaction(ws, transactionId);
+ const ctx = await getContextForTransaction(wex, transactionId);
await ctx.failTransaction();
}
@@ -1772,10 +1772,10 @@ export async function failTransaction(
* Resume a suspended transaction.
*/
export async function resumeTransaction(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
transactionId: string,
): Promise<void> {
- const ctx = await getContextForTransaction(ws, transactionId);
+ const ctx = await getContextForTransaction(wex, transactionId);
await ctx.resumeTransaction();
}
@@ -1783,21 +1783,21 @@ export async function resumeTransaction(
* Permanently delete a transaction based on the transaction ID.
*/
export async function deleteTransaction(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
transactionId: string,
): Promise<void> {
- const ctx = await getContextForTransaction(ws, transactionId);
+ const ctx = await getContextForTransaction(wex, transactionId);
await ctx.deleteTransaction();
if (ctx.taskId) {
- ws.taskScheduler.stopShepherdTask(ctx.taskId);
+ wex.taskScheduler.stopShepherdTask(ctx.taskId);
}
}
export async function abortTransaction(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
transactionId: string,
): Promise<void> {
- const ctx = await getContextForTransaction(ws, transactionId);
+ const ctx = await getContextForTransaction(wex, transactionId);
await ctx.abortTransaction();
}
@@ -1810,7 +1810,7 @@ export interface TransitionInfo {
* Notify of a state transition if necessary.
*/
export function notifyTransition(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
transactionId: string,
transitionInfo: TransitionInfo | undefined,
experimentalUserData: any = undefined,
@@ -1822,7 +1822,7 @@ export function notifyTransition(
transitionInfo.oldTxState.minor === transitionInfo.newTxState.minor
)
) {
- ws.notify({
+ wex.ws.notify({
type: NotificationType.TransactionStateTransition,
oldTxState: transitionInfo.oldTxState,
newTxState: transitionInfo.newTxState,
diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts
index f21ba6ec1..236b27575 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -285,6 +285,7 @@ export interface WalletExecutionContext {
readonly http: HttpRequestLibrary;
readonly db: DbAccess<typeof WalletStoresV1>;
readonly oc: ObservabilityContext;
+ readonly taskScheduler: TaskScheduler;
}
export const EXCHANGE_COINS_LOCK = "exchange-coins-lock";
@@ -299,16 +300,16 @@ type CancelFn = () => void;
* auditors into the database, unless these defaults have
* already been applied.
*/
-async function fillDefaults(ws: InternalWalletState): Promise<void> {
+async function fillDefaults(wex: WalletExecutionContext): Promise<void> {
const notifications: WalletNotification[] = [];
- await ws.db.runReadWriteTx(["config", "exchanges"], async (tx) => {
+ await wex.db.runReadWriteTx(["config", "exchanges"], async (tx) => {
const appliedRec = await tx.config.get("currencyDefaultsApplied");
let alreadyApplied = appliedRec ? !!appliedRec.value : false;
if (alreadyApplied) {
logger.trace("defaults already applied");
return;
}
- for (const exch of ws.config.builtin.exchanges) {
+ for (const exch of wex.ws.config.builtin.exchanges) {
const resp = await addPresetExchangeEntry(
tx,
exch.exchangeBaseUrl,
@@ -324,18 +325,18 @@ async function fillDefaults(ws: InternalWalletState): Promise<void> {
});
});
for (const notif of notifications) {
- ws.notify(notif);
+ wex.ws.notify(notif);
}
}
export async function getDenomInfo(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
tx: WalletDbReadOnlyTransaction<["denominations"]>,
exchangeBaseUrl: string,
denomPubHash: string,
): Promise<DenominationInfo | undefined> {
const key = `${exchangeBaseUrl}:${denomPubHash}`;
- const cached = ws.denomCache[key];
+ const cached = wex.ws.denomCache[key];
if (cached) {
return cached;
}
@@ -351,11 +352,11 @@ export async function getDenomInfo(
* previous withdrawals.
*/
async function listKnownBankAccounts(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
currency?: string,
): Promise<KnownBankAccounts> {
const accounts: KnownBankAccountsInfo[] = [];
- await ws.db.runReadOnlyTx(["bankAccounts"], async (tx) => {
+ await wex.db.runReadOnlyTx(["bankAccounts"], async (tx) => {
const knownAccounts = await tx.bankAccounts.iter().toArray();
for (const r of knownAccounts) {
if (currency && currency !== r.currency) {
@@ -378,12 +379,12 @@ async function listKnownBankAccounts(
/**
*/
async function addKnownBankAccounts(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
payto: string,
alias: string,
currency: string,
): Promise<void> {
- await ws.db.runReadWriteTx(["bankAccounts"], async (tx) => {
+ await wex.db.runReadWriteTx(["bankAccounts"], async (tx) => {
tx.bankAccounts.put({
uri: payto,
alias: alias,
@@ -397,10 +398,10 @@ async function addKnownBankAccounts(
/**
*/
async function forgetKnownBankAccounts(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
payto: string,
): Promise<void> {
- await ws.db.runReadWriteTx(["bankAccounts"], async (tx) => {
+ await wex.db.runReadWriteTx(["bankAccounts"], async (tx) => {
const account = await tx.bankAccounts.get(payto);
if (!account) {
throw Error(`account not found: ${payto}`);
@@ -411,11 +412,11 @@ async function forgetKnownBankAccounts(
}
async function setCoinSuspended(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
coinPub: string,
suspended: boolean,
): Promise<void> {
- await ws.db.runReadWriteTx(["coins", "coinAvailability"], async (tx) => {
+ await wex.db.runReadWriteTx(["coins", "coinAvailability"], async (tx) => {
const c = await tx.coins.get(coinPub);
if (!c) {
logger.warn(`coin ${coinPub} not found, won't suspend`);
@@ -453,10 +454,10 @@ async function setCoinSuspended(
/**
* Dump the public information of coins we have in an easy-to-process format.
*/
-async function dumpCoins(ws: InternalWalletState): Promise<CoinDumpJson> {
+async function dumpCoins(wex: WalletExecutionContext): Promise<CoinDumpJson> {
const coinsJson: CoinDumpJson = { coins: [] };
logger.info("dumping coins");
- await ws.db.runReadOnlyTx(["coins", "denominations"], async (tx) => {
+ await wex.db.runReadOnlyTx(["coins", "denominations"], async (tx) => {
const coins = await tx.coins.iter().toArray();
for (const c of coins) {
const denom = await tx.denominations.get([
@@ -477,7 +478,7 @@ async function dumpCoins(ws: InternalWalletState): Promise<CoinDumpJson> {
withdrawalReservePub = cs.reservePub;
}
const denomInfo = await getDenomInfo(
- ws,
+ wex,
tx,
c.exchangeBaseUrl,
c.denomPubHash,
@@ -530,10 +531,10 @@ async function getClientFromWalletState(
}
async function createStoredBackup(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
): Promise<CreateStoredBackupResponse> {
- const backup = await exportDb(ws.idb);
- const backupsDb = await openStoredBackupsDatabase(ws.idb);
+ const backup = await exportDb(wex.ws.idb);
+ const backupsDb = await openStoredBackupsDatabase(wex.ws.idb);
const name = `backup-${new Date().getTime()}`;
await backupsDb.runAllStoresReadWriteTx(async (tx) => {
await tx.backupMeta.add({
@@ -547,12 +548,12 @@ async function createStoredBackup(
}
async function listStoredBackups(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
): Promise<StoredBackupList> {
const storedBackups: StoredBackupList = {
storedBackups: [],
};
- const backupsDb = await openStoredBackupsDatabase(ws.idb);
+ const backupsDb = await openStoredBackupsDatabase(wex.ws.idb);
await backupsDb.runAllStoresReadWriteTx(async (tx) => {
await tx.backupMeta.iter().forEach((x) => {
storedBackups.storedBackups.push({
@@ -564,10 +565,10 @@ async function listStoredBackups(
}
async function deleteStoredBackup(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: DeleteStoredBackupRequest,
): Promise<void> {
- const backupsDb = await openStoredBackupsDatabase(ws.idb);
+ const backupsDb = await openStoredBackupsDatabase(wex.ws.idb);
await backupsDb.runAllStoresReadWriteTx(async (tx) => {
await tx.backupData.delete(req.name);
await tx.backupMeta.delete(req.name);
@@ -575,12 +576,12 @@ async function deleteStoredBackup(
}
async function recoverStoredBackup(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: RecoverStoredBackupRequest,
): Promise<void> {
logger.info(`Recovering stored backup ${req.name}`);
const { name } = req;
- const backupsDb = await openStoredBackupsDatabase(ws.idb);
+ const backupsDb = await openStoredBackupsDatabase(wex.ws.idb);
const bd = await backupsDb.runAllStoresReadWriteTx(async (tx) => {
const backupMeta = tx.backupMeta.get(name);
if (!backupMeta) {
@@ -593,12 +594,12 @@ async function recoverStoredBackup(
return backupData;
});
logger.info(`backup found, now importing`);
- await importDb(ws.db.idbHandle(), bd);
+ await importDb(wex.db.idbHandle(), bd);
logger.info(`import done`);
}
async function handlePrepareWithdrawExchange(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: PrepareWithdrawExchangeRequest,
): Promise<PrepareWithdrawExchangeResponse> {
const parsedUri = parseTalerUri(req.talerUri);
@@ -606,7 +607,7 @@ async function handlePrepareWithdrawExchange(
throw Error("expected a taler://withdraw-exchange URI");
}
const exchangeBaseUrl = parsedUri.exchangeBaseUrl;
- const exchange = await fetchFreshExchange(ws, exchangeBaseUrl);
+ const exchange = await fetchFreshExchange(wex, exchangeBaseUrl);
if (exchange.masterPub != parsedUri.exchangePub) {
throw Error("mismatch of exchange master public key (URI vs actual)");
}
@@ -638,11 +639,11 @@ export interface PendingOperationsResponse {
* Implementation of the "wallet-core" API.
*/
async function dispatchRequestInternal<Op extends WalletApiOperation>(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
operation: WalletApiOperation,
payload: unknown,
): Promise<WalletCoreResponseType<typeof operation>> {
- if (!ws.initCalled && operation !== WalletApiOperation.InitWallet) {
+ if (!wex.ws.initCalled && operation !== WalletApiOperation.InitWallet) {
throw Error(
`wallet must be initialized before running operation ${operation}`,
);
@@ -651,17 +652,17 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
// definitions we already have?
switch (operation) {
case WalletApiOperation.CreateStoredBackup:
- return createStoredBackup(ws);
+ return createStoredBackup(wex);
case WalletApiOperation.DeleteStoredBackup: {
const req = codecForDeleteStoredBackupRequest().decode(payload);
- await deleteStoredBackup(ws, req);
+ await deleteStoredBackup(wex, req);
return {};
}
case WalletApiOperation.ListStoredBackups:
- return listStoredBackups(ws);
+ return listStoredBackups(wex);
case WalletApiOperation.RecoverStoredBackup: {
const req = codecForRecoverStoredBackupRequest().decode(payload);
- await recoverStoredBackup(ws, req);
+ await recoverStoredBackup(wex, req);
return {};
}
case WalletApiOperation.InitWallet: {
@@ -669,7 +670,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
// Write to the DB to make sure that we're failing early in
// case the DB is not writeable.
try {
- await ws.db.runReadWriteTx(["config"], async (tx) => {
+ await wex.db.runReadWriteTx(["config"], async (tx) => {
tx.config.put({
key: ConfigRecordKey.LastInitInfo,
value: timestampProtocolToDb(TalerProtocolTimestamp.now()),
@@ -681,41 +682,41 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
innerError: getErrorDetailFromException(e),
});
}
- ws.initCalled = true;
- if (ws.config.testing.skipDefaults) {
+ wex.ws.initCalled = true;
+ if (wex.ws.config.testing.skipDefaults) {
logger.trace("skipping defaults");
} else {
logger.trace("filling defaults");
- await fillDefaults(ws);
+ await fillDefaults(wex);
}
const resp: InitResponse = {
- versionInfo: getVersion(ws),
+ versionInfo: getVersion(wex),
};
return resp;
}
case WalletApiOperation.WithdrawTestkudos: {
- await withdrawTestBalance(ws, {
+ await withdrawTestBalance(wex, {
amount: "TESTKUDOS:10" as AmountString,
corebankApiBaseUrl: "https://bank.test.taler.net/",
exchangeBaseUrl: "https://exchange.test.taler.net/",
});
return {
- versionInfo: getVersion(ws),
+ versionInfo: getVersion(wex),
};
}
case WalletApiOperation.WithdrawTestBalance: {
const req = codecForWithdrawTestBalance().decode(payload);
- await withdrawTestBalance(ws, req);
+ await withdrawTestBalance(wex, req);
return {};
}
case WalletApiOperation.RunIntegrationTest: {
const req = codecForIntegrationTestArgs().decode(payload);
- await runIntegrationTest(ws, req);
+ await runIntegrationTest(wex, req);
return {};
}
case WalletApiOperation.RunIntegrationTestV2: {
const req = codecForIntegrationTestV2Args().decode(payload);
- await runIntegrationTest2(ws, req);
+ await runIntegrationTest2(wex, req);
return {};
}
case WalletApiOperation.ValidateIban: {
@@ -728,45 +729,45 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
}
case WalletApiOperation.TestPay: {
const req = codecForTestPayArgs().decode(payload);
- return await testPay(ws, req);
+ return await testPay(wex, req);
}
case WalletApiOperation.GetTransactions: {
const req = codecForTransactionsRequest().decode(payload);
- return await getTransactions(ws, req);
+ return await getTransactions(wex, req);
}
case WalletApiOperation.GetTransactionById: {
const req = codecForTransactionByIdRequest().decode(payload);
- return await getTransactionById(ws, req);
+ return await getTransactionById(wex, req);
}
case WalletApiOperation.GetWithdrawalTransactionByUri: {
const req = codecForGetWithdrawalDetailsForUri().decode(payload);
- return await getWithdrawalTransactionByUri(ws, req);
+ return await getWithdrawalTransactionByUri(wex, req);
}
case WalletApiOperation.AddExchange: {
const req = codecForAddExchangeRequest().decode(payload);
- await fetchFreshExchange(ws, req.exchangeBaseUrl, {
+ await fetchFreshExchange(wex, req.exchangeBaseUrl, {
expectedMasterPub: req.masterPub,
});
return {};
}
case WalletApiOperation.UpdateExchangeEntry: {
const req = codecForUpdateExchangeEntryRequest().decode(payload);
- await fetchFreshExchange(ws, req.exchangeBaseUrl, {
+ await fetchFreshExchange(wex, req.exchangeBaseUrl, {
forceUpdate: !!req.force,
});
return {};
}
case WalletApiOperation.ListExchanges: {
- return await listExchanges(ws);
+ return await listExchanges(wex);
}
case WalletApiOperation.GetExchangeEntryByUrl: {
const req = codecForGetExchangeEntryByUrlRequest().decode(payload);
- return lookupExchangeByUri(ws, req);
+ return lookupExchangeByUri(wex, req);
}
case WalletApiOperation.ListExchangesForScopedCurrency: {
const req =
codecForListExchangesForScopedCurrencyRequest().decode(payload);
- const exchangesResp = await listExchanges(ws);
+ const exchangesResp = await listExchanges(wex);
const result: ExchangesShortListResponse = {
exchanges: [],
};
@@ -783,32 +784,32 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
}
case WalletApiOperation.GetExchangeDetailedInfo: {
const req = codecForAddExchangeRequest().decode(payload);
- return await getExchangeDetailedInfo(ws, req.exchangeBaseUrl);
+ return await getExchangeDetailedInfo(wex, req.exchangeBaseUrl);
}
case WalletApiOperation.ListKnownBankAccounts: {
const req = codecForListKnownBankAccounts().decode(payload);
- return await listKnownBankAccounts(ws, req.currency);
+ return await listKnownBankAccounts(wex, req.currency);
}
case WalletApiOperation.AddKnownBankAccounts: {
const req = codecForAddKnownBankAccounts().decode(payload);
- await addKnownBankAccounts(ws, req.payto, req.alias, req.currency);
+ await addKnownBankAccounts(wex, req.payto, req.alias, req.currency);
return {};
}
case WalletApiOperation.ForgetKnownBankAccounts: {
const req = codecForForgetKnownBankAccounts().decode(payload);
- await forgetKnownBankAccounts(ws, req.payto);
+ await forgetKnownBankAccounts(wex, req.payto);
return {};
}
case WalletApiOperation.GetWithdrawalDetailsForUri: {
const req = codecForGetWithdrawalDetailsForUri().decode(payload);
- return await getWithdrawalDetailsForUri(ws, req.talerWithdrawUri, {
+ return await getWithdrawalDetailsForUri(wex, req.talerWithdrawUri, {
notifyChangeFromPendingTimeoutMs: req.notifyChangeFromPendingTimeoutMs,
restrictAge: req.restrictAge,
});
}
case WalletApiOperation.AcceptManualWithdrawal: {
const req = codecForAcceptManualWithdrawalRequet().decode(payload);
- const res = await createManualWithdrawal(ws, {
+ const res = await createManualWithdrawal(wex, {
amount: Amounts.parseOrThrow(req.amount),
exchangeBaseUrl: req.exchangeBaseUrl,
restrictAge: req.restrictAge,
@@ -819,7 +820,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
const req =
codecForGetWithdrawalDetailsForAmountRequest().decode(payload);
const wi = await getExchangeWithdrawalInfo(
- ws,
+ wex,
req.exchangeBaseUrl,
Amounts.parseOrThrow(req.amount),
req.restrictAge,
@@ -843,23 +844,23 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
return resp;
}
case WalletApiOperation.GetBalances: {
- return await getBalances(ws);
+ return await getBalances(wex);
}
case WalletApiOperation.GetBalanceDetail: {
const req = codecForGetBalanceDetailRequest().decode(payload);
- return await getBalanceDetail(ws, req);
+ return await getBalanceDetail(wex, req);
}
case WalletApiOperation.GetUserAttentionRequests: {
const req = codecForUserAttentionsRequest().decode(payload);
- return await getUserAttentions(ws, req);
+ return await getUserAttentions(wex, req);
}
case WalletApiOperation.MarkAttentionRequestAsRead: {
const req = codecForUserAttentionByIdRequest().decode(payload);
- return await markAttentionRequestAsRead(ws, req);
+ return await markAttentionRequestAsRead(wex, req);
}
case WalletApiOperation.GetUserAttentionUnreadCount: {
const req = codecForUserAttentionsRequest().decode(payload);
- return await getUserAttentionsUnreadCount(ws, req);
+ return await getUserAttentionsUnreadCount(wex, req);
}
case WalletApiOperation.GetPendingOperations: {
// FIXME: Eventually remove the handler after deprecation period.
@@ -869,7 +870,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
}
case WalletApiOperation.SetExchangeTosAccepted: {
const req = codecForAcceptExchangeTosRequest().decode(payload);
- await acceptExchangeTermsOfService(ws, req.exchangeBaseUrl);
+ await acceptExchangeTermsOfService(wex, req.exchangeBaseUrl);
return {};
}
case WalletApiOperation.SetExchangeTosForgotten: {
@@ -880,7 +881,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
case WalletApiOperation.AcceptBankIntegratedWithdrawal: {
const req =
codecForAcceptBankIntegratedWithdrawalRequest().decode(payload);
- return await acceptWithdrawalFromUri(ws, {
+ return await acceptWithdrawalFromUri(wex, {
selectedExchange: req.exchangeBaseUrl,
talerWithdrawUri: req.talerWithdrawUri,
forcedDenomSel: req.forcedDenomSel,
@@ -890,7 +891,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
case WalletApiOperation.GetExchangeTos: {
const req = codecForGetExchangeTosRequest().decode(payload);
return getExchangeTos(
- ws,
+ wex,
req.exchangeBaseUrl,
req.acceptedFormat,
req.acceptLanguage,
@@ -898,7 +899,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
}
case WalletApiOperation.GetContractTermsDetails: {
const req = codecForGetContractTermsDetails().decode(payload);
- return getContractTermsDetails(ws, req.proposalId);
+ return getContractTermsDetails(wex, req.proposalId);
}
case WalletApiOperation.RetryPendingNow: {
logger.error("retryPendingNow currently not implemented");
@@ -906,19 +907,19 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
}
case WalletApiOperation.SharePayment: {
const req = codecForSharePaymentRequest().decode(payload);
- return await sharePayment(ws, req.merchantBaseUrl, req.orderId);
+ return await sharePayment(wex, req.merchantBaseUrl, req.orderId);
}
case WalletApiOperation.PrepareWithdrawExchange: {
const req = codecForPrepareWithdrawExchangeRequest().decode(payload);
- return handlePrepareWithdrawExchange(ws, req);
+ return handlePrepareWithdrawExchange(wex, req);
}
case WalletApiOperation.PreparePayForUri: {
const req = codecForPreparePayRequest().decode(payload);
- return await preparePayForUri(ws, req.talerPayUri);
+ return await preparePayForUri(wex, req.talerPayUri);
}
case WalletApiOperation.PreparePayForTemplate: {
const req = codecForPreparePayTemplateRequest().decode(payload);
- return preparePayForTemplate(ws, req);
+ return preparePayForTemplate(wex, req);
}
case WalletApiOperation.ConfirmPay: {
const req = codecForConfirmPayRequest().decode(payload);
@@ -934,45 +935,45 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
} else {
throw Error("transactionId or (deprecated) proposalId required");
}
- return await confirmPay(ws, transactionId, req.sessionId);
+ return await confirmPay(wex, transactionId, req.sessionId);
}
case WalletApiOperation.AbortTransaction: {
const req = codecForAbortTransaction().decode(payload);
- await abortTransaction(ws, req.transactionId);
+ await abortTransaction(wex, req.transactionId);
return {};
}
case WalletApiOperation.SuspendTransaction: {
const req = codecForSuspendTransaction().decode(payload);
- await suspendTransaction(ws, req.transactionId);
+ await suspendTransaction(wex, req.transactionId);
return {};
}
case WalletApiOperation.FailTransaction: {
const req = codecForFailTransactionRequest().decode(payload);
- await failTransaction(ws, req.transactionId);
+ await failTransaction(wex, req.transactionId);
return {};
}
case WalletApiOperation.ResumeTransaction: {
const req = codecForResumeTransaction().decode(payload);
- await resumeTransaction(ws, req.transactionId);
+ await resumeTransaction(wex, req.transactionId);
return {};
}
case WalletApiOperation.DumpCoins: {
- return await dumpCoins(ws);
+ return await dumpCoins(wex);
}
case WalletApiOperation.SetCoinSuspended: {
const req = codecForSetCoinSuspendedRequest().decode(payload);
- await setCoinSuspended(ws, req.coinPub, req.suspended);
+ await setCoinSuspended(wex, req.coinPub, req.suspended);
return {};
}
case WalletApiOperation.TestingGetSampleTransactions:
return { transactions: sampleWalletCoreTransactions };
case WalletApiOperation.ForceRefresh: {
const req = codecForForceRefreshRequest().decode(payload);
- return await forceRefresh(ws, req);
+ return await forceRefresh(wex, req);
}
case WalletApiOperation.StartRefundQueryForUri: {
const req = codecForPrepareRefundRequest().decode(payload);
- return await startRefundQueryForUri(ws, req.talerRefundUri);
+ return await startRefundQueryForUri(wex, req.talerRefundUri);
}
case WalletApiOperation.StartRefundQuery: {
const req = codecForStartRefundQueryRequest().decode(payload);
@@ -983,30 +984,30 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
if (txIdParsed.tag !== TransactionType.Payment) {
throw Error("expected payment transaction ID");
}
- await startQueryRefund(ws, txIdParsed.proposalId);
+ await startQueryRefund(wex, txIdParsed.proposalId);
return {};
}
case WalletApiOperation.AddBackupProvider: {
const req = codecForAddBackupProviderRequest().decode(payload);
- return await addBackupProvider(ws, req);
+ return await addBackupProvider(wex, req);
}
case WalletApiOperation.RunBackupCycle: {
const req = codecForRunBackupCycle().decode(payload);
- await runBackupCycle(ws, req);
+ await runBackupCycle(wex, req);
return {};
}
case WalletApiOperation.RemoveBackupProvider: {
const req = codecForRemoveBackupProvider().decode(payload);
- await removeBackupProvider(ws, req);
+ await removeBackupProvider(wex, req);
return {};
}
case WalletApiOperation.ExportBackupRecovery: {
- const resp = await getBackupRecovery(ws);
+ const resp = await getBackupRecovery(wex);
return resp;
}
case WalletApiOperation.TestingWaitTransactionState: {
const req = payload as TestingWaitTransactionRequest;
- await waitTransactionState(ws, req.transactionId, req.txState);
+ await waitTransactionState(wex, req.transactionId, req.txState);
return {};
}
case WalletApiOperation.GetCurrencySpecification: {
@@ -1055,7 +1056,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
}
case WalletApiOperation.ImportBackupRecovery: {
const req = codecForAny().decode(payload);
- await loadBackupRecovery(ws, req);
+ await loadBackupRecovery(wex, req);
return {};
}
// case WalletApiOperation.GetPlanForOperation: {
@@ -1064,31 +1065,31 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
// }
case WalletApiOperation.ConvertDepositAmount: {
const req = codecForConvertAmountRequest.decode(payload);
- return await convertDepositAmount(ws, req);
+ return await convertDepositAmount(wex, req);
}
case WalletApiOperation.GetMaxDepositAmount: {
const req = codecForGetAmountRequest.decode(payload);
- return await getMaxDepositAmount(ws, req);
+ return await getMaxDepositAmount(wex, req);
}
case WalletApiOperation.ConvertPeerPushAmount: {
const req = codecForConvertAmountRequest.decode(payload);
- return await convertPeerPushAmount(ws, req);
+ return await convertPeerPushAmount(wex, req);
}
case WalletApiOperation.GetMaxPeerPushAmount: {
const req = codecForGetAmountRequest.decode(payload);
- return await getMaxPeerPushAmount(ws, req);
+ return await getMaxPeerPushAmount(wex, req);
}
case WalletApiOperation.ConvertWithdrawalAmount: {
const req = codecForConvertAmountRequest.decode(payload);
- return await convertWithdrawalAmount(ws, req);
+ return await convertWithdrawalAmount(wex, req);
}
case WalletApiOperation.GetBackupInfo: {
- const resp = await getBackupInfo(ws);
+ const resp = await getBackupInfo(wex);
return resp;
}
case WalletApiOperation.PrepareDeposit: {
const req = codecForPrepareDepositRequest().decode(payload);
- return await prepareDepositGroup(ws, req);
+ return await prepareDepositGroup(wex, req);
}
case WalletApiOperation.GenerateDepositGroupTxId:
return {
@@ -1096,42 +1097,42 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
};
case WalletApiOperation.CreateDepositGroup: {
const req = codecForCreateDepositGroupRequest().decode(payload);
- return await createDepositGroup(ws, req);
+ return await createDepositGroup(wex, req);
}
case WalletApiOperation.DeleteTransaction: {
const req = codecForDeleteTransactionRequest().decode(payload);
- await deleteTransaction(ws, req.transactionId);
+ await deleteTransaction(wex, req.transactionId);
return {};
}
case WalletApiOperation.RetryTransaction: {
const req = codecForRetryTransactionRequest().decode(payload);
- await retryTransaction(ws, req.transactionId);
+ await retryTransaction(wex, req.transactionId);
return {};
}
case WalletApiOperation.SetWalletDeviceId: {
const req = codecForSetWalletDeviceIdRequest().decode(payload);
- await setWalletDeviceId(ws, req.walletDeviceId);
+ await setWalletDeviceId(wex, req.walletDeviceId);
return {};
}
case WalletApiOperation.TestCrypto: {
- return await ws.cryptoApi.hashString({ str: "hello world" });
+ return await wex.cryptoApi.hashString({ str: "hello world" });
}
case WalletApiOperation.ClearDb:
- await clearDatabase(ws.db.idbHandle());
+ await clearDatabase(wex.db.idbHandle());
return {};
case WalletApiOperation.Recycle: {
throw Error("not implemented");
return {};
}
case WalletApiOperation.ExportDb: {
- const dbDump = await exportDb(ws.idb);
+ const dbDump = await exportDb(wex.ws.idb);
return dbDump;
}
case WalletApiOperation.ListGlobalCurrencyExchanges: {
const resp: ListGlobalCurrencyExchangesResponse = {
exchanges: [],
};
- await ws.db.runReadOnlyTx(["globalCurrencyExchanges"], async (tx) => {
+ await wex.db.runReadOnlyTx(["globalCurrencyExchanges"], async (tx) => {
const gceList = await tx.globalCurrencyExchanges.iter().toArray();
for (const gce of gceList) {
resp.exchanges.push({
@@ -1147,7 +1148,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
const resp: ListGlobalCurrencyAuditorsResponse = {
auditors: [],
};
- await ws.db.runReadOnlyTx(["globalCurrencyAuditors"], async (tx) => {
+ await wex.db.runReadOnlyTx(["globalCurrencyAuditors"], async (tx) => {
const gcaList = await tx.globalCurrencyAuditors.iter().toArray();
for (const gca of gcaList) {
resp.auditors.push({
@@ -1161,7 +1162,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
}
case WalletApiOperation.AddGlobalCurrencyExchange: {
const req = codecForAddGlobalCurrencyExchangeRequest().decode(payload);
- await ws.db.runReadWriteTx(["globalCurrencyExchanges"], async (tx) => {
+ await wex.db.runReadWriteTx(["globalCurrencyExchanges"], async (tx) => {
const key = [req.currency, req.exchangeBaseUrl, req.exchangeMasterPub];
const existingRec =
await tx.globalCurrencyExchanges.indexes.byCurrencyAndUrlAndPub.get(
@@ -1180,7 +1181,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
}
case WalletApiOperation.RemoveGlobalCurrencyExchange: {
const req = codecForRemoveGlobalCurrencyExchangeRequest().decode(payload);
- await ws.db.runReadWriteTx(["globalCurrencyExchanges"], async (tx) => {
+ await wex.db.runReadWriteTx(["globalCurrencyExchanges"], async (tx) => {
const key = [req.currency, req.exchangeBaseUrl, req.exchangeMasterPub];
const existingRec =
await tx.globalCurrencyExchanges.indexes.byCurrencyAndUrlAndPub.get(
@@ -1196,7 +1197,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
}
case WalletApiOperation.AddGlobalCurrencyAuditor: {
const req = codecForAddGlobalCurrencyAuditorRequest().decode(payload);
- await ws.db.runReadWriteTx(["globalCurrencyAuditors"], async (tx) => {
+ await wex.db.runReadWriteTx(["globalCurrencyAuditors"], async (tx) => {
const key = [req.currency, req.auditorBaseUrl, req.auditorPub];
const existingRec =
await tx.globalCurrencyAuditors.indexes.byCurrencyAndUrlAndPub.get(
@@ -1215,7 +1216,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
}
case WalletApiOperation.RemoveGlobalCurrencyAuditor: {
const req = codecForRemoveGlobalCurrencyAuditorRequest().decode(payload);
- await ws.db.runReadWriteTx(["globalCurrencyAuditors"], async (tx) => {
+ await wex.db.runReadWriteTx(["globalCurrencyAuditors"], async (tx) => {
const key = [req.currency, req.auditorBaseUrl, req.auditorPub];
const existingRec =
await tx.globalCurrencyAuditors.indexes.byCurrencyAndUrlAndPub.get(
@@ -1231,67 +1232,67 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
}
case WalletApiOperation.ImportDb: {
const req = codecForImportDbRequest().decode(payload);
- await importDb(ws.db.idbHandle(), req.dump);
+ await importDb(wex.db.idbHandle(), req.dump);
return [];
}
case WalletApiOperation.CheckPeerPushDebit: {
const req = codecForCheckPeerPushDebitRequest().decode(payload);
- return await checkPeerPushDebit(ws, req);
+ return await checkPeerPushDebit(wex, req);
}
case WalletApiOperation.InitiatePeerPushDebit: {
const req = codecForInitiatePeerPushDebitRequest().decode(payload);
- return await initiatePeerPushDebit(ws, req);
+ return await initiatePeerPushDebit(wex, req);
}
case WalletApiOperation.PreparePeerPushCredit: {
const req = codecForPreparePeerPushCreditRequest().decode(payload);
- return await preparePeerPushCredit(ws, req);
+ return await preparePeerPushCredit(wex, req);
}
case WalletApiOperation.ConfirmPeerPushCredit: {
const req = codecForConfirmPeerPushPaymentRequest().decode(payload);
- return await confirmPeerPushCredit(ws, req);
+ return await confirmPeerPushCredit(wex, req);
}
case WalletApiOperation.CheckPeerPullCredit: {
const req = codecForPreparePeerPullPaymentRequest().decode(payload);
- return await checkPeerPullPaymentInitiation(ws, req);
+ return await checkPeerPullPaymentInitiation(wex, req);
}
case WalletApiOperation.InitiatePeerPullCredit: {
const req = codecForInitiatePeerPullPaymentRequest().decode(payload);
- return await initiatePeerPullPayment(ws, req);
+ return await initiatePeerPullPayment(wex, req);
}
case WalletApiOperation.PreparePeerPullDebit: {
const req = codecForCheckPeerPullPaymentRequest().decode(payload);
- return await preparePeerPullDebit(ws, req);
+ return await preparePeerPullDebit(wex, req);
}
case WalletApiOperation.ConfirmPeerPullDebit: {
const req = codecForAcceptPeerPullPaymentRequest().decode(payload);
- return await confirmPeerPullDebit(ws, req);
+ return await confirmPeerPullDebit(wex, req);
}
case WalletApiOperation.ApplyDevExperiment: {
const req = codecForApplyDevExperiment().decode(payload);
- await applyDevExperiment(ws, req.devExperimentUri);
+ await applyDevExperiment(wex, req.devExperimentUri);
return {};
}
case WalletApiOperation.GetVersion: {
- return getVersion(ws);
+ return getVersion(wex);
}
case WalletApiOperation.TestingWaitTransactionsFinal:
- return await waitUntilAllTransactionsFinal(ws);
+ return await waitUntilAllTransactionsFinal(wex);
case WalletApiOperation.TestingWaitRefreshesFinal:
- return await waitUntilRefreshesDone(ws);
+ return await waitUntilRefreshesDone(wex);
case WalletApiOperation.TestingSetTimetravel: {
const req = codecForTestingSetTimetravelRequest().decode(payload);
setDangerousTimetravel(req.offsetMs);
- ws.taskScheduler.reload();
+ wex.taskScheduler.reload();
return {};
}
case WalletApiOperation.DeleteExchange: {
const req = codecForDeleteExchangeRequest().decode(payload);
- await deleteExchange(ws, req);
+ await deleteExchange(wex, req);
return {};
}
case WalletApiOperation.GetExchangeResources: {
const req = codecForGetExchangeResourcesRequest().decode(payload);
- return await getExchangeResources(ws, req.exchangeBaseUrl);
+ return await getExchangeResources(wex, req.exchangeBaseUrl);
}
case WalletApiOperation.TestingInfiniteTransactionLoop: {
const myDelayMs = (payload as any).delayMs ?? 5;
@@ -1301,7 +1302,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
const url =
"https://exchange.demo.taler.net/reserves/01PMMB9PJN0QBWAFBXV6R0KNJJMAKXCV4D6FDG0GJFDJQXGYP32G?timeout_ms=30000";
logger.info(`fetching ${url}`);
- const res = await ws.http.fetch(url);
+ const res = await wex.http.fetch(url);
logger.info(`fetch result ${res.status}`);
}
};
@@ -1312,7 +1313,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
let loopCount = 0;
while (true) {
logger.info(`looping test write tx, iteration ${loopCount}`);
- await ws.db.runReadWriteTx(["config"], async (tx) => {
+ await wex.db.runReadWriteTx(["config"], async (tx) => {
await tx.config.put({
key: ConfigRecordKey.TestLoopTx,
value: loopCount,
@@ -1338,7 +1339,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
);
}
-export function getVersion(ws: InternalWalletState): WalletCoreVersion {
+export function getVersion(wex: WalletExecutionContext): WalletCoreVersion {
const result: WalletCoreVersion = {
implementationSemver: walletCoreBuildInfo.implementationSemver,
implementationGitHash: walletCoreBuildInfo.implementationGitHash,
@@ -1364,9 +1365,21 @@ async function handleCoreApiRequest(
id: string,
payload: unknown,
): Promise<CoreApiResponse> {
+ const wex: WalletExecutionContext = {
+ ws,
+ cancellationToken: CancellationToken.CONTINUE,
+ cryptoApi: ws.cryptoApi,
+ db: ws.db,
+ http: ws.http,
+ taskScheduler: ws.taskScheduler,
+ oc: {
+ observe(event) {},
+ },
+ };
+
try {
await ws.ensureWalletDbOpen();
- const result = await dispatchRequestInternal(ws, operation as any, payload);
+ const result = await dispatchRequestInternal(wex, operation as any, payload);
return {
type: "response",
operation,
diff --git a/packages/taler-wallet-core/src/withdraw.ts b/packages/taler-wallet-core/src/withdraw.ts
index 541525c6b..44f1ee4f9 100644
--- a/packages/taler-wallet-core/src/withdraw.ts
+++ b/packages/taler-wallet-core/src/withdraw.ts
@@ -146,7 +146,11 @@ import {
WALLET_BANK_INTEGRATION_PROTOCOL_VERSION,
WALLET_EXCHANGE_PROTOCOL_VERSION,
} from "./versions.js";
-import { getDenomInfo, type InternalWalletState } from "./wallet.js";
+import {
+ WalletExecutionContext,
+ getDenomInfo,
+ type InternalWalletState,
+} from "./wallet.js";
/**
* Logger for this file.
@@ -158,7 +162,7 @@ export class WithdrawTransactionContext implements TransactionContext {
readonly taskId: TaskIdStr;
constructor(
- public ws: InternalWalletState,
+ public wex: WalletExecutionContext,
public withdrawalGroupId: string,
) {
this.transactionId = constructTransactionIdentifier({
@@ -172,7 +176,7 @@ export class WithdrawTransactionContext implements TransactionContext {
}
async deleteTransaction(): Promise<void> {
- const { ws, withdrawalGroupId } = this;
+ const { wex: ws, withdrawalGroupId } = this;
await ws.db.runReadWriteTx(
["withdrawalGroups", "tombstones"],
async (tx) => {
@@ -190,8 +194,8 @@ export class WithdrawTransactionContext implements TransactionContext {
}
async suspendTransaction(): Promise<void> {
- const { ws, withdrawalGroupId, transactionId, taskId } = this;
- const transitionInfo = await ws.db.runReadWriteTx(
+ const { wex, withdrawalGroupId, transactionId, taskId } = this;
+ const transitionInfo = await wex.db.runReadWriteTx(
["withdrawalGroups"],
async (tx) => {
const wg = await tx.withdrawalGroups.get(withdrawalGroupId);
@@ -240,12 +244,12 @@ export class WithdrawTransactionContext implements TransactionContext {
return undefined;
},
);
- ws.taskScheduler.stopShepherdTask(taskId);
- notifyTransition(ws, transactionId, transitionInfo);
+ wex.taskScheduler.stopShepherdTask(taskId);
+ notifyTransition(wex, transactionId, transitionInfo);
}
async abortTransaction(): Promise<void> {
- const { ws, withdrawalGroupId, transactionId, taskId } = this;
+ const { wex: ws, withdrawalGroupId, transactionId, taskId } = this;
const transitionInfo = await ws.db.runReadWriteTx(
["withdrawalGroups"],
async (tx) => {
@@ -307,7 +311,12 @@ export class WithdrawTransactionContext implements TransactionContext {
}
async resumeTransaction(): Promise<void> {
- const { ws, withdrawalGroupId, transactionId, taskId: retryTag } = this;
+ const {
+ wex: ws,
+ withdrawalGroupId,
+ transactionId,
+ taskId: retryTag,
+ } = this;
const transitionInfo = await ws.db.runReadWriteTx(
["withdrawalGroups"],
async (tx) => {
@@ -362,7 +371,12 @@ export class WithdrawTransactionContext implements TransactionContext {
}
async failTransaction(): Promise<void> {
- const { ws, withdrawalGroupId, transactionId, taskId: retryTag } = this;
+ const {
+ wex: ws,
+ withdrawalGroupId,
+ transactionId,
+ taskId: retryTag,
+ } = this;
const stateUpdate = await ws.db.runReadWriteTx(
["withdrawalGroups"],
async (tx) => {
@@ -618,17 +632,17 @@ export async function getBankWithdrawalInfo(
* Return denominations that can potentially used for a withdrawal.
*/
async function getCandidateWithdrawalDenoms(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
exchangeBaseUrl: string,
currency: string,
): Promise<DenominationRecord[]> {
- return await ws.db.runReadOnlyTx(["denominations"], async (tx) => {
- return getCandidateWithdrawalDenomsTx(ws, tx, exchangeBaseUrl, currency);
+ return await wex.db.runReadOnlyTx(["denominations"], async (tx) => {
+ return getCandidateWithdrawalDenomsTx(wex, tx, exchangeBaseUrl, currency);
});
}
export async function getCandidateWithdrawalDenomsTx(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
tx: WalletDbReadOnlyTransaction<["denominations"]>,
exchangeBaseUrl: string,
currency: string,
@@ -638,7 +652,9 @@ export async function getCandidateWithdrawalDenomsTx(
await tx.denominations.indexes.byExchangeBaseUrl.getAll(exchangeBaseUrl);
return allDenoms
.filter((d) => d.currency === currency)
- .filter((d) => isWithdrawableDenom(d, ws.config.testing.denomselAllowLate));
+ .filter((d) =>
+ isWithdrawableDenom(d, wex.ws.config.testing.denomselAllowLate),
+ );
}
/**
@@ -649,11 +665,11 @@ export async function getCandidateWithdrawalDenomsTx(
* the exchange requests per reserve.
*/
async function processPlanchetGenerate(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
withdrawalGroup: WithdrawalGroupRecord,
coinIdx: number,
): Promise<void> {
- let planchet = await ws.db.runReadOnlyTx(["planchets"], async (tx) => {
+ let planchet = await wex.db.runReadOnlyTx(["planchets"], async (tx) => {
return tx.planchets.indexes.byGroupAndIndex.get([
withdrawalGroup.withdrawalGroupId,
coinIdx,
@@ -677,11 +693,11 @@ async function processPlanchetGenerate(
}
const denomPubHash = maybeDenomPubHash;
- const denom = await ws.db.runReadOnlyTx(["denominations"], async (tx) => {
- return getDenomInfo(ws, tx, withdrawalGroup.exchangeBaseUrl, denomPubHash);
+ const denom = await wex.db.runReadOnlyTx(["denominations"], async (tx) => {
+ return getDenomInfo(wex, tx, withdrawalGroup.exchangeBaseUrl, denomPubHash);
});
checkDbInvariant(!!denom);
- const r = await ws.cryptoApi.createPlanchet({
+ const r = await wex.cryptoApi.createPlanchet({
denomPub: denom.denomPub,
feeWithdraw: Amounts.parseOrThrow(denom.feeWithdraw),
reservePriv: withdrawalGroup.reservePriv,
@@ -705,7 +721,7 @@ async function processPlanchetGenerate(
ageCommitmentProof: r.ageCommitmentProof,
lastError: undefined,
};
- await ws.db.runReadWriteTx(["planchets"], async (tx) => {
+ await wex.db.runReadWriteTx(["planchets"], async (tx) => {
const p = await tx.planchets.indexes.byGroupAndIndex.get([
withdrawalGroup.withdrawalGroupId,
coinIdx,
@@ -743,15 +759,15 @@ enum ExchangeAmlStatus {
* Emit a notification for the (self-)transition.
*/
async function transitionKycUrlUpdate(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
withdrawalGroupId: string,
kycUrl: string,
): Promise<void> {
let notificationKycUrl: string | undefined = undefined;
- const ctx = new WithdrawTransactionContext(ws, withdrawalGroupId);
+ const ctx = new WithdrawTransactionContext(wex, withdrawalGroupId);
const transactionId = ctx.transactionId;
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["withdrawalGroups"],
async (tx) => {
const wg2 = await tx.withdrawalGroups.get(withdrawalGroupId);
@@ -777,7 +793,7 @@ async function transitionKycUrlUpdate(
);
if (transitionInfo) {
// Always notify, even on self-transition, as the KYC URL might have changed.
- ws.notify({
+ wex.ws.notify({
type: NotificationType.TransactionStateTransition,
oldTxState: transitionInfo.oldTxState,
newTxState: transitionInfo.newTxState,
@@ -785,16 +801,15 @@ async function transitionKycUrlUpdate(
experimentalUserData: notificationKycUrl,
});
}
- ws.taskScheduler.startShepherdTask(ctx.taskId);
+ wex.taskScheduler.startShepherdTask(ctx.taskId);
}
async function handleKycRequired(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
withdrawalGroup: WithdrawalGroupRecord,
resp: HttpResponse,
startIdx: number,
requestCoinIdxs: number[],
- cancellationToken: CancellationToken,
): Promise<void> {
logger.info("withdrawal requires KYC");
const respJson = await resp.json();
@@ -816,9 +831,9 @@ async function handleKycRequired(
exchangeUrl,
);
logger.info(`kyc url ${url.href}`);
- const kycStatusRes = await ws.http.fetch(url.href, {
+ const kycStatusRes = await wex.http.fetch(url.href, {
method: "GET",
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
let kycUrl: string;
let amlStatus: ExchangeAmlStatus | undefined;
@@ -846,7 +861,7 @@ async function handleKycRequired(
let notificationKycUrl: string | undefined = undefined;
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["planchets", "withdrawalGroups"],
async (tx) => {
for (let i = startIdx; i < requestCoinIdxs.length; i++) {
@@ -897,7 +912,7 @@ async function handleKycRequired(
}
},
);
- notifyTransition(ws, transactionId, transitionInfo, notificationKycUrl);
+ notifyTransition(wex, transactionId, transitionInfo, notificationKycUrl);
}
/**
@@ -906,10 +921,9 @@ async function handleKycRequired(
* The verification of the response is done asynchronously to enable parallelism.
*/
async function processPlanchetExchangeBatchRequest(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
wgContext: WithdrawalGroupContext,
args: WithdrawalRequestBatchArgs,
- cancellationToken: CancellationToken,
): Promise<WithdrawalBatchResult> {
const withdrawalGroup: WithdrawalGroupRecord = wgContext.wgRecord;
logger.info(
@@ -920,7 +934,7 @@ async function processPlanchetExchangeBatchRequest(
// Indices of coins that are included in the batch request
const requestCoinIdxs: number[] = [];
- await ws.db.runReadOnlyTx(["planchets", "denominations"], async (tx) => {
+ await wex.db.runReadOnlyTx(["planchets", "denominations"], async (tx) => {
for (
let coinIdx = args.coinStartIndex;
coinIdx < args.coinStartIndex + args.batchSize &&
@@ -939,7 +953,7 @@ async function processPlanchetExchangeBatchRequest(
continue;
}
const denom = await getDenomInfo(
- ws,
+ wex,
tx,
withdrawalGroup.exchangeBaseUrl,
planchet.denomPubHash,
@@ -972,7 +986,7 @@ async function processPlanchetExchangeBatchRequest(
const errDetail = getErrorDetailFromException(e);
logger.trace("withdrawal request failed", e);
logger.trace(String(e));
- await ws.db.runReadWriteTx(["planchets"], async (tx) => {
+ await wex.db.runReadWriteTx(["planchets"], async (tx) => {
let planchet = await tx.planchets.indexes.byGroupAndIndex.get([
withdrawalGroup.withdrawalGroupId,
coinIdx,
@@ -993,21 +1007,14 @@ async function processPlanchetExchangeBatchRequest(
).href;
try {
- const resp = await ws.http.fetch(reqUrl, {
+ const resp = await wex.http.fetch(reqUrl, {
method: "POST",
body: batchReq,
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
timeout: Duration.fromSpec({ seconds: 40 }),
});
if (resp.status === HttpStatusCode.UnavailableForLegalReasons) {
- await handleKycRequired(
- ws,
- withdrawalGroup,
- resp,
- 0,
- requestCoinIdxs,
- cancellationToken,
- );
+ await handleKycRequired(wex, withdrawalGroup, resp, 0, requestCoinIdxs);
return {
batchResp: { ev_sigs: [] },
coinIdxs: [],
@@ -1031,14 +1038,14 @@ async function processPlanchetExchangeBatchRequest(
}
async function processPlanchetVerifyAndStoreCoin(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
wgContext: WithdrawalGroupContext,
coinIdx: number,
resp: ExchangeWithdrawResponse,
): Promise<void> {
const withdrawalGroup = wgContext.wgRecord;
logger.trace(`checking and storing planchet idx=${coinIdx}`);
- const d = await ws.db.runReadOnlyTx(
+ const d = await wex.db.runReadOnlyTx(
["planchets", "denominations"],
async (tx) => {
let planchet = await tx.planchets.indexes.byGroupAndIndex.get([
@@ -1053,7 +1060,7 @@ async function processPlanchetVerifyAndStoreCoin(
return;
}
const denomInfo = await getDenomInfo(
- ws,
+ wex,
tx,
withdrawalGroup.exchangeBaseUrl,
planchet.denomPubHash,
@@ -1090,20 +1097,20 @@ async function processPlanchetVerifyAndStoreCoin(
throw Error("unsupported cipher");
}
- const denomSigRsa = await ws.cryptoApi.rsaUnblind({
+ const denomSigRsa = await wex.cryptoApi.rsaUnblind({
bk: planchet.blindingKey,
blindedSig: evSig.blinded_rsa_signature,
pk: planchetDenomPub.rsa_public_key,
});
- const isValid = await ws.cryptoApi.rsaVerify({
+ const isValid = await wex.cryptoApi.rsaVerify({
hm: planchet.coinPub,
pk: planchetDenomPub.rsa_public_key,
sig: denomSigRsa.sig,
});
if (!isValid) {
- await ws.db.runReadWriteTx(["planchets"], async (tx) => {
+ await wex.db.runReadWriteTx(["planchets"], async (tx) => {
let planchet = await tx.planchets.indexes.byGroupAndIndex.get([
withdrawalGroup.withdrawalGroupId,
coinIdx,
@@ -1156,7 +1163,7 @@ async function processPlanchetVerifyAndStoreCoin(
wgContext.planchetsFinished.add(planchet.coinPub);
- await ws.db.runReadWriteTx(
+ await wex.db.runReadWriteTx(
["planchets", "coins", "coinAvailability", "denominations"],
async (tx) => {
const p = await tx.planchets.get(planchetCoinPub);
@@ -1166,7 +1173,7 @@ async function processPlanchetVerifyAndStoreCoin(
p.planchetStatus = PlanchetStatus.WithdrawalDone;
p.lastError = undefined;
await tx.planchets.put(p);
- await makeCoinAvailable(ws, tx, coin);
+ await makeCoinAvailable(wex, tx, coin);
},
);
}
@@ -1176,13 +1183,13 @@ async function processPlanchetVerifyAndStoreCoin(
* are validated, and the result of validation is stored in the database.
*/
async function updateWithdrawalDenoms(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
exchangeBaseUrl: string,
): Promise<void> {
logger.trace(
`updating denominations used for withdrawal for ${exchangeBaseUrl}`,
);
- const exchangeDetails = await ws.db.runReadOnlyTx(
+ const exchangeDetails = await wex.db.runReadOnlyTx(
["exchanges", "exchangeDetails"],
async (tx) => {
return getExchangeWireDetailsInTx(tx, exchangeBaseUrl);
@@ -1196,7 +1203,7 @@ async function updateWithdrawalDenoms(
// is checked and the result is stored in the database.
logger.trace("getting candidate denominations");
const denominations = await getCandidateWithdrawalDenoms(
- ws,
+ wex,
exchangeBaseUrl,
exchangeDetails.currency,
);
@@ -1222,10 +1229,10 @@ async function updateWithdrawalDenoms(
}) signature of ${denom.denomPubHash}`,
);
let valid = false;
- if (ws.config.testing.insecureTrustExchange) {
+ if (wex.ws.config.testing.insecureTrustExchange) {
valid = true;
} else {
- const res = await ws.cryptoApi.isValidDenom({
+ const res = await wex.cryptoApi.isValidDenom({
denom,
masterPub: exchangeDetails.masterPublicKey,
});
@@ -1246,7 +1253,7 @@ async function updateWithdrawalDenoms(
}
if (updatedDenominations.length > 0) {
logger.trace("writing denomination batch to db");
- await ws.db.runReadWriteTx(["denominations"], async (tx) => {
+ await wex.db.runReadWriteTx(["denominations"], async (tx) => {
for (let i = 0; i < updatedDenominations.length; i++) {
const denom = updatedDenominations[i];
await tx.denominations.put(denom);
@@ -1266,15 +1273,14 @@ async function updateWithdrawalDenoms(
* create a new withdrawal group for the remaining amount.
*/
async function processQueryReserve(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
withdrawalGroupId: string,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const transactionId = constructTransactionIdentifier({
tag: TransactionType.Withdrawal,
withdrawalGroupId,
});
- const withdrawalGroup = await getWithdrawalGroupRecordTx(ws.db, {
+ const withdrawalGroup = await getWithdrawalGroupRecordTx(wex.db, {
withdrawalGroupId,
});
checkDbInvariant(!!withdrawalGroup);
@@ -1291,9 +1297,9 @@ async function processQueryReserve(
logger.trace(`querying reserve status via ${reserveUrl.href}`);
- const resp = await ws.http.fetch(reserveUrl.href, {
+ const resp = await wex.http.fetch(reserveUrl.href, {
timeout: getReserveRequestTimeout(withdrawalGroup),
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
logger.trace(`reserve status code: HTTP ${resp.status}`);
@@ -1316,7 +1322,7 @@ async function processQueryReserve(
logger.trace(`got reserve status ${j2s(result.response)}`);
- const transitionResult = await ws.db.runReadWriteTx(
+ const transitionResult = await wex.db.runReadWriteTx(
["withdrawalGroups"],
async (tx) => {
const wg = await tx.withdrawalGroups.get(withdrawalGroupId);
@@ -1336,7 +1342,7 @@ async function processQueryReserve(
},
);
- notifyTransition(ws, transactionId, transitionResult);
+ notifyTransition(wex, transactionId, transitionResult);
if (transitionResult) {
return TaskRunResult.progress();
@@ -1361,9 +1367,8 @@ interface WithdrawalGroupContext {
}
async function processWithdrawalGroupAbortingBank(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
withdrawalGroup: WithdrawalGroupRecord,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const { withdrawalGroupId } = withdrawalGroup;
const transactionId = constructTransactionIdentifier({
@@ -1377,14 +1382,14 @@ async function processWithdrawalGroupAbortingBank(
}
const abortUrl = getBankAbortUrl(wgInfo.bankInfo.talerWithdrawUri);
logger.info(`aborting withdrawal at ${abortUrl}`);
- const abortResp = await ws.http.fetch(abortUrl, {
+ const abortResp = await wex.http.fetch(abortUrl, {
method: "POST",
body: {},
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
logger.info(`abort response status: ${abortResp.status}`);
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["withdrawalGroups"],
async (tx) => {
const wg = await tx.withdrawalGroups.get(withdrawalGroupId);
@@ -1402,7 +1407,7 @@ async function processWithdrawalGroupAbortingBank(
};
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
return TaskRunResult.finished();
}
@@ -1411,14 +1416,14 @@ async function processWithdrawalGroupAbortingBank(
* satisfied.
*/
async function transitionKycSatisfied(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
withdrawalGroup: WithdrawalGroupRecord,
): Promise<void> {
const transactionId = constructTransactionIdentifier({
tag: TransactionType.Withdrawal,
withdrawalGroupId: withdrawalGroup.withdrawalGroupId,
});
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["withdrawalGroups"],
async (tx) => {
const wg2 = await tx.withdrawalGroups.get(
@@ -1445,13 +1450,12 @@ async function transitionKycSatisfied(
}
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
}
async function processWithdrawalGroupPendingKyc(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
withdrawalGroup: WithdrawalGroupRecord,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const userType = "individual";
const kycInfo = withdrawalGroup.kycPending;
@@ -1468,9 +1472,9 @@ async function processWithdrawalGroupPendingKyc(
const withdrawalGroupId = withdrawalGroup.withdrawalGroupId;
logger.info(`long-polling for withdrawal KYC status via ${url.href}`);
- const kycStatusRes = await ws.http.fetch(url.href, {
+ const kycStatusRes = await wex.http.fetch(url.href, {
method: "GET",
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
logger.info(`kyc long-polling response status: HTTP ${kycStatusRes.status}`);
if (
@@ -1479,13 +1483,13 @@ async function processWithdrawalGroupPendingKyc(
// remove after the exchange is fixed or clarified
kycStatusRes.status === HttpStatusCode.NoContent
) {
- await transitionKycSatisfied(ws, withdrawalGroup);
+ await transitionKycSatisfied(wex, withdrawalGroup);
} else if (kycStatusRes.status === HttpStatusCode.Accepted) {
const kycStatus = await kycStatusRes.json();
logger.info(`kyc status: ${j2s(kycStatus)}`);
const kycUrl = kycStatus.kyc_url;
if (typeof kycUrl === "string") {
- await transitionKycUrlUpdate(ws, withdrawalGroupId, kycUrl);
+ await transitionKycUrlUpdate(wex, withdrawalGroupId, kycUrl);
}
} else if (
kycStatusRes.status === HttpStatusCode.UnavailableForLegalReasons
@@ -1499,9 +1503,8 @@ async function processWithdrawalGroupPendingKyc(
}
async function processWithdrawalGroupPendingReady(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
withdrawalGroup: WithdrawalGroupRecord,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const { withdrawalGroupId } = withdrawalGroup;
const transactionId = constructTransactionIdentifier({
@@ -1509,11 +1512,11 @@ async function processWithdrawalGroupPendingReady(
withdrawalGroupId,
});
- await fetchFreshExchange(ws, withdrawalGroup.exchangeBaseUrl);
+ await fetchFreshExchange(wex, withdrawalGroup.exchangeBaseUrl);
if (withdrawalGroup.denomsSel.selectedDenoms.length === 0) {
logger.warn("Finishing empty withdrawal group (no denoms)");
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["withdrawalGroups"],
async (tx) => {
const wg = await tx.withdrawalGroups.get(withdrawalGroupId);
@@ -1531,7 +1534,7 @@ async function processWithdrawalGroupPendingReady(
};
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
return TaskRunResult.finished();
}
@@ -1545,7 +1548,7 @@ async function processWithdrawalGroupPendingReady(
wgRecord: withdrawalGroup,
};
- await ws.db.runReadOnlyTx(["planchets"], async (tx) => {
+ await wex.db.runReadOnlyTx(["planchets"], async (tx) => {
const planchets =
await tx.planchets.indexes.byGroup.getAll(withdrawalGroupId);
for (const p of planchets) {
@@ -1558,21 +1561,16 @@ async function processWithdrawalGroupPendingReady(
// We sequentially generate planchets, so that
// large withdrawal groups don't make the wallet unresponsive.
for (let i = 0; i < numTotalCoins; i++) {
- await processPlanchetGenerate(ws, withdrawalGroup, i);
+ await processPlanchetGenerate(wex, withdrawalGroup, i);
}
const maxBatchSize = 100;
for (let i = 0; i < numTotalCoins; i += maxBatchSize) {
- const resp = await processPlanchetExchangeBatchRequest(
- ws,
- wgContext,
- {
- batchSize: maxBatchSize,
- coinStartIndex: i,
- },
- cancellationToken,
- );
+ const resp = await processPlanchetExchangeBatchRequest(wex, wgContext, {
+ batchSize: maxBatchSize,
+ coinStartIndex: i,
+ });
let work: Promise<void>[] = [];
work = [];
for (let j = 0; j < resp.coinIdxs.length; j++) {
@@ -1582,7 +1580,7 @@ async function processWithdrawalGroupPendingReady(
}
work.push(
processPlanchetVerifyAndStoreCoin(
- ws,
+ wex,
wgContext,
resp.coinIdxs[j],
resp.batchResp.ev_sigs[j],
@@ -1597,7 +1595,7 @@ async function processWithdrawalGroupPendingReady(
let numPlanchetErrors = 0;
const maxReportedErrors = 5;
- const res = await ws.db.runReadWriteTx(
+ const res = await wex.db.runReadWriteTx(
["coins", "coinAvailability", "withdrawalGroups", "planchets"],
async (tx) => {
const wg = await tx.withdrawalGroups.get(withdrawalGroupId);
@@ -1623,7 +1621,7 @@ async function processWithdrawalGroupPendingReady(
if (wg.timestampFinish === undefined && numFinished === numTotalCoins) {
wg.timestampFinish = timestampPreciseToDb(TalerPreciseTimestamp.now());
wg.status = WithdrawalGroupStatus.Done;
- await makeCoinsVisible(ws, tx, transactionId);
+ await makeCoinsVisible(wex, tx, transactionId);
}
const newTxState = computeWithdrawalTransactionStatus(wg);
@@ -1643,8 +1641,8 @@ async function processWithdrawalGroupPendingReady(
throw Error("withdrawal group does not exist anymore");
}
- notifyTransition(ws, transactionId, res.transitionInfo);
- ws.notify({
+ notifyTransition(wex, transactionId, res.transitionInfo);
+ wex.ws.notify({
type: NotificationType.BalanceChange,
hintTransactionId: transactionId,
});
@@ -1666,12 +1664,11 @@ async function processWithdrawalGroupPendingReady(
}
export async function processWithdrawalGroup(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
withdrawalGroupId: string,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
logger.trace("processing withdrawal group", withdrawalGroupId);
- const withdrawalGroup = await ws.db.runReadOnlyTx(
+ const withdrawalGroup = await wex.db.runReadOnlyTx(
["withdrawalGroups"],
async (tx) => {
return tx.withdrawalGroups.get(withdrawalGroupId);
@@ -1684,41 +1681,21 @@ export async function processWithdrawalGroup(
switch (withdrawalGroup.status) {
case WithdrawalGroupStatus.PendingRegisteringBank:
- return await processBankRegisterReserve(
- ws,
- withdrawalGroupId,
- cancellationToken,
- );
+ return await processBankRegisterReserve(wex, withdrawalGroupId);
case WithdrawalGroupStatus.PendingQueryingStatus:
- return processQueryReserve(ws, withdrawalGroupId, cancellationToken);
+ return processQueryReserve(wex, withdrawalGroupId);
case WithdrawalGroupStatus.PendingWaitConfirmBank:
- return await processReserveBankStatus(
- ws,
- withdrawalGroupId,
- cancellationToken,
- );
+ return await processReserveBankStatus(wex, withdrawalGroupId);
case WithdrawalGroupStatus.PendingAml:
// FIXME: Handle this case, withdrawal doesn't support AML yet.
return TaskRunResult.backoff();
case WithdrawalGroupStatus.PendingKyc:
- return processWithdrawalGroupPendingKyc(
- ws,
- withdrawalGroup,
- cancellationToken,
- );
+ return processWithdrawalGroupPendingKyc(wex, withdrawalGroup);
case WithdrawalGroupStatus.PendingReady:
// Continue with the actual withdrawal!
- return await processWithdrawalGroupPendingReady(
- ws,
- withdrawalGroup,
- cancellationToken,
- );
+ return await processWithdrawalGroupPendingReady(wex, withdrawalGroup);
case WithdrawalGroupStatus.AbortingBank:
- return await processWithdrawalGroupAbortingBank(
- ws,
- withdrawalGroup,
- cancellationToken,
- );
+ return await processWithdrawalGroupAbortingBank(wex, withdrawalGroup);
case WithdrawalGroupStatus.AbortedBank:
case WithdrawalGroupStatus.AbortedExchange:
case WithdrawalGroupStatus.FailedAbortingBank:
@@ -1743,13 +1720,13 @@ const AGE_MASK_GROUPS = "8:10:12:14:16:18"
.map((n) => parseInt(n, 10));
export async function getExchangeWithdrawalInfo(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
exchangeBaseUrl: string,
instructedAmount: AmountJson,
ageRestricted: number | undefined,
): Promise<ExchangeWithdrawalDetails> {
logger.trace("updating exchange");
- const exchange = await fetchFreshExchange(ws, exchangeBaseUrl);
+ const exchange = await fetchFreshExchange(wex, exchangeBaseUrl);
if (exchange.currency != instructedAmount.currency) {
// Specifying the amount in the conversion input currency is not yet supported.
@@ -1760,7 +1737,7 @@ export async function getExchangeWithdrawalInfo(
}
const withdrawalAccountsList = await fetchWithdrawalAccountInfo(
- ws,
+ wex,
{
exchange,
instructedAmount,
@@ -1769,11 +1746,11 @@ export async function getExchangeWithdrawalInfo(
);
logger.trace("updating withdrawal denoms");
- await updateWithdrawalDenoms(ws, exchangeBaseUrl);
+ await updateWithdrawalDenoms(wex, exchangeBaseUrl);
logger.trace("getting candidate denoms");
const denoms = await getCandidateWithdrawalDenoms(
- ws,
+ wex,
exchangeBaseUrl,
instructedAmount.currency,
);
@@ -1781,7 +1758,7 @@ export async function getExchangeWithdrawalInfo(
const selectedDenoms = selectWithdrawalDenominations(
instructedAmount,
denoms,
- ws.config.testing.denomselAllowLate,
+ wex.ws.config.testing.denomselAllowLate,
);
logger.trace("selection done");
@@ -1806,11 +1783,11 @@ export async function getExchangeWithdrawalInfo(
let earliestDepositExpiration: TalerProtocolTimestamp | undefined;
- await ws.db.runReadOnlyTx(["denominations"], async (tx) => {
+ await wex.db.runReadOnlyTx(["denominations"], async (tx) => {
for (let i = 0; i < selectedDenoms.selectedDenoms.length; i++) {
const ds = selectedDenoms.selectedDenoms[i];
const denom = await getDenomInfo(
- ws,
+ wex,
tx,
exchangeBaseUrl,
ds.denomPubHash,
@@ -1837,7 +1814,7 @@ export async function getExchangeWithdrawalInfo(
checkLogicInvariant(!!earliestDepositExpiration);
const possibleDenoms = await getCandidateWithdrawalDenoms(
- ws,
+ wex,
exchangeBaseUrl,
instructedAmount.currency,
);
@@ -1915,18 +1892,18 @@ const ongoingChecks: WithdrawalOperationMemoryMap = {};
* to the wallet's list of known exchanges.
*/
export async function getWithdrawalDetailsForUri(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
talerWithdrawUri: string,
opts: GetWithdrawalDetailsForUriOpts = {},
): Promise<WithdrawUriInfoResponse> {
logger.trace(`getting withdrawal details for URI ${talerWithdrawUri}`);
- const info = await getBankWithdrawalInfo(ws.http, talerWithdrawUri);
+ const info = await getBankWithdrawalInfo(wex.http, talerWithdrawUri);
logger.trace(`got bank info`);
if (info.suggestedExchange) {
try {
// If the exchange entry doesn't exist yet,
// it'll be created as an ephemeral entry.
- await fetchFreshExchange(ws, info.suggestedExchange);
+ await fetchFreshExchange(wex, 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.
@@ -1938,7 +1915,7 @@ export async function getWithdrawalDetailsForUri(
const currency = Amounts.currencyOf(info.amount);
- const listExchangesResp = await listExchanges(ws);
+ const listExchangesResp = await listExchanges(wex);
const possibleExchanges = listExchangesResp.exchanges.filter((x) => {
return (
x.currency === currency &&
@@ -1957,7 +1934,7 @@ export async function getWithdrawalDetailsForUri(
ongoingChecks[talerWithdrawUri] = true;
const bankApi = new TalerBankIntegrationHttpClient(
info.apiBaseUrl,
- ws.http,
+ wex.http,
);
console.log(
`waiting operation (${info.operationId}) to change from pending`,
@@ -2076,11 +2053,10 @@ export function getBankAbortUrl(talerWithdrawUri: string): string {
}
async function registerReserveWithBank(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
withdrawalGroupId: string,
- cancellationToken: CancellationToken,
): Promise<void> {
- const withdrawalGroup = await ws.db.runReadOnlyTx(
+ const withdrawalGroup = await wex.db.runReadOnlyTx(
["withdrawalGroups"],
async (tx) => {
return await tx.withdrawalGroups.get(withdrawalGroupId);
@@ -2112,17 +2088,17 @@ async function registerReserveWithBank(
selected_exchange: bankInfo.exchangePaytoUri,
};
logger.info(`registering reserve with bank: ${j2s(reqBody)}`);
- const httpResp = await ws.http.fetch(bankStatusUrl, {
+ const httpResp = await wex.http.fetch(bankStatusUrl, {
method: "POST",
body: reqBody,
timeout: getReserveRequestTimeout(withdrawalGroup),
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
const status = await readSuccessResponseJsonOrThrow(
httpResp,
codeForBankWithdrawalOperationPostResponse(),
);
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["withdrawalGroups"],
async (tx) => {
const r = await tx.withdrawalGroups.get(withdrawalGroupId);
@@ -2154,14 +2130,14 @@ async function registerReserveWithBank(
},
);
- notifyTransition(ws, transactionId, transitionInfo);
+ notifyTransition(wex, transactionId, transitionInfo);
}
async function transitionBankAborted(
ctx: WithdrawTransactionContext,
): Promise<TaskRunResult> {
logger.info("bank aborted the withdrawal");
- const transitionInfo = await ctx.ws.db.runReadWriteTx(
+ const transitionInfo = await ctx.wex.db.runReadWriteTx(
["withdrawalGroups"],
async (tx) => {
const r = await tx.withdrawalGroups.get(ctx.withdrawalGroupId);
@@ -2190,17 +2166,16 @@ async function transitionBankAborted(
};
},
);
- notifyTransition(ctx.ws, ctx.transactionId, transitionInfo);
+ notifyTransition(ctx.wex, ctx.transactionId, transitionInfo);
return TaskRunResult.finished();
}
async function processBankRegisterReserve(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
withdrawalGroupId: string,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
- const ctx = new WithdrawTransactionContext(ws, withdrawalGroupId);
- const withdrawalGroup = await getWithdrawalGroupRecordTx(ws.db, {
+ const ctx = new WithdrawTransactionContext(wex, withdrawalGroupId);
+ const withdrawalGroup = await getWithdrawalGroupRecordTx(wex.db, {
withdrawalGroupId,
});
if (!withdrawalGroup) {
@@ -2226,9 +2201,9 @@ async function processBankRegisterReserve(
uriResult.bankIntegrationApiBaseUrl,
);
- const statusResp = await ws.http.fetch(url.href, {
+ const statusResp = await wex.http.fetch(url.href, {
timeout: getReserveRequestTimeout(withdrawalGroup),
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
const status = await readSuccessResponseJsonOrThrow(
@@ -2242,16 +2217,15 @@ async function processBankRegisterReserve(
// FIXME: Put confirm transfer URL in the DB!
- await registerReserveWithBank(ws, withdrawalGroupId, cancellationToken);
+ await registerReserveWithBank(wex, withdrawalGroupId);
return TaskRunResult.progress();
}
async function processReserveBankStatus(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
withdrawalGroupId: string,
- cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
- const withdrawalGroup = await getWithdrawalGroupRecordTx(ws.db, {
+ const withdrawalGroup = await getWithdrawalGroupRecordTx(wex.db, {
withdrawalGroupId,
});
@@ -2259,7 +2233,7 @@ async function processReserveBankStatus(
return TaskRunResult.finished();
}
- const ctx = new WithdrawTransactionContext(ws, withdrawalGroupId);
+ const ctx = new WithdrawTransactionContext(wex, withdrawalGroupId);
if (
withdrawalGroup.wgInfo.withdrawalType != WithdrawalRecordType.BankIntegrated
@@ -2282,9 +2256,9 @@ async function processReserveBankStatus(
bankStatusUrl.searchParams.set("long_poll_ms", "30000");
logger.info(`long-polling for withdrawal operation at ${bankStatusUrl.href}`);
- const statusResp = await ws.http.fetch(bankStatusUrl.href, {
+ const statusResp = await wex.http.fetch(bankStatusUrl.href, {
timeout: getReserveRequestTimeout(withdrawalGroup),
- cancellationToken,
+ cancellationToken: wex.cancellationToken,
});
logger.info(
`long-polling for withdrawal operation returned status ${statusResp.status}`,
@@ -2307,7 +2281,7 @@ async function processReserveBankStatus(
return TaskRunResult.longpollReturnedPending();
}
- const transitionInfo = await ws.db.runReadWriteTx(
+ const transitionInfo = await wex.db.runReadWriteTx(
["withdrawalGroups"],
async (tx) => {
const r = await tx.withdrawalGroups.get(withdrawalGroupId);
@@ -2341,7 +2315,7 @@ async function processReserveBankStatus(
},
);
- notifyTransition(ws, ctx.transactionId, transitionInfo);
+ notifyTransition(wex, ctx.transactionId, transitionInfo);
if (transitionInfo) {
return TaskRunResult.progress();
@@ -2360,7 +2334,7 @@ export interface PrepareCreateWithdrawalGroupResult {
}
export async function internalPrepareCreateWithdrawalGroup(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
args: {
reserveStatus: WithdrawalGroupStatus;
amount: AmountJson;
@@ -2373,7 +2347,7 @@ export async function internalPrepareCreateWithdrawalGroup(
},
): Promise<PrepareCreateWithdrawalGroupResult> {
const reserveKeyPair =
- args.reserveKeyPair ?? (await ws.cryptoApi.createEddsaKeypair({}));
+ args.reserveKeyPair ?? (await wex.cryptoApi.createEddsaKeypair({}));
const now = AbsoluteTime.toPreciseTimestamp(AbsoluteTime.now());
const secretSeed = encodeCrock(getRandomBytes(32));
const canonExchange = canonicalizeBaseUrl(args.exchangeBaseUrl);
@@ -2385,7 +2359,7 @@ export async function internalPrepareCreateWithdrawalGroup(
if (args.forcedWithdrawalGroupId) {
withdrawalGroupId = args.forcedWithdrawalGroupId;
const wgId = withdrawalGroupId;
- const existingWg = await ws.db.runReadOnlyTx(
+ const existingWg = await wex.db.runReadOnlyTx(
["withdrawalGroups"],
async (tx) => {
return tx.withdrawalGroups.get(wgId);
@@ -2403,9 +2377,9 @@ export async function internalPrepareCreateWithdrawalGroup(
withdrawalGroupId = encodeCrock(getRandomBytes(32));
}
- await updateWithdrawalDenoms(ws, canonExchange);
+ await updateWithdrawalDenoms(wex, canonExchange);
const denoms = await getCandidateWithdrawalDenoms(
- ws,
+ wex,
canonExchange,
currency,
);
@@ -2418,13 +2392,13 @@ export async function internalPrepareCreateWithdrawalGroup(
amount,
denoms,
args.forcedDenomSel,
- ws.config.testing.denomselAllowLate,
+ wex.ws.config.testing.denomselAllowLate,
);
} else {
initialDenomSel = selectWithdrawalDenominations(
amount,
denoms,
- ws.config.testing.denomselAllowLate,
+ wex.ws.config.testing.denomselAllowLate,
);
}
@@ -2447,7 +2421,7 @@ export async function internalPrepareCreateWithdrawalGroup(
wgInfo: args.wgInfo,
};
- await fetchFreshExchange(ws, canonExchange);
+ await fetchFreshExchange(wex, canonExchange);
const transactionId = constructTransactionIdentifier({
tag: TransactionType.Withdrawal,
withdrawalGroupId: withdrawalGroup.withdrawalGroupId,
@@ -2476,7 +2450,7 @@ export interface PerformCreateWithdrawalGroupResult {
}
export async function internalPerformCreateWithdrawalGroup(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
tx: WalletDbReadWriteTransaction<
["withdrawalGroups", "reserves", "exchanges"]
>,
@@ -2523,17 +2497,17 @@ export async function internalPerformCreateWithdrawalGroup(
};
const exchangeUsedRes = await markExchangeUsed(
- ws,
+ wex,
tx,
prep.withdrawalGroup.exchangeBaseUrl,
);
const ctx = new WithdrawTransactionContext(
- ws,
+ wex,
withdrawalGroup.withdrawalGroupId,
);
- ws.taskScheduler.startShepherdTask(ctx.taskId);
+ wex.taskScheduler.startShepherdTask(ctx.taskId);
return {
withdrawalGroup,
@@ -2551,7 +2525,7 @@ export async function internalPerformCreateWithdrawalGroup(
* of the other arguments is done in that case.
*/
export async function internalCreateWithdrawalGroup(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
args: {
reserveStatus: WithdrawalGroupStatus;
amount: AmountJson;
@@ -2563,21 +2537,21 @@ export async function internalCreateWithdrawalGroup(
wgInfo: WgInfo;
},
): Promise<WithdrawalGroupRecord> {
- const prep = await internalPrepareCreateWithdrawalGroup(ws, args);
+ const prep = await internalPrepareCreateWithdrawalGroup(wex, args);
const transactionId = constructTransactionIdentifier({
tag: TransactionType.Withdrawal,
withdrawalGroupId: prep.withdrawalGroup.withdrawalGroupId,
});
- const res = await ws.db.runReadWriteTx(
+ const res = await wex.db.runReadWriteTx(
["withdrawalGroups", "reserves", "exchanges", "exchangeDetails"],
async (tx) => {
- return await internalPerformCreateWithdrawalGroup(ws, tx, prep);
+ return await internalPerformCreateWithdrawalGroup(wex, tx, prep);
},
);
if (res.exchangeNotif) {
- ws.notify(res.exchangeNotif);
+ wex.ws.notify(res.exchangeNotif);
}
- notifyTransition(ws, transactionId, res.transitionInfo);
+ notifyTransition(wex, transactionId, res.transitionInfo);
return res.withdrawalGroup;
}
@@ -2590,7 +2564,7 @@ export async function internalCreateWithdrawalGroup(
* with the bank.
*/
export async function acceptWithdrawalFromUri(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: {
talerWithdrawUri: string;
selectedExchange: string;
@@ -2602,7 +2576,7 @@ export async function acceptWithdrawalFromUri(
logger.info(
`accepting withdrawal via ${req.talerWithdrawUri}, canonicalized selected exchange ${selectedExchange}`,
);
- const existingWithdrawalGroup = await ws.db.runReadOnlyTx(
+ const existingWithdrawalGroup = await wex.db.runReadOnlyTx(
["withdrawalGroups"],
async (tx) => {
return await tx.withdrawalGroups.indexes.byTalerWithdrawUri.get(
@@ -2629,21 +2603,21 @@ export async function acceptWithdrawalFromUri(
};
}
- await fetchFreshExchange(ws, selectedExchange);
+ await fetchFreshExchange(wex, selectedExchange);
const withdrawInfo = await getBankWithdrawalInfo(
- ws.http,
+ wex.http,
req.talerWithdrawUri,
);
const exchangePaytoUri = await getExchangePaytoUri(
- ws,
+ wex,
selectedExchange,
withdrawInfo.wireTypes,
);
- const exchange = await fetchFreshExchange(ws, selectedExchange);
+ const exchange = await fetchFreshExchange(wex, selectedExchange);
const withdrawalAccountList = await fetchWithdrawalAccountInfo(
- ws,
+ wex,
{
exchange,
instructedAmount: withdrawInfo.amount,
@@ -2651,7 +2625,7 @@ export async function acceptWithdrawalFromUri(
CancellationToken.CONTINUE,
);
- const withdrawalGroup = await internalCreateWithdrawalGroup(ws, {
+ const withdrawalGroup = await internalCreateWithdrawalGroup(wex, {
amount: withdrawInfo.amount,
exchangeBaseUrl: req.selectedExchange,
wgInfo: {
@@ -2672,16 +2646,16 @@ export async function acceptWithdrawalFromUri(
const withdrawalGroupId = withdrawalGroup.withdrawalGroupId;
- const ctx = new WithdrawTransactionContext(ws, withdrawalGroupId);
+ const ctx = new WithdrawTransactionContext(wex, withdrawalGroupId);
- ws.notify({
+ wex.ws.notify({
type: NotificationType.BalanceChange,
hintTransactionId: ctx.transactionId,
});
- await waitWithdrawalRegistered(ws, ctx);
+ await waitWithdrawalRegistered(wex, ctx);
- ws.taskScheduler.startShepherdTask(ctx.taskId);
+ wex.taskScheduler.startShepherdTask(ctx.taskId);
return {
reservePub: withdrawalGroup.reservePub,
@@ -2691,12 +2665,12 @@ export async function acceptWithdrawalFromUri(
}
async function internalWaitWithdrawalRegistered(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
ctx: WithdrawTransactionContext,
withdrawalNotifFlag: AsyncFlag,
): Promise<void> {
while (true) {
- const { withdrawalRec, retryRec } = await ws.db.runReadOnlyTx(
+ const { withdrawalRec, retryRec } = await wex.db.runReadOnlyTx(
["withdrawalGroups", "operationRetries"],
async (tx) => {
return {
@@ -2742,7 +2716,7 @@ async function internalWaitWithdrawalRegistered(
}
async function waitWithdrawalRegistered(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
ctx: WithdrawTransactionContext,
): Promise<void> {
// FIXME: We should use Symbol.dispose magic here for cleanup!
@@ -2750,7 +2724,7 @@ async function waitWithdrawalRegistered(
const withdrawalNotifFlag = 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.TransactionStateTransition &&
notif.transactionId === ctx.transactionId
@@ -2762,7 +2736,7 @@ async function waitWithdrawalRegistered(
try {
const res = await internalWaitWithdrawalRegistered(
- ws,
+ wex,
ctx,
withdrawalNotifFlag,
);
@@ -2774,7 +2748,7 @@ async function waitWithdrawalRegistered(
}
async function fetchAccount(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
instructedAmount: AmountJson,
acct: ExchangeWireAccount,
reservePub: string | undefined,
@@ -2789,7 +2763,7 @@ async function fetchAccount(
"amount_credit",
Amounts.stringify(instructedAmount),
);
- const httpResp = await ws.http.fetch(reqUrl.href, {
+ const httpResp = await wex.http.fetch(reqUrl.href, {
cancellationToken,
});
const respOrErr = await readSuccessResponseJsonOrErrorCode(
@@ -2807,7 +2781,7 @@ async function fetchAccount(
paytoUri = acct.payto_uri;
transferAmount = resp.amount_debit;
const configUrl = new URL("config", acct.conversion_url);
- const configResp = await ws.http.fetch(configUrl.href, {
+ const configResp = await wex.http.fetch(configUrl.href, {
cancellationToken,
});
const configRespOrError = await readSuccessResponseJsonOrErrorCode(
@@ -2854,7 +2828,7 @@ async function fetchAccount(
* currency and require conversion.
*/
async function fetchWithdrawalAccountInfo(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: {
exchange: ReadyExchangeSummary;
instructedAmount: AmountJson;
@@ -2866,7 +2840,7 @@ async function fetchWithdrawalAccountInfo(
const withdrawalAccounts: WithdrawalExchangeAccountDetails[] = [];
for (let acct of exchange.wireInfo.accounts) {
const acctInfo = await fetchAccount(
- ws,
+ wex,
req.instructedAmount,
acct,
req.reservePub,
@@ -2886,7 +2860,7 @@ async function fetchWithdrawalAccountInfo(
* Asynchronously starts the withdrawal.
*/
export async function createManualWithdrawal(
- ws: InternalWalletState,
+ wex: WalletExecutionContext,
req: {
exchangeBaseUrl: string;
amount: AmountLike;
@@ -2896,19 +2870,19 @@ export async function createManualWithdrawal(
): Promise<AcceptManualWithdrawalResult> {
const { exchangeBaseUrl } = req;
const amount = Amounts.parseOrThrow(req.amount);
- const exchange = await fetchFreshExchange(ws, exchangeBaseUrl);
+ const exchange = await fetchFreshExchange(wex, exchangeBaseUrl);
if (exchange.currency != amount.currency) {
throw Error(
"manual withdrawal with conversion from foreign currency is not yet supported",
);
}
- const reserveKeyPair: EddsaKeypair = await ws.cryptoApi.createEddsaKeypair(
+ const reserveKeyPair: EddsaKeypair = await wex.cryptoApi.createEddsaKeypair(
{},
);
const withdrawalAccountsList = await fetchWithdrawalAccountInfo(
- ws,
+ wex,
{
exchange,
instructedAmount: amount,
@@ -2917,7 +2891,7 @@ export async function createManualWithdrawal(
CancellationToken.CONTINUE,
);
- const withdrawalGroup = await internalCreateWithdrawalGroup(ws, {
+ const withdrawalGroup = await internalCreateWithdrawalGroup(wex, {
amount: Amounts.jsonifyAmount(req.amount),
wgInfo: {
withdrawalType: WithdrawalRecordType.BankManual,
@@ -2931,23 +2905,23 @@ export async function createManualWithdrawal(
});
const ctx = new WithdrawTransactionContext(
- ws,
+ wex,
withdrawalGroup.withdrawalGroupId,
);
- const exchangePaytoUris = await ws.db.runReadOnlyTx(
+ const exchangePaytoUris = await wex.db.runReadOnlyTx(
["withdrawalGroups", "exchanges", "exchangeDetails"],
async (tx) => {
return await getFundingPaytoUris(tx, withdrawalGroup.withdrawalGroupId);
},
);
- ws.notify({
+ wex.ws.notify({
type: NotificationType.BalanceChange,
hintTransactionId: ctx.transactionId,
});
- ws.taskScheduler.startShepherdTask(ctx.taskId);
+ wex.taskScheduler.startShepherdTask(ctx.taskId);
return {
reservePub: withdrawalGroup.reservePub,