@teleportdao/bitcoin 1.6.1 → 1.7.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/.tmp/check.ts +101 -0
- package/.tmp/psbt/sign-transaction.ts +121 -0
- package/.tmp/rbf.ts +45 -0
- package/dist/bitcoin-interface-ordinal.d.ts +109 -0
- package/dist/bitcoin-interface-ordinal.d.ts.map +1 -0
- package/dist/bitcoin-interface-ordinal.js +141 -0
- package/dist/bitcoin-interface-ordinal.js.map +1 -0
- package/dist/bitcoin-interface-teleswap.d.ts +148 -0
- package/dist/bitcoin-interface-teleswap.d.ts.map +1 -0
- package/dist/bitcoin-interface-teleswap.js +179 -0
- package/dist/bitcoin-interface-teleswap.js.map +1 -0
- package/dist/bitcoin-interface-utils.d.ts.map +1 -1
- package/dist/bitcoin-interface-utils.js.map +1 -1
- package/dist/bitcoin-interface.d.ts +45 -333
- package/dist/bitcoin-interface.d.ts.map +1 -1
- package/dist/bitcoin-interface.js +68 -202
- package/dist/bitcoin-interface.js.map +1 -1
- package/dist/bitcoin-utils.d.ts +12 -59
- package/dist/bitcoin-utils.d.ts.map +1 -1
- package/dist/bitcoin-utils.js +61 -61
- package/dist/bitcoin-utils.js.map +1 -1
- package/dist/{bitcoin-base.d.ts → bitcoin-wallet-base.d.ts} +9 -9
- package/dist/bitcoin-wallet-base.d.ts.map +1 -0
- package/dist/{bitcoin-base.js → bitcoin-wallet-base.js} +15 -14
- package/dist/bitcoin-wallet-base.js.map +1 -0
- package/dist/helper/brc20-helper.d.ts +43 -0
- package/dist/helper/brc20-helper.d.ts.map +1 -0
- package/dist/helper/brc20-helper.js +129 -0
- package/dist/helper/brc20-helper.js.map +1 -0
- package/dist/helper/index.d.ts +4 -0
- package/dist/helper/index.d.ts.map +1 -0
- package/dist/helper/index.js +30 -0
- package/dist/helper/index.js.map +1 -0
- package/dist/helper/ordinal-helper.d.ts +13 -0
- package/dist/helper/ordinal-helper.d.ts.map +1 -0
- package/dist/helper/ordinal-helper.js +127 -0
- package/dist/helper/ordinal-helper.js.map +1 -0
- package/dist/helper/teleswap-helper.d.ts +84 -0
- package/dist/helper/teleswap-helper.d.ts.map +1 -0
- package/dist/helper/teleswap-helper.js +181 -0
- package/dist/helper/teleswap-helper.js.map +1 -0
- package/dist/index.d.ts +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -3
- package/dist/index.js.map +1 -1
- package/dist/ordinal-wallet.d.ts +536 -0
- package/dist/ordinal-wallet.d.ts.map +1 -0
- package/dist/ordinal-wallet.js +448 -0
- package/dist/ordinal-wallet.js.map +1 -0
- package/dist/sign/sign-transaction.d.ts +2 -4
- package/dist/sign/sign-transaction.d.ts.map +1 -1
- package/dist/sign/sign-transaction.js +26 -22
- package/dist/sign/sign-transaction.js.map +1 -1
- package/dist/teleswap-wallet.d.ts +54 -0
- package/dist/teleswap-wallet.d.ts.map +1 -0
- package/dist/teleswap-wallet.js +87 -0
- package/dist/teleswap-wallet.js.map +1 -0
- package/dist/transaction-builder/bitcoin-transaction-builder.d.ts +2 -20
- package/dist/transaction-builder/bitcoin-transaction-builder.d.ts.map +1 -1
- package/dist/transaction-builder/bitcoin-transaction-builder.js +5 -4
- package/dist/transaction-builder/bitcoin-transaction-builder.js.map +1 -1
- package/dist/transaction-builder/index.d.ts +2 -1
- package/dist/transaction-builder/index.d.ts.map +1 -1
- package/dist/transaction-builder/index.js +2 -6
- package/dist/transaction-builder/index.js.map +1 -1
- package/dist/transaction-builder/ordinal-transaction-builder.d.ts +63 -0
- package/dist/transaction-builder/ordinal-transaction-builder.d.ts.map +1 -0
- package/dist/transaction-builder/ordinal-transaction-builder.js +131 -0
- package/dist/transaction-builder/ordinal-transaction-builder.js.map +1 -0
- package/dist/transaction-builder/transaction-builder.d.ts +10 -7
- package/dist/transaction-builder/transaction-builder.d.ts.map +1 -1
- package/dist/transaction-builder/transaction-builder.js +18 -9
- package/dist/transaction-builder/transaction-builder.js.map +1 -1
- package/dist/type.d.ts +43 -0
- package/dist/type.d.ts.map +1 -0
- package/dist/type.js +3 -0
- package/dist/type.js.map +1 -0
- package/dist/utils/tools.d.ts +4 -4
- package/dist/utils/tools.d.ts.map +1 -1
- package/dist/utils/tools.js +8 -5
- package/dist/utils/tools.js.map +1 -1
- package/package.json +6 -9
- package/src/bitcoin-interface-ordinal.ts +181 -0
- package/src/bitcoin-interface-teleswap.ts +255 -0
- package/src/bitcoin-interface-utils.ts +1 -1
- package/src/bitcoin-interface.ts +99 -303
- package/src/bitcoin-utils.ts +65 -90
- package/src/{bitcoin-base.ts → bitcoin-wallet-base.ts} +24 -19
- package/src/helper/brc20-helper.ts +181 -0
- package/src/helper/index.ts +3 -0
- package/src/helper/ordinal-helper.ts +118 -0
- package/src/helper/teleswap-helper.ts +300 -0
- package/src/index.ts +11 -3
- package/src/ordinal-wallet.ts +738 -0
- package/src/sign/sign-transaction.ts +42 -33
- package/src/teleswap-wallet.ts +155 -0
- package/src/transaction-builder/bitcoin-transaction-builder.ts +7 -24
- package/src/transaction-builder/index.ts +2 -1
- package/src/transaction-builder/ordinal-transaction-builder.ts +147 -0
- package/src/transaction-builder/transaction-builder.ts +33 -15
- package/src/type.ts +43 -0
- package/src/utils/tools.ts +17 -11
- package/tsconfig.json +1 -2
- package/dist/bitcoin-base.d.ts.map +0 -1
- package/dist/bitcoin-base.js.map +0 -1
- package/dist/bitcoin-utils-2.d.ts +0 -2
- package/dist/bitcoin-utils-2.d.ts.map +0 -1
- package/dist/bitcoin-utils-2.js +0 -13
- package/dist/bitcoin-utils-2.js.map +0 -1
- package/dist/bundle.js +0 -17
- package/dist/helper/burn-request-helper.d.ts +0 -7
- package/dist/helper/burn-request-helper.d.ts.map +0 -1
- package/dist/helper/burn-request-helper.js +0 -26
- package/dist/helper/burn-request-helper.js.map +0 -1
- package/dist/helper/teleport-request-helper.d.ts +0 -47
- package/dist/helper/teleport-request-helper.d.ts.map +0 -1
- package/dist/helper/teleport-request-helper.js +0 -146
- package/dist/helper/teleport-request-helper.js.map +0 -1
- package/dist/mempool-space.d.ts +0 -69
- package/dist/mempool-space.d.ts.map +0 -1
- package/dist/mempool-space.js +0 -266
- package/dist/mempool-space.js.map +0 -1
- package/dist/teleport-dao-payments.d.ts +0 -76
- package/dist/teleport-dao-payments.d.ts.map +0 -1
- package/dist/teleport-dao-payments.js +0 -217
- package/dist/teleport-dao-payments.js.map +0 -1
- package/src/helper/burn-request-helper.js +0 -27
- package/src/helper/teleport-request-helper.js +0 -181
- package/src/teleport-dao-payments.ts +0 -347
package/src/bitcoin-utils.ts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
3
2
|
import * as bip39 from "bip39"
|
|
4
3
|
import BIP32Factory from "bip32"
|
|
5
4
|
import * as ecc from "@bitcoinerlab/secp256k1"
|
|
6
5
|
import * as bitcoin from "bitcoinjs-lib"
|
|
7
6
|
import * as bitcoinEcPair from "bitcoinjs-ecpair"
|
|
7
|
+
import networks from "./utils/networks"
|
|
8
|
+
import { Transaction } from "./type"
|
|
8
9
|
|
|
9
10
|
const bip32 = BIP32Factory(ecc)
|
|
10
|
-
const ECPair = bitcoinEcPair
|
|
11
|
+
const { ECPair } = bitcoinEcPair
|
|
11
12
|
|
|
12
13
|
bitcoin.initEccLib(ecc)
|
|
13
|
-
|
|
14
|
+
|
|
15
|
+
const varUnit = require("varuint-bitcoin")
|
|
14
16
|
const fastRoot = require("merkle-lib/fastRoot")
|
|
15
17
|
const merkle = require("merkle-lib")
|
|
16
18
|
const merkleProof = require("merkle-lib/proof")
|
|
@@ -201,12 +203,66 @@ export function parseBlockHeader(headerHex: string) {
|
|
|
201
203
|
}
|
|
202
204
|
}
|
|
203
205
|
|
|
206
|
+
export function getAddressType(address: string, network = bitcoin.networks.bitcoin) {
|
|
207
|
+
if (address.startsWith(`${network.bech32}1p`)) {
|
|
208
|
+
// todo validate p2tr address
|
|
209
|
+
return "p2tr"
|
|
210
|
+
}
|
|
211
|
+
if (address.startsWith(network.bech32)) {
|
|
212
|
+
bitcoin.address.fromBech32(address)
|
|
213
|
+
return "p2wpkh"
|
|
214
|
+
}
|
|
215
|
+
let base58Data = bitcoin.address.fromBase58Check(address)
|
|
216
|
+
if (base58Data.version === Number(network.scriptHash)) {
|
|
217
|
+
return "p2sh"
|
|
218
|
+
}
|
|
219
|
+
if (base58Data.version === Number(network.pubKeyHash)) {
|
|
220
|
+
return "p2pkh"
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
throw new Error("invalid address")
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export function createAddressObjectByAddress(address: string, network = bitcoin.networks.bitcoin) {
|
|
227
|
+
let addressType = getAddressType(address, network)
|
|
228
|
+
let addressObject
|
|
229
|
+
switch (addressType) {
|
|
230
|
+
case "p2pkh":
|
|
231
|
+
addressObject = bitcoin.payments.p2pkh({
|
|
232
|
+
address,
|
|
233
|
+
network,
|
|
234
|
+
})
|
|
235
|
+
break
|
|
236
|
+
case "p2wpkh":
|
|
237
|
+
addressObject = bitcoin.payments.p2wpkh({
|
|
238
|
+
address,
|
|
239
|
+
network,
|
|
240
|
+
})
|
|
241
|
+
break
|
|
242
|
+
case "p2sh":
|
|
243
|
+
addressObject = bitcoin.payments.p2sh({
|
|
244
|
+
address,
|
|
245
|
+
network,
|
|
246
|
+
})
|
|
247
|
+
break
|
|
248
|
+
case "p2tr":
|
|
249
|
+
addressObject = bitcoin.payments.p2tr({
|
|
250
|
+
address,
|
|
251
|
+
network,
|
|
252
|
+
})
|
|
253
|
+
break
|
|
254
|
+
default:
|
|
255
|
+
throw new Error("address type is incorrect")
|
|
256
|
+
}
|
|
257
|
+
return { addressObject, addressType }
|
|
258
|
+
}
|
|
259
|
+
|
|
204
260
|
// used in block parser functions ( newt 2 functions )
|
|
205
261
|
export function convertBitcoinScriptToAddress(script: Buffer, network = bitcoin.networks.bitcoin) {
|
|
206
262
|
try {
|
|
207
263
|
return bitcoin.address.fromOutputScript(script, network)
|
|
208
264
|
} catch (error) {
|
|
209
|
-
return
|
|
265
|
+
return undefined
|
|
210
266
|
}
|
|
211
267
|
}
|
|
212
268
|
|
|
@@ -250,7 +306,7 @@ export function extractTransactionsAndBlockInfoFromRawBlock(
|
|
|
250
306
|
inputTxIds: {
|
|
251
307
|
txId: string
|
|
252
308
|
index: number
|
|
253
|
-
address
|
|
309
|
+
address: string
|
|
254
310
|
script?: string
|
|
255
311
|
value?: number
|
|
256
312
|
}[] = [],
|
|
@@ -274,32 +330,6 @@ export function extractTransactionsAndBlockInfoFromRawBlock(
|
|
|
274
330
|
|
|
275
331
|
let blockTxIds = block.transactions!.map((tx) => tx.getId())
|
|
276
332
|
|
|
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
333
|
let withdrawTxs: Transaction[] = []
|
|
304
334
|
let depositTxs: Transaction[] = []
|
|
305
335
|
block.transactions?.forEach((tx) => {
|
|
@@ -333,9 +363,9 @@ export function extractTransactionsAndBlockInfoFromRawBlock(
|
|
|
333
363
|
return {
|
|
334
364
|
txId: Buffer.from(vi.hash).reverse().toString("hex"),
|
|
335
365
|
index: vi.index,
|
|
336
|
-
address: viInput?.address
|
|
337
|
-
script: viInput?.script
|
|
338
|
-
value: viInput?.value
|
|
366
|
+
address: viInput?.address,
|
|
367
|
+
script: viInput?.script,
|
|
368
|
+
value: viInput?.value,
|
|
339
369
|
}
|
|
340
370
|
}),
|
|
341
371
|
address: inputTxAddress,
|
|
@@ -359,7 +389,6 @@ export function extractTransactionsAndBlockInfoFromRawBlock(
|
|
|
359
389
|
})
|
|
360
390
|
|
|
361
391
|
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
392
|
let txMerkleProof = calculateMerkleProof(blockTxIds, txId, merkleRoot)
|
|
364
393
|
depositTxs.push({
|
|
365
394
|
txId: tx.getId(),
|
|
@@ -412,26 +441,6 @@ function toXOnlyPublicKey(pubKey: Buffer) {
|
|
|
412
441
|
return pubKey.length === 32 ? pubKey : pubKey.slice(1, 33)
|
|
413
442
|
}
|
|
414
443
|
|
|
415
|
-
export function getAddressType(address: string, network = bitcoin.networks.bitcoin) {
|
|
416
|
-
if (address.startsWith(`${network.bech32}1p`)) {
|
|
417
|
-
// todo validate p2tr address
|
|
418
|
-
return "p2tr"
|
|
419
|
-
}
|
|
420
|
-
if (address.startsWith(network.bech32)) {
|
|
421
|
-
bitcoin.address.fromBech32(address)
|
|
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
444
|
export function createAddressObjectByScript(
|
|
436
445
|
{ addressType, script }: { addressType: string; script: Buffer },
|
|
437
446
|
network: bitcoin.Network = bitcoin.networks.bitcoin,
|
|
@@ -556,40 +565,6 @@ export function createAddressObjectByPublicKey(
|
|
|
556
565
|
return addressObject
|
|
557
566
|
}
|
|
558
567
|
|
|
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
568
|
export function publicKeyConvertor(publicKeyHex: string, compressed = true) {
|
|
594
569
|
let pubkey = ECPair.fromPublicKey(Buffer.from(publicKeyHex, "hex"), {
|
|
595
570
|
compressed,
|
|
@@ -1,23 +1,21 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
} from "
|
|
1
|
+
import * as bip39 from "bip39"
|
|
2
|
+
import { hdWalletPath } from "@teleportdao/configs"
|
|
3
|
+
import { Network, Payment } from "bitcoinjs-lib"
|
|
4
|
+
import BIP32Factory from "bip32"
|
|
5
|
+
import ecc from "@bitcoinerlab/secp256k1"
|
|
6
|
+
import { BitcoinTransactionBuilder } from "./transaction-builder"
|
|
7
|
+
import type { BitcoinConnectionInfo } from "./type"
|
|
4
8
|
|
|
5
9
|
import type { ExtendedUtxo, SignerInfo, Target } from "./transaction-builder/transaction-builder"
|
|
6
10
|
import BitcoinSign from "./sign/sign-transaction"
|
|
7
11
|
|
|
8
|
-
import * as bip39 from "bip39"
|
|
9
|
-
import { hdWalletPath } from "@teleportdao/configs"
|
|
10
12
|
import { getPubKeyFromPrivateKeyHex } from "./bitcoin-utils"
|
|
11
13
|
import networks from "./utils/networks"
|
|
12
|
-
import { Network, Payment, Psbt } from "bitcoinjs-lib"
|
|
13
14
|
import { BitcoinInterface } from "./bitcoin-interface"
|
|
14
15
|
|
|
15
|
-
import BIP32Factory from "bip32"
|
|
16
|
-
import ecc from "@bitcoinerlab/secp256k1"
|
|
17
|
-
|
|
18
16
|
const bip32 = BIP32Factory(ecc)
|
|
19
17
|
|
|
20
|
-
class
|
|
18
|
+
export class BitcoinBaseWallet {
|
|
21
19
|
network: Network
|
|
22
20
|
hdWalletPath: {
|
|
23
21
|
p2pkh: string
|
|
@@ -28,7 +26,7 @@ class BitcoinBase {
|
|
|
28
26
|
"p2sh-p2wsh": string
|
|
29
27
|
p2tr: string
|
|
30
28
|
}
|
|
31
|
-
transactionBuilder:
|
|
29
|
+
transactionBuilder: BitcoinTransactionBuilder
|
|
32
30
|
btcInterface: BitcoinInterface
|
|
33
31
|
signer: BitcoinSign
|
|
34
32
|
currentAccount?: string
|
|
@@ -42,7 +40,6 @@ class BitcoinBase {
|
|
|
42
40
|
networkName: string,
|
|
43
41
|
connectionInfo: BitcoinConnectionInfo = {
|
|
44
42
|
api: {
|
|
45
|
-
enabled: true,
|
|
46
43
|
provider: "BlockStream",
|
|
47
44
|
},
|
|
48
45
|
},
|
|
@@ -50,7 +47,11 @@ class BitcoinBase {
|
|
|
50
47
|
this.network = networks[networkName]
|
|
51
48
|
this.hdWalletPath = hdWalletPath.bitcoin
|
|
52
49
|
|
|
53
|
-
this.transactionBuilder = new
|
|
50
|
+
this.transactionBuilder = new BitcoinTransactionBuilder(
|
|
51
|
+
connectionInfo,
|
|
52
|
+
networkName,
|
|
53
|
+
this.network,
|
|
54
|
+
)
|
|
54
55
|
this.btcInterface = this.transactionBuilder.btcInterface
|
|
55
56
|
|
|
56
57
|
this.signer = new BitcoinSign(this.network)
|
|
@@ -126,6 +127,8 @@ class BitcoinBase {
|
|
|
126
127
|
|
|
127
128
|
// todo : not completed
|
|
128
129
|
setMultiSigAccount(accountType = "p2sh") {
|
|
130
|
+
throw new Error("not supported yet")
|
|
131
|
+
|
|
129
132
|
/* eslint-disable no-unreachable */
|
|
130
133
|
// todo : not completed
|
|
131
134
|
switch (accountType) {
|
|
@@ -150,10 +153,6 @@ class BitcoinBase {
|
|
|
150
153
|
this.publicKey = publicKey
|
|
151
154
|
}
|
|
152
155
|
|
|
153
|
-
setAccountPublicKey(publicKeyHex: string) {
|
|
154
|
-
this.publicKey = Buffer.from(publicKeyHex, "hex")
|
|
155
|
-
}
|
|
156
|
-
|
|
157
156
|
setAccountPrivateKeyByMnemonic({
|
|
158
157
|
mnemonic,
|
|
159
158
|
mnemonicPassword = "",
|
|
@@ -182,6 +181,10 @@ class BitcoinBase {
|
|
|
182
181
|
return this.setAccount(addressType)
|
|
183
182
|
}
|
|
184
183
|
|
|
184
|
+
setAccountPublicKey(publicKeyHex: string) {
|
|
185
|
+
this.publicKey = Buffer.from(publicKeyHex, "hex")
|
|
186
|
+
}
|
|
187
|
+
|
|
185
188
|
setAccount(accountType = "p2pkh") {
|
|
186
189
|
if (!this.publicKey) {
|
|
187
190
|
throw new Error("account not initialized")
|
|
@@ -197,6 +200,8 @@ class BitcoinBase {
|
|
|
197
200
|
return addressObj.address
|
|
198
201
|
}
|
|
199
202
|
|
|
203
|
+
//
|
|
204
|
+
|
|
200
205
|
async getExtendedUtxo(input: SignerInfo) {
|
|
201
206
|
return this.transactionBuilder.getExtendedUtxo(input)
|
|
202
207
|
}
|
|
@@ -266,7 +271,7 @@ class BitcoinBase {
|
|
|
266
271
|
changeAddress: string,
|
|
267
272
|
staticFeeRate?: number,
|
|
268
273
|
) {
|
|
269
|
-
let transaction = await this.btcInterface.getTransaction(txId)
|
|
274
|
+
let transaction = await this.btcInterface.apiProvider.getTransaction(txId)
|
|
270
275
|
|
|
271
276
|
let extendedUtxo = transaction.vin.map((vi) => ({
|
|
272
277
|
signerInfo: signerInfos.find((s) => s.address === vi.address)!,
|
|
@@ -303,7 +308,7 @@ class BitcoinBase {
|
|
|
303
308
|
targets,
|
|
304
309
|
feeRate,
|
|
305
310
|
changeAddress: changeIndex >= 0 ? transaction.vout[changeIndex].address : changeAddress,
|
|
311
|
+
selectType: "inOrder",
|
|
306
312
|
})
|
|
307
313
|
}
|
|
308
314
|
}
|
|
309
|
-
export { BitcoinBase }
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import BigNumber from "bignumber.js"
|
|
2
|
+
import { brc20 } from "@teleportdao/configs"
|
|
3
|
+
|
|
4
|
+
export type WrapOpReturn = {
|
|
5
|
+
chainId: number
|
|
6
|
+
appId: number
|
|
7
|
+
brc20TokenId: number
|
|
8
|
+
recipientAddress: string
|
|
9
|
+
inputAmount: string
|
|
10
|
+
outputAmount?: string
|
|
11
|
+
outputToken?: string
|
|
12
|
+
thirdPartyId?: number
|
|
13
|
+
}
|
|
14
|
+
export type WrapOpReturnAndType = WrapOpReturn & {
|
|
15
|
+
requestType: "wrap" | "wrapAndExchange"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const brc20WrapRequests = brc20.requestAppId
|
|
19
|
+
|
|
20
|
+
export function generateBrc2OpReturn({
|
|
21
|
+
chainId,
|
|
22
|
+
appId,
|
|
23
|
+
brc20TokenId,
|
|
24
|
+
inputAmount,
|
|
25
|
+
recipientAddress,
|
|
26
|
+
thirdPartyId = 0,
|
|
27
|
+
isExchange = false,
|
|
28
|
+
outputToken,
|
|
29
|
+
outputAmount,
|
|
30
|
+
}: WrapOpReturn & {
|
|
31
|
+
isExchange?: boolean
|
|
32
|
+
}) {
|
|
33
|
+
let data = ""
|
|
34
|
+
if (chainId.toString(16).length > 4) throw new Error("chainId should be less than 2 bytes")
|
|
35
|
+
data += chainId.toString(16).padStart(4, "0") // 2 bytes
|
|
36
|
+
data += appId.toString(16).padStart(2, "0") // 1 bytes
|
|
37
|
+
data += brc20TokenId.toString(16).padStart(4, "0") // 2 bytes
|
|
38
|
+
data += BigNumber(inputAmount).toString(16).padStart(26, "0") // 13 bytes
|
|
39
|
+
data += recipientAddress.replace("0x", "").toLowerCase().padStart(40, "0") // 20 bytes
|
|
40
|
+
data += BigNumber(thirdPartyId).toString(16).padStart(2, "0") // 1 bytes
|
|
41
|
+
if (isExchange) {
|
|
42
|
+
if (!outputAmount || !outputToken) {
|
|
43
|
+
throw new Error("outputAmount and outputToken are required for exchange")
|
|
44
|
+
}
|
|
45
|
+
data += outputToken.replace("0x", "").toLowerCase().padStart(40, "0") // 20 bytes
|
|
46
|
+
data += BigNumber(outputAmount).toString(16).padStart(26, "0") // 13 bytes
|
|
47
|
+
}
|
|
48
|
+
return data
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function parseBrc20OpReturn(data: string) {
|
|
52
|
+
let parsedData: any = {}
|
|
53
|
+
parsedData.chainId = Number(`0x${data.slice(0, 4)}`) // 2 bytes
|
|
54
|
+
parsedData.appId = Number(`0x${data.slice(4, 6)}`) // 1 bytes
|
|
55
|
+
parsedData.brc20TokenId = Number(`0x${data.slice(6, 10)}`) // 2 bytes
|
|
56
|
+
parsedData.inputAmount = new BigNumber(`0x${data.slice(10, 36)}`).toFixed(0) // 11 bytes
|
|
57
|
+
parsedData.recipientAddress = `0x${data.slice(36, 76)}` // 20 bytes
|
|
58
|
+
parsedData.thirdPartyId = `0x${data.slice(76, 78)}` // 20 bytes
|
|
59
|
+
if (data.length === 78) {
|
|
60
|
+
parsedData.requestType = "wrap"
|
|
61
|
+
return {
|
|
62
|
+
status: true,
|
|
63
|
+
data: parsedData as WrapOpReturnAndType,
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
parsedData.outputToken = `0x${data.slice(78, 118)}` // 20 bytes
|
|
67
|
+
parsedData.outputAmount = new BigNumber(`0x${data.slice(118, 144)}`).toFixed(0) // 20 bytes
|
|
68
|
+
if (data.length === 144) {
|
|
69
|
+
parsedData.requestType = "swapAndWrap"
|
|
70
|
+
return {
|
|
71
|
+
status: true,
|
|
72
|
+
data: parsedData as WrapOpReturnAndType,
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
status: false,
|
|
78
|
+
message: `invalid OP_RETURN data for requestType: 'wrap or exchange'. invalid data length : ${data.length} - valid length : 144 , 78`,
|
|
79
|
+
code: "INVALID_OP_RETURN",
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function parseBrc20RawRequest(opReturnData: string): {
|
|
84
|
+
status: boolean
|
|
85
|
+
data?: WrapOpReturnAndType
|
|
86
|
+
message?: string
|
|
87
|
+
code?: string
|
|
88
|
+
} {
|
|
89
|
+
let data = opReturnData.slice(2, 4) === "4c" ? opReturnData.slice(6) : opReturnData.slice(4)
|
|
90
|
+
// eslint-disable-next-line no-unused-vars
|
|
91
|
+
let appIdHex = data.slice(4, 6) // 2 bytes
|
|
92
|
+
if (!appIdHex) {
|
|
93
|
+
return {
|
|
94
|
+
status: false,
|
|
95
|
+
message: `invalid OP_RETURN data : ${data}`,
|
|
96
|
+
code: "INVALID_APP_ID",
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let appId = Number(`0x${appIdHex}`) // 2 bytes
|
|
101
|
+
|
|
102
|
+
// get type base on appId
|
|
103
|
+
let requestType = Object.keys(brc20WrapRequests).find(
|
|
104
|
+
(key) =>
|
|
105
|
+
appId >= brc20WrapRequests[key as keyof typeof brc20WrapRequests].appIdRange[0] &&
|
|
106
|
+
appId <= brc20WrapRequests[key as keyof typeof brc20WrapRequests].appIdRange[1],
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
switch (requestType) {
|
|
110
|
+
case "wrap":
|
|
111
|
+
case "wrapAndExchange":
|
|
112
|
+
return parseBrc20OpReturn(data)
|
|
113
|
+
default:
|
|
114
|
+
return {
|
|
115
|
+
status: false,
|
|
116
|
+
message: `invalid appId : ${appId}`,
|
|
117
|
+
code: "INVALID_OP_RETURN",
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function checkAndParseBrc20Request(
|
|
123
|
+
vouts: {
|
|
124
|
+
address?: string
|
|
125
|
+
script: string
|
|
126
|
+
value: number
|
|
127
|
+
}[],
|
|
128
|
+
address: string,
|
|
129
|
+
): {
|
|
130
|
+
status: boolean
|
|
131
|
+
data?: WrapOpReturnAndType
|
|
132
|
+
dataOutputIndex?: number
|
|
133
|
+
lockerFeeValue?: number
|
|
134
|
+
lockerFeeOutputIndex?: number
|
|
135
|
+
brc20OutputIndex?: number
|
|
136
|
+
brc20OutputValue?: number
|
|
137
|
+
message?: string
|
|
138
|
+
code?: string
|
|
139
|
+
} {
|
|
140
|
+
let requestOutputIndex = vouts.findIndex((vout_) => vout_.script.startsWith("6a"))
|
|
141
|
+
if (requestOutputIndex >= 0) {
|
|
142
|
+
let opReturnData = vouts[requestOutputIndex]?.script
|
|
143
|
+
if (!opReturnData) {
|
|
144
|
+
return {
|
|
145
|
+
status: false,
|
|
146
|
+
message: "invalid OP_RETURN",
|
|
147
|
+
code: "INVALID_OP_RETURN",
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
let brc20Transfer = vouts[0]
|
|
152
|
+
if (brc20Transfer.address !== address || brc20Transfer.value < 546) {
|
|
153
|
+
return {
|
|
154
|
+
status: false,
|
|
155
|
+
message: "no brc20 transfer output",
|
|
156
|
+
code: "NO_BRC20_TRANSFER",
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
let dataResponse = parseBrc20RawRequest(opReturnData)
|
|
161
|
+
if (dataResponse.status) {
|
|
162
|
+
let lockerFeeOutputIndex = vouts.findIndex((vout_, i) => vout_.address === address && +i > 0)
|
|
163
|
+
let lockerFeeValue = lockerFeeOutputIndex >= 0 ? vouts[lockerFeeOutputIndex].value : 0
|
|
164
|
+
return {
|
|
165
|
+
status: true,
|
|
166
|
+
data: dataResponse.data!,
|
|
167
|
+
dataOutputIndex: requestOutputIndex,
|
|
168
|
+
lockerFeeValue,
|
|
169
|
+
lockerFeeOutputIndex,
|
|
170
|
+
brc20OutputIndex: 0,
|
|
171
|
+
brc20OutputValue: brc20Transfer.value,
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return dataResponse
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
status: false,
|
|
178
|
+
message: "transaction outputs should contain OP_RETURN",
|
|
179
|
+
code: "NO_OP_RETURN",
|
|
180
|
+
}
|
|
181
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import * as bitcoin from "bitcoinjs-lib"
|
|
2
|
+
import * as ecc from "tiny-secp256k1"
|
|
3
|
+
|
|
4
|
+
bitcoin.initEccLib(ecc)
|
|
5
|
+
|
|
6
|
+
// eslint-disable-next-line consistent-return
|
|
7
|
+
export function createAddressObjectByScriptNoType(
|
|
8
|
+
script: Buffer,
|
|
9
|
+
network: bitcoin.Network = bitcoin.networks.bitcoin,
|
|
10
|
+
) {
|
|
11
|
+
let addressObject: bitcoin.payments.Payment
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
addressObject = bitcoin.payments.p2pkh({
|
|
15
|
+
output: script,
|
|
16
|
+
network,
|
|
17
|
+
})
|
|
18
|
+
if (addressObject.address) {
|
|
19
|
+
return {
|
|
20
|
+
addressObject,
|
|
21
|
+
addressType: "p2pkh",
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
} catch (err) {
|
|
25
|
+
/* empty */
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
addressObject = bitcoin.payments.p2wpkh({
|
|
30
|
+
output: script,
|
|
31
|
+
network,
|
|
32
|
+
})
|
|
33
|
+
if (addressObject.address) {
|
|
34
|
+
return {
|
|
35
|
+
addressObject,
|
|
36
|
+
addressType: "p2wpkh",
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
} catch (err) {
|
|
40
|
+
/* empty */
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
addressObject = bitcoin.payments.p2sh({
|
|
45
|
+
output: script,
|
|
46
|
+
network,
|
|
47
|
+
})
|
|
48
|
+
if (addressObject.address) {
|
|
49
|
+
return {
|
|
50
|
+
addressObject,
|
|
51
|
+
addressType: "p2sh",
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
} catch (err) {
|
|
55
|
+
/* empty */
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
addressObject = bitcoin.payments.p2wsh({
|
|
60
|
+
output: script,
|
|
61
|
+
network,
|
|
62
|
+
})
|
|
63
|
+
if (addressObject.address) {
|
|
64
|
+
return {
|
|
65
|
+
addressObject,
|
|
66
|
+
addressType: "p2wsh",
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
} catch (err) {
|
|
70
|
+
/* empty */
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
addressObject = bitcoin.payments.p2tr({
|
|
75
|
+
output: script,
|
|
76
|
+
network,
|
|
77
|
+
})
|
|
78
|
+
if (addressObject.address) {
|
|
79
|
+
return {
|
|
80
|
+
addressObject,
|
|
81
|
+
addressType: "p2tr",
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
} catch (err) {
|
|
85
|
+
/* empty */
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function splitBuffer(buffer: Buffer, partLength: number) {
|
|
90
|
+
const parts: Buffer[] = []
|
|
91
|
+
for (let i = 0; i < buffer.length; i += partLength) {
|
|
92
|
+
const part = buffer.subarray(i, i + partLength)
|
|
93
|
+
parts.push(part)
|
|
94
|
+
}
|
|
95
|
+
return parts
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function getOrdinalScript(
|
|
99
|
+
file: { buffer: Buffer; type: string },
|
|
100
|
+
internalPublicKeyHex: string,
|
|
101
|
+
) {
|
|
102
|
+
let bufferParts = splitBuffer(file.buffer, 520)
|
|
103
|
+
const splittedFileHex = bufferParts.map((part) => part.toString("hex")).join(" ")
|
|
104
|
+
const fileTypeHex = Buffer.from(file.type!, "utf8").toString("hex")
|
|
105
|
+
const ORDINAL_ORD_HEX = Buffer.from("ord", "utf8").toString("hex")
|
|
106
|
+
const script = `${internalPublicKeyHex} OP_CHECKSIG OP_FALSE OP_IF ${ORDINAL_ORD_HEX} 00000000000000000000 ${fileTypeHex} OP_0 ${splittedFileHex} OP_ENDIF`
|
|
107
|
+
|
|
108
|
+
// we add 00000000000000000000 so we can modify INCORRECT OPCODE
|
|
109
|
+
const leafScript = Buffer.from(
|
|
110
|
+
bitcoin.script.fromASM(script).toString("hex").replace("0a00000000000000000000", "0101"),
|
|
111
|
+
"hex",
|
|
112
|
+
)
|
|
113
|
+
return leafScript
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function toXOnly(pubKey: Buffer) {
|
|
117
|
+
return pubKey.length === 32 ? pubKey : pubKey.subarray(1, 33)
|
|
118
|
+
}
|