@teleportdao/bitcoin 2.0.5 → 2.0.8

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.
Files changed (90) hide show
  1. package/dist/bitcoin-interface-ordinal.d.ts +108 -108
  2. package/dist/bitcoin-interface-ordinal.js +140 -140
  3. package/dist/bitcoin-interface-teleswap.d.ts +83 -101
  4. package/dist/bitcoin-interface-teleswap.d.ts.map +1 -1
  5. package/dist/bitcoin-interface-teleswap.js +119 -176
  6. package/dist/bitcoin-interface-teleswap.js.map +1 -1
  7. package/dist/bitcoin-interface-utils.d.ts +20 -20
  8. package/dist/bitcoin-interface-utils.js +45 -45
  9. package/dist/bitcoin-interface-wallet.d.ts +29 -28
  10. package/dist/bitcoin-interface-wallet.d.ts.map +1 -1
  11. package/dist/bitcoin-interface-wallet.js +126 -125
  12. package/dist/bitcoin-interface-wallet.js.map +1 -1
  13. package/dist/bitcoin-interface.d.ts +63 -66
  14. package/dist/bitcoin-interface.d.ts.map +1 -1
  15. package/dist/bitcoin-interface.js +112 -119
  16. package/dist/bitcoin-interface.js.map +1 -1
  17. package/dist/bitcoin-utils.d.ts +96 -96
  18. package/dist/bitcoin-utils.js +514 -514
  19. package/dist/bitcoin-wallet-base.d.ts +111 -111
  20. package/dist/bitcoin-wallet-base.d.ts.map +1 -1
  21. package/dist/bitcoin-wallet-base.js +258 -258
  22. package/dist/helper/brc20-helper.d.ts +42 -42
  23. package/dist/helper/brc20-helper.js +127 -127
  24. package/dist/helper/index.d.ts +3 -3
  25. package/dist/helper/index.js +29 -29
  26. package/dist/helper/ordinal-helper.d.ts +12 -12
  27. package/dist/helper/ordinal-helper.js +129 -129
  28. package/dist/helper/teleswap-helper.d.ts +95 -95
  29. package/dist/helper/teleswap-helper.js +186 -186
  30. package/dist/index.d.ts +12 -12
  31. package/dist/index.js +41 -41
  32. package/dist/ordinal-wallet.d.ts +492 -495
  33. package/dist/ordinal-wallet.d.ts.map +1 -1
  34. package/dist/ordinal-wallet.js +386 -386
  35. package/dist/ordinal-wallet.js.map +1 -1
  36. package/dist/sign/index.d.ts +1 -1
  37. package/dist/sign/index.js +8 -8
  38. package/dist/sign/sign-transaction.d.ts +12 -12
  39. package/dist/sign/sign-transaction.js +82 -82
  40. package/dist/teleswap-wallet.d.ts +45 -45
  41. package/dist/teleswap-wallet.js +68 -68
  42. package/dist/transaction-builder/bitcoin-transaction-builder.d.ts +9 -9
  43. package/dist/transaction-builder/bitcoin-transaction-builder.d.ts.map +1 -1
  44. package/dist/transaction-builder/bitcoin-transaction-builder.js +54 -54
  45. package/dist/transaction-builder/bitcoin-transaction-builder.js.map +1 -1
  46. package/dist/transaction-builder/index.d.ts +3 -3
  47. package/dist/transaction-builder/index.js +19 -19
  48. package/dist/transaction-builder/ordinal-transaction-builder.d.ts +63 -63
  49. package/dist/transaction-builder/ordinal-transaction-builder.js +125 -125
  50. package/dist/transaction-builder/transaction-builder.d.ts +223 -223
  51. package/dist/transaction-builder/transaction-builder.d.ts.map +1 -1
  52. package/dist/transaction-builder/transaction-builder.js +442 -447
  53. package/dist/transaction-builder/transaction-builder.js.map +1 -1
  54. package/dist/type.d.ts +55 -61
  55. package/dist/type.d.ts.map +1 -1
  56. package/dist/type.js +2 -2
  57. package/dist/utils/networks.d.ts +5 -5
  58. package/dist/utils/networks.js +53 -53
  59. package/dist/utils/tools.d.ts +18 -18
  60. package/dist/utils/tools.js +74 -74
  61. package/package.json +4 -4
  62. package/src/bitcoin-interface-ordinal.ts +185 -185
  63. package/src/bitcoin-interface-teleswap.ts +246 -251
  64. package/src/bitcoin-interface-utils.ts +60 -60
  65. package/src/bitcoin-interface-wallet.ts +112 -114
  66. package/src/bitcoin-interface.ts +146 -156
  67. package/src/bitcoin-utils.ts +591 -591
  68. package/src/bitcoin-wallet-base.ts +344 -344
  69. package/src/helper/brc20-helper.ts +179 -179
  70. package/src/helper/ordinal-helper.ts +118 -118
  71. package/src/index.ts +15 -15
  72. package/src/ordinal-wallet.ts +654 -659
  73. package/src/sign/index.ts +1 -1
  74. package/src/sign/sign-transaction.ts +108 -108
  75. package/src/teleswap-wallet.ts +133 -133
  76. package/src/transaction-builder/bitcoin-transaction-builder.ts +26 -26
  77. package/src/transaction-builder/index.ts +3 -3
  78. package/src/transaction-builder/ordinal-transaction-builder.ts +139 -139
  79. package/src/transaction-builder/transaction-builder.ts +686 -690
  80. package/src/type.ts +64 -74
  81. package/src/utils/networks.ts +33 -33
  82. package/src/utils/tools.ts +92 -92
  83. package/tsconfig.json +9 -9
  84. package/webpack.config.js +16 -16
  85. package/.tmp/block-parser.ts +0 -58
  86. package/.tmp/check.ts +0 -101
  87. package/.tmp/ordinal-helper.ts +0 -133
  88. package/.tmp/ordinal.ts +0 -25
  89. package/.tmp/psbt/sign-transaction.ts +0 -121
  90. package/.tmp/rbf.ts +0 -45
