summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/host-impl.node.ts
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 /packages/taler-wallet-core/src/host-impl.node.ts
parentcb2f4c21d85707abb0221cbf2a859a98836b2d44 (diff)
downloadwallet-core-825d2c4352022e7397854b2bd9ba7d3589873c07.tar.gz
wallet-core-825d2c4352022e7397854b2bd9ba7d3589873c07.tar.bz2
wallet-core-825d2c4352022e7397854b2bd9ba7d3589873c07.zip
make wallet-cli runnable under qtart
Diffstat (limited to 'packages/taler-wallet-core/src/host-impl.node.ts')
-rw-r--r--packages/taler-wallet-core/src/host-impl.node.ts159
1 files changed, 159 insertions, 0 deletions
diff --git a/packages/taler-wallet-core/src/host-impl.node.ts b/packages/taler-wallet-core/src/host-impl.node.ts
new file mode 100644
index 000000000..ec57e0ebe
--- /dev/null
+++ b/packages/taler-wallet-core/src/host-impl.node.ts
@@ -0,0 +1,159 @@
+/*
+ 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 { Logger } from "@gnu-taler/taler-util";
+import * as fs from "fs";
+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";
+
+const logger = new Logger("host-impl.node.ts");
+
+
+/**
+ * Get a wallet instance with default settings for node.
+ *
+ * Extended version that allows getting DB stats.
+ */
+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) {
+ try {
+ const dbContentStr: string = fs.readFileSync(storagePath, {
+ encoding: "utf-8",
+ });
+ const dbContent = JSON.parse(dbContentStr);
+ myBackend.importDump(dbContent);
+ } catch (e: any) {
+ const code: string = e.code;
+ if (code === "ENOENT") {
+ logger.trace("wallet file doesn't exist yet");
+ } else {
+ logger.error("could not open wallet database file");
+ throw e;
+ }
+ }
+
+ 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`;
+ logger.trace("exported DB dump");
+ const dbContent = myBackend.exportDump();
+ fs.writeFileSync(tmpPath, JSON.stringify(dbContent, undefined, 2), {
+ encoding: "utf-8",
+ });
+ // Atomically move the temporary file onto the DB path.
+ fs.renameSync(tmpPath, args.persistentStoragePath);
+ logger.trace("committing database done");
+ };
+ }
+
+ 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({
+ enableThrottling: true,
+ });
+ }
+
+ 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;
+ const cryptoWorkerType = args.cryptoWorkerType ?? "node-worker-thread";
+ if (cryptoWorkerType === "sync") {
+ logger.info("using synchronous crypto worker");
+ workerFactory = new SynchronousCryptoWorkerFactoryPlain();
+ } else if (cryptoWorkerType === "node-worker-thread") {
+ try {
+ // Try if we have worker threads available, fails in older node versions.
+ const _r = "require";
+ // eslint-disable-next-line no-unused-vars
+ const worker_threads = module[_r]("worker_threads");
+ // require("worker_threads");
+ workerFactory = new NodeThreadCryptoWorkerFactory();
+ logger.info("using node thread crypto worker");
+ } catch (e) {
+ logger.warn(
+ "worker threads not available, falling back to synchronous workers",
+ );
+ workerFactory = new SynchronousCryptoWorkerFactoryPlain();
+ }
+ } else {
+ throw Error(`unsupported crypto worker type '${cryptoWorkerType}'`);
+ }
+
+ 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,
+ };
+}