@spirobel/monero-wallet-api 0.3.18 → 0.4.1
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.
- package/dist/api.d.ts +5 -2
- package/dist/api.js +5 -1
- package/dist/io/atomicWrite.js +3 -1
- package/dist/io/indexedDB.js +7 -2
- package/dist/io/logging.d.ts +40 -0
- package/dist/io/logging.js +172 -0
- package/dist/keypairs-seeds/keypairs.d.ts +21 -0
- package/dist/keypairs-seeds/keypairs.js +21 -0
- package/dist/node-interaction/binaryEndpoints.d.ts +31 -2
- package/dist/node-interaction/binaryEndpoints.js +61 -43
- package/dist/node-interaction/jsonEndpoints.d.ts +257 -130
- package/dist/node-interaction/jsonEndpoints.js +159 -119
- package/dist/node-interaction/nodeUrl.d.ts +21 -6
- package/dist/node-interaction/nodeUrl.js +50 -8
- package/dist/scanning-syncing/backgroundWorker.d.ts +10 -6
- package/dist/scanning-syncing/backgroundWorker.js +88 -39
- package/dist/scanning-syncing/blocksbuffer/blocksBufferFetchLoop.d.ts +44 -0
- package/dist/scanning-syncing/blocksbuffer/blocksBufferFetchLoop.js +355 -0
- package/dist/scanning-syncing/blocksbuffer/blocksbufferCoordination.d.ts +15 -0
- package/dist/scanning-syncing/blocksbuffer/blocksbufferCoordination.js +28 -0
- package/dist/scanning-syncing/{scanresult → blocksbuffer}/getBlocksbinBuffer.d.ts +5 -5
- package/dist/scanning-syncing/{scanresult → blocksbuffer}/getBlocksbinBuffer.js +7 -5
- package/dist/scanning-syncing/connectionStatus.d.ts +33 -9
- package/dist/scanning-syncing/connectionStatus.js +89 -19
- package/dist/scanning-syncing/scanSettings.d.ts +21 -0
- package/dist/scanning-syncing/scanSettings.js +29 -0
- package/dist/scanning-syncing/scanresult/reorg.d.ts +0 -11
- package/dist/scanning-syncing/scanresult/reorg.js +39 -16
- package/dist/scanning-syncing/scanresult/scanCache.d.ts +16 -2
- package/dist/scanning-syncing/scanresult/scanCache.js +65 -5
- package/dist/scanning-syncing/scanresult/scanCacheOpened.d.ts +18 -0
- package/dist/scanning-syncing/scanresult/scanCacheOpened.js +56 -11
- package/dist/scanning-syncing/scanresult/scanCoordination.d.ts +127 -0
- package/dist/scanning-syncing/scanresult/scanCoordination.js +602 -0
- package/dist/scanning-syncing/scanresult/scanLoop.d.ts +20 -0
- package/dist/scanning-syncing/scanresult/scanLoop.js +116 -0
- package/dist/scanning-syncing/scanresult/scanResult.d.ts +24 -3
- package/dist/scanning-syncing/scanresult/scanResult.js +159 -97
- package/dist/scanning-syncing/worker-entrypoints/worker.js +1 -1
- package/dist/scanning-syncing/worker-mains/coordinator-main.d.ts +1 -0
- package/dist/scanning-syncing/worker-mains/coordinator-main.js +24 -0
- package/dist/scanning-syncing/worker-mains/cpubound-main.d.ts +5 -0
- package/dist/scanning-syncing/worker-mains/cpubound-main.js +122 -0
- package/dist/scanning-syncing/worker-mains/worker.d.ts +1 -1
- package/dist/scanning-syncing/worker-mains/worker.js +62 -6
- package/dist/viewpair/ViewPair.d.ts +30 -7
- package/dist/viewpair/ViewPair.js +56 -118
- package/dist/wasm-processing/wasmFile.js +1 -1
- package/package.json +22 -24
- package/dist/io/extension.d.ts +0 -18
- package/dist/io/extension.js +0 -11
|
@@ -1,51 +1,95 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
1
|
+
function obj(s) {
|
|
2
|
+
function p(d) {
|
|
3
|
+
if (typeof d !== "object" || d === null)
|
|
4
|
+
throw 0;
|
|
5
|
+
const r = {};
|
|
6
|
+
for (const k in s)
|
|
7
|
+
r[k] = s[k](d[k]);
|
|
8
|
+
return r;
|
|
9
|
+
}
|
|
10
|
+
p.safeParse = (d) => {
|
|
11
|
+
try {
|
|
12
|
+
return { success: true, data: p(d) };
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return { success: false, error: new Error() };
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
return p;
|
|
19
|
+
}
|
|
20
|
+
const str = (x) => {
|
|
21
|
+
if (typeof x !== "string")
|
|
22
|
+
throw 0;
|
|
23
|
+
return x;
|
|
24
|
+
};
|
|
25
|
+
const num = (x) => {
|
|
26
|
+
if (typeof x !== "number")
|
|
27
|
+
throw 0;
|
|
28
|
+
return x;
|
|
29
|
+
};
|
|
30
|
+
const bool = (x) => {
|
|
31
|
+
if (typeof x !== "boolean")
|
|
32
|
+
throw 0;
|
|
33
|
+
return x;
|
|
34
|
+
};
|
|
35
|
+
const lit = (v) => (x) => {
|
|
36
|
+
if (x !== v)
|
|
37
|
+
throw 0;
|
|
38
|
+
return v;
|
|
39
|
+
};
|
|
40
|
+
const arr = (f) => (x) => {
|
|
41
|
+
if (!Array.isArray(x))
|
|
42
|
+
throw 0;
|
|
43
|
+
return x.map(f);
|
|
44
|
+
};
|
|
45
|
+
const opt = (f) => (x) => x === undefined ? undefined : f(x);
|
|
46
|
+
export const GetInfoResponseSchema = obj({
|
|
47
|
+
id: str,
|
|
48
|
+
jsonrpc: lit("2.0"),
|
|
49
|
+
result: obj({
|
|
50
|
+
adjusted_time: num,
|
|
51
|
+
alt_blocks_count: num,
|
|
52
|
+
block_size_limit: num,
|
|
53
|
+
block_size_median: num,
|
|
54
|
+
block_weight_limit: num,
|
|
55
|
+
block_weight_median: num,
|
|
56
|
+
bootstrap_daemon_address: str,
|
|
57
|
+
busy_syncing: bool,
|
|
58
|
+
credits: num,
|
|
59
|
+
cumulative_difficulty: num,
|
|
60
|
+
cumulative_difficulty_top64: num,
|
|
61
|
+
database_size: num,
|
|
62
|
+
difficulty: num,
|
|
63
|
+
difficulty_top64: num,
|
|
64
|
+
free_space: num,
|
|
65
|
+
grey_peerlist_size: num,
|
|
66
|
+
height: num,
|
|
67
|
+
height_without_bootstrap: num,
|
|
68
|
+
incoming_connections_count: num,
|
|
69
|
+
mainnet: bool,
|
|
70
|
+
nettype: str,
|
|
71
|
+
offline: bool,
|
|
72
|
+
outgoing_connections_count: num,
|
|
73
|
+
restricted: bool,
|
|
74
|
+
rpc_connections_count: num,
|
|
75
|
+
stagenet: bool,
|
|
76
|
+
start_time: num,
|
|
77
|
+
status: str,
|
|
78
|
+
synchronized: bool,
|
|
79
|
+
target: num,
|
|
80
|
+
target_height: num,
|
|
81
|
+
testnet: bool,
|
|
82
|
+
top_block_hash: str,
|
|
83
|
+
top_hash: str,
|
|
84
|
+
tx_count: num,
|
|
85
|
+
tx_pool_size: num,
|
|
86
|
+
untrusted: bool,
|
|
87
|
+
update_available: bool,
|
|
88
|
+
version: str,
|
|
89
|
+
was_bootstrap_ever_used: bool,
|
|
90
|
+
white_peerlist_size: num,
|
|
91
|
+
wide_cumulative_difficulty: str,
|
|
92
|
+
wide_difficulty: str,
|
|
49
93
|
}),
|
|
50
94
|
});
|
|
51
95
|
/**
|
|
@@ -61,17 +105,17 @@ export const GetInfoResponseSchema = z.object({
|
|
|
61
105
|
* - start_height: unsigned int; Note that this is not necessarily equal to from_height, especially for amount=0 where start_height will be no less than the height of the v4 hardfork.
|
|
62
106
|
* - status: string; General RPC error code. "OK" means everything looks good.
|
|
63
107
|
*/
|
|
64
|
-
export const GetOutputDistributionResponseSchema =
|
|
65
|
-
id:
|
|
66
|
-
jsonrpc:
|
|
67
|
-
result:
|
|
68
|
-
distributions:
|
|
69
|
-
amount:
|
|
70
|
-
base:
|
|
71
|
-
distribution:
|
|
72
|
-
start_height:
|
|
108
|
+
export const GetOutputDistributionResponseSchema = obj({
|
|
109
|
+
id: str,
|
|
110
|
+
jsonrpc: lit("2.0"),
|
|
111
|
+
result: obj({
|
|
112
|
+
distributions: arr(obj({
|
|
113
|
+
amount: num,
|
|
114
|
+
base: num,
|
|
115
|
+
distribution: arr(num),
|
|
116
|
+
start_height: num,
|
|
73
117
|
})),
|
|
74
|
-
status:
|
|
118
|
+
status: str,
|
|
75
119
|
}),
|
|
76
120
|
});
|
|
77
121
|
export function parseGetOutputDistributionResponse(data) {
|
|
@@ -154,14 +198,14 @@ export async function get_output_distribution(NODE_URL, params = {
|
|
|
154
198
|
* - fees: (Optional) Array of unsigned int; Fee estimates for priorities 1–4.
|
|
155
199
|
* - quantization_mask: unsigned int; Mask used for fee rounding.
|
|
156
200
|
*/
|
|
157
|
-
export const GetFeeEstimateResponseSchema =
|
|
158
|
-
id:
|
|
159
|
-
jsonrpc:
|
|
160
|
-
result:
|
|
161
|
-
status:
|
|
162
|
-
fee:
|
|
163
|
-
fees:
|
|
164
|
-
quantization_mask:
|
|
201
|
+
export const GetFeeEstimateResponseSchema = obj({
|
|
202
|
+
id: str,
|
|
203
|
+
jsonrpc: lit("2.0"),
|
|
204
|
+
result: obj({
|
|
205
|
+
status: str,
|
|
206
|
+
fee: num,
|
|
207
|
+
fees: opt(arr(num)),
|
|
208
|
+
quantization_mask: num,
|
|
165
209
|
}),
|
|
166
210
|
});
|
|
167
211
|
export function parseGetFeeEstimateResponse(data) {
|
|
@@ -199,19 +243,19 @@ export async function get_fee_estimate(NODE_URL) {
|
|
|
199
243
|
}
|
|
200
244
|
return parsedResult.result;
|
|
201
245
|
}
|
|
202
|
-
export const SendRawTransactionResponseSchema =
|
|
203
|
-
double_spend:
|
|
204
|
-
fee_too_low:
|
|
205
|
-
invalid_input:
|
|
206
|
-
invalid_output:
|
|
207
|
-
low_mixin:
|
|
208
|
-
not_rct:
|
|
209
|
-
not_relayed:
|
|
210
|
-
overspend:
|
|
211
|
-
reason:
|
|
212
|
-
status:
|
|
213
|
-
too_big:
|
|
214
|
-
untrusted:
|
|
246
|
+
export const SendRawTransactionResponseSchema = obj({
|
|
247
|
+
double_spend: bool, // double_spend - boolean; Transaction is a double spend (true) or not (false).
|
|
248
|
+
fee_too_low: bool, // fee_too_low - boolean; Fee is too low (true) or OK (false).
|
|
249
|
+
invalid_input: bool, // invalid_input - boolean; Input is invalid (true) or valid (false).
|
|
250
|
+
invalid_output: bool, // invalid_output - boolean; Output is invalid (true) or valid (false).
|
|
251
|
+
low_mixin: bool, // low_mixin - boolean; Mixin count is too low (true) or OK (false).
|
|
252
|
+
not_rct: opt(bool), // not_rct - boolean; Transaction is a standard ring transaction (true) or a ring confidential transaction (false).
|
|
253
|
+
not_relayed: bool, // not_relayed - boolean; Transaction was not relayed (true) or relayed (false).
|
|
254
|
+
overspend: bool, // overspend - boolean; Transaction uses more money than available (true) or not (false).
|
|
255
|
+
reason: str, // reason - string; Additional information. Currently empty or "Not relayed" if transaction was accepted but not relayed.
|
|
256
|
+
status: str, // status - string; General RPC error code. "OK" means everything looks good. Any other value means that something went wrong.
|
|
257
|
+
too_big: bool, // too_big - boolean; Transaction size is too big (true) or OK (false).
|
|
258
|
+
untrusted: bool, // untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced and thus handles the RPC locally (false)
|
|
215
259
|
});
|
|
216
260
|
export function parseSendRawTransactionResponse(data) {
|
|
217
261
|
const result = SendRawTransactionResponseSchema.safeParse(data);
|
|
@@ -279,47 +323,43 @@ do_not_relay = false) {
|
|
|
279
323
|
* - code: int; Error code.
|
|
280
324
|
* - message: string; Error message.
|
|
281
325
|
*/
|
|
282
|
-
export const GetBlockHeadersRangeResponseSchema =
|
|
283
|
-
id:
|
|
284
|
-
jsonrpc:
|
|
285
|
-
result:
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
wide_difficulty: z.string(),
|
|
326
|
+
export const GetBlockHeadersRangeResponseSchema = obj({
|
|
327
|
+
id: str,
|
|
328
|
+
jsonrpc: lit("2.0"),
|
|
329
|
+
result: opt(obj({
|
|
330
|
+
credits: num,
|
|
331
|
+
headers: arr(obj({
|
|
332
|
+
block_size: num,
|
|
333
|
+
block_weight: num,
|
|
334
|
+
cumulative_difficulty: num,
|
|
335
|
+
cumulative_difficulty_top64: num,
|
|
336
|
+
depth: num,
|
|
337
|
+
difficulty: num,
|
|
338
|
+
difficulty_top64: num,
|
|
339
|
+
hash: str,
|
|
340
|
+
height: num,
|
|
341
|
+
long_term_weight: num,
|
|
342
|
+
major_version: num,
|
|
343
|
+
miner_tx_hash: str,
|
|
344
|
+
minor_version: num,
|
|
345
|
+
nonce: num,
|
|
346
|
+
num_txes: num,
|
|
347
|
+
orphan_status: bool,
|
|
348
|
+
pow_hash: str,
|
|
349
|
+
prev_hash: str,
|
|
350
|
+
reward: num,
|
|
351
|
+
timestamp: num,
|
|
352
|
+
wide_cumulative_difficulty: str,
|
|
353
|
+
wide_difficulty: str,
|
|
311
354
|
})),
|
|
312
|
-
status:
|
|
313
|
-
top_hash:
|
|
314
|
-
untrusted:
|
|
315
|
-
})
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
message: z.string(),
|
|
321
|
-
})
|
|
322
|
-
.optional(),
|
|
355
|
+
status: str,
|
|
356
|
+
top_hash: str,
|
|
357
|
+
untrusted: bool,
|
|
358
|
+
})),
|
|
359
|
+
error: opt(obj({
|
|
360
|
+
code: num,
|
|
361
|
+
message: str,
|
|
362
|
+
})),
|
|
323
363
|
});
|
|
324
364
|
export function parseGetBlockHeadersRangeResponse(data) {
|
|
325
365
|
const result = GetBlockHeadersRangeResponseSchema.safeParse(data);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { type GetBlocksBinRequest, type
|
|
1
|
+
import { type Output, type GetBlocksBinRequest, type GetBlocksResultMeta, type GetOutsBinRequest } from "./binaryEndpoints";
|
|
2
2
|
import { type FeeEstimateResponse, type GetBlockHeadersRangeParams, type GetOutputDistributionParams, type SendRawTransactionResult } from "./jsonEndpoints";
|
|
3
|
+
export type NETWORKS = "mainnet" | "stagenet" | "testnet";
|
|
3
4
|
import { type SignedTransaction, type Input } from "../send-functionality/transactionBuilding";
|
|
4
5
|
import { WasmProcessor } from "../wasm-processing/wasmProcessor";
|
|
5
6
|
/**
|
|
@@ -11,14 +12,27 @@ import { WasmProcessor } from "../wasm-processing/wasmProcessor";
|
|
|
11
12
|
export declare class NodeUrl extends WasmProcessor {
|
|
12
13
|
node_url: string;
|
|
13
14
|
protected constructor(node_url: string);
|
|
15
|
+
private _network;
|
|
16
|
+
get network(): NETWORKS;
|
|
17
|
+
private _genesis_hash;
|
|
18
|
+
get genesis_hash(): string;
|
|
14
19
|
static create(node_url?: string): Promise<NodeUrl>;
|
|
15
20
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* @param params params
|
|
19
|
-
* @
|
|
21
|
+
* Executes a get_blocks.bin request and returns the raw binary response buffer.
|
|
22
|
+
* @link https://docs.getmonero.org/rpc-library/monerod-rpc/#get_blocksbin
|
|
23
|
+
* @param params params for the get_blocks.bin request
|
|
24
|
+
* @param stopSync optional AbortSignal
|
|
25
|
+
* @returns the raw binary response buffer
|
|
26
|
+
*/
|
|
27
|
+
getBlocksBinExecuteRequest(params: GetBlocksBinRequest, stopSync?: AbortSignal): Promise<Uint8Array<ArrayBufferLike>>;
|
|
28
|
+
/**
|
|
29
|
+
* Loads a getBlocks.bin response into the WASM module.
|
|
30
|
+
* Unlike getBlocksBinExecuteRequest, this does not make a request, it parses an already fetched
|
|
31
|
+
* binary response and stores it in WASM memory. Subsequent calls overwrite the stored response.
|
|
32
|
+
* @param getBlocksBinResponseBuffer the raw binary response from the get_blocks.bin endpoint
|
|
33
|
+
* @returns metadata about the loaded blocks (new_height, daemon_height, status, block_infos)
|
|
20
34
|
*/
|
|
21
|
-
|
|
35
|
+
loadGetBlocksBinResponse(getBlocksBinResponseBuffer: Uint8Array): Promise<GetBlocksResultMeta>;
|
|
22
36
|
/**
|
|
23
37
|
* This request helps making requests to the get_outs.bin endpoint of the Monerod nodes.
|
|
24
38
|
* @link https://docs.getmonero.org/rpc-library/monerod-rpc/#get_outsbin
|
|
@@ -125,5 +139,6 @@ export declare class NodeUrl extends WasmProcessor {
|
|
|
125
139
|
wide_cumulative_difficulty: string;
|
|
126
140
|
wide_difficulty: string;
|
|
127
141
|
}>;
|
|
142
|
+
addGenesisHashToBlockIds(params: GetBlocksBinRequest): Promise<GetBlocksBinRequest>;
|
|
128
143
|
}
|
|
129
144
|
export declare const LOCAL_NODE_DEFAULT_URL = "http://127.0.0.1:18081";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getBlocksBinExecuteRequest, loadGetBlocksBinResponse, getOutsBinJson, getOutsBinExecuteRequest, MAINNET_GENESIS_BLOCK_HASH, STAGENET_GENESIS_BLOCK_HASH, } from "./binaryEndpoints";
|
|
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";
|
|
@@ -14,19 +14,41 @@ export class NodeUrl extends WasmProcessor {
|
|
|
14
14
|
super();
|
|
15
15
|
this.node_url = node_url;
|
|
16
16
|
}
|
|
17
|
+
_network;
|
|
18
|
+
get network() {
|
|
19
|
+
return this._network; // we set this in ViewPair.create()
|
|
20
|
+
}
|
|
21
|
+
_genesis_hash;
|
|
22
|
+
get genesis_hash() {
|
|
23
|
+
if (!this._genesis_hash) {
|
|
24
|
+
throw new Error("Genesis hash not set. Node not connected?");
|
|
25
|
+
}
|
|
26
|
+
return this._genesis_hash; // set in first call to ViewPair.getBlocksBin, if params.block_ids is supplied
|
|
27
|
+
}
|
|
17
28
|
static async create(node_url) {
|
|
18
29
|
const nodeUrl = new NodeUrl(node_url || LOCAL_NODE_DEFAULT_URL);
|
|
19
30
|
await nodeUrl.initWasmModule();
|
|
20
31
|
return nodeUrl;
|
|
21
32
|
}
|
|
22
33
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* @param params params
|
|
26
|
-
* @
|
|
34
|
+
* Executes a get_blocks.bin request and returns the raw binary response buffer.
|
|
35
|
+
* @link https://docs.getmonero.org/rpc-library/monerod-rpc/#get_blocksbin
|
|
36
|
+
* @param params params for the get_blocks.bin request
|
|
37
|
+
* @param stopSync optional AbortSignal
|
|
38
|
+
* @returns the raw binary response buffer
|
|
27
39
|
*/
|
|
28
|
-
|
|
29
|
-
return
|
|
40
|
+
async getBlocksBinExecuteRequest(params, stopSync) {
|
|
41
|
+
return await getBlocksBinExecuteRequest(this, await this.addGenesisHashToBlockIds(params), stopSync);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Loads a getBlocks.bin response into the WASM module.
|
|
45
|
+
* Unlike getBlocksBinExecuteRequest, this does not make a request, it parses an already fetched
|
|
46
|
+
* binary response and stores it in WASM memory. Subsequent calls overwrite the stored response.
|
|
47
|
+
* @param getBlocksBinResponseBuffer the raw binary response from the get_blocks.bin endpoint
|
|
48
|
+
* @returns metadata about the loaded blocks (new_height, daemon_height, status, block_infos)
|
|
49
|
+
*/
|
|
50
|
+
loadGetBlocksBinResponse(getBlocksBinResponseBuffer) {
|
|
51
|
+
return loadGetBlocksBinResponse(this, getBlocksBinResponseBuffer);
|
|
30
52
|
}
|
|
31
53
|
/**
|
|
32
54
|
* This request helps making requests to the get_outs.bin endpoint of the Monerod nodes.
|
|
@@ -99,7 +121,7 @@ export class NodeUrl extends WasmProcessor {
|
|
|
99
121
|
* @returns The result object with headers, status, etc. Throws if the range is invalid:(end_height > daemonheight)
|
|
100
122
|
*/
|
|
101
123
|
async getBlockHeadersRange(params) {
|
|
102
|
-
return get_block_headers_range(this.node_url, params);
|
|
124
|
+
return await get_block_headers_range(this.node_url, params);
|
|
103
125
|
}
|
|
104
126
|
/**
|
|
105
127
|
* Fetch general information about the Monero daemon.
|
|
@@ -109,5 +131,25 @@ export class NodeUrl extends WasmProcessor {
|
|
|
109
131
|
async getInfo() {
|
|
110
132
|
return get_info(this.node_url);
|
|
111
133
|
}
|
|
134
|
+
async addGenesisHashToBlockIds(params) {
|
|
135
|
+
if (params.block_ids) {
|
|
136
|
+
if (!this._genesis_hash && this.network === "mainnet") {
|
|
137
|
+
this._genesis_hash = MAINNET_GENESIS_BLOCK_HASH;
|
|
138
|
+
}
|
|
139
|
+
if (!this._genesis_hash && this.network === "stagenet") {
|
|
140
|
+
this._genesis_hash = STAGENET_GENESIS_BLOCK_HASH;
|
|
141
|
+
}
|
|
142
|
+
if (!this._genesis_hash) {
|
|
143
|
+
// TESTNET
|
|
144
|
+
const range = await this.getBlockHeadersRange({
|
|
145
|
+
start_height: 0,
|
|
146
|
+
end_height: 0,
|
|
147
|
+
});
|
|
148
|
+
this._genesis_hash = range.headers[0].hash;
|
|
149
|
+
}
|
|
150
|
+
params.block_ids.push(this.genesis_hash);
|
|
151
|
+
}
|
|
152
|
+
return params;
|
|
153
|
+
}
|
|
112
154
|
}
|
|
113
155
|
export const LOCAL_NODE_DEFAULT_URL = "http://127.0.0.1:18081";
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
export declare
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { type CacheChangedCallbackParameters } from "./scanresult/scanCache";
|
|
2
|
+
export declare const CPU_POOL_SIZE = 4;
|
|
3
|
+
export type WorkerSet = {
|
|
4
|
+
fetchWorker: Worker;
|
|
5
|
+
cpuWorkers: Worker[];
|
|
6
|
+
terminate: () => void;
|
|
7
|
+
};
|
|
8
|
+
export declare function createWebworker(handle_result?: (result: CacheChangedCallbackParameters) => void, scan_settings_path?: string, pathPrefix?: string, handle_error?: (error: unknown) => void): Promise<WorkerSet | undefined>;
|
|
9
|
+
export declare function makeWebworkerScript(): string;
|
|
10
|
+
export declare function startWebworker(handle_result?: (result: unknown) => void, handle_error?: (error: unknown) => void): Worker;
|
|
@@ -1,66 +1,115 @@
|
|
|
1
|
-
import { get_info, ViewPair } from "../api";
|
|
2
1
|
import { LOCAL_NODE_DEFAULT_URL } from "../node-interaction/nodeUrl";
|
|
3
2
|
import {} from "./scanresult/scanCache";
|
|
4
|
-
import {
|
|
3
|
+
import { openScanSettingsFile, SCAN_SETTINGS_STORE_NAME_DEFAULT, } from "./scanSettings";
|
|
4
|
+
import { log, setupLoggingPath } from "../io/logging";
|
|
5
5
|
import { workerMainCode } from "./worker-entrypoints/worker";
|
|
6
|
-
export
|
|
7
|
-
const nonHaltedWallets = await openNonHaltedWallets(scan_settings_path);
|
|
8
|
-
const masterWalletSettings = nonHaltedWallets[0];
|
|
9
|
-
if (!masterWalletSettings)
|
|
10
|
-
return;
|
|
11
|
-
const masterWithKeys = await walletSettingsPlusKeys(masterWalletSettings);
|
|
12
|
-
const masterViewPair = await ViewPair.create(masterWalletSettings.primary_address, masterWithKeys.secret_view_key, masterWalletSettings.subaddress_index, masterWalletSettings.node_url);
|
|
13
|
-
await masterViewPair.scan(cacheChanged, stopSync, scan_settings_path, pathPrefix);
|
|
14
|
-
}
|
|
6
|
+
export const CPU_POOL_SIZE = 4;
|
|
15
7
|
export async function createWebworker(handle_result, scan_settings_path, pathPrefix, handle_error) {
|
|
16
8
|
try {
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
9
|
+
const resolvedPath = scan_settings_path || SCAN_SETTINGS_STORE_NAME_DEFAULT;
|
|
10
|
+
const scanSettings = await openScanSettingsFile(resolvedPath);
|
|
11
|
+
await setupLoggingPath(resolvedPath, pathPrefix ?? "", "mainthread");
|
|
12
|
+
const node_url = scanSettings?.node_url || LOCAL_NODE_DEFAULT_URL;
|
|
13
|
+
const cpu_worker_count = typeof scanSettings?.cpu_worker_count !== "undefined"
|
|
14
|
+
? scanSettings?.cpu_worker_count
|
|
15
|
+
: CPU_POOL_SIZE;
|
|
16
|
+
// spawn CPU workers
|
|
17
|
+
const cpuWorkers = [];
|
|
18
|
+
const cpuPorts = [];
|
|
19
|
+
for (let i = 0; i < cpu_worker_count; i++) {
|
|
20
|
+
const channel = new MessageChannel();
|
|
21
|
+
const cpuWorker = await startWebworkerReady();
|
|
22
|
+
cpuWorker.postMessage({
|
|
23
|
+
type: "setup",
|
|
24
|
+
role: "cpubound",
|
|
25
|
+
cpu_worker_id: i,
|
|
26
|
+
scan_settings_path: resolvedPath,
|
|
27
|
+
pathPrefix,
|
|
28
|
+
}, [channel.port1]);
|
|
29
|
+
cpuWorker.onerror = (e) => {
|
|
30
|
+
if (handle_error)
|
|
31
|
+
handle_error("cpu worker " + i + " error: " + (e.message ?? String(e)));
|
|
32
|
+
};
|
|
33
|
+
cpuWorkers.push(cpuWorker);
|
|
34
|
+
cpuPorts.push(channel.port2);
|
|
35
|
+
}
|
|
36
|
+
const coordinationWorker = await startWebworkerReady();
|
|
37
|
+
coordinationWorker.postMessage({
|
|
38
|
+
type: "setup",
|
|
39
|
+
scan_settings_path: resolvedPath,
|
|
40
|
+
pathPrefix,
|
|
41
|
+
role: "coordinator",
|
|
42
|
+
node_url,
|
|
43
|
+
start_height: 0,
|
|
44
|
+
}, cpuPorts); // transfer CPU port2s to coordination worker
|
|
45
|
+
log("createWebworker", [
|
|
46
|
+
"coordinator worker started, node_url=" + node_url,
|
|
47
|
+
", cpuPorts=" + cpuPorts.length,
|
|
48
|
+
]);
|
|
49
|
+
coordinationWorker.onmessage = (event) => {
|
|
50
|
+
if (event.data.type === "ERROR") {
|
|
51
|
+
if (handle_error)
|
|
52
|
+
handle_error(event.data.payload);
|
|
53
|
+
}
|
|
54
|
+
else if (event.data.type === "SCAN_RESULT") {
|
|
55
|
+
if (handle_result)
|
|
56
|
+
handle_result(event.data.payload);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
return {
|
|
60
|
+
fetchWorker: coordinationWorker,
|
|
61
|
+
cpuWorkers,
|
|
62
|
+
terminate: () => {
|
|
63
|
+
coordinationWorker.terminate();
|
|
64
|
+
for (const w of cpuWorkers)
|
|
65
|
+
w.terminate();
|
|
66
|
+
},
|
|
67
|
+
};
|
|
23
68
|
}
|
|
24
69
|
catch (error) {
|
|
25
70
|
handle_error?.(error);
|
|
26
71
|
}
|
|
27
72
|
}
|
|
28
|
-
export function makeWebworkerScript(
|
|
29
|
-
|
|
30
|
-
? `const scan_settings_path = '${scan_settings_path}';`
|
|
31
|
-
: "const scan_settings_path = undefined;";
|
|
32
|
-
const pathPrefixLine = pathPrefix
|
|
33
|
-
? `const pathPrefix = '${pathPrefix}';`
|
|
34
|
-
: "const pathPrefix = undefined;";
|
|
35
|
-
return `\n
|
|
36
|
-
${settingsPathLine}
|
|
37
|
-
${pathPrefixLine}
|
|
38
|
-
${workerMainCode}
|
|
39
|
-
`;
|
|
73
|
+
export function makeWebworkerScript() {
|
|
74
|
+
return workerMainCode;
|
|
40
75
|
}
|
|
41
|
-
export function startWebworker(
|
|
42
|
-
const blob = new Blob([
|
|
76
|
+
export function startWebworker(handle_result, handle_error) {
|
|
77
|
+
const blob = new Blob([workerMainCode], {
|
|
43
78
|
type: "text/javascript",
|
|
44
79
|
});
|
|
45
80
|
const url = URL.createObjectURL(blob);
|
|
46
81
|
const worker = new Worker(url, { type: "module" });
|
|
47
82
|
worker.onmessage = (event) => {
|
|
48
83
|
switch (event.data.type) {
|
|
49
|
-
case "RESULT":
|
|
84
|
+
case "RESULT":
|
|
50
85
|
if (handle_result)
|
|
51
86
|
handle_result(event.data.payload);
|
|
52
87
|
break;
|
|
53
88
|
case "ERROR":
|
|
89
|
+
case "scan_error":
|
|
54
90
|
if (handle_error)
|
|
55
|
-
handle_error(event.data.payload);
|
|
91
|
+
handle_error(event.data.payload ?? event.data.error);
|
|
92
|
+
break;
|
|
93
|
+
case "DEBUG":
|
|
94
|
+
log("startWebworker", ["worker debug:", event.data.payload]);
|
|
56
95
|
break;
|
|
57
96
|
}
|
|
58
97
|
};
|
|
59
98
|
return worker;
|
|
60
99
|
}
|
|
61
|
-
//
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
);
|
|
100
|
+
// creates a worker via startWebworker, then waits for it to signal
|
|
101
|
+
// WORKER_READY (meaning self.onmessage = handleMessage has executed).
|
|
102
|
+
// after that, postMessage is safe, no race between worker startup
|
|
103
|
+
// and message delivery.
|
|
104
|
+
function startWebworkerReady() {
|
|
105
|
+
const worker = startWebworker();
|
|
106
|
+
return new Promise((resolve) => {
|
|
107
|
+
const onReady = (e) => {
|
|
108
|
+
if (e.data?.type === "WORKER_READY") {
|
|
109
|
+
worker.removeEventListener("message", onReady);
|
|
110
|
+
resolve(worker);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
worker.addEventListener("message", onReady);
|
|
114
|
+
});
|
|
115
|
+
}
|