@teleportdao/bitcoin 1.4.3 → 1.4.6
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/dist/bitcoin-base.d.ts +66 -53
- package/dist/bitcoin-base.d.ts.map +1 -1
- package/dist/bitcoin-base.js +47 -38
- package/dist/bitcoin-base.js.map +1 -1
- package/dist/bitcoin-interface-utils.d.ts +12 -10
- package/dist/bitcoin-interface-utils.d.ts.map +1 -1
- package/dist/bitcoin-interface-utils.js +16 -10
- package/dist/bitcoin-interface-utils.js.map +1 -1
- package/dist/bitcoin-interface.d.ts +206 -50
- package/dist/bitcoin-interface.d.ts.map +1 -1
- package/dist/bitcoin-interface.js +42 -27
- package/dist/bitcoin-interface.js.map +1 -1
- package/dist/bitcoin-utils.d.ts +111 -41
- package/dist/bitcoin-utils.d.ts.map +1 -1
- package/dist/bitcoin-utils.js +215 -156
- package/dist/bitcoin-utils.js.map +1 -1
- package/dist/bundle.js +13 -0
- package/dist/index.d.ts +5 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +32 -12
- package/dist/index.js.map +1 -1
- package/dist/sign/sign-transaction.d.ts +9 -5
- package/dist/sign/sign-transaction.d.ts.map +1 -1
- package/dist/sign/sign-transaction.js +14 -11
- package/dist/sign/sign-transaction.js.map +1 -1
- package/dist/teleport-dao-payments.d.ts +68 -89
- package/dist/teleport-dao-payments.d.ts.map +1 -1
- package/dist/teleport-dao-payments.js +16 -4
- package/dist/teleport-dao-payments.js.map +1 -1
- package/dist/transaction-builder/bitcoin-transaction-builder.d.ts +30 -11
- package/dist/transaction-builder/bitcoin-transaction-builder.d.ts.map +1 -1
- package/dist/transaction-builder/bitcoin-transaction-builder.js +37 -9
- package/dist/transaction-builder/bitcoin-transaction-builder.js.map +1 -1
- package/dist/transaction-builder/transaction-builder.d.ts +198 -9
- package/dist/transaction-builder/transaction-builder.d.ts.map +1 -1
- package/dist/transaction-builder/transaction-builder.js +291 -38
- package/dist/transaction-builder/transaction-builder.js.map +1 -1
- package/dist/utils/networks.d.ts +5 -35
- package/dist/utils/networks.d.ts.map +1 -1
- package/dist/utils/networks.js +26 -2
- package/dist/utils/networks.js.map +1 -1
- package/dist/utils/tools.d.ts +15 -9
- package/dist/utils/tools.d.ts.map +1 -1
- package/dist/utils/tools.js +14 -11
- package/dist/utils/tools.js.map +1 -1
- package/package.json +8 -6
- package/src/{bitcoin-base.js → bitcoin-base.ts} +248 -219
- package/src/{bitcoin-interface-utils.js → bitcoin-interface-utils.ts} +59 -53
- package/src/{bitcoin-interface.js → bitcoin-interface.ts} +420 -350
- package/src/{bitcoin-utils.js → bitcoin-utils.ts} +608 -483
- package/src/helper/teleport-request-helper.js +179 -179
- package/src/index.ts +5 -0
- package/src/sign/sign-transaction.ts +96 -0
- package/src/{teleport-dao-payments.js → teleport-dao-payments.ts} +341 -280
- package/src/transaction-builder/bitcoin-transaction-builder.ts +61 -0
- package/src/transaction-builder/transaction-builder.ts +567 -0
- package/src/utils/{networks.js → networks.ts} +33 -31
- package/src/utils/{tools.js → tools.ts} +80 -72
- package/tsconfig.json +10 -9
- package/webpack.config.js +16 -0
- package/dist/transaction-builder/transaction-builder-common.d.ts +0 -57
- package/dist/transaction-builder/transaction-builder-common.d.ts.map +0 -1
- package/dist/transaction-builder/transaction-builder-common.js +0 -183
- package/dist/transaction-builder/transaction-builder-common.js.map +0 -1
- package/src/index.js +0 -15
- package/src/sign/sign-transaction.js +0 -36
- package/src/transaction-builder/bitcoin-transaction-builder.js +0 -37
- package/src/transaction-builder/transaction-builder-common.js +0 -236
- package/src/transaction-builder/transaction-builder.js +0 -159
|
@@ -1,483 +1,608 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
let
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
let
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
let
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
)
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
let
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
merkleRoot
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
})
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
) {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
if (
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
txId: tx.getId(),
|
|
366
|
-
version: tx.version,
|
|
367
|
-
locktime: tx.locktime,
|
|
368
|
-
blockNumber,
|
|
369
|
-
blockHash,
|
|
370
|
-
merkleProof: txMerkleProof,
|
|
371
|
-
vout: tx.outs.map((vo) => ({
|
|
372
|
-
address: convertBitcoinScriptToAddress(vo.script, network),
|
|
373
|
-
script: vo.script.toString("hex"),
|
|
374
|
-
value: vo.value,
|
|
375
|
-
})),
|
|
376
|
-
vin: tx.ins.map((vi) => {
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
let
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
1
|
+
import * as bip39 from "bip39"
|
|
2
|
+
import * as bip32 from "bip32"
|
|
3
|
+
import networks from "./utils/networks"
|
|
4
|
+
|
|
5
|
+
// import BIP32Factory from "bip32"
|
|
6
|
+
// import ECPairFactory from "ecpair"
|
|
7
|
+
// import * as ecc from "tiny-secp256k1"
|
|
8
|
+
import * as bitcoin from "bitcoinjs-lib"
|
|
9
|
+
|
|
10
|
+
// bitcoin.initEccLib(ecc)
|
|
11
|
+
// const bip32 = BIP32Factory(ecc)
|
|
12
|
+
const ECPair = bitcoin.ECPair
|
|
13
|
+
|
|
14
|
+
let varUnit = require("varuint-bitcoin")
|
|
15
|
+
const fastRoot = require("merkle-lib/fastRoot")
|
|
16
|
+
const merkle = require("merkle-lib")
|
|
17
|
+
const merkleProof = require("merkle-lib/proof")
|
|
18
|
+
|
|
19
|
+
// const bip32Prefix = {
|
|
20
|
+
// xprv: "0x0488ade4", // Mainnet - P2PKH or P2SH - m/44'/0'
|
|
21
|
+
// yprv: "0x049d7878", // Mainnet - P2WPKH in P2SH - m/49'/0'
|
|
22
|
+
// zprv: "0x04b2430c", // Mainnet - P2WPKH - m/84'/0'
|
|
23
|
+
// Yprv: "0x0295b005", // Mainnet - Multi-signature P2WSH in P2SH
|
|
24
|
+
// Zprv: "0x02aa7a99", // Mainnet - Multi-signature P2WSH
|
|
25
|
+
// tprv: "0x04358394", // Testnet - P2PKH or P2SH - m/44'/1'
|
|
26
|
+
// uprv: "0x044a4e28", // Testnet - P2WPKH in P2SH - m/49'/1'
|
|
27
|
+
// vprv: "0x045f18bc", // Testnet - P2WPKH - m/84'/1'
|
|
28
|
+
// Uprv: "0x024285b5", // Testnet - Multi-signature P2WSH in P2SH
|
|
29
|
+
// Vprv: "0x02575048", // Testnet - Multi-signature P2WSH
|
|
30
|
+
|
|
31
|
+
// xpub: "0x0488b21e", // Mainnet - P2PKH or P2SH - m/44'/0'
|
|
32
|
+
// ypub: "0x049d7cb2", // Mainnet - P2WPKH in P2SH - m/49'/0'
|
|
33
|
+
// zpub: "0x04b24746", // Mainnet - P2WPKH - m/84'/0'
|
|
34
|
+
// Ypub: "0x0295b43f", // Mainnet - Multi-signature P2WSH in P2SH
|
|
35
|
+
// Zpub: "0x02aa7ed3", // Mainnet - Multi-signature P2WSH
|
|
36
|
+
// tpub: "0x043587cf", // Testnet - P2PKH or P2SH - m/44'/1'
|
|
37
|
+
// upub: "0x044a5262", // Testnet - P2WPKH in P2SH - m/49'/1'
|
|
38
|
+
// vpub: "0x045f1cf6", // Testnet - P2WPKH - m/84'/1'
|
|
39
|
+
// Upub: "0x024289ef", // Testnet - Multi-signature P2WSH in P2SH
|
|
40
|
+
// Vpub: "0x02575483", // Testnet - Multi-signature P2WSH
|
|
41
|
+
// }
|
|
42
|
+
export { networks }
|
|
43
|
+
|
|
44
|
+
export function generateMnemonic() {
|
|
45
|
+
const mnemonic = bip39.generateMnemonic(256)
|
|
46
|
+
return mnemonic
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function parseRawTransaction(rawTransaction: string) {
|
|
50
|
+
const size = {
|
|
51
|
+
version: 4,
|
|
52
|
+
flag: 2,
|
|
53
|
+
tx: 32,
|
|
54
|
+
index: 4,
|
|
55
|
+
sequence: 4,
|
|
56
|
+
amount: 8,
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let offset = 0
|
|
60
|
+
let version = rawTransaction.slice(offset, size.version * 2)
|
|
61
|
+
offset += size.version * 2
|
|
62
|
+
let flag = rawTransaction.slice(offset, offset + size.flag * 2)
|
|
63
|
+
offset = flag === "0001" ? offset + size.flag * 2 : offset // * 0x0001 is flag in segwit transactions
|
|
64
|
+
|
|
65
|
+
let inputsStartIndex = offset
|
|
66
|
+
|
|
67
|
+
let numberOfInputs = varUnit.decode(Buffer.from(rawTransaction.slice(offset), "hex"))
|
|
68
|
+
let noiSize = varUnit.encodingLength(numberOfInputs)
|
|
69
|
+
offset += noiSize * 2
|
|
70
|
+
|
|
71
|
+
for (let i = 0; i < numberOfInputs; i += 1) {
|
|
72
|
+
offset += size.tx * 2
|
|
73
|
+
offset += size.index * 2
|
|
74
|
+
let sigLength = varUnit.decode(Buffer.from(rawTransaction.slice(offset), "hex"))
|
|
75
|
+
let sigLengthSize = varUnit.encodingLength(sigLength)
|
|
76
|
+
offset += sigLengthSize * 2
|
|
77
|
+
offset += sigLength * 2
|
|
78
|
+
offset += size.sequence * 2
|
|
79
|
+
}
|
|
80
|
+
let inputLastIndex = offset
|
|
81
|
+
let outputStartIndex = offset
|
|
82
|
+
|
|
83
|
+
let numberOfOutputs = varUnit.decode(Buffer.from(rawTransaction.slice(offset), "hex"))
|
|
84
|
+
let nooSize = varUnit.encodingLength(numberOfOutputs)
|
|
85
|
+
offset += nooSize * 2
|
|
86
|
+
|
|
87
|
+
for (let i = 0; i < numberOfOutputs; i += 1) {
|
|
88
|
+
offset += size.amount * 2
|
|
89
|
+
let unlockSigLength = varUnit.decode(Buffer.from(rawTransaction.slice(offset), "hex"))
|
|
90
|
+
let unlockSigLengthSize = varUnit.encodingLength(unlockSigLength)
|
|
91
|
+
offset += unlockSigLengthSize * 2
|
|
92
|
+
offset += unlockSigLength * 2
|
|
93
|
+
}
|
|
94
|
+
let outputLastIndex = offset
|
|
95
|
+
|
|
96
|
+
version = `0x${version}`
|
|
97
|
+
flag = `0x${flag}`
|
|
98
|
+
const vin = `0x${rawTransaction.slice(inputsStartIndex, inputLastIndex)}`
|
|
99
|
+
const vout = `0x${rawTransaction.slice(outputStartIndex, outputLastIndex)}`
|
|
100
|
+
let witness = `0x${rawTransaction.slice(outputLastIndex, rawTransaction.length - 8)}`
|
|
101
|
+
let locktime = `0x${rawTransaction.slice(rawTransaction.length - 8, rawTransaction.length)}`
|
|
102
|
+
return { version, flag, vin, vout, witness, locktime }
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function reverseBytes(hexInput: string) {
|
|
106
|
+
return Buffer.from(hexInput, "hex").reverse().toString("hex")
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function getPublicKeyHexByXpubAndIndex(
|
|
110
|
+
xpub: string,
|
|
111
|
+
index = 0,
|
|
112
|
+
isChange = false,
|
|
113
|
+
network = networks.bitcoin,
|
|
114
|
+
) {
|
|
115
|
+
const node = bip32.fromBase58(xpub, network)
|
|
116
|
+
return node
|
|
117
|
+
.derive(isChange ? 1 : 0)
|
|
118
|
+
.derive(index)
|
|
119
|
+
.publicKey.toString("hex")
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function getPubKeyFromPrivateKeyWIF(
|
|
123
|
+
privateKeyWIF: string,
|
|
124
|
+
network = bitcoin.networks.bitcoin,
|
|
125
|
+
) {
|
|
126
|
+
let key = bitcoin.ECPair.fromWIF(privateKeyWIF, network)
|
|
127
|
+
return key.publicKey
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function getPubKeyFromPrivateKeyHex(
|
|
131
|
+
privateKeyHex: string,
|
|
132
|
+
network = bitcoin.networks.bitcoin,
|
|
133
|
+
) {
|
|
134
|
+
let key = bitcoin.ECPair.fromPrivateKey(Buffer.from(privateKeyHex, "hex"), { network })
|
|
135
|
+
return key.publicKey
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function getPrivateKeyHexFromWIF(privateKeyWIF: string, network = bitcoin.networks.bitcoin) {
|
|
139
|
+
let key = bitcoin.ECPair.fromWIF(privateKeyWIF, network)
|
|
140
|
+
return key.privateKey!.toString("hex")
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export function calculateMerkleProof(
|
|
144
|
+
blockTransactions: string[],
|
|
145
|
+
txId: string,
|
|
146
|
+
blockMerkleRoot?: string,
|
|
147
|
+
) {
|
|
148
|
+
let transactionIndex = blockTransactions.findIndex((tx) => tx === txId)
|
|
149
|
+
if (transactionIndex < 0) throw new Error("txId is not in this tree")
|
|
150
|
+
let data = blockTransactions.map((a) => Buffer.from(a, "hex").reverse())
|
|
151
|
+
|
|
152
|
+
if (
|
|
153
|
+
blockMerkleRoot &&
|
|
154
|
+
blockMerkleRoot !== fastRoot(data, bitcoin.crypto.hash256).toString("hex")
|
|
155
|
+
) {
|
|
156
|
+
throw new Error("calculated merkleRoot and block merkleRoot not matched")
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
let tree = merkle(data, bitcoin.crypto.hash256)
|
|
160
|
+
let proof = merkleProof(tree, data[transactionIndex])
|
|
161
|
+
|
|
162
|
+
let intermediateNodesArray = proof
|
|
163
|
+
.map((_id?: Buffer) => _id && _id.toString("hex"))
|
|
164
|
+
.filter((_id?: Buffer) => _id != null)
|
|
165
|
+
let intermediateNodes: string = intermediateNodesArray.reduce(
|
|
166
|
+
(a: string, value: string, index: number) =>
|
|
167
|
+
index !== transactionIndex % 2 && index < intermediateNodesArray.length - 1 ? a + value : a,
|
|
168
|
+
"0x",
|
|
169
|
+
)
|
|
170
|
+
return {
|
|
171
|
+
intermediateNodes,
|
|
172
|
+
transactionIndex,
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export function parseBlockHeader(headerHex: string) {
|
|
177
|
+
const size: {
|
|
178
|
+
[key: string]: number
|
|
179
|
+
} = {
|
|
180
|
+
version: 4,
|
|
181
|
+
previousBlockHash: 32,
|
|
182
|
+
merkleRoot: 32,
|
|
183
|
+
timestamp: 4,
|
|
184
|
+
difficulty: 4,
|
|
185
|
+
nonce: 4,
|
|
186
|
+
}
|
|
187
|
+
let offset = 0
|
|
188
|
+
let result: {
|
|
189
|
+
[key: string]: string
|
|
190
|
+
} = {}
|
|
191
|
+
for (let key in size) {
|
|
192
|
+
result[key] = headerHex.slice(offset, offset + size[key] * 2)
|
|
193
|
+
offset += size[key] * 2
|
|
194
|
+
}
|
|
195
|
+
return result as {
|
|
196
|
+
version: string
|
|
197
|
+
previousBlockHash: string
|
|
198
|
+
merkleRoot: string
|
|
199
|
+
timestamp: string
|
|
200
|
+
difficulty: string
|
|
201
|
+
nonce: string
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export function convertBitcoinScriptToAddress(script: Buffer, network = bitcoin.networks.bitcoin) {
|
|
206
|
+
try {
|
|
207
|
+
return bitcoin.address.fromOutputScript(script, network)
|
|
208
|
+
} catch (error) {
|
|
209
|
+
return null
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export function parseRawBlock(
|
|
214
|
+
rawBlockHex: string,
|
|
215
|
+
blockNumber?: number,
|
|
216
|
+
network = bitcoin.networks.bitcoin,
|
|
217
|
+
) {
|
|
218
|
+
let block = bitcoin.Block.fromBuffer(Buffer.from(rawBlockHex, "hex"))
|
|
219
|
+
let blockHash = block.getHash().toString("hex")
|
|
220
|
+
let merkleRoot = block.merkleRoot!.toString("hex")
|
|
221
|
+
let prvBlockHash = block.prevHash!.toString("hex")
|
|
222
|
+
return {
|
|
223
|
+
blockNumber,
|
|
224
|
+
merkleRoot,
|
|
225
|
+
prvBlockHash,
|
|
226
|
+
transactions: block.transactions?.map((tx) => ({
|
|
227
|
+
txId: tx.getId(),
|
|
228
|
+
version: tx.version,
|
|
229
|
+
locktime: tx.locktime,
|
|
230
|
+
blockNumber,
|
|
231
|
+
blockHash,
|
|
232
|
+
vout: tx.outs.map((vo, index) => ({
|
|
233
|
+
address: convertBitcoinScriptToAddress(vo.script, network),
|
|
234
|
+
script: vo.script.toString("hex"),
|
|
235
|
+
value: vo.value,
|
|
236
|
+
index,
|
|
237
|
+
})),
|
|
238
|
+
vin: tx.ins.map((vi) => ({
|
|
239
|
+
txId: Buffer.from(vi.hash).reverse().toString("hex"),
|
|
240
|
+
index: vi.index,
|
|
241
|
+
})),
|
|
242
|
+
})),
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export function extractTransactionsAndBlockInfoFromRawBlock(
|
|
247
|
+
rawBlockHex: string,
|
|
248
|
+
blockNumber: number,
|
|
249
|
+
addresses: string[] = [],
|
|
250
|
+
inputTxIds: {
|
|
251
|
+
txId: string
|
|
252
|
+
index: number
|
|
253
|
+
address?: string
|
|
254
|
+
script?: string
|
|
255
|
+
value?: number
|
|
256
|
+
}[] = [],
|
|
257
|
+
network = bitcoin.networks.bitcoin,
|
|
258
|
+
) {
|
|
259
|
+
let block = bitcoin.Block.fromBuffer(Buffer.from(rawBlockHex, "hex"))
|
|
260
|
+
let blockHash = block.getHash().reverse().toString("hex")
|
|
261
|
+
let merkleRoot = block.merkleRoot!.toString("hex")
|
|
262
|
+
let prvBlockHash = block.prevHash!.toString("hex")
|
|
263
|
+
|
|
264
|
+
let blockInfo = {
|
|
265
|
+
blockNumber,
|
|
266
|
+
blockHash,
|
|
267
|
+
merkleRoot,
|
|
268
|
+
prvBlockHash,
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
let addressScript = addresses.map((address) =>
|
|
272
|
+
createAddressObjectByAddress(address, network).addressObject.output!.toString("hex"),
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
let blockTxIds = block.transactions!.map((tx) => tx.getId())
|
|
276
|
+
|
|
277
|
+
type Transaction = {
|
|
278
|
+
txId: string
|
|
279
|
+
version: number
|
|
280
|
+
locktime: number
|
|
281
|
+
blockNumber: number
|
|
282
|
+
blockHash: string
|
|
283
|
+
merkleProof: {
|
|
284
|
+
intermediateNodes: string
|
|
285
|
+
transactionIndex: number
|
|
286
|
+
}
|
|
287
|
+
vout: {
|
|
288
|
+
address: string | null
|
|
289
|
+
script: string
|
|
290
|
+
value: number
|
|
291
|
+
}[]
|
|
292
|
+
vin: {
|
|
293
|
+
txId: string
|
|
294
|
+
index: number
|
|
295
|
+
address?: string | null
|
|
296
|
+
script?: string | null
|
|
297
|
+
value?: number | null
|
|
298
|
+
}[]
|
|
299
|
+
address: string
|
|
300
|
+
addressScript: string
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
let withdrawTxs: Transaction[] = []
|
|
304
|
+
let depositTxs: Transaction[] = []
|
|
305
|
+
block.transactions?.forEach((tx) => {
|
|
306
|
+
let txId = tx.getId()
|
|
307
|
+
|
|
308
|
+
let inputTxAddress: string | undefined
|
|
309
|
+
let isWithdraw = tx.ins.find((vi) => {
|
|
310
|
+
let viTxId = Buffer.from(vi.hash).reverse().toString("hex")
|
|
311
|
+
let viInput = inputTxIds.find((vin) => vin.txId === viTxId && vin.index === vi.index)
|
|
312
|
+
inputTxAddress = viInput?.address
|
|
313
|
+
return !!inputTxAddress
|
|
314
|
+
})
|
|
315
|
+
if (isWithdraw && inputTxAddress) {
|
|
316
|
+
let txMerkleProof = calculateMerkleProof(blockTxIds, txId, merkleRoot)
|
|
317
|
+
|
|
318
|
+
withdrawTxs.push({
|
|
319
|
+
txId: tx.getId(),
|
|
320
|
+
version: tx.version,
|
|
321
|
+
locktime: tx.locktime,
|
|
322
|
+
blockNumber,
|
|
323
|
+
blockHash,
|
|
324
|
+
merkleProof: txMerkleProof,
|
|
325
|
+
vout: tx.outs.map((vo) => ({
|
|
326
|
+
address: convertBitcoinScriptToAddress(vo.script, network),
|
|
327
|
+
script: vo.script.toString("hex"),
|
|
328
|
+
value: vo.value,
|
|
329
|
+
})),
|
|
330
|
+
vin: tx.ins.map((vi) => {
|
|
331
|
+
let viTxId = Buffer.from(vi.hash).reverse().toString("hex")
|
|
332
|
+
let viInput = inputTxIds.find((vin) => vin.txId === viTxId && vin.index === vi.index)
|
|
333
|
+
return {
|
|
334
|
+
txId: Buffer.from(vi.hash).reverse().toString("hex"),
|
|
335
|
+
index: vi.index,
|
|
336
|
+
address: viInput?.address || null,
|
|
337
|
+
script: viInput?.script || null,
|
|
338
|
+
value: viInput?.value || null,
|
|
339
|
+
}
|
|
340
|
+
}),
|
|
341
|
+
address: inputTxAddress,
|
|
342
|
+
addressScript: createAddressObjectByAddress(
|
|
343
|
+
inputTxAddress,
|
|
344
|
+
network,
|
|
345
|
+
).addressObject.output!.toString("hex"),
|
|
346
|
+
})
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
let addressIndex: number = -1
|
|
350
|
+
let isDeposit = tx.outs.find((blockTxVo) => {
|
|
351
|
+
let sIndex = addressScript.findIndex(
|
|
352
|
+
(addScript) => addScript === blockTxVo.script.toString("hex"),
|
|
353
|
+
)
|
|
354
|
+
if (sIndex >= 0) {
|
|
355
|
+
addressIndex = sIndex
|
|
356
|
+
return true
|
|
357
|
+
}
|
|
358
|
+
return false
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
if (isDeposit && addressIndex >= 0) {
|
|
362
|
+
// todo we can optimize this calculation (in following function, merkle tree calculate each times but we can do this once for block)
|
|
363
|
+
let txMerkleProof = calculateMerkleProof(blockTxIds, txId, merkleRoot)
|
|
364
|
+
depositTxs.push({
|
|
365
|
+
txId: tx.getId(),
|
|
366
|
+
version: tx.version,
|
|
367
|
+
locktime: tx.locktime,
|
|
368
|
+
blockNumber,
|
|
369
|
+
blockHash,
|
|
370
|
+
merkleProof: txMerkleProof,
|
|
371
|
+
vout: tx.outs.map((vo) => ({
|
|
372
|
+
address: convertBitcoinScriptToAddress(vo.script, network),
|
|
373
|
+
script: vo.script.toString("hex"),
|
|
374
|
+
value: vo.value,
|
|
375
|
+
})),
|
|
376
|
+
vin: tx.ins.map((vi) => ({
|
|
377
|
+
txId: Buffer.from(vi.hash).reverse().toString("hex"),
|
|
378
|
+
index: vi.index,
|
|
379
|
+
})),
|
|
380
|
+
addressScript: addressScript[addressIndex],
|
|
381
|
+
address: addresses[addressIndex],
|
|
382
|
+
})
|
|
383
|
+
}
|
|
384
|
+
})
|
|
385
|
+
return {
|
|
386
|
+
blockInfo,
|
|
387
|
+
withdrawTxs,
|
|
388
|
+
depositTxs,
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
export function validateAddress(address: string, network = bitcoin.networks.bitcoin) {
|
|
393
|
+
try {
|
|
394
|
+
let isValid = false
|
|
395
|
+
let isAddressSegwit = address.startsWith(network.bech32)
|
|
396
|
+
if (isAddressSegwit) {
|
|
397
|
+
bitcoin.address.fromBech32(address)
|
|
398
|
+
isValid = true
|
|
399
|
+
} else {
|
|
400
|
+
let base58Data = bitcoin.address.fromBase58Check(address)
|
|
401
|
+
isValid =
|
|
402
|
+
base58Data.version === Number(network.scriptHash) ||
|
|
403
|
+
base58Data.version === Number(network.pubKeyHash)
|
|
404
|
+
}
|
|
405
|
+
return isValid
|
|
406
|
+
} catch (error) {
|
|
407
|
+
return false
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
function toXOnlyPublicKey(pubKey: Buffer) {
|
|
412
|
+
return pubKey.length === 32 ? pubKey : pubKey.slice(1, 33)
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
export function getAddressType(address: string, network = bitcoin.networks.bitcoin) {
|
|
416
|
+
if (address.startsWith(`${network.bech32}1p`)) {
|
|
417
|
+
// todo : check length - it could be p2wsh
|
|
418
|
+
return "p2tr"
|
|
419
|
+
}
|
|
420
|
+
if (address.startsWith(network.bech32)) {
|
|
421
|
+
// todo : check length - it could be p2wsh
|
|
422
|
+
return "p2wpkh"
|
|
423
|
+
}
|
|
424
|
+
let base58Data = bitcoin.address.fromBase58Check(address)
|
|
425
|
+
if (base58Data.version === Number(network.scriptHash)) {
|
|
426
|
+
return "p2sh"
|
|
427
|
+
}
|
|
428
|
+
if (base58Data.version === Number(network.pubKeyHash)) {
|
|
429
|
+
return "p2pkh"
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
throw new Error("invalid address")
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
export function createAddressObjectByScript(
|
|
436
|
+
{ addressType, script }: { addressType: string; script: Buffer },
|
|
437
|
+
network: bitcoin.Network = bitcoin.networks.bitcoin,
|
|
438
|
+
) {
|
|
439
|
+
let addressObject
|
|
440
|
+
switch (addressType) {
|
|
441
|
+
case "p2pkh":
|
|
442
|
+
addressObject = bitcoin.payments.p2pkh({
|
|
443
|
+
output: script,
|
|
444
|
+
network,
|
|
445
|
+
})
|
|
446
|
+
break
|
|
447
|
+
case "p2wpkh":
|
|
448
|
+
addressObject = bitcoin.payments.p2wpkh({
|
|
449
|
+
output: script,
|
|
450
|
+
network,
|
|
451
|
+
})
|
|
452
|
+
break
|
|
453
|
+
case "p2sh":
|
|
454
|
+
addressObject = bitcoin.payments.p2sh({
|
|
455
|
+
output: script,
|
|
456
|
+
network,
|
|
457
|
+
})
|
|
458
|
+
break
|
|
459
|
+
case "p2wsh":
|
|
460
|
+
addressObject = bitcoin.payments.p2wsh({
|
|
461
|
+
output: script,
|
|
462
|
+
network,
|
|
463
|
+
})
|
|
464
|
+
break
|
|
465
|
+
// case "p2tr":
|
|
466
|
+
// addressObject = bitcoin.payments.p2tr({
|
|
467
|
+
// output: script,
|
|
468
|
+
// network,
|
|
469
|
+
// })
|
|
470
|
+
// break
|
|
471
|
+
default:
|
|
472
|
+
throw new Error("address type is incorrect")
|
|
473
|
+
}
|
|
474
|
+
return addressObject
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
export function createAddressObjectByHash(
|
|
478
|
+
{ addressType, hash }: { addressType: string; hash: Buffer },
|
|
479
|
+
network: bitcoin.Network = bitcoin.networks.bitcoin,
|
|
480
|
+
) {
|
|
481
|
+
let addressObject
|
|
482
|
+
switch (addressType) {
|
|
483
|
+
case "p2pkh":
|
|
484
|
+
addressObject = bitcoin.payments.p2pkh({
|
|
485
|
+
hash,
|
|
486
|
+
network,
|
|
487
|
+
})
|
|
488
|
+
break
|
|
489
|
+
case "p2wpkh":
|
|
490
|
+
addressObject = bitcoin.payments.p2wpkh({
|
|
491
|
+
hash,
|
|
492
|
+
network,
|
|
493
|
+
})
|
|
494
|
+
break
|
|
495
|
+
case "p2sh":
|
|
496
|
+
addressObject = bitcoin.payments.p2sh({
|
|
497
|
+
hash,
|
|
498
|
+
network,
|
|
499
|
+
})
|
|
500
|
+
break
|
|
501
|
+
case "p2wsh":
|
|
502
|
+
addressObject = bitcoin.payments.p2wsh({
|
|
503
|
+
hash,
|
|
504
|
+
network,
|
|
505
|
+
})
|
|
506
|
+
break
|
|
507
|
+
// case "p2tr":
|
|
508
|
+
// // here hash is the public key of tweaked private key
|
|
509
|
+
// addressObject = bitcoin.payments.p2tr({
|
|
510
|
+
// pubkey: hash,
|
|
511
|
+
// network,
|
|
512
|
+
// })
|
|
513
|
+
// break
|
|
514
|
+
default:
|
|
515
|
+
throw new Error("address type is incorrect")
|
|
516
|
+
}
|
|
517
|
+
return addressObject
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
export function createAddressObjectByPublicKey(
|
|
521
|
+
{ addressType, publicKey }: { addressType: string; publicKey: Buffer },
|
|
522
|
+
network: bitcoin.Network = bitcoin.networks.bitcoin,
|
|
523
|
+
): bitcoin.payments.Payment {
|
|
524
|
+
let addressObject
|
|
525
|
+
switch (addressType) {
|
|
526
|
+
case "p2pkh":
|
|
527
|
+
addressObject = bitcoin.payments.p2pkh({
|
|
528
|
+
pubkey: publicKey,
|
|
529
|
+
network,
|
|
530
|
+
})
|
|
531
|
+
break
|
|
532
|
+
case "p2wpkh":
|
|
533
|
+
addressObject = bitcoin.payments.p2wpkh({
|
|
534
|
+
pubkey: publicKey,
|
|
535
|
+
network,
|
|
536
|
+
})
|
|
537
|
+
break
|
|
538
|
+
case "p2sh-p2wpkh":
|
|
539
|
+
addressObject = bitcoin.payments.p2sh({
|
|
540
|
+
redeem: bitcoin.payments.p2wpkh({
|
|
541
|
+
pubkey: publicKey,
|
|
542
|
+
network,
|
|
543
|
+
}),
|
|
544
|
+
})
|
|
545
|
+
break
|
|
546
|
+
case "p2tr":
|
|
547
|
+
// // this public key is public key of main private key
|
|
548
|
+
// addressObject = bitcoin.payments.p2tr({
|
|
549
|
+
// internalPubkey: toXOnlyPublicKey(publicKey),
|
|
550
|
+
// network,
|
|
551
|
+
// })
|
|
552
|
+
// break
|
|
553
|
+
default:
|
|
554
|
+
throw new Error("address type is incorrect")
|
|
555
|
+
}
|
|
556
|
+
return addressObject
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
export function createAddressObjectByAddress(address: string, network = bitcoin.networks.bitcoin) {
|
|
560
|
+
let addressType = getAddressType(address, network)
|
|
561
|
+
let addressObject
|
|
562
|
+
switch (addressType) {
|
|
563
|
+
case "p2pkh":
|
|
564
|
+
addressObject = bitcoin.payments.p2pkh({
|
|
565
|
+
address,
|
|
566
|
+
network,
|
|
567
|
+
})
|
|
568
|
+
break
|
|
569
|
+
case "p2wpkh":
|
|
570
|
+
addressObject = bitcoin.payments.p2wpkh({
|
|
571
|
+
address,
|
|
572
|
+
network,
|
|
573
|
+
})
|
|
574
|
+
break
|
|
575
|
+
case "p2sh":
|
|
576
|
+
addressObject = bitcoin.payments.p2sh({
|
|
577
|
+
address,
|
|
578
|
+
network,
|
|
579
|
+
})
|
|
580
|
+
break
|
|
581
|
+
// case "p2tr":
|
|
582
|
+
// addressObject = bitcoin.payments.p2tr({
|
|
583
|
+
// address,
|
|
584
|
+
// network,
|
|
585
|
+
// })
|
|
586
|
+
// break
|
|
587
|
+
default:
|
|
588
|
+
throw new Error("address type is incorrect")
|
|
589
|
+
}
|
|
590
|
+
return { addressObject, addressType }
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
export function publicKeyConvertor(publicKeyHex: string, compressed = true) {
|
|
594
|
+
let pubkey = ECPair.fromPublicKey(Buffer.from(publicKeyHex, "hex"), {
|
|
595
|
+
compressed,
|
|
596
|
+
})
|
|
597
|
+
return pubkey.publicKey.toString("hex")
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
export const addressTypeHelper: {
|
|
601
|
+
addressTypesNumber: {
|
|
602
|
+
[key: string]: number
|
|
603
|
+
}
|
|
604
|
+
addressTypes: string[]
|
|
605
|
+
} = {
|
|
606
|
+
addressTypesNumber: { p2pk: 0, p2pkh: 1, p2sh: 2, p2wpkh: 3, p2wsh: 4, p2tr: 5 },
|
|
607
|
+
addressTypes: ["p2pk", "p2pkh", "p2sh", "p2wpkh", "p2wsh", "p2tr"],
|
|
608
|
+
}
|