mainnet-js 2.6.7 → 2.7.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 (98) hide show
  1. package/dist/index.html +1 -1
  2. package/dist/{mainnet-2.6.7.js → mainnet-2.7.0.js} +446 -156
  3. package/dist/module/cli.js +0 -4
  4. package/dist/module/cli.js.map +1 -1
  5. package/dist/module/index.d.ts +1 -3
  6. package/dist/module/index.d.ts.map +1 -1
  7. package/dist/module/index.js +1 -3
  8. package/dist/module/index.js.map +1 -1
  9. package/dist/module/network/ElectrumNetworkProvider.d.ts +21 -27
  10. package/dist/module/network/ElectrumNetworkProvider.d.ts.map +1 -1
  11. package/dist/module/network/ElectrumNetworkProvider.js +92 -102
  12. package/dist/module/network/ElectrumNetworkProvider.js.map +1 -1
  13. package/dist/module/network/NetworkProvider.d.ts +9 -22
  14. package/dist/module/network/NetworkProvider.d.ts.map +1 -1
  15. package/dist/module/network/constant.d.ts +0 -21
  16. package/dist/module/network/constant.d.ts.map +1 -1
  17. package/dist/module/network/constant.js +0 -21
  18. package/dist/module/network/constant.js.map +1 -1
  19. package/dist/module/network/default.d.ts +2 -2
  20. package/dist/module/network/default.d.ts.map +1 -1
  21. package/dist/module/network/default.js +15 -45
  22. package/dist/module/network/default.js.map +1 -1
  23. package/dist/module/network/interface.d.ts +2 -8
  24. package/dist/module/network/interface.d.ts.map +1 -1
  25. package/dist/module/network/util.d.ts.map +1 -1
  26. package/dist/module/network/util.js +4 -5
  27. package/dist/module/network/util.js.map +1 -1
  28. package/dist/module/rate/ExchangeRate.js +2 -1
  29. package/dist/module/rate/ExchangeRate.js.map +1 -1
  30. package/dist/module/transaction/Wif.d.ts.map +1 -1
  31. package/dist/module/transaction/Wif.js +1 -1
  32. package/dist/module/transaction/Wif.js.map +1 -1
  33. package/dist/module/wallet/Base.d.ts +282 -88
  34. package/dist/module/wallet/Base.d.ts.map +1 -1
  35. package/dist/module/wallet/Base.js +1058 -215
  36. package/dist/module/wallet/Base.js.map +1 -1
  37. package/dist/module/wallet/Util.d.ts +7 -54
  38. package/dist/module/wallet/Util.d.ts.map +1 -1
  39. package/dist/module/wallet/Util.js +12 -79
  40. package/dist/module/wallet/Util.js.map +1 -1
  41. package/dist/module/wallet/Wif.d.ts +46 -251
  42. package/dist/module/wallet/Wif.d.ts.map +1 -1
  43. package/dist/module/wallet/Wif.js +126 -1026
  44. package/dist/module/wallet/Wif.js.map +1 -1
  45. package/dist/module/wallet/createWallet.d.ts +2 -1
  46. package/dist/module/wallet/createWallet.d.ts.map +1 -1
  47. package/dist/module/wallet/createWallet.js +2 -3
  48. package/dist/module/wallet/createWallet.js.map +1 -1
  49. package/dist/module/wallet/interface.d.ts +2 -4
  50. package/dist/module/wallet/interface.d.ts.map +1 -1
  51. package/dist/tsconfig.tsbuildinfo +1 -1
  52. package/package.json +6 -12
  53. package/src/cli.ts +0 -4
  54. package/src/index.ts +1 -5
  55. package/src/network/ElectrumNetworkProvider.ts +133 -188
  56. package/src/network/NetworkProvider.ts +9 -30
  57. package/src/network/Rpc.test.ts +14 -5
  58. package/src/network/constant.ts +0 -23
  59. package/src/network/default.ts +26 -66
  60. package/src/network/electrum.test.ts +2 -4
  61. package/src/network/interface.ts +2 -9
  62. package/src/network/util.ts +6 -7
  63. package/src/rate/ExchangeRate.test.ts +1 -1
  64. package/src/rate/ExchangeRate.ts +2 -1
  65. package/{polyfill/json.js → src/test/json.test.ts} +7 -1
  66. package/src/transaction/Wif.ts +2 -1
  67. package/src/wallet/Base.ts +1520 -273
  68. package/src/wallet/Cashtokens.test.headless.js +1 -1
  69. package/src/wallet/Cashtokens.test.ts +7 -8
  70. package/src/wallet/Util.ts +20 -102
  71. package/src/wallet/Wif.bip39.test.ts +3 -3
  72. package/src/wallet/Wif.test.ts +31 -25
  73. package/src/wallet/Wif.ts +174 -1493
  74. package/src/wallet/Wif.watchOnly.test.ts +5 -5
  75. package/src/wallet/createWallet.ts +11 -10
  76. package/src/wallet/interface.ts +3 -4
  77. package/webpack.config.cjs +4 -55
  78. package/dist/module/qr/Qr.d.ts +0 -9
  79. package/dist/module/qr/Qr.d.ts.map +0 -1
  80. package/dist/module/qr/Qr.js +0 -22
  81. package/dist/module/qr/Qr.js.map +0 -1
  82. package/dist/module/qr/interface.d.ts +0 -6
  83. package/dist/module/qr/interface.d.ts.map +0 -1
  84. package/dist/module/qr/interface.js +0 -2
  85. package/dist/module/qr/interface.js.map +0 -1
  86. package/dist/module/util/eventsource.d.ts +0 -3
  87. package/dist/module/util/eventsource.d.ts.map +0 -1
  88. package/dist/module/util/eventsource.js +0 -11
  89. package/dist/module/util/eventsource.js.map +0 -1
  90. package/polyfill/README.md +0 -1
  91. package/polyfill/eventsource.js +0 -6
  92. package/polyfill/support/types.js +0 -286
  93. package/polyfill/util.cjs +0 -249
  94. package/src/network/default.test.ts +0 -37
  95. package/src/qr/Qr.test.ts +0 -14
  96. package/src/qr/Qr.ts +0 -24
  97. package/src/qr/interface.ts +0 -5
  98. package/src/util/eventsource.ts +0 -12
