@teleportdao/bitcoin 1.8.9 → 2.0.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.
- package/.tmp/block-parser.ts +58 -0
- package/dist/bitcoin-interface-ordinal.d.ts +2 -2
- package/dist/bitcoin-interface-ordinal.d.ts.map +1 -1
- package/dist/bitcoin-interface-ordinal.js +1 -1
- package/dist/bitcoin-interface-ordinal.js.map +1 -1
- package/dist/bitcoin-interface-teleswap.d.ts +2 -53
- package/dist/bitcoin-interface-teleswap.d.ts.map +1 -1
- package/dist/bitcoin-interface-teleswap.js +6 -17
- package/dist/bitcoin-interface-teleswap.js.map +1 -1
- package/dist/bitcoin-interface-wallet.d.ts +29 -0
- package/dist/bitcoin-interface-wallet.d.ts.map +1 -0
- package/dist/bitcoin-interface-wallet.js +126 -0
- package/dist/bitcoin-interface-wallet.js.map +1 -0
- package/dist/bitcoin-interface.d.ts +5 -23
- package/dist/bitcoin-interface.d.ts.map +1 -1
- package/dist/bitcoin-interface.js +13 -92
- package/dist/bitcoin-interface.js.map +1 -1
- package/dist/bitcoin-wallet-base.d.ts +55 -31
- package/dist/bitcoin-wallet-base.d.ts.map +1 -1
- package/dist/bitcoin-wallet-base.js +105 -84
- package/dist/bitcoin-wallet-base.js.map +1 -1
- package/dist/ordinal-wallet.d.ts +29 -71
- package/dist/ordinal-wallet.d.ts.map +1 -1
- package/dist/ordinal-wallet.js +48 -108
- package/dist/ordinal-wallet.js.map +1 -1
- package/dist/teleswap-wallet.d.ts +10 -16
- package/dist/teleswap-wallet.d.ts.map +1 -1
- package/dist/teleswap-wallet.js +10 -30
- package/dist/teleswap-wallet.js.map +1 -1
- package/dist/transaction-builder/bitcoin-transaction-builder.d.ts +4 -11
- package/dist/transaction-builder/bitcoin-transaction-builder.d.ts.map +1 -1
- package/dist/transaction-builder/bitcoin-transaction-builder.js +2 -23
- package/dist/transaction-builder/bitcoin-transaction-builder.js.map +1 -1
- package/dist/transaction-builder/ordinal-transaction-builder.d.ts +3 -2
- package/dist/transaction-builder/ordinal-transaction-builder.d.ts.map +1 -1
- package/dist/transaction-builder/ordinal-transaction-builder.js +1 -6
- package/dist/transaction-builder/ordinal-transaction-builder.js.map +1 -1
- package/dist/transaction-builder/transaction-builder.d.ts +3 -7
- package/dist/transaction-builder/transaction-builder.d.ts.map +1 -1
- package/dist/transaction-builder/transaction-builder.js +22 -49
- package/dist/transaction-builder/transaction-builder.js.map +1 -1
- package/dist/type.d.ts +33 -18
- package/dist/type.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/bitcoin-interface-ordinal.ts +7 -3
- package/src/bitcoin-interface-teleswap.ts +7 -22
- package/src/bitcoin-interface-wallet.ts +114 -0
- package/src/bitcoin-interface.ts +15 -98
- package/src/bitcoin-wallet-base.ts +166 -132
- package/src/ordinal-wallet.ts +73 -162
- package/src/teleswap-wallet.ts +50 -72
- package/src/transaction-builder/bitcoin-transaction-builder.ts +6 -24
- package/src/transaction-builder/ordinal-transaction-builder.ts +2 -10
- package/src/transaction-builder/transaction-builder.ts +34 -50
- package/src/type.ts +45 -19
|
@@ -5,17 +5,24 @@ import BIP32Factory from "bip32"
|
|
|
5
5
|
import ecc from "@bitcoinerlab/secp256k1"
|
|
6
6
|
import BigNumber from "bignumber.js"
|
|
7
7
|
import { BitcoinTransactionBuilder } from "./transaction-builder"
|
|
8
|
-
import type {
|
|
8
|
+
import type { APIConnectionInfo, RPCConnectionInfo, UtxoConnectionInfo } from "./type"
|
|
9
9
|
|
|
10
|
-
import type {
|
|
10
|
+
import type {
|
|
11
|
+
ExtendedUtxo,
|
|
12
|
+
SignerInfo,
|
|
13
|
+
Target,
|
|
14
|
+
TargetAddress,
|
|
15
|
+
} from "./transaction-builder/transaction-builder"
|
|
11
16
|
import BitcoinSign from "./sign/sign-transaction"
|
|
12
17
|
|
|
13
18
|
import { getPubKeyFromPrivateKeyHex } from "./bitcoin-utils"
|
|
14
19
|
import networks from "./utils/networks"
|
|
15
|
-
import {
|
|
20
|
+
import { BitcoinInterfaceWallet } from "./bitcoin-interface-wallet"
|
|
21
|
+
import { runWithRetries } from "./utils/tools"
|
|
16
22
|
|
|
17
23
|
const bip32 = BIP32Factory(ecc)
|
|
18
24
|
|
|
25
|
+
export type FeeRateType = "normal" | "slow" | "fast" | number
|
|
19
26
|
export class BitcoinBaseWallet {
|
|
20
27
|
network: Network
|
|
21
28
|
hdWalletPath: {
|
|
@@ -28,7 +35,7 @@ export class BitcoinBaseWallet {
|
|
|
28
35
|
p2tr: string
|
|
29
36
|
}
|
|
30
37
|
transactionBuilder: BitcoinTransactionBuilder
|
|
31
|
-
btcInterface:
|
|
38
|
+
btcInterface: BitcoinInterfaceWallet
|
|
32
39
|
signer: BitcoinSign
|
|
33
40
|
currentAccount?: string
|
|
34
41
|
currentAccountType?: string
|
|
@@ -39,33 +46,41 @@ export class BitcoinBaseWallet {
|
|
|
39
46
|
bitcoinAddress: string | undefined
|
|
40
47
|
constructor(
|
|
41
48
|
networkName: string,
|
|
42
|
-
connectionInfo
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
49
|
+
connectionInfo?: {
|
|
50
|
+
utxo?: UtxoConnectionInfo
|
|
51
|
+
// rpc used for getRawTransaction in transaction builder if set (optional)
|
|
52
|
+
rpc?: RPCConnectionInfo
|
|
46
53
|
},
|
|
47
54
|
) {
|
|
48
55
|
this.network = networks[networkName]
|
|
49
56
|
this.hdWalletPath = hdWalletPath.bitcoin
|
|
50
57
|
|
|
51
58
|
this.transactionBuilder = new BitcoinTransactionBuilder(
|
|
52
|
-
connectionInfo,
|
|
53
59
|
networkName,
|
|
54
60
|
this.network,
|
|
61
|
+
connectionInfo,
|
|
55
62
|
)
|
|
56
63
|
this.btcInterface = this.transactionBuilder.btcInterface
|
|
57
64
|
|
|
58
65
|
this.signer = new BitcoinSign(this.network)
|
|
59
66
|
|
|
67
|
+
// initialize account
|
|
60
68
|
this.currentAccount = undefined
|
|
61
69
|
this.currentAccountType = undefined
|
|
62
|
-
|
|
63
70
|
this.privateKey = undefined
|
|
64
71
|
this.publicKey = undefined
|
|
65
|
-
// todo multisig
|
|
66
|
-
this.publicKeys = []
|
|
67
72
|
}
|
|
68
73
|
|
|
74
|
+
static satoshiToBTC(satoshi: number | string) {
|
|
75
|
+
return new BigNumber(satoshi).dividedBy(1e8).toString()
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
static btcToSatoshi(btc: number | string) {
|
|
79
|
+
return new BigNumber(btc).multipliedBy(1e8).toFixed(0)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// initialize account
|
|
83
|
+
|
|
69
84
|
get signerInfo() {
|
|
70
85
|
return this.privateKey
|
|
71
86
|
? {
|
|
@@ -76,82 +91,26 @@ export class BitcoinBaseWallet {
|
|
|
76
91
|
: undefined
|
|
77
92
|
}
|
|
78
93
|
|
|
79
|
-
createTransactionInputsAndOutputs({
|
|
80
|
-
targets,
|
|
81
|
-
extendedUtxo,
|
|
82
|
-
changeAddress,
|
|
83
|
-
feeRate,
|
|
84
|
-
}: {
|
|
85
|
-
targets: Target[]
|
|
86
|
-
extendedUtxo: ExtendedUtxo[]
|
|
87
|
-
changeAddress: string
|
|
88
|
-
feeRate: number
|
|
89
|
-
fullAmount?: boolean
|
|
90
|
-
}) {
|
|
91
|
-
return this.transactionBuilder.helperHandleInputsAndOutputs({
|
|
92
|
-
targets,
|
|
93
|
-
extendedUtxo,
|
|
94
|
-
changeObject: {
|
|
95
|
-
address: changeAddress,
|
|
96
|
-
},
|
|
97
|
-
feeRate,
|
|
98
|
-
})
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
checkBalanceIsSufficient({
|
|
102
|
-
targets,
|
|
103
|
-
extendedUtxo,
|
|
104
|
-
changeAddress,
|
|
105
|
-
feeRate,
|
|
106
|
-
fullAmount = false,
|
|
107
|
-
}: {
|
|
108
|
-
targets: Target[]
|
|
109
|
-
extendedUtxo: ExtendedUtxo[]
|
|
110
|
-
changeAddress: string
|
|
111
|
-
feeRate: number
|
|
112
|
-
fullAmount?: boolean
|
|
113
|
-
}) {
|
|
114
|
-
try {
|
|
115
|
-
this.transactionBuilder.helperHandleInputsAndOutputs({
|
|
116
|
-
targets,
|
|
117
|
-
extendedUtxo,
|
|
118
|
-
changeObject: {
|
|
119
|
-
address: changeAddress,
|
|
120
|
-
},
|
|
121
|
-
feeRate,
|
|
122
|
-
})
|
|
123
|
-
return true
|
|
124
|
-
} catch (err) {
|
|
125
|
-
return false
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// todo : not completed
|
|
130
|
-
setMultiSigAccount(accountType = "p2sh") {
|
|
131
|
-
throw new Error("not supported yet")
|
|
132
|
-
|
|
133
|
-
/* eslint-disable no-unreachable */
|
|
134
|
-
// todo : not completed
|
|
135
|
-
switch (accountType) {
|
|
136
|
-
// case 'p2sh':
|
|
137
|
-
// this.currentAccount = ''
|
|
138
|
-
// break
|
|
139
|
-
// case 'p2wsh':
|
|
140
|
-
// this.currentAccount = ''
|
|
141
|
-
// break
|
|
142
|
-
// case 'p2sh-p2wsh':
|
|
143
|
-
// this.currentAccount = ''
|
|
144
|
-
// break
|
|
145
|
-
default:
|
|
146
|
-
throw new Error("accountType is incorrect")
|
|
147
|
-
}
|
|
148
|
-
this.currentAccountType = accountType
|
|
149
|
-
}
|
|
150
|
-
|
|
151
94
|
setAccountPrivateKey(privateKeyHex: string) {
|
|
152
95
|
this.privateKey = Buffer.from(privateKeyHex, "hex")
|
|
153
96
|
let publicKey = getPubKeyFromPrivateKeyHex(privateKeyHex, this.network)
|
|
154
97
|
this.publicKey = publicKey
|
|
98
|
+
this.setAccountType("p2wpkh")
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
setAccountType(accountType = "p2pkh") {
|
|
102
|
+
if (!this.publicKey) {
|
|
103
|
+
throw new Error("account not initialized")
|
|
104
|
+
}
|
|
105
|
+
let addressObj = this.transactionBuilder.createAddressObject({
|
|
106
|
+
addressType: accountType,
|
|
107
|
+
publicKey: this.publicKey,
|
|
108
|
+
})
|
|
109
|
+
this.currentAccount = addressObj.address
|
|
110
|
+
this.currentAccountType = accountType
|
|
111
|
+
this.addressObj = addressObj
|
|
112
|
+
this.bitcoinAddress = addressObj.address
|
|
113
|
+
return addressObj.address!
|
|
155
114
|
}
|
|
156
115
|
|
|
157
116
|
setAccountPrivateKeyByMnemonic({
|
|
@@ -179,87 +138,162 @@ export class BitcoinBaseWallet {
|
|
|
179
138
|
const account = node.derivePath(path)
|
|
180
139
|
const userKeyPair = account.derive(index)
|
|
181
140
|
this.setAccountPrivateKey(userKeyPair.privateKey!.toString("hex"))
|
|
182
|
-
return this.
|
|
141
|
+
return this.setAccountType(addressType)
|
|
183
142
|
}
|
|
184
143
|
|
|
185
|
-
|
|
186
|
-
this.publicKey = Buffer.from(publicKeyHex, "hex")
|
|
187
|
-
}
|
|
144
|
+
// helper function
|
|
188
145
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
146
|
+
checkBalanceIsSufficient({
|
|
147
|
+
targets,
|
|
148
|
+
extendedUtxo,
|
|
149
|
+
changeAddress,
|
|
150
|
+
feeRate,
|
|
151
|
+
}: {
|
|
152
|
+
targets: Target[]
|
|
153
|
+
extendedUtxo: ExtendedUtxo[]
|
|
154
|
+
changeAddress: string
|
|
155
|
+
feeRate: number
|
|
156
|
+
}) {
|
|
157
|
+
try {
|
|
158
|
+
this.transactionBuilder.helperHandleInputsAndOutputs({
|
|
159
|
+
targets,
|
|
160
|
+
extendedUtxo,
|
|
161
|
+
changeObject: {
|
|
162
|
+
address: changeAddress,
|
|
163
|
+
},
|
|
164
|
+
feeRate,
|
|
165
|
+
})
|
|
166
|
+
return true
|
|
167
|
+
} catch (err) {
|
|
168
|
+
return false
|
|
192
169
|
}
|
|
193
|
-
let addressObj = this.transactionBuilder.createAddressObject({
|
|
194
|
-
addressType: accountType,
|
|
195
|
-
publicKey: this.publicKey,
|
|
196
|
-
})
|
|
197
|
-
this.currentAccount = addressObj.address
|
|
198
|
-
this.currentAccountType = accountType
|
|
199
|
-
this.addressObj = addressObj
|
|
200
|
-
this.bitcoinAddress = addressObj.address
|
|
201
|
-
return addressObj.address
|
|
202
170
|
}
|
|
203
171
|
|
|
204
|
-
//
|
|
205
|
-
|
|
206
172
|
async getExtendedUtxo(input: SignerInfo) {
|
|
207
|
-
return this.
|
|
173
|
+
return this.btcInterface.getExtendedUtxo(input)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
async getFeeRate(feeRate: FeeRateType = "normal") {
|
|
177
|
+
if (feeRate === 0) throw new Error("feeRate should be greater than 0")
|
|
178
|
+
if (+feeRate > 0) return +feeRate
|
|
179
|
+
if (typeof feeRate === "string") return this.btcInterface.getFeeRate(feeRate)
|
|
180
|
+
throw new Error("incorrect feeRate")
|
|
208
181
|
}
|
|
209
182
|
|
|
210
|
-
|
|
183
|
+
// signed methods
|
|
184
|
+
|
|
185
|
+
async sendBTC(
|
|
211
186
|
receiverAddress: string,
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
187
|
+
amountInSatoshi: number | "all",
|
|
188
|
+
fee: FeeRateType = "normal",
|
|
189
|
+
staticExtendedUtxo?: ExtendedUtxo[],
|
|
215
190
|
) {
|
|
216
|
-
if (!this.
|
|
191
|
+
if (!this.signerInfo! || !this.privateKey) {
|
|
217
192
|
throw new Error("account not initialized")
|
|
218
193
|
}
|
|
194
|
+
const unsignedTx = await this.sendBTCUnsignedTx(
|
|
195
|
+
receiverAddress,
|
|
196
|
+
amountInSatoshi,
|
|
197
|
+
this.signerInfo!,
|
|
198
|
+
fee,
|
|
199
|
+
staticExtendedUtxo,
|
|
200
|
+
)
|
|
201
|
+
let signedPsbt = await this.signer.signPsbt(unsignedTx, this.privateKey)
|
|
202
|
+
let signedTx = this.signer.finalizePsbts([signedPsbt])
|
|
203
|
+
let txId = await this.sendSignedTx(signedTx)
|
|
204
|
+
return txId
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async sendBTCMultipleAddress(
|
|
208
|
+
receivers: TargetAddress[],
|
|
209
|
+
fee: FeeRateType = "normal",
|
|
210
|
+
staticExtendedUtxo?: ExtendedUtxo[],
|
|
211
|
+
) {
|
|
212
|
+
if (!this.signerInfo! || !this.privateKey) {
|
|
213
|
+
throw new Error("account not initialized")
|
|
214
|
+
}
|
|
215
|
+
const unsignedTx = await this.sendBTCToMultipleAddressUnsignedTx(
|
|
216
|
+
receivers,
|
|
217
|
+
this.signerInfo!,
|
|
218
|
+
fee,
|
|
219
|
+
staticExtendedUtxo,
|
|
220
|
+
)
|
|
221
|
+
let signedPsbt = await this.signer.signPsbt(unsignedTx, this.privateKey)
|
|
222
|
+
let signedTx = this.signer.finalizePsbts([signedPsbt])
|
|
223
|
+
let txId = await this.sendSignedTx(signedTx)
|
|
224
|
+
return txId
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// unsigned methods
|
|
228
|
+
async sendBTCToMultipleAddressUnsignedTx(
|
|
229
|
+
receivers: TargetAddress[],
|
|
230
|
+
signerInfo: SignerInfo,
|
|
231
|
+
fee: FeeRateType = "normal",
|
|
232
|
+
staticExtendedUtxo?: ExtendedUtxo[],
|
|
233
|
+
fullAmount = false,
|
|
234
|
+
) {
|
|
235
|
+
if (!fullAmount) {
|
|
236
|
+
receivers.forEach((r) => {
|
|
237
|
+
if (BigNumber(r.value).isEqualTo(0)) throw new Error("incorrect amount")
|
|
238
|
+
})
|
|
239
|
+
} else if (receivers.length > 1) throw new Error("fullAmount only support one receiver")
|
|
240
|
+
|
|
241
|
+
let feeRate = await this.getFeeRate(fee)
|
|
242
|
+
let extendedUtxo = staticExtendedUtxo || (await this.getExtendedUtxo(signerInfo))
|
|
219
243
|
|
|
220
|
-
let extendedUtxo = await this.getExtendedUtxo({
|
|
221
|
-
address: this.currentAccount,
|
|
222
|
-
addressType: this.currentAccountType,
|
|
223
|
-
publicKey: this.publicKey.toString("hex"),
|
|
224
|
-
})
|
|
225
|
-
if (!fullAmount && BigNumber(amount).isEqualTo(0))
|
|
226
|
-
throw new Error("incorrect amount. amount should be in satoshi")
|
|
227
|
-
let feeRate = await this.transactionBuilder._getFeeRate(speed)
|
|
228
244
|
let unsignedTx = await this.transactionBuilder.processUnsignedTransaction({
|
|
229
245
|
extendedUtxo,
|
|
230
|
-
targets:
|
|
231
|
-
|
|
232
|
-
address: receiverAddress,
|
|
233
|
-
value: +amount,
|
|
234
|
-
},
|
|
235
|
-
],
|
|
236
|
-
changeAddress: this.currentAccount,
|
|
246
|
+
targets: receivers,
|
|
247
|
+
changeAddress: signerInfo.address,
|
|
237
248
|
feeRate,
|
|
238
249
|
fullAmount,
|
|
239
250
|
})
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
251
|
+
return unsignedTx
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
async sendBTCUnsignedTx(
|
|
255
|
+
receiver: string,
|
|
256
|
+
amountInSatoshi: number | "all",
|
|
257
|
+
signerInfo: SignerInfo,
|
|
258
|
+
fee: FeeRateType = "normal",
|
|
259
|
+
staticExtendedUtxo?: ExtendedUtxo[],
|
|
260
|
+
) {
|
|
261
|
+
return this.sendBTCToMultipleAddressUnsignedTx(
|
|
262
|
+
[{ address: receiver, value: amountInSatoshi === "all" ? 0 : amountInSatoshi }],
|
|
263
|
+
signerInfo,
|
|
264
|
+
fee,
|
|
265
|
+
staticExtendedUtxo,
|
|
266
|
+
amountInSatoshi === "all",
|
|
267
|
+
)
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// send tx
|
|
271
|
+
|
|
272
|
+
async sendSignedTx(signedTx: string) {
|
|
273
|
+
let txId = await this.btcInterface.sendRawTransaction(signedTx)
|
|
243
274
|
return txId
|
|
244
275
|
}
|
|
245
276
|
|
|
246
277
|
async sendSignedPsbt(signedPsbt: string) {
|
|
247
278
|
let signedTx = this.signer.finalizePsbts([signedPsbt])
|
|
248
|
-
let txId = await this.
|
|
279
|
+
let txId = await this.sendSignedTx(signedTx)
|
|
249
280
|
return txId
|
|
250
281
|
}
|
|
251
282
|
|
|
252
|
-
async
|
|
253
|
-
|
|
254
|
-
|
|
283
|
+
async sendSignedPsbtWithRetry(signedPsbt: string, { maxTries = 5, retrySleep = 5000 } = {}) {
|
|
284
|
+
return runWithRetries(() => this.sendSignedPsbt(signedPsbt), {
|
|
285
|
+
retrySleep,
|
|
286
|
+
maxTries,
|
|
287
|
+
})
|
|
255
288
|
}
|
|
256
289
|
|
|
257
290
|
async sendMultiSignedPsbt(signedPsbts: string[] = []) {
|
|
258
291
|
let signedTx = this.signer.finalizePsbts(signedPsbts)
|
|
259
|
-
let txId = await this.
|
|
292
|
+
let txId = await this.btcInterface.sendRawTransaction(signedTx)
|
|
260
293
|
return txId
|
|
261
294
|
}
|
|
262
295
|
|
|
296
|
+
// increase transaction fee (beta vesrion)
|
|
263
297
|
async increaseTransactionFeeUnsignedPsbt(
|
|
264
298
|
txId: string,
|
|
265
299
|
signerInfos: SignerInfo[],
|
|
@@ -284,7 +318,7 @@ export class BitcoinBaseWallet {
|
|
|
284
318
|
transaction.vin.find((vi) => vo.address === vi.address || vo.address === changeAddress),
|
|
285
319
|
)
|
|
286
320
|
|
|
287
|
-
const feeRate = staticFeeRate || (await this.
|
|
321
|
+
const feeRate = staticFeeRate || (await this.btcInterface.getFeeRate("fast"))
|
|
288
322
|
|
|
289
323
|
let targets = transaction.vout
|
|
290
324
|
.filter((_, index) => index !== changeIndex)
|