@teleportdao/bitcoin 3.0.3 → 4.0.0-alpha.0

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 (105) hide show
  1. package/dist/bitcoin-interface-ordinal.d.ts +24 -24
  2. package/dist/bitcoin-interface-ordinal.d.ts.map +1 -1
  3. package/dist/bitcoin-interface-ordinal.js +89 -107
  4. package/dist/bitcoin-interface-ordinal.js.map +1 -1
  5. package/dist/bitcoin-interface-teleswap.d.ts +2 -2
  6. package/dist/bitcoin-interface-teleswap.d.ts.map +1 -1
  7. package/dist/bitcoin-interface-teleswap.js +77 -88
  8. package/dist/bitcoin-interface-teleswap.js.map +1 -1
  9. package/dist/bitcoin-interface-utils.d.ts +7 -4
  10. package/dist/bitcoin-interface-utils.d.ts.map +1 -1
  11. package/dist/bitcoin-interface-utils.js +11 -5
  12. package/dist/bitcoin-interface-utils.js.map +1 -1
  13. package/dist/bitcoin-interface-wallet.d.ts +1 -0
  14. package/dist/bitcoin-interface-wallet.d.ts.map +1 -1
  15. package/dist/bitcoin-interface-wallet.js +87 -95
  16. package/dist/bitcoin-interface-wallet.js.map +1 -1
  17. package/dist/bitcoin-interface.d.ts.map +1 -1
  18. package/dist/bitcoin-interface.js +58 -87
  19. package/dist/bitcoin-interface.js.map +1 -1
  20. package/dist/bitcoin-utils.d.ts +7 -4
  21. package/dist/bitcoin-utils.d.ts.map +1 -1
  22. package/dist/bitcoin-utils.js +93 -54
  23. package/dist/bitcoin-utils.js.map +1 -1
  24. package/dist/bitcoin-wallet-base.d.ts +23 -11
  25. package/dist/bitcoin-wallet-base.d.ts.map +1 -1
  26. package/dist/bitcoin-wallet-base.js +148 -138
  27. package/dist/bitcoin-wallet-base.js.map +1 -1
  28. package/dist/helper/brc20-helper.d.ts.map +1 -1
  29. package/dist/helper/brc20-helper.js +4 -6
  30. package/dist/helper/brc20-helper.js.map +1 -1
  31. package/dist/helper/index.js +17 -7
  32. package/dist/helper/index.js.map +1 -1
  33. package/dist/helper/ordinal-helper.d.ts +3 -9
  34. package/dist/helper/ordinal-helper.d.ts.map +1 -1
  35. package/dist/helper/ordinal-helper.js +20 -85
  36. package/dist/helper/ordinal-helper.js.map +1 -1
  37. package/dist/helper/teleswap-helper.d.ts.map +1 -1
  38. package/dist/helper/teleswap-helper.js +13 -12
  39. package/dist/helper/teleswap-helper.js.map +1 -1
  40. package/dist/index.d.ts +1 -0
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +18 -7
  43. package/dist/index.js.map +1 -1
  44. package/dist/multisig-wallet-helper.d.ts +14 -1
  45. package/dist/multisig-wallet-helper.d.ts.map +1 -1
  46. package/dist/multisig-wallet-helper.js +135 -149
  47. package/dist/multisig-wallet-helper.js.map +1 -1
  48. package/dist/ordinal-wallet.d.ts +27 -19
  49. package/dist/ordinal-wallet.d.ts.map +1 -1
  50. package/dist/ordinal-wallet.js +263 -293
  51. package/dist/ordinal-wallet.js.map +1 -1
  52. package/dist/sign/sign-transaction.d.ts +5 -2
  53. package/dist/sign/sign-transaction.d.ts.map +1 -1
  54. package/dist/sign/sign-transaction.js +32 -39
  55. package/dist/sign/sign-transaction.js.map +1 -1
  56. package/dist/teleswap-wallet.d.ts +1 -0
  57. package/dist/teleswap-wallet.d.ts.map +1 -1
  58. package/dist/teleswap-wallet.js +40 -53
  59. package/dist/teleswap-wallet.js.map +1 -1
  60. package/dist/transaction-builder/bitcoin-transaction-builder.js +21 -21
  61. package/dist/transaction-builder/bitcoin-transaction-builder.js.map +1 -1
  62. package/dist/transaction-builder/coin-select.d.ts +19 -3
  63. package/dist/transaction-builder/coin-select.d.ts.map +1 -1
  64. package/dist/transaction-builder/coin-select.js +193 -181
  65. package/dist/transaction-builder/coin-select.js.map +1 -1
  66. package/dist/transaction-builder/index.d.ts +1 -0
  67. package/dist/transaction-builder/index.d.ts.map +1 -1
  68. package/dist/transaction-builder/index.js +1 -0
  69. package/dist/transaction-builder/index.js.map +1 -1
  70. package/dist/transaction-builder/ordinal-transaction-builder.d.ts +4 -4
  71. package/dist/transaction-builder/ordinal-transaction-builder.d.ts.map +1 -1
  72. package/dist/transaction-builder/ordinal-transaction-builder.js +51 -48
  73. package/dist/transaction-builder/ordinal-transaction-builder.js.map +1 -1
  74. package/dist/transaction-builder/transaction-builder.d.ts +57 -54
  75. package/dist/transaction-builder/transaction-builder.d.ts.map +1 -1
  76. package/dist/transaction-builder/transaction-builder.js +394 -308
  77. package/dist/transaction-builder/transaction-builder.js.map +1 -1
  78. package/dist/utils/networks.js +17 -7
  79. package/dist/utils/networks.js.map +1 -1
  80. package/dist/utils/tools.js +24 -35
  81. package/dist/utils/tools.js.map +1 -1
  82. package/package.json +4 -4
  83. package/src/bitcoin-interface-utils.ts +17 -8
  84. package/src/bitcoin-interface-wallet.ts +15 -1
  85. package/src/bitcoin-utils.ts +52 -3
  86. package/src/bitcoin-wallet-base.ts +67 -23
  87. package/src/helper/ordinal-helper.ts +0 -83
  88. package/src/index.ts +2 -0
  89. package/src/multisig-wallet-helper.ts +296 -0
  90. package/src/sign/sign-transaction.ts +5 -7
  91. package/src/transaction-builder/coin-select.ts +633 -0
  92. package/src/transaction-builder/index.ts +1 -0
  93. package/src/transaction-builder/transaction-builder.ts +424 -279
  94. package/dist/bitcoin-wallet-base copy.d.ts +0 -122
  95. package/dist/bitcoin-wallet-base copy.d.ts.map +0 -1
  96. package/dist/bitcoin-wallet-base copy.js +0 -279
  97. package/dist/bitcoin-wallet-base copy.js.map +0 -1
  98. package/dist/multisig-coordinator-wallet.d.ts +0 -2
  99. package/dist/multisig-coordinator-wallet.d.ts.map +0 -1
  100. package/dist/multisig-coordinator-wallet.js +0 -6
  101. package/dist/multisig-coordinator-wallet.js.map +0 -1
  102. package/dist/multisig-wallet.d.ts +0 -20
  103. package/dist/multisig-wallet.d.ts.map +0 -1
  104. package/dist/multisig-wallet.js +0 -119
  105. package/dist/multisig-wallet.js.map +0 -1
