From 6cf20da379de1cd6cde2eca0877cbc9843ec3d1a Mon Sep 17 00:00:00 2001 From: goshiz Date: Tue, 25 Jul 2023 20:58:36 +0000 Subject: [PATCH] update core to use Full instead of Wasm --- package-lock.json | 4 +- package.json | 2 +- src/main/js/wallet/MoneroWalletFull.js | 824 ++++++++++++------------- 3 files changed, 415 insertions(+), 415 deletions(-) diff --git a/package-lock.json b/package-lock.json index c7305aab0..543f7af2a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "haven-wallet-core", - "version": "3.0.13", + "version": "3.0.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "haven-wallet-core", - "version": "3.0.13", + "version": "3.0.14", "license": "MIT", "dependencies": { "ajv": "^6.12.6", diff --git a/package.json b/package.json index 3d8820e37..229ded6dd 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "haven-wallet-core", "description": "A JavaScript library for using Haven", - "version": "3.0.13", + "version": "3.0.14", "license": "MIT", "repository": "https://github.com/haven-protocol-org/haven-web-core", "private": false, diff --git a/src/main/js/wallet/MoneroWalletFull.js b/src/main/js/wallet/MoneroWalletFull.js index 322696869..6da31b576 100644 --- a/src/main/js/wallet/MoneroWalletFull.js +++ b/src/main/js/wallet/MoneroWalletFull.js @@ -36,18 +36,18 @@ const MoneroMessageSignatureResult = require("./model/MoneroMessageSignatureResu /** * Implements a Monero wallet using fully client-side WebAssembly bindings to monero-project's wallet2 in C++. - * + * * @extends {MoneroWalletKeys} * @implements {MoneroWallet} * @hideconstructor */ class MoneroWalletFull extends MoneroWalletKeys { - + // --------------------------- STATIC UTILITIES ----------------------------- - + /** * Check if a wallet exists at a given path. - * + * * @param {string} path - path of the wallet on the file system * @param {fs} - Node.js compatible file system to use (optional, defaults to disk if nodejs) * @return {boolean} true if a wallet exists at the given path, false otherwise @@ -55,18 +55,18 @@ class MoneroWalletFull extends MoneroWalletKeys { static walletExists(path, fs) { assert(path, "Must provide a path to look for a wallet"); const keysPath = path + ".keys"; - if (!fs) fs = MoneroWalletWasm._getFs(); + if (!fs) fs = MoneroWalletFull._getFs(); if (!fs) throw new MoneroError("Must provide file system to check if wallet exists"); let exists = fs.existsSync(keysPath); LibraryUtils.log(1, "Wallet exists at " + path + ": " + exists); return exists; } - + /** *

Open an existing wallet using WebAssembly bindings to wallet2.h.

- * + * *

Examples:

