@spirobel/monero-wallet-api 0.6.1 → 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/README.md +40 -4
  2. package/dist/actionlog/actionLogOpened.js +7 -2
  3. package/dist/frost_dkg.wasm +0 -0
  4. package/dist/io/logging.js +1 -1
  5. package/dist/keypairs-seeds/keypairs.js +5 -5
  6. package/dist/monero_wallet_api.wasm +0 -0
  7. package/dist/multisig/DistributedKeyGenerator.js +3 -3
  8. package/dist/multisig/MultiSigTxSigner.js +2 -2
  9. package/dist/multisig/escrow.js +1 -1
  10. package/dist/multisig/multisig.js +4 -0
  11. package/dist/node-interaction/binaryEndpoints.d.ts +3 -3
  12. package/dist/node-interaction/nodeUrl.js +2 -2
  13. package/dist/scanning-syncing/backgroundWorker.d.ts +3 -0
  14. package/dist/scanning-syncing/backgroundWorker.js +38 -8
  15. package/dist/scanning-syncing/blocksbuffer/blocksBufferFetchLoop.d.ts +1 -1
  16. package/dist/scanning-syncing/blocksbuffer/blocksBufferFetchLoop.js +1 -1
  17. package/dist/scanning-syncing/blocksbuffer/blocksbufferCoordination.d.ts +1 -1
  18. package/dist/scanning-syncing/blocksbuffer/blocksbufferCoordination.js +1 -1
  19. package/dist/scanning-syncing/connectionStatus.d.ts +1 -1
  20. package/dist/scanning-syncing/connectionStatus.js +2 -2
  21. package/dist/scanning-syncing/openWallet.js +1 -1
  22. package/dist/scanning-syncing/scanresult/computeKeyImage.d.ts +1 -1
  23. package/dist/scanning-syncing/scanresult/computeKeyImage.js +2 -2
  24. package/dist/scanning-syncing/scanresult/scanCache.d.ts +1 -1
  25. package/dist/scanning-syncing/scanresult/scanCache.js +1 -1
  26. package/dist/scanning-syncing/scanresult/scanCacheOpened.d.ts +1 -1
  27. package/dist/scanning-syncing/scanresult/scanCacheOpened.js +33 -16
  28. package/dist/scanning-syncing/scanresult/scanCoordination.d.ts +2 -2
  29. package/dist/scanning-syncing/scanresult/scanCoordination.js +2 -2
  30. package/dist/scanning-syncing/scanresult/scanLoop.d.ts +1 -1
  31. package/dist/scanning-syncing/scanresult/scanLoop.js +1 -1
  32. package/dist/scanning-syncing/scanresult/scanResult.d.ts +1 -1
  33. package/dist/scanning-syncing/scanresult/scanResult.js +3 -3
  34. package/dist/scanning-syncing/scanresult/scanStats.d.ts +1 -1
  35. package/dist/scanning-syncing/scanresult/scanStats.js +1 -2
  36. package/dist/scanning-syncing/worker-entrypoints/worker.js +1 -1
  37. package/dist/scanning-syncing/worker-mains/cpubound-main.js +1 -1
  38. package/dist/scanning-syncing/worker-mains/multisig-main.d.ts +1 -1
  39. package/dist/scanning-syncing/worker-mains/multisig-main.js +1 -1
  40. package/dist/scanning-syncing/worker-mains/worker.js +9 -1
  41. package/dist/scansettings/scanSettings.js +1 -1
  42. package/dist/scansettings/scanSettingsOpened.d.ts +2 -1
  43. package/dist/scansettings/scanSettingsOpened.js +13 -6
  44. package/dist/send-functionality/inputSelection.d.ts +1 -1
  45. package/dist/send-functionality/transactionBuilding.d.ts +1 -1
  46. package/dist/send-functionality/transactionBuilding.js +3 -3
  47. package/dist/viewpair/ViewPair.d.ts +4 -4
  48. package/dist/viewpair/ViewPair.js +4 -4
  49. package/dist/wasm-processing/wasmLoader.d.ts +10 -0
  50. package/dist/wasm-processing/wasmLoader.js +108 -0
  51. package/dist/worker_unpacked.js +14055 -0
  52. package/dist/xmr3.d.ts +1 -39
  53. package/dist/xmr3.js +10 -37
  54. package/dist/xmr3_common.d.ts +39 -0
  55. package/dist/xmr3_common.js +37 -0
  56. package/dist/xmr3_unpacked.d.ts +9 -0
  57. package/dist/xmr3_unpacked.js +14 -0
  58. package/package.json +9 -2
  59. package/dist/actionlog/actionLog.d.ts +0 -4
  60. package/dist/actionlog/actionLog.js +0 -9
  61. package/dist/actionlog/backend/jsonlBackend.d.ts +0 -19
  62. package/dist/actionlog/backend/jsonlBackend.js +0 -110
  63. package/dist/actionlog/backend/memoryBackend.d.ts +0 -11
  64. package/dist/actionlog/backend/memoryBackend.js +0 -31
  65. package/dist/actionlog/backend.d.ts +0 -12
  66. package/dist/actionlog/backend.js +0 -1
  67. package/dist/actionlog/idbBackend.d.ts +0 -19
  68. package/dist/actionlog/idbBackend.js +0 -98
  69. package/dist/actionlog/jsonlBackend.d.ts +0 -19
  70. package/dist/actionlog/jsonlBackend.js +0 -75
  71. package/dist/actionlog/memoryBackend.d.ts +0 -14
  72. package/dist/actionlog/memoryBackend.js +0 -38
  73. package/dist/actionlog/openMaps.d.ts +0 -11
  74. package/dist/actionlog/openMaps.js +0 -32
  75. package/dist/actionlog/sqliteBackend.d.ts +0 -18
  76. package/dist/actionlog/sqliteBackend.js +0 -105
  77. package/dist/actionlog/toolContext.d.ts +0 -36
  78. package/dist/actionlog/toolContext.js +0 -1
  79. package/dist/actionlog/types.d.ts +0 -62
  80. package/dist/actionlog/types.js +0 -62
  81. package/dist/scanning-syncing/blocksbuffer/getBlocksbinBuffer.d.ts +0 -28
  82. package/dist/scanning-syncing/blocksbuffer/getBlocksbinBuffer.js +0 -54
  83. package/dist/scanning-syncing/scanSettings.d.ts +0 -165
  84. package/dist/scanning-syncing/scanSettings.js +0 -338
  85. package/dist/scanning-syncing/scanresult/reorg.d.ts +0 -3
  86. package/dist/scanning-syncing/scanresult/reorg.js +0 -101
  87. package/dist/scanning-syncing/scansettings/scanSettings.d.ts +0 -165
  88. package/dist/scanning-syncing/scansettings/scanSettings.js +0 -338
  89. package/dist/send-functionality/multisig.d.ts +0 -72
  90. package/dist/send-functionality/multisig.js +0 -97
  91. package/dist/tools/calls/002-content.d.ts +0 -46
  92. package/dist/tools/calls/002-content.js +0 -135
  93. package/dist/tools/calls/002-fail-cleanup.d.ts +0 -27
  94. package/dist/tools/calls/002-fail-cleanup.js +0 -60
  95. package/dist/tools/counterparty.d.ts +0 -3
  96. package/dist/tools/counterparty.js +0 -1
  97. package/dist/tools/monero-tools-content.d.ts +0 -29
  98. package/dist/tools/monero-tools-content.js +0 -80
  99. package/dist/tools/runtimeMessages.d.ts +0 -4
  100. package/dist/tools/runtimeMessages.js +0 -18
  101. package/dist/tools/toolActionLogContext.d.ts +0 -33
  102. package/dist/tools/toolActionLogContext.js +0 -1
  103. package/dist/tools/toolArm.d.ts +0 -47
  104. package/dist/tools/toolArm.js +0 -1
  105. package/dist/tools/ui.d.ts +0 -2
  106. package/dist/tools/ui.js +0 -1
  107. package/dist/tools/worker.d.ts +0 -1
  108. package/dist/tools/worker.js +0 -1