@@ -3,89 +3,6 @@ import ecc from "@bitcoinerlab/secp256k1"
3
3
 
4
4
  bitcoin.initEccLib(ecc)
5
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
6
  export function splitBuffer(buffer: Buffer, partLength: number) {
90
7
  const parts: Buffer[] = []
91
8
  for (let i = 0; i < buffer.length; i += partLength) {
package/src/index.ts CHANGED
@@ -6,6 +6,8 @@ export * from "./teleswap-wallet"
6
6
  export * from "./ordinal-wallet"
7
7
  export * from "./bitcoin-wallet-base"
8
8
  //
9
+ export * from "./multisig-wallet-helper"
10
+ //
9
11
  export * from "./bitcoin-interface-utils"
10
12
  export * from "./bitcoin-interface"
11
13
  export * from "./bitcoin-interface-teleswap"
@@ -0,0 +1,296 @@
1
+ import { TeleportdaoMultisigCoordinator, TxRequest } from "@teleportdao/providers"
2
+ import BigNumber from "bignumber.js"
3
+ import { BitcoinBaseWallet, FeeRateType } from "./bitcoin-wallet-base"
4
+ import {
5
+ ExtendedUnsignedTransaction,
6
+ ExtendedUtxo,
7
+ SignerInfo,
8
+ TargetAddress,
9
+ } from "./transaction-builder"
10
+
11
+ export class MultisigWalletHelper {
12
+ baseWallet: BitcoinBaseWallet
13
+ coordinator: TeleportdaoMultisigCoordinator
14
+ acceptableFeeDiff: number
15
+ txCheckConfig: { sleepTime: number; maxRetry: number }
16
+ txCounter?: number
17
+ txCounterMonitor: boolean
18
+ coordinatorUrl: string
19
+ coordinatorApiKey?: string
20
+ constructor(
21
+ baseWallet: BitcoinBaseWallet,
22
+ coordinatorUrl: string,
23
+ coordinatorApiKey?: string,
24
+ txCounterMonitor = true,
25
+ acceptableFeeDiffPercentage?: number,
26
+ txCheckConfig?: { sleepTime: number; maxRetry: number },
27
+ ) {
28
+ this.baseWallet = baseWallet
29
+ this.coordinatorUrl = coordinatorUrl
30
+ this.coordinator = new TeleportdaoMultisigCoordinator(coordinatorUrl, coordinatorApiKey)
31
+ this.acceptableFeeDiff = acceptableFeeDiffPercentage || 30
32
+ this.txCheckConfig = txCheckConfig || {
33
+ sleepTime: 1500,
34
+ maxRetry: 30,
35
+ }
36
+ this.txCounterMonitor = txCounterMonitor
37
+ this.txCounter = undefined
38
+ }
39
+
40
+ get bitcoinAddress() {
41
+ return this.baseWallet.bitcoinAddress
42
+ }
43
+
44
+ setAccountType(
45
+ addressType: "p2sh" | "p2wsh" | "p2sh-p2wsh",
46
+ publicKeys: string[],
47
+ numberOfSigners?: number,
48
+ ) {
49
+ if (
50
+ !this.baseWallet.publicKey ||
51
+ !publicKeys.includes(this.baseWallet.publicKey.toString("hex"))
52
+ ) {
53
+ throw new Error("public keys not match with the key")
54
+ }
55
+
56
+ return this.baseWallet.setAccountType(addressType, {
57
+ publicKeys,
58
+ numberOfSigners,
59
+ })
60
+ }
61
+
62
+ async setAPIKey() {
63
+ if (
64
+ !this.baseWallet.signerInfo ||
65
+ !this.baseWallet.signerInfo.publicKeys ||
66
+ !this.baseWallet.bitcoinAddress
67
+ ) {
68
+ throw new Error("wallet not initialized")
69
+ }
70
+ let response = await this.coordinator.registerOrGetWallet(
71
+ this.baseWallet.signerInfo.publicKey,
72
+ this.baseWallet.signerInfo.publicKeys,
73
+ this.baseWallet.bitcoinAddress,
74
+ this.baseWallet.signerInfo.addressType,
75
+ this.baseWallet.signerInfo.numberOfSigners,
76
+ )
77
+ this.coordinator = new TeleportdaoMultisigCoordinator(this.coordinatorUrl, response.apiKey)
78
+ return response
79
+ }
80
+
81
+ async setTxCounter(txCounter: number) {
82
+ if (this.txCounterMonitor) this.txCounter = txCounter
83
+ }
84
+
85
+ async resetTxCounter() {
86
+ const wallet = await this.coordinator.getWallet()
87
+ this.setTxCounter(wallet.txCounter)
88
+ return wallet.txCounter
89
+ }
90
+
91
+ async step1SendBTCToMultipleAddressUnsigned(
92
+ receivers: TargetAddress[],
93
+ signerInfo: SignerInfo,
94
+ fee: FeeRateType = "normal",
95
+ staticExtendedUtxo?: ExtendedUtxo[],
96
+ fullAmount = false,
97
+ ) {
98
+ try {
99
+ let unsignedTx = await this.baseWallet.sendBTCToMultipleAddressUnsignedTx(
100
+ receivers,
101
+ signerInfo,
102
+ fee,
103
+ staticExtendedUtxo,
104
+ fullAmount,
105
+ )
106
+
107
+ console.log("this.txCounter step 1 start", this.txCounter)
108
+
109
+ let txRequest = await this.coordinator.createOrConfirmNewTx({
110
+ inputs: unsignedTx.inputs.map((x) => ({
111
+ hash: x.hash,
112
+ index: x.index,
113
+ value: x.value,
114
+ })),
115
+ outputs: unsignedTx.outputs as any,
116
+ feeRate: unsignedTx.feeRate,
117
+ unsignedPsbt: unsignedTx.unsignedTransaction,
118
+ txCounter: this.txCounter,
119
+ })
120
+
121
+ if (txRequest.status !== "Rejected" && txRequest.status !== "Broadcasted") {
122
+ this.setTxCounter(txRequest.txCounter)
123
+ } else {
124
+ await this.resetTxCounter()
125
+ }
126
+
127
+ console.log("this.txCounter step 1 end", this.txCounter)
128
+ return {
129
+ txRequest,
130
+ unsignedTx,
131
+ }
132
+ } catch (e) {
133
+ await this.resetTxCounter()
134
+ throw e
135
+ }
136
+ }
137
+
138
+ async step2WaitForUnsignedTxApproval(input: {
139
+ unsignedTx: ExtendedUnsignedTransaction
140
+ txRequest: TxRequest
141
+ }) {
142
+ const feeRateDiffPercentage = this.acceptableFeeDiff
143
+ let newUnsignedTx = input.unsignedTx
144
+ let newTxRequest = input.txRequest
145
+
146
+ // Wait for approval
147
+ if (newTxRequest.status === "Pending") {
148
+ this.setTxCounter(newTxRequest.txCounter)
149
+
150
+ if (newTxRequest.unsignedPsbt !== newUnsignedTx.unsignedTransaction) {
151
+ const feeDiff = BigNumber(newTxRequest.feeRate)
152
+ .minus(newUnsignedTx.feeRate)
153
+ .abs()
154
+ .dividedBy(newUnsignedTx.feeRate)
155
+ if (!feeDiff.isLessThan(feeRateDiffPercentage / 100)) {
156
+ const txRequest = await this.coordinator.rejectTxRequest(newTxRequest.id)
157
+ this.setTxCounter((this.txCounter || txRequest.txCounter) + 1)
158
+ throw new Error("Reject because of Invalid FeeRate")
159
+ }
160
+
161
+ const { signerInfo } = newUnsignedTx.inputs[0]
162
+
163
+ console.log(newUnsignedTx.outputs, newTxRequest.outputs)
164
+
165
+ newUnsignedTx = await this.baseWallet.sendBTCToMultipleAddressUnsignedTx(
166
+ newUnsignedTx.outputs as TargetAddress[],
167
+ signerInfo,
168
+ +newTxRequest.feeRate,
169
+ newTxRequest.inputs.map((x) => ({
170
+ ...x,
171
+ signerInfo,
172
+ })),
173
+ )
174
+
175
+ let updatedTxRequest = await this.coordinator.confirmOrRejectTxRequest(
176
+ newTxRequest.id,
177
+ newUnsignedTx.unsignedTransaction,
178
+ )
179
+
180
+ if (
181
+ updatedTxRequest.status === "Rejected" ||
182
+ updatedTxRequest.unsignedPsbt !== newUnsignedTx.unsignedTransaction
183
+ ) {
184
+ console.log("not equal unsignedPsbt")
185
+ console.log(updatedTxRequest.unsignedPsbt)
186
+ console.log(newUnsignedTx.unsignedTransaction)
187
+ this.setTxCounter((this.txCounter || updatedTxRequest.txCounter) + 1)
188
+ throw new Error("Reject because of invalid outputs")
189
+ }
190
+ newTxRequest = updatedTxRequest
191
+ }
192
+
193
+ const updatedTxRequest = await this.coordinator.waitTxStatusChange(
194
+ newTxRequest.id,
195
+ "Pending",
196
+ this.txCheckConfig.sleepTime,
197
+ this.txCheckConfig.maxRetry,
198
+ )
199
+
200
+ if (!updatedTxRequest) {
201
+ await this.coordinator.rejectTxRequest(newTxRequest.id)
202
+ if (this.txCounter) this.setTxCounter(this.txCounter + 1)
203
+ throw new Error("Tx Timeout")
204
+ }
205
+ newTxRequest = updatedTxRequest
206
+
207
+ if (newTxRequest.status === "Rejected") {
208
+ if (this.txCounter) this.setTxCounter(this.txCounter + 1)
209
+ throw new Error("Tx Rejected")
210
+ }
211
+ }
212
+
213
+ if (newTxRequest.status === "Rejected") {
214
+ await this.resetTxCounter()
215
+ throw new Error("Tx was Rejected")
216
+ }
217
+ console.log("this.txCounter step 2 end", this.txCounter)
218
+
219
+ return {
220
+ unsignedTx: newUnsignedTx,
221
+ txRequest: newTxRequest,
222
+ }
223
+ }
224
+
225
+ // this step need privatekey
226
+ async step3SignTxAndWaitForBroadcast(input: {
227
+ unsignedTx: ExtendedUnsignedTransaction
228
+ txRequest: TxRequest
229
+ }) {
230
+ if (!this.baseWallet.privateKey) throw new Error("account is not initialized")
231
+ const { unsignedTx, txRequest } = input
232
+ let newTxRequest = txRequest
233
+ if (newTxRequest.status === "Approved") {
234
+ const signed = await this.baseWallet.signer.signPsbt(unsignedTx, this.baseWallet.privateKey!)
235
+ newTxRequest = await this.coordinator.submitSignedPsbt(newTxRequest.id, signed)
236
+ }
237
+
238
+ // Wait for broadcast
239
+ if (newTxRequest.status === "Approved") {
240
+ if (this.txCounter) this.setTxCounter(newTxRequest.txCounter)
241
+ const finalTx = await this.coordinator.waitTxStatusChange(
242
+ newTxRequest.id,
243
+ "Approved",
244
+ this.txCheckConfig.sleepTime,
245
+ this.txCheckConfig.maxRetry,
246
+ )
247
+ if (!finalTx || finalTx.status === "Failed") {
248
+ throw new Error("Tx not broadcasted for long time")
249
+ }
250
+ newTxRequest = finalTx
251
+ }
252
+
253
+ if (this.txCounter) this.setTxCounter(this.txCounter + 1)
254
+
255
+ console.log("this.txCounter step3", this.txCounter)
256
+
257
+ return newTxRequest
258
+ }
259
+
260
+ async sendBTCMultipleAddress(
261
+ receivers: TargetAddress[],
262
+ fee: FeeRateType = "normal",
263
+ staticExtendedUtxo?: ExtendedUtxo[],
264
+ fullAmount = false,
265
+ ) {
266
+ if (!this.baseWallet.signerInfo || !this.baseWallet.privateKey) {
267
+ throw new Error("account not initialized")
268
+ }
269
+ // todo catch error on different step and customize error so we can distinguish important error from regular error
270
+ let unsignedResponse = await this.step1SendBTCToMultipleAddressUnsigned(
271
+ receivers,
272
+ this.baseWallet.signerInfo,
273
+ fee,
274
+ staticExtendedUtxo,
275
+ fullAmount,
276
+ )
277
+ unsignedResponse = await this.step2WaitForUnsignedTxApproval(unsignedResponse)
278
+ const txRequest = await this.step3SignTxAndWaitForBroadcast(unsignedResponse)
279
+ return txRequest
280
+ }
281
+
282
+ async sendBTC(
283
+ receiverAddress: string,
284
+ amountInSatoshi: number | "all",
285
+ fee: FeeRateType = "normal",
286
+ staticExtendedUtxo?: ExtendedUtxo[],
287
+ ) {
288
+ const txRequest = await this.sendBTCMultipleAddress(
289
+ [{ address: receiverAddress, value: amountInSatoshi === "all" ? 0 : amountInSatoshi }],
290
+ fee,
291
+ staticExtendedUtxo,
292
+ amountInSatoshi === "all",
293
+ )
294
+ return txRequest
295
+ }
296
+ }
@@ -93,15 +93,13 @@ class BitcoinLikeSignTransaction {
93
93
  const finals = psbtsBase64.map((psbtBase64) =>
94
94
  Psbt.fromBase64(psbtBase64, { network: this.network }),
95
95
  )
96
- const psbt =
97
- finals.length === 1 ? finals[0] : new Psbt({ network: this.network }).combine(...finals)
98
-
96
+ let psbt = finals[0]
97
+ for (let i = 1; i < finals.length; i += 1) {
98
+ psbt.combine(finals[i])
99
+ }
99
100
  psbt.finalizeAllInputs()
100
-
101
101
  let finalizeTx = psbt.extractTransaction()
102
- // const rawTx = finalizeTx.toBuffer()
103
- // const hex = rawTx.toString("hex")
104
- return finalizeTx.toHex()
102
+ return { hex: finalizeTx.toHex(), txId: finalizeTx.getId(), vBytes: finalizeTx.virtualSize() }
105
103
  }
106
104
  }
107
105