summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2024-02-22 11:33:32 +0100
committerFlorian Dold <florian@dold.me>2024-02-27 14:58:36 +0100
commit2ab4ad686380b3cfe5c5245312e42af8a69c01f6 (patch)
treee82af5ea7defbc4bdd7b468f714212041914dc59 /packages/taler-wallet-core
parent41f34031ae934e8c802cdbb73fffb5a39c9c6a68 (diff)
downloadwallet-core-2ab4ad686380b3cfe5c5245312e42af8a69c01f6.tar.gz
wallet-core-2ab4ad686380b3cfe5c5245312e42af8a69c01f6.tar.bz2
wallet-core-2ab4ad686380b3cfe5c5245312e42af8a69c01f6.zip
move operation out of ws
Diffstat (limited to 'packages/taler-wallet-core')
-rw-r--r--packages/taler-wallet-core/src/coinSelection.ts4
-rw-r--r--packages/taler-wallet-core/src/common.ts4
-rw-r--r--packages/taler-wallet-core/src/deposits.ts6
-rw-r--r--packages/taler-wallet-core/src/pay-merchant.ts8
-rw-r--r--packages/taler-wallet-core/src/pay-peer-common.ts6
-rw-r--r--packages/taler-wallet-core/src/recoup.ts10
-rw-r--r--packages/taler-wallet-core/src/refresh.ts22
-rw-r--r--packages/taler-wallet-core/src/wallet.ts61
-rw-r--r--packages/taler-wallet-core/src/withdraw.ts27
9 files changed, 82 insertions, 66 deletions
diff --git a/packages/taler-wallet-core/src/coinSelection.ts b/packages/taler-wallet-core/src/coinSelection.ts
index f0b435b54..e1ae613bc 100644
--- a/packages/taler-wallet-core/src/coinSelection.ts
+++ b/packages/taler-wallet-core/src/coinSelection.ts
@@ -64,7 +64,7 @@ import { getAutoRefreshExecuteThreshold } from "./common.js";
import { DenominationRecord, WalletDbReadOnlyTransaction } from "./db.js";
import { isWithdrawableDenom } from "./denominations.js";
import { getExchangeWireDetailsInTx } from "./exchanges.js";
-import { InternalWalletState } from "./wallet.js";
+import { getDenomInfo, InternalWalletState } from "./wallet.js";
const logger = new Logger("coinSelection.ts");
@@ -1088,7 +1088,7 @@ export async function selectPeerCoins(
if (!coin) {
throw Error("repair not possible, coin not found");
}
- const denom = await ws.getDenomInfo(
+ const denom = await getDenomInfo(
ws,
tx,
coin.exchangeBaseUrl,
diff --git a/packages/taler-wallet-core/src/common.ts b/packages/taler-wallet-core/src/common.ts
index 8c6650f4a..08adb2515 100644
--- a/packages/taler-wallet-core/src/common.ts
+++ b/packages/taler-wallet-core/src/common.ts
@@ -61,7 +61,7 @@ import {
timestampPreciseToDb,
} from "./db.js";
import { createRefreshGroup } from "./refresh.js";
-import { InternalWalletState } from "./wallet.js";
+import { InternalWalletState, getDenomInfo } from "./wallet.js";
const logger = new Logger("operations/common.ts");
@@ -161,7 +161,7 @@ export async function spendCoins(
if (!coin) {
throw Error("coin allocated for payment doesn't exist anymore");
}
- const denom = await ws.getDenomInfo(
+ const denom = await getDenomInfo(
ws,
tx,
coin.exchangeBaseUrl,
diff --git a/packages/taler-wallet-core/src/deposits.ts b/packages/taler-wallet-core/src/deposits.ts
index ed8778368..9db8cfc27 100644
--- a/packages/taler-wallet-core/src/deposits.ts
+++ b/packages/taler-wallet-core/src/deposits.ts
@@ -109,7 +109,7 @@ import {
notifyTransition,
parseTransactionIdentifier,
} from "./transactions.js";
-import { InternalWalletState } from "./wallet.js";
+import { InternalWalletState, getDenomInfo } from "./wallet.js";
import { getCandidateWithdrawalDenomsTx } from "./withdraw.js";
/**
@@ -1527,7 +1527,7 @@ export async function getCounterpartyEffectiveDepositAmount(
if (!coin) {
throw Error("can't calculate deposit amount, coin not found");
}
- const denom = await ws.getDenomInfo(
+ const denom = await getDenomInfo(
ws,
tx,
coin.exchangeBaseUrl,
@@ -1593,7 +1593,7 @@ async function getTotalFeesForDepositAmount(
if (!coin) {
throw Error("can't calculate deposit amount, coin not found");
}
- const denom = await ws.getDenomInfo(
+ const denom = await getDenomInfo(
ws,
tx,
coin.exchangeBaseUrl,
diff --git a/packages/taler-wallet-core/src/pay-merchant.ts b/packages/taler-wallet-core/src/pay-merchant.ts
index 8fcb728d4..332660ad5 100644
--- a/packages/taler-wallet-core/src/pay-merchant.ts
+++ b/packages/taler-wallet-core/src/pay-merchant.ts
@@ -138,7 +138,11 @@ import {
notifyTransition,
parseTransactionIdentifier,
} from "./transactions.js";
-import { EXCHANGE_COINS_LOCK, InternalWalletState } from "./wallet.js";
+import {
+ EXCHANGE_COINS_LOCK,
+ getDenomInfo,
+ InternalWalletState,
+} from "./wallet.js";
import { getCandidateWithdrawalDenomsTx } from "./withdraw.js";
/**
@@ -2959,7 +2963,7 @@ async function computeRefreshRequest(
if (!coin) {
throw Error("coin not found");
}
- const denomInfo = await ws.getDenomInfo(
+ const denomInfo = await getDenomInfo(
ws,
tx,
coin.exchangeBaseUrl,
diff --git a/packages/taler-wallet-core/src/pay-peer-common.ts b/packages/taler-wallet-core/src/pay-peer-common.ts
index efb5bdb7e..dbc3376b4 100644
--- a/packages/taler-wallet-core/src/pay-peer-common.ts
+++ b/packages/taler-wallet-core/src/pay-peer-common.ts
@@ -33,7 +33,7 @@ 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 } from "./wallet.js";
+import { InternalWalletState, getDenomInfo } from "./wallet.js";
import { getCandidateWithdrawalDenomsTx } from "./withdraw.js";
/**
@@ -50,7 +50,7 @@ export async function queryCoinInfosForSelection(
if (!coin) {
throw Error("coin not found anymore");
}
- const denom = await ws.getDenomInfo(
+ const denom = await getDenomInfo(
ws,
tx,
coin.exchangeBaseUrl,
@@ -84,7 +84,7 @@ export async function getTotalPeerPaymentCost(
if (!coin) {
throw Error("can't calculate payment cost, coin not found");
}
- const denomInfo = await ws.getDenomInfo(
+ const denomInfo = await getDenomInfo(
ws,
tx,
coin.exchangeBaseUrl,
diff --git a/packages/taler-wallet-core/src/recoup.ts b/packages/taler-wallet-core/src/recoup.ts
index 0ec71f4e7..ecf55d42b 100644
--- a/packages/taler-wallet-core/src/recoup.ts
+++ b/packages/taler-wallet-core/src/recoup.ts
@@ -63,7 +63,7 @@ import {
} from "./db.js";
import { createRefreshGroup } from "./refresh.js";
import { constructTransactionIdentifier } from "./transactions.js";
-import type { InternalWalletState } from "./wallet.js";
+import { getDenomInfo, type InternalWalletState } from "./wallet.js";
import { internalCreateWithdrawalGroup } from "./withdraw.js";
const logger = new Logger("operations/recoup.ts");
@@ -123,7 +123,7 @@ async function recoupWithdrawCoin(
): Promise<void> {
const reservePub = cs.reservePub;
const denomInfo = await ws.db.runReadOnlyTx(["denominations"], async (tx) => {
- const denomInfo = await ws.getDenomInfo(
+ const denomInfo = await getDenomInfo(
ws,
tx,
coin.exchangeBaseUrl,
@@ -194,7 +194,7 @@ async function recoupRefreshCoin(
const d = await ws.db.runReadOnlyTx(
["coins", "denominations"],
async (tx) => {
- const denomInfo = await ws.getDenomInfo(
+ const denomInfo = await getDenomInfo(
ws,
tx,
coin.exchangeBaseUrl,
@@ -258,13 +258,13 @@ async function recoupRefreshCoin(
logger.warn("refresh old coin for recoup not found");
return;
}
- const oldCoinDenom = await ws.getDenomInfo(
+ const oldCoinDenom = await getDenomInfo(
ws,
tx,
oldCoin.exchangeBaseUrl,
oldCoin.denomPubHash,
);
- const revokedCoinDenom = await ws.getDenomInfo(
+ const revokedCoinDenom = await getDenomInfo(
ws,
tx,
revokedCoin.exchangeBaseUrl,
diff --git a/packages/taler-wallet-core/src/refresh.ts b/packages/taler-wallet-core/src/refresh.ts
index f1ee84f3e..cc5eff12c 100644
--- a/packages/taler-wallet-core/src/refresh.ts
+++ b/packages/taler-wallet-core/src/refresh.ts
@@ -99,7 +99,11 @@ import {
constructTransactionIdentifier,
notifyTransition,
} from "./transactions.js";
-import { EXCHANGE_COINS_LOCK, InternalWalletState } from "./wallet.js";
+import {
+ EXCHANGE_COINS_LOCK,
+ getDenomInfo,
+ InternalWalletState,
+} from "./wallet.js";
import { getCandidateWithdrawalDenomsTx } from "./withdraw.js";
const logger = new Logger("refresh.ts");
@@ -378,7 +382,7 @@ async function provideRefreshSession(
const { availableAmount, availableDenoms } = await ws.db.runReadOnlyTx(
["denominations"],
async (tx) => {
- const oldDenom = await ws.getDenomInfo(
+ const oldDenom = await getDenomInfo(
ws,
tx,
exch.exchangeBaseUrl,
@@ -516,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 ws.getDenomInfo(
+ const oldDenom = await getDenomInfo(
ws,
tx,
oldCoin.exchangeBaseUrl,
@@ -530,7 +534,7 @@ async function refreshMelt(
const newCoinDenoms: RefreshNewDenomInfo[] = [];
for (const dh of refreshSession.newDenoms) {
- const newDenom = await ws.getDenomInfo(
+ const newDenom = await getDenomInfo(
ws,
tx,
oldCoin.exchangeBaseUrl,
@@ -819,7 +823,7 @@ async function refreshReveal(
const oldCoin = await tx.coins.get(refreshGroup.oldCoinPubs[coinIndex]);
checkDbInvariant(!!oldCoin, "melt coin doesn't exist");
- const oldDenom = await ws.getDenomInfo(
+ const oldDenom = await getDenomInfo(
ws,
tx,
oldCoin.exchangeBaseUrl,
@@ -833,7 +837,7 @@ async function refreshReveal(
const newCoinDenoms: RefreshNewDenomInfo[] = [];
for (const dh of refreshSession.newDenoms) {
- const newDenom = await ws.getDenomInfo(
+ const newDenom = await getDenomInfo(
ws,
tx,
oldCoin.exchangeBaseUrl,
@@ -1162,7 +1166,7 @@ export async function calculateRefreshOutput(
for (const ocp of oldCoinPubs) {
const coin = await tx.coins.get(ocp.coinPub);
checkDbInvariant(!!coin, "coin must be in database");
- const denom = await ws.getDenomInfo(
+ const denom = await getDenomInfo(
ws,
tx,
coin.exchangeBaseUrl,
@@ -1210,7 +1214,7 @@ async function applyRefresh(
for (const ocp of oldCoinPubs) {
const coin = await tx.coins.get(ocp.coinPub);
checkDbInvariant(!!coin, "coin must be in database");
- const denom = await ws.getDenomInfo(
+ const denom = await getDenomInfo(
ws,
tx,
coin.exchangeBaseUrl,
@@ -1420,7 +1424,7 @@ export async function forceRefresh(
if (!coin) {
throw Error(`coin (pubkey ${c}) not found`);
}
- const denom = await ws.getDenomInfo(
+ const denom = await getDenomInfo(
ws,
tx,
coin.exchangeBaseUrl,
diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts
index f21db0531..086c2ffa5 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -26,7 +26,7 @@ import { IDBFactory } from "@gnu-taler/idb-bridge";
import {
AmountString,
Amounts,
- AsyncCondition,
+ CancellationToken,
CoinDumpJson,
CoinStatus,
CoreApiResponse,
@@ -135,6 +135,7 @@ import {
validateIban,
} from "@gnu-taler/taler-util";
import type { HttpRequestLibrary } from "@gnu-taler/taler-util/http";
+import { ObservabilityContext } from "../../taler-util/src/observability.js";
import {
getUserAttentions,
getUserAttentionsUnreadCount,
@@ -269,6 +270,21 @@ import {
const logger = new Logger("wallet.ts");
+/**
+ * Execution context for code that is run in the wallet.
+ *
+ * Typically the excecution context is either for a wallet-core
+ * request handler or for a shepherded task.
+ */
+export interface WalletExecutionContext {
+ readonly ws: InternalWalletState;
+ readonly cryptoApi: TalerCryptoInterface;
+ readonly cancellationToken: CancellationToken;
+ readonly http: HttpRequestLibrary;
+ readonly db: DbAccess<typeof WalletStoresV1>;
+ readonly oc: ObservabilityContext;
+}
+
export const EXCHANGE_COINS_LOCK = "exchange-coins-lock";
export const EXCHANGE_RESERVES_LOCK = "exchange-reserves-lock";
@@ -440,7 +456,7 @@ async function dumpCoins(ws: InternalWalletState): Promise<CoinDumpJson> {
if (cs.type == CoinSourceType.Withdraw) {
withdrawalReservePub = cs.reservePub;
}
- const denomInfo = await ws.getDenomInfo(
+ const denomInfo = await getDenomInfo(
ws,
tx,
c.exchangeBaseUrl,
@@ -1438,6 +1454,24 @@ export class Wallet {
}
}
+export async function getDenomInfo(
+ ws: InternalWalletState,
+ tx: WalletDbReadOnlyTransaction<["denominations"]>,
+ exchangeBaseUrl: string,
+ denomPubHash: string,
+): Promise<DenominationInfo | undefined> {
+ const key = `${exchangeBaseUrl}:${denomPubHash}`;
+ const cached = ws.denomCache[key];
+ if (cached) {
+ return cached;
+ }
+ const d = await tx.denominations.get([exchangeBaseUrl, denomPubHash]);
+ if (d) {
+ return DenominationRecord.toDenomInfo(d);
+ }
+ return undefined;
+}
+
/**
* Internal state of the wallet.
*
@@ -1445,10 +1479,9 @@ export class Wallet {
*/
export class InternalWalletState {
cryptoApi: TalerCryptoInterface;
- cryptoDispatcher: CryptoDispatcher;
+ private cryptoDispatcher: CryptoDispatcher;
readonly timerGroup: TimerGroup;
- workAvailable = new AsyncCondition();
stopped = false;
private listeners: NotificationListener[] = [];
@@ -1456,7 +1489,7 @@ export class InternalWalletState {
initCalled = false;
// FIXME: Use an LRU cache here.
- private denomCache: Record<string, DenominationInfo> = {};
+ denomCache: Record<string, DenominationInfo> = {};
/**
* Promises that are waiting for a particular resource.
@@ -1517,24 +1550,6 @@ export class InternalWalletState {
}
}
- async getDenomInfo(
- ws: InternalWalletState,
- tx: WalletDbReadOnlyTransaction<["denominations"]>,
- exchangeBaseUrl: string,
- denomPubHash: string,
- ): Promise<DenominationInfo | undefined> {
- const key = `${exchangeBaseUrl}:${denomPubHash}`;
- const cached = this.denomCache[key];
- if (cached) {
- return cached;
- }
- const d = await tx.denominations.get([exchangeBaseUrl, denomPubHash]);
- if (d) {
- return DenominationRecord.toDenomInfo(d);
- }
- return undefined;
- }
-
notify(n: WalletNotification): void {
logger.trace(`Notification: ${j2s(n)}`);
for (const l of this.listeners) {
diff --git a/packages/taler-wallet-core/src/withdraw.ts b/packages/taler-wallet-core/src/withdraw.ts
index a54295613..c3c3c2a8e 100644
--- a/packages/taler-wallet-core/src/withdraw.ts
+++ b/packages/taler-wallet-core/src/withdraw.ts
@@ -146,7 +146,7 @@ import {
WALLET_BANK_INTEGRATION_PROTOCOL_VERSION,
WALLET_EXCHANGE_PROTOCOL_VERSION,
} from "./versions.js";
-import type { InternalWalletState } from "./wallet.js";
+import { getDenomInfo, type InternalWalletState } from "./wallet.js";
/**
* Logger for this file.
@@ -678,12 +678,7 @@ async function processPlanchetGenerate(
const denomPubHash = maybeDenomPubHash;
const denom = await ws.db.runReadOnlyTx(["denominations"], async (tx) => {
- return ws.getDenomInfo(
- ws,
- tx,
- withdrawalGroup.exchangeBaseUrl,
- denomPubHash,
- );
+ return getDenomInfo(ws, tx, withdrawalGroup.exchangeBaseUrl, denomPubHash);
});
checkDbInvariant(!!denom);
const r = await ws.cryptoApi.createPlanchet({
@@ -943,7 +938,7 @@ async function processPlanchetExchangeBatchRequest(
logger.warn("processPlanchet: planchet already withdrawn");
continue;
}
- const denom = await ws.getDenomInfo(
+ const denom = await getDenomInfo(
ws,
tx,
withdrawalGroup.exchangeBaseUrl,
@@ -1057,7 +1052,7 @@ async function processPlanchetVerifyAndStoreCoin(
logger.warn("processPlanchet: planchet already withdrawn");
return;
}
- const denomInfo = await ws.getDenomInfo(
+ const denomInfo = await getDenomInfo(
ws,
tx,
withdrawalGroup.exchangeBaseUrl,
@@ -1814,7 +1809,7 @@ export async function getExchangeWithdrawalInfo(
await ws.db.runReadOnlyTx(["denominations"], async (tx) => {
for (let i = 0; i < selectedDenoms.selectedDenoms.length; i++) {
const ds = selectedDenoms.selectedDenoms[i];
- const denom = await ws.getDenomInfo(
+ const denom = await getDenomInfo(
ws,
tx,
exchangeBaseUrl,
@@ -1911,7 +1906,9 @@ export interface GetWithdrawalDetailsForUriOpts {
type WithdrawalOperationMemoryMap = {
[uri: string]: boolean | undefined;
};
+
const ongoingChecks: WithdrawalOperationMemoryMap = {};
+
/**
* Get more information about a taler://withdraw URI.
*
@@ -1964,9 +1961,10 @@ export async function getWithdrawalDetailsForUri(
info.apiBaseUrl,
ws.http,
);
- console.log(
- `waiting operation (${info.operationId}) to change from pending`,
+ logger.info(
+ `waiting for operation (${info.operationId}) to change from pending`,
);
+ // FIXME: This needs a cancellation token or timeout!
bankApi
.getWithdrawalOperationById(info.operationId, {
old_state: "pending",
@@ -1980,11 +1978,6 @@ export async function getWithdrawalDetailsForUri(
2,
)}`,
);
- ws.notify({
- type: NotificationType.WithdrawalOperationTransition,
- operationId: info.operationId,
- state: resp.type === "fail" ? info.status : resp.body.status,
- });
ongoingChecks[talerWithdrawUri] = false;
});
}