aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-embedded
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2023-01-03 10:51:05 +0100
committerFlorian Dold <florian@dold.me>2023-01-04 09:55:10 +0100
commitf26cbe7c1f10d2d6430c9f444342180d1445ed33 (patch)
tree19b9d0a47246c442e1bd8fff1c64e65ebb88b310 /packages/taler-wallet-embedded
parent9ad1f2712a92d58804e090a7c3dd4cc0a41ee1d9 (diff)
downloadwallet-core-f26cbe7c1f10d2d6430c9f444342180d1445ed33.tar.xz
-qjs fixes
Diffstat (limited to 'packages/taler-wallet-embedded')
-rwxr-xr-xpackages/taler-wallet-embedded/build.mjs2
-rw-r--r--packages/taler-wallet-embedded/src/wallet-qjs.ts106
2 files changed, 60 insertions, 48 deletions
diff --git a/packages/taler-wallet-embedded/build.mjs b/packages/taler-wallet-embedded/build.mjs
index 0f12ef2c6..537a4fbc0 100755
--- a/packages/taler-wallet-embedded/build.mjs
+++ b/packages/taler-wallet-embedded/build.mjs
@@ -51,7 +51,7 @@ export const buildConfig = {
target: [
'es2020'
],
- external: ["os"],
+ external: ["os", "std"],
format: 'esm',
platform: 'neutral',
mainFields: ["module", "main"],
diff --git a/packages/taler-wallet-embedded/src/wallet-qjs.ts b/packages/taler-wallet-embedded/src/wallet-qjs.ts
index a9c314c6d..4c39e6188 100644
--- a/packages/taler-wallet-embedded/src/wallet-qjs.ts
+++ b/packages/taler-wallet-embedded/src/wallet-qjs.ts
@@ -21,8 +21,6 @@ import {
AccessStats,
DefaultNodeWalletArgs,
getErrorDetailFromException,
- handleWorkerError,
- handleWorkerMessage,
Headers,
HttpRequestLibrary,
HttpRequestOptions,
@@ -51,6 +49,8 @@ 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();
@@ -80,12 +80,20 @@ export interface QjsHttpOptions {
export interface QjsOsLib {
// Not async!
fetchHttp(url: string, options?: QjsHttpOptions): 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;
-export { handleWorkerError, handleWorkerMessage };
+const qjsStd: QjsStdLib = _qjsStdImp as any;
const logger = new Logger("taler-wallet-embedded/index.ts");
@@ -163,17 +171,22 @@ export class NativeHttpLib implements HttpRequestLibrary {
}
function sendNativeMessage(ev: CoreApiEnvelope): void {
- // @ts-ignore
- const sendMessage = globalThis.__native_sendMessage;
- if (typeof sendMessage !== "function") {
- const errMsg =
- "FATAL: cannot install native wallet listener: native functions missing";
- logger.error(errMsg);
- throw new Error(errMsg);
- }
const m = JSON.stringify(ev);
- // @ts-ignore
- sendMessage(m);
+ 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<{
@@ -186,40 +199,32 @@ export async function getWallet(args: DefaultNodeWalletArgs = {}): Promise<{
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;
- // }
- // }
+ const dbContentStr = qjsStd.loadFile(storagePath);
+ if (dbContentStr != null) {
+ const dbContent = JSON.parse(dbContentStr);
+ myBackend.importDump(dbContent);
+ }
myBackend.afterCommitCallback = async () => {
- logger.error("DB commit not implemented");
- // 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();
- // 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");
+ 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);
@@ -292,7 +297,7 @@ class NativeWalletMessageHandler {
const resp = await w.handleCoreApiRequest(
"initWallet",
"native-init",
- {},
+ {...this.walletArgs},
);
initResponse = resp.type == "response" ? resp.result : resp.error;
w.runTaskLoop().catch((e) => {
@@ -306,6 +311,7 @@ class NativeWalletMessageHandler {
switch (operation) {
case "init": {
this.walletArgs = {
+ ...args,
notifyHandler: async (notification: WalletNotification) => {
sendNativeMessage({ type: "notification", payload: notification });
},
@@ -378,7 +384,7 @@ export function installNativeWalletListener(): void {
logger.info(`native listener: got request for ${operation} (${id})`);
try {
- const respMsg = await handler.handleMessage(operation, id, msg.args);
+ const respMsg = await handler.handleMessage(operation, id, msg.payload ?? {});
logger.info(
`native listener: sending success response for ${operation} (${id})`,
);
@@ -395,8 +401,7 @@ export function installNativeWalletListener(): void {
}
};
- // @ts-ignore
- globalThis.__native_onMessage = onMessage;
+ qjsOs.setMessageFromHostHandler((m) => onMessage(m))
logger.info("native wallet listener installed");
}
@@ -423,10 +428,15 @@ export async function testWithGv() {
}
export async function testWithLocal() {
- const w = await getWallet();
+ console.log("running local test");
+ const w = await getWallet({
+ persistentStoragePath: "walletdb.json",
+ });
+ console.log("created wallet");
await w.wallet.client.call(WalletApiOperation.InitWallet, {
skipDefaults: true,
});
+ console.log("initialized wallet");
await w.wallet.client.call(WalletApiOperation.RunIntegrationTest, {
amountToSpend: "TESTKUDOS:1",
amountToWithdraw: "TESTKUDOS:3",
@@ -435,9 +445,11 @@ export async function testWithLocal() {
exchangeBaseUrl: "http://localhost:8081/",
merchantBaseUrl: "http://localhost:8083/",
});
+ console.log("started integration test");
await w.wallet.runTaskLoop({
stopWhenDone: true,
});
+ console.log("done with task loop");
w.wallet.stop();
}