@teleportdao/bitcoin 1.6.0 → 1.6.1
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/bundle.js +7 -7
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/sign/index.d.ts +2 -0
- package/dist/sign/index.d.ts.map +1 -0
- package/dist/sign/index.js +9 -0
- package/dist/sign/index.js.map +1 -0
- package/dist/sign/sign-transaction.d.ts +4 -1
- package/dist/sign/sign-transaction.d.ts.map +1 -1
- package/dist/sign/sign-transaction.js +25 -48
- package/dist/sign/sign-transaction.js.map +1 -1
- package/dist/transaction-builder/bitcoin-transaction-builder.d.ts +1 -1
- package/dist/transaction-builder/bitcoin-transaction-builder.d.ts.map +1 -1
- package/dist/transaction-builder/bitcoin-transaction-builder.js +2 -5
- package/dist/transaction-builder/bitcoin-transaction-builder.js.map +1 -1
- package/dist/transaction-builder/index.d.ts +3 -0
- package/dist/transaction-builder/index.d.ts.map +1 -0
- package/dist/transaction-builder/index.js +24 -0
- package/dist/transaction-builder/index.js.map +1 -0
- package/dist/transaction-builder/transaction-builder.d.ts +26 -2
- package/dist/transaction-builder/transaction-builder.d.ts.map +1 -1
- package/dist/transaction-builder/transaction-builder.js +51 -44
- package/dist/transaction-builder/transaction-builder.js.map +1 -1
- package/package.json +2 -2
- package/src/helper/burn-request-helper.js +27 -27
- package/src/index.ts +2 -0
- package/src/sign/index.ts +1 -0
- package/src/sign/sign-transaction.ts +39 -37
- package/src/transaction-builder/bitcoin-transaction-builder.ts +1 -1
- package/src/transaction-builder/index.ts +2 -0
- package/src/transaction-builder/transaction-builder.ts +91 -52
- package/.tmp/check.ts +0 -101
- package/.tmp/psbt/sign-transaction.ts +0 -115
- package/.tmp/rbf.ts +0 -45
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
function getBurnTransactionInfo(address, vin = [], vouts = []) {
|
|
2
|
-
let lockerVinIndex = vin.findIndex((vi) => vi.address === address)
|
|
3
|
-
if (lockerVinIndex >= 0) {
|
|
4
|
-
let lockerVin = vin[lockerVinIndex]
|
|
5
|
-
lockerVin.vinIndex = lockerVinIndex
|
|
6
|
-
let totalInputValue = vin.reduce((acc, current) => +acc + +current.value, 0)
|
|
7
|
-
let receivers = []
|
|
8
|
-
let changes = []
|
|
9
|
-
for (let i in vouts) {
|
|
10
|
-
let vout = {
|
|
11
|
-
...vouts[i],
|
|
12
|
-
index: i,
|
|
13
|
-
}
|
|
14
|
-
if (vout.address === address) {
|
|
15
|
-
changes.push(vout)
|
|
16
|
-
} else {
|
|
17
|
-
receivers.push(vout)
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
return { receivers, changes, totalInputValue, lockerVin }
|
|
21
|
-
}
|
|
22
|
-
return null
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
module.exports = {
|
|
26
|
-
getBurnTransactionInfo,
|
|
27
|
-
}
|
|
1
|
+
function getBurnTransactionInfo(address, vin = [], vouts = []) {
|
|
2
|
+
let lockerVinIndex = vin.findIndex((vi) => vi.address === address)
|
|
3
|
+
if (lockerVinIndex >= 0) {
|
|
4
|
+
let lockerVin = vin[lockerVinIndex]
|
|
5
|
+
lockerVin.vinIndex = lockerVinIndex
|
|
6
|
+
let totalInputValue = vin.reduce((acc, current) => +acc + +current.value, 0)
|
|
7
|
+
let receivers = []
|
|
8
|
+
let changes = []
|
|
9
|
+
for (let i in vouts) {
|
|
10
|
+
let vout = {
|
|
11
|
+
...vouts[i],
|
|
12
|
+
index: i,
|
|
13
|
+
}
|
|
14
|
+
if (vout.address === address) {
|
|
15
|
+
changes.push(vout)
|
|
16
|
+
} else {
|
|
17
|
+
receivers.push(vout)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return { receivers, changes, totalInputValue, lockerVin }
|
|
21
|
+
}
|
|
22
|
+
return null
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
module.exports = {
|
|
26
|
+
getBurnTransactionInfo,
|
|
27
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as BaseBitcoinSigner } from "./sign-transaction"
|
|
@@ -1,56 +1,58 @@
|
|
|
1
1
|
import { Psbt, crypto, Network } from "bitcoinjs-lib"
|
|
2
2
|
// import BIP32Factory from "bip32"
|
|
3
3
|
import ecc from "@bitcoinerlab/secp256k1"
|
|
4
|
-
import
|
|
5
|
-
|
|
4
|
+
import ECPairFactory from "ecpair"
|
|
5
|
+
|
|
6
|
+
const ECPair = ECPairFactory(ecc)
|
|
6
7
|
|
|
7
8
|
function tapTweakHash(pubKey: Buffer, h?: Buffer) {
|
|
8
9
|
return crypto.taggedHash("TapTweak", Buffer.concat(h ? [pubKey, h] : [pubKey]))
|
|
9
10
|
}
|
|
10
11
|
|
|
11
|
-
function tweakSigner(
|
|
12
|
-
privateKey: Buffer,
|
|
13
|
-
opts = {} as {
|
|
14
|
-
[key: string]: Buffer
|
|
15
|
-
},
|
|
16
|
-
network: Network,
|
|
17
|
-
) {
|
|
18
|
-
let newPrv = privateKey
|
|
19
|
-
let keyPair = ECPair.fromPrivateKey(privateKey, {
|
|
20
|
-
network: network,
|
|
21
|
-
compressed: true,
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
if (!keyPair.privateKey) throw new Error("private key not exist")
|
|
25
|
-
|
|
26
|
-
if (keyPair.publicKey.toString("hex").startsWith("03")) {
|
|
27
|
-
newPrv = ecc.privateNegate(keyPair.privateKey) as Buffer
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const tweakedPrivateKey = ecc.privateAdd(
|
|
31
|
-
newPrv,
|
|
32
|
-
tapTweakHash(Buffer.from(keyPair.publicKey.toString("hex").slice(2), "hex"), opts?.tweakHash),
|
|
33
|
-
)
|
|
34
|
-
if (!tweakedPrivateKey) {
|
|
35
|
-
throw new Error("Invalid tweaked private key!")
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return ECPair.fromPrivateKey(Buffer.from(tweakedPrivateKey), {
|
|
39
|
-
network: network,
|
|
40
|
-
})
|
|
41
|
-
}
|
|
42
|
-
|
|
43
12
|
class BitcoinLikeSignTransaction {
|
|
44
13
|
network: Network
|
|
45
14
|
constructor(network: Network) {
|
|
46
15
|
this.network = network
|
|
47
16
|
}
|
|
48
17
|
|
|
18
|
+
static tweakSigner(
|
|
19
|
+
privateKey: Buffer,
|
|
20
|
+
opts = {} as {
|
|
21
|
+
[key: string]: Buffer
|
|
22
|
+
},
|
|
23
|
+
network: Network,
|
|
24
|
+
) {
|
|
25
|
+
let newPrv = privateKey
|
|
26
|
+
let keyPair = ECPair.fromPrivateKey(privateKey, {
|
|
27
|
+
network: network,
|
|
28
|
+
compressed: true,
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
if (!keyPair.privateKey) throw new Error("private key not exist")
|
|
32
|
+
|
|
33
|
+
if (keyPair.publicKey.toString("hex").startsWith("03")) {
|
|
34
|
+
newPrv = ecc.privateNegate(keyPair.privateKey) as Buffer
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const tweakedPrivateKey = ecc.privateAdd(
|
|
38
|
+
newPrv,
|
|
39
|
+
tapTweakHash(Buffer.from(keyPair.publicKey.toString("hex").slice(2), "hex"), opts?.tweakHash),
|
|
40
|
+
)
|
|
41
|
+
if (!tweakedPrivateKey) {
|
|
42
|
+
throw new Error("Invalid tweaked private key!")
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return ECPair.fromPrivateKey(Buffer.from(tweakedPrivateKey), {
|
|
46
|
+
network: network,
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
|
|
49
50
|
async signPsbt(
|
|
50
51
|
unsignedPsbt: {
|
|
51
52
|
unsignedTransaction: string
|
|
52
53
|
},
|
|
53
54
|
privateKey: Buffer,
|
|
55
|
+
sighashTypes?: any[],
|
|
54
56
|
) {
|
|
55
57
|
const { network } = this
|
|
56
58
|
const keyPair = ECPair.fromPrivateKey(privateKey, {
|
|
@@ -66,10 +68,10 @@ class BitcoinLikeSignTransaction {
|
|
|
66
68
|
for (let i = 0; i < numberOfInputs; i += 1) {
|
|
67
69
|
let type = psbt.getInputType(i)
|
|
68
70
|
if (type === "nonstandard") {
|
|
69
|
-
let a = tweakSigner(privateKey, undefined, this.network)
|
|
70
|
-
await psbt.signInputAsync(i, a)
|
|
71
|
+
let a = BitcoinLikeSignTransaction.tweakSigner(privateKey, undefined, this.network)
|
|
72
|
+
await psbt.signInputAsync(i, a, sighashTypes)
|
|
71
73
|
} else {
|
|
72
|
-
await psbt.signInputAsync(i, keyPair)
|
|
74
|
+
await psbt.signInputAsync(i, keyPair, sighashTypes)
|
|
73
75
|
}
|
|
74
76
|
}
|
|
75
77
|
|
|
@@ -8,19 +8,39 @@ const coinselectSplit = require("coinselect/split")
|
|
|
8
8
|
const coinselectAccumulative = require("coinselect/accumulative")
|
|
9
9
|
|
|
10
10
|
// https://bitcoin.stackexchange.com/questions/84004/how-do-virtual-size-stripped-size-and-raw-size-compare-between-legacy-address-f
|
|
11
|
-
const componentBytes = {
|
|
11
|
+
// export const componentBytes = {
|
|
12
|
+
// bytePerInput: {
|
|
13
|
+
// p2pkh: 148,
|
|
14
|
+
// p2wpkh: 70, // 68
|
|
15
|
+
// "p2sh-p2wpkh": 91,
|
|
16
|
+
// p2tr: 60, // actual 58
|
|
17
|
+
// },
|
|
18
|
+
// baseTxBytes: 10 + 5, // +5 extra bytes to be sure
|
|
19
|
+
// bytePerOutput: {
|
|
20
|
+
// p2pkh: 35, // 34
|
|
21
|
+
// p2wpkh: 35, // 31
|
|
22
|
+
// p2sh: 35, // 32
|
|
23
|
+
// p2tr: 45, // 43
|
|
24
|
+
// default: 35,
|
|
25
|
+
// },
|
|
26
|
+
// opReturn: {
|
|
27
|
+
// dataLessThan75: 31,
|
|
28
|
+
// dataMoreThan75: 91,
|
|
29
|
+
// },
|
|
30
|
+
// }
|
|
31
|
+
export const componentBytes = {
|
|
12
32
|
bytePerInput: {
|
|
13
33
|
p2pkh: 148,
|
|
14
|
-
p2wpkh:
|
|
34
|
+
p2wpkh: 68, // 68
|
|
15
35
|
"p2sh-p2wpkh": 91,
|
|
16
|
-
p2tr:
|
|
36
|
+
p2tr: 58, // actual 58
|
|
17
37
|
},
|
|
18
|
-
baseTxBytes: 10 + 5, // +
|
|
38
|
+
baseTxBytes: 10 + 5, // +5 extra bytes to be sure
|
|
19
39
|
bytePerOutput: {
|
|
20
|
-
p2pkh:
|
|
21
|
-
p2wpkh:
|
|
22
|
-
p2sh:
|
|
23
|
-
p2tr:
|
|
40
|
+
p2pkh: 34, // 34
|
|
41
|
+
p2wpkh: 31, // 31
|
|
42
|
+
p2sh: 32, // 32
|
|
43
|
+
p2tr: 43, // 43
|
|
24
44
|
default: 35,
|
|
25
45
|
},
|
|
26
46
|
opReturn: {
|
|
@@ -97,7 +117,7 @@ export type ExtendedUnsignedTransaction = {
|
|
|
97
117
|
change: TargetAddress | undefined
|
|
98
118
|
}
|
|
99
119
|
|
|
100
|
-
class
|
|
120
|
+
export class BaseTransactionBuilder {
|
|
101
121
|
testnet: boolean
|
|
102
122
|
network: bitcoin.Network
|
|
103
123
|
maximumNumberOfOutputsInTransaction: number
|
|
@@ -177,6 +197,52 @@ class BaseBitcoinLikeTransaction {
|
|
|
177
197
|
return extendedUtxo
|
|
178
198
|
}
|
|
179
199
|
|
|
200
|
+
calculateTxSize(
|
|
201
|
+
inputTypes: string[],
|
|
202
|
+
outputs: {
|
|
203
|
+
script?: Buffer
|
|
204
|
+
address?: string
|
|
205
|
+
value: number
|
|
206
|
+
}[],
|
|
207
|
+
changeAddressType = "default",
|
|
208
|
+
) {
|
|
209
|
+
const inputsSizes = inputTypes.map(
|
|
210
|
+
(addressType) =>
|
|
211
|
+
componentBytes.bytePerInput[addressType as keyof typeof componentBytes.bytePerInput],
|
|
212
|
+
)
|
|
213
|
+
const outputSizes = outputs.map((outP: any) => {
|
|
214
|
+
if (outP.address) {
|
|
215
|
+
let addressType = "default"
|
|
216
|
+
try {
|
|
217
|
+
addressType = getAddressType(outP.address, this.network)
|
|
218
|
+
} catch {
|
|
219
|
+
addressType = "default"
|
|
220
|
+
}
|
|
221
|
+
return componentBytes.bytePerOutput[
|
|
222
|
+
addressType as keyof typeof componentBytes.bytePerOutput
|
|
223
|
+
]
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (outP.script) {
|
|
227
|
+
if (outP.script.byteLength < 75) {
|
|
228
|
+
return componentBytes.opReturn.dataLessThan75
|
|
229
|
+
}
|
|
230
|
+
return componentBytes.opReturn.dataMoreThan75
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return componentBytes.bytePerOutput[
|
|
234
|
+
changeAddressType as keyof typeof componentBytes.bytePerOutput
|
|
235
|
+
]
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
const txSize =
|
|
239
|
+
componentBytes.baseTxBytes +
|
|
240
|
+
inputsSizes.reduce((a, c) => a + c, 0) +
|
|
241
|
+
outputSizes.reduce((a, c) => a + c, 0)
|
|
242
|
+
|
|
243
|
+
return txSize
|
|
244
|
+
}
|
|
245
|
+
|
|
180
246
|
helperHandleInputsAndOutputs({
|
|
181
247
|
targets,
|
|
182
248
|
extendedUtxo,
|
|
@@ -247,49 +313,24 @@ class BaseBitcoinLikeTransaction {
|
|
|
247
313
|
fee = inputs.reduce((a, b) => a + b.value, 0) - outputs.reduce((a, b) => a + b.value, 0)
|
|
248
314
|
}
|
|
249
315
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
const outputSizes = outputs.map((outP) => {
|
|
257
|
-
if (outP.address) {
|
|
258
|
-
let addressType = "default"
|
|
259
|
-
try {
|
|
260
|
-
addressType = getAddressType(outP.address, this.network)
|
|
261
|
-
} catch {
|
|
262
|
-
addressType = "default"
|
|
263
|
-
}
|
|
264
|
-
return componentBytes.bytePerOutput[
|
|
265
|
-
addressType as keyof typeof componentBytes.bytePerOutput
|
|
266
|
-
]
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
if (outP.script) {
|
|
270
|
-
if (outP.script.byteLength < 75) {
|
|
271
|
-
return componentBytes.opReturn.dataLessThan75
|
|
272
|
-
}
|
|
273
|
-
return componentBytes.opReturn.dataMoreThan75
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
let addressType = "default"
|
|
277
|
-
try {
|
|
278
|
-
addressType = getAddressType(changeObject?.address || "", this.network)
|
|
279
|
-
} catch {
|
|
280
|
-
addressType = "default"
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
return componentBytes.bytePerOutput[addressType as keyof typeof componentBytes.bytePerOutput]
|
|
284
|
-
})
|
|
316
|
+
let changeAddressType = "default"
|
|
317
|
+
try {
|
|
318
|
+
changeAddressType = getAddressType(changeObject?.address || "", this.network)
|
|
319
|
+
} catch {
|
|
320
|
+
changeAddressType = "default"
|
|
321
|
+
}
|
|
285
322
|
|
|
286
323
|
const txSize =
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
324
|
+
this.calculateTxSize(
|
|
325
|
+
inputs.map((i) => i.signerInfo.addressType),
|
|
326
|
+
outputs,
|
|
327
|
+
changeAddressType,
|
|
328
|
+
) + componentBytes.bytePerOutput.default
|
|
329
|
+
|
|
330
|
+
let txFee = Math.round(txSize * feeRate)
|
|
331
|
+
if (Math.round(feeRate) === 1) {
|
|
332
|
+
txFee = Math.round(txFee + txFee * 0.1)
|
|
333
|
+
}
|
|
293
334
|
if (
|
|
294
335
|
inputs.reduce((a, b) => a + b.value, 0) -
|
|
295
336
|
outputs.filter((o) => o.address || o.script).reduce((a, b) => a + b.value, 0) -
|
|
@@ -644,5 +685,3 @@ class BaseBitcoinLikeTransaction {
|
|
|
644
685
|
return unsignedTransaction
|
|
645
686
|
}
|
|
646
687
|
}
|
|
647
|
-
|
|
648
|
-
export default BaseBitcoinLikeTransaction
|
package/.tmp/check.ts
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { BitcoinBase, TeleportDaoPayment, TransferRequest } from "@teleportdao/bitcoin"
|
|
2
|
-
import { parseRawTransaction } from "../dist/bitcoin-utils"
|
|
3
|
-
;(async () => {
|
|
4
|
-
const testnet = true
|
|
5
|
-
let address = "tb1psfytxls4urhycq63xjrfmseq73wwuql2syn3n8398rqkyf5m3z8shy5sl7"
|
|
6
|
-
let btc = new TeleportDaoPayment("bitcoin_testnet")
|
|
7
|
-
let deadline = Math.ceil(new Date().getTime() / 1000 + 3600)
|
|
8
|
-
let transferRequest: TransferRequest = {
|
|
9
|
-
changeAddress: address,
|
|
10
|
-
lockerAddress: testnet
|
|
11
|
-
? "2MzQA2boKkWPkooDkN9dKfqzFndSvjHw5kg"
|
|
12
|
-
: "3CAQAw7m95axbY761Xq8d9DADhjNaX9b8o",
|
|
13
|
-
amount: +(0.0001 * 1e8).toFixed(),
|
|
14
|
-
recipientAddress: "0x7C124a845BC48D957748661452dc996FF487B252",
|
|
15
|
-
percentageFee: 4, // 2 bytes in satoshi
|
|
16
|
-
|
|
17
|
-
chainId: 3,
|
|
18
|
-
appId: 0,
|
|
19
|
-
speed: 0, // 1 byte
|
|
20
|
-
|
|
21
|
-
// exchange
|
|
22
|
-
isExchange: false,
|
|
23
|
-
exchangeTokenAddress: undefined,
|
|
24
|
-
outputAmount: undefined,
|
|
25
|
-
isFixedToken: false,
|
|
26
|
-
deadline,
|
|
27
|
-
feeSpeed: "normal",
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
let extendedUtxo = await btc.transactionBuilder.getExtendedUtxo({
|
|
31
|
-
address: address,
|
|
32
|
-
addressType: "p2tr",
|
|
33
|
-
publicKey: "021f6adece8789d520aaea90a2ca9faff45bdd2dca02fd819815673953dc674d54",
|
|
34
|
-
includeHex: false,
|
|
35
|
-
})
|
|
36
|
-
console.log(extendedUtxo.reduce((a, b) => a + b.value, 0) / 1e8)
|
|
37
|
-
extendedUtxo = extendedUtxo.filter((u) => u.value > 145 * 68)
|
|
38
|
-
console.log(extendedUtxo.reduce((a, b) => a + b.value, 0) / 1e8)
|
|
39
|
-
console.log(extendedUtxo.length)
|
|
40
|
-
|
|
41
|
-
// const extendedUtxo = [
|
|
42
|
-
// {
|
|
43
|
-
// hash: "1a69625b1fe4392e4130f30fa1e6794dd8b81f54bc9d7ccf7a3479d8ccf419a6",
|
|
44
|
-
// value: 99787,
|
|
45
|
-
// index: 1,
|
|
46
|
-
// signerInfo: {
|
|
47
|
-
// address: "tb1psfytxls4urhycq63xjrfmseq73wwuql2syn3n8398rqkyf5m3z8shy5sl7",
|
|
48
|
-
// publicKey: "021f6adece8789d520aaea90a2ca9faff45bdd2dca02fd819815673953dc674d54",
|
|
49
|
-
// addressType: "p2tr",
|
|
50
|
-
// },
|
|
51
|
-
// },
|
|
52
|
-
// {
|
|
53
|
-
// hash: "93f0b41f26480068a219a8620313f6fa146f076e4ef03ab781638965a2a1c7c4",
|
|
54
|
-
// value: 8000,
|
|
55
|
-
// index: 1,
|
|
56
|
-
// signerInfo: {
|
|
57
|
-
// address: "tb1psfytxls4urhycq63xjrfmseq73wwuql2syn3n8398rqkyf5m3z8shy5sl7",
|
|
58
|
-
// publicKey: "021f6adece8789d520aaea90a2ca9faff45bdd2dca02fd819815673953dc674d54",
|
|
59
|
-
// addressType: "p2tr",
|
|
60
|
-
// },
|
|
61
|
-
// },
|
|
62
|
-
// {
|
|
63
|
-
// hash: "6c666a7036fdff9f4c1cce2f9233eac3c4b56601cdc5ea82554b8af90e962ced",
|
|
64
|
-
// value: 8000,
|
|
65
|
-
// index: 1,
|
|
66
|
-
// signerInfo: {
|
|
67
|
-
// address: "tb1psfytxls4urhycq63xjrfmseq73wwuql2syn3n8398rqkyf5m3z8shy5sl7",
|
|
68
|
-
// publicKey: "021f6adece8789d520aaea90a2ca9faff45bdd2dca02fd819815673953dc674d54",
|
|
69
|
-
// addressType: "p2tr",
|
|
70
|
-
// },
|
|
71
|
-
// },
|
|
72
|
-
// {
|
|
73
|
-
// hash: "2437ddbde4bb469c5c1f8dcb09959962a9e844ba9b56420bb5391fb29f50400c",
|
|
74
|
-
// value: 8000,
|
|
75
|
-
// index: 0,
|
|
76
|
-
// signerInfo: {
|
|
77
|
-
// address: "tb1psfytxls4urhycq63xjrfmseq73wwuql2syn3n8398rqkyf5m3z8shy5sl7",
|
|
78
|
-
// publicKey: "021f6adece8789d520aaea90a2ca9faff45bdd2dca02fd819815673953dc674d54",
|
|
79
|
-
// addressType: "p2tr",
|
|
80
|
-
// },
|
|
81
|
-
// },
|
|
82
|
-
// ]
|
|
83
|
-
|
|
84
|
-
// normal transfer
|
|
85
|
-
// let tx = await btc.transactionBuilder.processUnsignedTransaction({
|
|
86
|
-
// extendedUtxo,
|
|
87
|
-
// targets: [{
|
|
88
|
-
// address: addressObj.address!,
|
|
89
|
-
// value: 0.0001 * 1e8
|
|
90
|
-
// }],
|
|
91
|
-
// feeRate:1,
|
|
92
|
-
// changeAddress: addressObj.address!
|
|
93
|
-
// })
|
|
94
|
-
|
|
95
|
-
let tx = await btc.getBitcoinToEthUnsignedPsbt({
|
|
96
|
-
...transferRequest,
|
|
97
|
-
extendedUtxo,
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
console.log("tx", tx)
|
|
101
|
-
})()
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { Psbt, crypto, Network } from "bitcoinjs-lib"
|
|
2
|
-
// import BIP32Factory from "bip32"
|
|
3
|
-
import ecc from "@bitcoinerlab/secp256k1"
|
|
4
|
-
import * as bitcoinEcPair from "bitcoinjs-ecpair"
|
|
5
|
-
const ECPair = bitcoinEcPair.ECPair
|
|
6
|
-
|
|
7
|
-
function tapTweakHash(pubKey: Buffer, h?: Buffer) {
|
|
8
|
-
return crypto.taggedHash("TapTweak", Buffer.concat(h ? [pubKey, h] : [pubKey]))
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function tweakSigner(
|
|
12
|
-
privateKey: Buffer,
|
|
13
|
-
opts = {} as {
|
|
14
|
-
[key: string]: Buffer
|
|
15
|
-
},
|
|
16
|
-
network: Network,
|
|
17
|
-
) {
|
|
18
|
-
let newPrv = privateKey
|
|
19
|
-
let keyPair = ECPair.fromPrivateKey(privateKey, {
|
|
20
|
-
network: network,
|
|
21
|
-
compressed: true,
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
if (!keyPair.privateKey) throw new Error("private key not exist")
|
|
25
|
-
|
|
26
|
-
if (keyPair.publicKey.toString("hex").startsWith("03")) {
|
|
27
|
-
newPrv = ecc.privateNegate(keyPair.privateKey) as Buffer
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const tweakedPrivateKey = ecc.privateAdd(
|
|
31
|
-
newPrv,
|
|
32
|
-
tapTweakHash(Buffer.from(keyPair.publicKey.toString("hex").slice(2), "hex"), opts?.tweakHash),
|
|
33
|
-
)
|
|
34
|
-
if (!tweakedPrivateKey) {
|
|
35
|
-
throw new Error("Invalid tweaked private key!")
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return ECPair.fromPrivateKey(Buffer.from(tweakedPrivateKey), {
|
|
39
|
-
network: network,
|
|
40
|
-
})
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
class BitcoinLikeSignTransaction {
|
|
44
|
-
network: Network
|
|
45
|
-
constructor(network: Network) {
|
|
46
|
-
this.network = network
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
async signPsbt(
|
|
50
|
-
unsignedPsbt: {
|
|
51
|
-
unsignedTransaction: string
|
|
52
|
-
},
|
|
53
|
-
privateKey: Buffer,
|
|
54
|
-
) {
|
|
55
|
-
const { network } = this
|
|
56
|
-
const keyPair = ECPair.fromPrivateKey(privateKey, {
|
|
57
|
-
network,
|
|
58
|
-
compressed: true,
|
|
59
|
-
})
|
|
60
|
-
const psbt = Psbt.fromBase64(unsignedPsbt.unsignedTransaction, {
|
|
61
|
-
network,
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
let numberOfInputs = psbt.inputCount
|
|
65
|
-
|
|
66
|
-
for (let i = 0; i < numberOfInputs; i += 1) {
|
|
67
|
-
let type = psbt.getInputType(i)
|
|
68
|
-
if (type === "nonstandard") {
|
|
69
|
-
let a = tweakSigner(privateKey, undefined, this.network)
|
|
70
|
-
await psbt.signInputAsync(i, a)
|
|
71
|
-
} else {
|
|
72
|
-
await psbt.signInputAsync(i, keyPair)
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// psbt.signAllInputs(keyPair)
|
|
77
|
-
const partialSigendPsbt = psbt.toBase64()
|
|
78
|
-
return partialSigendPsbt
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
finalizePsbts(psbtsBase64: string[] = []) {
|
|
82
|
-
const finals = psbtsBase64.map((psbtBase64) =>
|
|
83
|
-
Psbt.fromBase64(psbtBase64, { network: this.network }),
|
|
84
|
-
)
|
|
85
|
-
const psbt =
|
|
86
|
-
finals.length === 1 ? finals[0] : new Psbt({ network: this.network }).combine(...finals)
|
|
87
|
-
|
|
88
|
-
let newPsbt = new Psbt({ network: this.network })
|
|
89
|
-
newPsbt.addOutputs(psbt.txOutputs)
|
|
90
|
-
|
|
91
|
-
newPsbt.addInputs(
|
|
92
|
-
psbt.txInputs.map((txIn, i) => ({
|
|
93
|
-
...txIn,
|
|
94
|
-
partialSig: psbt.data.inputs[i].partialSig,
|
|
95
|
-
witnessUtxo: psbt.data.inputs[i].witnessUtxo,
|
|
96
|
-
})),
|
|
97
|
-
)
|
|
98
|
-
|
|
99
|
-
psbt.finalizeAllInputs()
|
|
100
|
-
|
|
101
|
-
for (let i = 0; i < psbt.txInputs.length; i += 1) {
|
|
102
|
-
// console.log(psbt.data.inputs[i])
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
newPsbt.finalizeAllInputs()
|
|
106
|
-
|
|
107
|
-
let finalizeTx = newPsbt.extractTransaction()
|
|
108
|
-
// console.log(finalizeTx.getId())
|
|
109
|
-
|
|
110
|
-
// console.log(finalizeTx.ins, finalizeTx.outs)
|
|
111
|
-
return finalizeTx.toHex()
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export default BitcoinLikeSignTransaction
|
package/.tmp/rbf.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { sleep } from "../dist/utils/tools"
|
|
2
|
-
import { BitcoinBase, TeleportDaoPayment, TransferRequest } from "@teleportdao/bitcoin"
|
|
3
|
-
import { parseRawTransaction } from "../dist/bitcoin-utils"
|
|
4
|
-
require("dotenv").config()
|
|
5
|
-
;(async () => {
|
|
6
|
-
let btc = new TeleportDaoPayment("bitcoin_testnet", {
|
|
7
|
-
api: {
|
|
8
|
-
enabled: true,
|
|
9
|
-
provider: "MempoolSpace",
|
|
10
|
-
},
|
|
11
|
-
})
|
|
12
|
-
btc.setAccountPrivateKeyByMnemonic({
|
|
13
|
-
mnemonic: process.env.ACCOUNT__MNEMONIC!,
|
|
14
|
-
index: 2,
|
|
15
|
-
addressType: "p2wpkh",
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
console.log(btc.bitcoinAddress)
|
|
19
|
-
let balance = await btc.btcInterface.getBalance(btc.bitcoinAddress!)
|
|
20
|
-
|
|
21
|
-
console.log(balance)
|
|
22
|
-
|
|
23
|
-
let txId = await btc.send({
|
|
24
|
-
receiverAddress: btc.bitcoinAddress!,
|
|
25
|
-
fullAmount: true,
|
|
26
|
-
amount: 0,
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
console.log(txId)
|
|
30
|
-
await sleep(5_000)
|
|
31
|
-
|
|
32
|
-
// const txId = "a4335df47c09cc983d0ba56373212b86c266ea434bb87d610ae5c892da79e1b7"
|
|
33
|
-
|
|
34
|
-
let unsigned = await btc.increaseTransactionFeeUnsignedPsbt(
|
|
35
|
-
txId,
|
|
36
|
-
[btc.signerInfo!],
|
|
37
|
-
[],
|
|
38
|
-
btc.bitcoinAddress!,
|
|
39
|
-
5,
|
|
40
|
-
)
|
|
41
|
-
let signedPsbt = await btc.signer.signPsbt(unsigned, btc.privateKey!)
|
|
42
|
-
let txIdNew = await btc.sendSignedPsbt(signedPsbt)
|
|
43
|
-
|
|
44
|
-
console.log(txIdNew)
|
|
45
|
-
})()
|