@@ -1,9 +1,10 @@
1
1
  import {
2
- ElectrumCluster,
3
2
  ElectrumClient,
4
3
  RequestResponse,
4
+ ElectrumClientEvents,
5
+ RPCNotification,
5
6
  ConnectionStatus,
6
- } from "electrum-cash";
7
+ } from "@electrum-cash/network";
7
8
  import { default as NetworkProvider } from "./NetworkProvider.js";
8
9
  import {
9
10
  HexHeaderI,
@@ -16,7 +17,7 @@ import { Network } from "../interface.js";
16
17
  import { delay } from "../util/delay.js";
17
18
  import { ElectrumRawTransaction, ElectrumUtxo } from "./interface.js";
18
19
 
19
- import { CancelWatchFn } from "../wallet/interface.js";
20
+ import { CancelFn } from "../wallet/interface.js";
20
21
  import { getTransactionHash } from "../util/transaction.js";
21
22
  import { Config } from "../config.js";
22
23
  import { decodeHeader } from "../util/header.js";
@@ -26,10 +27,12 @@ import { WebStorageCache } from "../cache/WebStorageCache.js";
26
27
  import { MemoryCache } from "../cache/MemoryCache.js";
27
28
 
28
29
  export default class ElectrumNetworkProvider implements NetworkProvider {
29
- public electrum: ElectrumCluster | ElectrumClient;
30
+ public electrum: ElectrumClient<ElectrumClientEvents>;
30
31
  public subscriptions: number = 0;
31
32
  public version;
32
33
  private connectPromise;
34
+ private subscribedToHeaders: boolean = false;
35
+ private subscriptionMap: Record<string, number> = {};
33
36
 
34
37
  private _cache: CacheProvider | undefined;
35
38
 
@@ -65,20 +68,16 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
65
68
  }
66
69
 
67
70
  constructor(
68
- electrum: ElectrumCluster | ElectrumClient,
71
+ electrum: ElectrumClient<ElectrumClientEvents>,
69
72
  public network: Network = Network.MAINNET,
70
73
  private manualConnectionManagement?: boolean
71
74
  ) {
72
75
  if (electrum) {
73
76
  this.electrum = electrum;
74
77
  this.connectPromise = this.getConnectPromise();
75
- if (this.electrum instanceof ElectrumCluster) {
76
- this.version = (this.electrum as ElectrumCluster).version;
77
- } else {
78
- this.version = (this.electrum as ElectrumClient).connection.version;
79
- }
78
+ this.version = this.electrum.version;
80
79
  } else {
81
- throw new Error(`A electrum-cash cluster or client is required.`);
80
+ throw new Error(`A electrum-cash client is required.`);
82
81
  }
83
82
  }
84
83
 
@@ -89,40 +88,18 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
89
88
  await Promise.race([
90
89
  new Promise(async (resolve) => {
91
90
  this.connectPromise = undefined;
92
-
93
- if (this.electrum instanceof ElectrumCluster) {
94
- try {
95
- await this.connectCluster();
96
- } catch (e) {
97
- console.warn(
98
- `Unable to connect to one or more electrum-cash hosts: ${JSON.stringify(
99
- e
100
- )}`
101
- );
102
- }
103
- resolve(await this.readyCluster());
104
- } else {
105
- resolve(await this.connectClient());
106
- }
91
+ resolve(await this.connectClient());
107
92
  }),
108
- // new Promise(
109
- // (_resolve, reject) =>
110
- // (timeoutHandle = setTimeout(() => {
111
- // reject(
112
- // new Error(`Timeout connecting to electrum network: ${this.network}`)
113
- // );
114
- // }, _timeout))
115
- // ),
116
93
  ]);
117
94
  clearTimeout(timeoutHandle);
118
95
  }
