@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,87 @@
1
+ import { _private } from "../../src/actions/checkAddress";
2
+ import { DERIVATION_SCOPE } from "../../src/configuration/settings";
3
+
4
+ const testSearchFunction = (xpub: string, providedAddress: string) => {
5
+ return _private.search(
6
+ xpub,
7
+ providedAddress,
8
+ DERIVATION_SCOPE.quick_search,
9
+ "quick search",
10
+ );
11
+ };
12
+
13
+ describe("check whether addresses belong or not to xpubs", () => {
14
+ /* eslint-disable */
15
+ console.log = function () {};
16
+
17
+ const xpub =
18
+ "Ltub2ZoLFXBt7mLeb4out9duUxMmqCSX9mqi73NcQ8nyjQsJEm76JP1poExdj9rRCFfHyuUVKgj5t2B2EBsmFvKivKzVpmKKZ4XiAVx65s3WZ8j";
19
+
20
+ describe("addresses belonging to the xpub", () => {
21
+ it("complete legacy address — m/1/640", () => {
22
+ const providedAddress = "LXSUUS8Phpm4zGsdfA7pFsDN17yyK8N2Km";
23
+ const expectedResult = { account: 1, index: 640 };
24
+
25
+ const match = testSearchFunction(xpub, providedAddress);
26
+
27
+ expect(match).toEqual(expectedResult);
28
+ });
29
+
30
+ it("partial legacy address — m/1/640", () => {
31
+ const providedAddress = "LXSUUS8Ph??4zGsdfA7pFsDN17yyK8N2K?";
32
+ const expectedResult = {
33
+ account: 1,
34
+ index: 640,
35
+ partial: "LXSUUS8Phpm4zGsdfA7pFsDN17yyK8N2Km",
36
+ };
37
+
38
+ const match = testSearchFunction(xpub, providedAddress);
39
+
40
+ expect(match).toEqual(expectedResult);
41
+ });
42
+
43
+ it("complete SegWit address — m/3/3", () => {
44
+ const providedAddress = "MNY33b2fP4zLQ7W9oBGgw9TfFAm2TxWPAY";
45
+ const expectedResult = { account: 3, index: 3 };
46
+
47
+ const match = testSearchFunction(xpub, providedAddress);
48
+
49
+ expect(match).toEqual(expectedResult);
50
+ });
51
+
52
+ it("partial SegWit address — m/3/3", () => {
53
+ const providedAddress = "MNY33b2fP4zLQ7W9oBGgw9TfFAm2TxW???";
54
+ const expectedResult = {
55
+ account: 3,
56
+ index: 3,
57
+ partial: "MNY33b2fP4zLQ7W9oBGgw9TfFAm2TxWPAY",
58
+ };
59
+
60
+ const match = testSearchFunction(xpub, providedAddress);
61
+
62
+ expect(match).toEqual(expectedResult);
63
+ });
64
+
65
+ it("complete native SegWit address — m/3/898", () => {
66
+ const providedAddress = "ltc1q2vld3k49e7425kwtu2h0507pnx026gcyy4qgvd";
67
+ const expectedResult = { account: 3, index: 898 };
68
+
69
+ const match = testSearchFunction(xpub, providedAddress);
70
+
71
+ expect(match).toEqual(expectedResult);
72
+ });
73
+
74
+ it("partial native SegWit address — m/3/898", () => {
75
+ const providedAddress = "ltc1q2vld3k49e742??wtu2h?507pnx026gcyy4qg?d";
76
+ const expectedResult = {
77
+ account: 3,
78
+ index: 898,
79
+ partial: "ltc1q2vld3k49e7425kwtu2h0507pnx026gcyy4qgvd",
80
+ };
81
+
82
+ const match = testSearchFunction(xpub, providedAddress);
83
+
84
+ expect(match).toEqual(expectedResult);
85
+ });
86
+ });
87
+ });
@@ -0,0 +1,183 @@
1
+ import { configuration } from "../../src/configuration/settings";
2
+ import { currencies, DerivationMode } from "../../src/configuration/currencies";
3
+ import { Address } from "../../src/models/address";
4
+ import { Operation } from "../../src/models/operation";
5
+ import { Transaction } from "../../src/models/transaction";
6
+ import fakeRawTransaction from "./fakeRawTransactions.json";
7
+
8
+ const account = 0;
9
+ const index = 0;
10
+
11
+ describe("create a Bitcoin address object", () => {
12
+ let xpub;
13
+ let address;
14
+
15
+ beforeEach(() => {
16
+ configuration.currency = currencies.btc;
17
+ configuration.currency.network = currencies.btc.network_mainnet;
18
+
19
+ xpub =
20
+ "xpub6C9vKwUFiBLbQKS6mhEAtEYhS24sVz8MkvMjxQSECTZVCnFmy675zojLthvXVuQf15RT6ggmt7PTgLBV2tLHHdJenoEkNWe5VPBETncxf2q";
21
+
22
+ address = new Address(xpub, DerivationMode.LEGACY, account, index);
23
+ });
24
+
25
+ it("generate a valid Bitcoin address object", () => {
26
+ expect(address.toString()).toEqual("1AC4EypEKiobnZfDv1pSEt28g3D4MwY5WB");
27
+ expect(address.asCashAddress()).toBeUndefined;
28
+ expect(address.account).toEqual(account);
29
+ expect(address.index).toEqual(index);
30
+ expect(address.getDerivationMode()).toEqual("Legacy");
31
+ expect(address.getDerivation()).toMatchObject({
32
+ account,
33
+ index,
34
+ });
35
+ });
36
+
37
+ it("set and get balance as a string", () => {
38
+ const balance = "123.456789";
39
+
40
+ address.setBalance(balance);
41
+
42
+ expect(address.getBalance()).toMatch(balance);
43
+ expect(address.isUTXO()).toEqual(true);
44
+ });
45
+
46
+ it("set and get balance as a number", () => {
47
+ const balance = 123.456789;
48
+
49
+ address.setBalance(balance);
50
+
51
+ expect(address.getBalance()).toEqual(balance.toPrecision());
52
+ expect(address.isUTXO()).toEqual(true);
53
+ });
54
+
55
+ it("set and get an empty balance", () => {
56
+ const balance = "0";
57
+
58
+ address.setBalance(balance);
59
+
60
+ expect(address.getBalance()).toEqual(balance);
61
+ expect(address.isUTXO()).toEqual(false);
62
+ });
63
+
64
+ it("set and get basic stats", () => {
65
+ const transactionsCount = 1;
66
+ const totalFunded = 0.987654321;
67
+ const totalSpent = 0.123456789;
68
+
69
+ address.setStats(transactionsCount, totalFunded, totalSpent);
70
+
71
+ const stats = address.getStats();
72
+
73
+ expect(stats.txsCount.toString()).toEqual(transactionsCount.toString());
74
+ expect(stats.funded.toString()).toEqual(totalFunded.toString());
75
+ expect(stats.spent.toString()).toEqual(totalSpent.toString());
76
+ });
77
+
78
+ describe("set and get transactional objects", () => {
79
+ const op1 = new Operation("2020-05-28T00:00:00Z", "0.00001");
80
+ const op2 = new Operation("2020-05-28T00:00:00Z", "0.123");
81
+ const op3 = new Operation("2020-05-28T00:00:00Z", "0.0000001");
82
+ const op4 = new Operation("2022-05-22T00:00:00Z", "0.9999");
83
+
84
+ const transaction1 = new Transaction(
85
+ 10,
86
+ "2020-05-28T00:00:00Z",
87
+ "6a832f494b57870a4cb8c9d4094373a6726ad501a12ee1106b371ef592df1df6",
88
+ [op1, op2],
89
+ [op3],
90
+ );
91
+
92
+ const transaction2 = new Transaction(
93
+ 10,
94
+ "2022-05-22T00:00:00Z",
95
+ "91bef9ebc0b0c680765faaa2e050f6ca871ce3c7fca69a22278aa77692041974",
96
+ [],
97
+ [op4],
98
+ );
99
+
100
+ it("try to get raw transactions", () => {
101
+ expect(address.getRawTransactions()).toMatchObject([]);
102
+ });
103
+
104
+ it("set and get raw transactions", () => {
105
+ address.setRawTransactions(fakeRawTransaction);
106
+
107
+ expect(address.getRawTransactions()).toMatchObject(fakeRawTransaction);
108
+ });
109
+
110
+ it("set and get normalized transactions", () => {
111
+ const normalizedTransactions = [transaction1, transaction2];
112
+
113
+ address.setTransactions(normalizedTransactions);
114
+
115
+ expect(address.getTransactions()).toMatchObject(normalizedTransactions);
116
+ });
117
+
118
+ it("set and get funded transactions", () => {
119
+ address.addFundedOperation(op1);
120
+
121
+ expect(address.getFundedOperations()).toMatchObject([op1]);
122
+ });
123
+
124
+ it("set and get sent transactions", () => {
125
+ address.addSentOperation(op2);
126
+
127
+ expect(address.getSentOperations()).toMatchObject([op2]);
128
+ });
129
+ });
130
+ });
131
+
132
+ describe("create a Bitcoin Cash address object", () => {
133
+ let xpub;
134
+ let address;
135
+
136
+ beforeEach(() => {
137
+ configuration.currency = currencies.bch;
138
+ configuration.currency.network = currencies.bch.network_mainnet;
139
+
140
+ xpub =
141
+ "xpub6CJgFcZxrd2yjt11C91E4xTb7whLw1amvXzzhhdmfqutTdbT53GS4nbS6pcsPQ2EJyPBxWi7Rvro2pqBVUuKj1BqET1gujWmLE6WJD7pb1o";
142
+
143
+ address = new Address(xpub, DerivationMode.BCH, account, index);
144
+ });
145
+
146
+ it("generate a valid Bitcoin Cash address object", () => {
147
+ expect(address.toString()).toEqual("195D2Q9NPSpZxkD2gmEtNFzK8s65FS7QZB");
148
+ expect(address.account).toEqual(account);
149
+ expect(address.index).toEqual(index);
150
+ expect(address.derivationMode).toEqual("Bitcoin Cash");
151
+ expect(address.getDerivation()).toMatchObject({
152
+ account,
153
+ index,
154
+ });
155
+ });
156
+
157
+ it("generate a valid Bitcoin Cash address as string", () => {
158
+ configuration.currency = currencies.bch;
159
+
160
+ expect(address.asCashAddress()).toEqual(
161
+ "qpvgedg5e92ut08ksxrw0w9l9xevecfwg5dg503vfy",
162
+ );
163
+ });
164
+ });
165
+
166
+ describe("create an Ethereum address object", () => {
167
+ let ethereumAddress;
168
+ let address;
169
+
170
+ beforeEach(() => {
171
+ configuration.currency = currencies.eth;
172
+
173
+ ethereumAddress = "0x243b14754EF82F881a4a81f9af07c58Ea5eb4a87";
174
+
175
+ address = new Address(ethereumAddress);
176
+ });
177
+
178
+ it("generate a valid Ethereum address object", () => {
179
+ expect(address.toString()).toEqual(
180
+ "0x243b14754EF82F881a4a81f9af07c58Ea5eb4a87",
181
+ );
182
+ });
183
+ });
@@ -0,0 +1,182 @@
1
+ [
2
+ {
3
+ "index": 1886,
4
+ "minedInBlockHash": "0000000000000000000b96dc8d6e75dc3eb4f995a10545f84ad1b8f1de4b9893",
5
+ "minedInBlockHeight": 710566,
6
+ "recipients": [
7
+ {
8
+ "address": "3Q2AxuRxJnvddAa1wAm8PXeQCiBhkCGndi",
9
+ "amount": "0.00070000"
10
+ },
11
+ {
12
+ "address": "1GiCSuc1harcGUePV2EfZxmKoJou8V6KVE",
13
+ "amount": "0.00010056"
14
+ }
15
+ ],
16
+ "senders": [
17
+ {
18
+ "address": "1CiWPcvoNz9DhrMbb8QLzX2GfhN96TDF78",
19
+ "amount": "0.00012300"
20
+ },
21
+ {
22
+ "address": "12bNVFv2eTy5wkDQKFT78a47Pk8TEaQjBL",
23
+ "amount": "0.00070000"
24
+ }
25
+ ],
26
+ "timestamp": 1637412724,
27
+ "transactionHash": "6a832f494b57870a4cb8c9d4094373a6726ad501a12ee1106b371ef592df1df6",
28
+ "transactionId": "6a832f494b57870a4cb8c9d4094373a6726ad501a12ee1106b371ef592df1df6",
29
+ "fee": { "amount": "0.00002244", "unit": "BTC" },
30
+ "blockchainSpecific": {
31
+ "locktime": 0,
32
+ "size": 371,
33
+ "vSize": 371,
34
+ "version": 2,
35
+ "vin": [
36
+ {
37
+ "addresses": ["1CiWPcvoNz9DhrMbb8QLzX2GfhN96TDF78"],
38
+ "scriptSig": {
39
+ "asm": "3044022058d101dcea46d3f287820afa12b28d8da8664b2cf125d8d6421b7a561fe187fd0220688045f5c20d182db323ff5e993bfd613b471c6b4520beffd60372a014adc2bf[ALL] 030e829360f4691b62271a20765efd661f781cd5d7556a4f3dc453c1ad6e873cbe",
40
+ "hex": "473044022058d101dcea46d3f287820afa12b28d8da8664b2cf125d8d6421b7a561fe187fd0220688045f5c20d182db323ff5e993bfd613b471c6b4520beffd60372a014adc2bf0121030e829360f4691b62271a20765efd661f781cd5d7556a4f3dc453c1ad6e873cbe",
41
+ "type": "pubkeyhash"
42
+ },
43
+ "sequence": "4294967295",
44
+ "txid": "1591f1cca0e197d337bd6e55621e1df0888f15c283b6538e0fb74f7e68a4faab",
45
+ "txinwitness": [],
46
+ "value": "0.000123",
47
+ "vout": 0
48
+ },
49
+ {
50
+ "addresses": ["12bNVFv2eTy5wkDQKFT78a47Pk8TEaQjBL"],
51
+ "scriptSig": {
52
+ "asm": "3045022100b3b9b793abaddb4533e0e0639c5142a1a2210a44c4cddfc10140d46b692f6c8c02202e9c76a29c950dfc2e1f113418dccdd62ca50f0b5c855b2ba1383a9c26455b01[ALL] 02c045574551a8f1e5b600c5f59b222b4bbc648e436e11ef623d6178b95d081f4b",
53
+ "hex": "483045022100b3b9b793abaddb4533e0e0639c5142a1a2210a44c4cddfc10140d46b692f6c8c02202e9c76a29c950dfc2e1f113418dccdd62ca50f0b5c855b2ba1383a9c26455b01012102c045574551a8f1e5b600c5f59b222b4bbc648e436e11ef623d6178b95d081f4b",
54
+ "type": "pubkeyhash"
55
+ },
56
+ "sequence": "4294967295",
57
+ "txid": "91bef9ebc0b0c680765faaa2e050f6ca871ce3c7fca69a22278aa77692041974",
58
+ "txinwitness": [],
59
+ "value": "0.0007",
60
+ "vout": 0
61
+ }
62
+ ],
63
+ "vout": [
64
+ {
65
+ "isSpent": true,
66
+ "scriptPubKey": {
67
+ "addresses": ["3Q2AxuRxJnvddAa1wAm8PXeQCiBhkCGndi"],
68
+ "asm": "OP_HASH160 f4f237a2426d8070036ae8428b06a243dd5b8f40 OP_EQUAL",
69
+ "hex": "a914f4f237a2426d8070036ae8428b06a243dd5b8f4087",
70
+ "reqSigs": 1,
71
+ "type": "scripthash"
72
+ },
73
+ "value": "0.00070000"
74
+ },
75
+ {
76
+ "isSpent": false,
77
+ "scriptPubKey": {
78
+ "addresses": ["1GiCSuc1harcGUePV2EfZxmKoJou8V6KVE"],
79
+ "asm": "OP_DUP OP_HASH160 ac547f137094459445cc03234a1007ef6a4bb925 OP_EQUALVERIFY OP_CHECKSIG",
80
+ "hex": "76a914ac547f137094459445cc03234a1007ef6a4bb92588ac",
81
+ "reqSigs": 1,
82
+ "type": "pubkeyhash"
83
+ },
84
+ "value": "0.00010056"
85
+ }
86
+ ]
87
+ }
88
+ },
89
+ {
90
+ "index": 610,
91
+ "minedInBlockHash": "00000000000000000001338b537f738a5c3b2e3c3f280bce875ccef0d4117bc7",
92
+ "minedInBlockHeight": 710564,
93
+ "recipients": [
94
+ {
95
+ "address": "12bNVFv2eTy5wkDQKFT78a47Pk8TEaQjBL",
96
+ "amount": "0.00070000"
97
+ },
98
+ {
99
+ "address": "3ABEPGqmMW6nDfukW8iA8M93gsSMyPmyAM",
100
+ "amount": "0.00010068"
101
+ }
102
+ ],
103
+ "senders": [
104
+ {
105
+ "address": "35Nmr5AzLgj7dgNVAqBf5R79nPoVw2XmAZ",
106
+ "amount": "0.00070000"
107
+ },
108
+ {
109
+ "address": "3EBHXFYLnXrjLSsy9SJ1x61cURhPGsetyH",
110
+ "amount": "0.00010842"
111
+ }
112
+ ],
113
+ "timestamp": 1637410404,
114
+ "transactionHash": "8fc8b64cab9970613e738d5821d5d670a7dce441fc46482cf41a794133d7d539",
115
+ "transactionId": "91bef9ebc0b0c680765faaa2e050f6ca871ce3c7fca69a22278aa77692041974",
116
+ "fee": { "amount": "0.00000774", "unit": "BTC" },
117
+ "blockchainSpecific": {
118
+ "locktime": 0,
119
+ "size": 422,
120
+ "vSize": 259,
121
+ "version": 2,
122
+ "vin": [
123
+ {
124
+ "addresses": ["35Nmr5AzLgj7dgNVAqBf5R79nPoVw2XmAZ"],
125
+ "scriptSig": {
126
+ "asm": "00147c08556d3be866d322ae721fdfcdf2bdec80d991",
127
+ "hex": "1600147c08556d3be866d322ae721fdfcdf2bdec80d991",
128
+ "type": "scripthash"
129
+ },
130
+ "sequence": "4294967295",
131
+ "txid": "814ef9f1dc6fa7a1d5a4b9166775c3c1f3beba9236f62d412ec9a77c314d9811",
132
+ "txinwitness": [
133
+ "30450221009cca3ff3bc03c44874c71fb4d743208cf612d2f1675eefa4ba33b95fce8ed37402206c1809d62481a6ac175fb27ac200b84f99f7a71b8531ce3c9a4410ab7482fe1801",
134
+ "036342c1734aa296d531390a9643890455abac58ab1be11f2e1a43472dfc3a71b4"
135
+ ],
136
+ "value": "0.0007",
137
+ "vout": 0
138
+ },
139
+ {
140
+ "addresses": ["3EBHXFYLnXrjLSsy9SJ1x61cURhPGsetyH"],
141
+ "scriptSig": {
142
+ "asm": "00142def04c5cde6fc1f83d409ace1a704c7f39b7227",
143
+ "hex": "1600142def04c5cde6fc1f83d409ace1a704c7f39b7227",
144
+ "type": "scripthash"
145
+ },
146
+ "sequence": "4294967295",
147
+ "txid": "814ef9f1dc6fa7a1d5a4b9166775c3c1f3beba9236f62d412ec9a77c314d9811",
148
+ "txinwitness": [
149
+ "3045022100e7f6e28b5bd253710e4a66efe18e0110f545d660b4d0825e62819f881cfe274102200fb44193bf330a705017faac7e769112fc7d5841fc2877b958ca0456bcda469401",
150
+ "02bdbd3a491f79c88d5f31b86907ee4ee420a5ba388b81bd29b42753b17eb47c98"
151
+ ],
152
+ "value": "0.00010842",
153
+ "vout": 1
154
+ }
155
+ ],
156
+ "vout": [
157
+ {
158
+ "isSpent": true,
159
+ "scriptPubKey": {
160
+ "addresses": ["12bNVFv2eTy5wkDQKFT78a47Pk8TEaQjBL"],
161
+ "asm": "OP_DUP OP_HASH160 11783480bbac3aafee18437a1daedb43ea412170 OP_EQUALVERIFY OP_CHECKSIG",
162
+ "hex": "76a91411783480bbac3aafee18437a1daedb43ea41217088ac",
163
+ "reqSigs": 1,
164
+ "type": "pubkeyhash"
165
+ },
166
+ "value": "0.00070000"
167
+ },
168
+ {
169
+ "isSpent": true,
170
+ "scriptPubKey": {
171
+ "addresses": ["3ABEPGqmMW6nDfukW8iA8M93gsSMyPmyAM"],
172
+ "asm": "OP_HASH160 5d170e14ebc81f830f88d2ca83e1d5bfddc34c50 OP_EQUAL",
173
+ "hex": "a9145d170e14ebc81f830f88d2ca83e1d5bfddc34c5087",
174
+ "reqSigs": 1,
175
+ "type": "scripthash"
176
+ },
177
+ "value": "0.00010068"
178
+ }
179
+ ]
180
+ }
181
+ }
182
+ ]
@@ -0,0 +1,207 @@
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 addresses", () => {
6
+ let xpub;
7
+ let derivationMode;
8
+
9
+ describe("derive Bitcoin mainnet addresses", () => {
10
+ beforeEach(() => {
11
+ xpub =
12
+ "xpub6C9vKwUFiBLbQKS6mhEAtEYhS24sVz8MkvMjxQSECTZVCnFmy675zojLthvXVuQf15RT6ggmt7PTgLBV2tLHHdJenoEkNWe5VPBETncxf2q";
13
+ configuration.currency = currencies.btc;
14
+ configuration.currency.network = currencies.btc.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("1AC4EypEKiobnZfDv1pSEt28g3D4MwY5WB");
25
+ });
26
+
27
+ it("derive m/0/1", () => {
28
+ const address = deriveAddress(derivationMode, xpub, 0, 1);
29
+ expect(address).toEqual("12hLWc8AXB6sikou3raetiMtNWR3dXjR5r");
30
+ });
31
+
32
+ it("derive m/1/0", () => {
33
+ const address = deriveAddress(derivationMode, xpub, 1, 0);
34
+ expect(address).toEqual("1GiCSuc1harcGUePV2EfZxmKoJou8V6KVE");
35
+ });
36
+
37
+ it("derive m/1/1", () => {
38
+ const address = deriveAddress(derivationMode, xpub, 1, 1);
39
+ expect(address).toEqual("1DfgByahHwa2rs8e5AQQ3EXGxS1akWpK8d");
40
+ });
41
+
42
+ it("derive m/1/10000000", () => {
43
+ const address = deriveAddress(derivationMode, xpub, 1, 10000000);
44
+ expect(address).toEqual("17Csc51yzoY74HNU6DLf3LcPNtNVf2JRhM");
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("3KwhDgypnTVdEDsF9PCDJcizjVWemGXB3X");
56
+ });
57
+
58
+ it("derive m/0/1", () => {
59
+ const address = deriveAddress(derivationMode, xpub, 0, 1);
60
+ expect(address).toEqual("33ZsFvSgNt5LfRZarSCiLFeGMdgtBsu5eN");
61
+ });
62
+
63
+ it("derive m/1/0", () => {
64
+ const address = deriveAddress(derivationMode, xpub, 1, 0);
65
+ expect(address).toEqual("3FJCQWSjxcRoE5KzEhtxUzD8NEgSMk5oXn");
66
+ });
67
+
68
+ it("derive m/1/1", () => {
69
+ const address = deriveAddress(derivationMode, xpub, 1, 1);
70
+ expect(address).toEqual("33uXGPKEbtNtxbvEJ6tJUcxWkxFRQDLtMP");
71
+ });
72
+
73
+ it("derive m/1/10000000", () => {
74
+ const address = deriveAddress(derivationMode, xpub, 1, 10000000);
75
+ expect(address).toEqual("35GUpR3pkEsUNV8n7mg67NqL9ctDs8q8z1");
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("bc1qvngxns2mvj00uptukvnh63apg6mg4ac3wan0xz");
87
+ });
88
+
89
+ it("derive m/0/1", () => {
90
+ const address = deriveAddress(derivationMode, xpub, 0, 1);
91
+ expect(address).toEqual("bc1qz2vselsfhyqckeelqgks4avuav95nkzc2gt092");
92
+ });
93
+
94
+ it("derive m/1/0", () => {
95
+ const address = deriveAddress(derivationMode, xpub, 1, 0);
96
+ expect(address).toEqual("bc1q43287ymsj3zeg3wvqv355yq8aa4yhwf998wmhj");
97
+ });
98
+
99
+ it("derive m/1/10000000", () => {
100
+ const address = deriveAddress(derivationMode, xpub, 1, 10000000);
101
+ expect(address).toEqual("bc1qgs8e92jz68wg9cn4uewasqc9e9hamfcexcnn82");
102
+ });
103
+ });
104
+ });
105
+
106
+ describe("derive Bitcoin testnet addresses", () => {
107
+ beforeEach(() => {
108
+ xpub =
109
+ "tpubDCCpYzH6NwKVnAipf8ChTfiTG4XtmxncwL97rQGLJ3SqfFCWzDq78LX1a7s2WXJsyfvR6bMiLkC7FSXLGoBo3dsH6DE9JKJb6LQSPasuSWj";
110
+ configuration.currency = currencies.btc;
111
+ configuration.currency.network = currencies.btc.network_testnet;
112
+ });
113
+
114
+ describe("derive Legacy addresses", () => {
115
+ beforeEach(() => {
116
+ derivationMode = DerivationMode.LEGACY;
117
+ });
118
+
119
+ it("derive m/0/0", () => {
120
+ const address = deriveAddress(derivationMode, xpub, 0, 0);
121
+ expect(address).toEqual("mmv9shvEyT8S3zvuCpjqqF66o4hbAcQuep");
122
+ });
123
+
124
+ it("derive m/0/1", () => {
125
+ const address = deriveAddress(derivationMode, xpub, 0, 1);
126
+ expect(address).toEqual("mgB5hxwThBUvZL9JaSKJ1M6vp8PcpkX4SK");
127
+ });
128
+
129
+ it("derive m/1/0", () => {
130
+ const address = deriveAddress(derivationMode, xpub, 1, 0);
131
+ expect(address).toEqual("mnUoHb6kCwnWmX7UoE4D4uiKH99VvPzXMg");
132
+ });
133
+
134
+ it("derive m/1/1", () => {
135
+ const address = deriveAddress(derivationMode, xpub, 1, 1);
136
+ expect(address).toEqual("mjUpakufYeoLDwMjqZd8nVxndMWAmACJ5M");
137
+ });
138
+
139
+ it("derive m/1/10000000", () => {
140
+ const address = deriveAddress(derivationMode, xpub, 1, 10000000);
141
+ expect(address).toEqual("mo2Ynyn89spBJNKqvC4Evq7w8fMs9KmSfD");
142
+ });
143
+ });
144
+
145
+ describe("derive SegWit addresses", () => {
146
+ beforeEach(() => {
147
+ derivationMode = DerivationMode.SEGWIT;
148
+ });
149
+
150
+ it("derive m/0/0", () => {
151
+ const address = deriveAddress(derivationMode, xpub, 0, 0);
152
+ expect(address).toEqual("2N8gfmL6ffuLTqrxie5GEJwhNahuoviWx51");
153
+ });
154
+
155
+ it("derive m/0/1", () => {
156
+ const address = deriveAddress(derivationMode, xpub, 0, 1);
157
+ expect(address).toEqual("2N5Aj5P7qZz26xS7FkvPPXzAL3KFu7nCNEa");
158
+ });
159
+
160
+ it("derive m/1/0", () => {
161
+ const address = deriveAddress(derivationMode, xpub, 1, 0);
162
+ expect(address).toEqual("2N4AwppWA11uaa17S92qoVGy4uHL5nYm9jq");
163
+ });
164
+
165
+ it("derive m/1/1", () => {
166
+ const address = deriveAddress(derivationMode, xpub, 1, 1);
167
+ expect(address).toEqual("2N1ec7LYa3cuXytxrUmJmWBE4gTkCaAvwf9");
168
+ });
169
+
170
+ it("derive m/1/10000000", () => {
171
+ const address = deriveAddress(derivationMode, xpub, 1, 10000000);
172
+ expect(address).toEqual("2Mz98kL4gs2gsZAhcBuCmT8SNBA6oXvDKaK");
173
+ });
174
+ });
175
+
176
+ describe("derive Native SegWit addresses", () => {
177
+ beforeEach(() => {
178
+ derivationMode = DerivationMode.NATIVE;
179
+ });
180
+
181
+ it("derive m/0/0", () => {
182
+ const address = deriveAddress(derivationMode, xpub, 0, 0);
183
+ expect(address).toEqual("tb1qgcel6r30c8pvjlplh9j3w55qnlv6r2dk5j9gv5");
184
+ });
185
+
186
+ it("derive m/0/1", () => {
187
+ const address = deriveAddress(derivationMode, xpub, 0, 1);
188
+ expect(address).toEqual("tb1qqu6luaj7pgl5del4lgp6mujr0nmlg0ktp4ju9r");
189
+ });
190
+
191
+ it("derive m/1/0", () => {
192
+ const address = deriveAddress(derivationMode, xpub, 1, 0);
193
+ expect(address).toEqual("tb1qf3sgwmmh8t9d640ea8hst058kryc9wm35twege");
194
+ });
195
+
196
+ it("derive m/1/1", () => {
197
+ const address = deriveAddress(derivationMode, xpub, 1, 1);
198
+ expect(address).toEqual("tb1q9dunhjjwxm8fx24hrxvvmxnt39d7tq0gfw8zlg");
199
+ });
200
+
201
+ it("derive m/1/10000000", () => {
202
+ const address = deriveAddress(derivationMode, xpub, 1, 10000000);
203
+ expect(address).toEqual("tb1q2fsmm5zz3258ulpquftfl2s0jeuzfhy9uwwwee");
204
+ });
205
+ });
206
+ });
207
+ });