summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2023-02-15 23:32:42 +0100
committerFlorian Dold <florian@dold.me>2023-02-16 02:50:29 +0100
commit825d2c4352022e7397854b2bd9ba7d3589873c07 (patch)
treed23530bf8408367439e6b3820ea0c4269bfeb39a
parentcb2f4c21d85707abb0221cbf2a859a98836b2d44 (diff)
downloadwallet-core-825d2c4352022e7397854b2bd9ba7d3589873c07.tar.gz
wallet-core-825d2c4352022e7397854b2bd9ba7d3589873c07.tar.bz2
wallet-core-825d2c4352022e7397854b2bd9ba7d3589873c07.zip
make wallet-cli runnable under qtart
-rw-r--r--packages/anastasis-core/src/cli.ts2
-rw-r--r--packages/merchant-backoffice-ui/src/utils/regex.test.ts2
-rw-r--r--packages/taler-harness/src/bench1.ts17
-rw-r--r--packages/taler-harness/src/bench2.ts11
-rw-r--r--packages/taler-harness/src/bench3.ts15
-rw-r--r--packages/taler-harness/src/harness/harness.ts9
-rw-r--r--packages/taler-harness/src/index.ts13
-rw-r--r--packages/taler-harness/src/integrationtests/test-exchange-timetravel.ts10
-rw-r--r--packages/taler-harness/src/integrationtests/test-kyc.ts14
-rw-r--r--packages/taler-harness/src/integrationtests/test-merchant-spec-public-orders.ts5
-rw-r--r--packages/taler-harness/src/integrationtests/test-payment-on-demo.ts4
-rw-r--r--packages/taler-harness/src/integrationtests/test-wallet-cryptoworker.ts13
-rw-r--r--packages/taler-harness/src/integrationtests/test-wallet-dbless.ts11
-rw-r--r--packages/taler-harness/src/lint.ts10
-rw-r--r--packages/taler-util/package.json30
-rw-r--r--packages/taler-util/src/clk.ts53
-rw-r--r--packages/taler-util/src/compat.d.ts (renamed from packages/taler-wallet-core/src/crypto/workers/synchronousWorkerFactoryNode.ts)28
-rw-r--r--packages/taler-util/src/compat.node.ts59
-rw-r--r--packages/taler-util/src/compat.qtart.ts53
-rw-r--r--packages/taler-util/src/errors.ts (renamed from packages/taler-wallet-core/src/errors.ts)0
-rw-r--r--packages/taler-util/src/http-common.ts39
-rw-r--r--packages/taler-util/src/http-impl.node.d.ts17
-rw-r--r--packages/taler-util/src/http-impl.node.ts175
-rw-r--r--packages/taler-util/src/http-impl.qtart.ts127
-rw-r--r--packages/taler-util/src/http.ts (renamed from packages/taler-wallet-core/src/util/http.ts)8
-rw-r--r--packages/taler-util/src/index.browser.ts4
-rw-r--r--packages/taler-util/src/index.node.ts1
-rw-r--r--packages/taler-util/src/index.ts1
-rw-r--r--packages/taler-util/src/qtart.ts36
-rw-r--r--packages/taler-util/src/twrpc-impl.missing.ts9
-rwxr-xr-xpackages/taler-wallet-cli/build.mjs6
-rw-r--r--packages/taler-wallet-cli/src/index.ts131
-rw-r--r--packages/taler-wallet-core/package.json8
-rw-r--r--packages/taler-wallet-core/src/bank-api-client.ts7
-rw-r--r--packages/taler-wallet-core/src/crypto/workers/crypto-dispatcher.test.ts2
-rw-r--r--packages/taler-wallet-core/src/crypto/workers/crypto-dispatcher.ts2
-rw-r--r--packages/taler-wallet-core/src/crypto/workers/rpcClient.ts92
-rw-r--r--packages/taler-wallet-core/src/crypto/workers/synchronousWorkerNode.ts174
-rw-r--r--packages/taler-wallet-core/src/crypto/workers/worker-common.ts2
-rw-r--r--packages/taler-wallet-core/src/db.ts3
-rw-r--r--packages/taler-wallet-core/src/dbless.ts2
-rw-r--r--packages/taler-wallet-core/src/dev-experiments.ts2
-rw-r--r--packages/taler-wallet-core/src/headless/NodeHttpLib.ts183
-rw-r--r--packages/taler-wallet-core/src/host-common.ts60
-rw-r--r--packages/taler-wallet-core/src/host-impl.node.ts (renamed from packages/taler-wallet-core/src/headless/helpers.ts)78
-rw-r--r--packages/taler-wallet-core/src/host-impl.qtart.ts120
-rw-r--r--packages/taler-wallet-core/src/host.ts47
-rw-r--r--packages/taler-wallet-core/src/index.node.ts11
-rw-r--r--packages/taler-wallet-core/src/index.ts6
-rw-r--r--packages/taler-wallet-core/src/internal-wallet-state.ts13
-rw-r--r--packages/taler-wallet-core/src/operations/backup/index.ts4
-rw-r--r--packages/taler-wallet-core/src/operations/common.ts2
-rw-r--r--packages/taler-wallet-core/src/operations/deposits.ts6
-rw-r--r--packages/taler-wallet-core/src/operations/exchanges.ts9
-rw-r--r--packages/taler-wallet-core/src/operations/merchants.ts2
-rw-r--r--packages/taler-wallet-core/src/operations/pay-merchant.ts7
-rw-r--r--packages/taler-wallet-core/src/operations/pay-peer.ts5
-rw-r--r--packages/taler-wallet-core/src/operations/recoup.ts2
-rw-r--r--packages/taler-wallet-core/src/operations/refresh.ts4
-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/withdraw.ts4
-rw-r--r--packages/taler-wallet-core/src/remote.ts2
-rw-r--r--packages/taler-wallet-core/src/util/retries.ts2
-rw-r--r--packages/taler-wallet-core/src/wallet.ts4
-rwxr-xr-xpackages/taler-wallet-embedded/build.mjs1
-rw-r--r--packages/taler-wallet-embedded/src/index.ts28
-rw-r--r--packages/taler-wallet-embedded/src/wallet-qjs.ts237
-rw-r--r--packages/taler-wallet-webextension/src/browserHttpLib.ts10
-rw-r--r--packages/taler-wallet-webextension/src/browserWorkerEntry.ts7
-rw-r--r--packages/taler-wallet-webextension/src/cta/InvoiceCreate/state.ts2
-rw-r--r--packages/taler-wallet-webextension/src/cta/InvoicePay/state.ts6
-rw-r--r--packages/taler-wallet-webextension/src/cta/TransferCreate/state.ts6
-rw-r--r--packages/taler-wallet-webextension/src/cta/TransferPickup/state.ts7
-rw-r--r--packages/taler-wallet-webextension/src/cta/Withdraw/state.ts3
-rw-r--r--packages/taler-wallet-webextension/src/hooks/useAsyncAsHook.ts3
-rw-r--r--packages/taler-wallet-webextension/src/platform/chrome.ts3
-rw-r--r--packages/taler-wallet-webextension/src/serviceWorkerCryptoWorkerFactory.ts4
-rw-r--r--packages/taler-wallet-webextension/src/serviceWorkerHttpLib.ts4
-rw-r--r--packages/taler-wallet-webextension/src/wxApi.ts8
-rw-r--r--packages/taler-wallet-webextension/src/wxBackend.ts4
81 files changed, 1070 insertions, 1047 deletions
diff --git a/packages/anastasis-core/src/cli.ts b/packages/anastasis-core/src/cli.ts
index 517f2876d..df53d6bd0 100644
--- a/packages/anastasis-core/src/cli.ts
+++ b/packages/anastasis-core/src/cli.ts
@@ -1,4 +1,4 @@
-import { clk } from "@gnu-taler/taler-util";
+import { clk } from "@gnu-taler/taler-util/clk";
import {
getBackupStartState,
getRecoveryStartState,
diff --git a/packages/merchant-backoffice-ui/src/utils/regex.test.ts b/packages/merchant-backoffice-ui/src/utils/regex.test.ts
index 341a19fb1..d473bd08c 100644
--- a/packages/merchant-backoffice-ui/src/utils/regex.test.ts
+++ b/packages/merchant-backoffice-ui/src/utils/regex.test.ts
@@ -20,7 +20,7 @@
*/
import { expect } from "chai";
-import { AMOUNT_REGEX, PAYTO_REGEX } from "../../src/utils/constants.js";
+import { AMOUNT_REGEX, PAYTO_REGEX } from "./constants.js";
describe("payto uri format", () => {
const valids = [
diff --git a/packages/taler-harness/src/bench1.ts b/packages/taler-harness/src/bench1.ts
index 84786d25a..0a4118ec1 100644
--- a/packages/taler-harness/src/bench1.ts
+++ b/packages/taler-harness/src/bench1.ts
@@ -19,19 +19,19 @@
*/
import {
buildCodecForObject,
+ codecForBoolean,
codecForNumber,
codecForString,
- codecForBoolean,
codecOptional,
j2s,
Logger,
} from "@gnu-taler/taler-util";
+import { createPlatformHttpLib } from "@gnu-taler/taler-util/http";
import {
- getDefaultNodeWallet2,
- NodeHttpLib,
- WalletApiOperation,
- Wallet,
AccessStats,
+ createNativeWalletHost2,
+ Wallet,
+ WalletApiOperation,
} from "@gnu-taler/taler-wallet-core";
/**
@@ -46,8 +46,9 @@ export async function runBench1(configJson: any): Promise<void> {
// Validate the configuration file for this benchmark.
const b1conf = codecForBench1Config().decode(configJson);
- const myHttpLib = new NodeHttpLib();
- myHttpLib.setThrottling(false);
+ const myHttpLib = createPlatformHttpLib({
+ enableThrottling: false,
+ });
const numIter = b1conf.iterations ?? 1;
const numDeposits = b1conf.deposits ?? 5;
@@ -81,7 +82,7 @@ export async function runBench1(configJson: any): Promise<void> {
console.log("wallet DB stats", j2s(getDbStats!()));
}
- const res = await getDefaultNodeWallet2({
+ const res = await createNativeWalletHost2({
// No persistent DB storage.
persistentStoragePath: undefined,
httpLib: myHttpLib,
diff --git a/packages/taler-harness/src/bench2.ts b/packages/taler-harness/src/bench2.ts
index 9fa5d7caf..ff87da52a 100644
--- a/packages/taler-harness/src/bench2.ts
+++ b/packages/taler-harness/src/bench2.ts
@@ -24,6 +24,7 @@ import {
codecOptional,
Logger,
} from "@gnu-taler/taler-util";
+import { createPlatformHttpLib } from "@gnu-taler/taler-util/http";
import {
checkReserve,
createFakebankReserve,
@@ -31,9 +32,8 @@ import {
depositCoin,
downloadExchangeInfo,
findDenomOrThrow,
- NodeHttpLib,
refreshCoin,
- SynchronousCryptoWorkerFactoryNode,
+ SynchronousCryptoWorkerFactoryPlain,
withdrawCoin,
} from "@gnu-taler/taler-wallet-core";
@@ -50,12 +50,13 @@ export async function runBench2(configJson: any): Promise<void> {
const benchConf = codecForBench2Config().decode(configJson);
const curr = benchConf.currency;
const cryptoDisp = new CryptoDispatcher(
- new SynchronousCryptoWorkerFactoryNode(),
+ new SynchronousCryptoWorkerFactoryPlain(),
);
const cryptoApi = cryptoDisp.cryptoApi;
- const http = new NodeHttpLib();
- http.setThrottling(false);
+ const http = createPlatformHttpLib({
+ enableThrottling: false,
+ });
const numIter = benchConf.iterations ?? 1;
const numDeposits = benchConf.deposits ?? 5;
diff --git a/packages/taler-harness/src/bench3.ts b/packages/taler-harness/src/bench3.ts
index 9679f05a6..5e8fac0e9 100644
--- a/packages/taler-harness/src/bench3.ts
+++ b/packages/taler-harness/src/bench3.ts
@@ -25,12 +25,12 @@ import {
j2s,
Logger,
} from "@gnu-taler/taler-util";
+import { createPlatformHttpLib } from "@gnu-taler/taler-util/http";
import {
- getDefaultNodeWallet2,
- NodeHttpLib,
- WalletApiOperation,
- Wallet,
AccessStats,
+ createNativeWalletHost2,
+ Wallet,
+ WalletApiOperation,
} from "@gnu-taler/taler-wallet-core";
import benchMerchantIDGenerator from "./benchMerchantIDGenerator.js";
@@ -50,8 +50,9 @@ export async function runBench3(configJson: any): Promise<void> {
throw new Error("Payto template url must contain '${id}' placeholder");
}
- const myHttpLib = new NodeHttpLib();
- myHttpLib.setThrottling(false);
+ const myHttpLib = createPlatformHttpLib({
+ enableThrottling: false,
+ });
const numIter = b3conf.iterations ?? 1;
const numDeposits = b3conf.deposits ?? 5;
@@ -89,7 +90,7 @@ export async function runBench3(configJson: any): Promise<void> {
console.log("wallet DB stats", j2s(getDbStats!()));
}
- const res = await getDefaultNodeWallet2({
+ const res = await createNativeWalletHost2({
// No persistent DB storage.
persistentStoragePath: undefined,
httpLib: myHttpLib,
diff --git a/packages/taler-harness/src/harness/harness.ts b/packages/taler-harness/src/harness/harness.ts
index 0b7ba14cf..518b98d82 100644
--- a/packages/taler-harness/src/harness/harness.ts
+++ b/packages/taler-harness/src/harness/harness.ts
@@ -41,17 +41,15 @@ import {
MerchantTemplateAddDetails,
parsePaytoUri,
stringToBytes,
+ TalerError,
TalerProtocolDuration,
WalletNotification,
} from "@gnu-taler/taler-util";
import {
- BankAccessApi,
BankApi,
BankServiceHandle,
HarnessExchangeBankAccount,
- NodeHttpLib,
openPromise,
- TalerError,
WalletCoreApiClient,
} from "@gnu-taler/taler-wallet-core";
import { deepStrictEqual } from "assert";
@@ -83,6 +81,7 @@ import {
RemoteWallet,
WalletNotificationWaiter,
} from "@gnu-taler/taler-wallet-core/remote";
+import { createPlatformHttpLib } from "@gnu-taler/taler-util/http";
const logger = new Logger("harness.ts");
@@ -507,7 +506,7 @@ class LibEuFinBankService extends BankServiceBase implements BankServiceHandle {
sandboxProc: ProcessWrapper | undefined;
nexusProc: ProcessWrapper | undefined;
- http = new NodeHttpLib();
+ http = createPlatformHttpLib();
static async create(
gc: GlobalTestState,
@@ -794,7 +793,7 @@ export class FakebankService
{
proc: ProcessWrapper | undefined;
- http = new NodeHttpLib();
+ http = createPlatformHttpLib();
// We store "created" accounts during setup and
// register them after startup.
diff --git a/packages/taler-harness/src/index.ts b/packages/taler-harness/src/index.ts
index e4ee25dae..14b8a4302 100644
--- a/packages/taler-harness/src/index.ts
+++ b/packages/taler-harness/src/index.ts
@@ -23,7 +23,6 @@ import os from "os";
import path from "path";
import {
Amounts,
- clk,
Configuration,
decodeCrock,
Logger,
@@ -38,6 +37,7 @@ import { GlobalTestState, runTestWithState } from "./harness/harness.js";
import { getTestInfo, runTests } from "./integrationtests/testrunner.js";
import { lintExchangeDeployment } from "./lint.js";
import { runEnvFull } from "./env-full.js";
+import { clk } from "@gnu-taler/taler-util/clk";
const logger = new Logger("taler-harness:index.ts");
@@ -75,6 +75,15 @@ const advancedCli = testingCli.subcommand("advancedArgs", "advanced", {
});
advancedCli
+ .subcommand("decode", "decode", {
+ help: "Decode base32-crockford.",
+ })
+ .action((args) => {
+ const enc = fs.readFileSync(0, "utf8");
+ console.log(decodeCrock(enc.trim()));
+ });
+
+advancedCli
.subcommand("bench1", "bench1", {
help: "Run the 'bench1' benchmark",
})
@@ -272,7 +281,7 @@ testingCli
help: "Produce less output.",
})
.flag("noTimeout", ["--no-timeout"], {
- help: "Do not time out tests."
+ help: "Do not time out tests.",
})
.action(async (args) => {
await runTests({
diff --git a/packages/taler-harness/src/integrationtests/test-exchange-timetravel.ts b/packages/taler-harness/src/integrationtests/test-exchange-timetravel.ts
index 074126e9f..20285cb6a 100644
--- a/packages/taler-harness/src/integrationtests/test-exchange-timetravel.ts
+++ b/packages/taler-harness/src/integrationtests/test-exchange-timetravel.ts
@@ -24,22 +24,18 @@ import {
Duration,
durationFromSpec,
} from "@gnu-taler/taler-util";
-import {
- NodeHttpLib,
- readSuccessResponseJsonOrThrow,
-} from "@gnu-taler/taler-wallet-core";
+import { createPlatformHttpLib, readSuccessResponseJsonOrThrow } from "@gnu-taler/taler-util/http";
import { makeNoFeeCoinConfig } from "../harness/denomStructures.js";
import {
BankService,
ExchangeService,
GlobalTestState,
- MerchantPrivateApi,
MerchantService,
setupDb,
WalletCli,
getPayto,
} from "../harness/harness.js";
-import { startWithdrawViaBank, withdrawViaBank } from "../harness/helpers.js";
+import { withdrawViaBank } from "../harness/helpers.js";
async function applyTimeTravel(
timetravelDuration: Duration,
@@ -69,7 +65,7 @@ async function applyTimeTravel(
}
}
-const http = new NodeHttpLib();
+const http = createPlatformHttpLib();
/**
* Basic time travel test.
diff --git a/packages/taler-harness/src/integrationtests/test-kyc.ts b/packages/taler-harness/src/integrationtests/test-kyc.ts
index 490673cee..915c3d470 100644
--- a/packages/taler-harness/src/integrationtests/test-kyc.ts
+++ b/packages/taler-harness/src/integrationtests/test-kyc.ts
@@ -17,11 +17,14 @@
/**
* Imports.
*/
-import { Duration, j2s, NotificationType } from "@gnu-taler/taler-util";
+import {
+ Duration,
+ j2s,
+ NotificationType,
+} from "@gnu-taler/taler-util";
import {
BankAccessApi,
BankApi,
- NodeHttpLib,
WalletApiOperation,
} from "@gnu-taler/taler-wallet-core";
import { CoinConfig, defaultCoinConfig } from "../harness/denomStructures.js";
@@ -37,6 +40,7 @@ import {
} from "../harness/harness.js";
import { EnvOptions, SimpleTestEnvironmentNg } from "../harness/helpers.js";
import * as http from "node:http";
+import { createPlatformHttpLib } from "@gnu-taler/taler-util/http";
export async function createKycTestkudosEnvironment(
t: GlobalTestState,
@@ -336,12 +340,12 @@ export async function runKycTest(t: GlobalTestState) {
// We now simulate the user interacting with the KYC service,
// which would usually done in the browser.
- const httpClient = new NodeHttpLib();
- const kycServerResp = await httpClient.get(kycNotif.kycUrl);
+ const httpLib = createPlatformHttpLib();
+ const kycServerResp = await httpLib.get(kycNotif.kycUrl);
const kycLoginResp = await kycServerResp.json();
console.log("kyc server resp:", j2s(kycLoginResp));
const kycProofUrl = kycLoginResp.redirect_uri;
- const proofHttpResp = await httpClient.get(kycProofUrl);
+ const proofHttpResp = await httpLib.get(kycProofUrl);
console.log("proof resp status", proofHttpResp.status);
console.log("resp headers", proofHttpResp.headers.toJSON());
diff --git a/packages/taler-harness/src/integrationtests/test-merchant-spec-public-orders.ts b/packages/taler-harness/src/integrationtests/test-merchant-spec-public-orders.ts
index 70edaaf0c..2fafe7584 100644
--- a/packages/taler-harness/src/integrationtests/test-merchant-spec-public-orders.ts
+++ b/packages/taler-harness/src/integrationtests/test-merchant-spec-public-orders.ts
@@ -24,7 +24,8 @@ import {
encodeCrock,
getRandomBytes,
} from "@gnu-taler/taler-util";
-import { NodeHttpLib, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { createPlatformHttpLib } from "@gnu-taler/taler-util/http";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import {
BankService,
ExchangeService,
@@ -38,7 +39,7 @@ import {
withdrawViaBank,
} from "../harness/helpers.js";
-const httpLib = new NodeHttpLib();
+const httpLib = createPlatformHttpLib();
interface Context {
merchant: MerchantService;
diff --git a/packages/taler-harness/src/integrationtests/test-payment-on-demo.ts b/packages/taler-harness/src/integrationtests/test-payment-on-demo.ts
index 737620ce7..22e88c8a0 100644
--- a/packages/taler-harness/src/integrationtests/test-payment-on-demo.ts
+++ b/packages/taler-harness/src/integrationtests/test-payment-on-demo.ts
@@ -24,8 +24,8 @@ import {
BankApi,
BankAccessApi,
BankServiceHandle,
- NodeHttpLib,
} from "@gnu-taler/taler-wallet-core";
+import { createPlatformHttpLib } from "@gnu-taler/taler-util/http";
/**
* Run test for basic, bank-integrated withdrawal and payment.
@@ -35,7 +35,7 @@ export async function runPaymentDemoTest(t: GlobalTestState) {
let bankInterface: BankServiceHandle = {
baseUrl: "https://bank.demo.taler.net/",
bankAccessApiBaseUrl: "https://bank.demo.taler.net/",
- http: new NodeHttpLib(),
+ http: createPlatformHttpLib(),
};
let user = await BankApi.createRandomBankUser(bankInterface);
let wop = await BankAccessApi.createWithdrawalOperation(
diff --git a/packages/taler-harness/src/integrationtests/test-wallet-cryptoworker.ts b/packages/taler-harness/src/integrationtests/test-wallet-cryptoworker.ts
index a9f1c4d80..6c2006636 100644
--- a/packages/taler-harness/src/integrationtests/test-wallet-cryptoworker.ts
+++ b/packages/taler-harness/src/integrationtests/test-wallet-cryptoworker.ts
@@ -17,23 +17,10 @@
/**
* Imports.
*/
-import { j2s } from "@gnu-taler/taler-util";
import {
- checkReserve,
- CryptoDispatcher,
- depositCoin,
- downloadExchangeInfo,
- findDenomOrThrow,
- NodeHttpLib,
- refreshCoin,
- SynchronousCryptoWorkerFactoryNode,
- TalerError,
- topupReserveWithDemobank,
WalletApiOperation,
- withdrawCoin,
} from "@gnu-taler/taler-wallet-core";
import { GlobalTestState, WalletCli } from "../harness/harness.js";
-import { createSimpleTestkudosEnvironment } from "../harness/helpers.js";
/**
* Run test for the different crypto workers.
diff --git a/packages/taler-harness/src/integrationtests/test-wallet-dbless.ts b/packages/taler-harness/src/integrationtests/test-wallet-dbless.ts
index 7692f12b2..08c10fd91 100644
--- a/packages/taler-harness/src/integrationtests/test-wallet-dbless.ts
+++ b/packages/taler-harness/src/integrationtests/test-wallet-dbless.ts
@@ -17,17 +17,16 @@
/**
* Imports.
*/
-import { j2s } from "@gnu-taler/taler-util";
+import { j2s, TalerError } from "@gnu-taler/taler-util";
+import { createPlatformHttpLib } from "@gnu-taler/taler-util/http";
import {
checkReserve,
CryptoDispatcher,
depositCoin,
downloadExchangeInfo,
findDenomOrThrow,
- NodeHttpLib,
refreshCoin,
- SynchronousCryptoWorkerFactoryNode,
- TalerError,
+ SynchronousCryptoWorkerFactoryPlain,
topupReserveWithDemobank,
withdrawCoin,
} from "@gnu-taler/taler-wallet-core";
@@ -42,9 +41,9 @@ export async function runWalletDblessTest(t: GlobalTestState) {
const { bank, exchange } = await createSimpleTestkudosEnvironment(t);
- const http = new NodeHttpLib();
+ const http = createPlatformHttpLib();
const cryptiDisp = new CryptoDispatcher(
- new SynchronousCryptoWorkerFactoryNode(),
+ new SynchronousCryptoWorkerFactoryPlain(),
);
const cryptoApi = cryptiDisp.cryptoApi;
diff --git a/packages/taler-harness/src/lint.ts b/packages/taler-harness/src/lint.ts
index 49fb9dc86..3d3805e79 100644
--- a/packages/taler-harness/src/lint.ts
+++ b/packages/taler-harness/src/lint.ts
@@ -37,13 +37,13 @@ import {
Configuration,
decodeCrock,
} from "@gnu-taler/taler-util";
-import {
- NodeHttpLib,
- readSuccessResponseJsonOrThrow,
-} from "@gnu-taler/taler-wallet-core";
import { URL } from "url";
import { spawn } from "child_process";
import { delayMs } from "./harness/harness.js";
+import {
+ createPlatformHttpLib,
+ readSuccessResponseJsonOrThrow,
+} from "@gnu-taler/taler-util/http";
interface BasicConf {
mainCurrency: string;
@@ -53,7 +53,7 @@ interface PubkeyConf {
masterPublicKey: string;
}
-const httpLib = new NodeHttpLib();
+const httpLib = createPlatformHttpLib();
interface ShellResult {
stdout: string;
diff --git a/packages/taler-util/package.json b/packages/taler-util/package.json
index 23ff5dcfa..9cf47d256 100644
--- a/packages/taler-util/package.json
+++ b/packages/taler-util/package.json
@@ -15,12 +15,38 @@
},
"./twrpc": {
"default": "./lib/twrpc.js"
+ },
+ "./compat": {
+ "types": "./lib/compat.node.js",
+ "node": "./lib/compat.node.js",
+ "qtart": "./lib/compat.qtart.js",
+ "default": "./lib/not-implemented.js"
+ },
+ "./clk": {
+ "default": "./lib/clk.js"
+ },
+ "./http": {
+ "default": "./lib/http.js"
+ },
+ "./qtart": {
+ "types": "./lib/qtart.js",
+ "qtart": "./lib/qtart.js",
+ "default": "./lib/not-implemented.js"
}
},
"imports": {
"#twrpc-impl": {
- "node": "./lib/twrpc-impl.node.js",
- "default": "./lib/twrpc-impl.missing.js"
+ "node": "./lib/twrpc-impl.node.js"
+ },
+ "#compat-impl": {
+ "node": "./lib/compat.node.js",
+ "qtart": "./lib/compat.qtart.js",
+ "type": "./lib/compat.d.ts"
+ },
+ "#http-impl": {
+ "type": "./lib/http-impl.node.js",
+ "node": "./lib/http-impl.node.js",
+ "qtart": "./lib/http-impl.qtart.js"
}
},
"scripts": {
diff --git a/packages/taler-util/src/clk.ts b/packages/taler-util/src/clk.ts
index e99ebf733..7bcd19b04 100644
--- a/packages/taler-util/src/clk.ts
+++ b/packages/taler-util/src/clk.ts
@@ -17,10 +17,12 @@
/**
* Imports.
*/
-import process from "process";
-import path from "path";
-import readline from "readline";
-import { devNull } from "os";
+import {
+ processExit,
+ processArgv,
+ readlinePrompt,
+ pathBasename,
+} from "#compat-impl";
export namespace clk {
class Converter<T> {}
@@ -359,13 +361,13 @@ export namespace clk {
console.error(
`error: unknown option '--${r.key}' for ${currentName}`,
);
- process.exit(-1);
+ processExit(-1);
throw Error("not reached");
}
if (d.isFlag) {
if (r.value !== undefined) {
console.error(`error: flag '--${r.key}' does not take a value`);
- process.exit(-1);
+ processExit(-1);
throw Error("not reached");
}
storeFlag(d, true);
@@ -373,7 +375,7 @@ export namespace clk {
if (r.value === undefined) {
if (i === unparsedArgs.length - 1) {
console.error(`error: option '--${r.key}' needs an argument`);
- process.exit(-1);
+ processExit(-1);
throw Error("not reached");
}
storeOption(d, unparsedArgs[i + 1]);
@@ -391,7 +393,7 @@ export namespace clk {
const opt = this.shortOptions[chr];
if (!opt) {
console.error(`error: option '-${chr}' not known`);
- process.exit(-1);
+ processExit(-1);
}
if (opt.isFlag) {
storeFlag(opt, true);
@@ -399,7 +401,7 @@ export namespace clk {
if (si == optShort.length - 1) {
if (i === unparsedArgs.length - 1) {
console.error(`error: option '-${chr}' needs an argument`);
- process.exit(-1);
+ processExit(-1);
throw Error("not reached");
} else {
storeOption(opt, unparsedArgs[i + 1]);
@@ -418,7 +420,7 @@ export namespace clk {
const subcmd = this.subcommandMap[argVal];
if (!subcmd) {
console.error(`error: unknown command '${argVal}'`);
- process.exit(-1);
+ processExit(-1);
throw Error("not reached");
}
foundSubcommand = subcmd.commandGroup;
@@ -427,7 +429,7 @@ export namespace clk {
const d = this.arguments[posArgIndex];
if (!d) {
console.error(`error: too many arguments for ${currentName}`);
- process.exit(-1);
+ processExit(-1);
throw Error("not reached");
}
myArgs[d.name] = unparsedArgs[i];
@@ -437,7 +439,7 @@ export namespace clk {
if (parsedArgs[this.argKey].help) {
this.printHelp(progname, parents);
- process.exit(0);
+ processExit(0);
throw Error("not reached");
}
@@ -450,7 +452,7 @@ export namespace clk {
console.error(
`error: missing positional argument '${d.name}' for ${currentName}`,
);
- process.exit(-1);
+ processExit(-1);
throw Error("not reached");
}
}
@@ -464,7 +466,7 @@ export namespace clk {
} else {
const name = option.flagspec.join(",");
console.error(`error: missing option '${name}'`);
- process.exit(-1);
+ processExit(-1);
throw Error("not reached");
}
}
@@ -492,16 +494,16 @@ export namespace clk {
} catch (e) {
console.error(`An error occurred while running ${currentName}`);
console.error(e);
- process.exit(1);
+ processExit(1);
}
Promise.resolve(r).catch((e) => {
console.error(`An error occurred while running ${currentName}`);
console.error(e);
- process.exit(1);
+ processExit(1);
});
} else {
this.printHelp(progname, parents);
- process.exit(-1);
+ processExit(-1);
throw Error("not reached");
}
}
@@ -524,15 +526,15 @@ export namespace clk {
if (cmdlineArgs) {
args = cmdlineArgs;
} else {
- args = process.argv.slice(1);
+ args = processArgv().slice(1);
}
if (args.length < 1) {
console.error(
"Error while parsing command line arguments: not enough arguments",
);
- process.exit(-1);
+ processExit(-1);
}
- const progname = path.basename(args[0]);
+ const progname = pathBasename(args[0]);
const rest = args.slice(1);
this.mainCommand.run(progname, [], rest, {});
@@ -622,15 +624,6 @@ export namespace clk {
}
export function prompt(question: string): Promise<string> {
- const stdinReadline = readline.createInterface({
- input: process.stdin,
- output: process.stdout,
- });
- return new Promise<string>((resolve, reject) => {
- stdinReadline.question(question, (res) => {
- resolve(res);
- stdinReadline.close();
- });
- });
+ return readlinePrompt(question);
}
}
diff --git a/packages/taler-wallet-core/src/crypto/workers/synchronousWorkerFactoryNode.ts b/packages/taler-util/src/compat.d.ts
index 90f9a43fa..12ba31124 100644
--- a/packages/taler-wallet-core/src/crypto/workers/synchronousWorkerFactoryNode.ts
+++ b/packages/taler-util/src/compat.d.ts
@@ -1,6 +1,6 @@
/*
This file is part of GNU Taler
- (C) 2019 GNUnet e.V.
+ (C) 2023 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
@@ -14,23 +14,9 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-/**
- * Imports.
- */
-import { CryptoWorkerFactory } from "./crypto-dispatcher.js";
-import { CryptoWorker } from "./cryptoWorkerInterface.js";
-import { SynchronousCryptoWorkerNode } from "./synchronousWorkerNode.js";
-
-/**
- * The synchronous crypto worker produced by this factory doesn't run in the
- * background, but actually blocks the caller until the operation is done.
- */
-export class SynchronousCryptoWorkerFactoryNode implements CryptoWorkerFactory {
- startWorker(): CryptoWorker {
- return new SynchronousCryptoWorkerNode();
- }
-
- getConcurrency(): number {
- return 1;
- }
-}
+export function processExit(status: number): never;
+export function processArgv(): string[];
+export function readlinePrompt(prompt: string): Promise<string>;
+export function pathBasename(s: string): string;
+export function setUnhandledRejectionHandler(h: (e: any) => void): void;
+export function getenv(name: string): string | undefined; \ No newline at end of file
diff --git a/packages/taler-util/src/compat.node.ts b/packages/taler-util/src/compat.node.ts
new file mode 100644
index 000000000..ed27a7acd
--- /dev/null
+++ b/packages/taler-util/src/compat.node.ts
@@ -0,0 +1,59 @@
+/*
+ This file is part of GNU Taler
+ (C) 2023 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/>
+ */
+
+import process from "node:process";
+import readline from "node:readline";
+import path from "node:path";
+import os from "node:os";
+
+export function processExit(status: number): never {
+ process.exit(1);
+}
+
+export function processArgv(): string[] {
+ return [...process.argv];
+}
+
+export function readlinePrompt(prompt: string): Promise<string> {
+ const stdinReadline = readline.createInterface({
+ input: process.stdin,
+ output: process.stdout,
+ });
+ return new Promise<string>((resolve, reject) => {
+ stdinReadline.question(prompt, (res) => {
+ resolve(res);
+ stdinReadline.close();
+ });
+ });
+}
+
+export function pathBasename(p: string): string {
+ return path.basename(p);
+}
+
+export function pathHomedir(): string {
+ return os.homedir();
+}
+
+export function setUnhandledRejectionHandler(h: (e: any) => void): void {
+ process.on("unhandledRejection", (e) => {
+ h(e);
+ });
+}
+
+export function getenv(name: string): string | undefined {
+ return process.env[name];
+}
diff --git a/packages/taler-util/src/compat.qtart.ts b/packages/taler-util/src/compat.qtart.ts
new file mode 100644
index 000000000..f8b336b11
--- /dev/null
+++ b/packages/taler-util/src/compat.qtart.ts
@@ -0,0 +1,53 @@
+/*
+ This file is part of GNU Taler
+ (C) 2023 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/>
+ */
+
+// qtart "std" library
+// @ts-ignore
+import * as std from "std";
+
+export function processExit(status: number): never {
+ std.exit(status);
+ throw Error("not reached");
+}
+
+export function processArgv(): string[] {
+ // @ts-ignore
+ return ["qtart", ...globalThis.scriptArgs];
+}
+
+export function readlinePrompt(prompt: string): Promise<string> {
+ throw new Error("not supported");
+}
+
+export function pathBasename(p: string): string {
+ const slashIndex = p.lastIndexOf("/");
+ if (slashIndex < 0) {
+ return p;
+ }
+ return p.substring(0, slashIndex);
+}
+
+export function pathHomedir(): string {
+ return std.getenv("HOME");
+}
+
+export function setUnhandledRejectionHandler(h: (e: any) => void): void {
+ // not supported
+}
+
+export function getenv(name: string): string | undefined {
+ return std.getenv(name);
+}
diff --git a/packages/taler-wallet-core/src/errors.ts b/packages/taler-util/src/errors.ts
index 038bdbc7c..038bdbc7c 100644
--- a/packages/taler-wallet-core/src/errors.ts
+++ b/packages/taler-util/src/errors.ts
diff --git a/packages/taler-util/src/http-common.ts b/packages/taler-util/src/http-common.ts
new file mode 100644
index 000000000..eeb335ba7
--- /dev/null
+++ b/packages/taler-util/src/http-common.ts
@@ -0,0 +1,39 @@
+/*
+ This file is part of GNU Taler
+ (C) 2023 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/>
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+*/
+
+const textEncoder = new TextEncoder();
+
+export interface HttpLibArgs {
+ enableThrottling?: boolean,
+}
+
+export function encodeBody(body: any): ArrayBuffer {
+ if (body == null) {
+ return new ArrayBuffer(0);
+ }
+ if (typeof body === "string") {
+ return textEncoder.encode(body).buffer;
+ } else if (ArrayBuffer.isView(body)) {
+ return body.buffer;
+ } else if (body instanceof ArrayBuffer) {
+ return body;
+ } else if (typeof body === "object") {
+ return textEncoder.encode(JSON.stringify(body)).buffer;
+ }
+ throw new TypeError("unsupported request body type");
+}
diff --git a/packages/taler-util/src/http-impl.node.d.ts b/packages/taler-util/src/http-impl.node.d.ts
new file mode 100644
index 000000000..b0fba9b30
--- /dev/null
+++ b/packages/taler-util/src/http-impl.node.d.ts
@@ -0,0 +1,17 @@
+import { HttpLibArgs } from "./http-common.js";
+import { HttpRequestLibrary, HttpRequestOptions, HttpResponse } from "./http.js";
+/**
+ * Implementation of the HTTP request library interface for node.
+ */
+export declare class HttpLibImpl implements HttpRequestLibrary {
+ private throttle;
+ private throttlingEnabled;
+ constructor(args?: HttpLibArgs);
+ /**
+ * Set whether requests should be throttled.
+ */
+ setThrottling(enabled: boolean): void;
+ fetch(url: string, opt?: HttpRequestOptions): Promise<HttpResponse>;
+ get(url: string, opt?: HttpRequestOptions): Promise<HttpResponse>;
+ postJson(url: string, body: any, opt?: HttpRequestOptions): Promise<HttpResponse>;
+}
diff --git a/packages/taler-util/src/http-impl.node.ts b/packages/taler-util/src/http-impl.node.ts
new file mode 100644
index 000000000..5f2b3ac8a
--- /dev/null
+++ b/packages/taler-util/src/http-impl.node.ts
@@ -0,0 +1,175 @@
+/*
+ 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/>
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+*/
+
+/**
+ * Imports.
+ */
+import * as http from "node:http";
+import { RequestOptions } from "node:http";
+import { TalerError } from "./errors.js";
+import { encodeBody, HttpLibArgs } from "./http-common.js";
+import {
+ DEFAULT_REQUEST_TIMEOUT_MS,
+ Headers,
+ HttpRequestLibrary,
+ HttpRequestOptions,
+ HttpResponse,
+} from "./http.js";
+import {
+ Logger,
+ RequestThrottler,
+ TalerErrorCode,
+ typedArrayConcat,
+ URL,
+} from "./index.js";
+
+const logger = new Logger("http-impl.node.ts");
+
+const textDecoder = new TextDecoder();
+
+/**
+ * Implementation of the HTTP request library interface for node.
+ */
+export class HttpLibImpl implements HttpRequestLibrary {
+ private throttle = new RequestThrottler();
+ private throttlingEnabled = true;
+
+ constructor(args?: HttpLibArgs) {
+ this.throttlingEnabled = args?.enableThrottling ?? false;
+ }
+
+ /**
+ * Set whether requests should be throttled.
+ */
+ setThrottling(enabled: boolean): void {
+ this.throttlingEnabled = enabled;
+ }
+
+ async fetch(url: string, opt?: HttpRequestOptions): Promise<HttpResponse> {
+ const method = opt?.method?.toUpperCase() ?? "GET";
+ let body = opt?.body;
+
+ logger.trace(`Requesting ${method} ${url}`);
+
+ const parsedUrl = new URL(url);
+ if (this.throttlingEnabled && this.throttle.applyThrottle(url)) {
+ throw TalerError.fromDetail(
+ TalerErrorCode.WALLET_HTTP_REQUEST_THROTTLED,
+ {
+ requestMethod: method,
+ requestUrl: url,
+ throttleStats: this.throttle.getThrottleStats(url),
+ },
+ `request to origin ${parsedUrl.origin} was throttled`,
+ );
+ }
+ let timeoutMs: number | undefined;
+ if (typeof opt?.timeout?.d_ms === "number") {
+ timeoutMs = opt.timeout.d_ms;
+ } else {
+ timeoutMs = DEFAULT_REQUEST_TIMEOUT_MS;
+ }
+
+ const headers = { ...opt?.headers };
+ headers["Content-Type"] = "application/json";
+
+ let reqBody: ArrayBuffer | undefined;
+
+ if (opt?.method == "POST") {
+ reqBody = encodeBody(opt.body);
+ }
+
+ const options: RequestOptions = {
+ protocol: parsedUrl.protocol,
+ port: parsedUrl.port,
+ host: parsedUrl.host,
+ method: method,
+ path: parsedUrl.pathname,
+ headers: opt?.headers,
+ };
+
+ const chunks: Uint8Array[] = [];
+
+ return new Promise((resolve, reject) => {
+ const req = http.request(options, (res) => {
+ res.on("data", (d) => {
+ chunks.push(d);
+ });
+ res.on("end", () => {
+ const headers: Headers = new Headers();
+ for (const [k, v] of Object.entries(res.headers)) {
+ if (!v) {
+ continue;
+ }
+ if (typeof v === "string") {
+ headers.set(k, v);
+ } else {
+ headers.set(k, v.join(", "));
+ }
+ }
+ const data = typedArrayConcat(chunks);
+ const resp: HttpResponse = {
+ requestMethod: method,
+ requestUrl: parsedUrl.href,
+ status: res.statusCode || 0,
+ headers,
+ async bytes() {
+ return data;
+ },
+ json() {
+ const text = textDecoder.decode(data);
+ return JSON.parse(text);
+ },
+ async text() {
+ const text = textDecoder.decode(data);
+ return text;
+ },
+ };
+ resolve(resp);
+ });
+ res.on("error", (e) => {
+ reject(e);
+ });
+ });
+
+ if (reqBody) {
+ req.write(reqBody);
+ }
+ req.end();
+ });
+ }
+
+ async get(url: string, opt?: HttpRequestOptions): Promise<HttpResponse> {
+ return this.fetch(url, {
+ method: "GET",
+ ...opt,
+ });
+ }
+
+ async postJson(
+ url: string,
+ body: any,
+ opt?: HttpRequestOptions,
+ ): Promise<HttpResponse> {
+ return this.fetch(url, {
+ method: "POST",
+ body,
+ ...opt,
+ });
+ }
+}
diff --git a/packages/taler-util/src/http-impl.qtart.ts b/packages/taler-util/src/http-impl.qtart.ts
new file mode 100644
index 000000000..954b41802
--- /dev/null
+++ b/packages/taler-util/src/http-impl.qtart.ts
@@ -0,0 +1,127 @@
+/*
+ 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/>
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+*/
+
+/**
+ * Imports.
+ */
+import { Logger } from "@gnu-taler/taler-util";
+import { TalerError } from "./errors.js";
+import { encodeBody, HttpLibArgs } from "./http-common.js";
+import {
+ Headers,
+ HttpRequestLibrary,
+ HttpRequestOptions,
+ HttpResponse,
+} from "./http.js";
+import { RequestThrottler, TalerErrorCode, URL } from "./index.js";
+import { qjsOs } from "./qtart.js";
+
+const logger = new Logger("http-impl.qtart.ts");
+
+const textDecoder = new TextDecoder();
+
+/**
+ * Implementation of the HTTP request library interface for node.
+ */
+export class HttpLibImpl implements HttpRequestLibrary {
+ private throttle = new RequestThrottler();
+ private throttlingEnabled = true;
+
+ constructor(args?: HttpLibArgs) {
+ this.throttlingEnabled = args?.enableThrottling ?? false;
+ }
+
+ /**
+ * Set whether requests should be throttled.
+ */
+ setThrottling(enabled: boolean): void {
+ this.throttlingEnabled = enabled;
+ }
+
+ async fetch(url: string, opt?: HttpRequestOptions): Promise<HttpResponse> {
+ const method = opt?.method ?? "GET";
+
+ logger.trace(`Requesting ${method} ${url}`);
+
+ const parsedUrl = new URL(url);
+ if (this.throttlingEnabled && this.throttle.applyThrottle(url)) {
+ throw TalerError.fromDetail(
+ TalerErrorCode.WALLET_HTTP_REQUEST_THROTTLED,
+ {
+ requestMethod: method,
+ requestUrl: url,
+ throttleStats: this.throttle.getThrottleStats(url),
+ },
+ `request to origin ${parsedUrl.origin} was throttled`,
+ );
+ }
+
+ let data: ArrayBuffer | undefined = undefined;
+ let headers: string[] = [];
+ if (opt?.headers) {
+ for (let headerName of Object.keys(opt.headers)) {
+ headers.push(`${headerName}: ${opt.headers[headerName]}`);
+ }
+ }
+ if (method.toUpperCase() === "POST") {
+ data = encodeBody(opt?.body);
+ }
+ const res = await qjsOs.fetchHttp(url, {
+ method,
+ data,
+ headers,
+ });
+ return {
+ requestMethod: method,
+ // FIXME: We don't return headers!
+ headers: new Headers(),
+ async bytes() {
+ return res.data;
+ },
+ json() {
+ const text = textDecoder.decode(res.data);
+ return JSON.parse(text);
+ },
+ async text() {
+ const text = textDecoder.decode(res.data);
+ return text;
+ },
+ requestUrl: url,
+ status: res.status,
+ };
+ }
+
+ async get(url: string, opt?: HttpRequestOptions): Promise<HttpResponse> {
+ return this.fetch(url, {
+ method: "GET",
+ ...opt,
+ });
+ }
+
+ async postJson(
+ url: string,
+ body: any,
+ opt?: HttpRequestOptions,
+ ): Promise<HttpResponse> {
+ return this.fetch(url, {
+ method: "POST",
+ body,
+ ...opt,
+ });
+ }
+}
diff --git a/packages/taler-wallet-core/src/util/http.ts b/packages/taler-util/src/http.ts
index 1da31a315..fd594b655 100644
--- a/packages/taler-wallet-core/src/util/http.ts
+++ b/packages/taler-util/src/http.ts
@@ -34,7 +34,9 @@ import {
CancellationToken,
} from "@gnu-taler/taler-util";
import { TalerErrorCode } from "@gnu-taler/taler-util";
-import { makeErrorDetail, TalerError } from "../errors.js";
+import { makeErrorDetail, TalerError } from "./errors.js";
+import * as impl from "#http-impl";
+import { HttpLibArgs } from "./http-common.js";
const logger = new Logger("http.ts");
@@ -352,3 +354,7 @@ export function getExpiry(
}
return t;
}
+
+export function createPlatformHttpLib(args?: HttpLibArgs): HttpRequestLibrary {
+ return new impl.HttpLibImpl(args);
+}
diff --git a/packages/taler-util/src/index.browser.ts b/packages/taler-util/src/index.browser.ts
index 3b8e194b3..2a600644d 100644
--- a/packages/taler-util/src/index.browser.ts
+++ b/packages/taler-util/src/index.browser.ts
@@ -19,3 +19,7 @@
import { loadBrowserPrng } from "./prng-browser.js";
loadBrowserPrng();
export * from "./index.js";
+
+// The web stuff doesn't support package.json export declarations yet,
+// so we export more stuff here than we should.
+export * from "./http.js";
diff --git a/packages/taler-util/src/index.node.ts b/packages/taler-util/src/index.node.ts
index bd59f320a..018b4767f 100644
--- a/packages/taler-util/src/index.node.ts
+++ b/packages/taler-util/src/index.node.ts
@@ -21,4 +21,3 @@ initNodePrng();
export * from "./index.js";
export * from "./talerconfig.js";
export * from "./globbing/minimatch.js";
-export { clk } from "./clk.js";
diff --git a/packages/taler-util/src/index.ts b/packages/taler-util/src/index.ts
index 661b0332f..cf4f545a4 100644
--- a/packages/taler-util/src/index.ts
+++ b/packages/taler-util/src/index.ts
@@ -36,3 +36,4 @@ export * from "./CancellationToken.js";
export * from "./contract-terms.js";
export * from "./base64.js";
export * from "./merchant-api-types.js";
+export * from "./errors.js";
diff --git a/packages/taler-util/src/qtart.ts b/packages/taler-util/src/qtart.ts
new file mode 100644
index 000000000..f8edf234e
--- /dev/null
+++ b/packages/taler-util/src/qtart.ts
@@ -0,0 +1,36 @@
+
+// @ts-ignore
+import * as _qjsOsImp from "os";
+// @ts-ignore
+import * as _qjsStdImp from "std";
+
+
+export interface QjsHttpResp {
+ status: number;
+ data: ArrayBuffer;
+}
+
+export interface QjsHttpOptions {
+ method: string;
+ debug?: boolean;
+ data?: ArrayBuffer;
+ headers?: string[];
+}
+
+
+export interface QjsOsLib {
+ fetchHttp(url: string, options?: QjsHttpOptions): Promise<QjsHttpResp>;
+ postMessageToHost(s: string): void;
+ setMessageFromHostHandler(h: (s: string) => void): void;
+ rename(oldPath: string, newPath: string): number;
+}
+
+export interface QjsStdLib {
+ writeFile(filename: string, contents: string): void;
+ loadFile(filename: string): string;
+}
+
+// This is not the nodejs "os" module, but the qjs "os" module.
+export const qjsOs: QjsOsLib = _qjsOsImp as any;
+
+export const qjsStd: QjsStdLib = _qjsStdImp as any; \ No newline at end of file
diff --git a/packages/taler-util/src/twrpc-impl.missing.ts b/packages/taler-util/src/twrpc-impl.missing.ts
index d9ed37815..7d7fa84ae 100644
--- a/packages/taler-util/src/twrpc-impl.missing.ts
+++ b/packages/taler-util/src/twrpc-impl.missing.ts
@@ -14,4 +14,13 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
+import type { RpcConnectArgs, RpcServerArgs } from "./twrpc.js";
+
// Not implemented.
+export async function connectRpc<T>(args: RpcConnectArgs<T>): Promise<T> {
+ throw Error("not implemented");
+}
+
+export async function runRpcServer(args: RpcServerArgs): Promise<void> {
+ throw Error("not implemented");
+}
diff --git a/packages/taler-wallet-cli/build.mjs b/packages/taler-wallet-cli/build.mjs
index 14b626815..b2ed2c937 100755
--- a/packages/taler-wallet-cli/build.mjs
+++ b/packages/taler-wallet-cli/build.mjs
@@ -53,7 +53,7 @@ function git_hash() {
export const buildConfig = {
entryPoints: ["src/index.ts"],
- outfile: "dist/taler-wallet-cli.mjs",
+ outfile: "dist/taler-wallet-cli.qtart.mjs",
bundle: true,
minify: false,
target: [
@@ -61,7 +61,11 @@ export const buildConfig = {
],
format: 'esm',
platform: 'neutral',
+ mainFields: ["module", "main"],
+ conditions: ["qtart"],
sourcemap: true,
+ // quickjs standard library
+ external: ["std", "os"],
define: {
'__VERSION__': `"${_package.version}"`,
'__GIT_HASH__': `"${GIT_HASH}"`,
diff --git a/packages/taler-wallet-cli/src/index.ts b/packages/taler-wallet-cli/src/index.ts
index 228395991..aed9a24c0 100644
--- a/packages/taler-wallet-cli/src/index.ts
+++ b/packages/taler-wallet-cli/src/index.ts
@@ -21,12 +21,11 @@ import {
addPaytoQueryParams,
AgeRestriction,
classifyTalerUri,
- clk,
codecForList,
codecForString,
CoreApiResponse,
- decodeCrock,
encodeCrock,
+ getErrorDetailFromException,
getRandomBytes,
j2s,
Logger,
@@ -35,20 +34,26 @@ import {
RecoveryMergeStrategy,
setDangerousTimetravel,
setGlobalLogLevelFromString,
+ summarizeTalerErrorDetail,
TalerUriType,
WalletNotification,
} from "@gnu-taler/taler-util";
+import { clk } from "@gnu-taler/taler-util/clk";
+import {
+ getenv,
+ pathHomedir,
+ processExit,
+ setUnhandledRejectionHandler,
+} from "@gnu-taler/taler-util/compat";
+import { createPlatformHttpLib } from "@gnu-taler/taler-util/http";
import { JsonMessage, runRpcServer } from "@gnu-taler/taler-util/twrpc";
import {
+ createNativeWalletHost,
+ createNativeWalletHost2,
CryptoDispatcher,
- getDefaultNodeWallet,
- getDefaultNodeWallet2,
- getErrorDetailFromException,
nativeCrypto,
- NodeHttpLib,
- NodeThreadCryptoWorkerFactory,
- summarizeTalerErrorDetail,
- SynchronousCryptoWorkerFactoryNode,
+ //NodeThreadCryptoWorkerFactory,
+ //SynchronousCryptoWorkerFactoryPlain,
TalerCryptoInterface,
Wallet,
WalletApiOperation,
@@ -60,8 +65,6 @@ import {
getClientFromRemoteWallet,
makeNotificationWaiter,
} from "@gnu-taler/taler-wallet-core/remote";
-import fs from "fs";
-import os from "os";
// This module also serves as the entry point for the crypto
// thread worker, and thus must expose these two handlers.
@@ -76,13 +79,13 @@ const EXIT_EXCEPTION = 4;
const EXIT_API_ERROR = 5;
const EXIT_RETRIES_EXCEEDED = 6;
-process.on("unhandledRejection", (error: any) => {
+setUnhandledRejectionHandler((error: any) => {
logger.error("unhandledRejection", error.message);
logger.error("stack", error.stack);
- process.exit(2);
+ processExit(1);
});
-const defaultWalletDbPath = os.homedir + "/" + ".talerwalletdb.json";
+const defaultWalletDbPath = pathHomedir() + "/" + ".talerwalletdb.json";
function assertUnreachable(x: never): never {
throw new Error("Didn't expect to get here");
@@ -99,7 +102,7 @@ async function doPay(
if (result.status === PreparePayResultType.InsufficientBalance) {
console.log("contract", result.contractTerms);
console.error("insufficient balance");
- process.exit(1);
+ processExit(1);
return;
}
if (result.status === PreparePayResultType.AlreadyConfirmed) {
@@ -108,8 +111,7 @@ async function doPay(
} else {
console.log("payment already in progress");
}
-
- process.exit(0);
+ processExit(0);
return;
}
if (result.status === "payment-possible") {
@@ -154,7 +156,7 @@ function applyVerbose(verbose: boolean): void {
declare const __VERSION__: string;
function printVersion(): void {
console.log(__VERSION__);
- process.exit(0);
+ processExit(0);
}
export const walletCli = clk
@@ -203,7 +205,7 @@ export const walletCli = clk
type WalletCliArgsType = clk.GetArgType<typeof walletCli>;
function checkEnvFlag(name: string): boolean {
- const val = process.env[name];
+ const val = getenv(name);
if (val == "1") {
return true;
}
@@ -238,11 +240,10 @@ async function createLocalWallet(
notificationHandler?: (n: WalletNotification) => void,
): Promise<Wallet> {
const dbPath = walletCliArgs.wallet.walletDbFile ?? defaultWalletDbPath;
- const myHttpLib = new NodeHttpLib();
- if (walletCliArgs.wallet.noThrottle) {
- myHttpLib.setThrottling(false);
- }
- const wallet = await getDefaultNodeWallet({
+ const myHttpLib = createPlatformHttpLib({
+ enableThrottling: walletCliArgs.wallet.noThrottle ? false : true,
+ });
+ const wallet = await createNativeWalletHost({
persistentStoragePath: dbPath !== ":memory:" ? dbPath : undefined,
httpLib: myHttpLib,
notifyHandler: (n) => {
@@ -268,7 +269,7 @@ async function createLocalWallet(
const ed = getErrorDetailFromException(e);
console.error("Operation failed: " + summarizeTalerErrorDetail(ed));
console.error("Error details:", JSON.stringify(ed, undefined, 2));
- process.exit(1);
+ processExit(1);
} finally {
logger.trace("operation with wallet finished, stopping");
logger.trace("stopped wallet");
@@ -357,7 +358,7 @@ walletCli
requestJson = JSON.parse(args.api.request);
} catch (e) {
console.error("Invalid JSON");
- process.exit(1);
+ processExit(1);
}
try {
const resp = await wallet.makeCoreApiRequest(
@@ -367,12 +368,12 @@ walletCli
console.log(JSON.stringify(resp, undefined, 2));
if (resp.type === "error") {
if (args.api.expectSuccess) {
- process.exit(EXIT_API_ERROR);
+ processExit(EXIT_API_ERROR);
}
}
} catch (e) {
logger.error(`Got exception while handling API request ${e}`);
- process.exit(EXIT_EXCEPTION);
+ processExit(EXIT_EXCEPTION);
}
});
logger.info("finished handling API request");
@@ -475,7 +476,7 @@ walletCli
});
wallet.ws.stop();
if (resp.retriesExceeded && args.finishPendingOpt.failOnMaxRetries) {
- process.exit(EXIT_RETRIES_EXCEEDED);
+ processExit(EXIT_RETRIES_EXCEEDED);
}
});
});
@@ -594,7 +595,7 @@ walletCli
const selectedExchange = withdrawInfo.defaultExchangeBaseUrl;
if (!selectedExchange) {
console.error("no suggested exchange!");
- process.exit(1);
+ processExit(1);
return;
}
const res = await wallet.client.call(
@@ -1014,9 +1015,10 @@ advancedCli
help: "Run the 'bench-internal' benchmark",
})
.action(async (args) => {
- const myHttpLib = new NodeHttpLib();
- myHttpLib.setThrottling(false);
- const res = await getDefaultNodeWallet2({
+ const myHttpLib = createPlatformHttpLib({
+ enableThrottling: false,
+ });
+ const res = await createNativeWalletHost2({
// No persistent DB storage.
persistentStoragePath: undefined,
httpLib: myHttpLib,
@@ -1061,15 +1063,6 @@ advancedCli
});
advancedCli
- .subcommand("decode", "decode", {
- help: "Decode base32-crockford.",
- })
- .action((args) => {
- const enc = fs.readFileSync(0, "utf8");
- console.log(decodeCrock(enc.trim()));
- });
-
-advancedCli
.subcommand("genSegwit", "gen-segwit")
.requiredArgument("paytoUri", clk.STRING)
.requiredArgument("reservePub", clk.STRING)
@@ -1229,7 +1222,7 @@ advancedCli
);
} catch (e: any) {
console.log("could not parse coin list:", e.message);
- process.exit(1);
+ processExit(1);
}
for (const c of coinPubList) {
await wallet.client.call(WalletApiOperation.SetCoinSuspended, {
@@ -1254,7 +1247,7 @@ advancedCli
);
} catch (e: any) {
console.log("could not parse coin list:", e.message);
- process.exit(1);
+ processExit(1);
}
for (const c of coinPubList) {
await wallet.client.call(WalletApiOperation.SetCoinSuspended, {
@@ -1420,33 +1413,33 @@ async function read(stream: NodeJS.ReadStream) {
return Buffer.concat(chunks).toString("utf8");
}
-testCli
- .subcommand("cryptoworker", "cryptoworker")
- .maybeOption("impl", ["--impl"], clk.STRING)
- .action(async (args) => {
- let cryptoApi: TalerCryptoInterface;
- if (!args.cryptoworker.impl || args.cryptoworker.impl === "node") {
- const workerFactory = new NodeThreadCryptoWorkerFactory();
- const cryptoDisp = new CryptoDispatcher(workerFactory);
- cryptoApi = cryptoDisp.cryptoApi;
- } else if (args.cryptoworker.impl === "sync") {
- const workerFactory = new SynchronousCryptoWorkerFactoryNode();
- const cryptoDisp = new CryptoDispatcher(workerFactory);
- cryptoApi = cryptoDisp.cryptoApi;
- } else if (args.cryptoworker.impl === "none") {
- cryptoApi = nativeCrypto;
- } else {
- throw Error(`invalid crypto worker type ${args.cryptoworker.impl}`);
- }
-
- const input = "foo";
- console.log(`testing crypto worker by hashing string '${input}'`);
- const res = await cryptoApi.hashString({ str: input });
- console.log(res);
- });
+// testCli
+// .subcommand("cryptoworker", "cryptoworker")
+// .maybeOption("impl", ["--impl"], clk.STRING)
+// .action(async (args) => {
+// let cryptoApi: TalerCryptoInterface;
+// if (!args.cryptoworker.impl || args.cryptoworker.impl === "node") {
+// const workerFactory = new NodeThreadCryptoWorkerFactory();
+// const cryptoDisp = new CryptoDispatcher(workerFactory);
+// cryptoApi = cryptoDisp.cryptoApi;
+// } else if (args.cryptoworker.impl === "sync") {
+// const workerFactory = new SynchronousCryptoWorkerFactoryPlain();
+// const cryptoDisp = new CryptoDispatcher(workerFactory);
+// cryptoApi = cryptoDisp.cryptoApi;
+// } else if (args.cryptoworker.impl === "none") {
+// cryptoApi = nativeCrypto;
+// } else {
+// throw Error(`invalid crypto worker type ${args.cryptoworker.impl}`);
+// }
+
+// const input = "foo";
+// console.log(`testing crypto worker by hashing string '${input}'`);
+// const res = await cryptoApi.hashString({ str: input });
+// console.log(res);
+// });
export function main() {
- if (process.env["TALER_WALLET_DEBUG_DENOMSEL_ALLOW_LATE"]) {
+ if (getenv("TALER_WALLET_DEBUG_DENOMSEL_ALLOW_LATE")) {
logger.warn("Allowing withdrawal of late denominations for debugging");
walletCoreDebugFlags.denomselAllowLate = true;
}
diff --git a/packages/taler-wallet-core/package.json b/packages/taler-wallet-core/package.json
index 4f1692872..72b4eb410 100644
--- a/packages/taler-wallet-core/package.json
+++ b/packages/taler-wallet-core/package.json
@@ -38,7 +38,13 @@
"default": "./lib/index.js"
},
"./remote": {
- "node": "./lib/remote.js"
+ "default": "./lib/remote.js"
+ }
+ },
+ "imports": {
+ "#host-impl": {
+ "node": "./lib/host-impl.node.js",
+ "qtart": "./lib/host-impl.qtart.js"
}
},
"devDependencies": {
diff --git a/packages/taler-wallet-core/src/bank-api-client.ts b/packages/taler-wallet-core/src/bank-api-client.ts
index dc7845150..addec709f 100644
--- a/packages/taler-wallet-core/src/bank-api-client.ts
+++ b/packages/taler-wallet-core/src/bank-api-client.ts
@@ -33,13 +33,10 @@ import {
j2s,
Logger,
stringToBytes,
+ TalerError,
TalerErrorCode,
} from "@gnu-taler/taler-util";
-import { TalerError } from "./errors.js";
-import {
- HttpRequestLibrary,
- readSuccessResponseJsonOrThrow,
-} from "./util/http.js";
+import { HttpRequestLibrary, readSuccessResponseJsonOrThrow } from "@gnu-taler/taler-util/http";
const logger = new Logger("bank-api-client.ts");
diff --git a/packages/taler-wallet-core/src/crypto/workers/crypto-dispatcher.test.ts b/packages/taler-wallet-core/src/crypto/workers/crypto-dispatcher.test.ts
index d8d53a839..1e9d82f66 100644
--- a/packages/taler-wallet-core/src/crypto/workers/crypto-dispatcher.test.ts
+++ b/packages/taler-wallet-core/src/crypto/workers/crypto-dispatcher.test.ts
@@ -21,8 +21,6 @@ import {
CryptoWorker,
CryptoWorkerResponseMessage,
} from "./cryptoWorkerInterface.js";
-import { SynchronousCryptoWorkerFactoryNode } from "./synchronousWorkerFactoryNode.js";
-import { processRequestWithImpl } from "./worker-common.js";
export class MyCryptoWorker implements CryptoWorker {
/**
diff --git a/packages/taler-wallet-core/src/crypto/workers/crypto-dispatcher.ts b/packages/taler-wallet-core/src/crypto/workers/crypto-dispatcher.ts
index f086691e5..192e9cda1 100644
--- a/packages/taler-wallet-core/src/crypto/workers/crypto-dispatcher.ts
+++ b/packages/taler-wallet-core/src/crypto/workers/crypto-dispatcher.ts
@@ -24,7 +24,7 @@
* Imports.
*/
import { j2s, Logger, TalerErrorCode } from "@gnu-taler/taler-util";
-import { TalerError } from "../../errors.js";
+import { TalerError } from "@gnu-taler/taler-util";
import { openPromise } from "../../util/promiseUtils.js";
import { timer, performanceNow, TimerHandle } from "../../util/timer.js";
import { nullCrypto, TalerCryptoInterface } from "../cryptoImplementation.js";
diff --git a/packages/taler-wallet-core/src/crypto/workers/rpcClient.ts b/packages/taler-wallet-core/src/crypto/workers/rpcClient.ts
deleted file mode 100644
index 21d88fffa..000000000
--- a/packages/taler-wallet-core/src/crypto/workers/rpcClient.ts
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2022 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 { Logger } from "@gnu-taler/taler-util";
-import child_process from "child_process";
-import type internal from "stream";
-import { OpenedPromise, openPromise } from "../../util/promiseUtils.js";
-
-const logger = new Logger("synchronousWorkerFactory.ts");
-
-/**
- * Client for the crypto helper process (taler-crypto-worker from exchange.git).
- */
-export class CryptoRpcClient {
- proc: child_process.ChildProcessByStdio<
- internal.Writable,
- internal.Readable,
- null
- >;
- requests: Array<{
- p: OpenedPromise<any>;
- req: any;
- }> = [];
-
- constructor() {
- const stdoutChunks: Buffer[] = [];
- this.proc = child_process.spawn("taler-crypto-worker", {
- //stdio: ["pipe", "pipe", "inherit"],
- stdio: ["pipe", "pipe", "inherit"],
- detached: true,
- });
- this.proc.on("close", (): void => {
- logger.error("child process exited");
- });
- (this.proc.stdout as any).unref();
- (this.proc.stdin as any).unref();
- this.proc.unref();
-
- this.proc.stdout.on("data", (x) => {
- if (x instanceof Buffer) {
- const nlIndex = x.indexOf("\n");
- if (nlIndex >= 0) {
- const before = x.slice(0, nlIndex);
- const after = x.slice(nlIndex + 1);
- stdoutChunks.push(after);
- const str = Buffer.concat([...stdoutChunks, before]).toString(
- "utf-8",
- );
- const req = this.requests.shift();
- if (!req) {
- throw Error("request was undefined");
- }
- if (this.requests.length === 0) {
- this.proc.unref();
- }
- //logger.info(`got response: ${str}`);
- req.p.resolve(JSON.parse(str));
- } else {
- stdoutChunks.push(x);
- }
- } else {
- throw Error(`unexpected data chunk type (${typeof x})`);
- }
- });
- }
-
- async queueRequest(req: any): Promise<any> {
- const p = openPromise<any>();
- if (this.requests.length === 0) {
- this.proc.ref();
- }
- this.requests.push({ req, p });
- this.proc.stdin.write(`${JSON.stringify(req)}\n`);
- return p.promise;
- }
-}
diff --git a/packages/taler-wallet-core/src/crypto/workers/synchronousWorkerNode.ts b/packages/taler-wallet-core/src/crypto/workers/synchronousWorkerNode.ts
deleted file mode 100644
index b2653158c..000000000
--- a/packages/taler-wallet-core/src/crypto/workers/synchronousWorkerNode.ts
+++ /dev/null
@@ -1,174 +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/>
- */
-
-import { j2s, Logger } from "@gnu-taler/taler-util";
-import {
- nativeCryptoR,
- TalerCryptoInterfaceR,
-} from "../cryptoImplementation.js";
-import { CryptoWorker } from "./cryptoWorkerInterface.js";
-import { CryptoRpcClient } from "./rpcClient.js";
-import { processRequestWithImpl } from "./worker-common.js";
-
-const logger = new Logger("synchronousWorker.ts");
-
-/**
- * Worker implementation that uses node subprocesses.
- *
- * The node crypto worker can also use IPC to offload cryptographic
- * operations to a helper process (usually written in C / part of taler-exchange).
- */
-export class SynchronousCryptoWorkerNode implements CryptoWorker {
- /**
- * Function to be called when we receive a message from the worker thread.
- */
- onmessage: undefined | ((m: any) => void);
-
- /**
- * Function to be called when we receive an error from the worker thread.
- */
- onerror: undefined | ((m: any) => void);
-
- cryptoImplR: TalerCryptoInterfaceR;
-
- rpcClient: CryptoRpcClient | undefined;
-
- constructor() {
- this.onerror = undefined;
- this.onmessage = undefined;
-
- this.cryptoImplR = { ...nativeCryptoR };
-
- if (process.env["TALER_WALLET_PRIMITIVE_WORKER"]) {
- logger.info("using RPC for some crypto operations");
- const rpc = (this.rpcClient = new CryptoRpcClient());
- this.cryptoImplR.eddsaSign = async (_, req) => {
- return await rpc.queueRequest({
- op: "eddsa_sign",
- args: {
- msg: req.msg,
- priv: req.priv,
- },
- });
- };
- this.cryptoImplR.setupRefreshPlanchet = async (_, req) => {
- const res = await rpc.queueRequest({
- op: "setup_refresh_planchet",
- args: {
- coin_index: req.coinNumber,
- transfer_secret: req.transferSecret,
- },
- });
- return {
- bks: res.blinding_key,
- coinPriv: res.coin_priv,
- coinPub: res.coin_pub,
- };
- };
- this.cryptoImplR.rsaBlind = async (_, req) => {
- const res = await rpc.queueRequest({
- op: "rsa_blind",
- args: {
- bks: req.bks,
- hm: req.hm,
- pub: req.pub,
- },
- });
- return {
- blinded: res.blinded,
- };
- };
- this.cryptoImplR.keyExchangeEcdheEddsa = async (_, req) => {
- const res = await rpc.queueRequest({
- op: "kx_ecdhe_eddsa",
- args: {
- ecdhe_priv: req.ecdhePriv,
- eddsa_pub: req.eddsaPub,
- },
- });
- return {
- h: res.h,
- };
- };
- this.cryptoImplR.eddsaGetPublic = async (_, req) => {
- const res = await rpc.queueRequest({
- op: "eddsa_get_public",
- args: {
- eddsa_priv: req.priv,
- },
- });
- return {
- pub: res.eddsa_pub,
- };
- };
- this.cryptoImplR.ecdheGetPublic = async (_, req) => {
- const res = await rpc.queueRequest({
- op: "ecdhe_get_public",
- args: {
- ecdhe_priv: req.priv,
- },
- });
- return {
- pub: res.ecdhe_pub,
- };
- };
- }
- }
-
- /**
- * Add an event listener for either an "error" or "message" event.
- */
- addEventListener(event: "message" | "error", fn: (x: any) => void): void {
- switch (event) {
- case "message":
- this.onmessage = fn;
- break;
- case "error":
- this.onerror = fn;
- break;
- }
- }
-
- private dispatchMessage(msg: any): void {
- if (this.onmessage) {
- this.onmessage(msg);
- }
- }
-
- /**
- * Send a message to the worker thread.
- */
- postMessage(msg: any): void {
- const handleRequest = async () => {
- const responseMsg = await processRequestWithImpl(msg, this.cryptoImplR);
- try {
- setTimeout(() => this.dispatchMessage(responseMsg), 0);
- } catch (e) {
- logger.error("got error during dispatch", e);
- }
- };
- handleRequest().catch((e) => {
- logger.error("Error while handling crypto request:", e);
- });
- }
-
- /**
- * Forcibly terminate the worker thread.
- */
- terminate(): void {
- // This is a no-op.
- }
-}
diff --git a/packages/taler-wallet-core/src/crypto/workers/worker-common.ts b/packages/taler-wallet-core/src/crypto/workers/worker-common.ts
index 8a74a5231..9f23cf685 100644
--- a/packages/taler-wallet-core/src/crypto/workers/worker-common.ts
+++ b/packages/taler-wallet-core/src/crypto/workers/worker-common.ts
@@ -23,7 +23,7 @@ import {
stringifyError as safeStringifyError,
TalerErrorCode,
} from "@gnu-taler/taler-util";
-import { getErrorDetailFromException, makeErrorDetail } from "../../errors.js";
+import { getErrorDetailFromException, makeErrorDetail } from "@gnu-taler/taler-util";
import { TalerCryptoInterfaceR } from "../cryptoImplementation.js";
import {
CryptoWorkerRequestMessage,
diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts
index 8bb8d519f..75e6408f7 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -2659,6 +2659,9 @@ function onMetaDbUpgradeNeeded(
/**
* Return a promise that resolves
* to the taler wallet db.
+ *
+ * @param onVersionChange Called when another client concurrenctly connects to the database
+ * with a higher version.
*/
export async function openTalerDatabase(
idbFactory: IDBFactory,
diff --git a/packages/taler-wallet-core/src/dbless.ts b/packages/taler-wallet-core/src/dbless.ts
index 544e2d458..99596edd8 100644
--- a/packages/taler-wallet-core/src/dbless.ts
+++ b/packages/taler-wallet-core/src/dbless.ts
@@ -58,7 +58,7 @@ import {
import {
HttpRequestLibrary,
readSuccessResponseJsonOrThrow,
-} from "./util/http.js";
+} from "@gnu-taler/taler-util/http";
import {
getBankStatusUrl,
getBankWithdrawalInfo,
diff --git a/packages/taler-wallet-core/src/dev-experiments.ts b/packages/taler-wallet-core/src/dev-experiments.ts
index 6c36d6f6c..3e6194ccd 100644
--- a/packages/taler-wallet-core/src/dev-experiments.ts
+++ b/packages/taler-wallet-core/src/dev-experiments.ts
@@ -32,7 +32,7 @@ import {
HttpRequestLibrary,
HttpRequestOptions,
HttpResponse,
-} from "./util/http.js";
+} from "@gnu-taler/taler-util/http";
const logger = new Logger("dev-experiments.ts");
diff --git a/packages/taler-wallet-core/src/headless/NodeHttpLib.ts b/packages/taler-wallet-core/src/headless/NodeHttpLib.ts
deleted file mode 100644
index c1d42796d..000000000
--- a/packages/taler-wallet-core/src/headless/NodeHttpLib.ts
+++ /dev/null
@@ -1,183 +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/>
-
- SPDX-License-Identifier: AGPL3.0-or-later
-*/
-
-/**
- * Imports.
- */
-import {
- DEFAULT_REQUEST_TIMEOUT_MS,
- Headers,
- HttpRequestLibrary,
- HttpRequestOptions,
- HttpResponse,
-} from "../util/http.js";
-import { RequestThrottler } from "@gnu-taler/taler-util";
-import axios, { AxiosResponse } from "axios";
-import { TalerError } from "../errors.js";
-import { Logger, bytesToString } from "@gnu-taler/taler-util";
-import { TalerErrorCode, URL } from "@gnu-taler/taler-util";
-
-const logger = new Logger("NodeHttpLib.ts");
-
-/**
- * Implementation of the HTTP request library interface for node.
- */
-export class NodeHttpLib implements HttpRequestLibrary {
- private throttle = new RequestThrottler();
- private throttlingEnabled = true;
-
- /**
- * Set whether requests should be throttled.
- */
- setThrottling(enabled: boolean): void {
- this.throttlingEnabled = enabled;
- }
-
- async fetch(url: string, opt?: HttpRequestOptions): Promise<HttpResponse> {
- const method = opt?.method ?? "GET";
- let body = opt?.body;
-
- logger.trace(`Requesting ${method} ${url}`);
-
- const parsedUrl = new URL(url);
- if (this.throttlingEnabled && this.throttle.applyThrottle(url)) {
- throw TalerError.fromDetail(
- TalerErrorCode.WALLET_HTTP_REQUEST_THROTTLED,
- {
- requestMethod: method,
- requestUrl: url,
- throttleStats: this.throttle.getThrottleStats(url),
- },
- `request to origin ${parsedUrl.origin} was throttled`,
- );
- }
- let timeoutMs: number | undefined;
- if (typeof opt?.timeout?.d_ms === "number") {
- timeoutMs = opt.timeout.d_ms;
- } else {
- timeoutMs = DEFAULT_REQUEST_TIMEOUT_MS;
- }
- // FIXME: Use AbortController / etc. to handle cancellation
- let resp: AxiosResponse;
- try {
- let respPromise = axios.default({
- method,
- url: url,
- responseType: "arraybuffer",
- headers: opt?.headers,
- validateStatus: () => true,
- transformResponse: (x) => x,
- data: body,
- timeout: timeoutMs,
- maxRedirects: 0,
- });
- if (opt?.cancellationToken) {
- respPromise = opt.cancellationToken.racePromise(respPromise);
- }
- resp = await respPromise;
- } catch (e: any) {
- throw TalerError.fromDetail(
- TalerErrorCode.WALLET_NETWORK_ERROR,
- {
- requestUrl: url,
- requestMethod: method,
- },
- `${e.message}`,
- );
- }
-
- const makeText = async (): Promise<string> => {
- opt?.cancellationToken?.throwIfCancelled();
- const respText = new Uint8Array(resp.data);
- return bytesToString(respText);
- };
-
- const makeJson = async (): Promise<any> => {
- opt?.cancellationToken?.throwIfCancelled();
- let responseJson;
- const respText = await makeText();
- try {
- responseJson = JSON.parse(respText);
- } catch (e) {
- logger.trace(`invalid json: '${resp.data}'`);
- throw TalerError.fromDetail(
- TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
- {
- httpStatusCode: resp.status,
- requestUrl: url,
- requestMethod: method,
- },
- "Could not parse response body as JSON",
- );
- }
- if (responseJson === null || typeof responseJson !== "object") {
- logger.trace(`invalid json (not an object): '${respText}'`);
- throw TalerError.fromDetail(
- TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
- {
- httpStatusCode: resp.status,
- requestUrl: url,
- requestMethod: method,
- },
- `invalid JSON`,
- );
- }
- return responseJson;
- };
- const makeBytes = async () => {
- opt?.cancellationToken?.throwIfCancelled();
- if (typeof resp.data.byteLength !== "number") {
- throw Error("expected array buffer");
- }
- const buf = resp.data;
- return buf;
- };
- const headers = new Headers();
- for (const hn of Object.keys(resp.headers)) {
- headers.set(hn, resp.headers[hn]);
- }
- return {
- requestUrl: url,
- requestMethod: method,
- headers,
- status: resp.status,
- text: makeText,
- json: makeJson,
- bytes: makeBytes,
- };
- }
-
- async get(url: string, opt?: HttpRequestOptions): Promise<HttpResponse> {
- return this.fetch(url, {
- method: "GET",
- ...opt,
- });
- }
-
- async postJson(
- url: string,
- body: any,
- opt?: HttpRequestOptions,
- ): Promise<HttpResponse> {
- return this.fetch(url, {
- method: "POST",
- body,
- ...opt,
- });
- }
-}
diff --git a/packages/taler-wallet-core/src/host-common.ts b/packages/taler-wallet-core/src/host-common.ts
new file mode 100644
index 000000000..7651e5a12
--- /dev/null
+++ b/packages/taler-wallet-core/src/host-common.ts
@@ -0,0 +1,60 @@
+/*
+ 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/>
+ */
+
+import { WalletNotification } from "@gnu-taler/taler-util";
+import { HttpRequestLibrary } from "@gnu-taler/taler-util/http";
+
+/**
+ * Helpers to initiate a wallet in a host environment.
+ */
+
+/**
+ */
+export interface DefaultNodeWalletArgs {
+ /**
+ * Location of the wallet database.
+ *
+ * If not specified, the wallet starts out with an empty database and
+ * the wallet database is stored only in memory.
+ */
+ persistentStoragePath?: string;
+
+ /**
+ * Handler for asynchronous notifications from the wallet.
+ */
+ notifyHandler?: (n: WalletNotification) => void;
+
+ /**
+ * If specified, use this as HTTP request library instead
+ * of the default one.
+ */
+ httpLib?: HttpRequestLibrary;
+
+ cryptoWorkerType?: "sync" | "node-worker-thread";
+}
+
+/**
+ * Generate a random alphanumeric ID. Does *not* use cryptographically
+ * secure randomness.
+ */
+export function makeTempfileId(length: number): string {
+ let result = "";
+ const characters = "abcdefghijklmnopqrstuvwxyz0123456789";
+ for (let i = 0; i < length; i++) {
+ result += characters.charAt(Math.floor(Math.random() * characters.length));
+ }
+ return result;
+}
diff --git a/packages/taler-wallet-core/src/headless/helpers.ts b/packages/taler-wallet-core/src/host-impl.node.ts
index fbeb84c67..ec57e0ebe 100644
--- a/packages/taler-wallet-core/src/headless/helpers.ts
+++ b/packages/taler-wallet-core/src/host-impl.node.ts
@@ -30,70 +30,27 @@ import {
shimIndexedDB,
} from "@gnu-taler/idb-bridge";
import { AccessStats } from "@gnu-taler/idb-bridge";
-import { Logger, WalletNotification } from "@gnu-taler/taler-util";
+import { Logger } from "@gnu-taler/taler-util";
import * as fs from "fs";
-import { NodeThreadCryptoWorkerFactory } from "../crypto/workers/nodeThreadWorker.js";
-import { SynchronousCryptoWorkerFactoryNode } from "../crypto/workers/synchronousWorkerFactoryNode.js";
-import { openTalerDatabase } from "../index.js";
-import { HttpRequestLibrary } from "../util/http.js";
-import { SetTimeoutTimerAPI } from "../util/timer.js";
-import { Wallet } from "../wallet.js";
-import { NodeHttpLib } from "./NodeHttpLib.js";
-
-const logger = new Logger("headless/helpers.ts");
-
-export interface DefaultNodeWalletArgs {
- /**
- * Location of the wallet database.
- *
- * If not specified, the wallet starts out with an empty database and
- * the wallet database is stored only in memory.
- */
- persistentStoragePath?: string;
-
- /**
- * Handler for asynchronous notifications from the wallet.
- */
- notifyHandler?: (n: WalletNotification) => void;
-
- /**
- * If specified, use this as HTTP request library instead
- * of the default one.
- */
- httpLib?: HttpRequestLibrary;
-
- cryptoWorkerType?: "sync" | "node-worker-thread";
-}
+import { NodeThreadCryptoWorkerFactory } from "./crypto/workers/nodeThreadWorker.js";
+import { SynchronousCryptoWorkerFactoryPlain } from "./crypto/workers/synchronousWorkerFactoryPlain.js";
+import { openTalerDatabase } from "./index.js";
+import {
+ createPlatformHttpLib,
+} from "@gnu-taler/taler-util/http";
+import { SetTimeoutTimerAPI } from "./util/timer.js";
+import { Wallet } from "./wallet.js";
+import { DefaultNodeWalletArgs, makeTempfileId } from "./host-common.js";
-/**
- * Generate a random alphanumeric ID. Does *not* use cryptographically
- * secure randomness.
- */
-function makeId(length: number): string {
- let result = "";
- const characters = "abcdefghijklmnopqrstuvwxyz0123456789";
- for (let i = 0; i < length; i++) {
- result += characters.charAt(Math.floor(Math.random() * characters.length));
- }
- return result;
-}
+const logger = new Logger("host-impl.node.ts");
-/**
- * Get a wallet instance with default settings for node.
- */
-export async function getDefaultNodeWallet(
- args: DefaultNodeWalletArgs = {},
-): Promise<Wallet> {
- const res = await getDefaultNodeWallet2(args);
- return res.wallet;
-}
/**
* Get a wallet instance with default settings for node.
*
* Extended version that allows getting DB stats.
*/
-export async function getDefaultNodeWallet2(
+export async function createNativeWalletHost2(
args: DefaultNodeWalletArgs = {},
): Promise<{
wallet: Wallet;
@@ -127,7 +84,8 @@ export async function getDefaultNodeWallet2(
if (args.persistentStoragePath === undefined) {
return;
}
- const tmpPath = `${args.persistentStoragePath}-${makeId(5)}.tmp`;
+ const tmpPath = `${args.persistentStoragePath}-${makeTempfileId(5)}.tmp`;
+ logger.trace("exported DB dump");
const dbContent = myBackend.exportDump();
fs.writeFileSync(tmpPath, JSON.stringify(dbContent, undefined, 2), {
encoding: "utf-8",
@@ -147,7 +105,9 @@ export async function getDefaultNodeWallet2(
if (args.httpLib) {
myHttpLib = args.httpLib;
} else {
- myHttpLib = new NodeHttpLib();
+ myHttpLib = createPlatformHttpLib({
+ enableThrottling: true,
+ });
}
const myVersionChange = (): Promise<void> => {
@@ -165,7 +125,7 @@ export async function getDefaultNodeWallet2(
const cryptoWorkerType = args.cryptoWorkerType ?? "node-worker-thread";
if (cryptoWorkerType === "sync") {
logger.info("using synchronous crypto worker");
- workerFactory = new SynchronousCryptoWorkerFactoryNode();
+ workerFactory = new SynchronousCryptoWorkerFactoryPlain();
} else if (cryptoWorkerType === "node-worker-thread") {
try {
// Try if we have worker threads available, fails in older node versions.
@@ -179,7 +139,7 @@ export async function getDefaultNodeWallet2(
logger.warn(
"worker threads not available, falling back to synchronous workers",
);
- workerFactory = new SynchronousCryptoWorkerFactoryNode();
+ workerFactory = new SynchronousCryptoWorkerFactoryPlain();
}
} else {
throw Error(`unsupported crypto worker type '${cryptoWorkerType}'`);
diff --git a/packages/taler-wallet-core/src/host-impl.qtart.ts b/packages/taler-wallet-core/src/host-impl.qtart.ts
new file mode 100644
index 000000000..337914292
--- /dev/null
+++ b/packages/taler-wallet-core/src/host-impl.qtart.ts
@@ -0,0 +1,120 @@
+/*
+ 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/>
+ */
+
+/**
+ * Helpers to create headless wallets.
+ * @author Florian Dold <dold@taler.net>
+ */
+
+/**
+ * Imports.
+ */
+import type { IDBFactory } from "@gnu-taler/idb-bridge";
+// eslint-disable-next-line no-duplicate-imports
+import {
+ BridgeIDBFactory,
+ MemoryBackend,
+ shimIndexedDB,
+} from "@gnu-taler/idb-bridge";
+import { AccessStats } from "@gnu-taler/idb-bridge";
+import { SynchronousCryptoWorkerFactoryPlain } from "./crypto/workers/synchronousWorkerFactoryPlain.js";
+import { openTalerDatabase } from "./index.js";
+import { Logger } from "@gnu-taler/taler-util";
+import { createPlatformHttpLib } from "@gnu-taler/taler-util/http";
+import { SetTimeoutTimerAPI } from "./util/timer.js";
+import { Wallet } from "./wallet.js";
+import { qjsOs, qjsStd } from "@gnu-taler/taler-util/qtart";
+import { DefaultNodeWalletArgs, makeTempfileId } from "./host-common.js";
+
+const logger = new Logger("host-impl.qtart.ts");
+
+export async function createNativeWalletHost2(
+ args: DefaultNodeWalletArgs = {},
+): Promise<{
+ wallet: Wallet;
+ getDbStats: () => AccessStats;
+}> {
+ BridgeIDBFactory.enableTracing = false;
+ const myBackend = new MemoryBackend();
+ myBackend.enableTracing = false;
+
+ const storagePath = args.persistentStoragePath;
+ if (storagePath) {
+ const dbContentStr = qjsStd.loadFile(storagePath);
+ if (dbContentStr != null) {
+ const dbContent = JSON.parse(dbContentStr);
+ myBackend.importDump(dbContent);
+ }
+
+ myBackend.afterCommitCallback = async () => {
+ logger.trace("committing database");
+ // Allow caller to stop persisting the wallet.
+ if (args.persistentStoragePath === undefined) {
+ return;
+ }
+ const tmpPath = `${args.persistentStoragePath}-${makeTempfileId(5)}.tmp`;
+ const dbContent = myBackend.exportDump();
+ logger.trace("exported DB dump");
+ qjsStd.writeFile(tmpPath, JSON.stringify(dbContent, undefined, 2));
+ // Atomically move the temporary file onto the DB path.
+ const res = qjsOs.rename(tmpPath, args.persistentStoragePath);
+ if (res != 0) {
+ throw Error("db commit failed at rename");
+ }
+ logger.trace("committing database done");
+ };
+ }
+
+ logger.info("done processing storage path");
+
+ BridgeIDBFactory.enableTracing = false;
+
+ const myBridgeIdbFactory = new BridgeIDBFactory(myBackend);
+ const myIdbFactory: IDBFactory = myBridgeIdbFactory as any as IDBFactory;
+
+ let myHttpLib;
+ if (args.httpLib) {
+ myHttpLib = args.httpLib;
+ } else {
+ myHttpLib = createPlatformHttpLib();
+ }
+
+ const myVersionChange = (): Promise<void> => {
+ logger.error("version change requested, should not happen");
+ throw Error(
+ "BUG: wallet DB version change event can't happen with memory IDB",
+ );
+ };
+
+ shimIndexedDB(myBridgeIdbFactory);
+
+ const myDb = await openTalerDatabase(myIdbFactory, myVersionChange);
+
+ let workerFactory;
+ workerFactory = new SynchronousCryptoWorkerFactoryPlain();
+
+ const timer = new SetTimeoutTimerAPI();
+
+ const w = await Wallet.create(myDb, myHttpLib, timer, workerFactory);
+
+ if (args.notifyHandler) {
+ w.addNotificationListener(args.notifyHandler);
+ }
+ return {
+ wallet: w,
+ getDbStats: () => myBackend.accessStats,
+ };
+}
diff --git a/packages/taler-wallet-core/src/host.ts b/packages/taler-wallet-core/src/host.ts
new file mode 100644
index 000000000..4b319f081
--- /dev/null
+++ b/packages/taler-wallet-core/src/host.ts
@@ -0,0 +1,47 @@
+/*
+ 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/>
+ */
+
+import { DefaultNodeWalletArgs } from "./host-common.js";
+import { Wallet } from "./index.js";
+
+import * as hostImpl from "#host-impl";
+import { AccessStats } from "@gnu-taler/idb-bridge";
+
+/**
+ * Helpers to initiate a wallet in a host environment.
+ */
+
+/**
+ * Get a wallet instance.
+ */
+export async function createNativeWalletHost2(
+ args: DefaultNodeWalletArgs = {},
+): Promise<{
+ wallet: Wallet;
+ getDbStats: () => AccessStats;
+}> {
+ return hostImpl.createNativeWalletHost2(args);
+}
+
+/**
+ * Get a wallet instance.
+ */
+export async function createNativeWalletHost(
+ args: DefaultNodeWalletArgs = {},
+): Promise<Wallet> {
+ const res = await hostImpl.createNativeWalletHost2(args);
+ return res.wallet;
+}
diff --git a/packages/taler-wallet-core/src/index.node.ts b/packages/taler-wallet-core/src/index.node.ts
index 8567d13ac..13392d39c 100644
--- a/packages/taler-wallet-core/src/index.node.ts
+++ b/packages/taler-wallet-core/src/index.node.ts
@@ -16,15 +16,8 @@
export * from "./index.js";
-// Utils for using the wallet under node
-export { NodeHttpLib } from "./headless/NodeHttpLib.js";
-export {
- getDefaultNodeWallet,
- getDefaultNodeWallet2,
- DefaultNodeWalletArgs,
-} from "./headless/helpers.js";
export * from "./crypto/workers/nodeThreadWorker.js";
-export { SynchronousCryptoWorkerNode as SynchronousCryptoWorker } from "./crypto/workers/synchronousWorkerNode.js";
+export { SynchronousCryptoWorkerPlain } from "./crypto/workers/synchronousWorkerPlain.js";
export type { AccessStats } from "@gnu-taler/idb-bridge";
-export * from "./crypto/workers/synchronousWorkerFactoryNode.js";
+export * from "./crypto/workers/synchronousWorkerFactoryPlain.js";
diff --git a/packages/taler-wallet-core/src/index.ts b/packages/taler-wallet-core/src/index.ts
index 031656a6c..7b21d8f91 100644
--- a/packages/taler-wallet-core/src/index.ts
+++ b/packages/taler-wallet-core/src/index.ts
@@ -18,13 +18,9 @@
* Module entry point for the wallet when used as a node module.
*/
-// Errors
-export * from "./errors.js";
-
// Util functionality
export * from "./util/promiseUtils.js";
export * from "./util/query.js";
-export * from "./util/http.js";
export * from "./versions.js";
@@ -67,3 +63,5 @@ export * from "./util/timer.js";
export * from "./util/denominations.js";
export { SynchronousCryptoWorkerFactoryPlain } from "./crypto/workers/synchronousWorkerFactoryPlain.js";
+export * from "./host-common.js";
+export * from "./host.js";
diff --git a/packages/taler-wallet-core/src/internal-wallet-state.ts b/packages/taler-wallet-core/src/internal-wallet-state.ts
index d180861f8..8434c3b8f 100644
--- a/packages/taler-wallet-core/src/internal-wallet-state.ts
+++ b/packages/taler-wallet-core/src/internal-wallet-state.ts
@@ -30,18 +30,14 @@
* Imports.
*/
import {
- WalletNotification,
- BalancesResponse,
- AmountJson,
- DenominationPubKey,
- TalerProtocolTimestamp,
CancellationToken,
+ CoinRefreshRequest,
DenominationInfo,
RefreshGroupId,
- CoinRefreshRequest,
RefreshReason,
+ WalletNotification,
} from "@gnu-taler/taler-util";
-import { CryptoDispatcher } from "./crypto/workers/crypto-dispatcher.js";
+import { HttpRequestLibrary } from "@gnu-taler/taler-util/http";
import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js";
import {
ExchangeDetailsRecord,
@@ -49,9 +45,6 @@ import {
RefreshReasonDetails,
WalletStoresV1,
} from "./db.js";
-import { PendingOperationsResponse } from "./pending-types.js";
-import { AsyncOpMemoMap, AsyncOpMemoSingle } from "./util/asyncMemo.js";
-import { HttpRequestLibrary } from "./util/http.js";
import { AsyncCondition } from "./util/promiseUtils.js";
import {
DbAccess,
diff --git a/packages/taler-wallet-core/src/operations/backup/index.ts b/packages/taler-wallet-core/src/operations/backup/index.ts
index 7d3953ebb..3dae26087 100644
--- a/packages/taler-wallet-core/src/operations/backup/index.ts
+++ b/packages/taler-wallet-core/src/operations/backup/index.ts
@@ -85,13 +85,13 @@ import {
ConfigRecordKey,
WalletBackupConfState,
} from "../../db.js";
-import { TalerError } from "../../errors.js";
+import { TalerError } from "@gnu-taler/taler-util";
import { InternalWalletState } from "../../internal-wallet-state.js";
import { assertUnreachable } from "../../util/assertUnreachable.js";
import {
readSuccessResponseJsonOrThrow,
readTalerErrorResponse,
-} from "../../util/http.js";
+} from "@gnu-taler/taler-util/http";
import {
checkDbInvariant,
checkLogicInvariant,
diff --git a/packages/taler-wallet-core/src/operations/common.ts b/packages/taler-wallet-core/src/operations/common.ts
index 3ea02012b..e61a6fe95 100644
--- a/packages/taler-wallet-core/src/operations/common.ts
+++ b/packages/taler-wallet-core/src/operations/common.ts
@@ -42,7 +42,7 @@ import {
ExchangeDetailsRecord,
ExchangeRecord,
} from "../db.js";
-import { makeErrorDetail, TalerError } from "../errors.js";
+import { makeErrorDetail, TalerError } from "@gnu-taler/taler-util";
import { InternalWalletState } from "../internal-wallet-state.js";
import { checkDbInvariant, checkLogicInvariant } from "../util/invariants.js";
import { GetReadWriteAccess } from "../util/query.js";
diff --git a/packages/taler-wallet-core/src/operations/deposits.ts b/packages/taler-wallet-core/src/operations/deposits.ts
index 4ff6a65cd..9d71f020f 100644
--- a/packages/taler-wallet-core/src/operations/deposits.ts
+++ b/packages/taler-wallet-core/src/operations/deposits.ts
@@ -62,10 +62,10 @@ import {
OperationStatus,
TransactionStatus,
} from "../db.js";
-import { TalerError } from "../errors.js";
-import { checkWithdrawalKycStatus, KycPendingInfo, KycUserType } from "../index.js";
+import { TalerError } from "@gnu-taler/taler-util";
+import { KycPendingInfo, KycUserType } from "../index.js";
import { InternalWalletState } from "../internal-wallet-state.js";
-import { readSuccessResponseJsonOrThrow } from "../util/http.js";
+import { readSuccessResponseJsonOrThrow } from "@gnu-taler/taler-util/http";
import { OperationAttemptResult } from "../util/retries.js";
import { makeTransactionId, spendCoins } from "./common.js";
import { getExchangeDetails } from "./exchanges.js";
diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts b/packages/taler-wallet-core/src/operations/exchanges.ts
index 67f77de77..2b6a881dd 100644
--- a/packages/taler-wallet-core/src/operations/exchanges.ts
+++ b/packages/taler-wallet-core/src/operations/exchanges.ts
@@ -41,6 +41,7 @@ import {
NotificationType,
parsePaytoUri,
Recoup,
+ TalerError,
TalerErrorCode,
TalerProtocolDuration,
TalerProtocolTimestamp,
@@ -49,6 +50,7 @@ import {
WireFeeMap,
WireInfo,
} from "@gnu-taler/taler-util";
+import { HttpRequestLibrary, readSuccessResponseTextOrThrow, readSuccessResponseJsonOrThrow, getExpiry } from "@gnu-taler/taler-util/http";
import {
DenominationRecord,
DenominationVerificationStatus,
@@ -56,14 +58,7 @@ import {
ExchangeRecord,
WalletStoresV1,
} from "../db.js";
-import { TalerError } from "../errors.js";
import { InternalWalletState, TrustInfo } from "../internal-wallet-state.js";
-import {
- getExpiry,
- HttpRequestLibrary,
- readSuccessResponseJsonOrThrow,
- readSuccessResponseTextOrThrow,
-} from "../util/http.js";
import { checkDbInvariant } from "../util/invariants.js";
import {
DbAccess,
diff --git a/packages/taler-wallet-core/src/operations/merchants.ts b/packages/taler-wallet-core/src/operations/merchants.ts
index eeefc0f79..c47ec4a0a 100644
--- a/packages/taler-wallet-core/src/operations/merchants.ts
+++ b/packages/taler-wallet-core/src/operations/merchants.ts
@@ -25,7 +25,7 @@ import {
LibtoolVersion,
} from "@gnu-taler/taler-util";
import { InternalWalletState, MerchantInfo } from "../internal-wallet-state.js";
-import { readSuccessResponseJsonOrThrow } from "../util/http.js";
+import { readSuccessResponseJsonOrThrow } from "@gnu-taler/taler-util/http";
const logger = new Logger("taler-wallet-core:merchants.ts");
diff --git a/packages/taler-wallet-core/src/operations/pay-merchant.ts b/packages/taler-wallet-core/src/operations/pay-merchant.ts
index 2a89c59ed..f84ac2567 100644
--- a/packages/taler-wallet-core/src/operations/pay-merchant.ts
+++ b/packages/taler-wallet-core/src/operations/pay-merchant.ts
@@ -94,13 +94,12 @@ import {
makePendingOperationFailedError,
TalerError,
TalerProtocolViolationError,
-} from "../errors.js";
-import { GetReadWriteAccess } from "../index.browser.js";
+} from "@gnu-taler/taler-util";
+import { GetReadWriteAccess } from "../index.js";
import {
EXCHANGE_COINS_LOCK,
InternalWalletState,
} from "../internal-wallet-state.js";
-import { PendingTaskType } from "../pending-types.js";
import { assertUnreachable } from "../util/assertUnreachable.js";
import {
CoinSelectionTally,
@@ -114,7 +113,7 @@ import {
readTalerErrorResponse,
readUnexpectedResponseDetails,
throwUnexpectedRequestError,
-} from "../util/http.js";
+} from "@gnu-taler/taler-util/http";
import { checkDbInvariant, checkLogicInvariant } from "../util/invariants.js";
import {
OperationAttemptResult,
diff --git a/packages/taler-wallet-core/src/operations/pay-peer.ts b/packages/taler-wallet-core/src/operations/pay-peer.ts
index 7dc7b67fe..022a824de 100644
--- a/packages/taler-wallet-core/src/operations/pay-peer.ts
+++ b/packages/taler-wallet-core/src/operations/pay-peer.ts
@@ -81,16 +81,15 @@ import {
WithdrawalGroupStatus,
WithdrawalRecordType,
} from "../db.js";
-import { TalerError } from "../errors.js";
+import { TalerError } from "@gnu-taler/taler-util";
import { InternalWalletState } from "../internal-wallet-state.js";
import {
makeTransactionId,
runOperationWithErrorReporting,
spendCoins,
} from "../operations/common.js";
-import { readSuccessResponseJsonOrThrow } from "../util/http.js";
+import { readSuccessResponseJsonOrThrow } from "@gnu-taler/taler-util/http";
import { checkDbInvariant } from "../util/invariants.js";
-import { GetReadOnlyAccess } from "../util/query.js";
import {
OperationAttemptResult,
OperationAttemptResultType,
diff --git a/packages/taler-wallet-core/src/operations/recoup.ts b/packages/taler-wallet-core/src/operations/recoup.ts
index 00dd0e1c6..3b423474b 100644
--- a/packages/taler-wallet-core/src/operations/recoup.ts
+++ b/packages/taler-wallet-core/src/operations/recoup.ts
@@ -49,7 +49,7 @@ import {
WithdrawCoinSource,
} from "../db.js";
import { InternalWalletState } from "../internal-wallet-state.js";
-import { readSuccessResponseJsonOrThrow } from "../util/http.js";
+import { readSuccessResponseJsonOrThrow } from "@gnu-taler/taler-util/http";
import { checkDbInvariant } from "../util/invariants.js";
import { GetReadWriteAccess } from "../util/query.js";
import {
diff --git a/packages/taler-wallet-core/src/operations/refresh.ts b/packages/taler-wallet-core/src/operations/refresh.ts
index 5b7bf8d83..773689635 100644
--- a/packages/taler-wallet-core/src/operations/refresh.ts
+++ b/packages/taler-wallet-core/src/operations/refresh.ts
@@ -63,7 +63,7 @@ import {
RefreshReasonDetails,
WalletStoresV1,
} from "../db.js";
-import { TalerError } from "../errors.js";
+import { TalerError } from "@gnu-taler/taler-util";
import {
EXCHANGE_COINS_LOCK,
InternalWalletState,
@@ -72,7 +72,7 @@ import { assertUnreachable } from "../util/assertUnreachable.js";
import {
readSuccessResponseJsonOrThrow,
readUnexpectedResponseDetails,
-} from "../util/http.js";
+} from "@gnu-taler/taler-util/http";
import { checkDbInvariant } from "../util/invariants.js";
import { GetReadWriteAccess } from "../util/query.js";
import {
diff --git a/packages/taler-wallet-core/src/operations/testing.ts b/packages/taler-wallet-core/src/operations/testing.ts
index 50454a920..873fac021 100644
--- a/packages/taler-wallet-core/src/operations/testing.ts
+++ b/packages/taler-wallet-core/src/operations/testing.ts
@@ -29,7 +29,7 @@ import {
HttpRequestLibrary,
readSuccessResponseJsonOrThrow,
checkSuccessResponseOrThrow,
-} from "../util/http.js";
+} from "@gnu-taler/taler-util/http";
import {
AmountString,
codecForAny,
diff --git a/packages/taler-wallet-core/src/operations/tip.ts b/packages/taler-wallet-core/src/operations/tip.ts
index 2bf216102..ec7546992 100644
--- a/packages/taler-wallet-core/src/operations/tip.ts
+++ b/packages/taler-wallet-core/src/operations/tip.ts
@@ -45,12 +45,12 @@ import {
DenominationRecord,
TipRecord,
} from "../db.js";
-import { makeErrorDetail } from "../errors.js";
+import { makeErrorDetail } from "@gnu-taler/taler-util";
import { InternalWalletState } from "../internal-wallet-state.js";
import {
getHttpResponseErrorDetails,
readSuccessResponseJsonOrThrow,
-} from "../util/http.js";
+} from "@gnu-taler/taler-util/http";
import { checkDbInvariant, checkLogicInvariant } from "../util/invariants.js";
import {
OperationAttemptResult,
diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts
index bcc8600c7..f6d79b229 100644
--- a/packages/taler-wallet-core/src/operations/withdraw.ts
+++ b/packages/taler-wallet-core/src/operations/withdraw.ts
@@ -85,7 +85,7 @@ import {
getErrorDetailFromException,
makeErrorDetail,
TalerError,
-} from "../errors.js";
+} from "@gnu-taler/taler-util";
import { InternalWalletState } from "../internal-wallet-state.js";
import {
makeCoinAvailable,
@@ -99,7 +99,7 @@ import {
readSuccessResponseJsonOrErrorCode,
readSuccessResponseJsonOrThrow,
throwUnexpectedRequestError,
-} from "../util/http.js";
+} from "@gnu-taler/taler-util/http";
import {
checkDbInvariant,
checkLogicInvariant,
diff --git a/packages/taler-wallet-core/src/remote.ts b/packages/taler-wallet-core/src/remote.ts
index bc0be9d30..89348698e 100644
--- a/packages/taler-wallet-core/src/remote.ts
+++ b/packages/taler-wallet-core/src/remote.ts
@@ -19,10 +19,10 @@ import {
CoreApiResponse,
j2s,
Logger,
+ TalerError,
WalletNotification,
} from "@gnu-taler/taler-util";
import { connectRpc, JsonMessage } from "@gnu-taler/taler-util/twrpc";
-import { TalerError } from "./errors.js";
import { OpenedPromise, openPromise } from "./index.js";
import { WalletCoreApiClient } from "./wallet-api-types.js";
diff --git a/packages/taler-wallet-core/src/util/retries.ts b/packages/taler-wallet-core/src/util/retries.ts
index fcb63ecd1..742381f7b 100644
--- a/packages/taler-wallet-core/src/util/retries.ts
+++ b/packages/taler-wallet-core/src/util/retries.ts
@@ -40,7 +40,7 @@ import {
WalletStoresV1,
WithdrawalGroupRecord,
} from "../db.js";
-import { TalerError } from "../errors.js";
+import { TalerError } from "@gnu-taler/taler-util";
import { InternalWalletState } from "../internal-wallet-state.js";
import { PendingTaskType } from "../pending-types.js";
import { GetReadWriteAccess } from "./query.js";
diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts
index a57c71bcf..0d02b667b 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -129,7 +129,7 @@ import {
maybeInitDevMode,
setDevMode,
} from "./dev-experiments.js";
-import { getErrorDetailFromException, TalerError } from "./errors.js";
+import { getErrorDetailFromException, TalerError } from "@gnu-taler/taler-util";
import {
ActiveLongpollInfo,
ExchangeOperations,
@@ -247,7 +247,7 @@ import {
import {
HttpRequestLibrary,
readSuccessResponseJsonOrThrow,
-} from "./util/http.js";
+} from "@gnu-taler/taler-util/http";
import { checkDbInvariant } from "./util/invariants.js";
import {
AsyncCondition,
diff --git a/packages/taler-wallet-embedded/build.mjs b/packages/taler-wallet-embedded/build.mjs
index 537a4fbc0..28351e6e5 100755
--- a/packages/taler-wallet-embedded/build.mjs
+++ b/packages/taler-wallet-embedded/build.mjs
@@ -55,6 +55,7 @@ export const buildConfig = {
format: 'esm',
platform: 'neutral',
mainFields: ["module", "main"],
+ conditions: ["qtart"],
sourcemap: true,
define: {
'__VERSION__': `"${_package.version}"`,
diff --git a/packages/taler-wallet-embedded/src/index.ts b/packages/taler-wallet-embedded/src/index.ts
index b505a2d9d..e0a13390d 100644
--- a/packages/taler-wallet-embedded/src/index.ts
+++ b/packages/taler-wallet-embedded/src/index.ts
@@ -18,27 +18,25 @@
* Imports.
*/
import {
+ createNativeWalletHost,
DefaultNodeWalletArgs,
- getDefaultNodeWallet,
- getErrorDetailFromException,
handleWorkerError,
handleWorkerMessage,
- Headers,
- HttpRequestLibrary,
- HttpRequestOptions,
- HttpResponse,
- NodeHttpLib,
OpenedPromise,
openPromise,
Wallet,
- WALLET_EXCHANGE_PROTOCOL_VERSION,
- WALLET_MERCHANT_PROTOCOL_VERSION,
} from "@gnu-taler/taler-wallet-core";
import {
CoreApiMessageEnvelope,
CoreApiResponse,
CoreApiResponseSuccess,
+ createPlatformHttpLib,
+ getErrorDetailFromException,
+ Headers,
+ HttpRequestLibrary,
+ HttpRequestOptions,
+ HttpResponse,
Logger,
WalletNotification,
} from "@gnu-taler/taler-util";
@@ -51,7 +49,7 @@ const logger = new Logger("taler-wallet-embedded/index.ts");
export class NativeHttpLib implements HttpRequestLibrary {
useNfcTunnel = false;
- private nodeHttpLib: HttpRequestLibrary = new NodeHttpLib();
+ private httpLib: HttpRequestLibrary = createPlatformHttpLib();
private requestId = 1;
@@ -62,7 +60,7 @@ export class NativeHttpLib implements HttpRequestLibrary {
constructor(private sendMessage: (m: string) => void) {}
fetch(url: string, opt?: HttpRequestOptions): Promise<HttpResponse> {
- return this.nodeHttpLib.fetch(url, opt);
+ return this.httpLib.fetch(url, opt);
}
get(url: string, opt?: HttpRequestOptions): Promise<HttpResponse> {
@@ -83,7 +81,7 @@ export class NativeHttpLib implements HttpRequestLibrary {
);
return p.promise;
} else {
- return this.nodeHttpLib.get(url, opt);
+ return this.httpLib.get(url, opt);
}
}
@@ -106,7 +104,7 @@ export class NativeHttpLib implements HttpRequestLibrary {
);
return p.promise;
} else {
- return this.nodeHttpLib.postJson(url, body, opt);
+ return this.httpLib.postJson(url, body, opt);
}
}
@@ -158,7 +156,7 @@ class NativeWalletMessageHandler {
walletArgs: DefaultNodeWalletArgs | undefined;
maybeWallet: Wallet | undefined;
wp = openPromise<Wallet>();
- httpLib = new NodeHttpLib();
+ httpLib = createPlatformHttpLib();
/**
* Handle a request from the native wallet.
@@ -181,7 +179,7 @@ class NativeWalletMessageHandler {
const reinit = async () => {
logger.info("in reinit");
- const w = await getDefaultNodeWallet(this.walletArgs);
+ const w = await createNativeWalletHost(this.walletArgs);
this.maybeWallet = w;
const resp = await w.handleCoreApiRequest(
"initWallet",
diff --git a/packages/taler-wallet-embedded/src/wallet-qjs.ts b/packages/taler-wallet-embedded/src/wallet-qjs.ts
index f7b73711c..77d166095 100644
--- a/packages/taler-wallet-embedded/src/wallet-qjs.ts
+++ b/packages/taler-wallet-embedded/src/wallet-qjs.ts
@@ -18,43 +18,25 @@
* Imports.
*/
import {
- AccessStats,
- DefaultNodeWalletArgs,
- getErrorDetailFromException,
- Headers,
- HttpRequestLibrary,
- HttpRequestOptions,
- HttpResponse,
- openPromise,
- openTalerDatabase,
- SetTimeoutTimerAPI,
- SynchronousCryptoWorkerFactoryPlain,
- Wallet,
- WalletApiOperation,
-} from "@gnu-taler/taler-wallet-core";
-
-import {
CoreApiMessageEnvelope,
CoreApiResponse,
CoreApiResponseSuccess,
+ createPlatformHttpLib,
+ getErrorDetailFromException,
InitRequest,
- j2s,
Logger,
setGlobalLogLevelFromString,
setPRNG,
WalletNotification,
} from "@gnu-taler/taler-util";
-import { BridgeIDBFactory } from "@gnu-taler/idb-bridge";
-import { MemoryBackend } from "@gnu-taler/idb-bridge";
-import { shimIndexedDB } from "@gnu-taler/idb-bridge";
-import { IDBFactory } from "@gnu-taler/idb-bridge";
-
-import * as _qjsOsImp from "os";
-// @ts-ignore
-import * as _qjsStdImp from "std";
-
-const textDecoder = new TextDecoder();
-const textEncoder = new TextEncoder();
+import { qjsOs } from "@gnu-taler/taler-util/qtart";
+import {
+ createNativeWalletHost2,
+ DefaultNodeWalletArgs,
+ openPromise,
+ Wallet,
+ WalletApiOperation,
+} from "@gnu-taler/taler-wallet-core";
setGlobalLogLevelFromString("trace");
@@ -66,210 +48,19 @@ setPRNG(function (x: Uint8Array, n: number) {
for (let i = 0; i < v.length; i++) v[i] = 0;
});
-export interface QjsHttpResp {
- status: number;
- data: ArrayBuffer;
-}
-
-export interface QjsHttpOptions {
- method: string;
- debug?: boolean;
- data?: ArrayBuffer;
- headers?: string[];
-}
-
-export interface QjsOsLib {
- fetchHttp(url: string, options?: QjsHttpOptions): Promise<QjsHttpResp>;
- postMessageToHost(s: string): void;
- setMessageFromHostHandler(h: (s: string) => void): void;
- rename(oldPath: string, newPath: string): number;
-}
-
-export interface QjsStdLib {
- writeFile(filename: string, contents: string): void;
- loadFile(filename: string): string;
-}
-
-// This is not the nodejs "os" module, but the qjs "os" module.
-const qjsOs: QjsOsLib = _qjsOsImp as any;
-
-const qjsStd: QjsStdLib = _qjsStdImp as any;
-
const logger = new Logger("taler-wallet-embedded/index.ts");
-export class NativeHttpLib implements HttpRequestLibrary {
- get(
- url: string,
- opt?: HttpRequestOptions | undefined,
- ): Promise<HttpResponse> {
- return this.fetch(url, {
- method: "GET",
- ...opt,
- });
- }
- postJson(
- url: string,
- body: any,
- opt?: HttpRequestOptions | undefined,
- ): Promise<HttpResponse> {
- return this.fetch(url, {
- method: "POST",
- body,
- ...opt,
- });
- }
- async fetch(
- url: string,
- opt?: HttpRequestOptions | undefined,
- ): Promise<HttpResponse> {
- const method = opt?.method ?? "GET";
- let data: ArrayBuffer | undefined = undefined;
- let headers: string[] = [];
- if (opt?.headers) {
- for (let headerName of Object.keys(opt.headers)) {
- headers.push(`${headerName}: ${opt.headers[headerName]}`);
- }
- }
- if (method.toUpperCase() === "POST") {
- if (opt?.body) {
- if (typeof opt.body === "string") {
- data = textEncoder.encode(opt.body).buffer;
- } else if (ArrayBuffer.isView(opt.body)) {
- data = opt.body.buffer;
- } else if (opt.body instanceof ArrayBuffer) {
- data = opt.body;
- } else if (typeof opt.body === "object") {
- data = textEncoder.encode(JSON.stringify(opt.body)).buffer;
- }
- } else {
- data = new ArrayBuffer(0);
- }
- }
- const res = await qjsOs.fetchHttp(url, {
- method,
- data,
- headers,
- });
- return {
- requestMethod: method,
- headers: new Headers(),
- async bytes() {
- return res.data;
- },
- json() {
- const text = textDecoder.decode(res.data);
- return JSON.parse(text);
- },
- async text() {
- const text = textDecoder.decode(res.data);
- return text;
- },
- requestUrl: url,
- status: res.status,
- };
- }
-}
-
function sendNativeMessage(ev: CoreApiMessageEnvelope): void {
const m = JSON.stringify(ev);
qjsOs.postMessageToHost(m);
}
-/**
- * Generate a random alphanumeric ID. Does *not* use cryptographically
- * secure randomness.
- */
-function makeId(length: number): string {
- let result = "";
- const characters =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
- for (let i = 0; i < length; i++) {
- result += characters.charAt(Math.floor(Math.random() * characters.length));
- }
- return result;
-}
-
-export async function getWallet(args: DefaultNodeWalletArgs = {}): Promise<{
- wallet: Wallet;
- getDbStats: () => AccessStats;
-}> {
- BridgeIDBFactory.enableTracing = false;
- const myBackend = new MemoryBackend();
- myBackend.enableTracing = false;
-
- const storagePath = args.persistentStoragePath;
- if (storagePath) {
- const dbContentStr = qjsStd.loadFile(storagePath);
- if (dbContentStr != null) {
- const dbContent = JSON.parse(dbContentStr);
- myBackend.importDump(dbContent);
- }
-
- myBackend.afterCommitCallback = async () => {
- logger.trace("committing database");
- // Allow caller to stop persisting the wallet.
- if (args.persistentStoragePath === undefined) {
- return;
- }
- const tmpPath = `${args.persistentStoragePath}-${makeId(5)}.tmp`;
- const dbContent = myBackend.exportDump();
- qjsStd.writeFile(tmpPath, JSON.stringify(dbContent, undefined, 2));
- // Atomically move the temporary file onto the DB path.
- const res = qjsOs.rename(tmpPath, args.persistentStoragePath);
- if (res != 0) {
- throw Error("db commit failed at rename");
- }
- logger.trace("committing database done");
- };
- }
-
- console.log("done processing storage path");
-
- BridgeIDBFactory.enableTracing = false;
-
- const myBridgeIdbFactory = new BridgeIDBFactory(myBackend);
- const myIdbFactory: IDBFactory = myBridgeIdbFactory as any as IDBFactory;
-
- let myHttpLib;
- if (args.httpLib) {
- myHttpLib = args.httpLib;
- } else {
- myHttpLib = new NativeHttpLib();
- }
-
- const myVersionChange = (): Promise<void> => {
- logger.error("version change requested, should not happen");
- throw Error(
- "BUG: wallet DB version change event can't happen with memory IDB",
- );
- };
-
- shimIndexedDB(myBridgeIdbFactory);
-
- const myDb = await openTalerDatabase(myIdbFactory, myVersionChange);
-
- let workerFactory;
- workerFactory = new SynchronousCryptoWorkerFactoryPlain();
-
- const timer = new SetTimeoutTimerAPI();
-
- const w = await Wallet.create(myDb, myHttpLib, timer, workerFactory);
-
- if (args.notifyHandler) {
- w.addNotificationListener(args.notifyHandler);
- }
- return {
- wallet: w,
- getDbStats: () => myBackend.accessStats,
- };
-}
-
class NativeWalletMessageHandler {
walletArgs: DefaultNodeWalletArgs | undefined;
initRequest: InitRequest = {};
maybeWallet: Wallet | undefined;
wp = openPromise<Wallet>();
- httpLib = new NativeHttpLib();
+ httpLib = createPlatformHttpLib();
/**
* Handle a request from the native wallet.
@@ -292,7 +83,7 @@ class NativeWalletMessageHandler {
const reinit = async () => {
logger.info("in reinit");
- const wR = await getWallet(this.walletArgs);
+ const wR = await createNativeWalletHost2(this.walletArgs);
const w = wR.wallet;
this.maybeWallet = w;
const resp = await w.handleCoreApiRequest("initWallet", "native-init", {
@@ -422,7 +213,7 @@ globalThis.installNativeWalletListener = installNativeWalletListener;
globalThis.makeWallet = getWallet;
export async function testWithGv() {
- const w = await getWallet();
+ const w = await createNativeWalletHost2();
await w.wallet.client.call(WalletApiOperation.InitWallet, {});
await w.wallet.client.call(WalletApiOperation.RunIntegrationTest, {
amountToSpend: "KUDOS:1",
@@ -438,7 +229,7 @@ export async function testWithGv() {
export async function testWithLocal() {
console.log("running local test");
- const w = await getWallet({
+ const w = await createNativeWalletHost2({
persistentStoragePath: "walletdb.json",
});
console.log("created wallet");
diff --git a/packages/taler-wallet-webextension/src/browserHttpLib.ts b/packages/taler-wallet-webextension/src/browserHttpLib.ts
index 165a0037c..3b8bb1881 100644
--- a/packages/taler-wallet-webextension/src/browserHttpLib.ts
+++ b/packages/taler-wallet-webextension/src/browserHttpLib.ts
@@ -18,19 +18,17 @@
* Imports.
*/
import {
+ Logger,
+ RequestThrottler,
+ TalerErrorCode,
HttpRequestLibrary,
HttpRequestOptions,
HttpResponse,
Headers,
TalerError,
-} from "@gnu-taler/taler-wallet-core";
-import {
- Logger,
- RequestThrottler,
- stringToBytes,
- TalerErrorCode,
} from "@gnu-taler/taler-util";
+
const logger = new Logger("browserHttpLib");
/**
diff --git a/packages/taler-wallet-webextension/src/browserWorkerEntry.ts b/packages/taler-wallet-webextension/src/browserWorkerEntry.ts
index 2f1a26e36..bb1794e56 100644
--- a/packages/taler-wallet-webextension/src/browserWorkerEntry.ts
+++ b/packages/taler-wallet-webextension/src/browserWorkerEntry.ts
@@ -22,11 +22,12 @@
* Imports.
*/
-import { j2s, Logger } from "@gnu-taler/taler-util";
import {
+ j2s,
+ Logger,
getErrorDetailFromException,
- nativeCrypto,
-} from "@gnu-taler/taler-wallet-core";
+} from "@gnu-taler/taler-util";
+import { nativeCrypto } from "@gnu-taler/taler-wallet-core";
const logger = new Logger("browserWorkerEntry.ts");
diff --git a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/state.ts b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/state.ts
index ee5375859..670a67599 100644
--- a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/state.ts
@@ -16,7 +16,7 @@
/* eslint-disable react-hooks/rules-of-hooks */
import { Amounts, TalerProtocolTimestamp } from "@gnu-taler/taler-util";
-import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { isFuture, parse } from "date-fns";
import { useState } from "preact/hooks";
import { alertFromError, useAlertContext } from "../../context/alert.js";
diff --git a/packages/taler-wallet-webextension/src/cta/InvoicePay/state.ts b/packages/taler-wallet-webextension/src/cta/InvoicePay/state.ts
index 66c018ddf..8459d5ca2 100644
--- a/packages/taler-wallet-webextension/src/cta/InvoicePay/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/InvoicePay/state.ts
@@ -20,16 +20,14 @@ import {
NotificationType,
PreparePayResult,
PreparePayResultType,
- TalerErrorDetail,
TalerProtocolTimestamp,
} from "@gnu-taler/taler-util";
-import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { useEffect, useState } from "preact/hooks";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { useEffect } from "preact/hooks";
import { alertFromError, useAlertContext } from "../../context/alert.js";
import { useBackendContext } from "../../context/backend.js";
import { useTranslationContext } from "../../context/translation.js";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
-import { withSafe } from "../../mui/handlers.js";
import { Props, State } from "./index.js";
export function useComponentState({
diff --git a/packages/taler-wallet-webextension/src/cta/TransferCreate/state.ts b/packages/taler-wallet-webextension/src/cta/TransferCreate/state.ts
index 6574d6ba1..b306ca122 100644
--- a/packages/taler-wallet-webextension/src/cta/TransferCreate/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/TransferCreate/state.ts
@@ -15,11 +15,9 @@
*/
import {
- Amounts,
- TalerErrorDetail,
- TalerProtocolTimestamp,
+ Amounts, TalerProtocolTimestamp
} from "@gnu-taler/taler-util";
-import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { isFuture, parse } from "date-fns";
import { useState } from "preact/hooks";
import { alertFromError, useAlertContext } from "../../context/alert.js";
diff --git a/packages/taler-wallet-webextension/src/cta/TransferPickup/state.ts b/packages/taler-wallet-webextension/src/cta/TransferPickup/state.ts
index 12643b893..6b50faf10 100644
--- a/packages/taler-wallet-webextension/src/cta/TransferPickup/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/TransferPickup/state.ts
@@ -16,12 +16,9 @@
import {
AbsoluteTime,
- Amounts,
- TalerErrorDetail,
- TalerProtocolTimestamp,
+ Amounts, TalerProtocolTimestamp
} from "@gnu-taler/taler-util";
-import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { useState } from "preact/hooks";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { alertFromError, useAlertContext } from "../../context/alert.js";
import { useBackendContext } from "../../context/backend.js";
import { useTranslationContext } from "../../context/translation.js";
diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts b/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts
index 5f149064c..9522c2bfb 100644
--- a/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts
@@ -20,8 +20,9 @@ import {
Amounts,
ExchangeListItem,
ExchangeTosStatus,
+ TalerError,
} from "@gnu-taler/taler-util";
-import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { useState } from "preact/hooks";
import { alertFromError, useAlertContext } from "../../context/alert.js";
import { useBackendContext } from "../../context/backend.js";
diff --git a/packages/taler-wallet-webextension/src/hooks/useAsyncAsHook.ts b/packages/taler-wallet-webextension/src/hooks/useAsyncAsHook.ts
index cf9409bad..a5e357f7d 100644
--- a/packages/taler-wallet-webextension/src/hooks/useAsyncAsHook.ts
+++ b/packages/taler-wallet-webextension/src/hooks/useAsyncAsHook.ts
@@ -13,8 +13,7 @@
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/>
*/
-import { TalerErrorDetail } from "@gnu-taler/taler-util";
-import { TalerError } from "@gnu-taler/taler-wallet-core";
+import { TalerErrorDetail, TalerError } from "@gnu-taler/taler-util";
import { useEffect, useMemo, useState } from "preact/hooks";
import { BackgroundError } from "../wxApi.js";
diff --git a/packages/taler-wallet-webextension/src/platform/chrome.ts b/packages/taler-wallet-webextension/src/platform/chrome.ts
index 07829641e..beb65b2d0 100644
--- a/packages/taler-wallet-webextension/src/platform/chrome.ts
+++ b/packages/taler-wallet-webextension/src/platform/chrome.ts
@@ -19,8 +19,9 @@ import {
Logger,
TalerErrorCode,
TalerUriType,
+ TalerError,
} from "@gnu-taler/taler-util";
-import { TalerError, WalletOperations } from "@gnu-taler/taler-wallet-core";
+import { WalletOperations } from "@gnu-taler/taler-wallet-core";
import { BackgroundOperations } from "../wxApi.js";
import {
BackgroundPlatformAPI,
diff --git a/packages/taler-wallet-webextension/src/serviceWorkerCryptoWorkerFactory.ts b/packages/taler-wallet-webextension/src/serviceWorkerCryptoWorkerFactory.ts
index 0742d5ccd..4ee572435 100644
--- a/packages/taler-wallet-webextension/src/serviceWorkerCryptoWorkerFactory.ts
+++ b/packages/taler-wallet-webextension/src/serviceWorkerCryptoWorkerFactory.ts
@@ -22,12 +22,12 @@
import {
CryptoWorker,
CryptoWorkerFactory,
- SynchronousCryptoWorker,
+ SynchronousCryptoWorkerPlain,
} from "@gnu-taler/taler-wallet-core";
export class SynchronousCryptoWorkerFactory implements CryptoWorkerFactory {
startWorker(): CryptoWorker {
- return new SynchronousCryptoWorker();
+ return new SynchronousCryptoWorkerPlain();
}
getConcurrency(): number {
diff --git a/packages/taler-wallet-webextension/src/serviceWorkerHttpLib.ts b/packages/taler-wallet-webextension/src/serviceWorkerHttpLib.ts
index 4b47e89d5..00c0085ef 100644
--- a/packages/taler-wallet-webextension/src/serviceWorkerHttpLib.ts
+++ b/packages/taler-wallet-webextension/src/serviceWorkerHttpLib.ts
@@ -21,14 +21,12 @@ import {
Logger,
RequestThrottler,
TalerErrorCode,
-} from "@gnu-taler/taler-util";
-import {
Headers,
HttpRequestLibrary,
HttpRequestOptions,
HttpResponse,
TalerError,
-} from "@gnu-taler/taler-wallet-core";
+} from "@gnu-taler/taler-util";
/**
* An implementation of the [[HttpRequestLibrary]] using the
diff --git a/packages/taler-wallet-webextension/src/wxApi.ts b/packages/taler-wallet-webextension/src/wxApi.ts
index c064d7111..5f3d09619 100644
--- a/packages/taler-wallet-webextension/src/wxApi.ts
+++ b/packages/taler-wallet-webextension/src/wxApi.ts
@@ -29,20 +29,18 @@ import {
NotificationType,
TalerErrorCode,
TalerErrorDetail,
- WalletDiagnostics,
+ WalletDiagnostics
} from "@gnu-taler/taler-util";
import {
- TalerError,
WalletCoreApiClient,
WalletCoreOpKeys,
WalletCoreRequestType,
- WalletCoreResponseType,
- WalletOperations,
+ WalletCoreResponseType
} from "@gnu-taler/taler-wallet-core";
import {
MessageFromBackend,
MessageFromFrontendBackground,
- MessageFromFrontendWallet,
+ MessageFromFrontendWallet
} from "./platform/api.js";
import { platform } from "./platform/foreground.js";
diff --git a/packages/taler-wallet-webextension/src/wxBackend.ts b/packages/taler-wallet-webextension/src/wxBackend.ts
index 99602445d..cca07941a 100644
--- a/packages/taler-wallet-webextension/src/wxBackend.ts
+++ b/packages/taler-wallet-webextension/src/wxBackend.ts
@@ -32,14 +32,14 @@ import {
TalerErrorCode,
TalerUriType,
WalletDiagnostics,
+ makeErrorDetail,
+ getErrorDetailFromException,
} from "@gnu-taler/taler-util";
import {
DbAccess,
deleteTalerDatabase,
exportDb,
- getErrorDetailFromException,
importDb,
- makeErrorDetail,
OpenedPromise,
openPromise,
openTalerDatabase,