- * + * * * let wallet1 = await MoneroWalletFull.openWallet(
*    "./wallets/wallet1",
@@ -74,7 +74,7 @@ class MoneroWalletFull extends MoneroWalletKeys { *    MoneroNetworkType.STAGENET,
*    "http://localhost:38081" // daemon uri
* );

- * + * * let wallet2 = await MoneroWalletFull.openWallet({
*    path: "./wallets/wallet2",
*    password: "supersecretpassword",
@@ -84,7 +84,7 @@ class MoneroWalletFull extends MoneroWalletKeys { *    serverPassword: "abctesting123"
* }); *
- * + * * @param {MoneroWalletConfig|object|string} configOrPath - MoneroWalletConfig or equivalent config object or a path to a wallet to open * @param {string} configOrPath.path - path of the wallet to open (optional if 'keysData' provided) * @param {string} configOrPath.password - password of the wallet to open @@ -126,12 +126,12 @@ class MoneroWalletFull extends MoneroWalletKeys { if (config.getRestoreHeight() !== undefined) throw new MoneroError("Cannot specify restore height when opening wallet"); if (config.getLanguage() !== undefined) throw new MoneroError("Cannot specify language when opening wallet"); if (config.getSaveCurrent() === true) throw new MoneroError("Cannot save current wallet when opening JNI wallet"); - + // read wallet data from disk if not provided if (!config.getKeysData()) { let fs = config.getFs() ? config.getFs() : MoneroWalletFull._getFs(); if (!fs) throw new MoneroError("Must provide file system to read wallet data from"); - // check if keys file exists + // check if keys file exists if (! this.walletExists(config.getPath(), fs)) throw new MoneroError("Wallet does not exist at path: " + config.getPath()); config.setKeysData(fs.readFileSync(config.getPath() + ".keys")); @@ -141,16 +141,16 @@ class MoneroWalletFull extends MoneroWalletKeys { } config.setCacheData(cacheData); } - + // open wallet from data return MoneroWalletFull._openWalletData(config.getPath(), config.getPassword(), config.getNetworkType(), config.getKeysData(), config.getCacheData(), config.getServer(), config.getProxyToWorker(), config.getFs()); } - + /** *

Create a wallet using WebAssembly bindings to wallet2.h.

- * + * *

Example:

- * + * * * let wallet = await MoneroWalletFull.createWallet({
*    path: "./test_wallets/wallet1", // leave blank for in-memory wallet
@@ -161,7 +161,7 @@ class MoneroWalletFull extends MoneroWalletKeys { *    server: new MoneroRpcConnection("http://localhost:38081", "daemon_user", "daemon_password_123"),
* }); *
- * + * * @param {object|MoneroWalletConfig} config - MoneroWalletConfig or equivalent config object * @param {string} config.path - path of the wallet to create (optional, in-memory wallet if not given) * @param {string} config.password - password of the wallet to create @@ -185,7 +185,7 @@ class MoneroWalletFull extends MoneroWalletKeys { * @return {MoneroWalletFull} the created wallet */ static async createWallet(config) { - + // normalize and validate config if (config === undefined) throw new MoneroError("Must provide config to create wallet"); config = config instanceof MoneroWalletConfig ? config : new MoneroWalletConfig(config); @@ -198,7 +198,7 @@ class MoneroWalletFull extends MoneroWalletKeys { if (config.getPath() === undefined) config.setPath(""); if (config.getPath() && MoneroWalletFull.walletExists(config.getPath(), config.getFs())) throw new MoneroError("Wallet already exists: " + config.getPath()); if (!config.getPassword()) throw new MoneroError("Must provide a password to create the wallet with"); - + // create wallet if (config.getMnemonic() !== undefined) { if (config.getLanguage() !== undefined) throw new MoneroError("Cannot provide language when creating wallet from mnemonic"); @@ -212,48 +212,48 @@ class MoneroWalletFull extends MoneroWalletKeys { return MoneroWalletFull._createWalletRandom(config); } } - + static async _createWalletFromMnemonic(config) { if (config.getProxyToWorker() === undefined) config.setProxyToWorker(true); if (config.getProxyToWorker()) return MoneroWalletFullProxy._createWallet(config); - + // validate and normalize params let daemonConnection = config.getServer(); let rejectUnauthorized = daemonConnection ? daemonConnection.getRejectUnauthorized() : true; if (config.getRestoreHeight() === undefined) config.setRestoreHeight(0); if (config.getSeedOffset() === undefined) config.setSeedOffset(""); - + // load full wasm module let module = await LibraryUtils.loadFullModule(); - + // create wallet in queue let wallet = await module.queueTask(async function() { return new Promise(function(resolve, reject) { - + // register fn informing if unauthorized reqs should be rejected let rejectUnauthorizedFnId = GenUtils.getUUID(); LibraryUtils.setRejectUnauthorizedFn(rejectUnauthorizedFnId, function() { return rejectUnauthorized }); - + // define callback for wasm let callbackFn = async function(cppAddress) { if (typeof cppAddress === "string") reject(new MoneroError(cppAddress)); else resolve(new MoneroWalletFull(cppAddress, config.getPath(), config.getPassword(), config.getFs(), config.getRejectUnauthorized(), rejectUnauthorizedFnId)); }; - + // create wallet in wasm and invoke callback when done module.create_full_wallet(JSON.stringify(config.toJson()), rejectUnauthorizedFnId, callbackFn); }); }); - + // save wallet if (config.getPath()) await wallet.save(); return wallet; } - + static async _createWalletFromKeys(config) { if (config.getProxyToWorker() === undefined) config.setProxyToWorker(true); if (config.getProxyToWorker()) return MoneroWalletFullProxy._createWallet(config); - + // validate and normalize params MoneroNetworkType.validate(config.getNetworkType()); if (config.getPrimaryAddress() === undefined) config.setPrimaryAddress(""); @@ -263,86 +263,86 @@ class MoneroWalletFull extends MoneroWalletKeys { let rejectUnauthorized = daemonConnection ? daemonConnection.getRejectUnauthorized() : true; if (config.getRestoreHeight() === undefined) config.setRestoreHeight(0); if (config.getLanguage() === undefined) config.setLanguage("English"); - + // load full wasm module let module = await LibraryUtils.loadFullModule(); - + // create wallet in queue let wallet = await module.queueTask(async function() { return new Promise(function(resolve, reject) { - + // register fn informing if unauthorized reqs should be rejected let rejectUnauthorizedFnId = GenUtils.getUUID(); LibraryUtils.setRejectUnauthorizedFn(rejectUnauthorizedFnId, function() { return rejectUnauthorized }); - + // define callback for wasm let callbackFn = async function(cppAddress) { if (typeof cppAddress === "string") reject(new MoneroError(cppAddress)); else resolve(new MoneroWalletFull(cppAddress, config.getPath(), config.getPassword(), config.getFs(), config.getRejectUnauthorized(), rejectUnauthorizedFnId)); }; - + // create wallet in wasm and invoke callback when done module.create_full_wallet(JSON.stringify(config.toJson()), rejectUnauthorizedFnId, callbackFn); }); }); - + // save wallet if (config.getPath()) await wallet.save(); return wallet; } - + static async _createWalletRandom(config) { if (config.getProxyToWorker() === undefined) config.setProxyToWorker(true); if (config.getProxyToWorker()) return MoneroWalletFullProxy._createWallet(config); - + // validate and normalize params if (config.getLanguage() === undefined) config.setLanguage("English"); let daemonConnection = config.getServer(); let rejectUnauthorized = daemonConnection ? daemonConnection.getRejectUnauthorized() : true; - + // load wasm module let module = await LibraryUtils.loadFullModule(); - + // create wallet in queue let wallet = await module.queueTask(async function() { return new Promise(function(resolve, reject) { - + // register fn informing if unauthorized reqs should be rejected let rejectUnauthorizedFnId = GenUtils.getUUID(); LibraryUtils.setRejectUnauthorizedFn(rejectUnauthorizedFnId, function() { return rejectUnauthorized }); - + // define callback for wasm let callbackFn = async function(cppAddress) { if (typeof cppAddress === "string") reject(new MoneroError(cppAddress)); else resolve(new MoneroWalletFull(cppAddress, config.getPath(), config.getPassword(), config.getFs(), config.getRejectUnauthorized(), rejectUnauthorizedFnId)); }; - + // create wallet in wasm and invoke callback when done module.create_full_wallet(JSON.stringify(config.toJson()), rejectUnauthorizedFnId, callbackFn); }); }); - + // save wallet if (config.getPath()) await wallet.save(); return wallet; } - + static async getMnemonicLanguages() { let module = await LibraryUtils.loadFullModule(); return module.queueTask(async function() { return JSON.parse(module.get_keys_wallet_mnemonic_languages()).languages; }); } - + // --------------------------- INSTANCE METHODS ----------------------------- - + /** * Internal constructor which is given the memory address of a C++ wallet * instance. - * + * * This method should not be called externally but should be called through * static wallet creation utilities in this class. - * + * * @param {int} cppAddress - address of the wallet instance in C++ * @param {string} path - path of the wallet instance * @param {string} password - password of the wallet instance @@ -365,9 +365,9 @@ class MoneroWalletFull extends MoneroWalletKeys { let that = this; LibraryUtils.setRejectUnauthorizedFn(rejectUnauthorizedFnId, function() { return that._rejectUnauthorized }); // register fn informing if unauthorized reqs should be rejected } - + // ------------ WALLET METHODS SPECIFIC TO WASM IMPLEMENTATION -------------- - + /** * Get the maximum height of the peers the wallet's daemon is connected to. * @@ -378,21 +378,21 @@ class MoneroWalletFull extends MoneroWalletKeys { return that._module.queueTask(async function() { that._assertNotClosed(); return new Promise(function(resolve, reject) { - + // define callback for wasm let callbackFn = function(resp) { resolve(resp); } - + // call wasm and invoke callback when done that._module.get_daemon_max_peer_height(that._cppAddress, callbackFn); }); }); } - + /** * Indicates if the wallet's daemon is synced with the network. - * + * * @return {boolean} true if the daemon is synced with the network, false otherwise */ async isDaemonSynced() { @@ -400,21 +400,21 @@ class MoneroWalletFull extends MoneroWalletKeys { return that._module.queueTask(async function() { that._assertNotClosed(); return new Promise(function(resolve, reject) { - + // define callback for wasm let callbackFn = function(resp) { resolve(resp); } - + // call wasm and invoke callback when done that._module.is_daemon_synced(that._cppAddress, callbackFn); }); }); } - + /** * Indicates if the wallet is synced with the daemon. - * + * * @return {boolean} true if the wallet is synced with the daemon, false otherwise */ async isSynced() { @@ -422,21 +422,21 @@ class MoneroWalletFull extends MoneroWalletKeys { return that._module.queueTask(async function() { that._assertNotClosed(); return new Promise(function(resolve, reject) { - + // define callback for wasm let callbackFn = function(resp) { resolve(resp); } - + // call wasm and invoke callback when done that._module.is_synced(that._cppAddress, callbackFn); }); }); } - + /** * Get the wallet's network type (mainnet, testnet, or stagenet). - * + * * @return {MoneroNetworkType} the wallet's network type */ async getNetworkType() { @@ -446,10 +446,10 @@ class MoneroWalletFull extends MoneroWalletKeys { return that._module.get_network_type(that._cppAddress); }); } - + /** * Get the height of the first block that the wallet scans. - * + * * @return {number} the height of the first block that the wallet scans */ async getSyncHeight() { @@ -459,10 +459,10 @@ class MoneroWalletFull extends MoneroWalletKeys { return that._module.get_sync_height(that._cppAddress); }); } - + /** * Set the height of the first block that the wallet scans. - * + * * @param {number} syncHeight - height of the first block that the wallet scans */ async setSyncHeight(syncHeight) { @@ -472,25 +472,25 @@ class MoneroWalletFull extends MoneroWalletKeys { return that._module.set_sync_height(that._cppAddress, syncHeight); }); } - + /** * Move the wallet from its current path to the given path. - * + * * @param {string} path - the wallet's destination path */ async moveTo(path) { return MoneroWalletFull._moveTo(path, this); } - + // -------------------------- COMMON WALLET METHODS ------------------------- - + async addListener(listener) { this._assertNotClosed(); assert(listener instanceof MoneroWalletListener, "Listener must be instance of MoneroWalletListener"); this._listeners.push(listener); await this._refreshListening(); } - + async removeListener(listener) { this._assertNotClosed(); let idx = this._listeners.indexOf(listener); @@ -498,15 +498,15 @@ class MoneroWalletFull extends MoneroWalletKeys { else throw new MoneroError("Listener is not registered with wallet"); await this._refreshListening(); } - + getListeners() { this._assertNotClosed(); return this._listeners; } - + async setDaemonConnection(uriOrRpcConnection) { this._assertNotClosed(); - + // normalize connection let connection = !uriOrRpcConnection ? undefined : uriOrRpcConnection instanceof MoneroRpcConnection ? uriOrRpcConnection : new MoneroRpcConnection(uriOrRpcConnection); let uri = connection && connection.getUri() ? connection.getUri() : ""; @@ -514,22 +514,22 @@ class MoneroWalletFull extends MoneroWalletKeys { let password = connection && connection.getPassword() ? connection.getPassword() : ""; let rejectUnauthorized = connection ? connection.getRejectUnauthorized() : undefined; this._rejectUnauthorized = rejectUnauthorized; // persist locally - + // set connection in queue let that = this; return that._module.queueTask(async function() { that._assertNotClosed(); return new Promise(function(resolve, reject) { - + // define callback for wasm let callbackFn = function(resp) { resolve(); } - + // call wasm and invoke callback when done that._module.set_daemon_connection(that._cppAddress, uri, username, password, callbackFn); }); }); } - + async getDaemonConnection() { let that = this; return that._module.queueTask(async function() { @@ -544,34 +544,34 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + async isConnectedToDaemon() { let that = this; return that._module.queueTask(async function() { that._assertNotClosed(); return new Promise(function(resolve, reject) { - + // define callback for wasm let callbackFn = function(resp) { resolve(resp); } - + // call wasm and invoke callback when done that._module.is_connected_to_daemon(that._cppAddress, callbackFn); }); }); } - + async getVersion() { this._assertNotClosed(); throw new MoneroError("Not implemented"); } - + async getPath() { this._assertNotClosed(); return this._path; } - + async getIntegratedAddress(standardAddress, paymentId) { let that = this; return that._module.queueTask(async function() { @@ -586,7 +586,7 @@ class MoneroWalletFull extends MoneroWalletKeys { } }); } - + async decodeIntegratedAddress(integratedAddress) { let that = this; return that._module.queueTask(async function() { @@ -600,86 +600,86 @@ class MoneroWalletFull extends MoneroWalletKeys { } }); } - + async getHeight() { let that = this; return that._module.queueTask(async function() { that._assertNotClosed(); return new Promise(function(resolve, reject) { - + // define callback for wasm let callbackFn = function(resp) { resolve(resp); } - + // call wasm and invoke callback when done that._module.get_height(that._cppAddress, callbackFn); }); }); } - + async getDaemonHeight() { this._assertNotClosed(); if (!(await this.isConnectedToDaemon())) throw new MoneroError("Wallet is not connected to daemon"); - + // schedule task let that = this; return that._module.queueTask(async function() { that._assertNotClosed(); return new Promise(function(resolve, reject) { - + // define callback for wasm let callbackFn = function(resp) { resolve(resp); } - + // call wasm and invoke callback when done that._module.get_daemon_height(that._cppAddress, callbackFn); }); }); } - + async getHeightByDate(year, month, day) { this._assertNotClosed(); if (!(await this.isConnectedToDaemon())) throw new MoneroError("Wallet is not connected to daemon"); - + // schedule task let that = this; return that._module.queueTask(async function() { that._assertNotClosed(); return new Promise(function(resolve, reject) { - + // define callback for wasm let callbackFn = function(resp) { if (typeof resp === "string") reject(new MoneroError(resp)); else resolve(resp); } - + // call wasm and invoke callback when done that._module.get_height_by_date(that._cppAddress, year, month, day, callbackFn); }); }); } - + /** * Synchronize the wallet with the daemon as a one-time synchronous process. - * + * * @param {MoneroWalletListener|number} listenerOrStartHeight - listener xor start height (defaults to no sync listener, the last synced block) * @param {number} startHeight - startHeight if not given in first arg (defaults to last synced block) - * @param {bool} allowConcurrentCalls - allow other wallet methods to be processed simultaneously during sync (default false)

WARNING: enabling this option will crash wallet execution if another call makes a simultaneous network request. TODO: possible to sync wasm network requests in http_client_wasm.cpp? + * @param {bool} allowConcurrentCalls - allow other wallet methods to be processed simultaneously during sync (default false)

WARNING: enabling this option will crash wallet execution if another call makes a simultaneous network request. TODO: possible to sync wasm network requests in http_client_wasm.cpp? */ async sync(listenerOrStartHeight, startHeight, allowConcurrentCalls) { this._assertNotClosed(); if (!(await this.isConnectedToDaemon())) throw new MoneroError("Wallet is not connected to daemon"); - + // normalize params startHeight = listenerOrStartHeight === undefined || listenerOrStartHeight instanceof MoneroWalletListener ? startHeight : listenerOrStartHeight; let listener = listenerOrStartHeight instanceof MoneroWalletListener ? listenerOrStartHeight : undefined; if (startHeight === undefined) startHeight = Math.max(await this.getHeight(), await this.getSyncHeight()); - + // register listener if given if (listener) await this.addListener(listener); - + // sync wallet let err; let result; @@ -689,7 +689,7 @@ class MoneroWalletFull extends MoneroWalletKeys { function syncWasm() { that._assertNotClosed(); return new Promise(function(resolve, reject) { - + // define callback for wasm let callbackFn = async function(resp) { if (resp.charAt(0) !== "{") reject(new MoneroError(resp)); @@ -698,7 +698,7 @@ class MoneroWalletFull extends MoneroWalletKeys { resolve(new MoneroSyncResult(respJson.numBlocksFetched, respJson.receivedMoney)); } } - + // sync wallet in wasm and invoke callback when done that._module.sync(that._cppAddress, startHeight, callbackFn); }); @@ -706,15 +706,15 @@ class MoneroWalletFull extends MoneroWalletKeys { } catch (e) { err = e; } - + // unregister listener if (listener) await this.removeListener(listener); - + // throw error or return if (err) throw err; return result; } - + async startSyncing(syncPeriodInMs) { this._assertNotClosed(); if (!(await this.isConnectedToDaemon())) throw new MoneroError("Wallet is not connected to daemon"); @@ -723,13 +723,13 @@ class MoneroWalletFull extends MoneroWalletKeys { if (!this._syncLooper) this._syncLooper = new TaskLooper(async function() { await that._backgroundSync(); }) this._syncLooper.start(this._syncPeriodInMs); } - + async stopSyncing() { this._assertNotClosed(); if (this._syncLooper) this._syncLooper.stop(); this._module.stop_syncing(this._cppAddress); // task is not queued so wallet stops immediately } - + async scanTxs(txHashes) { let that = this; return that._module.queueTask(async function() { @@ -738,12 +738,12 @@ class MoneroWalletFull extends MoneroWalletKeys { let callbackFn = function(err) { if (err) reject(new MoneroError(msg)); else resolve(); - } + } that._module.scan_txs(that._cppAddress, JSON.stringify({txHashes: txHashes}), callbackFn); }); }); } - + async rescanSpent() { let that = this; return that._module.queueTask(async function() { @@ -754,7 +754,7 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + async rescanBlockchain() { let that = this; return that._module.queueTask(async function() { @@ -771,7 +771,7 @@ class MoneroWalletFull extends MoneroWalletKeys { return that._module.queueTask(async function() { that._assertNotClosed(); return new Promise(function(resolve, reject) { - let callbackFn = function(resp) { + let callbackFn = function(resp) { const circulatingSupply = new HavenCirculatingSupply(JSON.parse(GenUtils.stringifyBIs(resp)).circulating_supply) resolve(circulatingSupply); } that._module.get_circulating_supply(that._cppAddress, callbackFn); @@ -784,7 +784,7 @@ class MoneroWalletFull extends MoneroWalletKeys { return that._module.queueTask(async function() { that._assertNotClosed(); return new Promise(function(resolve, reject) { - let callbackFn = function(resp) { + let callbackFn = function(resp) { const amount = BigInteger.parse(JSON.parse(GenUtils.stringifyBIs(resp)).block_cap) resolve(amount); } that._module.get_block_cap(that._cppAddress, callbackFn); @@ -797,7 +797,7 @@ class MoneroWalletFull extends MoneroWalletKeys { return that._module.queueTask(async function() { that._assertNotClosed(); return new Promise(function(resolve, reject) { - let callbackFn = function(resp) { + let callbackFn = function(resp) { const amount = BigInteger.parse(JSON.parse(GenUtils.stringifyBIs(resp)).max_destination_amount) resolve(amount); } that._module.get_max_destination_amount(that._cppAddress, sourceAssetType, destinationAssetType, callbackFn); @@ -810,19 +810,19 @@ class MoneroWalletFull extends MoneroWalletKeys { return that._module.queueTask(async function() { that._assertNotClosed(); return new Promise(function(resolve, reject) { - let callbackFn = function(resp) { + let callbackFn = function(resp) { const amount = BigInteger.parse(JSON.parse(GenUtils.stringifyBIs(resp)).collateral_requirements) resolve(amount); } that._module.get_collateral_requirements(that._cppAddress, sourceAssetType, destinationAssetType, amount.toString(), callbackFn); }); }); } - + async getBalance(accountIdx, subaddressIdx, assetType) { let that = this; return that._module.queueTask(async function() { that._assertNotClosed(); - + // get balance encoded in json string let balanceStr; if (accountIdx === undefined) { @@ -833,7 +833,7 @@ class MoneroWalletFull extends MoneroWalletKeys { } else { balanceStr = that._module.get_balance_subaddress(that._cppAddress, accountIdx, subaddressIdx); } - + // parse json string to BigInteger return new HavenBalance(JSON.parse(GenUtils.stringifyBIs(balanceStr)).balance, assetType); }); @@ -843,7 +843,7 @@ class MoneroWalletFull extends MoneroWalletKeys { let that = this; return that._module.queueTask(async function() { that._assertNotClosed(); - + // get balance encoded in json string let unlockedBalanceStr; if (accountIdx === undefined) { @@ -854,12 +854,12 @@ class MoneroWalletFull extends MoneroWalletKeys { } else { unlockedBalanceStr = that._module.get_unlocked_balance_subaddress(that._cppAddress, accountIdx, subaddressIdx); } - + // parse json string to BigInteger return new HavenBalance(JSON.parse(GenUtils.stringifyBIs(unlockedBalanceStr)).unlockedBalance, assetType); }); } - + async getAccounts(includeSubaddresses, tag) { let that = this; return that._module.queueTask(async function() { @@ -872,7 +872,7 @@ class MoneroWalletFull extends MoneroWalletKeys { return accounts; }); } - + async getAccount(accountIdx, includeSubaddresses) { let that = this; return that._module.queueTask(async function() { @@ -883,7 +883,7 @@ class MoneroWalletFull extends MoneroWalletKeys { }); } - + async createAccount(label) { if (label === undefined) label = ""; let that = this; @@ -894,7 +894,7 @@ class MoneroWalletFull extends MoneroWalletKeys { return MoneroWalletFull._sanitizeAccount(new MoneroAccount(accountJson)); }); } - + async getSubaddresses(accountIdx, subaddressIndices) { let args = {accountIdx: accountIdx, subaddressIndices: subaddressIndices === undefined ? [] : GenUtils.listify(subaddressIndices)}; let that = this; @@ -906,7 +906,7 @@ class MoneroWalletFull extends MoneroWalletKeys { return subaddresses; }); } - + async createSubaddress(accountIdx, label) { if (label === undefined) label = ""; let that = this; @@ -917,28 +917,28 @@ class MoneroWalletFull extends MoneroWalletKeys { return MoneroWalletFull._sanitizeSubaddress(new MoneroSubaddress(subaddressJson)); }); } - + async getTxs(query, missingTxHashes) { this._assertNotClosed(); - + // copy and normalize query up to block query = MoneroWallet._normalizeTxQuery(query); - + // schedule task let that = this; return that._module.queueTask(async function() { that._assertNotClosed(); return new Promise(function(resolve, reject) { - + // define callback for wasm let callbackFn = function(blocksJsonStr) { - + // check for error if (blocksJsonStr.charAt(0) !== "{") { reject(new MoneroError(blocksJsonStr)); return; } - + // resolve with deserialized txs try { resolve(MoneroWalletFull._deserializeTxs(query, blocksJsonStr, missingTxHashes)); @@ -946,69 +946,69 @@ class MoneroWalletFull extends MoneroWalletKeys { reject(err); } } - + // call wasm and invoke callback when done that._module.get_txs(that._cppAddress, JSON.stringify(query.getBlock().toJson()), callbackFn); }); }); } - + async getTransfers(query) { this._assertNotClosed(); - + // copy and normalize query up to block query = MoneroWallet._normalizeTransferQuery(query); - + // return promise which resolves on callback let that = this; return that._module.queueTask(async function() { that._assertNotClosed(); return new Promise(function(resolve, reject) { - + // define callback for wasm let callbackFn = function(blocksJsonStr) { - + // check for error if (blocksJsonStr.charAt(0) !== "{") { reject(new MoneroError(blocksJsonStr)); return; } - - // resolve with deserialized transfers + + // resolve with deserialized transfers try { resolve(MoneroWalletFull._deserializeTransfers(query, blocksJsonStr)); } catch (err) { reject(err); } } - + // call wasm and invoke callback when done that._module.get_transfers(that._cppAddress, JSON.stringify(query.getTxQuery().getBlock().toJson()), callbackFn); }); }); } - + async getOutputs(query) { this._assertNotClosed(); - + // copy and normalize query up to block query = MoneroWallet._normalizeOutputQuery(query); - + // return promise which resolves on callback let that = this; return that._module.queueTask(async function() { that._assertNotClosed(); return new Promise(function(resolve, reject) { - + // define callback for wasm let callbackFn = function(blocksJsonStr) { - + // check for error if (blocksJsonStr.charAt(0) !== "{") { reject(new MoneroError(blocksJsonStr)); return; } - + // resolve with deserialized outputs try { resolve(MoneroWalletFull._deserializeOutputs(query, blocksJsonStr)); @@ -1016,13 +1016,13 @@ class MoneroWalletFull extends MoneroWalletKeys { reject(err); } } - + // call wasm and invoke callback when done that._module.get_outputs(that._cppAddress, JSON.stringify(query.getTxQuery().getBlock().toJson()), callbackFn); }); }); } - + async exportOutputs(all) { let that = this; return that._module.queueTask(async function() { @@ -1032,7 +1032,7 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + async importOutputs(outputsHex) { let that = this; return that._module.queueTask(async function() { @@ -1042,7 +1042,7 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + async exportKeyImages(all) { let that = this; return that._module.queueTask(async function() { @@ -1057,7 +1057,7 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + async importKeyImages(keyImages) { let that = this; return that._module.queueTask(async function() { @@ -1070,12 +1070,12 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + async getNewKeyImagesFromLastImport() { this._assertNotClosed(); throw new MoneroError("Not implemented"); } - + async freezeOutput(keyImage) { if (!keyImage) throw new MoneroError("Must specify key image to freeze"); let that = this; @@ -1087,7 +1087,7 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + async thawOutput(keyImage) { if (!keyImage) throw new MoneroError("Must specify key image to thaw"); let that = this; @@ -1099,7 +1099,7 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + async isOutputFrozen(keyImage) { if (!keyImage) throw new MoneroError("Must specify key image to check if frozen"); let that = this; @@ -1111,50 +1111,50 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + async createTxs(config) { this._assertNotClosed(); - + // validate, copy, and normalize config config = MoneroWallet._normalizeCreateTxsConfig(config); if (config.getCanSplit() === undefined) config.setCanSplit(true); - + // return promise which resolves on callback let that = this; return that._module.queueTask(async function() { that._assertNotClosed(); return new Promise(function(resolve, reject) { - + // define callback for wasm let callbackFn = function(txSetJsonStr) { if (txSetJsonStr.charAt(0) !== '{') reject(new MoneroError(txSetJsonStr)); // json expected, else error else resolve(new MoneroTxSet(JSON.parse(GenUtils.stringifyBIs(txSetJsonStr))).getTxs()); } - + // create txs in wasm and invoke callback when done that._module.create_txs(that._cppAddress, JSON.stringify(config.toJson()), callbackFn); }); }); } - + async sweepOutput(config) { this._assertNotClosed(); - + // normalize and validate config config = MoneroWallet._normalizeSweepOutputConfig(config); - + // return promise which resolves on callback let that = this; return that._module.queueTask(async function() { that._assertNotClosed(); return new Promise(function(resolve, reject) { - + // define callback for wasm let callbackFn = function(txSetJsonStr) { if (txSetJsonStr.charAt(0) !== '{') reject(new MoneroError(txSetJsonStr)); // json expected, else error else resolve(new MoneroTxSet(JSON.parse(GenUtils.stringifyBIs(txSetJsonStr))).getTxs()[0]); } - + // sweep output in wasm and invoke callback when done that._module.sweep_output(that._cppAddress, JSON.stringify(config.toJson()), callbackFn); }); @@ -1163,16 +1163,16 @@ class MoneroWalletFull extends MoneroWalletKeys { async sweepUnlocked(config) { this._assertNotClosed(); - + // validate and normalize config config = MoneroWallet._normalizeSweepUnlockedConfig(config); - + // return promise which resolves on callback let that = this; return that._module.queueTask(async function() { // TODO: could factor this pattern out, invoked with module params and callback handler that._assertNotClosed(); return new Promise(function(resolve, reject) { - + // define callback for wasm let callbackFn = function(txSetsJson) { if (txSetsJson.charAt(0) !== '{') reject(new MoneroError(txSetsJson)); // json expected, else error @@ -1184,19 +1184,19 @@ class MoneroWalletFull extends MoneroWalletKeys { resolve(txs); } } - + // sweep unlocked in wasm and invoke callback when done that._module.sweep_unlocked(that._cppAddress, JSON.stringify(config.toJson()), callbackFn); }); }); } - + async sweepDust(relay) { let that = this; return that._module.queueTask(async function() { that._assertNotClosed(); return new Promise(function(resolve, reject) { - + // define callback for wasm let callbackFn = function(txSetJsonStr) { if (txSetJsonStr.charAt(0) !== '{') reject(new MoneroError(txSetJsonStr)); // json expected, else error @@ -1206,13 +1206,13 @@ class MoneroWalletFull extends MoneroWalletKeys { resolve(txSet.getTxs()); } } - + // call wasm and invoke callback when done that._module.sweep_dust(that._cppAddress, relay, callbackFn); }); }); } - + async relayTxs(txsOrMetadatas) { this._assertNotClosed(); assert(Array.isArray(txsOrMetadatas), "Must provide an array of txs or their metadata to relay"); @@ -1230,7 +1230,7 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + async describeTxSet(txSet) { let that = this; return that._module.queueTask(async function() { @@ -1243,7 +1243,7 @@ class MoneroWalletFull extends MoneroWalletKeys { catch (err) { throw new MoneroError(that._module.get_exception_message(err)); } }); } - + async signTxs(unsignedTxHex) { let that = this; return that._module.queueTask(async function() { @@ -1252,7 +1252,7 @@ class MoneroWalletFull extends MoneroWalletKeys { catch (err) { throw new MoneroError(that._module.get_exception_message(err)); } }); } - + async submitTxs(signedTxHex) { let that = this; return that._module.queueTask(async function() { @@ -1266,14 +1266,14 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + async signMessage(message, signatureType, accountIdx, subaddressIdx) { - + // assign defaults signatureType = signatureType || MoneroMessageSignatureType.SIGN_WITH_SPEND_KEY; accountIdx = accountIdx || 0; subaddressIdx = subaddressIdx || 0; - + // queue task to sign message let that = this; return that._module.queueTask(async function() { @@ -1282,7 +1282,7 @@ class MoneroWalletFull extends MoneroWalletKeys { catch (err) { throw new MoneroError(that._module.get_exception_message(err)); } }); } - + async verifyMessage(message, address, signature) { let that = this; return that._module.queueTask(async function() { @@ -1301,7 +1301,7 @@ class MoneroWalletFull extends MoneroWalletKeys { return result; }); } - + async getTxKey(txHash) { let that = this; return that._module.queueTask(async function() { @@ -1310,11 +1310,11 @@ class MoneroWalletFull extends MoneroWalletKeys { catch (err) { throw new MoneroError(that._module.get_exception_message(err)); } }); } - + async checkTxKey(txHash, txKey, address) { let that = this; return that._module.queueTask(async function() { - that._assertNotClosed(); + that._assertNotClosed(); return new Promise(function(resolve, reject) { that._module.check_tx_key(that._cppAddress, txHash, txKey, address, function(respJsonStr) { if (respJsonStr.charAt(0) !== "{") reject(new MoneroError(respJsonStr)); @@ -1323,7 +1323,7 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + async getTxProof(txHash, address, message) { let that = this; return that._module.queueTask(async function() { @@ -1337,11 +1337,11 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + async checkTxProof(txHash, address, message, signature) { let that = this; return that._module.queueTask(async function() { - that._assertNotClosed(); + that._assertNotClosed(); return new Promise(function(resolve, reject) { that._module.check_tx_proof(that._cppAddress, txHash || "", address || "", message || "", signature || "", function(respJsonStr) { if (respJsonStr.charAt(0) !== "{") reject(new MoneroError(respJsonStr)); @@ -1350,7 +1350,7 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + async getSpendProof(txHash, message) { let that = this; return that._module.queueTask(async function() { @@ -1364,11 +1364,11 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + async checkSpendProof(txHash, message, signature) { let that = this; return that._module.queueTask(async function() { - that._assertNotClosed(); + that._assertNotClosed(); return new Promise(function(resolve, reject) { that._module.check_spend_proof(that._cppAddress, txHash || "", message || "", signature || "", function(resp) { typeof resp === "string" ? reject(new MoneroError(resp)) : resolve(resp); @@ -1376,7 +1376,7 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + async getReserveProofWallet(message) { let that = this; return that._module.queueTask(async function() { @@ -1390,7 +1390,7 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + async getReserveProofAccount(accountIdx, amount, message) { let that = this; return that._module.queueTask(async function() { @@ -1408,7 +1408,7 @@ class MoneroWalletFull extends MoneroWalletKeys { async checkReserveProof(address, message, signature) { let that = this; return that._module.queueTask(async function() { - that._assertNotClosed(); + that._assertNotClosed(); return new Promise(function(resolve, reject) { that._module.check_reserve_proof(that._cppAddress, address, message, signature, function(respJsonStr) { if (respJsonStr.charAt(0) !== "{") reject(new MoneroError(respJsonStr, -1)); @@ -1417,7 +1417,7 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + async getTxNotes(txHashes) { let that = this; return that._module.queueTask(async function() { @@ -1426,7 +1426,7 @@ class MoneroWalletFull extends MoneroWalletKeys { catch (err) { throw new MoneroError(that._module.get_exception_message(err)); } }); } - + async setTxNotes(txHashes, notes) { let that = this; return that._module.queueTask(async function() { @@ -1435,7 +1435,7 @@ class MoneroWalletFull extends MoneroWalletKeys { catch (err) { throw new MoneroError(that._module.get_exception_message(err)); } }); } - + async getAddressBookEntries(entryIndices) { if (!entryIndices) entryIndices = []; let that = this; @@ -1448,7 +1448,7 @@ class MoneroWalletFull extends MoneroWalletKeys { return entries; }); } - + async addAddressBookEntry(address, description) { if (!address) address = ""; if (!description) description = ""; @@ -1458,7 +1458,7 @@ class MoneroWalletFull extends MoneroWalletKeys { return that._module.add_address_book_entry(that._cppAddress, address, description); }); } - + async editAddressBookEntry(index, setAddress, address, setDescription, description) { if (!setAddress) setAddress = false; if (!address) address = ""; @@ -1470,7 +1470,7 @@ class MoneroWalletFull extends MoneroWalletKeys { that._module.edit_address_book_entry(that._cppAddress, index, setAddress, address, setDescription, description); }); } - + async deleteAddressBookEntry(entryIdx) { let that = this; return that._module.queueTask(async function() { @@ -1478,7 +1478,7 @@ class MoneroWalletFull extends MoneroWalletKeys { that._module.delete_address_book_entry(that._cppAddress, entryIdx); }); } - + async tagAccounts(tag, accountIndices) { if (!tag) tag = ""; if (!accountIndices) accountIndices = []; @@ -1497,7 +1497,7 @@ class MoneroWalletFull extends MoneroWalletKeys { that._module.tag_accounts(that._cppAddress, JSON.stringify({accountIndices: accountIndices})); }); } - + async getAccountTags() { let that = this; return that._module.queueTask(async function() { @@ -1517,7 +1517,7 @@ class MoneroWalletFull extends MoneroWalletKeys { that._module.set_account_tag_label(that._cppAddress, tag, label); }); } - + async getPaymentUri(config) { config = MoneroWallet._normalizeCreateTxsConfig(config); let that = this; @@ -1530,7 +1530,7 @@ class MoneroWalletFull extends MoneroWalletKeys { } }); } - + async parsePaymentUri(uri) { let that = this; return that._module.queueTask(async function() { @@ -1542,7 +1542,7 @@ class MoneroWalletFull extends MoneroWalletKeys { } }); } - + async getAttribute(key) { this._assertNotClosed(); assert(typeof key === "string", "Attribute key must be a string"); @@ -1553,7 +1553,7 @@ class MoneroWalletFull extends MoneroWalletKeys { return value === "" ? null : value; }); } - + async setAttribute(key, val) { this._assertNotClosed(); assert(typeof key === "string", "Attribute key must be a string"); @@ -1564,19 +1564,19 @@ class MoneroWalletFull extends MoneroWalletKeys { that._module.set_attribute(that._cppAddress, key, val); }); } - + async startMining(numThreads, backgroundMining, ignoreBattery) { this._assertNotClosed(); let daemon = new MoneroDaemonRpc(Object.assign((await this.getDaemonConnection()).getConfig(), {proxyToWorker: false})); await daemon.startMining(await this.getPrimaryAddress(), numThreads, backgroundMining, ignoreBattery); } - + async stopMining() { this._assertNotClosed(); let daemon = new MoneroDaemonRpc(Object.assign((await this.getDaemonConnection()).getConfig(), {proxyToWorker: false})); await daemon.stopMining(); } - + async isMultisigImportNeeded() { let that = this; return that._module.queueTask(async function() { @@ -1584,7 +1584,7 @@ class MoneroWalletFull extends MoneroWalletKeys { return that._module.is_multisig_import_needed(that._cppAddress); }); } - + async isMultisig() { let that = this; return that._module.queueTask(async function() { @@ -1592,7 +1592,7 @@ class MoneroWalletFull extends MoneroWalletKeys { return that._module.is_multisig(that._cppAddress); }); } - + async getMultisigInfo() { let that = this; return that._module.queueTask(async function() { @@ -1600,7 +1600,7 @@ class MoneroWalletFull extends MoneroWalletKeys { return new MoneroMultisigInfo(JSON.parse(that._module.get_multisig_info(that._cppAddress))); }); } - + async prepareMultisig() { let that = this; return that._module.queueTask(async function() { @@ -1608,7 +1608,7 @@ class MoneroWalletFull extends MoneroWalletKeys { return that._module.prepare_multisig(that._cppAddress); }); } - + async makeMultisig(multisigHexes, threshold, password) { let that = this; return that._module.queueTask(async function() { @@ -1622,7 +1622,7 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + async exchangeMultisigKeys(multisigHexes, password) { let that = this; return that._module.queueTask(async function() { @@ -1636,7 +1636,7 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + async exportMultisigHex() { let that = this; return that._module.queueTask(async function() { @@ -1644,7 +1644,7 @@ class MoneroWalletFull extends MoneroWalletKeys { return that._module.export_multisig_hex(that._cppAddress); }); } - + async importMultisigHex(multisigHexes) { if (!GenUtils.isArray(multisigHexes)) throw new MoneroError("Must provide string[] to importMultisigHex()") let that = this; @@ -1659,7 +1659,7 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + async signMultisigTxHex(multisigTxHex) { let that = this; return that._module.queueTask(async function() { @@ -1673,7 +1673,7 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + async submitMultisigTxHex(signedMultisigTxHex) { let that = this; return that._module.queueTask(async function() { @@ -1684,57 +1684,57 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + /** * Get the wallet's keys and cache data. - * + * * @return {DataView[]} is the keys and cache data respectively */ async getData() { this._assertNotClosed(); - + // queue call to wasm module let viewOnly = await this.isViewOnly(); let that = this; return that._module.queueTask(async function() { that._assertNotClosed(); - + // store views in array let views = []; - + // malloc cache buffer and get buffer location in c++ heap let cacheBufferLoc = JSON.parse(that._module.get_cache_file_buffer(that._cppAddress, that._password)); - + // read binary data from heap to DataView let view = new DataView(new ArrayBuffer(cacheBufferLoc.length)); for (let i = 0; i < cacheBufferLoc.length; i++) { view.setInt8(i, that._module.HEAPU8[cacheBufferLoc.pointer / Uint8Array.BYTES_PER_ELEMENT + i]); } - + // free binary on heap that._module._free(cacheBufferLoc.pointer); - + // write cache file views.push(Buffer.from(view.buffer)); - + // malloc keys buffer and get buffer location in c++ heap let keysBufferLoc = JSON.parse(that._module.get_keys_file_buffer(that._cppAddress, that._password, viewOnly)); - + // read binary data from heap to DataView view = new DataView(new ArrayBuffer(keysBufferLoc.length)); for (let i = 0; i < keysBufferLoc.length; i++) { view.setInt8(i, that._module.HEAPU8[keysBufferLoc.pointer / Uint8Array.BYTES_PER_ELEMENT + i]); } - + // free binary on heap that._module._free(keysBufferLoc.pointer); - + // prepend keys file views.unshift(Buffer.from(view.buffer)); return views; }); } - + async changePassword(oldPassword, newPassword) { if (oldPassword !== this._password) throw new MoneroError("Invalid original password."); // wallet2 verify_password loads from disk so verify password here let that = this; @@ -1750,11 +1750,11 @@ class MoneroWalletFull extends MoneroWalletKeys { this._password = newPassword; if (this._path) await this.save(); // auto save } - + async save() { return MoneroWalletFull._save(this); } - + async close(save) { if (this._isClosed) return; // no effect if closed await this._refreshListening(); @@ -1766,9 +1766,9 @@ class MoneroWalletFull extends MoneroWalletKeys { delete this._fullListener; LibraryUtils.setRejectUnauthorizedFn(this._rejectUnauthorizedConfigId, undefined); // unregister fn informing if unauthorized reqs should be rejected } - + // ----------- ADD JSDOC FOR SUPPORTED DEFAULT IMPLEMENTATIONS -------------- - + async getNumBlocksToUnlock() { return super.getNumBlocksToUnlock(...arguments); } async getTx() { return super.getTx(...arguments); } async getIncomingTransfers() { return super.getIncomingTransfers(...arguments); } @@ -1777,17 +1777,17 @@ class MoneroWalletFull extends MoneroWalletKeys { async relayTx() { return super.relayTx(...arguments); } async getTxNote() { return super.getTxNote(...arguments); } async setTxNote() { return super.setTxNote(...arguments); } - + // ---------------------------- PRIVATE HELPERS ---------------------------- - + static _getFs() { if (!MoneroWalletFull.FS) MoneroWalletFull.FS = GenUtils.isBrowser() ? undefined : require('fs'); return MoneroWalletFull.FS; } - + static async _openWalletData(path, password, networkType, keysData, cacheData, daemonUriOrConnection, proxyToWorker, fs) { if (proxyToWorker) return MoneroWalletFullProxy.openWalletData(path, password, networkType, keysData, cacheData, daemonUriOrConnection, fs); - + // validate and normalize parameters assert(password, "Must provide a password to open the wallet"); if (networkType === undefined) throw new MoneroError("Must provide the wallet's network type"); @@ -1797,37 +1797,37 @@ class MoneroWalletFull extends MoneroWalletKeys { let daemonUsername = daemonConnection && daemonConnection.getUsername() ? daemonConnection.getUsername() : ""; let daemonPassword = daemonConnection && daemonConnection.getPassword() ? daemonConnection.getPassword() : ""; let rejectUnauthorized = daemonConnection ? daemonConnection.getRejectUnauthorized() : true; - + // load wasm module let module = await LibraryUtils.loadFullModule(); - + // open wallet in queue return module.queueTask(async function() { return new Promise(function(resolve, reject) { - + // register fn informing if unauthorized reqs should be rejected let rejectUnauthorizedFnId = GenUtils.getUUID(); LibraryUtils.setRejectUnauthorizedFn(rejectUnauthorizedFnId, function() { return rejectUnauthorized }); - + // define callback for wasm let callbackFn = async function(cppAddress) { if (typeof cppAddress === "string") reject(new MoneroError(cppAddress)); else resolve(new MoneroWalletFull(cppAddress, path, password, fs, rejectUnauthorized, rejectUnauthorizedFnId)); }; - + // create wallet in wasm and invoke callback when done module.open_wallet_full(password, networkType, keysData, cacheData, daemonUri, daemonUsername, daemonPassword, rejectUnauthorizedFnId, callbackFn); }); }); } - + async _backgroundSync() { let label = this._path ? this._path : (this._browserMainPath ? this._browserMainPath : "in-memory wallet"); // label for log LibraryUtils.log(1, "Background synchronizing " + label); try { await this.sync(); } catch (err) { if (!this._isClosed) console.error("Failed to background synchronize " + label + ": " + err.message); } } - + async _refreshListening() { let isEnabled = this._listeners.length > 0; let that = this; @@ -1853,29 +1853,29 @@ class MoneroWalletFull extends MoneroWalletKeys { }); }); } - + static _sanitizeBlock(block) { for (let tx of block.getTxs()) MoneroWalletFull._sanitizeTxWallet(tx); return block; } - + static _sanitizeTxWallet(tx) { assert(tx instanceof MoneroTxWallet); return tx; } - + static _sanitizeAccount(account) { if (account.getSubaddresses()) { for (let subaddress of account.getSubaddresses()) MoneroWalletFull._sanitizeSubaddress(subaddress); } return account; } - + static _sanitizeSubaddress(subaddress) { if (subaddress.getLabel() === "") subaddress.setLabel(undefined); return subaddress } - + static _deserializeBlocks(blocksJsonStr) { let blocksJson = JSON.parse(GenUtils.stringifyBIs(blocksJsonStr)); let deserializedBlocks = {}; @@ -1885,15 +1885,15 @@ class MoneroWalletFull extends MoneroWalletKeys { if (blocksJson.missingTxHashes) for (let missingTxHash of blocksJson.missingTxHashes) deserializedBlocks.missingTxHashes.push(missingTxHash); return deserializedBlocks; } - + static _deserializeTxs(query, blocksJsonStr, missingTxHashes) { - + // deserialize blocks let deserializedBlocks = MoneroWalletFull._deserializeBlocks(blocksJsonStr); if (missingTxHashes === undefined && deserializedBlocks.missingTxHashes.length > 0) throw new MoneroError("Wallet missing requested tx hashes: " + deserializedBlocks.missingTxHashes); for (let missingTxHash of deserializedBlocks.missingTxHashes) missingTxHashes.push(missingTxHash); let blocks = deserializedBlocks.blocks; - + // collect txs let txs = []; for (let block of blocks) { @@ -1903,7 +1903,7 @@ class MoneroWalletFull extends MoneroWalletKeys { txs.push(tx); } } - + // re-sort txs which is lost over wasm serialization // TODO: confirm that order is lost if (query.getHashes() !== undefined) { let txMap = new Map(); @@ -1912,17 +1912,17 @@ class MoneroWalletFull extends MoneroWalletKeys { for (let txHash of query.getHashes()) if (txMap[txHash] !== undefined) txsSorted.push(txMap[txHash]); txs = txsSorted; } - + return txs; } - + static _deserializeTransfers(query, blocksJsonStr) { - + // deserialize blocks let deserializedBlocks = MoneroWalletFull._deserializeBlocks(blocksJsonStr); if (deserializedBlocks.missingTxHashes.length > 0) throw new MoneroError("Wallet missing requested tx hashes: " + deserializedBlocks.missingTxHashes); let blocks = deserializedBlocks.blocks; - + // collect transfers let transfers = []; for (let block of blocks) { @@ -1934,17 +1934,17 @@ class MoneroWalletFull extends MoneroWalletKeys { } } } - + return transfers; } - + static _deserializeOutputs(query, blocksJsonStr) { - + // deserialize blocks let deserializedBlocks = MoneroWalletFull._deserializeBlocks(blocksJsonStr); if (deserializedBlocks.missingTxHashes.length > 0) throw new MoneroError("Wallet missing requested tx hashes: " + deserializedBlocks.missingTxHashes); let blocks = deserializedBlocks.blocks; - + // collect outputs let outputs = []; for (let block of blocks) { @@ -1952,37 +1952,37 @@ class MoneroWalletFull extends MoneroWalletKeys { for (let output of tx.getOutputs()) outputs.push(output); } } - + return outputs; } - + /** * Set the path of the wallet on the browser main thread if run as a worker. - * + * * @param {string} browserMainPath - path of the wallet on the browser main thread */ _setBrowserMainPath(browserMainPath) { this._browserMainPath = browserMainPath; } - + static async _moveTo(path, wallet) { if (await wallet.isClosed()) throw new MoneroError("Wallet is closed"); if (!path) throw new MoneroError("Must provide path of destination wallet"); - + // save and return if same path const Path = require("path"); if (Path.normalize(wallet._path) === Path.normalize(path)) { await wallet.save(); return; } - + // create destination directory if it doesn't exist let walletDir = Path.dirname(path); if (!wallet._fs.existsSync(walletDir)) { try { wallet._fs.mkdirSync(walletDir); } catch (err) { throw new MoneroError("Destination path " + path + " does not exist and cannot be created: " + err.message); } } - + // write wallet files let data = await wallet.getData(); wallet._fs.writeFileSync(path + ".keys", data[0], "binary"); @@ -1990,7 +1990,7 @@ class MoneroWalletFull extends MoneroWalletKeys { wallet._fs.writeFileSync(path + ".address.txt", await wallet.getPrimaryAddress()); let oldPath = wallet._path; wallet._path = path; - + // delete old wallet files if (oldPath) { wallet._fs.unlinkSync(oldPath + ".address.txt"); @@ -1998,21 +1998,21 @@ class MoneroWalletFull extends MoneroWalletKeys { wallet._fs.unlinkSync(oldPath); } } - + static async _save(wallet) { if (await wallet.isClosed()) throw new MoneroError("Wallet is closed"); - + // path must be set let path = await wallet.getPath(); if (!path) throw new MoneroError("Cannot save wallet because path is not set"); - + // write wallet files to *.new let pathNew = path + ".new"; let data = await wallet.getData(); wallet._fs.writeFileSync(pathNew + ".keys", data[0], "binary"); wallet._fs.writeFileSync(pathNew, data[1], "binary"); wallet._fs.writeFileSync(pathNew + ".address.txt", await wallet.getPrimaryAddress()); - + // replace old wallet files with new wallet._fs.renameSync(pathNew + ".keys", path + ".keys"); wallet._fs.renameSync(pathNew, path, path + ".keys"); @@ -2022,18 +2022,18 @@ class MoneroWalletFull extends MoneroWalletKeys { /** * Implements a MoneroWallet by proxying requests to a worker which runs a full wallet. - * + * * TODO: sort these methods according to master sort in MoneroWallet.js * TODO: probably only allow one listener to worker then propogate to registered listeners for performance * TODO: ability to recycle worker for use in another wallet * TODO: using LibraryUtils.WORKER_OBJECTS directly breaks encapsulation - * + * * @private */ class MoneroWalletFullProxy extends MoneroWallet { - + // -------------------------- WALLET STATIC UTILS --------------------------- - + static async openWalletData(path, password, networkType, keysData, cacheData, daemonUriOrConnection, fs) { let walletId = GenUtils.getUUID(); let daemonUriOrConfig = daemonUriOrConnection instanceof MoneroRpcConnection ? daemonUriOrConnection.getConfig() : daemonUriOrConnection; @@ -2042,7 +2042,7 @@ class MoneroWalletFullProxy extends MoneroWallet { if (path) await wallet.save(); return wallet; } - + static async _createWallet(config) { if (config.getPath() && MoneroWalletFull.walletExists(config.getPath(), config.getFs())) throw new MoneroError("Wallet already exists: " + path); let walletId = GenUtils.getUUID(); @@ -2051,15 +2051,15 @@ class MoneroWalletFullProxy extends MoneroWallet { if (config.getPath()) await wallet.save(); return wallet; } - + // --------------------------- INSTANCE METHODS ---------------------------- - + /** * Internal constructor which is given a worker to communicate with via messages. - * + * * This method should not be called externally but should be called through * static wallet creation utilities in this class. - * + * * @param {string} walletId - identifies the wallet with the worker * @param {Worker} worker - worker to communicate with via messages */ @@ -2071,113 +2071,113 @@ class MoneroWalletFullProxy extends MoneroWallet { this._fs = fs ? fs : (path ? MoneroWalletFull._getFs() : undefined); this._wrappedListeners = []; } - + async isViewOnly() { return this._invokeWorker("isViewOnly"); } - + async getNetworkType() { return this._invokeWorker("getNetworkType"); } - + async getVersion() { throw new MoneroError("Not implemented"); } - + getPath() { return this._path; } - + async getMnemonic() { return this._invokeWorker("getMnemonic"); } - + async getMnemonicLanguage() { return this._invokeWorker("getMnemonicLanguage"); } - + async getMnemonicLanguages() { return this._invokeWorker("getMnemonicLanguages"); } - + async getPrivateSpendKey() { return this._invokeWorker("getPrivateSpendKey"); } - + async getPrivateViewKey() { return this._invokeWorker("getPrivateViewKey"); } - + async getPublicViewKey() { return this._invokeWorker("getPublicViewKey"); } - + async getPublicSpendKey() { return this._invokeWorker("getPublicSpendKey"); } - + async getAddress(accountIdx, subaddressIdx) { return this._invokeWorker("getAddress", Array.from(arguments)); } - + async getAddressIndex(address) { let subaddressJson = await this._invokeWorker("getAddressIndex", Array.from(arguments)); return MoneroWalletFull._sanitizeSubaddress(new MoneroSubaddress(subaddressJson)); } - + async getIntegratedAddress(standardAddress, paymentId) { return new MoneroIntegratedAddress(await this._invokeWorker("getIntegratedAddress", Array.from(arguments))); } - + async decodeIntegratedAddress(integratedAddress) { return new MoneroIntegratedAddress(await this._invokeWorker("decodeIntegratedAddress", Array.from(arguments))); } - + async setDaemonConnection(uriOrRpcConnection) { if (!uriOrRpcConnection) await this._invokeWorker("setDaemonConnection"); else { let connection = !uriOrRpcConnection ? undefined : uriOrRpcConnection instanceof MoneroRpcConnection ? uriOrRpcConnection : new MoneroRpcConnection(uriOrRpcConnection); await this._invokeWorker("setDaemonConnection", connection ? connection.getConfig() : undefined); } - } + } async getDaemonConnection() { let rpcConfig = await this._invokeWorker("getDaemonConnection"); return rpcConfig ? new MoneroRpcConnection(rpcConfig) : undefined; } - + async isConnectedToDaemon() { return this._invokeWorker("isConnectedToDaemon"); } - + async getSyncHeight() { return this._invokeWorker("getSyncHeight"); } - + async setSyncHeight(syncHeight) { return this._invokeWorker("setSyncHeight", [syncHeight]); } - + async getDaemonHeight() { return this._invokeWorker("getDaemonHeight"); } - + async getDaemonMaxPeerHeight() { return this._invokeWorker("getDaemonMaxPeerHeight"); } - + async getHeightByDate(year, month, day) { return this._invokeWorker("getHeightByDate", [year, month, day]); } - + async isDaemonSynced() { return this._invokeWorker("isDaemonSynced"); } - + async getHeight() { return this._invokeWorker("getHeight"); } - + async addListener(listener) { let wrappedListener = new WalletWorkerListener(listener); let listenerId = wrappedListener.getId(); @@ -2189,7 +2189,7 @@ class MoneroWalletFullProxy extends MoneroWallet { this._wrappedListeners.push(wrappedListener); return this._invokeWorker("addListener", [listenerId]); } - + async removeListener(listener) { for (let i = 0; i < this._wrappedListeners.length; i++) { if (this._wrappedListeners[i].getListener() === listener) { @@ -2206,28 +2206,28 @@ class MoneroWalletFullProxy extends MoneroWallet { } throw new MoneroError("Listener is not registered with wallet"); } - + getListeners() { let listeners = []; for (let wrappedListener of this._wrappedListeners) listeners.push(wrappedListener.getListener()); return listeners; } - + async isSynced() { return this._invokeWorker("isSynced"); } - + async sync(listenerOrStartHeight, startHeight, allowConcurrentCalls) { - + // normalize params startHeight = listenerOrStartHeight instanceof MoneroWalletListener ? startHeight : listenerOrStartHeight; let listener = listenerOrStartHeight instanceof MoneroWalletListener ? listenerOrStartHeight : undefined; if (startHeight === undefined) startHeight = Math.max(await this.getHeight(), await this.getSyncHeight()); - + // register listener if given if (listener) await this.addListener(listener); - - // sync wallet in worker + + // sync wallet in worker let err; let result; try { @@ -2236,32 +2236,32 @@ class MoneroWalletFullProxy extends MoneroWallet { } catch (e) { err = e; } - + // unregister listener if (listener) await this.removeListener(listener); - + // throw error or return if (err) throw err; return result; } - + async startSyncing(syncPeriodInMs) { return this._invokeWorker("startSyncing", Array.from(arguments)); } - + async stopSyncing() { return this._invokeWorker("stopSyncing"); } - + async scanTxs(txHashes) { assert(Array.isArray(txHashes), "Must provide an array of txs hashes to scan"); return this._invokeWorker("scanTxs", [txHashes]); } - + async rescanSpent() { return this._invokeWorker("rescanSpent"); } - + async rescanBlockchain() { return this._invokeWorker("rescanBlockchain"); } @@ -2270,32 +2270,32 @@ class MoneroWalletFullProxy extends MoneroWallet { const circulatingSupply = await this._invokeWorker("getCirculatingSupply"); return new HavenCirculatingSupply(circulatingSupply); } - + async getBlockCap() { const blockCap = await this._invokeWorker("getBlockCap"); return BigInteger.parse(blockCap); } - + async getMaxDestinationAmount (sourceAssetType, destinationAssetType) { const maxAmount = await this._invokeWorker("getMaxDestinationAmount",Array.from(arguments)); return BigInteger.parse(maxAmount); } - + async getCollateralRequirements(sourceAssetType, destinationAssetType, amount) { const collateral = await this._invokeWorker("getCollateralRequirements", Array.from(arguments)); return BigInteger.parse(collateral); } - + async getBalance(accountIdx, subaddressIdx, assetType) { const lockedBalance = await this._invokeWorker("getBalance", Array.from(arguments)); return new HavenBalance(lockedBalance); } - + async getUnlockedBalance(accountIdx, subaddressIdx, assetType) { let unlockedBalanceStr = await this._invokeWorker("getUnlockedBalance", Array.from(arguments)); return new HavenBalance(unlockedBalanceStr); } - + async getAccounts(includeSubaddresses, tag) { let accounts = []; for (let accountJson of (await this._invokeWorker("getAccounts", Array.from(arguments)))) { @@ -2303,17 +2303,17 @@ class MoneroWalletFullProxy extends MoneroWallet { } return accounts; } - + async getAccount(accountIdx, includeSubaddresses) { let accountJson = await this._invokeWorker("getAccount", Array.from(arguments)); return MoneroWalletFull._sanitizeAccount(new MoneroAccount(accountJson)); } - + async createAccount(label) { let accountJson = await this._invokeWorker("createAccount", Array.from(arguments)); return MoneroWalletFull._sanitizeAccount(new MoneroAccount(accountJson)); } - + async getSubaddresses(accountIdx, subaddressIndices) { let subaddresses = []; for (let subaddressJson of (await this._invokeWorker("getSubaddresses", Array.from(arguments)))) { @@ -2321,72 +2321,72 @@ class MoneroWalletFullProxy extends MoneroWallet { } return subaddresses; } - + async createSubaddress(accountIdx, label) { let subaddressJson = await this._invokeWorker("createSubaddress", Array.from(arguments)); return MoneroWalletFull._sanitizeSubaddress(new MoneroSubaddress(subaddressJson)); } - + async getTxs(query, missingTxHashes) { query = MoneroWallet._normalizeTxQuery(query); let respJson = await this._invokeWorker("getTxs", [query.getBlock().toJson(), missingTxHashes]); return MoneroWalletFull._deserializeTxs(query, JSON.stringify({blocks: respJson.blocks, missingTxHashes: respJson.missingTxHashes}), missingTxHashes); // initialize txs from blocks json string TODO: this stringifies then utility parses, avoid } - + async getTransfers(query) { query = MoneroWallet._normalizeTransferQuery(query); let blockJsons = await this._invokeWorker("getTransfers", [query.getTxQuery().getBlock().toJson()]); return MoneroWalletFull._deserializeTransfers(query, JSON.stringify({blocks: blockJsons})); // initialize transfers from blocks json string TODO: this stringifies then utility parses, avoid } - + async getOutputs(query) { query = MoneroWallet._normalizeOutputQuery(query); let blockJsons = await this._invokeWorker("getOutputs", [query.getTxQuery().getBlock().toJson()]); return MoneroWalletFull._deserializeOutputs(query, JSON.stringify({blocks: blockJsons})); // initialize transfers from blocks json string TODO: this stringifies then utility parses, avoid } - + async exportOutputs(all) { return this._invokeWorker("exportOutputs", [all]); } - + async importOutputs(outputsHex) { return this._invokeWorker("importOutputs", [outputsHex]); } - + async exportKeyImages(all) { let keyImages = []; for (let keyImageJson of await this._invokeWorker("getKeyImages", [all])) keyImages.push(new MoneroKeyImage(keyImageJson)); return keyImages; } - + async importKeyImages(keyImages) { let keyImagesJson = []; for (let keyImage of keyImages) keyImagesJson.push(keyImage.toJson()); return new MoneroKeyImageImportResult(await this._invokeWorker("importKeyImages", [keyImagesJson])); } - + async getNewKeyImagesFromLastImport() { throw new MoneroError("MoneroWalletFull.getNewKeyImagesFromLastImport() not implemented"); } - + async freezeOutput(keyImage) { return this._invokeWorker("freezeOutput", [keyImage]); } - + async thawOutput(keyImage) { return this._invokeWorker("thawOutput", [keyImage]); } - + async isOutputFrozen(keyImage) { return this._invokeWorker("isOutputFrozen", [keyImage]); } - + async createTxs(config) { config = MoneroWallet._normalizeCreateTxsConfig(config); let txSetJson = await this._invokeWorker("createTxs", [config.toJson()]); return new MoneroTxSet(txSetJson).getTxs(); } - + async sweepOutput(config) { config = MoneroWallet._normalizeSweepOutputConfig(config); let txSetJson = await this._invokeWorker("sweepOutput", [config.toJson()]); @@ -2400,66 +2400,66 @@ class MoneroWalletFullProxy extends MoneroWallet { for (let txSetJson of txSetsJson) for (let tx of new MoneroTxSet(txSetJson).getTxs()) txs.push(tx); return txs; } - + async sweepDust(relay) { return new MoneroTxSet(await this._invokeWorker("sweepDust", [relay])).getTxs() || []; } - + async relayTxs(txsOrMetadatas) { assert(Array.isArray(txsOrMetadatas), "Must provide an array of txs or their metadata to relay"); let txMetadatas = []; for (let txOrMetadata of txsOrMetadatas) txMetadatas.push(txOrMetadata instanceof MoneroTxWallet ? txOrMetadata.getMetadata() : txOrMetadata); return this._invokeWorker("relayTxs", [txMetadatas]); } - + async describeTxSet(txSet) { return new MoneroTxSet(await this._invokeWorker("describeTxSet", [txSet.toJson()])); } - + async signTxs(unsignedTxHex) { return this._invokeWorker("signTxs", Array.from(arguments)); } - + async submitTxs(signedTxHex) { return this._invokeWorker("submitTxs", Array.from(arguments)); } - + async signMessage(message, signatureType, accountIdx, subaddressIdx) { return this._invokeWorker("signMessage", Array.from(arguments)); } - + async verifyMessage(message, address, signature) { return new MoneroMessageSignatureResult(await this._invokeWorker("verifyMessage", Array.from(arguments))); } - + async getTxKey(txHash) { return this._invokeWorker("getTxKey", Array.from(arguments)); } - + async checkTxKey(txHash, txKey, address) { return new MoneroCheckTx(await this._invokeWorker("checkTxKey", Array.from(arguments))); } - + async getTxProof(txHash, address, message) { return this._invokeWorker("getTxProof", Array.from(arguments)); } - + async checkTxProof(txHash, address, message, signature) { return new MoneroCheckTx(await this._invokeWorker("checkTxProof", Array.from(arguments))); } - + async getSpendProof(txHash, message) { return this._invokeWorker("getSpendProof", Array.from(arguments)); } - + async checkSpendProof(txHash, message, signature) { return this._invokeWorker("checkSpendProof", Array.from(arguments)); } - + async getReserveProofWallet(message) { return this._invokeWorker("getReserveProofWallet", Array.from(arguments)); } - + async getReserveProofAccount(accountIdx, amount, message) { try { return await this._invokeWorker("getReserveProofAccount", [accountIdx, amount.toString(), message]); } catch (e) { throw new MoneroError(e.message, -1); } @@ -2469,15 +2469,15 @@ class MoneroWalletFullProxy extends MoneroWallet { try { return new MoneroCheckReserve(await this._invokeWorker("checkReserveProof", Array.from(arguments))); } catch (e) { throw new MoneroError(e.message, -1); } } - + async getTxNotes(txHashes) { return this._invokeWorker("getTxNotes", Array.from(arguments)); } - + async setTxNotes(txHashes, notes) { return this._invokeWorker("setTxNotes", Array.from(arguments)); } - + async getAddressBookEntries(entryIndices) { if (!entryIndices) entryIndices = []; let entries = []; @@ -2486,19 +2486,19 @@ class MoneroWalletFullProxy extends MoneroWallet { } return entries; } - + async addAddressBookEntry(address, description) { return this._invokeWorker("addAddressBookEntry", Array.from(arguments)); } - + async editAddressBookEntry(index, setAddress, address, setDescription, description) { return this._invokeWorker("editAddressBookEntry", Array.from(arguments)); } - + async deleteAddressBookEntry(entryIdx) { return this._invokeWorker("deleteAddressBookEntry", Array.from(arguments)); } - + async tagAccounts(tag, accountIndices) { return this._invokeWorker("tagAccounts", Array.from(arguments)); } @@ -2506,7 +2506,7 @@ class MoneroWalletFullProxy extends MoneroWallet { async untagAccounts(accountIndices) { return this._invokeWorker("untagAccounts", Array.from(arguments)); } - + async getAccountTags() { return this._invokeWorker("getAccountTags", Array.from(arguments)); } @@ -2514,102 +2514,102 @@ class MoneroWalletFullProxy extends MoneroWallet { async setAccountTagLabel(tag, label) { return this._invokeWorker("setAccountTagLabel", Array.from(arguments)); } - + async getPaymentUri(config) { config = MoneroWallet._normalizeCreateTxsConfig(config); return this._invokeWorker("getPaymentUri", [config.toJson()]); } - + async parsePaymentUri(uri) { return new MoneroTxConfig(await this._invokeWorker("parsePaymentUri", Array.from(arguments))); } - + async getAttribute(key) { return this._invokeWorker("getAttribute", Array.from(arguments)); } - + async setAttribute(key, val) { return this._invokeWorker("setAttribute", Array.from(arguments)); } - + async startMining(numThreads, backgroundMining, ignoreBattery) { return this._invokeWorker("startMining", Array.from(arguments)); } - + async stopMining() { return this._invokeWorker("stopMining", Array.from(arguments)); } - + async isMultisigImportNeeded() { return this._invokeWorker("isMultisigImportNeeded"); } - + async isMultisig() { return this._invokeWorker("isMultisig"); } - + async getMultisigInfo() { return new MoneroMultisigInfo(await this._invokeWorker("getMultisigInfo")); } - + async prepareMultisig() { return this._invokeWorker("prepareMultisig"); } - + async makeMultisig(multisigHexes, threshold, password) { return await this._invokeWorker("makeMultisig", Array.from(arguments)); } - + async exchangeMultisigKeys(multisigHexes, password) { return new MoneroMultisigInitResult(await this._invokeWorker("exchangeMultisigKeys", Array.from(arguments))); } - + async exportMultisigHex() { return this._invokeWorker("exportMultisigHex"); } - + async importMultisigHex(multisigHexes) { return this._invokeWorker("importMultisigHex", Array.from(arguments)); } - + async signMultisigTxHex(multisigTxHex) { return new MoneroMultisigSignResult(await this._invokeWorker("signMultisigTxHex", Array.from(arguments))); } - + async submitMultisigTxHex(signedMultisigTxHex) { return this._invokeWorker("submitMultisigTxHex", Array.from(arguments)); } - + async getData() { return this._invokeWorker("getData"); } - + async moveTo(path) { return MoneroWalletFull._moveTo(path, this); } - + async changePassword(oldPassword, newPassword) { await this._invokeWorker("changePassword", Array.from(arguments)); if (this._path) await this.save(); // auto save } - + async save() { return MoneroWalletFull._save(this); } - + async close(save) { if (save) await this.save(); while (this._wrappedListeners.length) await this.removeListener(this._wrappedListeners[0].getListener()); await this._invokeWorker("close"); delete LibraryUtils.WORKER_OBJECTS[this._walletId]; } - + async isClosed() { return this._invokeWorker("isClosed"); } - + // --------------------------- PRIVATE HELPERS ------------------------------ - + async _invokeWorker(fnName, args) { return LibraryUtils.invokeWorker(this._walletId, fnName, args); } @@ -2619,29 +2619,29 @@ class MoneroWalletFullProxy extends MoneroWallet { /** * Receives notifications directly from wasm c++. - * + * * @private */ class WalletFullListener { - + constructor(wallet) { this._wallet = wallet; } - + async onSyncProgress(height, startHeight, endHeight, percentDone, message) { for (let listener of this._wallet.getListeners()) await listener.onSyncProgress(height, startHeight, endHeight, percentDone, message); } - + async onNewBlock(height) { for (let listener of this._wallet.getListeners()) await listener.onNewBlock(height); } - + async onBalancesChanged(newBalanceStr, newUnlockedBalanceStr, assetType) { for (let listener of this._wallet.getListeners()) await listener.onBalancesChanged(BigInteger.parse(newBalanceStr), BigInteger.parse(newUnlockedBalanceStr), assetType); } - + async onOutputReceived(height, txHash, amountStr, assetType, accountIdx, subaddressIdx, version, unlockHeight, isLocked) { - + // build received output let output = new MoneroOutputWallet(); output.setAmount(BigInteger.parse(amountStr)); @@ -2667,13 +2667,13 @@ class WalletFullListener { tx.setIsConfirmed(false); tx.setInTxPool(true); } - + // announce output for (let listener of this._wallet.getListeners()) await listener.onOutputReceived(tx.getOutputs()[0]); } - + async onOutputSpent(height, txHash, amountStr, accountIdxStr, subaddressIdxStr, version, unlockHeight, isLocked) { - + // build spent output let output = new MoneroOutputWallet(); output.setAmount(BigInteger.parse(amountStr)); @@ -2697,7 +2697,7 @@ class WalletFullListener { tx.setIsConfirmed(false); tx.setInTxPool(true); } - + // notify wallet listeners for (let listener of this._wallet.getListeners()) await listener.onOutputSpent(tx.getInputs()[0]); } @@ -2705,24 +2705,24 @@ class WalletFullListener { /** * Internal listener to bridge notifications to external listeners. - * + * * @private */ class WalletWorkerListener { - + constructor(listener) { this._id = GenUtils.getUUID(); this._listener = listener; } - + getId() { return this._id; } - + getListener() { return this._listener; } - + onSyncProgress(height, startHeight, endHeight, percentDone, message) { this._listener.onSyncProgress(height, startHeight, endHeight, percentDone, message); } @@ -2730,7 +2730,7 @@ class WalletWorkerListener { async onNewBlock(height) { await this._listener.onNewBlock(height); } - + async onBalancesChanged(newBalanceStr, newUnlockedBalanceStr, assetType) { await this._listener.onBalancesChanged(BigInteger.parse(newBalanceStr), BigInteger.parse(newUnlockedBalanceStr), assetType); } @@ -2739,7 +2739,7 @@ class WalletWorkerListener { let block = new MoneroBlock(blockJson, MoneroBlock.DeserializationType.TX_WALLET); await this._listener.onOutputReceived(block.getTxs()[0].getOutputs()[0]); } - + async onOutputSpent(blockJson) { let block = new MoneroBlock(blockJson, MoneroBlock.DeserializationType.TX_WALLET); await this._listener.onOutputSpent(block.getTxs()[0].getInputs()[0]);