@spirobel/monero-wallet-api 0.2.0 → 0.3.0

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 (68) hide show
  1. package/README.md +3 -3
  2. package/dist/api.d.ts +25 -96
  3. package/dist/api.js +23 -175
  4. package/dist/io/BunFileInterface.d.ts +32 -0
  5. package/dist/io/atomicWrite.d.ts +2 -0
  6. package/dist/io/atomicWrite.js +10 -0
  7. package/dist/io/extension.d.ts +18 -0
  8. package/dist/io/extension.js +11 -0
  9. package/dist/io/indexedDB.d.ts +45 -0
  10. package/dist/io/indexedDB.js +221 -0
  11. package/dist/io/readDir.d.ts +1 -0
  12. package/dist/io/readDir.js +7 -0
  13. package/dist/io/sleep.d.ts +1 -0
  14. package/dist/io/sleep.js +1 -0
  15. package/dist/keypairs-seeds/keypairs.d.ts +29 -0
  16. package/dist/keypairs-seeds/keypairs.js +207 -0
  17. package/dist/keypairs-seeds/writeKeypairs.d.ts +11 -0
  18. package/dist/keypairs-seeds/writeKeypairs.js +75 -0
  19. package/dist/node-interaction/binaryEndpoints.d.ts +59 -14
  20. package/dist/node-interaction/binaryEndpoints.js +110 -54
  21. package/dist/node-interaction/jsonEndpoints.d.ts +249 -187
  22. package/dist/node-interaction/jsonEndpoints.js +287 -0
  23. package/dist/node-interaction/nodeUrl.d.ts +129 -0
  24. package/dist/node-interaction/nodeUrl.js +113 -0
  25. package/dist/scanning-syncing/backgroundWorker.d.ts +6 -0
  26. package/dist/scanning-syncing/backgroundWorker.js +56 -0
  27. package/dist/scanning-syncing/connectionStatus.d.ts +15 -0
  28. package/dist/scanning-syncing/connectionStatus.js +35 -0
  29. package/dist/scanning-syncing/openWallet.d.ts +28 -0
  30. package/dist/scanning-syncing/openWallet.js +57 -0
  31. package/dist/scanning-syncing/scanSettings.d.ts +96 -0
  32. package/dist/scanning-syncing/scanSettings.js +243 -0
  33. package/dist/scanning-syncing/scanresult/computeKeyImage.d.ts +3 -0
  34. package/dist/scanning-syncing/scanresult/computeKeyImage.js +21 -0
  35. package/dist/scanning-syncing/scanresult/getBlocksbinBuffer.d.ts +28 -0
  36. package/dist/scanning-syncing/scanresult/getBlocksbinBuffer.js +52 -0
  37. package/dist/scanning-syncing/scanresult/reorg.d.ts +14 -0
  38. package/dist/scanning-syncing/scanresult/reorg.js +78 -0
  39. package/dist/scanning-syncing/scanresult/scanCache.d.ts +84 -0
  40. package/dist/scanning-syncing/scanresult/scanCache.js +134 -0
  41. package/dist/scanning-syncing/scanresult/scanCacheOpened.d.ts +149 -0
  42. package/dist/scanning-syncing/scanresult/scanCacheOpened.js +648 -0
  43. package/dist/scanning-syncing/scanresult/scanResult.d.ts +64 -0
  44. package/dist/scanning-syncing/scanresult/scanResult.js +213 -0
  45. package/dist/scanning-syncing/scanresult/scanStats.d.ts +60 -0
  46. package/dist/scanning-syncing/scanresult/scanStats.js +273 -0
  47. package/dist/scanning-syncing/worker-entrypoints/worker.d.ts +1 -0
  48. package/dist/scanning-syncing/worker-entrypoints/worker.js +8 -0
  49. package/dist/scanning-syncing/worker-mains/worker.d.ts +1 -0
  50. package/dist/scanning-syncing/worker-mains/worker.js +7 -0
  51. package/dist/send-functionality/conversion.d.ts +4 -0
  52. package/dist/send-functionality/conversion.js +75 -0
  53. package/dist/send-functionality/inputSelection.d.ts +13 -0
  54. package/dist/send-functionality/inputSelection.js +8 -0
  55. package/dist/send-functionality/transactionBuilding.d.ts +51 -0
  56. package/dist/send-functionality/transactionBuilding.js +111 -0
  57. package/dist/tools/monero-tools.d.ts +46 -0
  58. package/dist/tools/monero-tools.js +165 -0
  59. package/dist/viewpair/ViewPair.d.ts +157 -0
  60. package/dist/viewpair/ViewPair.js +346 -0
  61. package/dist/wasm-processing/wasi.js +1 -2
  62. package/dist/wasm-processing/wasmFile.d.ts +1 -1
  63. package/dist/wasm-processing/wasmFile.js +2 -2
  64. package/dist/wasm-processing/wasmProcessor.d.ts +16 -4
  65. package/dist/wasm-processing/wasmProcessor.js +23 -7
  66. package/package.json +29 -6
  67. package/dist/testscrap.js +0 -36
  68. /package/dist/{testscrap.d.ts → io/BunFileInterface.js} +0 -0
