@spirobel/monero-wallet-api 0.5.1 → 0.5.2

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 (28) hide show
  1. package/dist/actionlog/actionLog.d.ts +4 -0
  2. package/dist/actionlog/actionLog.js +9 -0
  3. package/dist/actionlog/actionLogOpened.d.ts +1 -0
  4. package/dist/actionlog/actionLogOpened.js +1 -0
  5. package/dist/api.d.ts +3 -2
  6. package/dist/api.js +3 -2
  7. package/dist/scanning-syncing/backgroundWorker.js +1 -1
  8. package/dist/scanning-syncing/blocksbuffer/blocksBufferFetchLoop.js +29 -3
  9. package/dist/scanning-syncing/blocksbuffer/blocksbufferCoordination.js +6 -3
  10. package/dist/scanning-syncing/connectionStatus.d.ts +1 -4
  11. package/dist/scanning-syncing/connectionStatus.js +1 -31
  12. package/dist/scanning-syncing/connectionStatusOpened.d.ts +15 -0
  13. package/dist/scanning-syncing/connectionStatusOpened.js +51 -0
  14. package/dist/scanning-syncing/openWallet.js +1 -1
  15. package/dist/scanning-syncing/scanresult/scanCacheOpened.d.ts +53 -7
  16. package/dist/scanning-syncing/scanresult/scanCacheOpened.js +185 -50
  17. package/dist/scanning-syncing/scanresult/scanCoordination.d.ts +1 -1
  18. package/dist/scanning-syncing/scanresult/scanCoordination.js +64 -2
  19. package/dist/scanning-syncing/scansettings/scanSettings.d.ts +165 -0
  20. package/dist/scanning-syncing/scansettings/scanSettings.js +338 -0
  21. package/dist/scanning-syncing/worker-entrypoints/worker.js +1 -1
  22. package/dist/scanning-syncing/worker-mains/worker.js +1 -2
  23. package/dist/scansettings/scanSettings.d.ts +165 -0
  24. package/dist/scansettings/scanSettings.js +338 -0
  25. package/dist/scansettings/scanSettingsOpened.d.ts +102 -0
  26. package/dist/scansettings/scanSettingsOpened.js +299 -0
  27. package/dist/viewpair/ViewPair.js +1 -1
  28. package/package.json +1 -1
