mainnet-js 2.3.15 → 2.3.16

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/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "url": "https://github.com/mainnet-cash/mainnet-js/issues"
10
10
  },
11
11
  "name": "mainnet-js",
12
- "version": "2.3.15",
12
+ "version": "2.3.16",
13
13
  "homepage": "https://mainnet.cash",
14
14
  "module": "dist/module/index.js",
15
15
  "browser": {
package/src/interface.ts CHANGED
@@ -35,11 +35,21 @@ export interface TxI {
35
35
  fee?: number;
36
36
  }
37
37
 
38
- export interface HeaderI {
38
+ export interface HexHeaderI {
39
39
  height: number;
40
40
  hex: string;
41
41
  }
42
42
 
43
+ export interface HeaderI {
44
+ version: number;
45
+ previousBlockHash: string;
46
+ merkleRoot: string;
47
+ timestamp: number;
48
+ bits: number;
49
+ nonce: number;
50
+ height: number;
51
+ }
52
+
43
53
  export interface TokenI {
44
54
  amount: bigint;
45
55
  tokenId: string;
@@ -5,7 +5,7 @@ import {
5
5
  ConnectionStatus,
6
6
  } from "electrum-cash";
7
7
  import { default as NetworkProvider } from "./NetworkProvider.js";
8
- import { HeaderI, TxI, UtxoI, ElectrumBalanceI } from "../interface.js";
8
+ import { HexHeaderI, TxI, UtxoI, ElectrumBalanceI, HeaderI } from "../interface.js";
9
9
  import { Network } from "../interface.js";
10
10
  import { delay } from "../util/delay.js";
11
11
  import { ElectrumRawTransaction, ElectrumUtxo } from "./interface.js";
@@ -13,6 +13,7 @@ import { ElectrumRawTransaction, ElectrumUtxo } from "./interface.js";
13
13
  import { CancelWatchFn } from "../wallet/interface.js";
14
14
  import { getTransactionHash } from "../util/transaction.js";
15
15
  import { Config } from "../config.js";
16
+ import { decodeHeader } from "../util/header.js";
16
17
 
17
18
  export default class ElectrumNetworkProvider implements NetworkProvider {
18
19
  public electrum: ElectrumCluster | ElectrumClient;
@@ -105,6 +106,29 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
105
106
  return result.confirmed + result.unconfirmed;
106
107
  }
107
108
 
109
+ static rawHeaderCache = {};
110
+ async getHeader(height: number, verbose: boolean = false): Promise<HeaderI | HexHeaderI> {
111
+ const key = `header-${this.network}-${height}-${verbose}`;
112
+
113
+ if (Config.UseLocalStorageCache) {
114
+ const cached = localStorage.getItem(key);
115
+ if (cached) {
116
+ return verbose ? decodeHeader(JSON.parse(cached)) : JSON.parse(cached);
117
+ }
118
+ } else {
119
+ ElectrumNetworkProvider.rawTransactionCache[key];
120
+ }
121
+
122
+ const result = await this.performRequest("blockchain.header.get", height) as HexHeaderI;
123
+ if (Config.UseLocalStorageCache) {
124
+ localStorage.setItem(key, JSON.stringify(result));
125
+ } else {
126
+ ElectrumNetworkProvider.rawTransactionCache[key] = result;
127
+ }
128
+
129
+ return verbose ? decodeHeader(result) : result;
130
+ }
131
+
108
132
  async getBlockHeight(): Promise<number> {
109
133
  return ((await this.performRequest("blockchain.headers.get_tip")) as any)
110
134
  .height;
@@ -116,7 +140,7 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
116
140
  verbose: boolean = false,
117
141
  loadInputValues: boolean = false
118
142
  ): Promise<string> {
119
- const key = `${this.network}-${txHash}-${verbose}-${loadInputValues}`;
143
+ const key = `tx-${this.network}-${txHash}-${verbose}-${loadInputValues}`;
120
144
 
121
145
  if (Config.UseLocalStorageCache) {
122
146
  const cached = localStorage.getItem(key);
@@ -317,9 +341,9 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
317
341
  }
318
342
 
319
343
  // Wait for the next block or a block at given blockchain height.
320
- public watchBlocks(callback: (header: HeaderI) => void): CancelWatchFn {
344
+ public watchBlocks(callback: (header: HexHeaderI) => void): CancelWatchFn {
321
345
  let acknowledged = false;
322
- const waitForBlockCallback = (_header: HeaderI | HeaderI[]) => {
346
+ const waitForBlockCallback = (_header: HexHeaderI | HexHeaderI[]) => {
323
347
  if (!acknowledged) {
324
348
  acknowledged = true;
325
349
  return;
@@ -336,7 +360,7 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
336
360
  }
337
361
 
338
362
  // Wait for the next block or a block at given blockchain height.
339
- public async waitForBlock(height?: number): Promise<HeaderI> {
363
+ public async waitForBlock(height?: number): Promise<HexHeaderI> {
340
364
  return new Promise(async (resolve) => {
341
365
  const cancelWatch = this.watchBlocks(async (header) => {
342
366
  if (height === undefined || header.height >= height!) {
@@ -348,13 +372,13 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
348
372
  }
349
373
 
350
374
  // subscribe to notifications sent when new block is found, the block header is sent to callback
351
- async subscribeToHeaders(callback: (header: HeaderI) => void): Promise<void> {
375
+ async subscribeToHeaders(callback: (header: HexHeaderI) => void): Promise<void> {
352
376
  await this.subscribeRequest("blockchain.headers.subscribe", callback);
353
377
  }
354
378
 
355
379
  // unsubscribe to notifications sent when new block is found
356
380
  async unsubscribeFromHeaders(
357
- callback: (header: HeaderI) => void
381
+ callback: (header: HexHeaderI) => void
358
382
  ): Promise<void> {
359
383
  await this.unsubscribeRequest("blockchain.headers.subscribe", callback);
360
384
  }
@@ -1,4 +1,4 @@
1
- import { TxI, UtxoI, Network, HeaderI } from "../interface.js";
1
+ import { TxI, UtxoI, Network, HexHeaderI, HeaderI } from "../interface.js";
2
2
 
3
3
  export default interface NetworkProvider {
4
4
  /**
@@ -20,6 +20,12 @@ export default interface NetworkProvider {
20
20
  */
21
21
  getBalance(cashaddr: string): Promise<number>;
22
22
 
23
+ /**
24
+ * @returns The block header fetched at blockheight @param height.
25
+ * @param verbose steers the response type. If true, a verbose response is returned.
26
+ */
27
+ getHeader(height: number, verbose: boolean): Promise<HeaderI | HexHeaderI>;
28
+
23
29
  /**
24
30
  * @returns The current block height.
25
31
  */
@@ -72,7 +78,7 @@ export default interface NetworkProvider {
72
78
  * @param height If specified, waits for blockchain to reach this height.
73
79
  * @returns Block header.
74
80
  */
75
- waitForBlock(height?: number): Promise<HeaderI>;
81
+ waitForBlock(height?: number): Promise<HexHeaderI>;
76
82
 
77
83
  /**
78
84
  * Subscribe to the address change events
@@ -0,0 +1,28 @@
1
+ import { HeaderI, HexHeaderI } from "../interface";
2
+ import { disconnectProviders, initProviders } from "../network";
3
+ import { Wallet } from "../wallet/Wif";
4
+
5
+ beforeAll(async () => {
6
+ await initProviders();
7
+ });
8
+ afterAll(async () => {
9
+ await disconnectProviders();
10
+ });
11
+
12
+ describe('header tests', () => {
13
+ it('decodeHeader', async () => {
14
+ const wallet = await Wallet.newRandom();
15
+ const hexHeader = await wallet.provider!.getHeader(854724) as HexHeaderI;
16
+ expect(hexHeader.height).toBe(854724);
17
+ expect(hexHeader.hex).toBe("0080c4339674a81d4e35a5b590b15a6b69f93b7b22bd14845b3517000000000000000000128a8b776c82fda87f60c6fdb0de26f021cdf39ffd835dc309eb1fc6bbfaac343e2f96662d5202184db2428f");
18
+
19
+ const header = await wallet.provider!.getHeader(854724, true) as HeaderI;
20
+ expect(header.version).toBe(868515840);
21
+ expect(header.previousBlockHash).toBe("00000000000000000017355b8414bd227b3bf9696b5ab190b5a5354e1da87496");
22
+ expect(header.merkleRoot).toBe("34acfabbc61feb09c35d83fd9ff3cd21f026deb0fdc6607fa8fd826c778b8a12");
23
+ expect(header.timestamp).toBe(1721118526);
24
+ expect(header.bits).toBe(402805293);
25
+ expect(header.nonce).toBe(2403512909);
26
+ expect(header.height).toBe(854724);
27
+ });
28
+ });
@@ -0,0 +1,16 @@
1
+ import { HeaderI, HexHeaderI } from "../interface";
2
+
3
+ export const decodeHeader = (hexHeader: HexHeaderI): HeaderI => {
4
+ const result = {} as HeaderI;
5
+
6
+ const header = Buffer.from(hexHeader.hex, "hex");
7
+ result.version = header.readUInt32LE(0);
8
+ result.previousBlockHash = header.subarray(4, 36).reverse().toString("hex");
9
+ result.merkleRoot = header.subarray(36, 68).reverse().toString("hex");
10
+ result.timestamp = header.readUInt32LE(68);
11
+ result.bits = header.readUInt32LE(72);
12
+ result.nonce = header.readUInt32LE(76);
13
+ result.height = hexHeader.height;
14
+
15
+ return result;
16
+ }
package/src/util/index.ts CHANGED
@@ -34,3 +34,4 @@ export {
34
34
  balanceResponseFromSatoshi,
35
35
  } from "./balanceObjectFromSatoshi.js";
36
36
  export * from "./sumUtxoValue.js";
37
+ export { decodeHeader } from "./header.js";
package/src/wallet/Wif.ts CHANGED
@@ -25,7 +25,7 @@ import {
25
25
  import { mnemonicToSeedSync, generateMnemonic } from "@scure/bip39";
26
26
  import { NetworkType, prefixFromNetworkMap, UnitEnum } from "../enum.js";
27
27
 
28
- import { Network, HeaderI, TxI, NFTCapability } from "../interface.js";
28
+ import { Network, HexHeaderI, TxI, NFTCapability } from "../interface.js";
29
29
 
30
30
  import { networkPrefixMap } from "../enum.js";
31
31
  import { PrivateKeyI, UtxoI } from "../interface.js";
@@ -1396,7 +1396,7 @@ export class Wallet extends BaseWallet {
1396
1396
  *
1397
1397
  * @returns a function which will cancel watching upon evaluation
1398
1398
  */
1399
- public watchBlocks(callback: (header: HeaderI) => void): CancelWatchFn {
1399
+ public watchBlocks(callback: (header: HexHeaderI) => void): CancelWatchFn {
1400
1400
  return (this.provider! as ElectrumNetworkProvider).watchBlocks(callback);
1401
1401
  }
1402
1402
 
@@ -1406,7 +1406,7 @@ export class Wallet extends BaseWallet {
1406
1406
  * @param height if specified waits for this exact blockchain height, otherwise resolves with the next block
1407
1407
  *
1408
1408
  */
1409
- public async waitForBlock(height?: number): Promise<HeaderI> {
1409
+ public async waitForBlock(height?: number): Promise<HexHeaderI> {
1410
1410
  return (this.provider! as ElectrumNetworkProvider).waitForBlock(height);
1411
1411
  }
1412
1412
  //#endregion Funds