aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/operations
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-core/src/operations')
-rw-r--r--packages/taler-wallet-core/src/operations/README.md7
-rw-r--r--packages/taler-wallet-core/src/operations/backup/export.ts2
-rw-r--r--packages/taler-wallet-core/src/operations/backup/import.ts2
-rw-r--r--packages/taler-wallet-core/src/operations/backup/index.ts2
-rw-r--r--packages/taler-wallet-core/src/operations/backup/state.ts2
-rw-r--r--packages/taler-wallet-core/src/operations/balance.ts5
-rw-r--r--packages/taler-wallet-core/src/operations/currencies.ts81
-rw-r--r--packages/taler-wallet-core/src/operations/deposits.ts33
-rw-r--r--packages/taler-wallet-core/src/operations/errors.ts132
-rw-r--r--packages/taler-wallet-core/src/operations/exchanges.ts86
-rw-r--r--packages/taler-wallet-core/src/operations/pay.ts4
-rw-r--r--packages/taler-wallet-core/src/operations/pending.ts2
-rw-r--r--packages/taler-wallet-core/src/operations/recoup.ts4
-rw-r--r--packages/taler-wallet-core/src/operations/refresh.ts4
-rw-r--r--packages/taler-wallet-core/src/operations/refund.ts30
-rw-r--r--packages/taler-wallet-core/src/operations/reserves.ts6
-rw-r--r--packages/taler-wallet-core/src/operations/state.ts148
-rw-r--r--packages/taler-wallet-core/src/operations/testing.ts2
-rw-r--r--packages/taler-wallet-core/src/operations/tip.ts4
-rw-r--r--packages/taler-wallet-core/src/operations/transactions.ts2
-rw-r--r--packages/taler-wallet-core/src/operations/versions.ts45
-rw-r--r--packages/taler-wallet-core/src/operations/withdraw.ts95
22 files changed, 173 insertions, 525 deletions
diff --git a/packages/taler-wallet-core/src/operations/README.md b/packages/taler-wallet-core/src/operations/README.md
new file mode 100644
index 000000000..32e2fbfc8
--- /dev/null
+++ b/packages/taler-wallet-core/src/operations/README.md
@@ -0,0 +1,7 @@
+# Wallet Operations
+
+This folder contains the implementations for all wallet operations that operate on the wallet state.
+
+To avoid cyclic dependencies, these files must **not** reference each other. Instead, other operations should only be accessed via injected dependencies.
+
+Avoiding cyclic dependencies is important for module bundlers. \ No newline at end of file
diff --git a/packages/taler-wallet-core/src/operations/backup/export.ts b/packages/taler-wallet-core/src/operations/backup/export.ts
index 4eab9d5ee..42cc9b651 100644
--- a/packages/taler-wallet-core/src/operations/backup/export.ts
+++ b/packages/taler-wallet-core/src/operations/backup/export.ts
@@ -49,7 +49,7 @@ import {
BackupRefreshSession,
BackupExchangeDetails,
} from "@gnu-taler/taler-util";
-import { InternalWalletState } from "../state.js";
+import { InternalWalletState } from "../../common.js";
import { provideBackupState, getWalletBackupState } from "./state";
import { Amounts, getTimestampNow } from "@gnu-taler/taler-util";
import {
diff --git a/packages/taler-wallet-core/src/operations/backup/import.ts b/packages/taler-wallet-core/src/operations/backup/import.ts
index 1caa508ff..ce4d14f1e 100644
--- a/packages/taler-wallet-core/src/operations/backup/import.ts
+++ b/packages/taler-wallet-core/src/operations/backup/import.ts
@@ -51,7 +51,7 @@ import { j2s } from "@gnu-taler/taler-util";
import { checkDbInvariant, checkLogicInvariant } from "../../util/invariants";
import { Logger } from "@gnu-taler/taler-util";
import { initRetryInfo } from "../../util/retries.js";
-import { InternalWalletState } from "../state.js";
+import { InternalWalletState } from "../../common.js";
import { provideBackupState } from "./state.js";
import { makeEventId, TombstoneTag } from "../transactions.js";
import { getExchangeDetails } from "../exchanges.js";
diff --git a/packages/taler-wallet-core/src/operations/backup/index.ts b/packages/taler-wallet-core/src/operations/backup/index.ts
index 2cc056721..8a0aad560 100644
--- a/packages/taler-wallet-core/src/operations/backup/index.ts
+++ b/packages/taler-wallet-core/src/operations/backup/index.ts
@@ -24,7 +24,7 @@
/**
* Imports.
*/
-import { InternalWalletState } from "../state.js";
+import { InternalWalletState } from "../../common.js";
import {
AmountString,
BackupRecovery,
diff --git a/packages/taler-wallet-core/src/operations/backup/state.ts b/packages/taler-wallet-core/src/operations/backup/state.ts
index bb540d5af..3a7311d14 100644
--- a/packages/taler-wallet-core/src/operations/backup/state.ts
+++ b/packages/taler-wallet-core/src/operations/backup/state.ts
@@ -23,7 +23,7 @@ import {
} from "../../db.js";
import { checkDbInvariant } from "../../util/invariants.js";
import { GetReadOnlyAccess } from "../../util/query.js";
-import { InternalWalletState } from "../state.js";
+import { InternalWalletState } from "../../common.js";
export async function provideBackupState(
ws: InternalWalletState,
diff --git a/packages/taler-wallet-core/src/operations/balance.ts b/packages/taler-wallet-core/src/operations/balance.ts
index 4dba6beb7..298893920 100644
--- a/packages/taler-wallet-core/src/operations/balance.ts
+++ b/packages/taler-wallet-core/src/operations/balance.ts
@@ -23,12 +23,11 @@ import {
Amounts,
Logger,
} from "@gnu-taler/taler-util";
-
import { CoinStatus, WalletStoresV1 } from "../db.js";
import { GetReadOnlyAccess } from "../util/query.js";
-import { InternalWalletState } from "./state.js";
+import { InternalWalletState } from "../common.js";
-const logger = new Logger("withdraw.ts");
+const logger = new Logger("operations/balance.ts");
interface WalletBalance {
available: AmountJson;
diff --git a/packages/taler-wallet-core/src/operations/currencies.ts b/packages/taler-wallet-core/src/operations/currencies.ts
deleted file mode 100644
index e591b50c0..000000000
--- a/packages/taler-wallet-core/src/operations/currencies.ts
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 Taler Systems S.A.
-
- GNU Taler is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
- */
-
-/**
- * Imports.
- */
-import { ExchangeRecord } from "../db.js";
-import { Logger } from "@gnu-taler/taler-util";
-import { getExchangeDetails } from "./exchanges.js";
-import { InternalWalletState } from "./state.js";
-
-const logger = new Logger("currencies.ts");
-
-export interface TrustInfo {
- isTrusted: boolean;
- isAudited: boolean;
-}
-
-/**
- * Check if and how an exchange is trusted and/or audited.
- */
-export async function getExchangeTrust(
- ws: InternalWalletState,
- exchangeInfo: ExchangeRecord,
-): Promise<TrustInfo> {
- let isTrusted = false;
- let isAudited = false;
-
- return await ws.db
- .mktx((x) => ({
- exchanges: x.exchanges,
- exchangeDetails: x.exchangeDetails,
- exchangesTrustStore: x.exchangeTrust,
- auditorTrust: x.auditorTrust,
- }))
- .runReadOnly(async (tx) => {
- const exchangeDetails = await getExchangeDetails(
- tx,
- exchangeInfo.baseUrl,
- );
-
- if (!exchangeDetails) {
- throw Error(`exchange ${exchangeInfo.baseUrl} details not available`);
- }
- const exchangeTrustRecord = await tx.exchangesTrustStore.indexes.byExchangeMasterPub.get(
- exchangeDetails.masterPublicKey,
- );
- if (
- exchangeTrustRecord &&
- exchangeTrustRecord.uids.length > 0 &&
- exchangeTrustRecord.currency === exchangeDetails.currency
- ) {
- isTrusted = true;
- }
-
- for (const auditor of exchangeDetails.auditors) {
- const auditorTrustRecord = await tx.auditorTrust.indexes.byAuditorPub.get(
- auditor.auditor_pub,
- );
- if (auditorTrustRecord && auditorTrustRecord.uids.length > 0) {
- isAudited = true;
- break;
- }
- }
-
- return { isTrusted, isAudited };
- });
-}
diff --git a/packages/taler-wallet-core/src/operations/deposits.ts b/packages/taler-wallet-core/src/operations/deposits.ts
index c376ae8e0..5051fd32a 100644
--- a/packages/taler-wallet-core/src/operations/deposits.ts
+++ b/packages/taler-wallet-core/src/operations/deposits.ts
@@ -14,19 +14,10 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { kdf } from "../crypto/primitives/kdf.js";
-import {
- encodeCrock,
- getRandomBytes,
- stringToBytes,
-} from "../crypto/talerCrypto.js";
-import { selectPayCoins } from "../util/coinSelection.js";
-import { canonicalJson } from "@gnu-taler/taler-util";
-import { readSuccessResponseJsonOrThrow } from "../util/http.js";
-import { initRetryInfo, updateRetryInfoTimeout } from "../util/retries.js";
import {
Amounts,
buildCodecForObject,
+ canonicalJson,
Codec,
codecForString,
codecForTimestamp,
@@ -36,6 +27,7 @@ import {
CreateDepositGroupResponse,
durationFromSpec,
getTimestampNow,
+ Logger,
NotificationType,
parsePaytoUri,
TalerErrorDetails,
@@ -45,7 +37,20 @@ import {
TrackDepositGroupRequest,
TrackDepositGroupResponse,
} from "@gnu-taler/taler-util";
-import { URL } from "../util/url";
+import { InternalWalletState } from "../common.js";
+import { kdf } from "../crypto/primitives/kdf.js";
+import {
+ encodeCrock,
+ getRandomBytes,
+ stringToBytes,
+} from "../crypto/talerCrypto.js";
+import { DepositGroupRecord } from "../db.js";
+import { guardOperationException } from "../errors.js";
+import { selectPayCoins } from "../util/coinSelection.js";
+import { readSuccessResponseJsonOrThrow } from "../util/http.js";
+import { initRetryInfo, updateRetryInfoTimeout } from "../util/retries.js";
+import { URL } from "../util/url.js";
+import { getExchangeDetails } from "./exchanges.js";
import {
applyCoinSpend,
extractContractData,
@@ -54,12 +59,6 @@ import {
getEffectiveDepositAmount,
getTotalPaymentCost,
} from "./pay.js";
-import { InternalWalletState } from "./state.js";
-import { Logger } from "@gnu-taler/taler-util";
-import { DepositGroupRecord } from "../db.js";
-
-import { guardOperationException } from "./errors.js";
-import { getExchangeDetails } from "./exchanges.js";
/**
* Logger.
diff --git a/packages/taler-wallet-core/src/operations/errors.ts b/packages/taler-wallet-core/src/operations/errors.ts
deleted file mode 100644
index d788405ff..000000000
--- a/packages/taler-wallet-core/src/operations/errors.ts
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2019-2020 Taler Systems SA
-
- GNU Taler is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
- */
-
-/**
- * Classes and helpers for error handling specific to wallet operations.
- *
- * @author Florian Dold <dold@taler.net>
- */
-
-/**
- * Imports.
- */
-import { TalerErrorCode, TalerErrorDetails } from "@gnu-taler/taler-util";
-
-/**
- * This exception is there to let the caller know that an error happened,
- * but the error has already been reported by writing it to the database.
- */
-export class OperationFailedAndReportedError extends Error {
- static fromCode(
- ec: TalerErrorCode,
- message: string,
- details: Record<string, unknown>,
- ): OperationFailedAndReportedError {
- return new OperationFailedAndReportedError(
- makeErrorDetails(ec, message, details),
- );
- }
-
- constructor(public operationError: TalerErrorDetails) {
- super(operationError.message);
-
- // Set the prototype explicitly.
- Object.setPrototypeOf(this, OperationFailedAndReportedError.prototype);
- }
-}
-
-/**
- * This exception is thrown when an error occurred and the caller is
- * responsible for recording the failure in the database.
- */
-export class OperationFailedError extends Error {
- static fromCode(
- ec: TalerErrorCode,
- message: string,
- details: Record<string, unknown>,
- ): OperationFailedError {
- return new OperationFailedError(makeErrorDetails(ec, message, details));
- }
-
- constructor(public operationError: TalerErrorDetails) {
- super(operationError.message);
-
- // Set the prototype explicitly.
- Object.setPrototypeOf(this, OperationFailedError.prototype);
- }
-}
-
-export function makeErrorDetails(
- ec: TalerErrorCode,
- message: string,
- details: Record<string, unknown>,
-): TalerErrorDetails {
- return {
- code: ec,
- hint: `Error: ${TalerErrorCode[ec]}`,
- details: details,
- message,
- };
-}
-
-/**
- * Run an operation and call the onOpError callback
- * when there was an exception or operation error that must be reported.
- * The cause will be re-thrown to the caller.
- */
-export async function guardOperationException<T>(
- op: () => Promise<T>,
- onOpError: (e: TalerErrorDetails) => Promise<void>,
-): Promise<T> {
- try {
- return await op();
- } catch (e) {
- if (e instanceof OperationFailedAndReportedError) {
- throw e;
- }
- if (e instanceof OperationFailedError) {
- await onOpError(e.operationError);
- throw new OperationFailedAndReportedError(e.operationError);
- }
- if (e instanceof Error) {
- const opErr = makeErrorDetails(
- TalerErrorCode.WALLET_UNEXPECTED_EXCEPTION,
- `unexpected exception (message: ${e.message})`,
- {
- stack: e.stack,
- },
- );
- await onOpError(opErr);
- throw new OperationFailedAndReportedError(opErr);
- }
- // Something was thrown that is not even an exception!
- // Try to stringify it.
- let excString: string;
- try {
- excString = e.toString();
- } catch (e) {
- // Something went horribly wrong.
- excString = "can't stringify exception";
- }
- const opErr = makeErrorDetails(
- TalerErrorCode.WALLET_UNEXPECTED_EXCEPTION,
- `unexpected exception (not an exception, ${excString})`,
- {},
- );
- await onOpError(opErr);
- throw new OperationFailedAndReportedError(opErr);
- }
-}
diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts b/packages/taler-wallet-core/src/operations/exchanges.ts
index c8dfcbc17..65cc8f5e9 100644
--- a/packages/taler-wallet-core/src/operations/exchanges.ts
+++ b/packages/taler-wallet-core/src/operations/exchanges.ts
@@ -20,6 +20,7 @@
import {
Amounts,
Auditor,
+ canonicalizeBaseUrl,
codecForExchangeKeysJson,
codecForExchangeWireJson,
compare,
@@ -30,6 +31,7 @@ import {
ExchangeWireJson,
getTimestampNow,
isTimestampExpired,
+ j2s,
Logger,
NotificationType,
parsePaytoUri,
@@ -38,38 +40,37 @@ import {
TalerErrorDetails,
Timestamp,
} from "@gnu-taler/taler-util";
+import { decodeCrock, encodeCrock, hash } from "../crypto/talerCrypto.js";
+import { CryptoApi } from "../crypto/workers/cryptoApi.js";
import {
DenominationRecord,
DenominationStatus,
+ ExchangeDetailsRecord,
ExchangeRecord,
+ WalletStoresV1,
WireFee,
- ExchangeDetailsRecord,
WireInfo,
- WalletStoresV1,
} from "../db.js";
-import { j2s, canonicalizeBaseUrl } from "@gnu-taler/taler-util";
-import { updateRetryInfoTimeout, initRetryInfo } from "../util/retries.js";
-import {
- makeErrorDetails,
- guardOperationException,
- OperationFailedError,
-} from "./errors.js";
-import { createRecoupGroup, processRecoupGroup } from "./recoup.js";
-import { InternalWalletState } from "./state.js";
-import {
- WALLET_CACHE_BREAKER_CLIENT_VERSION,
- WALLET_EXCHANGE_PROTOCOL_VERSION,
-} from "./versions.js";
import {
getExpiryTimestamp,
HttpRequestLibrary,
readSuccessResponseJsonOrThrow,
readSuccessResponseTextOrThrow,
} from "../util/http.js";
-import { CryptoApi } from "../crypto/workers/cryptoApi.js";
import { DbAccess, GetReadOnlyAccess } from "../util/query.js";
-import { decodeCrock, encodeCrock, hash } from "../crypto/talerCrypto.js";
+import { initRetryInfo, updateRetryInfoTimeout } from "../util/retries.js";
import { URL } from "../util/url.js";
+import {
+ guardOperationException,
+ makeErrorDetails,
+ OperationFailedError,
+} from "../errors.js";
+import { createRecoupGroup, processRecoupGroup } from "./recoup.js";
+import { InternalWalletState, TrustInfo } from "../common.js";
+import {
+ WALLET_CACHE_BREAKER_CLIENT_VERSION,
+ WALLET_EXCHANGE_PROTOCOL_VERSION,
+} from "../versions.js";
const logger = new Logger("exchanges.ts");
@@ -605,3 +606,54 @@ export async function getExchangePaytoUri(
}
throw Error("no matching exchange account found");
}
+
+/**
+ * Check if and how an exchange is trusted and/or audited.
+ */
+export async function getExchangeTrust(
+ ws: InternalWalletState,
+ exchangeInfo: ExchangeRecord,
+): Promise<TrustInfo> {
+ let isTrusted = false;
+ let isAudited = false;
+
+ return await ws.db
+ .mktx((x) => ({
+ exchanges: x.exchanges,
+ exchangeDetails: x.exchangeDetails,
+ exchangesTrustStore: x.exchangeTrust,
+ auditorTrust: x.auditorTrust,
+ }))
+ .runReadOnly(async (tx) => {
+ const exchangeDetails = await getExchangeDetails(
+ tx,
+ exchangeInfo.baseUrl,
+ );
+
+ if (!exchangeDetails) {
+ throw Error(`exchange ${exchangeInfo.baseUrl} details not available`);
+ }
+ const exchangeTrustRecord = await tx.exchangesTrustStore.indexes.byExchangeMasterPub.get(
+ exchangeDetails.masterPublicKey,
+ );
+ if (
+ exchangeTrustRecord &&
+ exchangeTrustRecord.uids.length > 0 &&
+ exchangeTrustRecord.currency === exchangeDetails.currency
+ ) {
+ isTrusted = true;
+ }
+
+ for (const auditor of exchangeDetails.auditors) {
+ const auditorTrustRecord = await tx.auditorTrust.indexes.byAuditorPub.get(
+ auditor.auditor_pub,
+ );
+ if (auditorTrustRecord && auditorTrustRecord.uids.length > 0) {
+ isAudited = true;
+ break;
+ }
+ }
+
+ return { isTrusted, isAudited };
+ });
+}
diff --git a/packages/taler-wallet-core/src/operations/pay.ts b/packages/taler-wallet-core/src/operations/pay.ts
index c62ad0f25..6d185cae8 100644
--- a/packages/taler-wallet-core/src/operations/pay.ts
+++ b/packages/taler-wallet-core/src/operations/pay.ts
@@ -68,7 +68,7 @@ import {
getRetryDuration,
} from "../util/retries.js";
import { getTotalRefreshCost, createRefreshGroup } from "./refresh.js";
-import { InternalWalletState, EXCHANGE_COINS_LOCK } from "./state.js";
+import { InternalWalletState, EXCHANGE_COINS_LOCK } from "../common.js";
import { ContractTermsUtil } from "../util/contractTerms.js";
import { getExchangeDetails } from "./exchanges.js";
import { GetReadWriteAccess } from "../util/query.js";
@@ -98,7 +98,7 @@ import {
makeErrorDetails,
OperationFailedAndReportedError,
OperationFailedError,
-} from "./errors.js";
+} from "../errors.js";
import { URL } from "../util/url.js";
/**
diff --git a/packages/taler-wallet-core/src/operations/pending.ts b/packages/taler-wallet-core/src/operations/pending.ts
index 8201e8cb9..fff64739c 100644
--- a/packages/taler-wallet-core/src/operations/pending.ts
+++ b/packages/taler-wallet-core/src/operations/pending.ts
@@ -29,7 +29,7 @@ import {
ReserveType,
} from "../pending-types.js";
import { getTimestampNow, Timestamp } from "@gnu-taler/taler-util";
-import { InternalWalletState } from "./state.js";
+import { InternalWalletState } from "../common.js";
import { getBalancesInsideTransaction } from "./balance.js";
import { GetReadOnlyAccess } from "../util/query.js";
diff --git a/packages/taler-wallet-core/src/operations/recoup.ts b/packages/taler-wallet-core/src/operations/recoup.ts
index 938422d3b..402111129 100644
--- a/packages/taler-wallet-core/src/operations/recoup.ts
+++ b/packages/taler-wallet-core/src/operations/recoup.ts
@@ -48,10 +48,10 @@ import { readSuccessResponseJsonOrThrow } from "../util/http.js";
import { Logger } from "@gnu-taler/taler-util";
import { initRetryInfo, updateRetryInfoTimeout } from "../util/retries.js";
import { URL } from "../util/url.js";
-import { guardOperationException } from "./errors.js";
+import { guardOperationException } from "../errors.js";
import { createRefreshGroup, processRefreshGroup } from "./refresh.js";
import { getReserveRequestTimeout, processReserve } from "./reserves.js";
-import { InternalWalletState } from "./state.js";
+import { InternalWalletState } from "../common.js";
import { GetReadWriteAccess } from "../util/query.js";
const logger = new Logger("operations/recoup.ts");
diff --git a/packages/taler-wallet-core/src/operations/refresh.ts b/packages/taler-wallet-core/src/operations/refresh.ts
index 3c81362ce..06d735645 100644
--- a/packages/taler-wallet-core/src/operations/refresh.ts
+++ b/packages/taler-wallet-core/src/operations/refresh.ts
@@ -52,9 +52,9 @@ import {
timestampMin,
} from "@gnu-taler/taler-util";
import { URL } from "../util/url.js";
-import { guardOperationException } from "./errors.js";
+import { guardOperationException } from "../errors.js";
import { updateExchangeFromUrl } from "./exchanges.js";
-import { EXCHANGE_COINS_LOCK, InternalWalletState } from "./state.js";
+import { EXCHANGE_COINS_LOCK, InternalWalletState } from "../common.js";
import {
isWithdrawableDenom,
selectWithdrawalDenominations,
diff --git a/packages/taler-wallet-core/src/operations/refund.ts b/packages/taler-wallet-core/src/operations/refund.ts
index 6ef55e535..09006b811 100644
--- a/packages/taler-wallet-core/src/operations/refund.ts
+++ b/packages/taler-wallet-core/src/operations/refund.ts
@@ -23,12 +23,7 @@
/**
* Imports.
*/
-import { InternalWalletState } from "./state.js";
-import { guardOperationException } from "./errors.js";
import {
- getTimestampNow,
- timestampAddDuration,
- TalerErrorDetails,
AbortingCoin,
AbortRequest,
AmountJson,
@@ -37,29 +32,34 @@ import {
codecForAbortResponse,
codecForMerchantOrderRefundPickupResponse,
CoinPublicKey,
+ getTimestampNow,
+ Logger,
MerchantCoinRefundFailureStatus,
MerchantCoinRefundStatus,
MerchantCoinRefundSuccessStatus,
NotificationType,
parseRefundUri,
RefreshReason,
+ TalerErrorCode,
+ TalerErrorDetails,
+ timestampAddDuration,
} from "@gnu-taler/taler-util";
-import { Logger } from "@gnu-taler/taler-util";
-import { readSuccessResponseJsonOrThrow } from "../util/http.js";
-import { URL } from "../util/url.js";
-import { updateRetryInfoTimeout, initRetryInfo } from "../util/retries.js";
-import { checkDbInvariant } from "../util/invariants.js";
-import { TalerErrorCode } from "@gnu-taler/taler-util";
import {
- PurchaseRecord,
- CoinStatus,
- RefundState,
AbortStatus,
+ CoinStatus,
+ PurchaseRecord,
RefundReason,
+ RefundState,
WalletStoresV1,
} from "../db.js";
-import { getTotalRefreshCost, createRefreshGroup } from "./refresh.js";
+import { readSuccessResponseJsonOrThrow } from "../util/http.js";
+import { checkDbInvariant } from "../util/invariants.js";
import { GetReadWriteAccess } from "../util/query.js";
+import { initRetryInfo, updateRetryInfoTimeout } from "../util/retries.js";
+import { URL } from "../util/url.js";
+import { guardOperationException } from "../errors.js";
+import { createRefreshGroup, getTotalRefreshCost } from "./refresh.js";
+import { InternalWalletState } from "../common.js";
const logger = new Logger("refund.ts");
diff --git a/packages/taler-wallet-core/src/operations/reserves.ts b/packages/taler-wallet-core/src/operations/reserves.ts
index 998fbf3e0..dde71f040 100644
--- a/packages/taler-wallet-core/src/operations/reserves.ts
+++ b/packages/taler-wallet-core/src/operations/reserves.ts
@@ -47,13 +47,14 @@ import {
getRetryDuration,
updateRetryInfoTimeout,
} from "../util/retries.js";
-import { guardOperationException, OperationFailedError } from "./errors.js";
+import { guardOperationException, OperationFailedError } from "../errors.js";
import {
updateExchangeFromUrl,
getExchangePaytoUri,
getExchangeDetails,
+ getExchangeTrust,
} from "./exchanges.js";
-import { InternalWalletState } from "./state.js";
+import { InternalWalletState } from "../common.js";
import {
updateWithdrawalDenoms,
getCandidateWithdrawalDenoms,
@@ -62,7 +63,6 @@ import {
processWithdrawGroup,
getBankWithdrawalInfo,
} from "./withdraw.js";
-import { getExchangeTrust } from "./currencies.js";
import { encodeCrock, getRandomBytes } from "../crypto/talerCrypto.js";
import { Logger } from "@gnu-taler/taler-util";
import {
diff --git a/packages/taler-wallet-core/src/operations/state.ts b/packages/taler-wallet-core/src/operations/state.ts
deleted file mode 100644
index ee7ceb8af..000000000
--- a/packages/taler-wallet-core/src/operations/state.ts
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2019 GNUnet e.V.
-
- GNU Taler is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
- */
-
-/**
- * Imports.
- */
-import {
- WalletNotification,
- BalancesResponse,
- Logger,
-} from "@gnu-taler/taler-util";
-import { CryptoApi, CryptoWorkerFactory } from "../crypto/workers/cryptoApi.js";
-import { WalletStoresV1 } from "../db.js";
-import { PendingOperationsResponse } from "../pending-types.js";
-import { AsyncOpMemoMap, AsyncOpMemoSingle } from "../util/asyncMemo.js";
-import { HttpRequestLibrary } from "../util/http";
-import {
- AsyncCondition,
- OpenedPromise,
- openPromise,
-} from "../util/promiseUtils.js";
-import { DbAccess } from "../util/query.js";
-import { TimerGroup } from "../util/timer.js";
-
-type NotificationListener = (n: WalletNotification) => void;
-
-const logger = new Logger("state.ts");
-
-export const EXCHANGE_COINS_LOCK = "exchange-coins-lock";
-export const EXCHANGE_RESERVES_LOCK = "exchange-reserves-lock";
-
-/**
- * Internal state of the wallet.
- */
-export class InternalWalletState {
- memoProcessReserve: AsyncOpMemoMap<void> = new AsyncOpMemoMap();
- memoMakePlanchet: AsyncOpMemoMap<void> = new AsyncOpMemoMap();
- memoGetPending: AsyncOpMemoSingle<PendingOperationsResponse> = new AsyncOpMemoSingle();
- memoGetBalance: AsyncOpMemoSingle<BalancesResponse> = new AsyncOpMemoSingle();
- memoProcessRefresh: AsyncOpMemoMap<void> = new AsyncOpMemoMap();
- memoProcessRecoup: AsyncOpMemoMap<void> = new AsyncOpMemoMap();
- memoProcessDeposit: AsyncOpMemoMap<void> = new AsyncOpMemoMap();
- cryptoApi: CryptoApi;
-
- timerGroup: TimerGroup = new TimerGroup();
- latch = new AsyncCondition();
- stopped = false;
- memoRunRetryLoop = new AsyncOpMemoSingle<void>();
-
- listeners: NotificationListener[] = [];
-
- initCalled: boolean = false;
-
- /**
- * Promises that are waiting for a particular resource.
- */
- private resourceWaiters: Record<string, OpenedPromise<void>[]> = {};
-
- /**
- * Resources that are currently locked.
- */
- private resourceLocks: Set<string> = new Set();
-
- constructor(
- // FIXME: Make this a getter and make
- // the actual value nullable.
- // Check if we are in a DB migration / garbage collection
- // and throw an error in that case.
- public db: DbAccess<typeof WalletStoresV1>,
- public http: HttpRequestLibrary,
- cryptoWorkerFactory: CryptoWorkerFactory,
- ) {
- this.cryptoApi = new CryptoApi(cryptoWorkerFactory);
- }
-
- notify(n: WalletNotification): void {
- logger.trace("Notification", n);
- for (const l of this.listeners) {
- const nc = JSON.parse(JSON.stringify(n));
- setTimeout(() => {
- l(nc);
- }, 0);
- }
- }
-
- addNotificationListener(f: (n: WalletNotification) => void): void {
- this.listeners.push(f);
- }
-
- /**
- * Stop ongoing processing.
- */
- stop(): void {
- this.stopped = true;
- this.timerGroup.stopCurrentAndFutureTimers();
- this.cryptoApi.stop();
- }
-
- /**
- * Run an async function after acquiring a list of locks, identified
- * by string tokens.
- */
- async runSequentialized<T>(tokens: string[], f: () => Promise<T>) {
- // Make sure locks are always acquired in the same order
- tokens = [...tokens].sort();
-
- for (const token of tokens) {
- if (this.resourceLocks.has(token)) {
- const p = openPromise<void>();
- let waitList = this.resourceWaiters[token];
- if (!waitList) {
- waitList = this.resourceWaiters[token] = [];
- }
- waitList.push(p);
- await p.promise;
- }
- this.resourceLocks.add(token);
- }
-
- try {
- logger.trace(`begin exclusive execution on ${JSON.stringify(tokens)}`);
- const result = await f();
- logger.trace(`end exclusive execution on ${JSON.stringify(tokens)}`);
- return result;
- } finally {
- for (const token of tokens) {
- this.resourceLocks.delete(token);
- let waiter = (this.resourceWaiters[token] ?? []).shift();
- if (waiter) {
- waiter.resolve();
- }
- }
- }
- }
-}
diff --git a/packages/taler-wallet-core/src/operations/testing.ts b/packages/taler-wallet-core/src/operations/testing.ts
index ce3a47f36..8a0c20200 100644
--- a/packages/taler-wallet-core/src/operations/testing.ts
+++ b/packages/taler-wallet-core/src/operations/testing.ts
@@ -34,7 +34,7 @@ import {
PreparePayResultType,
} from "@gnu-taler/taler-util";
import { createTalerWithdrawReserve } from "./reserves.js";
-import { InternalWalletState } from "./state.js";
+import { InternalWalletState } from "../common.js";
import { URL } from "../util/url.js";
import { confirmPay, preparePayForUri } from "./pay.js";
import { getBalances } from "./balance.js";
diff --git a/packages/taler-wallet-core/src/operations/tip.ts b/packages/taler-wallet-core/src/operations/tip.ts
index d82331632..1da2c887a 100644
--- a/packages/taler-wallet-core/src/operations/tip.ts
+++ b/packages/taler-wallet-core/src/operations/tip.ts
@@ -40,9 +40,9 @@ import {
import { j2s } from "@gnu-taler/taler-util";
import { checkDbInvariant, checkLogicInvariant } from "../util/invariants.js";
import { initRetryInfo, updateRetryInfoTimeout } from "../util/retries.js";
-import { guardOperationException, makeErrorDetails } from "./errors.js";
+import { guardOperationException, makeErrorDetails } from "../errors.js";
import { updateExchangeFromUrl } from "./exchanges.js";
-import { InternalWalletState } from "./state.js";
+import { InternalWalletState } from "../common.js";
import {
getExchangeWithdrawalInfo,
updateWithdrawalDenoms,
diff --git a/packages/taler-wallet-core/src/operations/transactions.ts b/packages/taler-wallet-core/src/operations/transactions.ts
index 5836a6ee3..82cfec551 100644
--- a/packages/taler-wallet-core/src/operations/transactions.ts
+++ b/packages/taler-wallet-core/src/operations/transactions.ts
@@ -17,7 +17,7 @@
/**
* Imports.
*/
-import { InternalWalletState } from "./state.js";
+import { InternalWalletState } from "../common.js";
import {
WalletRefundItem,
RefundState,
diff --git a/packages/taler-wallet-core/src/operations/versions.ts b/packages/taler-wallet-core/src/operations/versions.ts
deleted file mode 100644
index b798871c2..000000000
--- a/packages/taler-wallet-core/src/operations/versions.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2019 Taler Systems S.A.
-
- GNU Taler is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
- */
-
-/**
- * Protocol version spoken with the exchange.
- *
- * Uses libtool's current:revision:age versioning.
- */
-export const WALLET_EXCHANGE_PROTOCOL_VERSION = "9:0:0";
-
-/**
- * Protocol version spoken with the merchant.
- *
- * Uses libtool's current:revision:age versioning.
- */
-export const WALLET_MERCHANT_PROTOCOL_VERSION = "1:0:0";
-
-/**
- * Protocol version spoken with the merchant.
- *
- * Uses libtool's current:revision:age versioning.
- */
-export const WALLET_BANK_INTEGRATION_PROTOCOL_VERSION = "0:0:0";
-
-/**
- * Cache breaker that is appended to queries such as /keys and /wire
- * to break through caching, if it has been accidentally/badly configured
- * by the exchange.
- *
- * This is only a temporary measure.
- */
-export const WALLET_CACHE_BREAKER_CLIENT_VERSION = "3";
diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts
index 3400238ed..6cf20259c 100644
--- a/packages/taler-wallet-core/src/operations/withdraw.ts
+++ b/packages/taler-wallet-core/src/operations/withdraw.ts
@@ -17,65 +17,56 @@
/**
* Imports.
*/
+import * as LibtoolVersion from "@gnu-taler/taler-util";
import {
AmountJson,
Amounts,
+ BankWithdrawDetails,
+ codecForTalerConfigResponse,
+ codecForWithdrawOperationStatusResponse,
+ codecForWithdrawResponse,
+ compare,
durationFromSpec,
+ ExchangeListItem,
+ getDurationRemaining,
+ getTimestampNow,
+ Logger,
+ NotificationType,
parseWithdrawUri,
+ TalerErrorCode,
+ TalerErrorDetails,
Timestamp,
+ timestampCmp,
+ timestampSubtractDuraction,
+ WithdrawResponse,
+ WithdrawUriInfoResponse,
} from "@gnu-taler/taler-util";
import {
- DenominationRecord,
- DenominationStatus,
- CoinStatus,
CoinRecord,
CoinSourceType,
+ CoinStatus,
+ DenominationRecord,
DenominationSelectionInfo,
- PlanchetRecord,
+ DenominationStatus,
DenomSelectionState,
- ExchangeRecord,
ExchangeDetailsRecord,
+ ExchangeRecord,
+ PlanchetRecord,
} from "../db.js";
-import {
- BankWithdrawDetails,
- TalerErrorDetails,
- ExchangeListItem,
- WithdrawUriInfoResponse,
-} from "@gnu-taler/taler-util";
-import {
- codecForWithdrawOperationStatusResponse,
- codecForWithdrawResponse,
- WithdrawResponse,
- codecForTalerConfigResponse,
-} from "@gnu-taler/taler-util";
-import { InternalWalletState } from "./state.js";
-import { Logger } from "@gnu-taler/taler-util";
-import { getExchangeDetails, updateExchangeFromUrl } from "./exchanges.js";
-import {
- WALLET_EXCHANGE_PROTOCOL_VERSION,
- WALLET_BANK_INTEGRATION_PROTOCOL_VERSION,
-} from "./versions.js";
-
-import * as LibtoolVersion from "@gnu-taler/taler-util";
+import { walletCoreDebugFlags } from "../util/debugFlags.js";
+import { readSuccessResponseJsonOrThrow } from "../util/http.js";
+import { initRetryInfo, updateRetryInfoTimeout } from "../util/retries.js";
+import { URL } from "../util/url.js";
import {
guardOperationException,
makeErrorDetails,
OperationFailedError,
-} from "./errors.js";
-import { NotificationType } from "@gnu-taler/taler-util";
+} from "../errors.js";
+import { InternalWalletState } from "../common.js";
import {
- getTimestampNow,
- getDurationRemaining,
- timestampCmp,
- timestampSubtractDuraction,
-} from "@gnu-taler/taler-util";
-import { readSuccessResponseJsonOrThrow } from "../util/http.js";
-import { URL } from "../util/url.js";
-import { TalerErrorCode } from "@gnu-taler/taler-util";
-import { updateRetryInfoTimeout, initRetryInfo } from "../util/retries.js";
-import { compare } from "@gnu-taler/taler-util";
-import { walletCoreDebugFlags } from "../util/debugFlags.js";
-import { getExchangeTrust } from "./currencies.js";
+ WALLET_BANK_INTEGRATION_PROTOCOL_VERSION,
+ WALLET_EXCHANGE_PROTOCOL_VERSION,
+} from "../versions.js";
/**
* Logger for this file.
@@ -690,7 +681,7 @@ export async function updateWithdrawalDenoms(
exchangeDetails: x.exchangeDetails,
}))
.runReadOnly(async (tx) => {
- return getExchangeDetails(tx, exchangeBaseUrl);
+ return ws.exchangeOps.getExchangeDetails(tx, exchangeBaseUrl);
});
if (!exchangeDetails) {
logger.error("exchange details not available");
@@ -816,7 +807,10 @@ async function processWithdrawGroupImpl(
return;
}
- await updateExchangeFromUrl(ws, withdrawalGroup.exchangeBaseUrl);
+ await ws.exchangeOps.updateExchangeFromUrl(
+ ws,
+ withdrawalGroup.exchangeBaseUrl,
+ );
const numTotalCoins = withdrawalGroup.denomsSel.selectedDenoms
.map((x) => x.count)
@@ -910,10 +904,10 @@ export async function getExchangeWithdrawalInfo(
baseUrl: string,
amount: AmountJson,
): Promise<ExchangeWithdrawDetails> {
- const { exchange, exchangeDetails } = await updateExchangeFromUrl(
- ws,
- baseUrl,
- );
+ const {
+ exchange,
+ exchangeDetails,
+ } = await ws.exchangeOps.updateExchangeFromUrl(ws, baseUrl);
await updateWithdrawalDenoms(ws, baseUrl);
const denoms = await getCandidateWithdrawalDenoms(ws, baseUrl);
const selectedDenoms = selectWithdrawalDenominations(amount, denoms);
@@ -922,7 +916,10 @@ export async function getExchangeWithdrawalInfo(
exchangeWireAccounts.push(account.payto_uri);
}
- const { isTrusted, isAudited } = await getExchangeTrust(ws, exchange);
+ const { isTrusted, isAudited } = await ws.exchangeOps.getExchangeTrust(
+ ws,
+ exchange,
+ );
let earliestDepositExpiration =
selectedDenoms.selectedDenoms[0].denom.stampExpireDeposit;
@@ -1009,7 +1006,7 @@ export async function getWithdrawalDetailsForUri(
// FIXME: right now the exchange gets permanently added,
// we might want to only temporarily add it.
try {
- await updateExchangeFromUrl(ws, info.suggestedExchange);
+ await ws.exchangeOps.updateExchangeFromUrl(ws, info.suggestedExchange);
} catch (e) {
// We still continued if it failed, as other exchanges might be available.
// We don't want to fail if the bank-suggested exchange is broken/offline.
@@ -1029,7 +1026,7 @@ export async function getWithdrawalDetailsForUri(
.runReadOnly(async (tx) => {
const exchangeRecords = await tx.exchanges.iter().toArray();
for (const r of exchangeRecords) {
- const details = await getExchangeDetails(tx, r.baseUrl);
+ const details = await ws.exchangeOps.getExchangeDetails(tx, r.baseUrl);
if (details) {
exchanges.push({
exchangeBaseUrl: details.exchangeBaseUrl,