summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/wallet.ts
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2024-02-29 18:37:13 +0100
committerFlorian Dold <florian@dold.me>2024-02-29 23:24:06 +0100
commit277a5c641df336d8b5b2d9bd6559e45f0b02aa79 (patch)
tree49cbdadaf04b5630cdae3e2a89e6d3a74d30632b /packages/taler-wallet-core/src/wallet.ts
parent206780bb0ee763bcf50a3f4f9f78579a8adcdb3a (diff)
downloadwallet-core-277a5c641df336d8b5b2d9bd6559e45f0b02aa79.tar.gz
wallet-core-277a5c641df336d8b5b2d9bd6559e45f0b02aa79.tar.bz2
wallet-core-277a5c641df336d8b5b2d9bd6559e45f0b02aa79.zip
wallet-core: improve config handling, test builtin exchange config
Diffstat (limited to 'packages/taler-wallet-core/src/wallet.ts')
-rw-r--r--packages/taler-wallet-core/src/wallet.ts133
1 files changed, 87 insertions, 46 deletions
diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts
index 0dc066730..b397c43d5 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -47,6 +47,7 @@ import {
ObservabilityContext,
ObservabilityEventType,
OpenedPromise,
+ PartialWalletRunConfig,
PrepareWithdrawExchangeRequest,
PrepareWithdrawExchangeResponse,
RecoverStoredBackupRequest,
@@ -64,6 +65,7 @@ import {
ValidateIbanResponse,
WalletCoreVersion,
WalletNotification,
+ WalletRunConfig,
WithdrawalDetailsForAmount,
checkDbInvariant,
codecForAbortTransaction,
@@ -99,6 +101,7 @@ import {
codecForGetWithdrawalDetailsForAmountRequest,
codecForGetWithdrawalDetailsForUri,
codecForImportDbRequest,
+ codecForInitRequest,
codecForInitiatePeerPullPaymentRequest,
codecForInitiatePeerPushDebitRequest,
codecForIntegrationTestArgs,
@@ -277,8 +280,6 @@ import {
} from "./versions.js";
import {
WalletApiOperation,
- WalletConfig,
- WalletConfigParameter,
WalletCoreApiClient,
WalletCoreResponseType,
} from "./wallet-api-types.js";
@@ -685,6 +686,17 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
return {};
}
case WalletApiOperation.InitWallet: {
+ const req = codecForInitRequest().decode(payload);
+
+ logger.info(`init request: ${req}`);
+
+ if (wex.ws.initCalled) {
+ logger.warn(
+ "initWallet called twice, new run configuration is ignored",
+ );
+ return;
+ }
+
logger.trace("initializing wallet");
// Write to the DB to make sure that we're failing early in
// case the DB is not writeable.
@@ -701,6 +713,9 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
innerError: getErrorDetailFromException(e),
});
}
+
+ wex.ws.initWithConfig(applyRunConfigDefaults(req.config));
+
wex.ws.initCalled = true;
if (wex.ws.config.testing.skipDefaults) {
logger.trace("skipping defaults");
@@ -1437,7 +1452,12 @@ export function getNormalWalletExecutionContext(
cancellationToken,
cryptoApi: ws.cryptoApi,
db: ws.db,
- http: ws.http,
+ get http() {
+ if (ws.initCalled) {
+ return ws.http;
+ }
+ throw Error("wallet not initialized");
+ },
taskScheduler: ws.taskScheduler,
oc,
};
@@ -1456,7 +1476,7 @@ async function handleCoreApiRequest(
let wex: WalletExecutionContext;
let oc: ObservabilityContext;
- if (ws.config.testing.emitObservabilityEvents) {
+ if (ws.initCalled && ws.config.testing.emitObservabilityEvents) {
oc = {
observe(evt) {
ws.notify({
@@ -1512,6 +1532,34 @@ async function handleCoreApiRequest(
}
}
+export function applyRunConfigDefaults(
+ wcp?: PartialWalletRunConfig,
+): WalletRunConfig {
+ return {
+ builtin: {
+ exchanges: wcp?.builtin?.exchanges ?? [
+ {
+ exchangeBaseUrl: "https://exchange.demo.taler.net/",
+ currencyHint: "KUDOS",
+ },
+ ],
+ },
+ features: {
+ allowHttp: wcp?.features?.allowHttp ?? false,
+ },
+ testing: {
+ denomselAllowLate: wcp?.testing?.denomselAllowLate ?? false,
+ devModeActive: wcp?.testing?.devModeActive ?? false,
+ insecureTrustExchange: wcp?.testing?.insecureTrustExchange ?? false,
+ preventThrottling: wcp?.testing?.preventThrottling ?? false,
+ skipDefaults: wcp?.testing?.skipDefaults ?? false,
+ emitObservabilityEvents: wcp?.testing?.emitObservabilityEvents ?? false,
+ },
+ };
+}
+
+export type HttpFactory = (config: WalletRunConfig) => HttpRequestLibrary;
+
/**
* Public handle to a running wallet.
*/
@@ -1521,17 +1569,15 @@ export class Wallet {
private constructor(
idb: IDBFactory,
- http: HttpRequestLibrary,
+ httpFactory: HttpFactory,
timer: TimerAPI,
cryptoWorkerFactory: CryptoWorkerFactory,
- config?: WalletConfigParameter,
) {
this.ws = new InternalWalletState(
idb,
- http,
+ httpFactory,
timer,
cryptoWorkerFactory,
- Wallet.getEffectiveConfig(config),
);
}
@@ -1544,44 +1590,15 @@ export class Wallet {
static async create(
idb: IDBFactory,
- http: HttpRequestLibrary,
+ httpFactory: HttpFactory,
timer: TimerAPI,
cryptoWorkerFactory: CryptoWorkerFactory,
- config?: WalletConfigParameter,
): Promise<Wallet> {
- const w = new Wallet(idb, http, timer, cryptoWorkerFactory, config);
+ const w = new Wallet(idb, httpFactory, timer, cryptoWorkerFactory);
w._client = await getClientFromWalletState(w.ws);
return w;
}
- public static defaultConfig: Readonly<WalletConfig> = {
- builtin: {
- exchanges: [
- {
- exchangeBaseUrl: "https://exchange.demo.taler.net/",
- currencyHint: "KUDOS",
- },
- ],
- },
- features: {
- allowHttp: false,
- },
- testing: {
- preventThrottling: false,
- devModeActive: false,
- insecureTrustExchange: false,
- denomselAllowLate: false,
- skipDefaults: false,
- emitObservabilityEvents: false,
- },
- };
-
- static getEffectiveConfig(
- param?: WalletConfigParameter,
- ): Readonly<WalletConfig> {
- return deepMerge(Wallet.defaultConfig, param ?? {});
- }
-
addNotificationListener(f: (n: WalletNotification) => void): CancelFn {
return this.ws.addNotificationListener(f);
}
@@ -1637,10 +1654,12 @@ export class InternalWalletState {
taskScheduler: TaskScheduler = new TaskSchedulerImpl(this);
- config: Readonly<WalletConfig>;
+ private _config: Readonly<WalletRunConfig> | undefined;
private _db: DbAccess<typeof WalletStoresV1> | undefined = undefined;
+ private _http: HttpRequestLibrary | undefined = undefined;
+
get db(): DbAccess<typeof WalletStoresV1> {
if (!this._db) {
throw Error("db not initialized");
@@ -1648,20 +1667,42 @@ export class InternalWalletState {
return this._db;
}
+ initWithConfig(newConfig: WalletRunConfig): void {
+ if (this._config) {
+ throw Error("config already set");
+ }
+ this._config = newConfig;
+
+ this._http = this.httpFactory(newConfig);
+
+ if (this.config.testing.devModeActive) {
+ this._http = new DevExperimentHttpLib(this.http);
+ }
+ }
+
+ get config(): WalletRunConfig {
+ if (!this._config) {
+ throw Error("config not initialized");
+ }
+ return this._config;
+ }
+
+ get http(): HttpRequestLibrary {
+ if (!this._http) {
+ throw Error("wallet not initialized");
+ }
+ return this._http;
+ }
+
constructor(
public idb: IDBFactory,
- public http: HttpRequestLibrary,
+ private httpFactory: HttpFactory,
public timer: TimerAPI,
cryptoWorkerFactory: CryptoWorkerFactory,
- configParam: WalletConfig,
) {
this.cryptoDispatcher = new CryptoDispatcher(cryptoWorkerFactory);
this.cryptoApi = this.cryptoDispatcher.cryptoApi;
this.timerGroup = new TimerGroup(timer);
- this.config = configParam;
- if (this.config.testing.devModeActive) {
- this.http = new DevExperimentHttpLib(this.http);
- }
}
async ensureWalletDbOpen(): Promise<void> {