119
96
 
120
97
  async getUtxos(cashaddr: string): Promise<UtxoI[]> {
121
- const result = (await this.performRequest(
98
+ const result = await this.performRequest<ElectrumUtxo[]>(
122
99
  "blockchain.address.listunspent",
123
100
  cashaddr,
124
101
  "include_tokens"
125
- )) as ElectrumUtxo[];
102
+ );
126
103
  return result.map((utxo) => ({
127
104
  txid: utxo.tx_hash,
128
105
  vout: utxo.tx_pos,
@@ -140,10 +117,10 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
140
117
  }
141
118
 
142
119
  async getBalance(cashaddr: string): Promise<number> {
143
- const result = (await this.performRequest(
120
+ const result = await this.performRequest<ElectrumBalanceI>(
144
121
  "blockchain.address.get_balance",
145
122
  cashaddr
146
- )) as ElectrumBalanceI;
123
+ );
147
124
 
148
125
  return result.confirmed + result.unconfirmed;
149
126
  }
@@ -161,10 +138,10 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
161
138
  }
162
139
  }
163
140
 
164
- const result = (await this.performRequest(
141
+ const result = await this.performRequest<HexHeaderI>(
165
142
  "blockchain.header.get",
166
143
  height
167
- )) as HexHeaderI;
144
+ );
168
145
  if (this.cache) {
169
146
  await this.cache.setItem(key, JSON.stringify(result));
170
147
  }
@@ -173,7 +150,7 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
173
150
  }
174
151
 
175
152
  async getBlockHeight(): Promise<number> {
176
- return ((await this.performRequest("blockchain.headers.get_tip")) as any)
153
+ return (await this.performRequest<HexHeaderI>("blockchain.headers.get_tip"))
177
154
  .height;
178
155
  }
179
156
 
@@ -262,17 +239,22 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
262
239
  this.performRequest("blockchain.transaction.broadcast", txHex);
263
240
  resolve(txHash);