@@ -1,659 +1,654 @@
1
- import BigNumber from "bignumber.js"
2
- import { bitcoin as bitcoinProviders } from "@teleportdao/providers"
3
- import { OrdinalTransactionBuilder } from "./transaction-builder/ordinal-transaction-builder"
4
- import BitcoinSign from "./sign/sign-transaction"
5
- //
6
- import { BitcoinInterfaceOrdinal } from "./bitcoin-interface-ordinal"
7
- import { generateBrc2OpReturn } from "./helper/brc20-helper"
8
- import { sleep } from "./utils/tools"
9
- import { ChangeTarget, ExtendedUtxo, SignerInfo, Target } from "./transaction-builder"
10
- import { BitcoinBaseWallet, FeeRateType } from "./bitcoin-wallet-base"
11
- import { BTCTokenConnectionInfo, RPCConnectionInfo, UtxoConnectionInfo } from "./type"
12
-
13
- class OrdinalWallet extends BitcoinBaseWallet {
14
- unisat: bitcoinProviders.UniSat
15
- transactionBuilder: OrdinalTransactionBuilder
16
- btcInterface: BitcoinInterfaceOrdinal
17
- signer: BitcoinSign
18
- constructor(
19
- networkName: string,
20
- uniSatToken: string,
21
- connectionInfo: {
22
- // btcToken: BTCTokenConnectionInfo
23
- rpc: RPCConnectionInfo
24
- utxo?: UtxoConnectionInfo
25
- // rpc used for getRawTransaction in transaction builder if set (optional)
26
- },
27
- ) {
28
- if (!connectionInfo.rpc) {
29
- // because api providers usually don't support sending custom psbt include p2tr address so we need rpc provider
30
- throw new Error("rpc is required")
31
- }
32
- super(networkName, connectionInfo)
33
-
34
- this.transactionBuilder = new OrdinalTransactionBuilder(
35
- networkName,
36
- this.network,
37
- connectionInfo,
38
- )
39
- this.signer = new BitcoinSign(this.network)
40
- this.btcInterface = new BitcoinInterfaceOrdinal(connectionInfo, networkName, uniSatToken)
41
- this.unisat = this.btcInterface.unisat
42
- }
43
-
44
- static deployBRC20Data(tickName: string, max: number | string, limit: number | string) {
45
- let data = {
46
- p: "brc-20",
47
- op: "deploy",
48
- tick: tickName,
49
- max: `${max}`,
50
- lim: `${limit}`,
51
- }
52
- return {
53
- buffer: Buffer.from(JSON.stringify(data), "utf8"),
54
- type: "text/plain",
55
- // type: "application/json",
56
- }
57
- }
58
-
59
- static mintBRC20Data(tickName: string, amount: string | number) {
60
- if (BigNumber(amount).isLessThanOrEqualTo(0)) throw new Error("amount should be greater than 0")
61
- let data = {
62
- p: "brc-20",
63
- op: "mint",
64
- tick: tickName,
65
- amt: `${amount}`,
66
- }
67
- return {
68
- buffer: Buffer.from(JSON.stringify(data), "utf8"),
69
- type: "text/plain",
70
- // type: "application/json",
71
- }
72
- }
73
-
74
- static transferBRC20Data(tickName: string, amount: string | number) {
75
- if (BigNumber(amount).isLessThanOrEqualTo(0)) throw new Error("amount should be greater than 0")
76
- let data = {
77
- p: "brc-20",
78
- op: "transfer",
79
- tick: tickName,
80
- amt: `${amount}`,
81
- }
82
- return {
83
- buffer: Buffer.from(JSON.stringify(data), "utf8"),
84
- type: "text/plain",
85
- // type: "application/json",
86
- }
87
- }
88
-
89
- async inscribeOrdinalDepositUnsigned(
90
- file: {
91
- buffer: Buffer
92
- type: string
93
- },
94
- signer: SignerInfo,
95
- ordinalSigner?: SignerInfo,
96
- fee: FeeRateType = "normal",
97
- extendedUtxo?: ExtendedUtxo[],
98
- ) {
99
- const ordinalSignerPublicKey = ordinalSigner?.publicKey || signer.publicKey
100
- const publicKey = Buffer.from(ordinalSignerPublicKey, "hex")
101
- let transferOrdinal = this.transactionBuilder.createOrdinalAddress(file, publicKey)
102
- const leafScript = transferOrdinal.redeem.output
103
- const { ordinalAddress } = transferOrdinal
104
-
105
- let feeRate = await this.getFeeRate(fee)
106
- let extraFee = +(((400 + leafScript.length) / 4) * feeRate * 1.5).toFixed(0)
107
- let ordinalAmount = 600
108
-
109
- let utxo1: ExtendedUtxo[] =
110
- extendedUtxo || (await this.btcInterface.getBTCUtxo(signer.address, signer))
111
-
112
- let inscribeDepositUnsignedInfo = await this.sendBTCUnsignedTx(
113
- ordinalAddress,
114
- ordinalAmount + extraFee,
115
- signer,
116
- feeRate,
117
- utxo1,
118
- )
119
-
120
- return {
121
- inscribeDepositUnsignedInfo,
122
- transferOrdinal,
123
- }
124
- }
125
-
126
- async inscribeOrdinalUnsigned(
127
- file: {
128
- buffer: Buffer
129
- type: string
130
- },
131
- signer: SignerInfo,
132
- ordinalSigner?: SignerInfo,
133
- fee: FeeRateType = "normal",
134
- extendedUtxo?: ExtendedUtxo[],
135
- ) {
136
- const receiverAddress = ordinalSigner?.address || signer.address
137
- const { inscribeDepositUnsignedInfo, transferOrdinal } =
138
- await this.inscribeOrdinalDepositUnsigned(file, signer, ordinalSigner, fee, extendedUtxo)
139
- const { ordinalAddress } = transferOrdinal
140
- let ordinalAmount = 600
141
-
142
- if (!inscribeDepositUnsignedInfo.possibleTxId)
143
- throw new Error(
144
- "inscribeDepositUnsignedInfo.possibleTxId is required. inscriber address type is not p2tr",
145
- )
146
-
147
- let inscribeDeposit: {
148
- hash: string
149
- value: number
150
- index: number
151
- } = {
152
- hash: inscribeDepositUnsignedInfo.possibleTxId,
153
- value: inscribeDepositUnsignedInfo.outputs[0].value,
154
- index: 0,
155
- }
156
- let inscribeUnsignedInfo = this.transactionBuilder.createInscribeUnsignedTx(
157
- transferOrdinal,
158
- inscribeDeposit,
159
- receiverAddress,
160
- ordinalAmount,
161
- )
162
- return {
163
- inscribeDepositUnsignedInfo,
164
- inscribeUnsignedInfo,
165
- inscribeAddress: ordinalAddress,
166
- receiverAddress,
167
- }
168
- }
169
-
170
- async inscribeOrdinal(
171
- file: {
172
- buffer: Buffer
173
- type: string
174
- },
175
- fee: FeeRateType = "normal",
176
- extendedUtxo?: ExtendedUtxo[],
177
- ordinalReceiverAddress?: string,
178
- ) {
179
- if (!this.currentAccount || !this.currentAccountType || !this.publicKey || !this.privateKey) {
180
- throw new Error("account not initialized")
181
- }
182
- const receiverAddress = ordinalReceiverAddress || this.bitcoinAddress!
183
-
184
- const { inscribeDepositUnsignedInfo, transferOrdinal } =
185
- await this.inscribeOrdinalDepositUnsigned(
186
- file,
187
- this.signerInfo!,
188
- undefined,
189
- fee,
190
- extendedUtxo,
191
- )
192
- let ordinalUtxo = await this.btcInterface.getBTCUtxo(
193
- transferOrdinal.ordinalAddress,
194
- this.signerInfo!,
195
- )
196
-
197
- let inscribeDeposit: {
198
- inputs: {
199
- hash: string
200
- value: number
201
- index: number
202
- signerInfo: SignerInfo
203
- }[]
204
- hash: string
205
- value: number
206
- index: number
207
- change?: ChangeTarget
208
- changeIndex?: number
209
- }
210
-
211
- if (ordinalUtxo.length > 1) {
212
- throw new Error("multiple deposit found for this ordinal address")
213
- }
214
-
215
- if (
216
- ordinalUtxo.length === 0 ||
217
- ordinalUtxo[0].value <
218
- inscribeDepositUnsignedInfo.outputs[0].value -
219
- inscribeDepositUnsignedInfo.outputs[0].value * 0.15
220
- ) {
221
- const signedPsbt1 = await this.signer.signPsbt(inscribeDepositUnsignedInfo, this.privateKey!)
222
- console.log("inscribe deposit tx ...")
223
- const inscribeDepositTxId = await this.sendSignedPsbt(signedPsbt1)
224
- console.log(`inscribe deposit txId : ${inscribeDepositTxId}`)
225
-
226
- inscribeDeposit = {
227
- hash: inscribeDepositTxId,
228
- value: inscribeDepositUnsignedInfo.outputs[0].value,
229
- index: 0,
230
- inputs: inscribeDepositUnsignedInfo.inputs,
231
- change: inscribeDepositUnsignedInfo.change,
232
- changeIndex: inscribeDepositUnsignedInfo.change
233
- ? inscribeDepositUnsignedInfo.outputs.length
234
- : undefined,
235
- }
236
- } else {
237
- inscribeDeposit = {
238
- hash: ordinalUtxo[0].hash,
239
- value: ordinalUtxo[0].value,
240
- index: ordinalUtxo[0].index,
241
- inputs: [],
242
- }
243
- console.log("no need to deposit", inscribeDeposit)
244
- }
245
-
246
- const ordinalAmount = 600
247
- let inscribeUnsignedInfo = this.transactionBuilder.createInscribeUnsignedTx(
248
- transferOrdinal,
249
- inscribeDeposit,
250
- receiverAddress,
251
- ordinalAmount,
252
- )
253
-
254
- const signedPsbt2 = await this.signer.signPsbt(
255
- inscribeUnsignedInfo,
256
- this.privateKey!,
257
- undefined,
258
- false,
259
- )
260
-
261
- console.log("inscribeTxId ...")
262
- await sleep(10 * 1000)
263
- let inscribeTxId = await this.sendSignedPsbtWithRetry(signedPsbt2)
264
- console.log("inscribeTxId", inscribeTxId)
265
- return {
266
- inscribeTx: { hash: inscribeTxId, index: 0, value: ordinalAmount },
267
- inscribeDepositTx: inscribeDeposit,
268
- inscribeAddress: transferOrdinal.ordinalAddress,
269
- }
270
- }
271
-
272
- async deployBrc20(
273
- brc: { tick: string; max: number; limit: number },
274
- fee: FeeRateType = "normal",
275
- extendedUtxo?: ExtendedUtxo[],
276
- ) {
277
- let file = OrdinalWallet.deployBRC20Data(brc.tick, brc.max, brc.limit)
278
- return this.inscribeOrdinal(file, fee, extendedUtxo)
279
- }
280
-
281
- async mintBrc20(
282
- brc: { tick: string; amount: number | string },
283
- fee: FeeRateType = "normal",
284
- extendedUtxo?: ExtendedUtxo[],
285
- ) {
286
- let file = OrdinalWallet.mintBRC20Data(brc.tick, brc.amount)
287
- return this.inscribeOrdinal(file, fee, extendedUtxo)
288
- }
289
-
290
- async inscribeBrc20Unsigned(
291
- brc: { tick: string; amount: number | string },
292
- signer: SignerInfo,
293
- ordinalSigner?: SignerInfo,
294
- fee: FeeRateType = "normal",
295
- extendedUtxo?: ExtendedUtxo[],
296
- ) {
297
- let file = OrdinalWallet.transferBRC20Data(brc.tick, brc.amount)
298
- return this.inscribeOrdinalUnsigned(file, signer, ordinalSigner, fee, extendedUtxo)
299
- }
300
-
301
- async inscribeBrc20(
302
- brc: { tick: string; amount: number | string },
303
- fee: FeeRateType = "normal",
304
- extendedUtxo?: ExtendedUtxo[],
305
- ) {
306
- let file = OrdinalWallet.transferBRC20Data(brc.tick, brc.amount)
307
- return this.inscribeOrdinal(file, fee, extendedUtxo)
308
- }
309
-
310
- async transferBrc20Unsigned(
311
- receiver: string,
312
- brcInscribeUtxo: {
313
- hash: string
314
- value: number
315
- index: number
316
- },
317
- signer: SignerInfo,
318
- ordinalSigner?: SignerInfo,
319
- fee: FeeRateType = "normal",
320
- extendedUtxo?: ExtendedUtxo[],
321
- otherTargets?: Target[],
322
- ) {
323
- const ordinalSignerInfo = ordinalSigner || signer
324
- let utxo = extendedUtxo || (await this.btcInterface.getBTCUtxo(signer.address, signer))
325
- let feeRate = await this.getFeeRate(fee)
326
- let unsignedTx = await this.transactionBuilder.createNftPsbt({
327
- extendedUtxo: utxo,
328
- nftExtendedUtxo: {
329
- hash: brcInscribeUtxo.hash,
330
- index: 0,
331
- value: brcInscribeUtxo.value,
332
- signerInfo: ordinalSignerInfo,
333
- },
334
- feeRate,
335
- receiverAddress: receiver,
336
- changeAddress: signer.address,
337
- otherTargets,
338
- })
339
- return {
340
- ...unsignedTx,
341
- possibleTxId: this.transactionBuilder.getUnsignedPsbtTxId(unsignedTx.unsignedTransaction),
342
- }
343
- }
344
-
345
- async transferBrc20(
346
- receiver: string,
347
- brcInscribeUtxo: {
348
- hash: string
349
- value: number
350
- index: number
351
- },
352
- fee: FeeRateType = "normal",
353
- extendedUtxo: ExtendedUtxo[],
354
- otherTargets?: Target[],
355
- ) {
356
- if (!this.currentAccount || !this.currentAccountType || !this.publicKey || !this.privateKey) {
357
- throw new Error("account not initialized")
358
- }
359
- let feeRate = await this.getFeeRate(fee)
360
- let unsignedTx = await this.transactionBuilder.createNftPsbt({
361
- extendedUtxo,
362
- nftExtendedUtxo: {
363
- hash: brcInscribeUtxo.hash,
364
- index: 0,
365
- value: brcInscribeUtxo.value,
366
- signerInfo: this.signerInfo!,
367
- },
368
- feeRate,
369
- receiverAddress: receiver,
370
- changeAddress: this.bitcoinAddress!,
371
- otherTargets,
372
- })
373
-
374
- let signedTx = await this.signer.signPsbt(unsignedTx, this.privateKey!)
375
- let finalTransferTxId = await this.sendSignedPsbtWithRetry(signedTx)
376
- return {
377
- hash: finalTransferTxId,
378
- index: 0,
379
- value: brcInscribeUtxo.value,
380
- inputs: unsignedTx.inputs,
381
- change: unsignedTx.change,
382
- changeIndex: unsignedTx.change ? unsignedTx.outputs.length : undefined,
383
- }
384
- }
385
-
386
- async inscribeAndTransferBrc20Unsigned(
387
- receiver: string,
388
- brc: { tick: string; amount: number | string },
389
- signer: SignerInfo,
390
- ordinalSigner?: SignerInfo,
391
- otherTargets?: Target[],
392
- fee: FeeRateType = "normal",
393
- extendedUtxo?: ExtendedUtxo[],
394
- ) {
395
- const ordinalSignerInfo = ordinalSigner || signer
396
- // check all fee before process transaction
397
- let brc20Balance = await this.unisat.getBrc20AddressBalanceForTicker(signer.address, brc.tick)
398
-
399
- if (BigNumber(brc20Balance.transferableBalance).gte(brc.amount)) {
400
- let transferrableInscription = brc20Balance.transferableInscriptions.find(
401
- (insc) => insc.data.tick === brc.tick && BigNumber(insc.data.amt).isEqualTo(brc.amount),
402
- )
403
-
404
- console.log("transferrableInscription", transferrableInscription)
405
- }
406
-
407
- if (BigNumber(brc20Balance.availableBalanceSafe).isLessThan(brc.amount)) {
408
- throw new Error("insufficient balance")
409
- }
410
-
411
- let feeRate = await this.getFeeRate(fee)
412
-
413
- let utxo1: ExtendedUtxo[] =
414
- extendedUtxo || (await this.btcInterface.getBTCUtxo(signer.address, signer))
415
- let utxo2: ExtendedUtxo[] = []
416
- const { inscribeAddress, inscribeDepositUnsignedInfo, inscribeUnsignedInfo } =
417
- await this.inscribeBrc20Unsigned(brc, signer, ordinalSignerInfo, feeRate, utxo1)
418
-
419
- utxo2 = utxo1.filter(
420
- (u) =>
421
- inscribeDepositUnsignedInfo.inputs.findIndex(
422
- (i) => i.hash === u.hash && i.index === u.index,
423
- ) === -1,
424
- )
425
-
426
- if (inscribeDepositUnsignedInfo.change) {
427
- if (!inscribeDepositUnsignedInfo.possibleTxId) {
428
- throw new Error("inscribeDepositUnsignedInfo.possibleTxId is required")
429
- }
430
- utxo2.push({
431
- hash: inscribeDepositUnsignedInfo.possibleTxId,
432
- index: inscribeDepositUnsignedInfo.outputs.length,
433
- value: inscribeDepositUnsignedInfo.change.value,
434
- signerInfo: signer,
435
- })
436
- }
437
- let transferTxUnsignedInfo = await this.transferBrc20Unsigned(
438
- receiver,
439
- {
440
- hash: inscribeUnsignedInfo.possibleTxId,
441
- value: inscribeUnsignedInfo.outputs[0].value,
442
- index: 0,
443
- },
444
- signer,
445
- ordinalSignerInfo,
446
- feeRate,
447
- utxo2,
448
- otherTargets,
449
- )
450
- return {
451
- inscribeDepositUnsignedInfo,
452
- inscribeUnsignedInfo,
453
- transferTxUnsignedInfo,
454
- inscribeAddress,
455
- }
456
- }
457
-
458
- async inscribeAndTransferBrc20(
459
- receiver: string,
460
- brc: { tick: string; amount: number | string },
461
- otherTargets?: Target[],
462
- fee: FeeRateType = "normal",
463
- extendedUtxo?: ExtendedUtxo[],
464
- ) {
465
- // check all fee before process transaction
466
- let brc20Balance = await this.unisat.getBrc20AddressBalanceForTicker(
467
- this.bitcoinAddress!,
468
- brc.tick,
469
- )
470
-
471
- if (BigNumber(brc20Balance.transferableBalance).gte(brc.amount)) {
472
- let transferrableInscription = brc20Balance.transferableInscriptions.find(
473
- (insc) => insc.data.tick === brc.tick && BigNumber(insc.data.amt).isEqualTo(brc.amount),
474
- )
475
- console.log("transferrableInscription", transferrableInscription)
476
-
477
- if (transferrableInscription) {
478
- let ins = await this.btcInterface.unisat.getInscriptionInfo(
479
- transferrableInscription.inscriptionId,
480
- )
481
-
482
- if (ins) {
483
- let transferTx = await this.transferBrc20(
484
- receiver,
485
- {
486
- hash: ins.utxo.txid!,
487
- index: ins.utxo.vout!,
488
- value: ins.utxo.satoshi!,
489
- },
490
- await this.getFeeRate(fee),
491
- extendedUtxo ||
492
- (await this.btcInterface.getBTCUtxo(this.bitcoinAddress!, this.signerInfo!)),
493
- otherTargets,
494
- )
495
- return {
496
- transferTx,
497
- }
498
- }
499
- }
500
- }
501
-
502
- if (BigNumber(brc20Balance.availableBalanceSafe).isLessThan(brc.amount)) {
503
- throw new Error(`insufficient balance ${brc20Balance.availableBalanceSafe} ${brc.amount}`)
504
- }
505
-
506
- let feeRate = await this.getFeeRate(fee)
507
-
508
- let utxo1: ExtendedUtxo[] =
509
- extendedUtxo || (await this.btcInterface.getBTCUtxo(this.bitcoinAddress!, this.signerInfo!))
510
- let utxo2: ExtendedUtxo[] = []
511
- const { inscribeAddress, inscribeDepositTx, inscribeTx } = await this.inscribeBrc20(
512
- brc,
513
- feeRate,
514
- utxo1,
515
- )
516
-
517
- utxo2 = utxo1.filter(
518
- (u) =>
519
- inscribeDepositTx.inputs.findIndex((i) => i.hash === u.hash && i.index === u.index) === -1,
520
- )
521
-
522
- if (inscribeDepositTx.change) {
523
- utxo2.push({
524
- hash: inscribeDepositTx.hash,
525
- index: inscribeDepositTx.changeIndex!,
526
- value: inscribeDepositTx.change.value,
527
- signerInfo: this.signerInfo!,
528
- })
529
- }
530
- await sleep(10 * 1000)
531
- let transferTx = await this.transferBrc20(receiver, inscribeTx, feeRate, utxo2, otherTargets)
532
- return {
533
- inscribeTx,
534
- inscribeAddress,
535
- inscribeDepositTx,
536
- transferTx,
537
- }
538
- }
539
-
540
- async wrapBrc20Unsigned(
541
- recipientAddress: string,
542
- brc: { tick: string; amount: number | string },
543
- brc20TokenId: number,
544
- signer: SignerInfo,
545
- lockerAddress: string,
546
- exchange?: {
547
- outputToken: string
548
- outputAmount: string
549
- },
550
- ordinalSigner?: SignerInfo,
551
- fee: FeeRateType = "normal",
552
- extendedUtxo?: ExtendedUtxo[],
553
-
554
- { chainId = 137, appId = exchange ? 1 : 0 } = {},
555
- ) {
556
- const isExchange = !!exchange
557
- let dataHex = generateBrc2OpReturn({
558
- chainId,
559
- appId,
560
- brc20TokenId,
561
- inputAmount: BigNumber(brc.amount).multipliedBy(1e18).toFixed(0),
562
- recipientAddress,
563
- isExchange,
564
- outputToken: exchange?.outputToken,
565
- outputAmount: exchange?.outputAmount,
566
- })
567
- let opTarget = this.transactionBuilder.getOpReturnTarget(dataHex)
568
- return this.inscribeAndTransferBrc20Unsigned(
569
- lockerAddress,
570
- brc,
571
- signer,
572
- ordinalSigner,
573
- [opTarget],
574
- fee,
575
- extendedUtxo,
576
- )
577
- }
578
-
579
- async wrapBrc20OnlyTransferUnsigned(
580
- recipientAddress: string,
581
- brcInscribeTx: {
582
- hash: string
583
- value: number
584
- index: number
585
- },
586
- brc: { tick: string; amount: number | string },
587
- brc20TokenId: number,
588
- signer: SignerInfo,
589
- lockerAddress: string,
590
- exchange?: {
591
- outputToken: string
592
- outputAmount: string
593
- },
594
- ordinalSigner?: SignerInfo,
595
- fee: FeeRateType = "normal",
596
- extendedUtxo?: ExtendedUtxo[],
597
-
598
- { chainId = 137, appId = exchange ? 1 : 0 } = {},
599
- ) {
600
- let utxo: ExtendedUtxo[] =
601
- extendedUtxo || (await this.btcInterface.getBTCUtxo(signer.address, signer))
602
-
603
- const isExchange = !!exchange
604
- let dataHex = generateBrc2OpReturn({
605
- chainId,
606
- appId,
607
- brc20TokenId,
608
- inputAmount: BigNumber(brc.amount).multipliedBy(1e18).toFixed(0),
609
- recipientAddress,
610
- isExchange,
611
- outputToken: exchange?.outputToken,
612
- outputAmount: exchange?.outputAmount,
613
- })
614
- let opTarget = this.transactionBuilder.getOpReturnTarget(dataHex)
615
- let feeRate = await this.getFeeRate(fee)
616
- let transferTxUnsignedInfo = await this.transferBrc20Unsigned(
617
- lockerAddress,
618
- brcInscribeTx,
619
- signer,
620
- ordinalSigner,
621
- feeRate,
622
- utxo,
623
- [opTarget],
624
- )
625
- return transferTxUnsignedInfo
626
- }
627
-
628
- async wrapBrc20(
629
- recipientAddress: string,
630
- brc: { tick: string; amount: number | string },
631
- brc20TokenId: number,
632
- lockerAddress: string,
633
- exchange?: {
634
- outputToken: string
635
- outputAmount: string
636
- },
637
- fee: FeeRateType = "normal",
638
- extendedUtxo?: ExtendedUtxo[],
639
-
640
- { chainId = 137, appId = exchange ? 1 : 0 } = {},
641
- ) {
642
- const isExchange = !!exchange
643
-
644
- let dataHex = generateBrc2OpReturn({
645
- chainId,
646
- appId,
647
- brc20TokenId,
648
- inputAmount: BigNumber(brc.amount).multipliedBy(1e18).toFixed(0),
649
- recipientAddress,
650
- isExchange,
651
- outputToken: exchange?.outputToken,
652
- outputAmount: exchange?.outputAmount,
653
- })
654
- let opTarget = this.transactionBuilder.getOpReturnTarget(dataHex)
655
- return this.inscribeAndTransferBrc20(lockerAddress, brc, [opTarget], fee, extendedUtxo)
656
- }
657
- }
658
-
659
- export default OrdinalWallet
1
+ import BigNumber from "bignumber.js"
2
+ import { bitcoin as bitcoinProviders } from "@teleportdao/providers"
3
+ import { OrdinalTransactionBuilder } from "./transaction-builder/ordinal-transaction-builder"
4
+ import BitcoinSign from "./sign/sign-transaction"
5
+ //
6
+ import { BitcoinInterfaceOrdinal } from "./bitcoin-interface-ordinal"
7
+ import { generateBrc2OpReturn } from "./helper/brc20-helper"
8
+ import { sleep } from "./utils/tools"
9
+ import { ChangeTarget, ExtendedUtxo, SignerInfo, Target } from "./transaction-builder"
10
+ import { BitcoinBaseWallet, FeeRateType } from "./bitcoin-wallet-base"
11
+ import { BitcoinTokenNodeConnectionInfo } from "./type"
12
+
13
+ class OrdinalWallet extends BitcoinBaseWallet {
14
+ unisat: bitcoinProviders.UniSat
15
+ transactionBuilder: OrdinalTransactionBuilder
16
+ btcInterface: BitcoinInterfaceOrdinal
17
+ signer: BitcoinSign
18
+ constructor(
19
+ networkName: string,
20
+ uniSatToken: string,
21
+ connectionInfo: BitcoinTokenNodeConnectionInfo,
22
+ ) {
23
+ if (!connectionInfo.rpc) {
24
+ // because api providers usually don't support sending custom psbt include p2tr address so we need rpc provider
25
+ throw new Error("rpc is required")
26
+ }
27
+ super(networkName, connectionInfo)
28
+
29
+ this.transactionBuilder = new OrdinalTransactionBuilder(
30
+ networkName,
31
+ this.network,
32
+ connectionInfo,
33
+ )
34
+ this.signer = new BitcoinSign(this.network)
35
+ this.btcInterface = new BitcoinInterfaceOrdinal(connectionInfo, networkName, uniSatToken)
36
+ this.unisat = this.btcInterface.unisat
37
+ }
38
+
39
+ static deployBRC20Data(tickName: string, max: number | string, limit: number | string) {
40
+ let data = {
41
+ p: "brc-20",
42
+ op: "deploy",
43
+ tick: tickName,
44
+ max: `${max}`,
45
+ lim: `${limit}`,
46
+ }
47
+ return {
48
+ buffer: Buffer.from(JSON.stringify(data), "utf8"),
49
+ type: "text/plain",
50
+ // type: "application/json",
51
+ }
52
+ }
53
+
54
+ static mintBRC20Data(tickName: string, amount: string | number) {
55
+ if (BigNumber(amount).isLessThanOrEqualTo(0)) throw new Error("amount should be greater than 0")
56
+ let data = {
57
+ p: "brc-20",
58
+ op: "mint",
59
+ tick: tickName,
60
+ amt: `${amount}`,
61
+ }
62
+ return {
63
+ buffer: Buffer.from(JSON.stringify(data), "utf8"),
64
+ type: "text/plain",
65
+ // type: "application/json",
66
+ }
67
+ }
68
+
69
+ static transferBRC20Data(tickName: string, amount: string | number) {
70
+ if (BigNumber(amount).isLessThanOrEqualTo(0)) throw new Error("amount should be greater than 0")
71
+ let data = {
72
+ p: "brc-20",
73
+ op: "transfer",
74
+ tick: tickName,
75
+ amt: `${amount}`,
76
+ }
77
+ return {
78
+ buffer: Buffer.from(JSON.stringify(data), "utf8"),
79
+ type: "text/plain",
80
+ // type: "application/json",
81
+ }
82
+ }
83
+
84
+ async inscribeOrdinalDepositUnsigned(
85
+ file: {
86
+ buffer: Buffer
87
+ type: string
88
+ },
89
+ signer: SignerInfo,
90
+ ordinalSigner?: SignerInfo,
91
+ fee: FeeRateType = "normal",
92
+ extendedUtxo?: ExtendedUtxo[],
93
+ ) {
94
+ const ordinalSignerPublicKey = ordinalSigner?.publicKey || signer.publicKey
95
+ const publicKey = Buffer.from(ordinalSignerPublicKey, "hex")
96
+ let transferOrdinal = this.transactionBuilder.createOrdinalAddress(file, publicKey)
97
+ const leafScript = transferOrdinal.redeem.output
98
+ const { ordinalAddress } = transferOrdinal
99
+
100
+ let feeRate = await this.getFeeRate(fee)
101
+ let extraFee = +(((400 + leafScript.length) / 4) * feeRate * 1.5).toFixed(0)
102
+ let ordinalAmount = 600
103
+
104
+ let utxo1: ExtendedUtxo[] =
105
+ extendedUtxo || (await this.btcInterface.getBTCUtxo(signer.address, signer))
106
+
107
+ let inscribeDepositUnsignedInfo = await this.sendBTCUnsignedTx(
108
+ ordinalAddress,
109
+ ordinalAmount + extraFee,
110
+ signer,
111
+ feeRate,
112
+ utxo1,
113
+ )
114
+
115
+ return {
116
+ inscribeDepositUnsignedInfo,
117
+ transferOrdinal,
118
+ }
119
+ }
120
+
121
+ async inscribeOrdinalUnsigned(
122
+ file: {
123
+ buffer: Buffer
124
+ type: string
125
+ },
126
+ signer: SignerInfo,
127
+ ordinalSigner?: SignerInfo,
128
+ fee: FeeRateType = "normal",
129
+ extendedUtxo?: ExtendedUtxo[],
130
+ ) {
131
+ const receiverAddress = ordinalSigner?.address || signer.address
132
+ const { inscribeDepositUnsignedInfo, transferOrdinal } =
133
+ await this.inscribeOrdinalDepositUnsigned(file, signer, ordinalSigner, fee, extendedUtxo)
134
+ const { ordinalAddress } = transferOrdinal
135
+ let ordinalAmount = 600
136
+
137
+ if (!inscribeDepositUnsignedInfo.possibleTxId)
138
+ throw new Error(
139
+ "inscribeDepositUnsignedInfo.possibleTxId is required. inscriber address type is not p2tr",
140
+ )
141
+
142
+ let inscribeDeposit: {
143
+ hash: string
144
+ value: number
145
+ index: number
146
+ } = {
147
+ hash: inscribeDepositUnsignedInfo.possibleTxId,
148
+ value: inscribeDepositUnsignedInfo.outputs[0].value,
149
+ index: 0,
150
+ }
151
+ let inscribeUnsignedInfo = this.transactionBuilder.createInscribeUnsignedTx(
152
+ transferOrdinal,
153
+ inscribeDeposit,
154
+ receiverAddress,
155
+ ordinalAmount,
156
+ )
157
+ return {
158
+ inscribeDepositUnsignedInfo,
159
+ inscribeUnsignedInfo,
160
+ inscribeAddress: ordinalAddress,
161
+ receiverAddress,
162
+ }
163
+ }
164
+
165
+ async inscribeOrdinal(
166
+ file: {
167
+ buffer: Buffer
168
+ type: string
169
+ },
170
+ fee: FeeRateType = "normal",
171
+ extendedUtxo?: ExtendedUtxo[],
172
+ ordinalReceiverAddress?: string,
173
+ ) {
174
+ if (!this.currentAccount || !this.currentAccountType || !this.publicKey || !this.privateKey) {
175
+ throw new Error("account not initialized")
176
+ }
177
+ const receiverAddress = ordinalReceiverAddress || this.bitcoinAddress!
178
+
179
+ const { inscribeDepositUnsignedInfo, transferOrdinal } =
180
+ await this.inscribeOrdinalDepositUnsigned(
181
+ file,
182
+ this.signerInfo!,
183
+ undefined,
184
+ fee,
185
+ extendedUtxo,
186
+ )
187
+ let ordinalUtxo = await this.btcInterface.getBTCUtxo(
188
+ transferOrdinal.ordinalAddress,
189
+ this.signerInfo!,
190
+ )
191
+
192
+ let inscribeDeposit: {
193
+ inputs: {
194
+ hash: string
195
+ value: number
196
+ index: number
197
+ signerInfo: SignerInfo
198
+ }[]
199
+ hash: string
200
+ value: number
201
+ index: number
202
+ change?: ChangeTarget
203
+ changeIndex?: number
204
+ }
205
+
206
+ if (ordinalUtxo.length > 1) {
207
+ throw new Error("multiple deposit found for this ordinal address")
208
+ }
209
+
210
+ if (
211
+ ordinalUtxo.length === 0 ||
212
+ ordinalUtxo[0].value <
213
+ inscribeDepositUnsignedInfo.outputs[0].value -
214
+ inscribeDepositUnsignedInfo.outputs[0].value * 0.15
215
+ ) {
216
+ const signedPsbt1 = await this.signer.signPsbt(inscribeDepositUnsignedInfo, this.privateKey!)
217
+ console.log("inscribe deposit tx ...")
218
+ const inscribeDepositTxId = await this.sendSignedPsbt(signedPsbt1)
219
+ console.log(`inscribe deposit txId : ${inscribeDepositTxId}`)
220
+
221
+ inscribeDeposit = {
222
+ hash: inscribeDepositTxId,
223
+ value: inscribeDepositUnsignedInfo.outputs[0].value,
224
+ index: 0,
225
+ inputs: inscribeDepositUnsignedInfo.inputs,
226
+ change: inscribeDepositUnsignedInfo.change,
227
+ changeIndex: inscribeDepositUnsignedInfo.change
228
+ ? inscribeDepositUnsignedInfo.outputs.length
229
+ : undefined,
230
+ }
231
+ } else {
232
+ inscribeDeposit = {
233
+ hash: ordinalUtxo[0].hash,
234
+ value: ordinalUtxo[0].value,
235
+ index: ordinalUtxo[0].index,
236
+ inputs: [],
237
+ }
238
+ console.log("no need to deposit", inscribeDeposit)
239
+ }
240
+
241
+ const ordinalAmount = 600
242
+ let inscribeUnsignedInfo = this.transactionBuilder.createInscribeUnsignedTx(
243
+ transferOrdinal,
244
+ inscribeDeposit,
245
+ receiverAddress,
246
+ ordinalAmount,
247
+ )
248
+
249
+ const signedPsbt2 = await this.signer.signPsbt(
250
+ inscribeUnsignedInfo,
251
+ this.privateKey!,
252
+ undefined,
253
+ false,
254
+ )
255
+
256
+ console.log("inscribeTxId ...")
257
+ await sleep(10 * 1000)
258
+ let inscribeTxId = await this.sendSignedPsbtWithRetry(signedPsbt2)
259
+ console.log("inscribeTxId", inscribeTxId)
260
+ return {
261
+ inscribeTx: { hash: inscribeTxId, index: 0, value: ordinalAmount },
262
+ inscribeDepositTx: inscribeDeposit,
263
+ inscribeAddress: transferOrdinal.ordinalAddress,
264
+ }
265
+ }
266
+
267
+ async deployBrc20(
268
+ brc: { tick: string; max: number; limit: number },
269
+ fee: FeeRateType = "normal",
270
+ extendedUtxo?: ExtendedUtxo[],
271
+ ) {
272
+ let file = OrdinalWallet.deployBRC20Data(brc.tick, brc.max, brc.limit)
273
+ return this.inscribeOrdinal(file, fee, extendedUtxo)
274
+ }
275
+
276
+ async mintBrc20(
277
+ brc: { tick: string; amount: number | string },
278
+ fee: FeeRateType = "normal",
279
+ extendedUtxo?: ExtendedUtxo[],
280
+ ) {
281
+ let file = OrdinalWallet.mintBRC20Data(brc.tick, brc.amount)
282
+ return this.inscribeOrdinal(file, fee, extendedUtxo)
283
+ }
284
+
285
+ async inscribeBrc20Unsigned(
286
+ brc: { tick: string; amount: number | string },
287
+ signer: SignerInfo,
288
+ ordinalSigner?: SignerInfo,
289
+ fee: FeeRateType = "normal",
290
+ extendedUtxo?: ExtendedUtxo[],
291
+ ) {
292
+ let file = OrdinalWallet.transferBRC20Data(brc.tick, brc.amount)
293
+ return this.inscribeOrdinalUnsigned(file, signer, ordinalSigner, fee, extendedUtxo)
294
+ }
295
+
296
+ async inscribeBrc20(
297
+ brc: { tick: string; amount: number | string },
298
+ fee: FeeRateType = "normal",
299
+ extendedUtxo?: ExtendedUtxo[],
300
+ ) {
301
+ let file = OrdinalWallet.transferBRC20Data(brc.tick, brc.amount)
302
+ return this.inscribeOrdinal(file, fee, extendedUtxo)
303
+ }
304
+
305
+ async transferBrc20Unsigned(
306
+ receiver: string,
307
+ brcInscribeUtxo: {
308
+ hash: string
309
+ value: number
310
+ index: number
311
+ },
312
+ signer: SignerInfo,
313
+ ordinalSigner?: SignerInfo,
314
+ fee: FeeRateType = "normal",
315
+ extendedUtxo?: ExtendedUtxo[],
316
+ otherTargets?: Target[],
317
+ ) {
318
+ const ordinalSignerInfo = ordinalSigner || signer
319
+ let utxo = extendedUtxo || (await this.btcInterface.getBTCUtxo(signer.address, signer))
320
+ let feeRate = await this.getFeeRate(fee)
321
+ let unsignedTx = await this.transactionBuilder.createNftPsbt({
322
+ extendedUtxo: utxo,
323
+ nftExtendedUtxo: {
324
+ hash: brcInscribeUtxo.hash,
325
+ index: 0,
326
+ value: brcInscribeUtxo.value,
327
+ signerInfo: ordinalSignerInfo,
328
+ },
329
+ feeRate,
330
+ receiverAddress: receiver,
331
+ changeAddress: signer.address,
332
+ otherTargets,
333
+ })
334
+ return {
335
+ ...unsignedTx,
336
+ possibleTxId: this.transactionBuilder.getUnsignedPsbtTxId(unsignedTx.unsignedTransaction),
337
+ }
338
+ }
339
+
340
+ async transferBrc20(
341
+ receiver: string,
342
+ brcInscribeUtxo: {
343
+ hash: string
344
+ value: number
345
+ index: number
346
+ },
347
+ fee: FeeRateType = "normal",
348
+ extendedUtxo: ExtendedUtxo[],
349
+ otherTargets?: Target[],
350
+ ) {
351
+ if (!this.currentAccount || !this.currentAccountType || !this.publicKey || !this.privateKey) {
352
+ throw new Error("account not initialized")
353
+ }
354
+ let feeRate = await this.getFeeRate(fee)
355
+ let unsignedTx = await this.transactionBuilder.createNftPsbt({
356
+ extendedUtxo,
357
+ nftExtendedUtxo: {
358
+ hash: brcInscribeUtxo.hash,
359
+ index: 0,
360
+ value: brcInscribeUtxo.value,
361
+ signerInfo: this.signerInfo!,
362
+ },
363
+ feeRate,
364
+ receiverAddress: receiver,
365
+ changeAddress: this.bitcoinAddress!,
366
+ otherTargets,
367
+ })
368
+
369
+ let signedTx = await this.signer.signPsbt(unsignedTx, this.privateKey!)
370
+ let finalTransferTxId = await this.sendSignedPsbtWithRetry(signedTx)
371
+ return {
372
+ hash: finalTransferTxId,
373
+ index: 0,
374
+ value: brcInscribeUtxo.value,
375
+ inputs: unsignedTx.inputs,
376
+ change: unsignedTx.change,
377
+ changeIndex: unsignedTx.change ? unsignedTx.outputs.length : undefined,
378
+ }
379
+ }
380
+
381
+ async inscribeAndTransferBrc20Unsigned(
382
+ receiver: string,
383
+ brc: { tick: string; amount: number | string },
384
+ signer: SignerInfo,
385
+ ordinalSigner?: SignerInfo,
386
+ otherTargets?: Target[],
387
+ fee: FeeRateType = "normal",
388
+ extendedUtxo?: ExtendedUtxo[],
389
+ ) {
390
+ const ordinalSignerInfo = ordinalSigner || signer
391
+ // check all fee before process transaction
392
+ let brc20Balance = await this.unisat.getBrc20AddressBalanceForTicker(signer.address, brc.tick)
393
+
394
+ if (BigNumber(brc20Balance.transferableBalance).gte(brc.amount)) {
395
+ let transferrableInscription = brc20Balance.transferableInscriptions.find(
396
+ (insc) => insc.data.tick === brc.tick && BigNumber(insc.data.amt).isEqualTo(brc.amount),
397
+ )
398
+
399
+ console.log("transferrableInscription", transferrableInscription)
400
+ }
401
+
402
+ if (BigNumber(brc20Balance.availableBalanceSafe).isLessThan(brc.amount)) {
403
+ throw new Error("insufficient balance")
404
+ }
405
+
406
+ let feeRate = await this.getFeeRate(fee)
407
+
408
+ let utxo1: ExtendedUtxo[] =
409
+ extendedUtxo || (await this.btcInterface.getBTCUtxo(signer.address, signer))
410
+ let utxo2: ExtendedUtxo[] = []
411
+ const { inscribeAddress, inscribeDepositUnsignedInfo, inscribeUnsignedInfo } =
412
+ await this.inscribeBrc20Unsigned(brc, signer, ordinalSignerInfo, feeRate, utxo1)
413
+
414
+ utxo2 = utxo1.filter(
415
+ (u) =>
416
+ inscribeDepositUnsignedInfo.inputs.findIndex(
417
+ (i) => i.hash === u.hash && i.index === u.index,
418
+ ) === -1,
419
+ )
420
+
421
+ if (inscribeDepositUnsignedInfo.change) {
422
+ if (!inscribeDepositUnsignedInfo.possibleTxId) {
423
+ throw new Error("inscribeDepositUnsignedInfo.possibleTxId is required")
424
+ }
425
+ utxo2.push({
426
+ hash: inscribeDepositUnsignedInfo.possibleTxId,
427
+ index: inscribeDepositUnsignedInfo.outputs.length,
428
+ value: inscribeDepositUnsignedInfo.change.value,
429
+ signerInfo: signer,
430
+ })
431
+ }
432
+ let transferTxUnsignedInfo = await this.transferBrc20Unsigned(
433
+ receiver,
434
+ {
435
+ hash: inscribeUnsignedInfo.possibleTxId,
436
+ value: inscribeUnsignedInfo.outputs[0].value,
437
+ index: 0,
438
+ },
439
+ signer,
440
+ ordinalSignerInfo,
441
+ feeRate,
442
+ utxo2,
443
+ otherTargets,
444
+ )
445
+ return {
446
+ inscribeDepositUnsignedInfo,
447
+ inscribeUnsignedInfo,
448
+ transferTxUnsignedInfo,
449
+ inscribeAddress,
450
+ }
451
+ }
452
+
453
+ async inscribeAndTransferBrc20(
454
+ receiver: string,
455
+ brc: { tick: string; amount: number | string },
456
+ otherTargets?: Target[],
457
+ fee: FeeRateType = "normal",
458
+ extendedUtxo?: ExtendedUtxo[],
459
+ ) {
460
+ // check all fee before process transaction
461
+ let brc20Balance = await this.unisat.getBrc20AddressBalanceForTicker(
462
+ this.bitcoinAddress!,
463
+ brc.tick,
464
+ )
465
+
466
+ if (BigNumber(brc20Balance.transferableBalance).gte(brc.amount)) {
467
+ let transferrableInscription = brc20Balance.transferableInscriptions.find(
468
+ (insc) => insc.data.tick === brc.tick && BigNumber(insc.data.amt).isEqualTo(brc.amount),
469
+ )
470
+ console.log("transferrableInscription", transferrableInscription)
471
+
472
+ if (transferrableInscription) {
473
+ let ins = await this.btcInterface.unisat.getInscriptionInfo(
474
+ transferrableInscription.inscriptionId,
475
+ )
476
+
477
+ if (ins) {
478
+ let transferTx = await this.transferBrc20(
479
+ receiver,
480
+ {
481
+ hash: ins.utxo.txid!,
482
+ index: ins.utxo.vout!,
483
+ value: ins.utxo.satoshi!,
484
+ },
485
+ await this.getFeeRate(fee),
486
+ extendedUtxo ||
487
+ (await this.btcInterface.getBTCUtxo(this.bitcoinAddress!, this.signerInfo!)),
488
+ otherTargets,
489
+ )
490
+ return {
491
+ transferTx,
492
+ }
493
+ }
494
+ }
495
+ }
496
+
497
+ if (BigNumber(brc20Balance.availableBalanceSafe).isLessThan(brc.amount)) {
498
+ throw new Error(`insufficient balance ${brc20Balance.availableBalanceSafe} ${brc.amount}`)
499
+ }
500
+
501
+ let feeRate = await this.getFeeRate(fee)
502
+
503
+ let utxo1: ExtendedUtxo[] =
504
+ extendedUtxo || (await this.btcInterface.getBTCUtxo(this.bitcoinAddress!, this.signerInfo!))
505
+ let utxo2: ExtendedUtxo[] = []
506
+ const { inscribeAddress, inscribeDepositTx, inscribeTx } = await this.inscribeBrc20(
507
+ brc,
508
+ feeRate,
509
+ utxo1,
510
+ )
511
+
512
+ utxo2 = utxo1.filter(
513
+ (u) =>
514
+ inscribeDepositTx.inputs.findIndex((i) => i.hash === u.hash && i.index === u.index) === -1,
515
+ )
516
+
517
+ if (inscribeDepositTx.change) {
518
+ utxo2.push({
519
+ hash: inscribeDepositTx.hash,
520
+ index: inscribeDepositTx.changeIndex!,
521
+ value: inscribeDepositTx.change.value,
522
+ signerInfo: this.signerInfo!,
523
+ })
524
+ }
525
+ await sleep(10 * 1000)
526
+ let transferTx = await this.transferBrc20(receiver, inscribeTx, feeRate, utxo2, otherTargets)
527
+ return {
528
+ inscribeTx,
529
+ inscribeAddress,
530
+ inscribeDepositTx,
531
+ transferTx,
532
+ }
533
+ }
534
+
535
+ async wrapBrc20Unsigned(
536
+ recipientAddress: string,
537
+ brc: { tick: string; amount: number | string },
538
+ brc20TokenId: number,
539
+ signer: SignerInfo,
540
+ lockerAddress: string,
541
+ exchange?: {
542
+ outputToken: string
543
+ outputAmount: string
544
+ },
545
+ ordinalSigner?: SignerInfo,
546
+ fee: FeeRateType = "normal",
547
+ extendedUtxo?: ExtendedUtxo[],
548
+
549
+ { chainId = 137, appId = exchange ? 1 : 0 } = {},
550
+ ) {
551
+ const isExchange = !!exchange
552
+ let dataHex = generateBrc2OpReturn({
553
+ chainId,
554
+ appId,
555
+ brc20TokenId,
556
+ inputAmount: BigNumber(brc.amount).multipliedBy(1e18).toFixed(0),
557
+ recipientAddress,
558
+ isExchange,
559
+ outputToken: exchange?.outputToken,
560
+ outputAmount: exchange?.outputAmount,
561
+ })
562
+ let opTarget = this.transactionBuilder.getOpReturnTarget(dataHex)
563
+ return this.inscribeAndTransferBrc20Unsigned(
564
+ lockerAddress,
565
+ brc,
566
+ signer,
567
+ ordinalSigner,
568
+ [opTarget],
569
+ fee,
570
+ extendedUtxo,
571
+ )
572
+ }
573
+
574
+ async wrapBrc20OnlyTransferUnsigned(
575
+ recipientAddress: string,
576
+ brcInscribeTx: {
577
+ hash: string
578
+ value: number
579
+ index: number
580
+ },
581
+ brc: { tick: string; amount: number | string },
582
+ brc20TokenId: number,
583
+ signer: SignerInfo,
584
+ lockerAddress: string,
585
+ exchange?: {
586
+ outputToken: string
587
+ outputAmount: string
588
+ },
589
+ ordinalSigner?: SignerInfo,
590
+ fee: FeeRateType = "normal",
591
+ extendedUtxo?: ExtendedUtxo[],
592
+
593
+ { chainId = 137, appId = exchange ? 1 : 0 } = {},
594
+ ) {
595
+ let utxo: ExtendedUtxo[] =
596
+ extendedUtxo || (await this.btcInterface.getBTCUtxo(signer.address, signer))
597
+
598
+ const isExchange = !!exchange
599
+ let dataHex = generateBrc2OpReturn({
600
+ chainId,
601
+ appId,
602
+ brc20TokenId,
603
+ inputAmount: BigNumber(brc.amount).multipliedBy(1e18).toFixed(0),
604
+ recipientAddress,
605
+ isExchange,
606
+ outputToken: exchange?.outputToken,
607
+ outputAmount: exchange?.outputAmount,
608
+ })
609
+ let opTarget = this.transactionBuilder.getOpReturnTarget(dataHex)
610
+ let feeRate = await this.getFeeRate(fee)
611
+ let transferTxUnsignedInfo = await this.transferBrc20Unsigned(
612
+ lockerAddress,
613
+ brcInscribeTx,
614
+ signer,
615
+ ordinalSigner,
616
+ feeRate,
617
+ utxo,
618
+ [opTarget],
619
+ )
620
+ return transferTxUnsignedInfo
621
+ }
622
+
623
+ async wrapBrc20(
624
+ recipientAddress: string,
625
+ brc: { tick: string; amount: number | string },
626
+ brc20TokenId: number,
627
+ lockerAddress: string,
628
+ exchange?: {
629
+ outputToken: string
630
+ outputAmount: string
631
+ },
632
+ fee: FeeRateType = "normal",
633
+ extendedUtxo?: ExtendedUtxo[],
634
+
635
+ { chainId = 137, appId = exchange ? 1 : 0 } = {},
636
+ ) {
637
+ const isExchange = !!exchange
638
+
639
+ let dataHex = generateBrc2OpReturn({
640
+ chainId,
641
+ appId,
642
+ brc20TokenId,
643
+ inputAmount: BigNumber(brc.amount).multipliedBy(1e18).toFixed(0),
644
+ recipientAddress,
645
+ isExchange,
646
+ outputToken: exchange?.outputToken,
647
+ outputAmount: exchange?.outputAmount,
648
+ })
649
+ let opTarget = this.transactionBuilder.getOpReturnTarget(dataHex)
650
+ return this.inscribeAndTransferBrc20(lockerAddress, brc, [opTarget], fee, extendedUtxo)
651
+ }
652
+ }
653
+
654
+ export default OrdinalWallet