@@ -48,6 +48,42 @@ export const GetInfoResponseSchema = z.object({
48
48
  wide_difficulty: z.string(),
49
49
  }),
50
50
  });
51
+ /**
52
+ * Response schema for the get_output_distribution method.
53
+ *
54
+ * @property id - The request ID.
55
+ * @property jsonrpc - The JSON-RPC version.
56
+ * @property result - The result object containing:
57
+ * - distributions: An array of distribution objects, each with:
58
+ * - amount: unsigned int Same as in the request. Use 0 to get all RingCT outputs.
59
+ * - base: unsigned int; The total number of outputs of amount in the chain before, not including, the block at start_height.
60
+ * - distribution: array of unsigned int
61
+ * - 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
+ * - status: string; General RPC error code. "OK" means everything looks good.
63
+ */
64
+ export const GetOutputDistributionResponseSchema = z.object({
65
+ id: z.string(),
66
+ jsonrpc: z.literal("2.0"),
67
+ result: z.object({
68
+ distributions: z.array(z.object({
69
+ amount: z.number(),
70
+ base: z.number(),
71
+ distribution: z.array(z.number()),
72
+ start_height: z.number(),
73
+ })),
74
+ status: z.string(),
75
+ }),
76
+ });
77
+ export function parseGetOutputDistributionResponse(data) {
78
+ const result = GetOutputDistributionResponseSchema.safeParse(data);
79
+ if (result.success) {
80
+ return result.data;
81
+ }
82
+ else {
83
+ console.error("Validation failed:", result.error);
84
+ return null;
85
+ }
86
+ }
51
87
  export function parseGetInfoResponse(data) {
52
88
  const result = GetInfoResponseSchema.safeParse(data);
53
89
  if (result.success) {
@@ -80,3 +116,254 @@ export async function get_info(NODE_URL) {
80
116
  }
81
117
  return parsedResult.result;
82
118
  }
119
+ export async function get_output_distribution(NODE_URL, params = {
120
+ amounts: [0],
121
+ binary: false,
122
+ cumulative: true,
123
+ }) {
124
+ const getOutputDistributionResponse = await fetch(NODE_URL + "/json_rpc", {
125
+ method: "POST",
126
+ headers: {
127
+ "Content-Type": "application/json",
128
+ },
129
+ body: JSON.stringify({
130
+ jsonrpc: "2.0",
131
+ id: "0",
132
+ method: "get_output_distribution",
133
+ params,
134
+ }),
135
+ });
136
+ if (!getOutputDistributionResponse.ok) {
137
+ throw new Error(`Failed to get output distribution (for decoy sampling): ${getOutputDistributionResponse.statusText}`);
138
+ }
139
+ const getOutputDistributionResult = await getOutputDistributionResponse.json();
140
+ const parsedResult = parseGetOutputDistributionResponse(getOutputDistributionResult);
141
+ if (parsedResult === null || !parsedResult.result) {
142
+ throw new Error("Failed to receive output distribution from node (get_output_distribution result)");
143
+ }
144
+ return parsedResult.result;
145
+ }
146
+ /**
147
+ * Response schema for the get_fee_estimate method.
148
+ *
149
+ * @property id - The request ID.
150
+ * @property jsonrpc - The JSON-RPC version.
151
+ * @property result - The result object containing:
152
+ * - status: string; General RPC error code. "OK" means everything looks good.
153
+ * - fee: unsigned int; Base fee per byte.
154
+ * - fees: (Optional) Array of unsigned int; Fee estimates for priorities 1–4.
155
+ * - quantization_mask: unsigned int; Mask used for fee rounding.
156
+ */
157
+ export const GetFeeEstimateResponseSchema = z.object({
158
+ id: z.string(),
159
+ jsonrpc: z.literal("2.0"),
160
+ result: z.object({
161
+ status: z.string(),
162
+ fee: z.number(),
163
+ fees: z.array(z.number()).optional(),
164
+ quantization_mask: z.number(),
165
+ }),
166
+ });
167
+ export function parseGetFeeEstimateResponse(data) {
168
+ const result = GetFeeEstimateResponseSchema.safeParse(data);
169
+ if (result.success) {
170
+ return result.data;
171
+ }
172
+ else {
173
+ console.error("Validation failed:", result.error);
174
+ return null;
175
+ }
176
+ }
177
+ export async function get_fee_estimate(NODE_URL) {
178
+ // GRACE_BLOCKS_FOR_FEE_ESTIMATE: u64 = 10 (0xA) accoding to monero oxide
179
+ const GRACE_BLOCKS_FOR_FEE_ESTIMATE = 10;
180
+ const getFeeEstimateResponse = await fetch(NODE_URL + "/json_rpc", {
181
+ method: "POST",
182
+ headers: {
183
+ "Content-Type": "application/json",
184
+ },
185
+ body: JSON.stringify({
186
+ jsonrpc: "2.0",
187
+ id: "0",
188
+ method: "get_fee_estimate",
189
+ params: { grace_blocks: GRACE_BLOCKS_FOR_FEE_ESTIMATE },
190
+ }),
191
+ });
192
+ if (!getFeeEstimateResponse.ok) {
193
+ throw new Error(`Failed to get fee estimate: ${getFeeEstimateResponse.statusText}`);
194
+ }
195
+ const getFeeEstimateResult = await getFeeEstimateResponse.json();
196
+ const parsedResult = parseGetFeeEstimateResponse(getFeeEstimateResult);
197
+ if (parsedResult === null || !parsedResult.result) {
198
+ throw new Error("Failed to receive fee estimate from node (get_fee_estimate result)");
199
+ }
200
+ return parsedResult.result;
201
+ }
202
+ export const SendRawTransactionResponseSchema = z.object({
203
+ double_spend: z.boolean(), // double_spend - boolean; Transaction is a double spend (true) or not (false).
204
+ fee_too_low: z.boolean(), // fee_too_low - boolean; Fee is too low (true) or OK (false).
205
+ invalid_input: z.boolean(), // invalid_input - boolean; Input is invalid (true) or valid (false).
206
+ invalid_output: z.boolean(), // invalid_output - boolean; Output is invalid (true) or valid (false).
207
+ low_mixin: z.boolean(), // low_mixin - boolean; Mixin count is too low (true) or OK (false).
208
+ not_rct: z.boolean().optional(), // not_rct - boolean; Transaction is a standard ring transaction (true) or a ring confidential transaction (false).
209
+ not_relayed: z.boolean(), // not_relayed - boolean; Transaction was not relayed (true) or relayed (false).
210
+ overspend: z.boolean(), // overspend - boolean; Transaction uses more money than available (true) or not (false).
211
+ reason: z.string(), // reason - string; Additional information. Currently empty or "Not relayed" if transaction was accepted but not relayed.
212
+ status: z.string(), // status - string; General RPC error code. "OK" means everything looks good. Any other value means that something went wrong.
213
+ too_big: z.boolean(), // too_big - boolean; Transaction size is too big (true) or OK (false).
214
+ untrusted: z.boolean(), // 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
+ });
216
+ export function parseSendRawTransactionResponse(data) {
217
+ const result = SendRawTransactionResponseSchema.safeParse(data);
218
+ if (result.success) {
219
+ return result.data;
220
+ }
221
+ else {
222
+ console.error("Validation failed:", result.error);
223
+ return null;
224
+ }
225
+ }
226
+ export async function send_raw_transaction(NODE_URL, tx_as_hex, // tx_as_hex - string; Full transaction information as hexadecimal string.
227
+ do_not_relay = false) {
228
+ const sendRawTransactionResponse = await fetch(NODE_URL + "/send_raw_transaction", {
229
+ method: "POST",
230
+ headers: {
231
+ "Content-Type": "application/json",
232
+ },
233
+ body: JSON.stringify({ tx_as_hex, do_not_relay }),
234
+ });
235
+ if (!sendRawTransactionResponse.ok) {
236
+ throw new Error(`Failed to send raw transaction: ${sendRawTransactionResponse.statusText}`);
237
+ }
238
+ const sendRawTransactionResult = await sendRawTransactionResponse.json();
239
+ const parsedResult = parseSendRawTransactionResponse(sendRawTransactionResult);
240
+ if (parsedResult === null) {
241
+ throw new Error("Failed to receive response from node (send_raw_transaction result)");
242
+ }
243
+ return parsedResult;
244
+ }
245
+ /**
246
+ * Response schema for the get_block_headers_range method.
247
+ *
248
+ * @property id - The request ID.
249
+ * @property jsonrpc - The JSON-RPC version.
250
+ * @property result - The result object containing:
251
+ * - credits: unsigned int; If payment for RPC is enabled, the number of credits available to the requesting client. Otherwise, 0.
252
+ * - headers: array of block_header objects, each with:
253
+ * - block_size: unsigned int
254
+ * - block_weight: unsigned int
255
+ * - cumulative_difficulty: unsigned int
256
+ * - cumulative_difficulty_top64: unsigned int
257
+ * - depth: unsigned int
258
+ * - difficulty: unsigned int
259
+ * - difficulty_top64: unsigned int
260
+ * - hash: string
261
+ * - height: unsigned int
262
+ * - long_term_weight: unsigned int
263
+ * - major_version: unsigned int
264
+ * - miner_tx_hash: string
265
+ * - minor_version: unsigned int
266
+ * - nonce: unsigned int
267
+ * - num_txes: unsigned int
268
+ * - orphan_status: boolean
269
+ * - pow_hash: string (if fill_pow_hash is true)
270
+ * - prev_hash: string
271
+ * - reward: unsigned int
272
+ * - timestamp: unsigned int
273
+ * - wide_cumulative_difficulty: string
274
+ * - wide_difficulty: string
275
+ * - status: string; General RPC error code. "OK" means everything looks good.
276
+ * - top_hash: string; If payment for RPC is enabled, the hash of the highest block in the chain. Otherwise, empty.
277
+ * - untrusted: boolean; States if the result is obtained using the bootstrap mode (true) or not (false).
278
+ * @property error - Optional error object if the request failed:
279
+ * - code: int; Error code.
280
+ * - message: string; Error message.
281
+ */
282
+ export const GetBlockHeadersRangeResponseSchema = z.object({
283
+ id: z.string(),
284
+ jsonrpc: z.literal("2.0"),
285
+ result: z
286
+ .object({
287
+ credits: z.number(),
288
+ headers: z.array(z.object({
289
+ block_size: z.number(),
290
+ block_weight: z.number(),
291
+ cumulative_difficulty: z.number(),
292
+ cumulative_difficulty_top64: z.number(),
293
+ depth: z.number(),
294
+ difficulty: z.number(),
295
+ difficulty_top64: z.number(),
296
+ hash: z.string(),
297
+ height: z.number(),
298
+ long_term_weight: z.number(),
299
+ major_version: z.number(),
300
+ miner_tx_hash: z.string(),
301
+ minor_version: z.number(),
302
+ nonce: z.number(),
303
+ num_txes: z.number(),
304
+ orphan_status: z.boolean(),
305
+ pow_hash: z.string(),
306
+ prev_hash: z.string(),
307
+ reward: z.number(),
308
+ timestamp: z.number(),
309
+ wide_cumulative_difficulty: z.string(),
310
+ wide_difficulty: z.string(),
311
+ })),
312
+ status: z.string(),
313
+ top_hash: z.string(),
314
+ untrusted: z.boolean(),
315
+ })
316
+ .optional(),
317
+ error: z
318
+ .object({
319
+ code: z.number(),
320
+ message: z.string(),
321
+ })
322
+ .optional(),
323
+ });
324
+ export function parseGetBlockHeadersRangeResponse(data) {
325
+ const result = GetBlockHeadersRangeResponseSchema.safeParse(data);
326
+ if (result.success) {
327
+ return result.data;
328
+ }
329
+ else {
330
+ console.error("Validation failed:", result.error);
331
+ return null;
332
+ }
333
+ }
334
+ export const RESTRICTED_BLOCK_HEADER_RANGE = 1000;
335
+ export async function get_block_headers_range(NODE_URL, params) {
336
+ //https://github.com/monero-project/monero/blob/48ad374b0d6d6e045128729534dc2508e6999afe/src/rpc/core_rpc_server.cpp#L74
337
+ // #define RESTRICTED_BLOCK_HEADER_RANGE 1000
338
+ // https://github.com/monero-project/monero/blob/48ad374b0d6d6e045128729534dc2508e6999afe/src/rpc/core_rpc_server.cpp#L2612
339
+ if (params.end_height - params.start_height > RESTRICTED_BLOCK_HEADER_RANGE) {
340
+ throw new Error("Too many block headers requested. Max: " + RESTRICTED_BLOCK_HEADER_RANGE);
341
+ }
342
+ const getBlockHeadersRangeResponse = await fetch(NODE_URL + "/json_rpc", {
343
+ method: "POST",
344
+ headers: {
345
+ "Content-Type": "application/json",
346
+ },
347
+ body: JSON.stringify({
348
+ jsonrpc: "2.0",
349
+ id: "0",
350
+ method: "get_block_headers_range",
351
+ params,
352
+ }),
353
+ });
354
+ if (!getBlockHeadersRangeResponse.ok) {
355
+ throw new Error(`Failed to get block headers range: ${getBlockHeadersRangeResponse.statusText}`);
356
+ }
357
+ const getBlockHeadersRangeResult = await getBlockHeadersRangeResponse.json();
358
+ const parsedResult = parseGetBlockHeadersRangeResponse(getBlockHeadersRangeResult);
359
+ if (parsedResult === null) {
360
+ throw new Error("Failed to parse block headers range response from node");
361
+ }
362
+ if (parsedResult.error) {
363
+ throw new Error(`RPC error: ${parsedResult.error.message} (code: ${parsedResult.error.code})`);
364
+ }
365
+ if (!parsedResult.result) {
366
+ throw new Error("Failed to receive block headers range from node (missing result)");
367
+ }
368
+ return parsedResult.result;
369
+ }
@@ -0,0 +1,129 @@
1
+ import { type GetBlocksBinRequest, type Output, type GetOutsBinRequest } from "./binaryEndpoints";
2
+ import { type FeeEstimateResponse, type GetBlockHeadersRangeParams, type GetOutputDistributionParams, type SendRawTransactionResult } from "./jsonEndpoints";
3
+ import { type SignedTransaction, type Input } from "../send-functionality/transactionBuilding";
4
+ import { WasmProcessor } from "../wasm-processing/wasmProcessor";
5
+ /**
6
+ * This class is useful to interact with Moneros DaemonRpc binary requests in a convenient way.
7
+ * (similar to how you would interact with a REST api that gives you json back.)
8
+ * The wasm part will handle the creation of the binary requests and parse the responses and return them as json.
9
+ * {@link https://docs.getmonero.org/rpc-library/monerod-rpc/#get_blocksbin}
10
+ */
11
+ export declare class NodeUrl extends WasmProcessor {
12
+ node_url: string;
13
+ protected constructor(node_url: string);
14
+ static create(node_url?: string): Promise<NodeUrl>;
15
+ /**
16
+ * This request helps making requests to the get_blocks.bin endpoint of the Monerod nodes.
17
+ * @link https://docs.getmonero.org/rpc-library/monerod-rpc/#get_blocksbin
18
+ * @param params params that will be turned into epee (moner lib that does binary serialization)
19
+ * @returns after the request is made it will return epee serialized objects that are then parsed into json.
20
+ */
21
+ getBlocksBin(params: GetBlocksBinRequest): Promise<import("./binaryEndpoints").GetBlocksBinResponse | import("./binaryEndpoints").ErrorResponse>;
22
+ /**
23
+ * This request helps making requests to the get_outs.bin endpoint of the Monerod nodes.
24
+ * @link https://docs.getmonero.org/rpc-library/monerod-rpc/#get_outsbin
25
+ * @param outputIndexArrayToFetch an array of numbers that represent the output indices to be fetched. (candidates array returned from sampleDecoys for example)
26
+ * @returns after the request is made it will return epee serialized objects as a binary array.
27
+ */
28
+ getOutsBin(outputIndexArrayToFetch: GetOutsBinRequest): Promise<import("./binaryEndpoints").GetOutsResponseBuffer>;
29
+ /**
30
+ * This request helps making requests to the get_outs.bin endpoint of the Monerod nodes.
31
+ * @link https://docs.getmonero.org/rpc-library/monerod-rpc/#get_outsbin
32
+ * @param outputIndexArrayToFetch an array of numbers that represent the output indices to be fetched. (candidates array returned from sampleDecoys for example)
33
+ * @returns after the request is made it will return epee serialized objects that are then parsed into json.
34
+ */
35
+ getOutsBinJson(outputIndexArrayToFetch: GetOutsBinRequest): Promise<import("./binaryEndpoints").GetOutsBinResponse>;
36
+ /**
37
+ * fetch output distribution from node (necessary to make input - also named OutputWithDecoys in Monero-oxide)
38
+ * @param params defaults to: { amounts: [0], binary: false }
39
+ * @returns returns output distribution necessary to sample input candidates
40
+ */
41
+ getOutputDistribution(params?: GetOutputDistributionParams): Promise<number[]>;
42
+ /**
43
+ * fetch fee estimate from node
44
+ * @returns fee estimate response
45
+ */
46
+ getFeeEstimate(): Promise<FeeEstimateResponse>;
47
+ /**
48
+ * sample decoys with distibution (cumulative)
49
+ * @param outputToBeSpentIndex the index of the output to be spent
50
+ * @param distribution cumulative distribution fetched from the node with getOutputDistribution()
51
+ * @param candidatesLength the amount of candidates to be sampled + 1 (the result will also contain the original index so in total the length of the resulting array will be this + 2)
52
+ * @returns SampledDecoys: {candidates: number[]} - an array with output indices including the spent index
53
+ */
54
+ sampleDecoys(outputToBeSpentIndex: number, distribution: number[], candidatesLength: number): import("../send-functionality/transactionBuilding").SampledDecoys;
55
+ /**
56
+ * makeInput helper that uses the wasm module to create an input for a transaction.
57
+ * @param outputToBeSpent the output that should be spent
58
+ * @param candidates array of output indices that can be used as decoys
59
+ * @param get_outs_Response the response from a get_outs.bin request for the candidates
60
+ * @returns the input serialized that can be used in transaction building
61
+ */
62
+ makeInput(outputToBeSpent: Output, candidates: number[], get_outs_Response: Uint8Array): Input;
63
+ /**
64
+ * Send a raw transaction to the node for broadcasting.
65
+ * @link https://docs.getmonero.org/rpc-library/monerod-rpc/#send_raw_transaction
66
+ * @param tx_as_hex tx_as_hex - string; Full transaction information as hexadecimal string.
67
+ * @param do_not_relay (Optional) boolean; Stop relaying transaction to other nodes. Defaults to false.
68
+ * @returns The response indicating success or failure, with validation details.
69
+ */
70
+ sendRawTransaction(tx_as_hex: SignedTransaction, do_not_relay?: boolean): Promise<SendRawTransactionResult>;
71
+ /**
72
+ * Retrieve block headers for a specified range of heights.
73
+ * @link https://docs.getmonero.org/rpc-library/monerod-rpc/#get_block_headers_range
74
+ * @param params The parameters including start_height, end_height, and optional fill_pow_hash.
75
+ * @returns The result object with headers, status, etc. Throws if the range is invalid:(end_height > daemonheight)
76
+ */
77
+ getBlockHeadersRange(params: GetBlockHeadersRangeParams): Promise<import("./jsonEndpoints").GetBlockHeadersRange>;
78
+ /**
79
+ * Fetch general information about the Monero daemon.
80
+ * @link https://docs.getmonero.org/rpc-library/monerod-rpc/#get_info
81
+ * @returns The result object with daemon info like height, status, etc.
82
+ */
83
+ getInfo(): Promise<{
84
+ adjusted_time: number;
85
+ alt_blocks_count: number;
86
+ block_size_limit: number;
87
+ block_size_median: number;
88
+ block_weight_limit: number;
89
+ block_weight_median: number;
90
+ bootstrap_daemon_address: string;
91
+ busy_syncing: boolean;
92
+ credits: number;
93
+ cumulative_difficulty: number;
94
+ cumulative_difficulty_top64: number;
95
+ database_size: number;
96
+ difficulty: number;
97
+ difficulty_top64: number;
98
+ free_space: number;
99
+ grey_peerlist_size: number;
100
+ height: number;
101
+ height_without_bootstrap: number;
102
+ incoming_connections_count: number;
103
+ mainnet: boolean;
104
+ nettype: string;
105
+ offline: boolean;
106
+ outgoing_connections_count: number;
107
+ restricted: boolean;
108
+ rpc_connections_count: number;
109
+ stagenet: boolean;
110
+ start_time: number;
111
+ status: string;
112
+ synchronized: boolean;
113
+ target: number;
114
+ target_height: number;
115
+ testnet: boolean;
116
+ top_block_hash: string;
117
+ top_hash: string;
118
+ tx_count: number;
119
+ tx_pool_size: number;
120
+ untrusted: boolean;
121
+ update_available: boolean;
122
+ version: string;
123
+ was_bootstrap_ever_used: boolean;
124
+ white_peerlist_size: number;
125
+ wide_cumulative_difficulty: string;
126
+ wide_difficulty: string;
127
+ }>;
128
+ }
129
+ export declare const LOCAL_NODE_DEFAULT_URL = "http://127.0.0.1:18081";
@@ -0,0 +1,113 @@
1
+ import { getBlocksBinJson, getOutsBinJson, getOutsBinExecuteRequest, } from "./binaryEndpoints";
2
+ import { get_block_headers_range, get_fee_estimate, get_info, get_output_distribution, send_raw_transaction, } from "./jsonEndpoints";
3
+ import { makeInput, sampleDecoys, } from "../send-functionality/transactionBuilding";
4
+ import { WasmProcessor } from "../wasm-processing/wasmProcessor";
5
+ /**
6
+ * This class is useful to interact with Moneros DaemonRpc binary requests in a convenient way.
7
+ * (similar to how you would interact with a REST api that gives you json back.)
8
+ * The wasm part will handle the creation of the binary requests and parse the responses and return them as json.
9
+ * {@link https://docs.getmonero.org/rpc-library/monerod-rpc/#get_blocksbin}
10
+ */
11
+ export class NodeUrl extends WasmProcessor {
12
+ node_url;
13
+ constructor(node_url) {
14
+ super();
15
+ this.node_url = node_url;
16
+ }
17
+ static async create(node_url) {
18
+ const nodeUrl = new NodeUrl(node_url || LOCAL_NODE_DEFAULT_URL);
19
+ await nodeUrl.initWasmModule();
20
+ return nodeUrl;
21
+ }
22
+ /**
23
+ * This request helps making requests to the get_blocks.bin endpoint of the Monerod nodes.
24
+ * @link https://docs.getmonero.org/rpc-library/monerod-rpc/#get_blocksbin
25
+ * @param params params that will be turned into epee (moner lib that does binary serialization)
26
+ * @returns after the request is made it will return epee serialized objects that are then parsed into json.
27
+ */
28
+ getBlocksBin(params) {
29
+ return getBlocksBinJson(this, params);
30
+ }
31
+ /**
32
+ * This request helps making requests to the get_outs.bin endpoint of the Monerod nodes.
33
+ * @link https://docs.getmonero.org/rpc-library/monerod-rpc/#get_outsbin
34
+ * @param outputIndexArrayToFetch an array of numbers that represent the output indices to be fetched. (candidates array returned from sampleDecoys for example)
35
+ * @returns after the request is made it will return epee serialized objects as a binary array.
36
+ */
37
+ getOutsBin(outputIndexArrayToFetch) {
38
+ return getOutsBinExecuteRequest(this, outputIndexArrayToFetch);
39
+ }
40
+ /**
41
+ * This request helps making requests to the get_outs.bin endpoint of the Monerod nodes.
42
+ * @link https://docs.getmonero.org/rpc-library/monerod-rpc/#get_outsbin
43
+ * @param outputIndexArrayToFetch an array of numbers that represent the output indices to be fetched. (candidates array returned from sampleDecoys for example)
44
+ * @returns after the request is made it will return epee serialized objects that are then parsed into json.
45
+ */
46
+ getOutsBinJson(outputIndexArrayToFetch) {
47
+ return getOutsBinJson(this, outputIndexArrayToFetch);
48
+ }
49
+ /**
50
+ * fetch output distribution from node (necessary to make input - also named OutputWithDecoys in Monero-oxide)
51
+ * @param params defaults to: { amounts: [0], binary: false }
52
+ * @returns returns output distribution necessary to sample input candidates
53
+ */
54
+ async getOutputDistribution(params) {
55
+ return (await get_output_distribution(this.node_url, params))
56
+ .distributions[0].distribution;
57
+ }
58
+ /**
59
+ * fetch fee estimate from node
60
+ * @returns fee estimate response
61
+ */
62
+ getFeeEstimate() {
63
+ return get_fee_estimate(this.node_url);
64
+ }
65
+ /**
66
+ * sample decoys with distibution (cumulative)
67
+ * @param outputToBeSpentIndex the index of the output to be spent
68
+ * @param distribution cumulative distribution fetched from the node with getOutputDistribution()
69
+ * @param candidatesLength the amount of candidates to be sampled + 1 (the result will also contain the original index so in total the length of the resulting array will be this + 2)
70
+ * @returns SampledDecoys: {candidates: number[]} - an array with output indices including the spent index
71
+ */
72
+ sampleDecoys(outputToBeSpentIndex, distribution, candidatesLength) {
73
+ return sampleDecoys(this, outputToBeSpentIndex, distribution, candidatesLength);
74
+ }
75
+ /**
76
+ * makeInput helper that uses the wasm module to create an input for a transaction.
77
+ * @param outputToBeSpent the output that should be spent
78
+ * @param candidates array of output indices that can be used as decoys
79
+ * @param get_outs_Response the response from a get_outs.bin request for the candidates
80
+ * @returns the input serialized that can be used in transaction building
81
+ */
82
+ makeInput(outputToBeSpent, candidates, get_outs_Response) {
83
+ return makeInput(this, outputToBeSpent, candidates, get_outs_Response);
84
+ }
85
+ /**
86
+ * Send a raw transaction to the node for broadcasting.
87
+ * @link https://docs.getmonero.org/rpc-library/monerod-rpc/#send_raw_transaction
88
+ * @param tx_as_hex tx_as_hex - string; Full transaction information as hexadecimal string.
89
+ * @param do_not_relay (Optional) boolean; Stop relaying transaction to other nodes. Defaults to false.
90
+ * @returns The response indicating success or failure, with validation details.
91
+ */
92
+ async sendRawTransaction(tx_as_hex, do_not_relay = false) {
93
+ return send_raw_transaction(this.node_url, tx_as_hex, do_not_relay);
94
+ }
95
+ /**
96
+ * Retrieve block headers for a specified range of heights.
97
+ * @link https://docs.getmonero.org/rpc-library/monerod-rpc/#get_block_headers_range
98
+ * @param params The parameters including start_height, end_height, and optional fill_pow_hash.
99
+ * @returns The result object with headers, status, etc. Throws if the range is invalid:(end_height > daemonheight)
100
+ */
101
+ async getBlockHeadersRange(params) {
102
+ return get_block_headers_range(this.node_url, params);
103
+ }
104
+ /**
105
+ * Fetch general information about the Monero daemon.
106
+ * @link https://docs.getmonero.org/rpc-library/monerod-rpc/#get_info
107
+ * @returns The result object with daemon info like height, status, etc.
108
+ */
109
+ async getInfo() {
110
+ return get_info(this.node_url);
111
+ }
112
+ }
113
+ export const LOCAL_NODE_DEFAULT_URL = "http://127.0.0.1:18081";
@@ -0,0 +1,6 @@
1
+ import { type CacheChangedCallback, type CacheChangedCallbackParameters } from "./scanresult/scanCache";
2
+ export declare function scanWallets(cacheChanged?: CacheChangedCallback, stopSync?: AbortSignal, scan_settings_path?: string, pathPrefix?: string): Promise<void>;
3
+ export declare function createWebworker(handle_result?: (result: CacheChangedCallbackParameters) => void, scan_settings_path?: string, pathPrefix?: string, handle_error?: (error: unknown) => void): Worker;
4
+ export declare function makeWebworkerScript(scan_settings_path?: string, pathPrefix?: string): string;
5
+ export declare function startWebworker(worker_script: string, handle_result?: (result: unknown) => void, handle_error?: (error: unknown) => void): Worker;
6
+ export declare const WW_ERROR_FORWARDING_SNIPPET = "\n\nself.onerror = (e) => self.postMessage({ type: 'ERROR', payload: e });\nself.addEventListener('unhandledrejection', (e) => \n self.postMessage({ type: 'ERROR', payload: e.reason })\n); \n";
@@ -0,0 +1,56 @@
1
+ import { ViewPair } from "../api";
2
+ import {} from "./scanresult/scanCache";
3
+ import { openNonHaltedWallets, walletSettingsPlusKeys } from "./scanSettings";
4
+ import { workerMainCode } from "./worker-entrypoints/worker";
5
+ export async function scanWallets(cacheChanged = (params) => console.log(params), stopSync, scan_settings_path, pathPrefix) {
6
+ const nonHaltedWallets = await openNonHaltedWallets(scan_settings_path);
7
+ const masterWalletSettings = nonHaltedWallets[0];
8
+ if (!masterWalletSettings)
9
+ return;
10
+ const masterWithKeys = await walletSettingsPlusKeys(masterWalletSettings);
11
+ const masterViewPair = await ViewPair.create(masterWalletSettings.primary_address, masterWithKeys.secret_view_key, masterWalletSettings.subaddress_index, masterWalletSettings.node_url);
12
+ await masterViewPair.scan(cacheChanged, stopSync, scan_settings_path, pathPrefix);
13
+ }
14
+ export function createWebworker(handle_result, scan_settings_path, pathPrefix, handle_error) {
15
+ const worker_script = makeWebworkerScript(scan_settings_path, pathPrefix);
16
+ return startWebworker(worker_script, handle_result, handle_error);
17
+ }
18
+ export function makeWebworkerScript(scan_settings_path, pathPrefix) {
19
+ const settingsPathLine = scan_settings_path
20
+ ? `const scan_settings_path = '${scan_settings_path}';`
21
+ : "const scan_settings_path = undefined;";
22
+ const pathPrefixLine = pathPrefix
23
+ ? `const pathPrefix = '${pathPrefix}';`
24
+ : "const pathPrefix = undefined;";
25
+ return `\n
26
+ ${settingsPathLine}
27
+ ${pathPrefixLine}
28
+ ${workerMainCode}
29
+ `;
30
+ }
31
+ export function startWebworker(worker_script, handle_result, handle_error) {
32
+ const blob = new Blob([WW_ERROR_FORWARDING_SNIPPET + worker_script], {
33
+ type: "text/javascript",
34
+ });
35
+ const url = URL.createObjectURL(blob);
36
+ const worker = new Worker(url, { type: "module" });
37
+ worker.onmessage = (event) => {
38
+ switch (event.data.type) {
39
+ case "RESULT": // Handle normal messages
40
+ if (handle_result)
41
+ handle_result(event.data.payload);
42
+ break;
43
+ case "ERROR":
44
+ if (handle_error)
45
+ handle_error(event.data.payload);
46
+ break;
47
+ }
48
+ };
49
+ return worker;
50
+ }
51
+ // Autoforward ALL errors with error type (global handlers)
52
+ export const WW_ERROR_FORWARDING_SNIPPET = `\n
53
+ self.onerror = (e) => self.postMessage({ type: 'ERROR', payload: e });
54
+ self.addEventListener('unhandledrejection', (e) =>
55
+ self.postMessage({ type: 'ERROR', payload: e.reason })
56
+ ); \n`;
@@ -0,0 +1,15 @@
1
+ export type ConnectionStatusOptions = "OK" | "partial_read" | "connection_failed" | "no_connection_yet" | "catastrophic_reorg";
2
+ export type ConnectionStatus = {
3
+ last_packet: {
4
+ status: ConnectionStatusOptions;
5
+ bytes_read: number;
6
+ node_url: string;
7
+ timestamp: string;
8
+ };
9
+ };
10
+ export declare const DEFAULT_CONNECTION_STATUS_PREFIX = "ConnectionStatus-";
11
+ export declare function connectionStatusFilePath(scan_settings_path?: string): string;
12
+ export declare function readConnectionStatusDefaultLocation(scan_settings_path?: string): Promise<ConnectionStatus | undefined>;
13
+ export declare function readConnectionStatusFile(connectionStatusFilePath: string): Promise<ConnectionStatus | undefined>;
14
+ export declare function writeConnectionStatusFile(status: ConnectionStatusOptions, node_url: string, bytes_read?: number, scan_settings_path?: string): Promise<number>;
15
+ export declare function readWriteConnectionStatusFile(writeCB: (cs: ConnectionStatus | undefined) => ConnectionStatus | undefined, scan_settings_path?: string): Promise<number | undefined>;
@@ -0,0 +1,35 @@
1
+ import { atomicWrite } from "../api";
2
+ import { SCAN_SETTINGS_STORE_NAME_DEFAULT } from "./scanSettings";
3
+ export const DEFAULT_CONNECTION_STATUS_PREFIX = "ConnectionStatus-";
4
+ export function connectionStatusFilePath(scan_settings_path) {
5
+ if (!scan_settings_path)
6
+ scan_settings_path = SCAN_SETTINGS_STORE_NAME_DEFAULT;
7
+ return `${DEFAULT_CONNECTION_STATUS_PREFIX}${scan_settings_path}`;
8
+ }
9
+ export async function readConnectionStatusDefaultLocation(scan_settings_path) {
10
+ return await readConnectionStatusFile(connectionStatusFilePath(scan_settings_path));
11
+ }
12
+ export async function readConnectionStatusFile(connectionStatusFilePath) {
13
+ const jsonString = await Bun.file(connectionStatusFilePath)
14
+ .text()
15
+ .catch(() => undefined);
16
+ return jsonString ? JSON.parse(jsonString) : undefined;
17
+ }
18
+ export async function writeConnectionStatusFile(status, node_url, bytes_read = 0, scan_settings_path) {
19
+ const connectionStatus = {
20
+ last_packet: {
21
+ status,
22
+ bytes_read,
23
+ node_url,
24
+ timestamp: new Date().toISOString(),
25
+ },
26
+ };
27
+ return await atomicWrite(connectionStatusFilePath(scan_settings_path), JSON.stringify(connectionStatus, null, 2));
28
+ }
29
+ export async function readWriteConnectionStatusFile(writeCB, scan_settings_path) {
30
+ const connectionStatus = await readConnectionStatusDefaultLocation(scan_settings_path);
31
+ const cb = await writeCB(connectionStatus);
32
+ if (typeof cb === "undefined")
33
+ return;
34
+ return await writeConnectionStatusFile(cb.last_packet.status, cb.last_packet.node_url, cb.last_packet.bytes_read, scan_settings_path);
35
+ }