264
241
  } else {
242
+ let cancel: CancelFn;
243
+
265
244
  const waitForTransactionCallback = async (data) => {
266
- if (data && data[0] === txHash) {
267
- this.unsubscribeFromTransaction(txHash, waitForTransactionCallback);
245
+ if (data && data[0] === txHash && data[1] !== null) {
246
+ await cancel?.();
268
247
  resolve(txHash);
269
248
  }
270
249
  };
271
- this.subscribeToTransaction(txHash, waitForTransactionCallback);
250
+ cancel = await this.subscribeToTransaction(
251
+ txHash,
252
+ waitForTransactionCallback
253
+ );
272
254
 
273
255
  this.performRequest("blockchain.transaction.broadcast", txHex).catch(
274
- (error) => {
275
- this.unsubscribeFromTransaction(txHash, waitForTransactionCallback);
256
+ async (error) => {
257
+ await cancel?.();
276
258
  reject(error);
277
259
  }
278
260
  );
@@ -286,12 +268,12 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
286
268
  fromHeight: number = 0,
287
269
  toHeight: number = -1
288
270
  ): Promise<TxI[]> {
289
- const result = (await this.performRequest(
271
+ const result = await this.performRequest<TxI[]>(
290
272
  "blockchain.address.get_history",
291
273
  cashaddr,
292
274
  fromHeight,
293
275
  toHeight
294
- )) as TxI[];
276
+ );
295
277
 
296
278
  return result;
297
279
  }
@@ -303,10 +285,10 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
303
285
  return result;
304
286
  }
305
287
 
306
- public watchAddressStatus(
288
+ public async watchAddressStatus(
307
289
  cashaddr: string,
308
290
  callback: (status: string) => void
309
- ): CancelWatchFn {
291
+ ): Promise<CancelFn> {
310
292
  const watchAddressStatusCallback = async (data) => {
311
293
  // subscription acknowledgement is the latest known status or null if no status is known
312
294
  // status is an array: [ cashaddr, statusHash ]
@@ -321,17 +303,13 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
321
303
  }
322
304
  };
323
305
 
324
- this.subscribeToAddress(cashaddr, watchAddressStatusCallback);
325
-
326
- return async () => {
327
- await this.unsubscribeFromAddress(cashaddr, watchAddressStatusCallback);
328
- };
306
+ return this.subscribeToAddress(cashaddr, watchAddressStatusCallback);
329
307
  }
330
308
 
331
- public watchAddress(
309
+ public async watchAddress(
332
310
  cashaddr: string,
333
311
  callback: (txHash: string) => void
334
- ): CancelWatchFn {
312
+ ): Promise<CancelFn> {
335
313
  const historyMap: { [txid: string]: boolean } = {};
336
314
 
337
315
  this.getHistory(cashaddr).then((history) =>
@@ -359,20 +337,20 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
359
337
  return this.watchAddressStatus(cashaddr, watchAddressStatusCallback);
360
338
  }
361
339
 
362
- public watchAddressTransactions(
340
+ public async watchAddressTransactions(
363
341
  cashaddr: string,
364
342
  callback: (tx: ElectrumRawTransaction) => void
365
- ): CancelWatchFn {
343
+ ): Promise<CancelFn> {
366
344
  return this.watchAddress(cashaddr, async (txHash: string) => {
367
345
  const tx = await this.getRawTransactionObject(txHash);
368
346
  callback(tx);
369
347
  });
370
348
  }
371
349
 
372
- public watchAddressTokenTransactions(
350
+ public async watchAddressTokenTransactions(
373
351
  cashaddr: string,
374
352
  callback: (tx: ElectrumRawTransaction) => void
375
- ): CancelWatchFn {
353
+ ): Promise<CancelFn> {
376
354
  return this.watchAddress(cashaddr, async (txHash: string) => {
377
355
  const tx = await this.getRawTransactionObject(txHash, true);
378
356
  if (
@@ -385,10 +363,10 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
385
363
  }
386
364
 
387
365
  // watch for block headers and block height, if `skipCurrentHeight` is set, the notification about current block will not arrive
388
- public watchBlocks(
366
+ public async watchBlocks(
389
367
  callback: (header: HexHeaderI) => void,
390
368
  skipCurrentHeight: boolean = true
391
- ): CancelWatchFn {
369
+ ): Promise<CancelFn> {
392
370
  let acknowledged = !skipCurrentHeight;
393
371
  const waitForBlockCallback = (_header: HexHeaderI | HexHeaderI[]) => {
394
372
  if (!acknowledged) {
@@ -399,20 +377,27 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
399
377
  _header = _header instanceof Array ? _header[0] : _header;
400
378
  callback(_header);
401
379
  };
402
- this.subscribeToHeaders(waitForBlockCallback);
403
-
404
- return async () => {
405
- this.unsubscribeFromHeaders(waitForBlockCallback);
406
- };
380
+ return this.subscribeToHeaders(waitForBlockCallback);
407
381
  }
408
382
 
409
383
  // Wait for the next block or a block at given blockchain height.
410
384
  public async waitForBlock(height?: number): Promise<HexHeaderI> {
411
385
  return new Promise(async (resolve) => {
412
- const cancelWatch = this.watchBlocks(async (header) => {
413
- if (height === undefined || header.height >= height!) {
414
- await cancelWatch();
386
+ let cancelWatch: CancelFn;
387
+ if (this.electrum.chainHeight && !height) {
388
+ height = this.electrum.chainHeight + 1;
389
+ }
390
+
391
+ cancelWatch = await this.watchBlocks(async (header) => {
392
+ if (!height) {
393
+ height = header.height + 1;
394
+ return;
395
+ }
396
+
397
+ if (header.height >= height) {
398
+ await cancelWatch?.();
415
399
  resolve(header);
400
+ return;
416
401
  }
417
402
  });
418
403
  });
@@ -421,87 +406,36 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
421
406
  // subscribe to notifications sent when new block is found, the block header is sent to callback
422
407
  async subscribeToHeaders(
423
408
  callback: (header: HexHeaderI) => void
424
- ): Promise<void> {
425
- await this.subscribeRequest("blockchain.headers.subscribe", callback);
426
- }
427
-
428
- // unsubscribe to notifications sent when new block is found
429
- async unsubscribeFromHeaders(
430
- callback: (header: HexHeaderI) => void
431
- ): Promise<void> {
432
- await this.unsubscribeRequest("blockchain.headers.subscribe", callback);
409
+ ): Promise<CancelFn> {
410
+ return this.subscribeRequest("blockchain.headers.subscribe", callback);
433
411
  }
434
412
 
435
413
  async subscribeToAddress(
436
414
  cashaddr: string,
437
415
  callback: (data: any) => void
438
- ): Promise<void> {
439
- await this.subscribeRequest(
416
+ ): Promise<CancelFn> {
417
+ return this.subscribeRequest(
440
418
  "blockchain.address.subscribe",
441
419
  callback,
442
420
  cashaddr
443
421
  );
444
422
  }
445
423
 
446
- async unsubscribeFromAddress(
447
- cashaddr: string,
448
- callback: (data: any) => void
449
- ): Promise<void> {
450
- await this.unsubscribeRequest(
451
- "blockchain.address.subscribe",
452
- callback,
453
- cashaddr
454
- );
455
- }
456
-
457
- async subscribeToAddressTransactions(
458
- cashaddr: string,
459
- callback: (data: any) => void
460
- ): Promise<void> {
461
- await this.subscribeRequest(
462
- "blockchain.address.transactions.subscribe",
463
- callback,
464
- cashaddr
465
- );
466
- }
467
-
468
- async unsubscribeFromAddressTransactions(
469
- cashaddr: string,
470
- callback: (data: any) => void
471
- ): Promise<void> {
472
- await this.unsubscribeRequest(
473
- "blockchain.address.transactions.subscribe",
474
- callback,
475
- cashaddr
476
- );
477
- }
478
-
479
424
  async subscribeToTransaction(
480
425
  txHash: string,
481
426
  callback: (data: any) => void
482
- ): Promise<void> {
483
- await this.subscribeRequest(
427
+ ): Promise<CancelFn> {
428
+ return this.subscribeRequest(
484
429
  "blockchain.transaction.subscribe",
485
430
  callback,
486
431
  txHash
487
432
  );
488
433
  }
489
434
 
490
- async unsubscribeFromTransaction(
491
- txHash: string,
492
- callback: (data: any) => void
493
- ): Promise<void> {
494
- await this.unsubscribeRequest(
495
- "blockchain.transaction.subscribe",
496
- callback,
497
- txHash
498
- );
499
- }
500
-
501
- private async performRequest(
435
+ private async performRequest<T>(
502
436
  name: string,
503
437
  ...parameters: (string | number | boolean)[]
504
- ): Promise<RequestResponse> {
438
+ ): Promise<T> {
505
439
  await this.ready();
506
440
 
507
441
  const requestTimeout = new Promise(function (_resolve, reject) {
@@ -518,7 +452,7 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
518
452
  .then((value) => {
519
453
  if (value instanceof Error) throw value;
520
454
  let result = value as RequestResponse;
521
- return result;
455
+ return result as T;
522
456
  })
523
457
  .catch(async () => {
524
458
  // console.warn(
@@ -528,7 +462,7 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
528
462
  .then((value) => {
529
463
  if (value instanceof Error) throw value;
530
464
  let result = value as RequestResponse;
531
- return result;
465
+ return result as T;
532
466
  })
533
467
  .catch(function (e) {
534
468
  throw e;
@@ -536,74 +470,100 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
536
470
  });
537
471
  }
538
472
 
539
- private async subscribeRequest(
473
+ private async trackSubscription(
540
474
  methodName: string,
541
- callback: (data) => void,
542
475
  ...parameters: (string | number | boolean)[]
543
- ): Promise<true> {
544
- await this.ready();
545
-
546
- const result = await this.electrum.subscribe(
547
- callback,
548
- methodName,
549
- ...parameters
550
- );
476
+ ): Promise<void> {
477
+ const key = `${methodName}-${this.network}-${JSON.stringify(parameters)}`;
478
+ if (this.subscriptionMap[key]) {
479
+ this.subscriptionMap[key]++;
480
+ } else {
481
+ this.subscriptionMap[key] = 1;
482
+ }
551
483
 
552
- this.subscriptions++;
484
+ await this.electrum.subscribe(methodName, ...parameters);
485
+ }
553
486
 
554
- return result;
487
+ private async untrackSubscription(
488
+ methodName: string,
489
+ ...parameters: (string | number | boolean)[]
490
+ ): Promise<void> {
491
+ const key = `${methodName}-${this.network}-${JSON.stringify(parameters)}`;
492
+ if (this.subscriptionMap[key]) {
493
+ this.subscriptionMap[key]--;
494
+ if (this.subscriptionMap[key] <= 0) {
495
+ // only really unsubscribe if there are no more subscriptions for this `key`
496
+ delete this.subscriptionMap[key];
497
+
498
+ try {
499
+ await this.electrum.unsubscribe(methodName, ...parameters);
500
+ } catch {}
501
+ }
502
+ }
555
503
  }
556
504
 
557
- private async unsubscribeRequest(
505
+ public async subscribeRequest(
558
506
  methodName: string,
559
507
  callback: (data) => void,
560
508
  ...parameters: (string | number | boolean)[]
561
- ): Promise<true> {
509
+ ): Promise<CancelFn> {
562
510
  await this.ready();
563
511
 
564
- const result = this.electrum.unsubscribe(
565
- callback,
566
- methodName,
567
- ...parameters
568
- );
512
+ const handler = (data: RPCNotification) => {
513
+ if (data.method === methodName) {
514
+ callback(data.params);
515
+ }
516
+ };
569
517
 
570
- this.subscriptions--;
518
+ this.electrum.on("notification", handler);
571
519
 
572
- return result;
520
+ // safeguard against multiple subscriptions to headers
521
+ if (methodName === "blockhain.headers.subscribe") {
522
+ if (!this.subscribedToHeaders) {
523
+ this.subscribedToHeaders = true;
524
+
525
+ await this.trackSubscription(methodName, ...parameters);
526
+ }
527
+ } else {
528
+ await this.trackSubscription(methodName, ...parameters);
529
+ }
530
+
531
+ this.subscriptions++;
532
+
533
+ return async () => {
534
+ this.electrum.off("notification", handler);
535
+ this.subscriptions--;
536
+
537
+ // there are no blockchain.headers.unsubscribe method, so let's safeguard against it
538
+ if (methodName !== "blockchain.headers.subscribe") {
539
+ await this.untrackSubscription(methodName, ...parameters);
540
+ }
541
+ };
573
542
  }
574
543
 
575
544
  async ready(): Promise<boolean | unknown> {
576
- return (await this.connect()) as void[];
545
+ return this.connect();
577
546
  }
578
547
 
579
- async connect(): Promise<void[]> {
548
+ async connect(): Promise<void> {
580
549
  await this.cache?.init();
581
550
  return await this.connectPromise;
582
551
  }
583
552
 
584
- disconnect(): Promise<boolean[]> {
553
+ disconnect(): Promise<boolean> {
585
554
  if (this.subscriptions > 0) {
586
555
  // console.warn(
587
556
  // `Trying to disconnect a network provider with ${this.subscriptions} active subscriptions. This is in most cases a bad idea.`
588
557
  // );
589
558
  }
590
- return this.isElectrumClient()
591
- ? this.disconnectClient()
592
- : this.disconnectCluster();
593
- }
594
-
595
- isElectrumClient(): boolean {
596
- return this.electrum.hasOwnProperty("connection");
559
+ return this.disconnectClient();
597
560
  }
598
561
 
599
562
  async readyClient(timeout?: number): Promise<boolean | unknown> {
600
563
  timeout = typeof timeout !== "undefined" ? timeout : 3000;
601
564
 
602
565
  let connectPromise = async () => {
603
- while (
604
- (this.electrum as ElectrumClient).connection.status !==
605
- ConnectionStatus.CONNECTED
606
- ) {
566
+ while (this.electrum.status !== ConnectionStatus.CONNECTED) {
607
567
  await delay(100);
608
568
  }
609
569
  return true;
@@ -611,37 +571,22 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
611
571
  return connectPromise;
612
572
  }
613
573
 
614
- async readyCluster(timeout?: number): Promise<boolean> {
615
- timeout;
616
- return (this.electrum as ElectrumCluster).ready();
617
- }
618
-
619
- async connectCluster(): Promise<void[]> {
620
- return (this.electrum as ElectrumCluster).startup();
621
- }
622
-
623
- async connectClient(): Promise<void[]> {
574
+ async connectClient(): Promise<void> {
624
575
  let connectionPromise = async () => {
625
576
  try {
626
- return await (this.electrum as ElectrumClient).connect();
577
+ return await this.electrum.connect();
627
578
  } catch (e) {
628
579
  console.warn(
629
- `Warning: Failed to connect to client on ${this.network} at ${
630
- (this.electrum as ElectrumClient).connection.host
631
- }.`,
580
+ `Warning: Failed to connect to client on ${this.network} at ${this.electrum.hostIdentifier}.`,
632
581
  e
633
582
  );
634
583
  return;
635
584
  }
636
585
  };
637
- return [await connectionPromise()];
638
- }
639
-
640
- async disconnectCluster(): Promise<boolean[]> {
641
- return (this.electrum as ElectrumCluster).shutdown();
586
+ return connectionPromise();
642
587
  }
643
588
 
644
- async disconnectClient(): Promise<boolean[]> {
645
- return [await (this.electrum as ElectrumClient).disconnect(true)];
589
+ async disconnectClient(): Promise<boolean> {
590
+ return this.electrum.disconnect(true, false);
646
591
  }
647
592
  }
@@ -1,4 +1,5 @@
1
1
  import { TxI, UtxoI, Network, HexHeaderI, HeaderI } from "../interface.js";
2
+ import { CancelFn } from "../wallet/interface.js";
2
3
 
3
4
  export default interface NetworkProvider {
4
5
  /**
@@ -93,18 +94,7 @@ export default interface NetworkProvider {
93
94
  subscribeToAddress(
94
95
  cashaddr: string,
95
96
  callback: (data: any) => void
96
- ): Promise<void>;
97
-
98
- /**
99
- * Unsubscribe from the address change events
100
- * @param cashaddr The CashAddress for which we wish to retrieve history.
101
- * @throws {Error} If the unsubscription failed.
102
- * @returns nothing.
103
- */
104
- unsubscribeFromAddress(
105
- cashaddr: string,
106
- callback: (data: any) => void
107
- ): Promise<void>;
97
+ ): Promise<CancelFn>;
108
98
 
109
99
  /**
110
100
  * Subscribe to a transaction in order to receive future notifications if its confirmation status changes.
@@ -115,18 +105,7 @@ export default interface NetworkProvider {
115
105
  subscribeToTransaction(
116
106
  txHash: string,
117
107
  callback: (data: any) => void
118
- ): Promise<void>;
119
-
120
- /**
121
- * Unsubscribe from a transaction, preventing future notifications if its confirmation status changes.
122
- * @param txHash The transaction hash as a hexadecimal string.
123
- * @throws {Error} If the subscription failed.
124
- * @returns nothing.
125
- */
126
- unsubscribeFromTransaction(
127
- txHash: string,
128
- callback: (data: any) => void
129
- ): Promise<void>;
108
+ ): Promise<CancelFn>;
130
109
 
131
110
  /**
132
111
  * Function to wait for connection to be ready
@@ -136,14 +115,14 @@ export default interface NetworkProvider {
136
115
  ready(timeout?: number): Promise<boolean | unknown>;
137
116
 
138
117
  /**
139
- * Function to connect manually if using persistent connections
140
- * @returns array of connection boolean successes, or throws error
118
+ * Function to connect manually if using persistent connection
119
+ * @returns a promise resolving when the connection is established.
141
120
  */
142
- connect(): Promise<void[]>;
121
+ connect(): Promise<void>;
143
122
 
144
123
  /**
145
- * Function to disconnect manually if using persistent connections
146
- * @returns array of connection boolean successes, or throws error
124
+ * Function to disconnect manually if using persistent connection
125
+ * @returns true if successfully disconnected, or false if there was no connection
147
126
  */
148
- disconnect(): Promise<boolean[]>;
127
+ disconnect(): Promise<boolean>;
149
128
  }
@@ -15,11 +15,20 @@ afterAll(async () => {
15
15
  });
16
16
 
17
17
  describe("Rpc tests", () => {
18
+ test("get utxos", async () => {
19
+ const provider = getNetworkProvider(Network.REGTEST);
20
+ expect(
21
+ await provider.getUtxos(
22
+ "bchreg:qpttdv3qg2usm4nm7talhxhl05mlhms3ys43u76rn0"
23
+ )
24
+ ).not.toHaveLength(0);
25
+ });
26
+
18
27
  test("subcribe to address", async () => {
19
28
  const provider = getNetworkProvider(Network.REGTEST);
20
29
  try {
21
30
  await provider.subscribeToAddress(
22
- "bchtest:qzvnjv8xyfkq4uk0xggsfu6uxnray06rcuw7h4zk4u",
31
+ "bchreg:qpttdv3qg2usm4nm7talhxhl05mlhms3ys43u76rn0",
23
32
  async (data) => {
24
33
  expect(data).not.toBe("");
25
34
  }
@@ -36,7 +45,7 @@ describe("Rpc tests", () => {
36
45
 
37
46
  try {
38
47
  await provider.subscribeToAddress(
39
- "bchtest:qzvnjv8xyfkq4uk0xggsfu6uxnray06rcuw7h4zk4u",
48
+ "bchreg:qpttdv3qg2usm4nm7talhxhl05mlhms3ys43u76rn0",
40
49
  async (data) => {
41
50
  // console.log("First", data);
42
51
  expect(data).not.toBe("");
@@ -45,7 +54,7 @@ describe("Rpc tests", () => {
45
54
  );
46
55
 
47
56
  await provider.subscribeToAddress(
48
- "bchtest:qzt6sz836wdwscld0pgq2prcpck2pssmwge9q87pe9",
57
+ "bchreg:qpttdv3qg2usm4nm7talhxhl05mlhms3ys43u76rn0",
49
58
  async (data) => {
50
59
  // console.log("Second", data);
51
60
  expect(data).not.toBe("");
@@ -71,7 +80,7 @@ describe("Rpc tests", () => {
71
80
  });
72
81
  await new Promise((resolve) => setTimeout(resolve, 1000));
73
82
  // we do not trigger the callback upon subscription anymore
74
- expect(result).toBe(false);
83
+ expect(result).toBe(true);
75
84
  });
76
85
 
77
86
  test("Wait for block timeout", async () => {
@@ -118,5 +127,5 @@ describe("Rpc tests", () => {
118
127
 
119
128
  header = await provider.waitForBlock(height + 2);
120
129
  expect(header.height).toBe(height + 2);
121
- });
130
+ }, 20000);
122
131
  });