@@ -0,0 +1,299 @@
1
+ import { LOCAL_NODE_DEFAULT_URL } from "../node-interaction/nodeUrl";
2
+ import { LOGGING_FUNCTIONS } from "../io/logging";
3
+ import { getPathPrefix, makeSpendKeyFromSeed, makeViewKey, openScanSettingsFile, SCAN_SETTINGS_STORE_NAME_DEFAULT, SUB_ADDRESS_INDEX_DEFAULT_VALUE, walletSettingsPlusKeys, writeEnvLineToDotEnvRefresh, writeScanSettings, writeViewKeyToDotEnv, } from "../api";
4
+ export class ScanSettingsOpened {
5
+ _scan_settings_path;
6
+ _pathPrefix;
7
+ /**
8
+ * open the settings file and return a new ScanSettingsOpened instance.
9
+ * if the file does not exist, creates one with defaults.
10
+ */
11
+ static async create(scan_settings_path = SCAN_SETTINGS_STORE_NAME_DEFAULT, pathPrefix) {
12
+ pathPrefix = getPathPrefix(scan_settings_path, pathPrefix);
13
+ let settings = await openScanSettingsFile(scan_settings_path);
14
+ if (!settings) {
15
+ settings = {
16
+ wallets: [],
17
+ node_url: LOCAL_NODE_DEFAULT_URL,
18
+ start_height: null,
19
+ };
20
+ // persist the defaults so the file exists on disk
21
+ await writeScanSettings(settings, scan_settings_path);
22
+ }
23
+ ScanSettingsOpened._validateLogOptions(settings.logs_include, settings.logs_exclude);
24
+ return new ScanSettingsOpened(settings, scan_settings_path, pathPrefix);
25
+ }
26
+ get node_url() {
27
+ return this._settings.node_url;
28
+ }
29
+ get start_height() {
30
+ return this._settings.start_height;
31
+ }
32
+ get merchant_confirmations() {
33
+ return this._settings.merchant_confirmations;
34
+ }
35
+ get cpu_worker_count() {
36
+ return this._settings.cpu_worker_count;
37
+ }
38
+ get logs() {
39
+ return this._settings.logs;
40
+ }
41
+ get logs_include() {
42
+ return this._settings.logs_include;
43
+ }
44
+ get logs_exclude() {
45
+ return this._settings.logs_exclude;
46
+ }
47
+ get wallets() {
48
+ return this._settings.wallets;
49
+ }
50
+ get scan_settings_path() {
51
+ return this._scan_settings_path;
52
+ }
53
+ get pathPrefix() {
54
+ return this._pathPrefix;
55
+ }
56
+ async setNodeUrl(node_url) {
57
+ await this.reload();
58
+ this._settings.node_url = node_url;
59
+ await this._persist();
60
+ }
61
+ async setStartHeight(start_height) {
62
+ await this.reload();
63
+ this._settings.start_height = start_height;
64
+ await this._persist();
65
+ }
66
+ async setMerchantConfirmations(merchant_confirmations) {
67
+ await this.reload();
68
+ this._settings.merchant_confirmations = merchant_confirmations;
69
+ if (merchant_confirmations === null)
70
+ delete this._settings.merchant_confirmations;
71
+ await this._persist();
72
+ }
73
+ async setCpuWorkerCount(cpu_worker_count) {
74
+ await this.reload();
75
+ if (cpu_worker_count === null) {
76
+ delete this._settings.cpu_worker_count;
77
+ }
78
+ else {
79
+ this._settings.cpu_worker_count = cpu_worker_count;
80
+ }
81
+ await this._persist();
82
+ }
83
+ async setLogSettings(logs, logs_include, logs_exclude) {
84
+ await this.reload();
85
+ if (logs === null) {
86
+ delete this._settings.logs;
87
+ }
88
+ else {
89
+ this._settings.logs = logs;
90
+ }
91
+ if (logs_include === null) {
92
+ delete this._settings.logs_include;
93
+ }
94
+ else {
95
+ this._settings.logs_include = logs_include;
96
+ }
97
+ if (logs_exclude === null) {
98
+ delete this._settings.logs_exclude;
99
+ }
100
+ else {
101
+ this._settings.logs_exclude = logs_exclude;
102
+ }
103
+ // validate before persisting
104
+ ScanSettingsOpened._validateLogOptions(this._settings.logs_include, this._settings.logs_exclude);
105
+ await this._persist();
106
+ }
107
+ /**
108
+ * get a wallet's settings (without env keys).
109
+ * returns undefined if not found.
110
+ */
111
+ getWallet(primary_address) {
112
+ return this._settings.wallets.find((w) => w.primary_address === primary_address);
113
+ }
114
+ /**
115
+ * get a wallet's settings merged with env keys.
116
+ * throws if not found or view key missing.
117
+ */
118
+ async getWalletOpened(primary_address) {
119
+ const wallet = this.getWallet(primary_address);
120
+ if (!wallet)
121
+ throw new Error(`wallet not found: ${primary_address} in ${this._scan_settings_path}`);
122
+ return await walletSettingsPlusKeys({
123
+ ...wallet,
124
+ node_url: this._settings.node_url,
125
+ start_height: this._settings.start_height,
126
+ });
127
+ }
128
+ /**
129
+ * get all wallets merged with env keys.
130
+ * wallets missing env keys are skipped.
131
+ */
132
+ async getWalletsOpened() {
133
+ const opened = [];
134
+ for (const wallet of this._settings.wallets) {
135
+ try {
136
+ const withKeys = await walletSettingsPlusKeys({
137
+ ...wallet,
138
+ node_url: this._settings.node_url,
139
+ start_height: this._settings.start_height,
140
+ });
141
+ opened.push(withKeys);
142
+ }
143
+ catch {
144
+ // wallet has no view key in env, skip
145
+ }
146
+ }
147
+ return opened;
148
+ }
149
+ walletExists(primary_address) {
150
+ return this._settings.wallets.some((w) => w.primary_address === primary_address);
151
+ }
152
+ /**
153
+ * add a new view wallet to settings and write its view key to env.
154
+ * if the wallet already exists, updates it instead.
155
+ */
156
+ async addViewWallet(primary_address, view_key, fields) {
157
+ await this.reload();
158
+ const existing = this.getWallet(primary_address);
159
+ if (existing) {
160
+ throw new Error(`wallet already exists: ${primary_address} in ${this._scan_settings_path}`);
161
+ }
162
+ primary_address = primary_address.trim();
163
+ view_key = view_key.trim();
164
+ // write view key to env first
165
+ await writeViewKeyToDotEnv(primary_address, view_key);
166
+ const subaddress_index = fields?.subaddress_index ?? SUB_ADDRESS_INDEX_DEFAULT_VALUE;
167
+ this._settings.wallets.push({
168
+ primary_address,
169
+ ...fields,
170
+ subaddress_index,
171
+ });
172
+ await this._persist();
173
+ }
174
+ /**
175
+ * add a new view wallet to settings and write its view key to env.
176
+ * if the wallet already exists, updates it instead.
177
+ */
178
+ async addSpendWallet(wallet_secret, fields) {
179
+ // first part of writeWalletSecretsToDotEnv()
180
+ const spend_key = await makeSpendKeyFromSeed(wallet_secret.toHex());
181
+ const view_pair = await makeViewKey(spend_key);
182
+ const primary_address = view_pair.mainnet_primary;
183
+ await this.reload();
184
+ const existing = this.getWallet(primary_address);
185
+ if (existing) {
186
+ throw new Error(`wallet already exists: ${primary_address} in ${this._scan_settings_path}`);
187
+ }
188
+ // second part of writeWalletSecretsToDotEnv(),
189
+ await writeEnvLineToDotEnvRefresh(`vk${primary_address}`, view_pair.view_key);
190
+ await writeEnvLineToDotEnvRefresh(`sk${primary_address}`, spend_key);
191
+ const subaddress_index = fields?.subaddress_index ?? SUB_ADDRESS_INDEX_DEFAULT_VALUE;
192
+ this._settings.wallets.push({
193
+ primary_address,
194
+ ...fields,
195
+ subaddress_index,
196
+ });
197
+ await this._persist();
198
+ }
199
+ /**
200
+ * remove a wallet from settings by primary address.
201
+ * does not remove the view key from env.
202
+ */
203
+ async removeWallet(primary_address) {
204
+ await this.reload();
205
+ this._settings.wallets = this._settings.wallets.filter((w) => w.primary_address !== primary_address);
206
+ await this._persist();
207
+ }
208
+ /**
209
+ * update specific fields on an existing wallet.
210
+ * set a field to null to unset it.
211
+ */
212
+ async updateWallet(primary_address, fields) {
213
+ await this.reload();
214
+ const wallet = this.getWallet(primary_address);
215
+ if (!wallet)
216
+ throw new Error(`wallet not found: ${primary_address} in ${this._scan_settings_path}`);
217
+ wallet.wallet_name = fields.wallet_name ?? wallet.wallet_name;
218
+ wallet.wallet_slot = fields.wallet_slot ?? wallet.wallet_slot;
219
+ wallet.wallet_route = fields.wallet_route ?? wallet.wallet_route;
220
+ wallet.subaddress_index =
221
+ fields.subaddress_index ?? wallet.subaddress_index;
222
+ wallet.halted = fields.halted ?? wallet.halted;
223
+ if (fields.halted === null)
224
+ delete wallet.halted;
225
+ if (fields.subaddress_index === null)
226
+ delete wallet.subaddress_index;
227
+ if (fields.wallet_route === null)
228
+ delete wallet.wallet_route;
229
+ if (fields.wallet_slot === null)
230
+ delete wallet.wallet_slot;
231
+ if (fields.wallet_name === null)
232
+ delete wallet.wallet_name;
233
+ await this._persist();
234
+ }
235
+ async haltWallet(primary_address) {
236
+ await this.updateWallet(primary_address, { halted: true });
237
+ }
238
+ async unhaltWallet(primary_address) {
239
+ await this.updateWallet(primary_address, { halted: false });
240
+ }
241
+ async setWalletName(primary_address, name) {
242
+ await this.updateWallet(primary_address, { wallet_name: name ?? null });
243
+ }
244
+ async setWalletSlot(primary_address, slot) {
245
+ await this.updateWallet(primary_address, { wallet_slot: slot ?? null });
246
+ }
247
+ async setWalletRoute(primary_address, route) {
248
+ await this.updateWallet(primary_address, { wallet_route: route ?? null });
249
+ }
250
+ async setSubaddressIndex(primary_address, index) {
251
+ await this.updateWallet(primary_address, {
252
+ subaddress_index: index ?? null,
253
+ });
254
+ }
255
+ /**
256
+ * reread the settings file from disk and replace inmemory state.
257
+ */
258
+ async reload() {
259
+ const settings = await openScanSettingsFile(this._scan_settings_path);
260
+ if (settings) {
261
+ ScanSettingsOpened._validateLogOptions(settings.logs_include, settings.logs_exclude);
262
+ this._settings = settings;
263
+ }
264
+ }
265
+ /**
266
+ * validate that all entries in logs_include and logs_exclude
267
+ * are valid function names from LOGGING_FUNCTIONS.
268
+ * throws if any entry is invalid.
269
+ */
270
+ static _validateLogOptions(logs_include, logs_exclude) {
271
+ const valid = new Set(LOGGING_FUNCTIONS);
272
+ const invalid = [];
273
+ for (const arr of [logs_include, logs_exclude]) {
274
+ if (!arr)
275
+ continue;
276
+ for (const item of arr) {
277
+ if (!valid.has(item)) {
278
+ invalid.push(item);
279
+ }
280
+ }
281
+ }
282
+ if (invalid.length > 0) {
283
+ throw new Error(`invalid log function(s): ${invalid.join(", ")}. ` +
284
+ `valid options are: ${[...valid].join(", ")}`);
285
+ }
286
+ }
287
+ _settings;
288
+ constructor(settings, _scan_settings_path, _pathPrefix) {
289
+ this._scan_settings_path = _scan_settings_path;
290
+ this._pathPrefix = _pathPrefix;
291
+ this._settings = settings;
292
+ }
293
+ /**
294
+ * write current in memory state to disk.
295
+ */
296
+ async _persist() {
297
+ await writeScanSettings(this._settings, this._scan_settings_path);
298
+ }
299
+ }
@@ -8,7 +8,7 @@ import { monero_wallet_api_wasm } from "../wasm-processing/wasmFile";
8
8
  import { WasmProcessor } from "../wasm-processing/wasmProcessor";
9
9
  import { LOCAL_NODE_DEFAULT_URL, } from "../node-interaction/nodeUrl";
10
10
  import { get_block_headers_range, get_info, } from "../api";
11
- import { readWalletFromScanSettings } from "../scanning-syncing/scanSettings";
11
+ import { readWalletFromScanSettings } from "../api";
12
12
  import { sleep } from "../io/sleep";
13
13
  /**
14
14
  * This class is useful to interact with Moneros DaemonRpc binary requests in a convenient way.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spirobel/monero-wallet-api",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "main": "dist/api.js",
5
5
  "module": "dist/api.js",
6
6
  "devDependencies": {