@hackerhouse/xpub-scan 1.0.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 (83) hide show
  1. package/.claude/settings.local.json +8 -0
  2. package/CONTRIBUTING.md +130 -0
  3. package/LICENSE +23 -0
  4. package/README.md +215 -0
  5. package/__tests__/checkAddresses/checkBitcoinAddressesNegative.test.ts +75 -0
  6. package/__tests__/checkAddresses/checkBitcoinAddressesPositive.test.ts +87 -0
  7. package/__tests__/checkAddresses/checkDogeAddressesPositive.test.ts +43 -0
  8. package/__tests__/checkAddresses/checkLitecoinAddressesNegative.test.ts +75 -0
  9. package/__tests__/checkAddresses/checkLitecoinAddressesPositive.test.ts +87 -0
  10. package/__tests__/checkModels/address.test.ts +183 -0
  11. package/__tests__/checkModels/fakeRawTransactions.json +182 -0
  12. package/__tests__/deriveAddresses/deriveBitcoinAddresses.test.ts +207 -0
  13. package/__tests__/deriveAddresses/deriveBitcoinCashAddresses.test copy.ts +79 -0
  14. package/__tests__/deriveAddresses/deriveDogecoinAddresses.test.ts +43 -0
  15. package/__tests__/deriveAddresses/deriveEthereumAddresses.test.ts +26 -0
  16. package/__tests__/deriveAddresses/deriveLitecoinAddresses.test.ts +110 -0
  17. package/__tests__/helpers.test.ts +274 -0
  18. package/__tests__/test-utils.ts +3 -0
  19. package/babel.config.js +6 -0
  20. package/jest.config.ts +5 -0
  21. package/ledgerhq-xpub-scan-1.0.4.tgz +0 -0
  22. package/lib/actions/checkAddress.d.ts +29 -0
  23. package/lib/actions/checkAddress.js +122 -0
  24. package/lib/actions/checkBalance.d.ts +20 -0
  25. package/lib/actions/checkBalance.js +300 -0
  26. package/lib/actions/deriveAddresses.d.ts +17 -0
  27. package/lib/actions/deriveAddresses.js +239 -0
  28. package/lib/actions/processTransactions.d.ts +29 -0
  29. package/lib/actions/processTransactions.js +289 -0
  30. package/lib/actions/saveAnalysis.d.ts +2 -0
  31. package/lib/actions/saveAnalysis.js +800 -0
  32. package/lib/actions/scanner.d.ts +15 -0
  33. package/lib/actions/scanner.js +152 -0
  34. package/lib/api/customProvider.d.ts +19 -0
  35. package/lib/api/customProvider.js +434 -0
  36. package/lib/api/defaultProvider.d.ts +23 -0
  37. package/lib/api/defaultProvider.js +275 -0
  38. package/lib/comparison/compareOperations.d.ts +13 -0
  39. package/lib/comparison/compareOperations.js +500 -0
  40. package/lib/comparison/diffs.d.ts +18 -0
  41. package/lib/comparison/diffs.js +70 -0
  42. package/lib/configuration/currencies.d.ts +55 -0
  43. package/lib/configuration/currencies.js +72 -0
  44. package/lib/configuration/settings.d.ts +51 -0
  45. package/lib/configuration/settings.js +113 -0
  46. package/lib/display.d.ts +12 -0
  47. package/lib/display.js +251 -0
  48. package/lib/helpers.d.ts +27 -0
  49. package/lib/helpers.js +255 -0
  50. package/lib/input/args.d.ts +6 -0
  51. package/lib/input/args.js +129 -0
  52. package/lib/input/check.d.ts +6 -0
  53. package/lib/input/check.js +217 -0
  54. package/lib/input/importOperations.d.ts +11 -0
  55. package/lib/input/importOperations.js +406 -0
  56. package/lib/models/address.d.ts +40 -0
  57. package/lib/models/address.js +101 -0
  58. package/lib/models/comparison.d.ts +8 -0
  59. package/lib/models/comparison.js +6 -0
  60. package/lib/models/currency.d.ts +11 -0
  61. package/lib/models/currency.js +6 -0
  62. package/lib/models/operation.d.ts +33 -0
  63. package/lib/models/operation.js +80 -0
  64. package/lib/models/ownAddresses.d.ts +11 -0
  65. package/lib/models/ownAddresses.js +31 -0
  66. package/lib/models/scanLimits.d.ts +7 -0
  67. package/lib/models/scanLimits.js +6 -0
  68. package/lib/models/stats.d.ts +7 -0
  69. package/lib/models/stats.js +6 -0
  70. package/lib/models/transaction.d.ts +10 -0
  71. package/lib/models/transaction.js +13 -0
  72. package/lib/scan.d.ts +2 -0
  73. package/lib/scan.js +31 -0
  74. package/lib/templates/logos.base64.d.ts +2 -0
  75. package/lib/templates/logos.base64.js +9 -0
  76. package/lib/templates/report.html.d.ts +1 -0
  77. package/lib/templates/report.html.js +393 -0
  78. package/lib/tsconfig.tsbuildinfo +1 -0
  79. package/lib/types.d.ts +55 -0
  80. package/lib/types.js +2 -0
  81. package/npm-shrinkwrap.json +12323 -0
  82. package/package.json +81 -0
  83. package/sonar-project.properties +15 -0
