@teleportdao/bitcoin 2.3.0-alpha.0 → 3.0.3
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-interface-utils.d.ts +0 -4
- package/dist/bitcoin-interface-utils.d.ts.map +1 -1
- package/dist/bitcoin-interface-utils.js +0 -4
- package/dist/bitcoin-interface-utils.js.map +1 -1
- package/dist/bitcoin-utils.d.ts +1 -5
- package/dist/bitcoin-utils.d.ts.map +1 -1
- package/dist/bitcoin-utils.js +2 -44
- package/dist/bitcoin-utils.js.map +1 -1
- package/dist/bitcoin-wallet-base.d.ts +8 -18
- package/dist/bitcoin-wallet-base.d.ts.map +1 -1
- package/dist/bitcoin-wallet-base.js +13 -33
- package/dist/bitcoin-wallet-base.js.map +1 -1
- package/dist/multisig-wallet-helper.d.ts +46 -0
- package/dist/multisig-wallet-helper.d.ts.map +1 -0
- package/dist/multisig-wallet-helper.js +203 -0
- package/dist/multisig-wallet-helper.js.map +1 -0
- package/dist/multisig-wallet.d.ts +20 -0
- package/dist/multisig-wallet.d.ts.map +1 -0
- package/dist/multisig-wallet.js +119 -0
- package/dist/multisig-wallet.js.map +1 -0
- package/dist/sign/sign-transaction.d.ts +1 -5
- package/dist/sign/sign-transaction.d.ts.map +1 -1
- package/dist/sign/sign-transaction.js +2 -5
- package/dist/sign/sign-transaction.js.map +1 -1
- package/dist/teleswap-wallet.d.ts +2 -2
- package/dist/teleswap-wallet.d.ts.map +1 -1
- package/dist/teleswap-wallet.js +6 -4
- package/dist/teleswap-wallet.js.map +1 -1
- package/dist/transaction-builder/coin-select.d.ts +87 -0
- package/dist/transaction-builder/coin-select.d.ts.map +1 -0
- package/dist/transaction-builder/coin-select.js +359 -0
- package/dist/transaction-builder/coin-select.js.map +1 -0
- package/dist/transaction-builder/transaction-builder.d.ts +6 -28
- package/dist/transaction-builder/transaction-builder.d.ts.map +1 -1
- package/dist/transaction-builder/transaction-builder.js +115 -195
- package/dist/transaction-builder/transaction-builder.js.map +1 -1
- package/package.json +4 -4
- package/src/bitcoin-interface-utils.ts +0 -12
- package/src/bitcoin-utils.ts +2 -51
- package/src/bitcoin-wallet-base.ts +22 -62
- package/src/sign/sign-transaction.ts +7 -5
- package/src/teleswap-wallet.ts +6 -1
- package/src/transaction-builder/transaction-builder.ts +131 -266
- package/src/multisig-coordinator-wallet.ts +0 -9
|
@@ -2,11 +2,7 @@
|
|
|
2
2
|
/* eslint-disable no-underscore-dangle */
|
|
3
3
|
import * as bitcoin from "bitcoinjs-lib"
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
createAddressObjectByPublicKey,
|
|
7
|
-
getAddressType,
|
|
8
|
-
createMultisigAddressObjectByPublicKeys,
|
|
9
|
-
} from "../bitcoin-utils"
|
|
5
|
+
import { createAddressObjectByPublicKey, getAddressType } from "../bitcoin-utils"
|
|
10
6
|
|
|
11
7
|
const coinselect = require("coinselect")
|
|
12
8
|
const coinselectSplit = require("coinselect/split")
|
|
@@ -26,30 +22,24 @@ const coinselectAccumulative = require("coinselect/accumulative")
|
|
|
26
22
|
// p2wpkh: 35, // 31
|
|
27
23
|
// p2sh: 35, // 32
|
|
28
24
|
// p2tr: 45, // 43
|
|
29
|
-
// p2tr: 45, // 43
|
|
30
25
|
// default: 35,
|
|
31
26
|
// },
|
|
32
27
|
//
|
|
33
28
|
// }
|
|
34
|
-
|
|
35
|
-
const SINGLESIG_TYPES = ["p2pkh", "p2wpkh", "p2sh-p2wpkh", "p2tr"]
|
|
36
|
-
const MULTISIG_TYPES = ["p2sh", "p2wsh", "p2sh-p2wsh"]
|
|
37
|
-
|
|
38
29
|
export const componentBytes = {
|
|
39
30
|
bytePerInput: {
|
|
40
|
-
p2pkh:
|
|
41
|
-
p2wpkh:
|
|
42
|
-
"p2sh-p2wpkh":
|
|
43
|
-
p2tr:
|
|
31
|
+
p2pkh: 148,
|
|
32
|
+
p2wpkh: 68, // 68
|
|
33
|
+
"p2sh-p2wpkh": 91,
|
|
34
|
+
p2tr: 58, // actual 58
|
|
44
35
|
default: 100,
|
|
45
36
|
},
|
|
46
37
|
baseTxBytes: 10 + 5, // +5 extra bytes to be sure
|
|
47
38
|
bytePerOutput: {
|
|
48
|
-
p2pkh: 34, //
|
|
49
|
-
p2wpkh: 31, //
|
|
50
|
-
p2sh: 32, //
|
|
51
|
-
p2tr: 43, //
|
|
52
|
-
p2wsh: 44, // 43
|
|
39
|
+
p2pkh: 34, // 34
|
|
40
|
+
p2wpkh: 31, // 31
|
|
41
|
+
p2sh: 32, // 32
|
|
42
|
+
p2tr: 43, // 43
|
|
53
43
|
default: 35,
|
|
54
44
|
max: 45,
|
|
55
45
|
},
|
|
@@ -60,76 +50,6 @@ export const componentBytes = {
|
|
|
60
50
|
},
|
|
61
51
|
}
|
|
62
52
|
|
|
63
|
-
// P2SH | 46 + 74n + 34m
|
|
64
|
-
// P2SH-P2WSH | (306 + 76n + 34m) / 4
|
|
65
|
-
// P2WSH | (166 + 76n + 34m) / 4
|
|
66
|
-
|
|
67
|
-
export function getInputSize(
|
|
68
|
-
addressType: string,
|
|
69
|
-
details?: {
|
|
70
|
-
// op return or other script
|
|
71
|
-
script?: string
|
|
72
|
-
// n of m multisig
|
|
73
|
-
n?: number
|
|
74
|
-
m?: number
|
|
75
|
-
},
|
|
76
|
-
) {
|
|
77
|
-
let { m = 3 } = details || {}
|
|
78
|
-
const n = details?.n || m || 2
|
|
79
|
-
if (addressType === "p2sh") {
|
|
80
|
-
return 46 + 74 * n + 34 * m
|
|
81
|
-
}
|
|
82
|
-
if (addressType === "p2sh-p2wsh") {
|
|
83
|
-
return +((306 + 76 * n + 34 * m) / 4).toFixed()
|
|
84
|
-
}
|
|
85
|
-
if (addressType === "p2wsh") {
|
|
86
|
-
return +((166 + 76 * n + 34 * m) / 4).toFixed()
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return (
|
|
90
|
-
componentBytes.bytePerInput[addressType as keyof typeof componentBytes.bytePerInput] ||
|
|
91
|
-
componentBytes.bytePerInput.default
|
|
92
|
-
)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export function getOutputSize(
|
|
96
|
-
output: {
|
|
97
|
-
addressType?: string
|
|
98
|
-
address?: string
|
|
99
|
-
script?: Buffer
|
|
100
|
-
},
|
|
101
|
-
// use network to decode address
|
|
102
|
-
network: bitcoin.Network = bitcoin.networks.bitcoin,
|
|
103
|
-
) {
|
|
104
|
-
if (output.addressType) {
|
|
105
|
-
return (
|
|
106
|
-
componentBytes.bytePerOutput[
|
|
107
|
-
output.addressType as keyof typeof componentBytes.bytePerOutput
|
|
108
|
-
] || componentBytes.bytePerOutput.default
|
|
109
|
-
)
|
|
110
|
-
}
|
|
111
|
-
if (output.address) {
|
|
112
|
-
let addressType = "max"
|
|
113
|
-
try {
|
|
114
|
-
addressType = getAddressType(output.address, network)
|
|
115
|
-
} catch {
|
|
116
|
-
addressType = "max"
|
|
117
|
-
}
|
|
118
|
-
return (
|
|
119
|
-
componentBytes.bytePerOutput[addressType as keyof typeof componentBytes.bytePerOutput] ||
|
|
120
|
-
componentBytes.bytePerOutput.max
|
|
121
|
-
)
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (output.script) {
|
|
125
|
-
if (output.script.byteLength < 255) {
|
|
126
|
-
return output.script.byteLength + componentBytes.scriptExtraBytes.lessThan255
|
|
127
|
-
}
|
|
128
|
-
return output.script.byteLength + componentBytes.scriptExtraBytes.moreThan255
|
|
129
|
-
}
|
|
130
|
-
throw new Error("invalid output")
|
|
131
|
-
}
|
|
132
|
-
|
|
133
53
|
export const DUST = 1000
|
|
134
54
|
|
|
135
55
|
export type Utxo = {
|
|
@@ -137,21 +57,14 @@ export type Utxo = {
|
|
|
137
57
|
value: number
|
|
138
58
|
index: number
|
|
139
59
|
}
|
|
140
|
-
|
|
141
60
|
export type SignerInfo = {
|
|
142
61
|
address: string
|
|
143
62
|
publicKey: string
|
|
144
63
|
addressType: string
|
|
145
|
-
|
|
146
|
-
//
|
|
147
|
-
publicKeys?: string[]
|
|
148
|
-
numberOfSigners?: number
|
|
149
|
-
|
|
150
64
|
derivationPath?: string
|
|
151
65
|
masterFingerprint?: string
|
|
152
66
|
includeHex?: boolean
|
|
153
67
|
}
|
|
154
|
-
|
|
155
68
|
export type ExtendedUtxo = {
|
|
156
69
|
signerInfo: SignerInfo
|
|
157
70
|
hash: string
|
|
@@ -189,7 +102,6 @@ export type BitcoinJSInputInfo = ExtendedUtxo & {
|
|
|
189
102
|
value: number
|
|
190
103
|
}
|
|
191
104
|
redeemScript?: Buffer
|
|
192
|
-
witnessScript?: Buffer
|
|
193
105
|
tapInternalKey?: Buffer
|
|
194
106
|
}
|
|
195
107
|
|
|
@@ -223,13 +135,12 @@ function coinSelectInOrder(
|
|
|
223
135
|
}
|
|
224
136
|
|
|
225
137
|
export abstract class BaseTransactionBuilder {
|
|
226
|
-
MULTISIG_TYPES = MULTISIG_TYPES
|
|
227
|
-
|
|
228
138
|
testnet: boolean
|
|
229
139
|
network: bitcoin.Network
|
|
230
140
|
maximumNumberOfOutputsInTransaction: number
|
|
231
141
|
feeMin: number
|
|
232
142
|
dustLimit: number
|
|
143
|
+
NO_RBF_SEQUENCE = 0xffffffff
|
|
233
144
|
// abstract
|
|
234
145
|
constructor({
|
|
235
146
|
network,
|
|
@@ -251,25 +162,11 @@ export abstract class BaseTransactionBuilder {
|
|
|
251
162
|
this.dustLimit = dustLimit || 1 * 2 * componentBytes.bytePerInput.p2pkh
|
|
252
163
|
}
|
|
253
164
|
|
|
254
|
-
isMultiSig(addressType: string) {
|
|
255
|
-
return this.MULTISIG_TYPES.includes(addressType)
|
|
256
|
-
}
|
|
257
|
-
|
|
258
165
|
// eslint-disable-next-line no-unused-vars, class-methods-use-this
|
|
259
166
|
abstract _getTransactionHex(transactionId: string): Promise<string>
|
|
260
167
|
|
|
261
168
|
// eslint-disable-next-line no-unused-vars, class-methods-use-this
|
|
262
|
-
createAddressObject(input: {
|
|
263
|
-
addressType: string
|
|
264
|
-
publicKey: Buffer
|
|
265
|
-
publicKeys?: Buffer[]
|
|
266
|
-
numberOfSigners?: number
|
|
267
|
-
}) {
|
|
268
|
-
if (this.MULTISIG_TYPES.includes(input.addressType))
|
|
269
|
-
return createMultisigAddressObjectByPublicKeys(input.addressType, {
|
|
270
|
-
publicKeys: input.publicKeys!,
|
|
271
|
-
numberOfSigners: input.numberOfSigners,
|
|
272
|
-
})
|
|
169
|
+
createAddressObject(input: { addressType: string; publicKey: Buffer }) {
|
|
273
170
|
return createAddressObjectByPublicKey(input, this.network)
|
|
274
171
|
}
|
|
275
172
|
|
|
@@ -296,12 +193,7 @@ export abstract class BaseTransactionBuilder {
|
|
|
296
193
|
}
|
|
297
194
|
|
|
298
195
|
calculateTxSize(
|
|
299
|
-
inputTypes:
|
|
300
|
-
addressType: string
|
|
301
|
-
n?: number
|
|
302
|
-
m?: number
|
|
303
|
-
script?: string
|
|
304
|
-
}[],
|
|
196
|
+
inputTypes: string[],
|
|
305
197
|
outputs: {
|
|
306
198
|
script?: Buffer
|
|
307
199
|
address?: string
|
|
@@ -309,19 +201,33 @@ export abstract class BaseTransactionBuilder {
|
|
|
309
201
|
}[],
|
|
310
202
|
changeAddressType = "default",
|
|
311
203
|
) {
|
|
312
|
-
const inputsSizes = inputTypes.map(
|
|
313
|
-
|
|
204
|
+
const inputsSizes = inputTypes.map(
|
|
205
|
+
(addressType) =>
|
|
206
|
+
componentBytes.bytePerInput[addressType as keyof typeof componentBytes.bytePerInput],
|
|
314
207
|
)
|
|
315
208
|
const outputSizes = outputs.map((outP: any) => {
|
|
316
|
-
if (
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
209
|
+
if (outP.address) {
|
|
210
|
+
let addressType = "default"
|
|
211
|
+
try {
|
|
212
|
+
addressType = getAddressType(outP.address, this.network)
|
|
213
|
+
} catch {
|
|
214
|
+
addressType = "default"
|
|
215
|
+
}
|
|
216
|
+
return componentBytes.bytePerOutput[
|
|
217
|
+
addressType as keyof typeof componentBytes.bytePerOutput
|
|
218
|
+
]
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (outP.script) {
|
|
222
|
+
if (outP.script.byteLength < 255) {
|
|
223
|
+
return outP.script.byteLength + componentBytes.scriptExtraBytes.lessThan255
|
|
224
|
+
}
|
|
225
|
+
return outP.script.byteLength + componentBytes.scriptExtraBytes.moreThan255
|
|
323
226
|
}
|
|
324
|
-
|
|
227
|
+
|
|
228
|
+
return componentBytes.bytePerOutput[
|
|
229
|
+
changeAddressType as keyof typeof componentBytes.bytePerOutput
|
|
230
|
+
]
|
|
325
231
|
})
|
|
326
232
|
|
|
327
233
|
const txSize: number =
|
|
@@ -355,10 +261,9 @@ export abstract class BaseTransactionBuilder {
|
|
|
355
261
|
(u) =>
|
|
356
262
|
u.value >
|
|
357
263
|
+feeRate *
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
}),
|
|
264
|
+
componentBytes.bytePerInput[
|
|
265
|
+
u.signerInfo.addressType as keyof typeof componentBytes.bytePerInput
|
|
266
|
+
],
|
|
362
267
|
)
|
|
363
268
|
let selectResponse
|
|
364
269
|
switch (selectType) {
|
|
@@ -412,17 +317,13 @@ export abstract class BaseTransactionBuilder {
|
|
|
412
317
|
changeAddressType = "default"
|
|
413
318
|
}
|
|
414
319
|
|
|
415
|
-
const txSize =
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
outputs,
|
|
422
|
-
changeAddressType,
|
|
423
|
-
)
|
|
320
|
+
const txSize =
|
|
321
|
+
this.calculateTxSize(
|
|
322
|
+
inputs.map((i) => i.signerInfo.addressType),
|
|
323
|
+
outputs,
|
|
324
|
+
changeAddressType,
|
|
325
|
+
) + componentBytes.bytePerOutput.default
|
|
424
326
|
|
|
425
|
-
let extraChangeFee = Math.round(componentBytes.bytePerOutput.default * feeRate)
|
|
426
327
|
let txFee = Math.round(txSize * feeRate)
|
|
427
328
|
if (Math.round(feeRate) === 1) {
|
|
428
329
|
txFee = Math.round(txFee + txFee * 0.1)
|
|
@@ -430,8 +331,7 @@ export abstract class BaseTransactionBuilder {
|
|
|
430
331
|
if (
|
|
431
332
|
inputs.reduce((a, b) => a + b.value, 0) -
|
|
432
333
|
outputs.filter((o) => o.address || o.script).reduce((a, b) => a + b.value, 0) -
|
|
433
|
-
txFee
|
|
434
|
-
extraChangeFee <
|
|
334
|
+
txFee <
|
|
435
335
|
0
|
|
436
336
|
) {
|
|
437
337
|
let spendableBalance = inputs.reduce((a, b) => a + b.value, 0)
|
|
@@ -447,58 +347,35 @@ export abstract class BaseTransactionBuilder {
|
|
|
447
347
|
)}`,
|
|
448
348
|
)
|
|
449
349
|
}
|
|
450
|
-
|
|
451
350
|
let diff = fee - txFee
|
|
452
351
|
let changeIndex = outputs.findIndex((x) => !x?.address && !x.script && (x.value || 0) > 0)
|
|
453
352
|
let change: ChangeTarget | undefined
|
|
353
|
+
if (changeIndex >= 0 || diff > DUST) {
|
|
354
|
+
if (changeIndex >= 0) {
|
|
355
|
+
diff = diff + componentBytes.bytePerOutput.default * Math.round(feeRate)
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
if (diff < 0) {
|
|
359
|
+
diff = 0
|
|
360
|
+
}
|
|
454
361
|
|
|
455
|
-
if (diff > 0) {
|
|
456
362
|
if (selectType === "full") {
|
|
457
363
|
outputs[0].value = outputs[0].value + diff
|
|
458
364
|
fee = fee - diff
|
|
459
|
-
} else
|
|
365
|
+
} else {
|
|
460
366
|
if (!changeObject) throw new Error("change not exist")
|
|
461
367
|
change = {
|
|
462
368
|
address: changeObject.address,
|
|
463
|
-
value: outputs[changeIndex].value + diff,
|
|
369
|
+
value: changeIndex >= 0 ? outputs[changeIndex].value + diff : diff,
|
|
464
370
|
}
|
|
465
371
|
fee = fee - diff
|
|
466
|
-
} else if (diff - extraChangeFee > DUST) {
|
|
467
|
-
if (!changeObject) throw new Error("change not exist")
|
|
468
|
-
change = {
|
|
469
|
-
address: changeObject.address,
|
|
470
|
-
value: diff - extraChangeFee,
|
|
471
|
-
}
|
|
472
|
-
fee = fee - diff + extraChangeFee
|
|
473
372
|
}
|
|
474
|
-
} else if (-1 * diff > 0) {
|
|
475
|
-
const positiveDiff = -1 * diff
|
|
476
373
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
if (currentChangeValue - positiveDiff < -1 * DUST) {
|
|
480
|
-
throw new Error(`not enough balance.`) // it should no happen
|
|
374
|
+
if (changeIndex >= 0) {
|
|
375
|
+
outputs.splice(changeIndex, 1)
|
|
481
376
|
}
|
|
482
|
-
|
|
483
|
-
if (changeIndex > 0) {
|
|
484
|
-
if (!changeObject) throw new Error("change not exist")
|
|
485
|
-
change =
|
|
486
|
-
outputs[changeIndex].value - positiveDiff > DUST
|
|
487
|
-
? {
|
|
488
|
-
address: changeObject.address,
|
|
489
|
-
value: outputs[changeIndex].value - positiveDiff,
|
|
490
|
-
}
|
|
491
|
-
: undefined
|
|
492
|
-
fee = fee + positiveDiff
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
if (changeIndex >= 0) {
|
|
497
|
-
outputs.splice(changeIndex, 1)
|
|
498
377
|
}
|
|
499
378
|
|
|
500
|
-
console.log(fee, outputs, change)
|
|
501
|
-
|
|
502
379
|
return {
|
|
503
380
|
inputs,
|
|
504
381
|
fee,
|
|
@@ -557,21 +434,11 @@ export abstract class BaseTransactionBuilder {
|
|
|
557
434
|
})[] = baseInputs
|
|
558
435
|
const transactionHex: { [key: string]: string } = {}
|
|
559
436
|
for (let i in inputs) {
|
|
560
|
-
let {
|
|
561
|
-
|
|
562
|
-
publicKey,
|
|
563
|
-
derivationPath,
|
|
564
|
-
masterFingerprint,
|
|
565
|
-
addressType,
|
|
566
|
-
publicKeys,
|
|
567
|
-
numberOfSigners,
|
|
568
|
-
} = inputs[i].signerInfo
|
|
437
|
+
let { address, publicKey, derivationPath, masterFingerprint, addressType } =
|
|
438
|
+
inputs[i].signerInfo
|
|
569
439
|
// todo : support without publicKey
|
|
570
|
-
|
|
571
440
|
let addressObject = this.createAddressObject({
|
|
572
441
|
publicKey: Buffer.from(publicKey, "hex"),
|
|
573
|
-
publicKeys: publicKeys?.map((p) => Buffer.from(p, "hex")),
|
|
574
|
-
numberOfSigners,
|
|
575
442
|
addressType,
|
|
576
443
|
})
|
|
577
444
|
if (derivationPath && masterFingerprint && addressObject.pubkey) {
|
|
@@ -609,8 +476,7 @@ export abstract class BaseTransactionBuilder {
|
|
|
609
476
|
script: addressObject.output,
|
|
610
477
|
value: inputs[i].value,
|
|
611
478
|
}
|
|
612
|
-
if (!addressObject?.redeem?.output)
|
|
613
|
-
throw new Error("invalid signer info for p2sh-p2wpkh address")
|
|
479
|
+
if (!addressObject?.redeem?.output) throw new Error("invalid signer info for p2sh address")
|
|
614
480
|
inputs[i].redeemScript = addressObject.redeem.output
|
|
615
481
|
|
|
616
482
|
if (inputs[i].signerInfo.includeHex) {
|
|
@@ -628,51 +494,6 @@ export abstract class BaseTransactionBuilder {
|
|
|
628
494
|
if (!addressObject.pubkey) throw new Error("invalid signer info for p2tr address (pubkey)")
|
|
629
495
|
inputs[i].tapInternalKey = addressObject.internalPubkey
|
|
630
496
|
|
|
631
|
-
if (inputs[i].signerInfo.includeHex) {
|
|
632
|
-
const txHex =
|
|
633
|
-
transactionHex[inputs[i].hash] || (await this._getTransactionHex(inputs[i].hash))
|
|
634
|
-
transactionHex[inputs[i].hash] = txHex
|
|
635
|
-
inputs[i].nonWitnessUtxo = Buffer.from(txHex, "hex")
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
// multisig
|
|
639
|
-
else if (addressType === "p2sh") {
|
|
640
|
-
const txHex =
|
|
641
|
-
transactionHex[inputs[i].hash] || (await this._getTransactionHex(inputs[i].hash))
|
|
642
|
-
transactionHex[inputs[i].hash] = txHex
|
|
643
|
-
inputs[i].nonWitnessUtxo = Buffer.from(txHex, "hex")
|
|
644
|
-
|
|
645
|
-
if (!addressObject.output) throw new Error("invalid signer info")
|
|
646
|
-
if (!addressObject?.redeem?.output) throw new Error("invalid signer info for p2sh address")
|
|
647
|
-
inputs[i].redeemScript = addressObject.redeem.output
|
|
648
|
-
} else if (addressType === "p2wsh") {
|
|
649
|
-
if (!addressObject.output) throw new Error("invalid signer info")
|
|
650
|
-
inputs[i].witnessUtxo = {
|
|
651
|
-
script: addressObject.output,
|
|
652
|
-
value: inputs[i].value,
|
|
653
|
-
}
|
|
654
|
-
if (!addressObject?.redeem?.output) throw new Error("invalid signer info for p2wsh address")
|
|
655
|
-
inputs[i].witnessScript = addressObject.redeem?.output
|
|
656
|
-
|
|
657
|
-
if (inputs[i].signerInfo.includeHex) {
|
|
658
|
-
const txHex =
|
|
659
|
-
transactionHex[inputs[i].hash] || (await this._getTransactionHex(inputs[i].hash))
|
|
660
|
-
transactionHex[inputs[i].hash] = txHex
|
|
661
|
-
inputs[i].nonWitnessUtxo = Buffer.from(txHex, "hex")
|
|
662
|
-
}
|
|
663
|
-
} else if (addressType === "p2sh-p2wsh") {
|
|
664
|
-
if (!addressObject.output) throw new Error("invalid signer info")
|
|
665
|
-
inputs[i].witnessUtxo = {
|
|
666
|
-
script: addressObject.output,
|
|
667
|
-
value: inputs[i].value,
|
|
668
|
-
}
|
|
669
|
-
if (!addressObject?.redeem?.output) throw new Error("invalid signer info for p2sh address")
|
|
670
|
-
inputs[i].redeemScript = addressObject.redeem.output
|
|
671
|
-
|
|
672
|
-
if (!addressObject?.redeem?.redeem?.output)
|
|
673
|
-
throw new Error("invalid signer info for p2sh-p2wsh address")
|
|
674
|
-
inputs[i].witnessScript = addressObject.redeem.redeem.output
|
|
675
|
-
|
|
676
497
|
if (inputs[i].signerInfo.includeHex) {
|
|
677
498
|
const txHex =
|
|
678
499
|
transactionHex[inputs[i].hash] || (await this._getTransactionHex(inputs[i].hash))
|
|
@@ -692,42 +513,85 @@ export abstract class BaseTransactionBuilder {
|
|
|
692
513
|
change,
|
|
693
514
|
fee, // not used in this section - just returned
|
|
694
515
|
feeRate,
|
|
516
|
+
sequenceNumber,
|
|
695
517
|
}: {
|
|
696
518
|
inputs: BitcoinJSInputInfo[]
|
|
697
519
|
outputs: Target[]
|
|
698
520
|
change?: ChangeTarget
|
|
699
521
|
fee: number
|
|
700
522
|
feeRate: number
|
|
523
|
+
sequenceNumber?: number
|
|
701
524
|
}) {
|
|
702
|
-
const sequence =
|
|
525
|
+
const sequence = sequenceNumber || this.NO_RBF_SEQUENCE - 2
|
|
703
526
|
const { network } = this
|
|
704
527
|
const newPsbt = new bitcoin.Psbt({ network })
|
|
705
528
|
newPsbt.setMaximumFeeRate(+(feeRate + feeRate / 100).toFixed())
|
|
706
529
|
// add input
|
|
707
530
|
for (const input of inputs) {
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
531
|
+
let { addressType } = input.signerInfo
|
|
532
|
+
switch (addressType) {
|
|
533
|
+
case "p2pkh": {
|
|
534
|
+
let i = {
|
|
535
|
+
hash: input.hash,
|
|
536
|
+
index: Number(input.index),
|
|
537
|
+
nonWitnessUtxo: input.nonWitnessUtxo,
|
|
538
|
+
sequence,
|
|
539
|
+
bip32Derivation: input.bip32Derivation,
|
|
540
|
+
}
|
|
541
|
+
if (!i.bip32Derivation) delete i.bip32Derivation
|
|
542
|
+
newPsbt.addInput(i)
|
|
543
|
+
break
|
|
544
|
+
}
|
|
545
|
+
case "p2wpkh": {
|
|
546
|
+
let i = {
|
|
547
|
+
hash: input.hash,
|
|
548
|
+
index: Number(input.index),
|
|
549
|
+
witnessUtxo: input.witnessUtxo,
|
|
550
|
+
// we dont need nonWitnessUtxo. bud some application force nonWitnessUtxo
|
|
551
|
+
nonWitnessUtxo: input.nonWitnessUtxo,
|
|
552
|
+
sequence,
|
|
553
|
+
bip32Derivation: input.bip32Derivation,
|
|
554
|
+
}
|
|
555
|
+
if (!i.bip32Derivation) delete i.bip32Derivation
|
|
556
|
+
if (!i.nonWitnessUtxo) delete i.nonWitnessUtxo
|
|
557
|
+
newPsbt.addInput(i)
|
|
558
|
+
break
|
|
559
|
+
}
|
|
560
|
+
case "p2sh-p2wpkh": {
|
|
561
|
+
let i = {
|
|
562
|
+
hash: input.hash,
|
|
563
|
+
index: Number(input.index),
|
|
564
|
+
witnessUtxo: input.witnessUtxo,
|
|
565
|
+
// we dont need nonWitnessUtxo. bud some application force nonWitnessUtxo
|
|
566
|
+
nonWitnessUtxo: input.nonWitnessUtxo,
|
|
567
|
+
redeemScript: input.redeemScript,
|
|
568
|
+
sequence,
|
|
569
|
+
bip32Derivation: input.bip32Derivation,
|
|
570
|
+
}
|
|
571
|
+
if (!i.bip32Derivation) delete i.bip32Derivation
|
|
572
|
+
if (!i.nonWitnessUtxo) delete i.nonWitnessUtxo
|
|
573
|
+
newPsbt.addInput(i)
|
|
574
|
+
break
|
|
575
|
+
}
|
|
576
|
+
case "p2tr": {
|
|
577
|
+
let i = {
|
|
578
|
+
hash: input.hash,
|
|
579
|
+
index: Number(input.index),
|
|
580
|
+
witnessUtxo: input.witnessUtxo,
|
|
581
|
+
// we dont need nonWitnessUtxo. bud some application force nonWitnessUtxo
|
|
582
|
+
nonWitnessUtxo: input.nonWitnessUtxo,
|
|
583
|
+
tapInternalKey: input.tapInternalKey,
|
|
584
|
+
sequence,
|
|
585
|
+
bip32Derivation: input.bip32Derivation,
|
|
586
|
+
}
|
|
587
|
+
if (!i.bip32Derivation) delete i.bip32Derivation
|
|
588
|
+
if (!i.nonWitnessUtxo) delete i.nonWitnessUtxo
|
|
589
|
+
newPsbt.addInput(i)
|
|
590
|
+
break
|
|
591
|
+
}
|
|
592
|
+
default:
|
|
593
|
+
throw new Error("address type is incorrect")
|
|
720
594
|
}
|
|
721
|
-
|
|
722
|
-
if (!i.bip32Derivation) delete i.bip32Derivation
|
|
723
|
-
if (!i.nonWitnessUtxo) delete i.nonWitnessUtxo
|
|
724
|
-
if (!i.witnessUtxo) delete i.witnessUtxo
|
|
725
|
-
if (!i.redeemScript) delete i.redeemScript
|
|
726
|
-
if (!i.witnessScript) delete i.witnessScript
|
|
727
|
-
if (!i.tapInternalKey) delete i.tapInternalKey
|
|
728
|
-
|
|
729
|
-
newPsbt.addInput(i)
|
|
730
|
-
// console.log(i)
|
|
731
595
|
}
|
|
732
596
|
|
|
733
597
|
// add outputs
|
|
@@ -752,7 +616,7 @@ export abstract class BaseTransactionBuilder {
|
|
|
752
616
|
|
|
753
617
|
const unsignedPsbtBaseText = newPsbt.toBase64()
|
|
754
618
|
|
|
755
|
-
const safeAddressTypeForPossibleTxId = ["p2wpkh", "p2tr"
|
|
619
|
+
const safeAddressTypeForPossibleTxId = ["p2wpkh", "p2tr"]
|
|
756
620
|
const isPossibleTxId = inputs.reduce(
|
|
757
621
|
(a, b) => a && safeAddressTypeForPossibleTxId.includes(b.signerInfo.addressType),
|
|
758
622
|
true,
|
|
@@ -780,14 +644,15 @@ export abstract class BaseTransactionBuilder {
|
|
|
780
644
|
fullAmount = false,
|
|
781
645
|
feeRate,
|
|
782
646
|
selectType = "normal",
|
|
647
|
+
sequenceNumber,
|
|
783
648
|
}: {
|
|
784
649
|
extendedUtxo: ExtendedUtxo[]
|
|
785
650
|
targets: Target[]
|
|
786
651
|
feeRate: number
|
|
787
|
-
|
|
788
652
|
changeAddress?: string | SignerInfo
|
|
789
653
|
fullAmount?: boolean
|
|
790
654
|
selectType?: "normal" | "accumulative" | "full" | "inOrder"
|
|
655
|
+
sequenceNumber?: number
|
|
791
656
|
}) {
|
|
792
657
|
if (!changeAddress && targets.length === 0) throw new Error("no target")
|
|
793
658
|
let changeObject =
|
|
@@ -809,6 +674,7 @@ export abstract class BaseTransactionBuilder {
|
|
|
809
674
|
change,
|
|
810
675
|
fee,
|
|
811
676
|
feeRate,
|
|
677
|
+
sequenceNumber,
|
|
812
678
|
})
|
|
813
679
|
|
|
814
680
|
return unsignedTransaction
|
|
@@ -820,7 +686,6 @@ export abstract class BaseTransactionBuilder {
|
|
|
820
686
|
let psbt = bitcoin.Psbt.fromBase64(unsignedPsbt, {
|
|
821
687
|
network: this.network,
|
|
822
688
|
})
|
|
823
|
-
|
|
824
689
|
return (psbt as any).__CACHE.__TX.getId()
|
|
825
690
|
}
|
|
826
691
|
}
|