@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.
- package/.claude/settings.local.json +8 -0
- package/CONTRIBUTING.md +130 -0
- package/LICENSE +23 -0
- package/README.md +215 -0
- package/__tests__/checkAddresses/checkBitcoinAddressesNegative.test.ts +75 -0
- package/__tests__/checkAddresses/checkBitcoinAddressesPositive.test.ts +87 -0
- package/__tests__/checkAddresses/checkDogeAddressesPositive.test.ts +43 -0
- package/__tests__/checkAddresses/checkLitecoinAddressesNegative.test.ts +75 -0
- package/__tests__/checkAddresses/checkLitecoinAddressesPositive.test.ts +87 -0
- package/__tests__/checkModels/address.test.ts +183 -0
- package/__tests__/checkModels/fakeRawTransactions.json +182 -0
- package/__tests__/deriveAddresses/deriveBitcoinAddresses.test.ts +207 -0
- package/__tests__/deriveAddresses/deriveBitcoinCashAddresses.test copy.ts +79 -0
- package/__tests__/deriveAddresses/deriveDogecoinAddresses.test.ts +43 -0
- package/__tests__/deriveAddresses/deriveEthereumAddresses.test.ts +26 -0
- package/__tests__/deriveAddresses/deriveLitecoinAddresses.test.ts +110 -0
- package/__tests__/helpers.test.ts +274 -0
- package/__tests__/test-utils.ts +3 -0
- package/babel.config.js +6 -0
- package/jest.config.ts +5 -0
- package/ledgerhq-xpub-scan-1.0.4.tgz +0 -0
- package/lib/actions/checkAddress.d.ts +29 -0
- package/lib/actions/checkAddress.js +122 -0
- package/lib/actions/checkBalance.d.ts +20 -0
- package/lib/actions/checkBalance.js +300 -0
- package/lib/actions/deriveAddresses.d.ts +17 -0
- package/lib/actions/deriveAddresses.js +239 -0
- package/lib/actions/processTransactions.d.ts +29 -0
- package/lib/actions/processTransactions.js +289 -0
- package/lib/actions/saveAnalysis.d.ts +2 -0
- package/lib/actions/saveAnalysis.js +800 -0
- package/lib/actions/scanner.d.ts +15 -0
- package/lib/actions/scanner.js +152 -0
- package/lib/api/customProvider.d.ts +19 -0
- package/lib/api/customProvider.js +434 -0
- package/lib/api/defaultProvider.d.ts +23 -0
- package/lib/api/defaultProvider.js +275 -0
- package/lib/comparison/compareOperations.d.ts +13 -0
- package/lib/comparison/compareOperations.js +500 -0
- package/lib/comparison/diffs.d.ts +18 -0
- package/lib/comparison/diffs.js +70 -0
- package/lib/configuration/currencies.d.ts +55 -0
- package/lib/configuration/currencies.js +72 -0
- package/lib/configuration/settings.d.ts +51 -0
- package/lib/configuration/settings.js +113 -0
- package/lib/display.d.ts +12 -0
- package/lib/display.js +251 -0
- package/lib/helpers.d.ts +27 -0
- package/lib/helpers.js +255 -0
- package/lib/input/args.d.ts +6 -0
- package/lib/input/args.js +129 -0
- package/lib/input/check.d.ts +6 -0
- package/lib/input/check.js +217 -0
- package/lib/input/importOperations.d.ts +11 -0
- package/lib/input/importOperations.js +406 -0
- package/lib/models/address.d.ts +40 -0
- package/lib/models/address.js +101 -0
- package/lib/models/comparison.d.ts +8 -0
- package/lib/models/comparison.js +6 -0
- package/lib/models/currency.d.ts +11 -0
- package/lib/models/currency.js +6 -0
- package/lib/models/operation.d.ts +33 -0
- package/lib/models/operation.js +80 -0
- package/lib/models/ownAddresses.d.ts +11 -0
- package/lib/models/ownAddresses.js +31 -0
- package/lib/models/scanLimits.d.ts +7 -0
- package/lib/models/scanLimits.js +6 -0
- package/lib/models/stats.d.ts +7 -0
- package/lib/models/stats.js +6 -0
- package/lib/models/transaction.d.ts +10 -0
- package/lib/models/transaction.js +13 -0
- package/lib/scan.d.ts +2 -0
- package/lib/scan.js +31 -0
- package/lib/templates/logos.base64.d.ts +2 -0
- package/lib/templates/logos.base64.js +9 -0
- package/lib/templates/report.html.d.ts +1 -0
- package/lib/templates/report.html.js +393 -0
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/lib/types.d.ts +55 -0
- package/lib/types.js +2 -0
- package/npm-shrinkwrap.json +12323 -0
- package/package.json +81 -0
- 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
|
+
});
|