aboutsummaryrefslogtreecommitdiff
path: root/packages
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
parent206780bb0ee763bcf50a3f4f9f78579a8adcdb3a (diff)
wallet-core: improve config handling, test builtin exchange config
Diffstat (limited to 'packages')
-rw-r--r--packages/taler-harness/src/bench1.ts12
-rw-r--r--packages/taler-harness/src/bench2.ts9
-rw-r--r--packages/taler-harness/src/bench3.ts11
-rw-r--r--packages/taler-harness/src/harness/harness.ts1
-rw-r--r--packages/taler-harness/src/harness/helpers.ts9
-rw-r--r--packages/taler-harness/src/integrationtests/test-exchange-deposit.ts9
-rw-r--r--packages/taler-harness/src/integrationtests/test-exchange-purse.ts13
-rw-r--r--packages/taler-harness/src/integrationtests/test-kyc.ts15
-rw-r--r--packages/taler-harness/src/integrationtests/test-wallet-config.ts65
-rw-r--r--packages/taler-harness/src/integrationtests/test-wallet-dbless.ts10
-rw-r--r--packages/taler-harness/src/integrationtests/test-wallet-dd48.ts24
-rw-r--r--packages/taler-harness/src/integrationtests/test-wallet-notifications.ts6
-rw-r--r--packages/taler-harness/src/integrationtests/testrunner.ts2
-rw-r--r--packages/taler-util/src/wallet-types.ts52
-rw-r--r--packages/taler-wallet-cli/src/index.ts36
-rw-r--r--packages/taler-wallet-core/src/host-common.ts6
-rw-r--r--packages/taler-wallet-core/src/host-impl.node.ts30
-rw-r--r--packages/taler-wallet-core/src/host-impl.qtart.ts30
-rw-r--r--packages/taler-wallet-core/src/wallet-api-types.ts61
-rw-r--r--packages/taler-wallet-core/src/wallet.ts133
-rw-r--r--packages/taler-wallet-embedded/src/wallet-qjs.ts18
-rw-r--r--packages/taler-wallet-webextension/src/platform/api.ts6
-rw-r--r--packages/taler-wallet-webextension/src/wxBackend.ts30
23 files changed, 366 insertions, 222 deletions
diff --git a/packages/taler-harness/src/bench1.ts b/packages/taler-harness/src/bench1.ts
index b78fadf0b..428114e0e 100644
--- a/packages/taler-harness/src/bench1.ts
+++ b/packages/taler-harness/src/bench1.ts
@@ -29,6 +29,7 @@ import {
} from "@gnu-taler/taler-util";
import {
AccessStats,
+ applyRunConfigDefaults,
createNativeWalletHost2,
Wallet,
WalletApiOperation,
@@ -82,6 +83,10 @@ export async function runBench1(configJson: any): Promise<void> {
// No persistent DB storage.
persistentStoragePath: undefined,
httpLib: harnessHttpLib,
+ });
+ wallet = res.wallet;
+ getDbStats = res.getDbStats;
+ await wallet.client.call(WalletApiOperation.InitWallet, {
config: {
testing: {
insecureTrustExchange: trustExchange,
@@ -89,16 +94,13 @@ export async function runBench1(configJson: any): Promise<void> {
features: {},
},
});
- wallet = res.wallet;
- getDbStats = res.getDbStats;
- await wallet.client.call(WalletApiOperation.InitWallet, {});
}
logger.trace(`Starting withdrawal amount=${withdrawAmount}`);
let start = Date.now();
await wallet.client.call(WalletApiOperation.WithdrawTestBalance, {
- amount: b1conf.currency + ":" + withdrawAmount as AmountString,
+ amount: (b1conf.currency + ":" + withdrawAmount) as AmountString,
corebankApiBaseUrl: b1conf.bank,
exchangeBaseUrl: b1conf.exchange,
});
@@ -117,7 +119,7 @@ export async function runBench1(configJson: any): Promise<void> {
start = Date.now();
await wallet.client.call(WalletApiOperation.CreateDepositGroup, {
- amount: b1conf.currency + ":10" as AmountString,
+ amount: (b1conf.currency + ":10") as AmountString,
depositPaytoUri: b1conf.payto,
});
diff --git a/packages/taler-harness/src/bench2.ts b/packages/taler-harness/src/bench2.ts
index c85bd6a5d..90924caec 100644
--- a/packages/taler-harness/src/bench2.ts
+++ b/packages/taler-harness/src/bench2.ts
@@ -27,6 +27,7 @@ import {
} from "@gnu-taler/taler-util";
import { createPlatformHttpLib } from "@gnu-taler/taler-util/http";
import {
+ applyRunConfigDefaults,
CryptoDispatcher,
SynchronousCryptoWorkerFactoryPlain,
Wallet,
@@ -67,6 +68,8 @@ export async function runBench2(configJson: any): Promise<void> {
const reserveAmount = (numDeposits + 1) * 10;
+ const defaultConfig = applyRunConfigDefaults();
+
for (let i = 0; i < numIter; i++) {
const exchangeInfo = await downloadExchangeInfo(benchConf.exchange, http);
@@ -89,7 +92,7 @@ export async function runBench2(configJson: any): Promise<void> {
console.log("reserve found");
const d1 = findDenomOrThrow(exchangeInfo, `${curr}:8` as AmountString, {
- denomselAllowLate: Wallet.defaultConfig.testing.denomselAllowLate,
+ denomselAllowLate: defaultConfig.testing.denomselAllowLate,
});
for (let j = 0; j < numDeposits; j++) {
@@ -118,10 +121,10 @@ export async function runBench2(configJson: any): Promise<void> {
const refreshDenoms = [
findDenomOrThrow(exchangeInfo, `${curr}:1` as AmountString, {
- denomselAllowLate: Wallet.defaultConfig.testing.denomselAllowLate,
+ denomselAllowLate: defaultConfig.testing.denomselAllowLate,
}),
findDenomOrThrow(exchangeInfo, `${curr}:1` as AmountString, {
- denomselAllowLate: Wallet.defaultConfig.testing.denomselAllowLate,
+ denomselAllowLate: defaultConfig.testing.denomselAllowLate,
}),
];
diff --git a/packages/taler-harness/src/bench3.ts b/packages/taler-harness/src/bench3.ts
index c810f6804..f138dff68 100644
--- a/packages/taler-harness/src/bench3.ts
+++ b/packages/taler-harness/src/bench3.ts
@@ -93,6 +93,10 @@ export async function runBench3(configJson: any): Promise<void> {
// No persistent DB storage.
persistentStoragePath: undefined,
httpLib: myHttpLib,
+ });
+ wallet = res.wallet;
+ getDbStats = res.getDbStats;
+ await wallet.client.call(WalletApiOperation.InitWallet, {
config: {
features: {},
testing: {
@@ -100,16 +104,13 @@ export async function runBench3(configJson: any): Promise<void> {
},
},
});
- wallet = res.wallet;
- getDbStats = res.getDbStats;
- await wallet.client.call(WalletApiOperation.InitWallet, {});
}
logger.trace(`Starting withdrawal amount=${withdrawAmount}`);
let start = Date.now();
await wallet.client.call(WalletApiOperation.WithdrawTestBalance, {
- amount: b3conf.currency + ":" + withdrawAmount as AmountString,
+ amount: (b3conf.currency + ":" + withdrawAmount) as AmountString,
corebankApiBaseUrl: b3conf.bank,
exchangeBaseUrl: b3conf.exchange,
});
@@ -130,7 +131,7 @@ export async function runBench3(configJson: any): Promise<void> {
let payto = b3conf.paytoTemplate.replace("${id}", merchID.toString());
await wallet.client.call(WalletApiOperation.CreateDepositGroup, {
- amount: b3conf.currency + ":10" as AmountString,
+ amount: (b3conf.currency + ":10") as AmountString,
depositPaytoUri: payto,
});
diff --git a/packages/taler-harness/src/harness/harness.ts b/packages/taler-harness/src/harness/harness.ts
index 9418a3256..587860547 100644
--- a/packages/taler-harness/src/harness/harness.ts
+++ b/packages/taler-harness/src/harness/harness.ts
@@ -1961,6 +1961,7 @@ export class WalletService {
"serve",
"--unix-path",
unixPath,
+ "--no-init",
],
`wallet-${this.opts.name}`,
);
diff --git a/packages/taler-harness/src/harness/helpers.ts b/packages/taler-harness/src/harness/helpers.ts
index f567a87ff..46dc9f9d4 100644
--- a/packages/taler-harness/src/harness/helpers.ts
+++ b/packages/taler-harness/src/harness/helpers.ts
@@ -31,6 +31,7 @@ import {
MerchantApiClient,
MerchantContractTerms,
NotificationType,
+ PartialWalletRunConfig,
PreparePayResultType,
TalerCorebankApiClient,
TransactionMajorState,
@@ -406,6 +407,7 @@ export interface CreateWalletArgs {
name: string;
persistent?: boolean;
overrideDbPath?: string;
+ config?: PartialWalletRunConfig;
}
export async function createWalletDaemonWithClient(
@@ -431,8 +433,13 @@ export async function createWalletDaemonWithClient(
},
});
await walletClient.connect();
+ const defaultRunConfig = {
+ testing: {
+ skipDefaults: true,
+ },
+ };
await walletClient.client.call(WalletApiOperation.InitWallet, {
- skipDefaults: true,
+ config: args.config ?? defaultRunConfig,
});
return { walletClient, walletService };
diff --git a/packages/taler-harness/src/integrationtests/test-exchange-deposit.ts b/packages/taler-harness/src/integrationtests/test-exchange-deposit.ts
index ca8b9e375..05e6e153b 100644
--- a/packages/taler-harness/src/integrationtests/test-exchange-deposit.ts
+++ b/packages/taler-harness/src/integrationtests/test-exchange-deposit.ts
@@ -28,7 +28,6 @@ import { createPlatformHttpLib } from "@gnu-taler/taler-util/http";
import {
CryptoDispatcher,
SynchronousCryptoWorkerFactoryPlain,
- Wallet,
} from "@gnu-taler/taler-wallet-core";
import {
checkReserve,
@@ -76,9 +75,11 @@ export async function runExchangeDepositTest(t: GlobalTestState) {
await checkReserve(http, exchange.baseUrl, reserveKeyPair.pub);
- const d1 = findDenomOrThrow(exchangeInfo, "TESTKUDOS:8" as AmountString, {
- denomselAllowLate: Wallet.defaultConfig.testing.denomselAllowLate,
- });
+ const d1 = findDenomOrThrow(
+ exchangeInfo,
+ "TESTKUDOS:8" as AmountString,
+ {},
+ );
const coin = await withdrawCoin({
http,
diff --git a/packages/taler-harness/src/integrationtests/test-exchange-purse.ts b/packages/taler-harness/src/integrationtests/test-exchange-purse.ts
index 8ff740732..83ee13d4e 100644
--- a/packages/taler-harness/src/integrationtests/test-exchange-purse.ts
+++ b/packages/taler-harness/src/integrationtests/test-exchange-purse.ts
@@ -29,14 +29,12 @@ import {
j2s,
PeerContractTerms,
TalerError,
- TalerPreciseTimestamp,
} from "@gnu-taler/taler-util";
import {
CryptoDispatcher,
EncryptContractRequest,
SpendCoinDetails,
SynchronousCryptoWorkerFactoryPlain,
- Wallet,
} from "@gnu-taler/taler-wallet-core";
import {
checkReserve,
@@ -94,9 +92,11 @@ export async function runExchangePurseTest(t: GlobalTestState) {
await checkReserve(http, exchange.baseUrl, reserveKeyPair.pub);
- const d1 = findDenomOrThrow(exchangeInfo, "TESTKUDOS:8" as AmountString, {
- denomselAllowLate: Wallet.defaultConfig.testing.denomselAllowLate,
- });
+ const d1 = findDenomOrThrow(
+ exchangeInfo,
+ "TESTKUDOS:8" as AmountString,
+ {},
+ );
const coin = await withdrawCoin({
http,
@@ -110,9 +110,6 @@ export async function runExchangePurseTest(t: GlobalTestState) {
});
const amount = "TESTKUDOS:5" as AmountString;
- const purseFee = "TESTKUDOS:0";
-
- const mergeTimestamp = TalerPreciseTimestamp.now();
const contractTerms: PeerContractTerms = {
amount,
diff --git a/packages/taler-harness/src/integrationtests/test-kyc.ts b/packages/taler-harness/src/integrationtests/test-kyc.ts
index cc756f617..a9ef654fd 100644
--- a/packages/taler-harness/src/integrationtests/test-kyc.ts
+++ b/packages/taler-harness/src/integrationtests/test-kyc.ts
@@ -18,15 +18,14 @@
* Imports.
*/
import {
- TalerCorebankApiClient,
Duration,
- j2s,
Logger,
NotificationType,
+ TalerCorebankApiClient,
TransactionMajorState,
TransactionMinorState,
TransactionType,
- encodeCrock,
+ j2s,
} from "@gnu-taler/taler-util";
import { createPlatformHttpLib } from "@gnu-taler/taler-util/http";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
@@ -35,12 +34,12 @@ import { CoinConfig, defaultCoinConfig } from "../harness/denomStructures.js";
import {
BankService,
ExchangeService,
- generateRandomPayto,
GlobalTestState,
MerchantService,
- setupDb,
WalletClient,
WalletService,
+ generateRandomPayto,
+ setupDb,
} from "../harness/harness.js";
import { EnvOptions, SimpleTestEnvironmentNg } from "../harness/helpers.js";
@@ -199,7 +198,11 @@ export async function createKycTestkudosEnvironment(
});
await walletClient.connect();
await walletClient.client.call(WalletApiOperation.InitWallet, {
- skipDefaults: true,
+ config: {
+ testing: {
+ skipDefaults: true,
+ },
+ },
});
console.log("setup done!");
diff --git a/packages/taler-harness/src/integrationtests/test-wallet-config.ts b/packages/taler-harness/src/integrationtests/test-wallet-config.ts
new file mode 100644
index 000000000..81a723473
--- /dev/null
+++ b/packages/taler-harness/src/integrationtests/test-wallet-config.ts
@@ -0,0 +1,65 @@
+/*
+ This file is part of GNU Taler
+ (C) 2020 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 { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { GlobalTestState } from "../harness/harness.js";
+import { createWalletDaemonWithClient } from "../harness/helpers.js";
+
+export async function runWalletConfigTest(t: GlobalTestState) {
+ const w1 = await createWalletDaemonWithClient(t, {
+ name: "w1",
+ config: {
+ builtin: {
+ exchanges: [],
+ },
+ },
+ });
+
+ const exchangesResp1 = await w1.walletClient.call(
+ WalletApiOperation.ListExchanges,
+ {},
+ );
+
+ t.assertDeepEqual(exchangesResp1.exchanges.length, 0);
+
+ const w2 = await createWalletDaemonWithClient(t, {
+ name: "w2",
+ config: {
+ builtin: {
+ exchanges: [
+ {
+ exchangeBaseUrl: "https://exchange.demo.taler.net/",
+ },
+ {
+ exchangeBaseUrl: "https://exchange.test.taler.net/",
+ },
+ ],
+ },
+ },
+ });
+
+ const exchangesResp2 = await w2.walletClient.call(
+ WalletApiOperation.ListExchanges,
+ {},
+ );
+
+ t.assertDeepEqual(exchangesResp2.exchanges.length, 2);
+}
+
+runWalletConfigTest.suites = ["wallet"];
diff --git a/packages/taler-harness/src/integrationtests/test-wallet-dbless.ts b/packages/taler-harness/src/integrationtests/test-wallet-dbless.ts
index 1c4c16e0f..fadb34732 100644
--- a/packages/taler-harness/src/integrationtests/test-wallet-dbless.ts
+++ b/packages/taler-harness/src/integrationtests/test-wallet-dbless.ts
@@ -25,9 +25,9 @@ import {
TalerError,
} from "@gnu-taler/taler-util";
import {
+ applyRunConfigDefaults,
CryptoDispatcher,
SynchronousCryptoWorkerFactoryPlain,
- Wallet,
} from "@gnu-taler/taler-wallet-core";
import {
checkReserve,
@@ -87,8 +87,10 @@ export async function runWalletDblessTest(t: GlobalTestState) {
await checkReserve(http, exchange.baseUrl, reserveKeyPair.pub);
+ const defaultConfig = applyRunConfigDefaults();
+
const d1 = findDenomOrThrow(exchangeInfo, "TESTKUDOS:8" as AmountString, {
- denomselAllowLate: Wallet.defaultConfig.testing.denomselAllowLate,
+ denomselAllowLate: defaultConfig.testing.denomselAllowLate,
});
const coin = await withdrawCoin({
@@ -131,10 +133,10 @@ export async function runWalletDblessTest(t: GlobalTestState) {
const refreshDenoms = [
findDenomOrThrow(exchangeInfo, "TESTKUDOS:1" as AmountString, {
- denomselAllowLate: Wallet.defaultConfig.testing.denomselAllowLate,
+ denomselAllowLate: defaultConfig.testing.denomselAllowLate,
}),
findDenomOrThrow(exchangeInfo, "TESTKUDOS:1" as AmountString, {
- denomselAllowLate: Wallet.defaultConfig.testing.denomselAllowLate,
+ denomselAllowLate: defaultConfig.testing.denomselAllowLate,
}),
];
diff --git a/packages/taler-harness/src/integrationtests/test-wallet-dd48.ts b/packages/taler-harness/src/integrationtests/test-wallet-dd48.ts
index 47c96e0e2..3341b6a53 100644
--- a/packages/taler-harness/src/integrationtests/test-wallet-dd48.ts
+++ b/packages/taler-harness/src/integrationtests/test-wallet-dd48.ts
@@ -17,6 +17,14 @@
/**
* Imports.
*/
+import {
+ ExchangeEntryStatus,
+ NotificationType,
+ TalerError,
+ TalerErrorCode,
+ WalletNotification,
+ j2s,
+} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { CoinConfig, defaultCoinConfig } from "../harness/denomStructures.js";
import {
@@ -27,14 +35,6 @@ import {
WalletService,
setupDb,
} from "../harness/harness.js";
-import {
- ExchangeEntryStatus,
- NotificationType,
- TalerError,
- TalerErrorCode,
- WalletNotification,
- j2s,
-} from "@gnu-taler/taler-util";
import { withdrawViaBankV2 } from "../harness/helpers.js";
/**
@@ -96,7 +96,11 @@ export async function runWalletDd48Test(t: GlobalTestState) {
});
await walletClient.connect();
await walletClient.client.call(WalletApiOperation.InitWallet, {
- skipDefaults: true,
+ config: {
+ testing: {
+ skipDefaults: true,
+ },
+ },
});
await walletClient.call(WalletApiOperation.AddExchange, {
@@ -152,7 +156,7 @@ export async function runWalletDd48Test(t: GlobalTestState) {
x.type === NotificationType.ExchangeStateTransition &&
x.oldExchangeState == null &&
x.newExchangeState.exchangeEntryStatus ===
- ExchangeEntryStatus.Ephemeral,
+ ExchangeEntryStatus.Ephemeral,
),
);
diff --git a/packages/taler-harness/src/integrationtests/test-wallet-notifications.ts b/packages/taler-harness/src/integrationtests/test-wallet-notifications.ts
index c0c32a008..28b73a9f9 100644
--- a/packages/taler-harness/src/integrationtests/test-wallet-notifications.ts
+++ b/packages/taler-harness/src/integrationtests/test-wallet-notifications.ts
@@ -119,7 +119,11 @@ export async function runWalletNotificationsTest(t: GlobalTestState) {
});
await walletClient.connect();
await walletClient.client.call(WalletApiOperation.InitWallet, {
- skipDefaults: true,
+ config: {
+ testing: {
+ skipDefaults: true,
+ }
+ }
});
const bankAccessApiClient = new TalerCorebankApiClient(
diff --git a/packages/taler-harness/src/integrationtests/testrunner.ts b/packages/taler-harness/src/integrationtests/testrunner.ts
index b57d82939..73619a047 100644
--- a/packages/taler-harness/src/integrationtests/testrunner.ts
+++ b/packages/taler-harness/src/integrationtests/testrunner.ts
@@ -89,6 +89,7 @@ import { runWalletBackupDoublespendTest } from "./test-wallet-backup-doublespend
import { runWalletBalanceNotificationsTest } from "./test-wallet-balance-notifications.js";
import { runWalletBalanceTest } from "./test-wallet-balance.js";
import { runWalletCliTerminationTest } from "./test-wallet-cli-termination.js";
+import { runWalletConfigTest } from "./test-wallet-config.js";
import { runWalletCryptoWorkerTest } from "./test-wallet-cryptoworker.js";
import { runWalletDblessTest } from "./test-wallet-dbless.js";
import { runWalletDd48Test } from "./test-wallet-dd48.js";
@@ -196,6 +197,7 @@ const allTests: TestMainFunction[] = [
runOtpTest,
runWalletBalanceNotificationsTest,
runExchangeManagementTest,
+ runWalletConfigTest,
];
export interface TestRunSpec {
diff --git a/packages/taler-util/src/wallet-types.ts b/packages/taler-util/src/wallet-types.ts
index 19bebfb19..4fb9b77e7 100644
--- a/packages/taler-util/src/wallet-types.ts
+++ b/packages/taler-util/src/wallet-types.ts
@@ -462,10 +462,60 @@ export interface GetCurrencySpecificationResponse {
currencySpecification: CurrencySpecification;
}
+export interface BuiltinExchange {
+ exchangeBaseUrl: string;
+ currencyHint?: string;
+}
+
+export interface PartialWalletRunConfig {
+ builtin?: Partial<WalletRunConfig["builtin"]>;
+ testing?: Partial<WalletRunConfig["testing"]>;
+ features?: Partial<WalletRunConfig["features"]>;
+}
+
+export interface WalletRunConfig {
+ /**
+ * Initialization values useful for a complete startup.
+ *
+ * These are values may be overridden by different wallets
+ */
+ builtin: {
+ exchanges: BuiltinExchange[];
+ };
+
+ /**
+ * Unsafe options which it should only be used to create
+ * testing environment.
+ */
+ testing: {
+ /**
+ * Allow withdrawal of denominations even though they are about to expire.
+ */
+ denomselAllowLate: boolean;
+ devModeActive: boolean;
+ insecureTrustExchange: boolean;
+ preventThrottling: boolean;
+ skipDefaults: boolean;
+ emitObservabilityEvents?: boolean;
+ };
+
+ /**
+ * Configurations values that may be safe to show to the user
+ */
+ features: {
+ allowHttp: boolean;
+ };
+}
+
export interface InitRequest {
- skipDefaults?: boolean;
+ config?: PartialWalletRunConfig;
}
+export const codecForInitRequest = (): Codec<InitRequest> =>
+ buildCodecForObject<InitRequest>()
+ .property("config", codecForAny())
+ .build("InitRequest");
+
export interface InitResponse {
versionInfo: WalletCoreVersion;
}
diff --git a/packages/taler-wallet-cli/src/index.ts b/packages/taler-wallet-cli/src/index.ts
index ffe033b24..773379044 100644
--- a/packages/taler-wallet-cli/src/index.ts
+++ b/packages/taler-wallet-cli/src/index.ts
@@ -251,6 +251,7 @@ interface CreateWalletResult {
async function createLocalWallet(
walletCliArgs: WalletCliArgsType,
notificationHandler?: (n: WalletNotification) => void,
+ noInit?: boolean,
): Promise<CreateWalletResult> {
const dbPath = walletCliArgs.wallet.walletDbFile ?? defaultWalletDbPath;
const myHttpLib = createPlatformHttpLib({
@@ -267,23 +268,29 @@ async function createLocalWallet(
}
},
cryptoWorkerType: walletCliArgs.wallet.cryptoWorker as any,
- config: {
- features: {},
- testing: {
- devModeActive: checkEnvFlag("TALER_WALLET_DEV_MODE"),
- denomselAllowLate: checkEnvFlag(
- "TALER_WALLET_DEBUG_DENOMSEL_ALLOW_LATE",
- ),
- emitObservabilityEvents: observabilityEventFile != null,
- skipDefaults: walletCliArgs.wallet.skipDefaults,
- },
- },
});
applyVerbose(walletCliArgs.wallet.verbose);
+ const res = { wallet: wh.wallet, getStats: wh.getDbStats };
+
+ if (!noInit) {
+ return res;
+ }
try {
- await wh.wallet.handleCoreApiRequest("initWallet", "native-init", {});
- return { wallet: wh.wallet, getStats: wh.getDbStats };
+ await wh.wallet.handleCoreApiRequest("initWallet", "native-init", {
+ config: {
+ features: {},
+ testing: {
+ devModeActive: checkEnvFlag("TALER_WALLET_DEV_MODE"),
+ denomselAllowLate: checkEnvFlag(
+ "TALER_WALLET_DEBUG_DENOMSEL_ALLOW_LATE",
+ ),
+ emitObservabilityEvents: observabilityEventFile != null,
+ skipDefaults: walletCliArgs.wallet.skipDefaults,
+ },
+ },
+ });
+ return res;
} catch (e) {
const ed = getErrorDetailFromException(e);
console.error("Operation failed: " + summarizeTalerErrorDetail(ed));
@@ -1196,6 +1203,9 @@ advancedCli
.requiredOption("unixPath", ["--unix-path"], clk.STRING, {
default: "wallet-core.sock",
})
+ .flag("noInit", ["--no-init"], {
+ help: "Do not initialize the wallet. The client must send the initWallet message.",
+ })
.action(async (args) => {
logger.info(`serving at ${args.serve.unixPath}`);
const onNotif = (notif: WalletNotification) => {
diff --git a/packages/taler-wallet-core/src/host-common.ts b/packages/taler-wallet-core/src/host-common.ts
index c56d7ed1c..7651e5a12 100644
--- a/packages/taler-wallet-core/src/host-common.ts
+++ b/packages/taler-wallet-core/src/host-common.ts
@@ -16,7 +16,6 @@
import { WalletNotification } from "@gnu-taler/taler-util";
import { HttpRequestLibrary } from "@gnu-taler/taler-util/http";
-import { WalletConfigParameter } from "./index.js";
/**
* Helpers to initiate a wallet in a host environment.
@@ -45,11 +44,6 @@ export interface DefaultNodeWalletArgs {
httpLib?: HttpRequestLibrary;
cryptoWorkerType?: "sync" | "node-worker-thread";
-
- /**
- * Config parameters
- */
- config?: WalletConfigParameter;
}
/**
diff --git a/packages/taler-wallet-core/src/host-impl.node.ts b/packages/taler-wallet-core/src/host-impl.node.ts
index a0c739f45..6a32a086a 100644
--- a/packages/taler-wallet-core/src/host-impl.node.ts
+++ b/packages/taler-wallet-core/src/host-impl.node.ts
@@ -32,7 +32,11 @@ import {
shimIndexedDB,
} from "@gnu-taler/idb-bridge";
import { createNodeSqlite3Impl } from "@gnu-taler/idb-bridge/node-sqlite3-bindings";
-import { Logger, SetTimeoutTimerAPI } from "@gnu-taler/taler-util";
+import {
+ Logger,
+ SetTimeoutTimerAPI,
+ WalletRunConfig,
+} from "@gnu-taler/taler-util";
import { createPlatformHttpLib } from "@gnu-taler/taler-util/http";
import * as fs from "fs";
import { NodeThreadCryptoWorkerFactory } from "./crypto/workers/nodeThreadWorker.js";
@@ -133,15 +137,18 @@ export async function createNativeWalletHost2(
wallet: Wallet;
getDbStats: () => AccessStats;
}> {
- let myHttpLib;
- if (args.httpLib) {
- myHttpLib = args.httpLib;
- } else {
- myHttpLib = createPlatformHttpLib({
- enableThrottling: true,
- requireTls: !args.config?.features?.allowHttp,
- });
- }
+ const myHttpFactory = (config: WalletRunConfig) => {
+ let myHttpLib;
+ if (args.httpLib) {
+ myHttpLib = args.httpLib;
+ } else {
+ myHttpLib = createPlatformHttpLib({
+ enableThrottling: true,
+ requireTls: !config.features.allowHttp,
+ });
+ }
+ return myHttpLib;
+ };
let dbResp: MakeDbResult;
@@ -188,10 +195,9 @@ export async function createNativeWalletHost2(
const w = await Wallet.create(
myIdbFactory,
- myHttpLib,
+ myHttpFactory,
timer,
workerFactory,
- args.config,
);
if (args.notifyHandler) {
diff --git a/packages/taler-wallet-core/src/host-impl.qtart.ts b/packages/taler-wallet-core/src/host-impl.qtart.ts
index 329e491bf..9c985d0c1 100644
--- a/packages/taler-wallet-core/src/host-impl.qtart.ts
+++ b/packages/taler-wallet-core/src/host-impl.qtart.ts
@@ -36,7 +36,11 @@ import {
createSqliteBackend,
shimIndexedDB,
} from "@gnu-taler/idb-bridge";
-import { Logger, SetTimeoutTimerAPI } from "@gnu-taler/taler-util";
+import {
+ Logger,
+ SetTimeoutTimerAPI,
+ WalletRunConfig,
+} from "@gnu-taler/taler-util";
import { createPlatformHttpLib } from "@gnu-taler/taler-util/http";
import { qjsOs, qjsStd } from "@gnu-taler/taler-util/qtart";
import { SynchronousCryptoWorkerFactoryPlain } from "./crypto/workers/synchronousWorkerFactoryPlain.js";
@@ -180,15 +184,18 @@ export async function createNativeWalletHost2(
shimIndexedDB(dbResp.idbFactory);
- let myHttpLib;
- if (args.httpLib) {
- myHttpLib = args.httpLib;
- } else {
- myHttpLib = createPlatformHttpLib({
- enableThrottling: true,
- requireTls: !args.config?.features?.allowHttp,
- });
- }
+ const myHttpFactory = (config: WalletRunConfig) => {
+ let myHttpLib;
+ if (args.httpLib) {
+ myHttpLib = args.httpLib;
+ } else {
+ myHttpLib = createPlatformHttpLib({
+ enableThrottling: true,
+ requireTls: !config.features.allowHttp,
+ });
+ }
+ return myHttpLib;
+ };
let workerFactory;
workerFactory = new SynchronousCryptoWorkerFactoryPlain();
@@ -197,10 +204,9 @@ export async function createNativeWalletHost2(
const w = await Wallet.create(
myIdbFactory,
- myHttpLib,
+ myHttpFactory,
timer,
workerFactory,
- args.config,
);
if (args.notifyHandler) {
diff --git a/packages/taler-wallet-core/src/wallet-api-types.ts b/packages/taler-wallet-core/src/wallet-api-types.ts
index 553155ece..240012bca 100644
--- a/packages/taler-wallet-core/src/wallet-api-types.ts
+++ b/packages/taler-wallet-core/src/wallet-api-types.ts
@@ -277,53 +277,6 @@ export type GetVersionOp = {
response: WalletCoreVersion;
};
-/**
- * Configurations options for the Wallet
- *
- * All missing values of the config will be replaced with default values
- * Default values are defined by Wallet.getDefaultConfig()
- */
-export type WalletConfigParameter = RecursivePartial<WalletConfig>;
-
-export interface BuiltinExchange {
- exchangeBaseUrl: string;
- currencyHint?: string;
-}
-
-export interface WalletConfig {
- /**
- * Initialization values useful for a complete startup.
- *
- * These are values may be overridden by different wallets
- */
- builtin: {
- exchanges: BuiltinExchange[];
- };
-
- /**
- * Unsafe options which it should only be used to create
- * testing environment.
- */
- testing: {
- /**
- * Allow withdrawal of denominations even though they are about to expire.
- */
- denomselAllowLate: boolean;
- devModeActive: boolean;
- insecureTrustExchange: boolean;
- preventThrottling: boolean;
- skipDefaults: boolean;
- emitObservabilityEvents: boolean;
- };
-
- /**
- * Configurations values that may be safe to show to the user
- */
- features: {
- allowHttp: boolean;
- };
-}
-
// group: Basic Wallet Information
/**
@@ -1100,14 +1053,12 @@ export type GetPendingTasksOp = {
response: any;
};
-
export type GetActiveTasksOp = {
op: WalletApiOperation.GetActiveTasks;
request: EmptyObject;
response: GetActiveTasks;
};
-
/**
* Dump all coins of the wallet in a simple JSON format.
*/
@@ -1305,15 +1256,3 @@ export interface WalletCoreApiClient {
payload: WalletCoreRequestType<Op>,
): Promise<WalletCoreResponseType<Op>>;
}
-
-type Primitives = string | number | boolean;
-
-type RecursivePartial<T extends object> = {
- [P in keyof T]?: T[P] extends Array<infer U extends object>
- ? Array<RecursivePartial<U>>
- : T[P] extends Array<infer J extends Primitives>
- ? Array<J>
- : T[P] extends object
- ? RecursivePartial<T[P]>
- : T[P];
-} & object;
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> {
diff --git a/packages/taler-wallet-embedded/src/wallet-qjs.ts b/packages/taler-wallet-embedded/src/wallet-qjs.ts
index 3023ce79f..384dd3a2a 100644
--- a/packages/taler-wallet-embedded/src/wallet-qjs.ts
+++ b/packages/taler-wallet-embedded/src/wallet-qjs.ts
@@ -275,14 +275,14 @@ export function installNativeWalletListener(): void {
globalThis.installNativeWalletListener = installNativeWalletListener;
export async function testWithGv() {
- const w = await createNativeWalletHost2({
+ const w = await createNativeWalletHost2({});
+ await w.wallet.client.call(WalletApiOperation.InitWallet, {
config: {
features: {
allowHttp: true,
},
},
});
- await w.wallet.client.call(WalletApiOperation.InitWallet, {});
await w.wallet.client.call(WalletApiOperation.RunIntegrationTest, {
amountToSpend: "KUDOS:1" as AmountString,
amountToWithdraw: "KUDOS:3" as AmountString,
@@ -297,14 +297,14 @@ export async function testWithGv() {
}
export async function testWithFdold() {
- const w = await createNativeWalletHost2({
+ const w = await createNativeWalletHost2({});
+ await w.wallet.client.call(WalletApiOperation.InitWallet, {
config: {
features: {
allowHttp: true,
},
},
});
- await w.wallet.client.call(WalletApiOperation.InitWallet, {});
await w.wallet.client.call(WalletApiOperation.RunIntegrationTest, {
amountToSpend: "TESTKUDOS:1" as AmountString,
amountToWithdraw: "TESTKUDOS:3" as AmountString,
@@ -321,16 +321,18 @@ export async function testWithLocal(path: string) {
console.log("running local test");
const w = await createNativeWalletHost2({
persistentStoragePath: path ?? "walletdb.json",
+ });
+ console.log("created wallet");
+ await w.wallet.client.call(WalletApiOperation.InitWallet, {
config: {
features: {
allowHttp: true,
},
+ testing: {
+ skipDefaults: true,
+ },
},
});
- console.log("created wallet");
- await w.wallet.client.call(WalletApiOperation.InitWallet, {
- skipDefaults: true,
- });
console.log("initialized wallet");
await w.wallet.client.call(WalletApiOperation.RunIntegrationTest, {
amountToSpend: "TESTKUDOS:1" as AmountString,
diff --git a/packages/taler-wallet-webextension/src/platform/api.ts b/packages/taler-wallet-webextension/src/platform/api.ts
index faf0f2820..57e7c51f4 100644
--- a/packages/taler-wallet-webextension/src/platform/api.ts
+++ b/packages/taler-wallet-webextension/src/platform/api.ts
@@ -17,10 +17,10 @@
import {
CoreApiResponse,
TalerUri,
- WalletNotification
+ WalletNotification,
+ WalletRunConfig
} from "@gnu-taler/taler-util";
import {
- WalletConfig,
WalletOperations
} from "@gnu-taler/taler-wallet-core";
import {
@@ -108,7 +108,7 @@ export interface WalletWebExVersion {
version: string;
}
-type F = WalletConfig["features"];
+type F = WalletRunConfig["features"];
type kf = keyof F;
type WebexWalletConfig = {
[P in keyof F as `wallet${Capitalize<P>}`]: F[P];
diff --git a/packages/taler-wallet-webextension/src/wxBackend.ts b/packages/taler-wallet-webextension/src/wxBackend.ts
index 2753d57b4..0801d2ab0 100644
--- a/packages/taler-wallet-webextension/src/wxBackend.ts
+++ b/packages/taler-wallet-webextension/src/wxBackend.ts
@@ -248,20 +248,25 @@ async function reinitWallet(): Promise<void> {
}
currentDatabase = undefined;
// setBadgeText({ text: "" });
- let httpLib: HttpRequestLibrary;
let cryptoWorker;
let timer;
+ const httpFactory = (): HttpRequestLibrary => {
+ if (platform.useServiceWorkerAsBackgroundProcess()) {
+ return new ServiceWorkerHttpLib({
+ // enableThrottling: false,
+ });
+ } else {
+ return new BrowserHttpLib({
+ // enableThrottling: false,
+ });
+ }
+ };
+
if (platform.useServiceWorkerAsBackgroundProcess()) {
- httpLib = new ServiceWorkerHttpLib({
- // enableThrottling: false,
- });
cryptoWorker = new SynchronousCryptoWorkerFactoryPlain();
timer = new SetTimeoutTimerAPI();
} else {
- httpLib = new BrowserHttpLib({
- // enableThrottling: false,
- });
// We could (should?) use the BrowserCryptoWorkerFactory here,
// but right now we don't, to have less platform differences.
// cryptoWorker = new BrowserCryptoWorkerFactory();
@@ -273,20 +278,19 @@ async function reinitWallet(): Promise<void> {
logger.info("Setting up wallet");
const wallet = await Wallet.create(
indexedDB as any,
- httpLib as any,
+ httpFactory as any,
timer,
cryptoWorker,
- {
+ );
+ try {
+ await wallet.handleCoreApiRequest("initWallet", "native-init", {
testing: {
emitObservabilityEvents: true,
},
features: {
allowHttp: settings.walletAllowHttp,
},
- },
- );
- try {
- await wallet.handleCoreApiRequest("initWallet", "native-init", {});
+ });
} catch (e) {
logger.error("could not initialize wallet", e);
walletInit.reject(e);