-qjs fixes
This commit is contained in:
parent
9ad1f2712a
commit
f26cbe7c1f
@ -1632,7 +1632,7 @@ class InternalWalletStateImpl implements InternalWalletState {
|
||||
}
|
||||
|
||||
notify(n: WalletNotification): void {
|
||||
logger.trace("Notification", n);
|
||||
logger.trace("Notification", j2s(n));
|
||||
for (const l of this.listeners) {
|
||||
const nc = JSON.parse(JSON.stringify(n));
|
||||
setTimeout(() => {
|
||||
|
@ -51,7 +51,7 @@ export const buildConfig = {
|
||||
target: [
|
||||
'es2020'
|
||||
],
|
||||
external: ["os"],
|
||||
external: ["os", "std"],
|
||||
format: 'esm',
|
||||
platform: 'neutral',
|
||||
mainFields: ["module", "main"],
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user