@@ -0,0 +1,79 @@
1
+ import { configuration } from "../../src/configuration/settings";
2
+ import { currencies, DerivationMode } from "../../src/configuration/currencies";
3
+ import { deriveAddress } from "../../src/actions/deriveAddresses";
4
+
5
+ describe("derive Bitcoin Cash addresses", () => {
6
+ let xpub;
7
+ let derivationMode;
8
+
9
+ describe("derive Bitcoin Cash mainnet addresses", () => {
10
+ beforeEach(() => {
11
+ xpub =
12
+ "xpub6CJgFcZxrd2yjt11C91E4xTb7whLw1amvXzzhhdmfqutTdbT53GS4nbS6pcsPQ2EJyPBxWi7Rvro2pqBVUuKj1BqET1gujWmLE6WJD7pb1o";
13
+ configuration.currency = currencies.bch;
14
+ configuration.currency.network = currencies.bch.network_mainnet;
15
+ });
16
+
17
+ describe("derive Legacy addresses", () => {
18
+ beforeEach(() => {
19
+ derivationMode = DerivationMode.LEGACY;
20
+ });
21
+
22
+ it("derive m/0/0", () => {
23
+ const address = deriveAddress(derivationMode, xpub, 0, 0);
24
+ expect(address).toEqual("195D2Q9NPSpZxkD2gmEtNFzK8s65FS7QZB");
25
+ });
26
+
27
+ it("derive m/0/1", () => {
28
+ const address = deriveAddress(derivationMode, xpub, 0, 1);
29
+ expect(address).toEqual("1Nchm2Yu65gGua1jNF1viaNPYLtjmmgzpe");
30
+ });
31
+
32
+ it("derive m/1/0", () => {
33
+ const address = deriveAddress(derivationMode, xpub, 1, 0);
34
+ expect(address).toEqual("1JJEsMr4dpTtsA9JL8HyQVN2NZ4WsMuoMj");
35
+ });
36
+
37
+ it("derive m/1/1", () => {
38
+ const address = deriveAddress(derivationMode, xpub, 1, 1);
39
+ expect(address).toEqual("1EL7PVjrHMNPpCk47T86URSzVRqccdexVy");
40
+ });
41
+
42
+ it("derive m/1/10000000", () => {
43
+ const address = deriveAddress(derivationMode, xpub, 1, 10000000);
44
+ expect(address).toEqual("1Lutb2GiXzT1VmstpNp89Gdv5xK1WxS7yw");
45
+ });
46
+ });
47
+
48
+ describe("derive SegWit addresses", () => {
49
+ beforeEach(() => {
50
+ derivationMode = DerivationMode.SEGWIT;
51
+ });
52
+
53
+ it("derive m/0/0", () => {
54
+ const address = deriveAddress(derivationMode, xpub, 0, 0);
55
+ expect(address).toEqual("3Hznz37SVW7SCQVexMuHouGxS2JkT5SBcE");
56
+ });
57
+
58
+ it("derive m/0/1", () => {
59
+ const address = deriveAddress(derivationMode, xpub, 0, 1);
60
+ expect(address).toEqual("3H4PXNXFZBMXXtj73a2M4ZnWyKcAFMcw7p");
61
+ });
62
+
63
+ it("derive m/1/0", () => {
64
+ const address = deriveAddress(derivationMode, xpub, 1, 0);
65
+ expect(address).toEqual("3PXDUXZBqN1su1wYeBy1guBkUJVFLzupqP");
66
+ });
67
+
68
+ it("derive m/1/1", () => {
69
+ const address = deriveAddress(derivationMode, xpub, 1, 1);
70
+ expect(address).toEqual("34DmE8fnF6dSHHtY3H2suDB3jDedBMZVMf");
71
+ });
72
+
73
+ it("derive m/1/10000000", () => {
74
+ const address = deriveAddress(derivationMode, xpub, 1, 10000000);
75
+ expect(address).toEqual("3DdXQRrzTndRWyEiR1JRKVCJp7YZsJUwff");
76
+ });
77
+ });
78
+ });
79
+ });
@@ -0,0 +1,43 @@
1
+ import { configuration } from "../../src/configuration/settings";
2
+ import { currencies, DerivationMode } from "../../src/configuration/currencies";
3
+ import { deriveAddress } from "../../src/actions/deriveAddresses";
4
+
5
+ describe("derive Dogecoin addresses", () => {
6
+ let xpub;
7
+ let derivationMode;
8
+
9
+ describe("derive Dogecoin mainnet addresses", () => {
10
+ beforeEach(() => {
11
+ xpub =
12
+ "dgub8rDzyFqzw35B8zSqrW9sHDivXL2YmcGEVKyRMhPh8SoeUmkGozD5YzNyEkSH1T9zhvy9iQzns7igxrhQkg4jETWna4X1AUC4MT3YgHenTMB";
13
+ configuration.currency = currencies.doge;
14
+ configuration.currency.network = currencies.doge.network_mainnet;
15
+ derivationMode = DerivationMode.DOGECOIN;
16
+ });
17
+
18
+ it("derive m/0/0", () => {
19
+ const address = deriveAddress(derivationMode, xpub, 0, 0);
20
+ expect(address).toEqual("DNoFXKQVgbYU5pnpJEoiJjoWs1yH74KcvC");
21
+ });
22
+
23
+ it("derive m/0/1", () => {
24
+ const address = deriveAddress(derivationMode, xpub, 0, 1);
25
+ expect(address).toEqual("DNKtLJKxfYascpVyVHyQ73S65ssKQtH95A");
26
+ });
27
+
28
+ it("derive m/1/0", () => {
29
+ const address = deriveAddress(derivationMode, xpub, 1, 0);
30
+ expect(address).toEqual("DLnAvdtK2DDGeakaQUf2BUvZVUJw7KRgTg");
31
+ });
32
+
33
+ it("derive m/1/1", () => {
34
+ const address = deriveAddress(derivationMode, xpub, 1, 1);
35
+ expect(address).toEqual("DC6Pmh6eGENRC8T2cu5roTXPPQXBMk8b2o");
36
+ });
37
+
38
+ it("derive m/1/10000000", () => {
39
+ const address = deriveAddress(derivationMode, xpub, 1, 10000000);
40
+ expect(address).toEqual("D6Yf9DRNY8VSTtorybWJzJbDBugExnMTsg");
41
+ });
42
+ });
43
+ });
@@ -0,0 +1,26 @@
1
+ import { configuration } from "../../src/configuration/settings";
2
+ import { currencies, DerivationMode } from "../../src/configuration/currencies";
3
+ import { deriveAddress } from "../../src/actions/deriveAddresses";
4
+
5
+ describe("derive Ethereum addresses", () => {
6
+ let derivationMode;
7
+
8
+ beforeEach(() => {
9
+ derivationMode = DerivationMode.ETHEREUM;
10
+ configuration.currency = currencies.eth;
11
+ });
12
+
13
+ it("derive from xpub6Fx82V...zwKG5g4Sc6", () => {
14
+ const xpub =
15
+ "xpub6Fx82VfZ6EdtNfD7eANUEvKYxB2AV4hf4Xm4LpiyNVmNHDGKu7T72WVr7qmCzKFC3VQMYrMMNJVy9BNXKUtUebxZx7kRYNG89zwKG5g4Sc6";
16
+ const address = deriveAddress(derivationMode, xpub);
17
+ expect(address).toEqual("0xb56aa13aab4869da8ae07ad2a04ec2deec35e0f0");
18
+ });
19
+
20
+ it("derive from xpub6GkCbW...Lejvh9nHE", () => {
21
+ const xpub =
22
+ "xpub6GkCbW4FDnz8k9zhroVhZefi9fXhFFuTmmcQqfQKPDBrQjtSu4pdLpQ1Tje1BAzUw6PbJ47MMtNZ4RYM42VzRNxwaYUFnm3R44Lejvh9nHE";
23
+ const address = deriveAddress(derivationMode, xpub);
24
+ expect(address).toEqual("0x90f8bf6a479f320ead074411a4b0e7944ea8c9c1");
25
+ });
26
+ });
@@ -0,0 +1,110 @@
1
+ import { configuration } from "../../src/configuration/settings";
2
+ import { currencies, DerivationMode } from "../../src/configuration/currencies";
3
+ import { deriveAddress } from "../../src/actions/deriveAddresses";
4
+
5
+ describe("derive Litecoin addresses", () => {
6
+ let xpub;
7
+ let derivationMode;
8
+
9
+ describe("derive Litecoin mainnet addresses", () => {
10
+ beforeEach(() => {
11
+ xpub =
12
+ "Ltub2ZoLFXBt7mLeb4out9duUxMmqCSX9mqi73NcQ8nyjQsJEm76JP1poExdj9rRCFfHyuUVKgj5t2B2EBsmFvKivKzVpmKKZ4XiAVx65s3WZ8j";
13
+ configuration.currency = currencies.ltc;
14
+ configuration.currency.network = currencies.ltc.network_mainnet;
15
+ });
16
+
17
+ describe("derive Legacy addresses", () => {
18
+ beforeEach(() => {
19
+ derivationMode = DerivationMode.LEGACY;
20
+ });
21
+
22
+ it("derive m/0/0", () => {
23
+ const address = deriveAddress(derivationMode, xpub, 0, 0);
24
+ expect(address).toEqual("LQvJrXTHfAvUBGRs6LRTwC6nX7rYhzVbu9");
25
+ });
26
+
27
+ it("derive m/0/1", () => {
28
+ const address = deriveAddress(derivationMode, xpub, 0, 1);
29
+ expect(address).toEqual("LQFH5FQp2yi5NGspg8hGXeRJRzVYWAM2Ks");
30
+ });
31
+
32
+ it("derive m/1/0", () => {
33
+ const address = deriveAddress(derivationMode, xpub, 1, 0);
34
+ expect(address).toEqual("LYijJ7MzngZGGf5pQ1FBDLe23mjAM5dZWm");
35
+ });
36
+
37
+ it("derive m/1/1", () => {
38
+ const address = deriveAddress(derivationMode, xpub, 1, 1);
39
+ expect(address).toEqual("LTGro5xiqTsk7evvQmbAm4SqHq4X97pswZ");
40
+ });
41
+
42
+ it("derive m/1/10000000", () => {
43
+ const address = deriveAddress(derivationMode, xpub, 1, 10000000);
44
+ expect(address).toEqual("LUoTXPY5CfaXY3ZVMBbANX2erZK26bHsGP");
45
+ });
46
+ });
47
+
48
+ describe("derive SegWit addresses", () => {
49
+ beforeEach(() => {
50
+ derivationMode = DerivationMode.SEGWIT;
51
+ });
52
+
53
+ it("derive m/0/0", () => {
54
+ const address = deriveAddress(derivationMode, xpub, 0, 0);
55
+ expect(address).toEqual("MBz6dSyR1RkkUa7iEiKsXapEGEK6hxjWci");
56
+ });
57
+
58
+ it("derive m/0/1", () => {
59
+ const address = deriveAddress(derivationMode, xpub, 0, 1);
60
+ expect(address).toEqual("MMN88qfy1JmdCdmccXWeJCXJGAiVLgRTCY");
61
+ });
62
+
63
+ it("derive m/1/0", () => {
64
+ const address = deriveAddress(derivationMode, xpub, 1, 0);
65
+ expect(address).toEqual("MPxw2xaMUSTHjGQwqw51RMjrPpbK4cT86S");
66
+ });
67
+
68
+ it("derive m/1/1", () => {
69
+ const address = deriveAddress(derivationMode, xpub, 1, 1);
70
+ expect(address).toEqual("MN6dPnaRuMRtGj7WXjdJw2F37fhV8s6f9X");
71
+ });
72
+
73
+ it("derive m/1/10000000", () => {
74
+ const address = deriveAddress(derivationMode, xpub, 1, 10000000);
75
+ expect(address).toEqual("MULBsckG2JmuWqryuEqKLsCDC2dGxUdJaj");
76
+ });
77
+ });
78
+
79
+ describe("derive Native SegWit addresses", () => {
80
+ beforeEach(() => {
81
+ derivationMode = DerivationMode.NATIVE;
82
+ });
83
+
84
+ it("derive m/0/0", () => {
85
+ const address = deriveAddress(derivationMode, xpub, 0, 0);
86
+ expect(address).toEqual("ltc1q8ea8f4337su3ucfeaxq5pyyz3nttx6v3ehvg0l");
87
+ });
88
+
89
+ it("derive m/0/1", () => {
90
+ const address = deriveAddress(derivationMode, xpub, 0, 1);
91
+ expect(address).toEqual("ltc1qxuvt7k66rqdy7m76ckaum9cwcq2tezyc400gg0");
92
+ });
93
+
94
+ it("derive m/1/0", () => {
95
+ const address = deriveAddress(derivationMode, xpub, 1, 0);
96
+ expect(address).toEqual("ltc1qjs9dlgqa6lyu8m2w08yt0u20vaahcms2uxtdn6");
97
+ });
98
+
99
+ it("derive m/1/1", () => {
100
+ const address = deriveAddress(derivationMode, xpub, 1, 1);
101
+ expect(address).toEqual("ltc1qtpxmpgrhfwyvl3rtrl2dxjq3fma54y06prjy5a");
102
+ });
103
+
104
+ it("derive m/1/10000000", () => {
105
+ const address = deriveAddress(derivationMode, xpub, 1, 10000000);
106
+ expect(address).toEqual("ltc1qdy85jq4h6qsyc5ljayxev226rxp9gkupt4h9gt");
107
+ });
108
+ });
109
+ });
110
+ });
@@ -0,0 +1,274 @@
1
+ import BigNumber from "bignumber.js";
2
+ import { currencies } from "../src/configuration/currencies";
3
+ import { configuration } from "../src/configuration/settings";
4
+ import { retry, toAccountUnit, toBaseUnit } from "../src/helpers";
5
+ import { flushPromises } from "./test-utils";
6
+
7
+ describe("helpers", () => {
8
+ describe("convert from unit of account to base unit", () => {
9
+ describe("convert bitcoins to satoshis", () => {
10
+ beforeEach(() => {
11
+ configuration.currency = currencies.btc;
12
+ });
13
+
14
+ it("0.99999999 bitcoin ➝ 99999999 satoshis", () => {
15
+ const AmountInBaseUnit = new BigNumber(0.99999999);
16
+ const amountInAccountUnit = toBaseUnit(AmountInBaseUnit);
17
+ expect(amountInAccountUnit).toEqual("99999999");
18
+ });
19
+
20
+ it("1 bitcoin ➝ 100000000 satoshis", () => {
21
+ const AmountInBaseUnit = new BigNumber(1);
22
+ const amountInAccountUnit = toBaseUnit(AmountInBaseUnit);
23
+ expect(amountInAccountUnit).toEqual("100000000");
24
+ });
25
+
26
+ it("1.23456789 bitcoin ➝ 123456789 satoshis", () => {
27
+ const AmountInBaseUnit = new BigNumber(1.23456789);
28
+ const amountInAccountUnit = toBaseUnit(AmountInBaseUnit);
29
+ expect(amountInAccountUnit).toEqual("123456789");
30
+ });
31
+
32
+ it("123456789 bitcoins ➝ 12345678900000000 satoshis", () => {
33
+ const AmountInBaseUnit = new BigNumber(123456789);
34
+ const amountInAccountUnit = toBaseUnit(AmountInBaseUnit);
35
+ expect(amountInAccountUnit).toEqual("12345678900000000");
36
+ });
37
+ });
38
+
39
+ describe("convert litecoins to litoshi", () => {
40
+ beforeEach(() => {
41
+ configuration.currency = currencies.ltc;
42
+ });
43
+
44
+ it("0.99999999 litecoin ➝ 99999999 litoshis", () => {
45
+ const AmountInBaseUnit = new BigNumber(0.99999999);
46
+ const amountInAccountUnit = toBaseUnit(AmountInBaseUnit);
47
+ expect(amountInAccountUnit).toEqual("99999999");
48
+ });
49
+
50
+ it("1 litecoin ➝ 100000000 litoshis", () => {
51
+ const AmountInBaseUnit = new BigNumber(1);
52
+ const amountInAccountUnit = toBaseUnit(AmountInBaseUnit);
53
+ expect(amountInAccountUnit).toEqual("100000000");
54
+ });
55
+
56
+ it("1.23456789 litecoin ➝ 123456789 litoshis", () => {
57
+ const AmountInBaseUnit = new BigNumber(1.23456789);
58
+ const amountInAccountUnit = toBaseUnit(AmountInBaseUnit);
59
+ expect(amountInAccountUnit).toEqual("123456789");
60
+ });
61
+
62
+ it("123456789 litecoins ➝ 12345678900000000 litoshis", () => {
63
+ const AmountInBaseUnit = new BigNumber(123456789);
64
+ const amountInAccountUnit = toBaseUnit(AmountInBaseUnit);
65
+ expect(amountInAccountUnit).toEqual("12345678900000000");
66
+ });
67
+ });
68
+
69
+ describe("convert ethers to weis", () => {
70
+ beforeEach(() => {
71
+ configuration.currency = currencies.eth;
72
+ });
73
+
74
+ it("0.99999999 ether ➝ 999999990000000000 weis", () => {
75
+ const AmountInBaseUnit = new BigNumber(0.99999999);
76
+ const amountInAccountUnit = toBaseUnit(AmountInBaseUnit);
77
+ expect(amountInAccountUnit).toEqual("999999990000000000");
78
+ });
79
+
80
+ it("1 ether ➝ 1000000000000000000 weis", () => {
81
+ const AmountInBaseUnit = new BigNumber(1);
82
+ const amountInAccountUnit = toBaseUnit(AmountInBaseUnit);
83
+ expect(amountInAccountUnit).toEqual("1000000000000000000");
84
+ });
85
+
86
+ it("1.23456789 ether ➝ 1234567890000000000 weis", () => {
87
+ const AmountInBaseUnit = new BigNumber(1.23456789);
88
+ const amountInAccountUnit = toBaseUnit(AmountInBaseUnit);
89
+ expect(amountInAccountUnit).toEqual("1234567890000000000");
90
+ });
91
+
92
+ it("123456789 ethers ➝ 123456789000000000000000000 weis", () => {
93
+ const AmountInBaseUnit = new BigNumber(123456789);
94
+ const amountInAccountUnit = toBaseUnit(AmountInBaseUnit);
95
+ expect(amountInAccountUnit).toEqual("123456789000000000000000000");
96
+ });
97
+ });
98
+ });
99
+
100
+ describe("convert from base unit to unit of account", () => {
101
+ describe("convert satoshis to bitcoin", () => {
102
+ beforeEach(() => {
103
+ configuration.currency = currencies.btc;
104
+ });
105
+
106
+ it("1 satoshi ➝ 0.00000001 bitcoin", () => {
107
+ const amountInAccountUnit = new BigNumber(1);
108
+ const AmountInBaseUnit = toAccountUnit(amountInAccountUnit);
109
+ expect(AmountInBaseUnit).toEqual("0.00000001");
110
+ });
111
+
112
+ it("10 satoshis ➝ 0.0000001 bitcoin", () => {
113
+ const amountInAccountUnit = new BigNumber(10);
114
+ const AmountInBaseUnit = toAccountUnit(amountInAccountUnit);
115
+ expect(AmountInBaseUnit).toEqual("0.0000001");
116
+ });
117
+
118
+ it("9999999999 satoshis ➝ 99.99999999 bitcoins", () => {
119
+ const amountInAccountUnit = new BigNumber(9999999999);
120
+ const AmountInBaseUnit = toAccountUnit(amountInAccountUnit);
121
+ expect(AmountInBaseUnit).toEqual("99.99999999");
122
+ });
123
+
124
+ it("10000000000 satoshis ➝ 100 bitcoins", () => {
125
+ const amountInAccountUnit = new BigNumber(10000000000);
126
+ const AmountInBaseUnit = toAccountUnit(amountInAccountUnit);
127
+ expect(AmountInBaseUnit).toEqual("100");
128
+ });
129
+ });
130
+
131
+ describe("convert litoshis to litecoins", () => {
132
+ beforeEach(() => {
133
+ configuration.currency = currencies.ltc;
134
+ });
135
+
136
+ it("1 litoshi ➝ 0.00000001 litecoins", () => {
137
+ const amountInAccountUnit = new BigNumber(1);
138
+ const AmountInBaseUnit = toAccountUnit(amountInAccountUnit);
139
+ expect(AmountInBaseUnit).toEqual("0.00000001");
140
+ });
141
+
142
+ it("10 litoshis ➝ 0.0000001 litecoins", () => {
143
+ const amountInAccountUnit = new BigNumber(10);
144
+ const AmountInBaseUnit = toAccountUnit(amountInAccountUnit);
145
+ expect(AmountInBaseUnit).toEqual("0.0000001");
146
+ });
147
+
148
+ it("9999999999 litoshis ➝ 99.99999999 litecoins", () => {
149
+ const amountInAccountUnit = new BigNumber(9999999999);
150
+ const AmountInBaseUnit = toAccountUnit(amountInAccountUnit);
151
+ expect(AmountInBaseUnit).toEqual("99.99999999");
152
+ });
153
+
154
+ it("10000000000 litoshis ➝ 100 litecoins", () => {
155
+ const amountInAccountUnit = new BigNumber(10000000000);
156
+ const AmountInBaseUnit = toAccountUnit(amountInAccountUnit);
157
+ expect(AmountInBaseUnit).toEqual("100");
158
+ });
159
+ });
160
+
161
+ describe("convert weis to ethers", () => {
162
+ beforeEach(() => {
163
+ configuration.currency = currencies.eth;
164
+ });
165
+
166
+ it("1 wei ➝ 0.00000000 ether (because of the 10-digit precision)", () => {
167
+ const amountInAccountUnit = new BigNumber(1);
168
+ const AmountInBaseUnit = toAccountUnit(amountInAccountUnit);
169
+ expect(AmountInBaseUnit).toEqual("0.0000000000");
170
+ });
171
+
172
+ it("100000000 weis ➝ 0.0000000001 ether", () => {
173
+ const amountInAccountUnit = new BigNumber(100000000);
174
+ const AmountInBaseUnit = toAccountUnit(amountInAccountUnit);
175
+ expect(AmountInBaseUnit).toEqual("0.0000000001");
176
+ });
177
+
178
+ it("1000000000 weis ➝ 0.0000000010 ether", () => {
179
+ const amountInAccountUnit = new BigNumber(1000000000);
180
+ const AmountInBaseUnit = toAccountUnit(amountInAccountUnit);
181
+ expect(AmountInBaseUnit).toEqual("0.0000000010");
182
+ });
183
+
184
+ it("9999999999 weis ➝ 0.0000000100 ether (round up)", () => {
185
+ const amountInAccountUnit = new BigNumber(9999999999);
186
+ const AmountInBaseUnit = toAccountUnit(amountInAccountUnit);
187
+ expect(AmountInBaseUnit).toEqual("0.0000000100");
188
+ });
189
+
190
+ it("1000000000000000000 weis ➝ 1 ether", () => {
191
+ const amountInAccountUnit = new BigNumber(1000000000000000000);
192
+ const AmountInBaseUnit = toAccountUnit(amountInAccountUnit);
193
+ expect(AmountInBaseUnit).toEqual("1.0000000000");
194
+ });
195
+
196
+ it("1000000000000000000000 weis ➝ 1000 ethers", () => {
197
+ const amountInAccountUnit = new BigNumber(1000000000000000000000);
198
+ const AmountInBaseUnit = toAccountUnit(amountInAccountUnit);
199
+ expect(AmountInBaseUnit).toEqual("1000.0000000000");
200
+ });
201
+ });
202
+ });
203
+
204
+ describe("retry", () => {
205
+ it("should try only 1 time if job is successful", async () => {
206
+ const job = jest.fn();
207
+ await retry(job);
208
+ expect(job).toHaveBeenCalledTimes(1);
209
+ });
210
+
211
+ it("should retry and succeed on the second time", async () => {
212
+ let nonce = 0;
213
+ const mock = {
214
+ job: async () => {
215
+ nonce++;
216
+ if (nonce === 2) return { result: "test" };
217
+ throw new Error("Job failed");
218
+ },
219
+ };
220
+ const spy = jest.spyOn(mock, "job");
221
+ const res = await retry(mock.job);
222
+ expect(spy).toHaveBeenCalledTimes(2);
223
+ expect(res).toEqual({ result: "test" });
224
+ });
225
+
226
+ it("should error after all retries has been consumed", async () => {
227
+ const retriesCount = 23;
228
+ const mock = {
229
+ job: async () => {
230
+ throw new Error("Job failed");
231
+ },
232
+ };
233
+ let err;
234
+ const spy = jest.spyOn(mock, "job");
235
+ try {
236
+ await retry(mock.job, { retries: retriesCount });
237
+ } catch (e) {
238
+ err = e;
239
+ }
240
+ expect(spy).toHaveBeenCalledTimes(retriesCount);
241
+ expect(err).toEqual(new Error("Job failed"));
242
+ });
243
+
244
+ it("should allow delaying each retry", async () => {
245
+ let nonce = 0;
246
+ const mock = {
247
+ job: async () => {
248
+ nonce++;
249
+ if (nonce === 3) return { result: "test" };
250
+ throw new Error("Job failed");
251
+ },
252
+ };
253
+ const spy = jest.spyOn(mock, "job");
254
+ jest.useFakeTimers({ legacyFakeTimers: true });
255
+ const promise = retry(mock.job, { retryDelayMS: 500 });
256
+
257
+ await flushPromises();
258
+ expect(spy).toHaveBeenCalledTimes(1);
259
+
260
+ jest.advanceTimersByTime(500);
261
+ await flushPromises();
262
+
263
+ expect(spy).toHaveBeenCalledTimes(2);
264
+
265
+ jest.advanceTimersByTime(500);
266
+ await flushPromises();
267
+
268
+ expect(spy).toHaveBeenCalledTimes(3);
269
+
270
+ const res = await promise;
271
+ expect(res).toEqual({ result: "test" });
272
+ });
273
+ });
274
+ });
@@ -0,0 +1,3 @@
1
+ export function flushPromises() {
2
+ return new Promise((resolve) => setImmediate(resolve));
3
+ }
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ presets: [
3
+ ["@babel/preset-env", { targets: { node: "current" } }],
4
+ "@babel/preset-typescript",
5
+ ],
6
+ };
package/jest.config.ts ADDED
@@ -0,0 +1,5 @@
1
+ export default {
2
+ testEnvironment: "node",
3
+ testMatch: ["**/__tests__/**/*.test.ts"],
4
+ moduleDirectories: ["node_modules"],
5
+ };
Binary file
@@ -0,0 +1,29 @@
1
+ interface Result {
2
+ partial?: string;
3
+ account?: number;
4
+ index?: number;
5
+ }
6
+ interface SearchRange {
7
+ account: {
8
+ min: number;
9
+ max: number;
10
+ };
11
+ index: {
12
+ min: number;
13
+ max: number;
14
+ };
15
+ }
16
+ /**
17
+ * identify whether an address provided by the user belongs or not to the xpub
18
+ * @param xpub the xpub from which the address may have been derived
19
+ * @param providedAddress the address provided by the user
20
+ * @param range the range of the search (i.e., accounts and indices ranges)
21
+ * @param searchType indication of the type of search (quick/deep)
22
+ * @returns a match or an empty object (i.e., non-match)
23
+ */
24
+ declare function search(xpub: string, providedAddress: string, range: SearchRange, searchType: string): Result;
25
+ declare function run(xpub: string, providedAddress: string): void;
26
+ export declare const _private: {
27
+ search: typeof search;
28
+ };
29
+ export { run };