package/README.md CHANGED
@@ -64,12 +64,48 @@ makes it possible to easily run the [escrow test](tests/acceptance/escrow.test.t
64
64
 
65
65
  See the [acceptance test](tests/acceptance/dont_rescan.test.ts) for a full working sync example with mainnet data.
66
66
 
67
- ## install
67
+ ## unpacked build entrypoint
68
68
 
69
- To install the package:
69
+ In most cases you should use the default install / npm build entrypoint. It takes care of distributing the worker + wasm files as part of the package. When using the unpacked entrypoint via adding `/unpacked` to the end of the package import, you need to configure your build system to copy / distribute the wasm and worker urls and notify the package of those urls in your setup code via `configureUnpacked()`.
70
+ ``` ts
71
+ import { configureUnpacked, openWallets } from "@spirobel/monero-wallet-api/unpacked";
70
72
 
71
- ```bash
72
- bun add @spirobel/monero-wallet-api
73
+ ```
74
+
75
+ ### build result in dist dir
76
+
77
+ `bun run build` makes these files in `dist` (in addition to the packaged build `xmr3.js` and type definitions):
78
+
79
+ * `xmr3_unpacked.js` (entry without worker + wasm dataurls)
80
+ * `worker_unpacked.js` (worker source file that has to be distributed manually)
81
+ * `monero_wallet_api.wasm` (wasm file that has to be distributed manually)
82
+ * `frost_dkg.wasm` (wasm file that has to be distributed manually)
83
+
84
+ ### checklist for library consumer of unpacked entrypoint
85
+
86
+ 1. Install the lib.
87
+ 2. Copy the wasm files and the worker file to your dist folder.
88
+ 3. Import from `/unpacked`.
89
+ 4. Call `configureUnpacked` before `openWallets`.
90
+
91
+ Copy step in `package.json`:
92
+
93
+ ```json
94
+ "copyunpacked": "cp node_modules/@spirobel/monero-wallet-api/dist/*.wasm dist/chrome/ && cp node_modules/@spirobel/monero-wallet-api/dist/worker_unpacked.js dist/chrome/"
95
+ ```
96
+
97
+ Code example:
98
+
99
+ ```ts
100
+ import { configureUnpacked, openWallets } from "@spirobel/monero-wallet-api/unpacked";
101
+
102
+ configureUnpacked({
103
+ workerUrl: "worker_unpacked.js",
104
+ moneroWasmUrl: "monero_wallet_api.wasm",
105
+ dkgWasmUrl: "frost_dkg.wasm",
106
+ });
107
+
108
+ const wallets = await openWallets();
73
109
  ```
74
110
 
75
111
  ## build
@@ -245,8 +245,13 @@ export class ActionLogOpened {
245
245
  }
246
246
  case "worker.changeNodeUrlAndStartHeight": {
247
247
  const p = env.payload;
248
- await this.mco?.changeNodeUrlAndStartHeight(p?.node_url, p?.start_height);
249
- return {};
248
+ try {
249
+ await this.mco?.changeNodeUrlAndStartHeight(p?.node_url, p?.start_height);
250
+ return {};
251
+ }
252
+ catch (err) {
253
+ return { error: err instanceof Error ? err.message : String(err) };
254
+ }
250
255
  }
251
256
  case "worker.buildWallets":
252
257
  await this.mco?.buildWallets();
Binary file
@@ -1,4 +1,4 @@
1
- import { getPathPrefix, openScanSettingsFile } from "../xmr3";
1
+ import { getPathPrefix, openScanSettingsFile } from "../xmr3_common";
2
2
  import { atomicWrite } from "./atomicWrite";
3
3
  /**
4
4
  * logging function names registry.
@@ -60,7 +60,7 @@
60
60
  // simple wallet turns spend private key (recovery_val) into mnemonic words with this call:
61
61
  // 4849 crypto::ElectrumWords::bytes_to_words(recovery_val, electrum_words, mnemonic_language);
62
62
  // https://github.com/monero-project/monero/blob/48ad374b0d6d6e045128729534dc2508e6999afe/src/simplewallet/simplewallet.cpp#L4849
63
- import { monero_wallet_api_wasm } from "../wasm-processing/wasmFile";
63
+ import { getMoneroWasmBytes } from "../wasm-processing/wasmLoader";
64
64
  import { WasmProcessor } from "../wasm-processing/wasmProcessor";
65
65
  /**
66
66
  * use this function to generate a keypair for testing
@@ -77,7 +77,7 @@ export async function makeTestKeyPair() {
77
77
  * @returns SpendKey
78
78
  */
79
79
  export async function makeSpendKey() {
80
- const wasmProcessor = await WasmProcessor.init(monero_wallet_api_wasm);
80
+ const wasmProcessor = await WasmProcessor.init(await getMoneroWasmBytes());
81
81
  let result = undefined;
82
82
  wasmProcessor.readFromWasmMemory = (ptr, len) => {
83
83
  result = String(wasmProcessor.readString(ptr, len));
@@ -94,7 +94,7 @@ export async function makeSpendKeyFromSeed(wallet_secret) {
94
94
  throw new Error(`Invalid wallet secret length: ${wallet_secret.length}.
95
95
  Expected 128 hex characters (64 bytes).`);
96
96
  }
97
- const wasmProcessor = await WasmProcessor.init(monero_wallet_api_wasm);
97
+ const wasmProcessor = await WasmProcessor.init(await getMoneroWasmBytes());
98
98
  wasmProcessor.writeToWasmMemory = (ptr, len) => {
99
99
  wasmProcessor.writeString(ptr, len, wallet_secret);
100
100
  };
@@ -121,7 +121,7 @@ export async function makeViewKey(spend_private_key) {
121
121
  throw new Error(`Invalid spendkey length: ${spend_private_key.length}.
122
122
  Expected 64 hex characters (32 bytes).`);
123
123
  }
124
- const wasmProcessor = await WasmProcessor.init(monero_wallet_api_wasm);
124
+ const wasmProcessor = await WasmProcessor.init(await getMoneroWasmBytes());
125
125
  wasmProcessor.writeToWasmMemory = (ptr, len) => {
126
126
  wasmProcessor.writeString(ptr, len, spend_private_key);
127
127
  };
@@ -148,7 +148,7 @@ export async function vk_from_entropy(entropy) {
148
148
  throw new Error(`Invalid entropy length: ${entropy.length}.
149
149
  Expected 32 bytes array.`);
150
150
  }
151
- const wasmProcessor = await WasmProcessor.init(monero_wallet_api_wasm);
151
+ const wasmProcessor = await WasmProcessor.init(await getMoneroWasmBytes());
152
152
  wasmProcessor.writeToWasmMemory = (ptr, len) => {
153
153
  wasmProcessor.writeArray(ptr, len, entropy);
154
154
  };
Binary file
@@ -1,4 +1,4 @@
1
- import { frost_dkg_wasm } from "../wasm-processing/wasmFile";
1
+ import { getDkgWasmBytes } from "../wasm-processing/wasmLoader";
2
2
  import { WasmProcessor } from "../wasm-processing/wasmProcessor";
3
3
  /**
4
4
  * get the DKG public key from a 64-byte DKG secret key
@@ -38,7 +38,7 @@ export class DistributedKeyGenerator extends WasmProcessor {
38
38
  */
39
39
  static async create() {
40
40
  const dkg = new DistributedKeyGenerator();
41
- await dkg.initWasmModule(frost_dkg_wasm);
41
+ await dkg.initWasmModule(await getDkgWasmBytes());
42
42
  return dkg;
43
43
  }
44
44
  /**
@@ -49,7 +49,7 @@ export class DistributedKeyGenerator extends WasmProcessor {
49
49
  */
50
50
  static async createAndSetupGenerators(t, n) {
51
51
  const dkg = new DistributedKeyGenerator();
52
- await dkg.initWasmModule(frost_dkg_wasm);
52
+ await dkg.initWasmModule(await getDkgWasmBytes());
53
53
  dkg.setupGenerators(t, n);
54
54
  return dkg;
55
55
  }
@@ -1,9 +1,9 @@
1
- import { frost_dkg_wasm } from "../wasm-processing/wasmFile";
1
+ import { getDkgWasmBytes } from "../wasm-processing/wasmLoader";
2
2
  import { WasmProcessor } from "../wasm-processing/wasmProcessor";
3
3
  export class MultiSigTxSigner extends WasmProcessor {
4
4
  static async create() {
5
5
  const signer = new MultiSigTxSigner();
6
- await signer.initWasmModule(frost_dkg_wasm);
6
+ await signer.initWasmModule(await getDkgWasmBytes());
7
7
  return signer;
8
8
  }
9
9
  /**
@@ -1,6 +1,6 @@
1
1
  import { ed25519, x25519 } from "@noble/curves/ed25519.js";
2
2
  import { blake3 } from "@noble/hashes/blake3.js";
3
- import { vk_from_entropy } from "../xmr3";
3
+ import { vk_from_entropy } from "../xmr3_common";
4
4
  export function makeEscrowContext(context_index) {
5
5
  if (Number.isNaN(parseInt(String(context_index)))) {
6
6
  return { ok: false, error: `invalid context_index: "${context_index}"` };
@@ -1,5 +1,6 @@
1
1
  import { log } from "../io/logging";
2
2
  import { startWebworkerReady } from "../scanning-syncing/backgroundWorker";
3
+ import { getWasmUrls } from "../wasm-processing/wasmLoader";
3
4
  export class MultiSig {
4
5
  worker = undefined;
5
6
  /**
@@ -37,11 +38,14 @@ export class MultiSig {
37
38
  handleUnknownMessage(msg, "startWorker");
38
39
  }
39
40
  };
41
+ const wasmUrls = getWasmUrls();
40
42
  that.worker.postMessage({
41
43
  type: "setup",
42
44
  t,
43
45
  n,
44
46
  role: "multisig",
47
+ moneroWasmUrl: wasmUrls.monero,
48
+ dkgWasmUrl: wasmUrls.dkg,
45
49
  });
46
50
  });
47
51
  return await result_promise;
@@ -99,8 +99,8 @@ export declare const STAGENET_GENESIS_BLOCK_HASH = "76ee3cc98646292206cd3e86f74d
99
99
  */
100
100
  export declare function getBlocksBinMakeRequest<T extends WasmProcessor>(processor: T, params: GetBlocksBinRequest): Uint8Array<ArrayBufferLike>;
101
101
  export declare function getBlocksBinExecuteRequest<T extends WasmProcessor & HasNodeUrl>(processor: T, params: GetBlocksBinRequest, stopSync?: AbortSignal): Promise<Uint8Array<ArrayBufferLike>>;
102
- export declare function getBlocksBinScanResponse<T extends WasmProcessor>(processor: T, getBlocksBinResponseBuffer: Uint8Array, metaCallBack?: GetBlocksBinMetaCallback): Promise<ScanResult | ErrorResponse | undefined>;
103
- export declare function getBlocksBinScan<T extends WasmProcessor & HasNodeUrl>(processor: T, params: GetBlocksBinRequest, metaCallBack?: GetBlocksBinMetaCallback, stopSync?: AbortSignal): Promise<ScanResult | ErrorResponse | undefined>;
102
+ export declare function getBlocksBinScanResponse<T extends WasmProcessor>(processor: T, getBlocksBinResponseBuffer: Uint8Array, metaCallBack?: GetBlocksBinMetaCallback): Promise<ErrorResponse | ScanResult | undefined>;
103
+ export declare function getBlocksBinScan<T extends WasmProcessor & HasNodeUrl>(processor: T, params: GetBlocksBinRequest, metaCallBack?: GetBlocksBinMetaCallback, stopSync?: AbortSignal): Promise<ErrorResponse | ScanResult | undefined>;
104
104
  /**
105
105
  * throws error on failure to create request
106
106
  * @param processor wasmprocessor
@@ -141,6 +141,6 @@ export declare function loadGetBlocksBinResponse<T extends WasmProcessor>(proces
141
141
  * in block_parsing/mod.rs scan_block, scanner.scan(scan_block) failed
142
142
  * all errors are returned as { error: string } (ErrorResponse type)
143
143
  */
144
- export declare function getBlocksBinScanOneBlock<T extends WasmProcessor>(processor: T, blockIndex: number): Promise<ScanResult | ErrorResponse>;
144
+ export declare function getBlocksBinScanOneBlock<T extends WasmProcessor>(processor: T, blockIndex: number): Promise<ErrorResponse | ScanResult>;
145
145
  export declare function binaryFetchRequest(url: string, body: Uint8Array, stopSync?: AbortSignal): Promise<Uint8Array>;
146
146
  export {};
@@ -2,7 +2,7 @@ import { getBlocksBinExecuteRequest, loadGetBlocksBinResponse, getOutsBinJson, g
2
2
  import { get_block_headers_range, get_fee_estimate, get_info, get_output_distribution, send_raw_transaction, } from "./jsonEndpoints";
3
3
  import { makeInput, sampleDecoys, } from "../send-functionality/transactionBuilding";
4
4
  import { WasmProcessor } from "../wasm-processing/wasmProcessor";
5
- import { monero_wallet_api_wasm } from "../wasm-processing/wasmFile";
5
+ import { getMoneroWasmBytes } from "../wasm-processing/wasmLoader";
6
6
  /**
7
7
  * This class is useful to interact with Moneros DaemonRpc binary requests in a convenient way.
8
8
  * (similar to how you would interact with a REST api that gives you json back.)
@@ -28,7 +28,7 @@ export class NodeUrl extends WasmProcessor {
28
28
  }
29
29
  static async create(node_url) {
30
30
  const nodeUrl = new NodeUrl(node_url || LOCAL_NODE_DEFAULT_URL);
31
- await nodeUrl.initWasmModule(monero_wallet_api_wasm);
31
+ await nodeUrl.initWasmModule(await getMoneroWasmBytes());
32
32
  return nodeUrl;
33
33
  }
34
34
  /**
@@ -1,5 +1,8 @@
1
1
  import { type CacheChangedCallbackParameters } from "./scanresult/scanCache";
2
2
  export declare const CPU_POOL_SIZE = 4;
3
+ export declare function setInlineWorkerCode(code: string): void;
4
+ export declare function setWorkerUrl(url: string | undefined): void;
5
+ export declare function getWorkerUrl(): string | undefined;
3
6
  export type WorkerSet = {
4
7
  fetchWorker: Worker;
5
8
  cpuWorkers: Worker[];
@@ -1,9 +1,29 @@
1
1
  import { LOCAL_NODE_DEFAULT_URL } from "../node-interaction/nodeUrl";
2
2
  import {} from "./scanresult/scanCache";
3
- import { openScanSettingsFile, SCAN_SETTINGS_STORE_NAME_DEFAULT, sleep, } from "../xmr3";
3
+ import { openScanSettingsFile, SCAN_SETTINGS_STORE_NAME_DEFAULT, sleep, } from "../xmr3_common";
4
4
  import { log, setupLoggingPath } from "../io/logging";
5
- import { workerMainCode } from "./worker-entrypoints/worker";
5
+ import { getWasmUrls } from "../wasm-processing/wasmLoader";
6
6
  export const CPU_POOL_SIZE = 4;
7
+ // inline worker code for packed mode, set by xmr3 entry
8
+ let inlineWorkerCode = "";
9
+ let blobUrl;
10
+ // custom worker url for unpacked mode, set by consumer
11
+ let customWorkerUrl;
12
+ export function setInlineWorkerCode(code) {
13
+ inlineWorkerCode = code;
14
+ if (code) {
15
+ const blob = new Blob([code], {
16
+ type: "text/javascript",
17
+ });
18
+ blobUrl = URL.createObjectURL(blob);
19
+ }
20
+ }
21
+ export function setWorkerUrl(url) {
22
+ customWorkerUrl = url;
23
+ }
24
+ export function getWorkerUrl() {
25
+ return customWorkerUrl;
26
+ }
7
27
  export async function createWebworker(handle_result, scan_settings_path, pathPrefix, handle_error) {
8
28
  try {
9
29
  const resolvedPath = scan_settings_path || SCAN_SETTINGS_STORE_NAME_DEFAULT;
@@ -14,6 +34,7 @@ export async function createWebworker(handle_result, scan_settings_path, pathPre
14
34
  const cpu_worker_count = typeof scanSettings?.cpu_worker_count !== "undefined"
15
35
  ? scanSettings?.cpu_worker_count || 1
16
36
  : CPU_POOL_SIZE;
37
+ const wasmUrls = getWasmUrls();
17
38
  // spawn CPU workers
18
39
  const cpuWorkers = [];
19
40
  const cpuPorts = [];
@@ -26,6 +47,8 @@ export async function createWebworker(handle_result, scan_settings_path, pathPre
26
47
  cpu_worker_id: i,
27
48
  scan_settings_path: resolvedPath,
28
49
  pathPrefix,
50
+ moneroWasmUrl: wasmUrls.monero,
51
+ dkgWasmUrl: wasmUrls.dkg,
29
52
  }, [channel.port1]);
30
53
  cpuWorker.onerror = (e) => {
31
54
  if (handle_error)
@@ -41,6 +64,8 @@ export async function createWebworker(handle_result, scan_settings_path, pathPre
41
64
  scan_settings_path: resolvedPath,
42
65
  pathPrefix,
43
66
  role: "coordinator",
67
+ moneroWasmUrl: wasmUrls.monero,
68
+ dkgWasmUrl: wasmUrls.dkg,
44
69
  }, cpuPorts); // transfer CPU ports to coordination worker
45
70
  log("createWebworker", [
46
71
  "coordinator worker started, node_url=" + node_url,
@@ -161,18 +186,23 @@ export async function createWebworker(handle_result, scan_settings_path, pathPre
161
186
  }
162
187
  }
163
188
  export function makeWebworkerScript() {
164
- return workerMainCode;
189
+ return inlineWorkerCode;
165
190
  }
166
- const blob = new Blob([workerMainCode], {
167
- type: "text/javascript",
168
- });
169
- const url = URL.createObjectURL(blob);
170
191
  // creates a worker via startWebworker, then waits for it to signal
171
192
  // WORKER_READY (meaning self.onmessage = handleMessage has executed).
172
193
  // after that, postMessage is safe, no race between worker startup
173
194
  // and message delivery.
174
195
  export function startWebworkerReady() {
175
- const worker = new Worker(url, { type: "module" });
196
+ let worker;
197
+ if (customWorkerUrl) {
198
+ worker = new Worker(customWorkerUrl, { type: "module" });
199
+ }
200
+ else if (blobUrl) {
201
+ worker = new Worker(blobUrl, { type: "module" });
202
+ }
203
+ else {
204
+ throw new Error("no worker url and no inline worker code, call setWorkerUrl or use packed entry");
205
+ }
176
206
  return new Promise((resolve) => {
177
207
  const onReady = (e) => {
178
208
  if (e.data?.type === "WORKER_READY") {
@@ -1,4 +1,4 @@
1
- import { NodeUrl, type BlockInfo, type CacheRange, type GetBlocksResultMeta } from "../../xmr3";
1
+ import { NodeUrl, type BlockInfo, type CacheRange, type GetBlocksResultMeta } from "../../xmr3_common";
2
2
  import { type ConnectionSatusLastPacket, type ConnectionStatus, type ConnectionStatusSync } from "../connectionStatus";
3
3
  export type GetBlocksBinBufferItem = {
4
4
  local_uuid: string;
@@ -1,4 +1,4 @@
1
- import { findRange, get_block_headers_range, get_info, mergeRanges, NodeUrl, sleep, } from "../../xmr3";
1
+ import { findRange, get_block_headers_range, get_info, mergeRanges, NodeUrl, sleep, } from "../../xmr3_common";
2
2
  import {} from "../connectionStatus";
3
3
  import { log } from "../../io/logging";
4
4
  export const MAX_BLOCKS_BUFFER_SIZE = 10;
@@ -1,4 +1,4 @@
1
- import { type GetBlocksBinBufferItem, type ConnectionStatus, type BlocksBufferLoopResult, type CacheRange } from "../../xmr3";
1
+ import { type GetBlocksBinBufferItem, type ConnectionStatus, type BlocksBufferLoopResult, type CacheRange } from "../../xmr3_common";
2
2
  export type SetupBlocksBufferGeneratorParams = {
3
3
  nodeUrl: string;
4
4
  startHeight: number;
@@ -1,4 +1,4 @@
1
- import { blocksBufferFetchLoop, readWriteConnectionStatusFile, applyLastPacket, CatastrophicReorgError, readOrInitConnectionStatus, } from "../../xmr3";
1
+ import { blocksBufferFetchLoop, readWriteConnectionStatusFile, applyLastPacket, CatastrophicReorgError, readOrInitConnectionStatus, } from "../../xmr3_common";
2
2
  import { log } from "../../io/logging";
3
3
  export async function setupBlocksBufferGenerator(params) {
4
4
  const blocksBuffer = [];
@@ -1,4 +1,4 @@
1
- import { type CacheRange, type ReorgInfo } from "../xmr3";
1
+ import { type CacheRange, type ReorgInfo } from "../xmr3_common";
2
2
  export type ConnectionStatusOptions = "OK" | "partial_read" | "connection_failed" | "blocks_buffer_full" | "no_connection_yet" | "catastrophic_reorg";
3
3
  export type ConnectionSatusLastPacket = {
4
4
  status: ConnectionStatusOptions;
@@ -1,5 +1,5 @@
1
- import { atomicWrite, } from "../xmr3";
2
- import { SCAN_SETTINGS_STORE_NAME_DEFAULT } from "../xmr3";
1
+ import { atomicWrite, } from "../xmr3_common";
2
+ import { SCAN_SETTINGS_STORE_NAME_DEFAULT } from "../xmr3_common";
3
3
  // wallet progress write: always set scan fields; only replace eta when a new one is provided
4
4
  // so a missing eta does not wipe / flicker the previous value.
5
5
  export function applyWalletScanProgress(cs, progress) {
@@ -1,5 +1,5 @@
1
1
  import { ManyScanCachesOpened, ScanCacheOpened, } from "./scanresult/scanCacheOpened";
2
- import { openScanSettingsFile, writeWalletToScanSettings } from "../xmr3";
2
+ import { openScanSettingsFile, writeWalletToScanSettings } from "../xmr3_common";
3
3
  /**
4
4
  * Opens all **non halted wallets listed in ScanSettings.json** for scanning.
5
5
  *
@@ -1,4 +1,4 @@
1
- import type { Output } from "../../xmr3";
1
+ import type { Output } from "../../xmr3_common";
2
2
  import { WasmProcessor } from "../../wasm-processing/wasmProcessor";
3
3
  export type KeyImage = string;
4
4
  export declare function computeKeyImage(output: Output, sender_spend_key: string, wasmProcessor?: WasmProcessor): Promise<KeyImage | undefined>;
@@ -1,8 +1,8 @@
1
- import { monero_wallet_api_wasm } from "../../wasm-processing/wasmFile";
1
+ import { getMoneroWasmBytes } from "../../wasm-processing/wasmLoader";
2
2
  import { WasmProcessor } from "../../wasm-processing/wasmProcessor";
3
3
  export async function computeKeyImage(output, sender_spend_key, wasmProcessor) {
4
4
  if (!wasmProcessor)
5
- wasmProcessor = await WasmProcessor.init(monero_wallet_api_wasm);
5
+ wasmProcessor = await WasmProcessor.init(await getMoneroWasmBytes());
6
6
  wasmProcessor.writeToWasmMemory = (ptr, len) => {
7
7
  wasmProcessor.writeString(ptr, len, output.serialized);
8
8
  wasmProcessor.writeToWasmMemory = (ptr, len) => {
@@ -1,5 +1,5 @@
1
1
  import { type KeyImage } from "./computeKeyImage";
2
- import { type BlockInfo, type FeeEstimateResponse, type GetBlockHeadersRange, type GetBlockHeadersRangeParams, type Output, type SendRawTransactionResult, type ViewPair } from "../../xmr3";
2
+ import { type BlockInfo, type FeeEstimateResponse, type GetBlockHeadersRange, type GetBlockHeadersRangeParams, type Output, type SendRawTransactionResult, type ViewPair } from "../../xmr3_common";
3
3
  import type { Payment } from "../../send-functionality/inputSelection";
4
4
  export declare function initScanCache(viewpair: ViewPair, start_height: number, scan_settings_path?: string, pathPrefix?: string): Promise<CacheRange>;
5
5
  export declare function getBlockInfoForHeight(height: number, node_url: string): Promise<BlockInfo>;
@@ -1,5 +1,5 @@
1
1
  import {} from "./computeKeyImage";
2
- import { get_block_headers_range, } from "../../xmr3";
2
+ import { get_block_headers_range, } from "../../xmr3_common";
3
3
  import { atomicWrite } from "../../io/atomicWrite";
4
4
  import { log } from "../../io/logging";
5
5
  export async function initScanCache(viewpair, start_height, scan_settings_path, pathPrefix) {
@@ -1,4 +1,4 @@
1
- import { ViewPair, type FeeEstimateResponse, type Output, type SendRawTransactionResult } from "../../xmr3";
1
+ import { ViewPair, type FeeEstimateResponse, type Output, type SendRawTransactionResult } from "../../xmr3_common";
2
2
  import { type Payment } from "../../send-functionality/inputSelection";
3
3
  import { ConnectionStatusOpened } from "../connectionStatusOpened";
4
4
  import { ActionLogOpened, type ActionLogBackendKind, type ExtensionMessageBus } from "../../actionlog/actionLogOpened";
@@ -1,8 +1,8 @@
1
- import { get_info, NodeUrl, signTransaction, ViewPair, } from "../../xmr3";
1
+ import { get_info, NodeUrl, signTransaction, ViewPair, } from "../../xmr3_common";
2
2
  import { prepareInput, sumPayments, } from "../../send-functionality/inputSelection";
3
3
  import { createWebworker } from "../backgroundWorker";
4
4
  import { spendable } from "./scanResult";
5
- import { getPathPrefix, readPrivateSpendKeyFromEnv, SCAN_SETTINGS_STORE_NAME_DEFAULT, SUB_ADDRESS_INDEX_DEFAULT_VALUE, walletSettingsPlusKeys, } from "../../xmr3";
5
+ import { getPathPrefix, readPrivateSpendKeyFromEnv, SCAN_SETTINGS_STORE_NAME_DEFAULT, SUB_ADDRESS_INDEX_DEFAULT_VALUE, walletSettingsPlusKeys, } from "../../xmr3_common";
6
6
  import { ScanSettingsOpened } from "../../scansettings/scanSettingsOpened";
7
7
  import { ConnectionStatusOpened } from "../connectionStatusOpened";
8
8
  import { ActionLogOpened, } from "../../actionlog/actionLogOpened";
@@ -173,14 +173,19 @@ export class ScanCacheOpened {
173
173
  return this._scanSettings.logs_exclude;
174
174
  }
175
175
  async changeNodeUrlAndStartHeight(node_url, start_height) {
176
- await this.stopWorker();
177
- if (node_url !== undefined) {
178
- await this._scanSettings.setNodeUrl(node_url);
179
- this.node_url = node_url;
176
+ // stop first so a live worker cannot write the old file over the new url.
177
+ try {
178
+ await this.stopWorker();
180
179
  }
181
- if (start_height !== undefined) {
182
- await this._scanSettings.setStartHeight(start_height);
183
- this._start_height = start_height;
180
+ catch {
181
+ // stop can fail. still write the new url.
182
+ }
183
+ if (node_url !== undefined || start_height !== undefined) {
184
+ await this._scanSettings.setNodeUrlAndStartHeight(node_url, start_height);
185
+ if (node_url !== undefined)
186
+ this.node_url = node_url;
187
+ if (start_height !== undefined)
188
+ this._start_height = start_height;
184
189
  }
185
190
  await this.unpause();
186
191
  }
@@ -751,7 +756,11 @@ export class ScanCacheOpened {
751
756
  delete this.worker;
752
757
  // drain coordinator first, then hard kill workers
753
758
  try {
754
- await worker.shutdown();
759
+ // shutdown already races 5s. this race still returns if that promise never settles.
760
+ await Promise.race([
761
+ worker.shutdown(),
762
+ new Promise((resolve) => setTimeout(resolve, 5000)),
763
+ ]);
755
764
  }
756
765
  catch {
757
766
  // still terminate below
@@ -925,17 +934,25 @@ export class ManyScanCachesOpened {
925
934
  }
926
935
  async changeNodeUrlAndStartHeight(node_url, start_height) {
927
936
  if (this.actionLogOpened.extensionMessageBus === "ui") {
928
- await sendToBackground("worker.changeNodeUrlAndStartHeight", {
937
+ // the background owns the worker. it stops, then writes. do not write here first.
938
+ const result = await sendToBackground("worker.changeNodeUrlAndStartHeight", {
929
939
  node_url,
930
940
  start_height,
931
- }).catch(() => { });
941
+ });
942
+ if (result &&
943
+ typeof result === "object" &&
944
+ "error" in result &&
945
+ result.error) {
946
+ throw new Error(String(result.error));
947
+ }
948
+ if (result == null)
949
+ throw new Error("background did not save the node url");
932
950
  return;
933
951
  }
934
952
  if (this.wallets.length === 0) {
935
- if (node_url !== undefined)
936
- await this._scanSettings.setNodeUrl(node_url);
937
- if (start_height !== undefined)
938
- await this._scanSettings.setStartHeight(start_height);
953
+ if (node_url !== undefined || start_height !== undefined) {
954
+ await this._scanSettings.setNodeUrlAndStartHeight(node_url, start_height);
955
+ }
939
956
  return;
940
957
  }
941
958
  await this.wallets[0].changeNodeUrlAndStartHeight(node_url, start_height);
@@ -1,7 +1,7 @@
1
- import { type GetBlocksBinBufferItem, type BlocksBufferLoopResult, type BlocksBufferIteratorResult, type ProcessScanResult, type BlockInfo } from "../../xmr3";
1
+ import { type GetBlocksBinBufferItem, type BlocksBufferLoopResult, type BlocksBufferIteratorResult, type ProcessScanResult, type BlockInfo } from "../../xmr3_common";
2
2
  import { type ScanLoopYield } from "./scanLoop";
3
3
  import { type WorkItem } from "./scanLoop";
4
- import { type ScanSettings } from "../../xmr3";
4
+ import { type ScanSettings } from "../../xmr3_common";
5
5
  import { type CacheRange, type ScanCache } from "./scanCache";
6
6
  export type WalletConfig = {
7
7
  primary_address: string;
@@ -1,7 +1,7 @@
1
- import { setupBlocksBufferGenerator, ViewPair, handleConnectionStatusChanges, processScanResult, writeCacheToFile, sleep, findTipIndex, readWriteConnectionStatusFile, applyWalletScanProgress, } from "../../xmr3";
1
+ import { setupBlocksBufferGenerator, ViewPair, handleConnectionStatusChanges, processScanResult, writeCacheToFile, sleep, findTipIndex, readWriteConnectionStatusFile, applyWalletScanProgress, } from "../../xmr3_common";
2
2
  import {} from "./scanLoop";
3
3
  import { makeWorkItem } from "./scanLoop";
4
- import { cullTooLargeScanHeight, getNonHaltedWallets, getPathPrefix, openScanSettingsFile, SCAN_SETTINGS_STORE_NAME_DEFAULT, walletSettingsPlusKeys, } from "../../xmr3";
4
+ import { cullTooLargeScanHeight, getNonHaltedWallets, getPathPrefix, openScanSettingsFile, SCAN_SETTINGS_STORE_NAME_DEFAULT, walletSettingsPlusKeys, } from "../../xmr3_common";
5
5
  import { currentScanHeightFromRanges, findRange, initScanCacheFile, lastRange, makeCacheRangeForHeight, mergeRanges, } from "./scanCache";
6
6
  import { sendToCpuWorker } from "../worker-mains/cpubound-main";
7
7
  import { log } from "../../io/logging";
@@ -1,4 +1,4 @@
1
- import { type GetBlocksBinBufferItem, type ScanResult, type WalletConfig, type WalletConfigPlusCache } from "../../xmr3";
1
+ import { type GetBlocksBinBufferItem, type ScanResult, type WalletConfig, type WalletConfigPlusCache } from "../../xmr3_common";
2
2
  export type WorkItem = {
3
3
  walletConfig: WalletConfigPlusCache;
4
4
  batch: GetBlocksBinBufferItem;
@@ -1,4 +1,4 @@
1
- import { sleep, ViewPair, } from "../../xmr3";
1
+ import { sleep, ViewPair, } from "../../xmr3_common";
2
2
  export function makeWorkItem(walletConfig, batch, from, to) {
3
3
  if (to && to > batch.get_blocks_result_meta.block_infos.length - 1) {
4
4
  // we could throw here but we dont. Off by one errors shouldnt break the application
@@ -1,4 +1,4 @@
1
- import { type BlockInfo, type Output } from "../../xmr3";
1
+ import { type BlockInfo, type Output } from "../../xmr3_common";
2
2
  import { type KeyImage } from "./computeKeyImage";
3
3
  import { type ErrorResponse } from "../../node-interaction/binaryEndpoints";
4
4
  import type { CacheChangedCallback, CacheRange, ChangedOutput, ScanCache } from "./scanCache";
@@ -1,10 +1,10 @@
1
- import { CatastrophicReorgError } from "../../xmr3";
1
+ import { CatastrophicReorgError } from "../../xmr3_common";
2
2
  import { computeKeyImage } from "./computeKeyImage";
3
3
  import { log } from "../../io/logging";
4
4
  import { mergeRanges, findRange, findRangeThrows } from "./scanCache";
5
5
  import {} from "../../node-interaction/binaryEndpoints";
6
6
  import { WasmProcessor } from "../../wasm-processing/wasmProcessor";
7
- import { monero_wallet_api_wasm } from "../../wasm-processing/wasmFile";
7
+ import { getMoneroWasmBytes } from "../../wasm-processing/wasmLoader";
8
8
  export async function processScanResult(params) {
9
9
  const { result, scanCache: cache, secret_spend_key } = params;
10
10
  let changed_outputs = [];
@@ -145,7 +145,7 @@ export function makeNewRange(newRange, cache) {
145
145
  // Assumption: result is new, cache is still old. (this + detectOwnspends() turns the catch new, based on the scan result)
146
146
  export async function detectOutputs(result, cache, spend_private_key) {
147
147
  let changed_outputs = [];
148
- const wasmProcessor = await WasmProcessor.init(monero_wallet_api_wasm);
148
+ const wasmProcessor = await WasmProcessor.init(await getMoneroWasmBytes());
149
149
  for (const output of result.outputs) {
150
150
  // 0. prevent burning bug and avoid overwriting earlier found outputs
151
151
  const duplicate = Object.values(cache.outputs).find((ex) => ex.stealth_address === output.stealth_address && !ex.burned);
@@ -1,4 +1,4 @@
1
- import { ViewPair, type Output } from "../../xmr3";
1
+ import { ViewPair, type Output } from "../../xmr3_common";
2
2
  import type { ScanCache, Subaddress, TxLog } from "./scanCache";
3
3
  import { type OutputStatus } from "./scanResult";
4
4
  export type WriteStatsFileParams = {
@@ -1,5 +1,4 @@
1
- import { stat } from "fs";
2
- import { atomicWrite, ViewPair } from "../../xmr3";
1
+ import { atomicWrite, ViewPair } from "../../xmr3_common";
3
2
  import { outputStatus } from "./scanResult";
4
3
  export async function writeStatsFileDefaultLocation(params) {
5
4
  let stats = await readStatsFileDefaultLocation(params.primary_address, params.pathPrefix);