@teleportdao/bitcoin 1.4.4 → 1.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bitcoin-base.d.ts +62 -50
- package/dist/bitcoin-base.d.ts.map +1 -1
- package/dist/bitcoin-base.js +55 -28
- package/dist/bitcoin-base.js.map +1 -1
- package/dist/bitcoin-interface-utils.d.ts +12 -10
- package/dist/bitcoin-interface-utils.d.ts.map +1 -1
- package/dist/bitcoin-interface-utils.js +16 -10
- package/dist/bitcoin-interface-utils.js.map +1 -1
- package/dist/bitcoin-interface.d.ts +206 -50
- package/dist/bitcoin-interface.d.ts.map +1 -1
- package/dist/bitcoin-interface.js +42 -27
- package/dist/bitcoin-interface.js.map +1 -1
- package/dist/bitcoin-utils.d.ts +111 -41
- package/dist/bitcoin-utils.d.ts.map +1 -1
- package/dist/bitcoin-utils.js +215 -159
- package/dist/bitcoin-utils.js.map +1 -1
- package/dist/bundle.js +13 -4
- package/dist/index.d.ts +5 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +31 -13
- package/dist/index.js.map +1 -1
- package/dist/teleport-dao-payments.d.ts +60 -92
- package/dist/teleport-dao-payments.d.ts.map +1 -1
- package/dist/teleport-dao-payments.js +12 -1
- package/dist/teleport-dao-payments.js.map +1 -1
- package/dist/transaction-builder/bitcoin-transaction-builder.d.ts +8 -4
- package/dist/transaction-builder/bitcoin-transaction-builder.d.ts.map +1 -1
- package/dist/transaction-builder/bitcoin-transaction-builder.js +3 -3
- package/dist/transaction-builder/bitcoin-transaction-builder.js.map +1 -1
- package/dist/transaction-builder/transaction-builder.d.ts +63 -13
- package/dist/transaction-builder/transaction-builder.d.ts.map +1 -1
- package/dist/transaction-builder/transaction-builder.js +72 -19
- package/dist/transaction-builder/transaction-builder.js.map +1 -1
- package/dist/utils/networks.d.ts +5 -35
- package/dist/utils/networks.d.ts.map +1 -1
- package/dist/utils/networks.js +26 -2
- package/dist/utils/networks.js.map +1 -1
- package/dist/utils/tools.d.ts +15 -9
- package/dist/utils/tools.d.ts.map +1 -1
- package/dist/utils/tools.js +14 -11
- package/dist/utils/tools.js.map +1 -1
- package/package.json +6 -6
- package/src/{bitcoin-base.js → bitcoin-base.ts} +97 -69
- package/src/{bitcoin-interface-utils.js → bitcoin-interface-utils.ts} +59 -53
- package/src/{bitcoin-interface.js → bitcoin-interface.ts} +115 -45
- package/src/{bitcoin-utils.js → bitcoin-utils.ts} +337 -216
- package/src/index.ts +5 -8
- package/src/{teleport-dao-payments.js → teleport-dao-payments.ts} +67 -6
- package/src/transaction-builder/bitcoin-transaction-builder.ts +8 -4
- package/src/transaction-builder/transaction-builder.ts +102 -25
- package/src/utils/{networks.js → networks.ts} +33 -31
- package/src/utils/{tools.js → tools.ts} +80 -72
- package/tsconfig.json +10 -9
- package/webpack.config.js +16 -0
- package/dist/transaction-builder/transaction-builder-common.d.ts +0 -57
- package/dist/transaction-builder/transaction-builder-common.d.ts.map +0 -1
- package/dist/transaction-builder/transaction-builder-common.js +0 -183
- package/dist/transaction-builder/transaction-builder-common.js.map +0 -1
|
@@ -1,9 +1,31 @@
|
|
|
1
|
+
import type { ExtendedUtxo, Target } from "./transaction-builder/transaction-builder"
|
|
1
2
|
import { BitcoinBase } from "./bitcoin-base"
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
export type TransferRequest = {
|
|
5
|
+
changeAddress?: string
|
|
6
|
+
lockerAddress: string
|
|
7
|
+
amount: number
|
|
8
|
+
fullAmount?: boolean
|
|
9
|
+
//-----------
|
|
10
|
+
chainId: number
|
|
11
|
+
appId: number
|
|
12
|
+
recipientAddress: string // 20 bytes
|
|
13
|
+
percentageFee: number // 2 bytes in satoshi
|
|
14
|
+
speed?: number | boolean // 1 byte
|
|
15
|
+
isExchange?: boolean
|
|
16
|
+
exchangeTokenAddress?: string // 20 bytes
|
|
17
|
+
outputAmount?: number // 28 bytes
|
|
18
|
+
deadline?: number // 4 bytes
|
|
19
|
+
isFixedToken?: boolean // 1 byte
|
|
20
|
+
feeSpeed?: "normal" | "fast" | "slow"
|
|
21
|
+
}
|
|
22
|
+
export class TeleportDaoPayment extends BitcoinBase {
|
|
4
23
|
// payment
|
|
5
|
-
async payBurnRequest(receivers, feeSpeed = "normal") {
|
|
6
|
-
|
|
24
|
+
async payBurnRequest(receivers: Target[], feeSpeed: "normal" | "fast" | "slow" = "normal") {
|
|
25
|
+
if (!this.currentAccount || !this.currentAccountType || !this.publicKey || !this.privateKey) {
|
|
26
|
+
throw new Error("account not initialized")
|
|
27
|
+
}
|
|
28
|
+
let extendedUtxo = await this.getExtendedUtxo({
|
|
7
29
|
address: this.currentAccount,
|
|
8
30
|
addressType: this.currentAccountType,
|
|
9
31
|
publicKey: this.publicKey.toString("hex"),
|
|
@@ -40,7 +62,10 @@ class TeleportDaoPayment extends BitcoinBase {
|
|
|
40
62
|
deadline, // 4 bytes
|
|
41
63
|
isFixedToken = false, // 1 byte
|
|
42
64
|
feeSpeed = "normal",
|
|
43
|
-
}) {
|
|
65
|
+
}: TransferRequest) {
|
|
66
|
+
if (!this.currentAccount || !this.currentAccountType || !this.publicKey || !this.privateKey) {
|
|
67
|
+
throw new Error("account not initialized")
|
|
68
|
+
}
|
|
44
69
|
let extendedUtxo = await this.getExtendedUtxo({
|
|
45
70
|
address: this.currentAccount,
|
|
46
71
|
addressType: this.currentAccountType,
|
|
@@ -86,7 +111,7 @@ class TeleportDaoPayment extends BitcoinBase {
|
|
|
86
111
|
outputAmount = 0, // 28 bytes
|
|
87
112
|
deadline = 0, // 4 bytes
|
|
88
113
|
isFixedToken = false, // 1 byte
|
|
89
|
-
}) {
|
|
114
|
+
}: TransferRequest): Promise<Target[]> {
|
|
90
115
|
let dataHex = TeleportDaoPayment.getTransferOpReturnData({
|
|
91
116
|
chainId,
|
|
92
117
|
appId,
|
|
@@ -129,6 +154,8 @@ class TeleportDaoPayment extends BitcoinBase {
|
|
|
129
154
|
deadline = 0, // 4 bytes
|
|
130
155
|
isFixedToken = false, // 1 byte
|
|
131
156
|
feeSpeed = "normal",
|
|
157
|
+
}: TransferRequest & {
|
|
158
|
+
extendedUtxo: ExtendedUtxo[]
|
|
132
159
|
}) {
|
|
133
160
|
let feeRate = await this.transactionBuilder._getFeeRate(feeSpeed)
|
|
134
161
|
let targets = await this.getBitcoinToEthTargetOutputs({
|
|
@@ -169,7 +196,22 @@ class TeleportDaoPayment extends BitcoinBase {
|
|
|
169
196
|
isBorrow = false,
|
|
170
197
|
tokenAddress = "0x0000000000000000000000000000000000000000", // 20 bytes
|
|
171
198
|
borrowAmount = 0, // 28 bytes
|
|
199
|
+
}: {
|
|
200
|
+
lockerAddress: string
|
|
201
|
+
amount: number
|
|
202
|
+
chainId: number
|
|
203
|
+
appId: number
|
|
204
|
+
recipientAddress: string // 20 bytes
|
|
205
|
+
percentageFee: number // 2 bytes in satoshi
|
|
206
|
+
mode?: 0 | 1 | boolean // 1 byte
|
|
207
|
+
isBorrow?: boolean
|
|
208
|
+
tokenAddress?: string // 20 bytes
|
|
209
|
+
borrowAmount?: number // 28 bytes
|
|
172
210
|
}) {
|
|
211
|
+
if (!this.currentAccount || !this.currentAccountType || !this.publicKey || !this.privateKey) {
|
|
212
|
+
throw new Error("account not initialized")
|
|
213
|
+
}
|
|
214
|
+
|
|
173
215
|
let dataHex = TeleportDaoPayment.getLendingOpReturnData({
|
|
174
216
|
chainId,
|
|
175
217
|
appId,
|
|
@@ -217,6 +259,17 @@ class TeleportDaoPayment extends BitcoinBase {
|
|
|
217
259
|
outputAmount = 0, // 28 bytes
|
|
218
260
|
deadline, // 4 bytes
|
|
219
261
|
isFixedToken = false, // 1 byte
|
|
262
|
+
}: {
|
|
263
|
+
chainId: number
|
|
264
|
+
appId: number
|
|
265
|
+
recipientAddress: string // 20 bytes
|
|
266
|
+
percentageFee: number // 2 bytes in satoshi
|
|
267
|
+
deadline: number // 4 bytes
|
|
268
|
+
speed?: number | boolean // 1 byte
|
|
269
|
+
isExchange?: boolean
|
|
270
|
+
exchangeTokenAddress?: string // 20 bytes
|
|
271
|
+
outputAmount?: number // 28 bytes
|
|
272
|
+
isFixedToken?: boolean // 1 byte
|
|
220
273
|
}) {
|
|
221
274
|
let chainIdHex = Number(chainId).toString(16).padStart(2, "0")
|
|
222
275
|
let appIdHex = Number(appId).toString(16).padStart(4, "0")
|
|
@@ -255,6 +308,15 @@ class TeleportDaoPayment extends BitcoinBase {
|
|
|
255
308
|
isBorrow = false,
|
|
256
309
|
tokenAddress = "0x0000000000000000000000000000000000000000", // 20 bytes
|
|
257
310
|
borrowAmount = 0, // 28 bytes
|
|
311
|
+
}: {
|
|
312
|
+
chainId: number
|
|
313
|
+
appId: number
|
|
314
|
+
recipientAddress: string // 20 bytes
|
|
315
|
+
percentageFee: number // 2 bytes in satoshi
|
|
316
|
+
mode?: 0 | 1 | boolean // 1 byte
|
|
317
|
+
isBorrow?: boolean
|
|
318
|
+
tokenAddress?: string // 20 bytes
|
|
319
|
+
borrowAmount?: number // 28 bytes
|
|
258
320
|
}) {
|
|
259
321
|
let chainIdHex = Number(chainId).toString(16).padStart(2, "0")
|
|
260
322
|
let appIdHex = Number(appId).toString(16).padStart(4, "0")
|
|
@@ -276,5 +338,4 @@ class TeleportDaoPayment extends BitcoinBase {
|
|
|
276
338
|
return dataHex
|
|
277
339
|
}
|
|
278
340
|
}
|
|
279
|
-
|
|
280
341
|
export default TeleportDaoPayment
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import BaseTransactionBuilder from "./transaction-builder"
|
|
2
|
-
import BitcoinInterface from "../bitcoin-interface"
|
|
2
|
+
import { BitcoinInterface } from "../bitcoin-interface"
|
|
3
3
|
import * as bitcoin from "bitcoinjs-lib"
|
|
4
4
|
|
|
5
5
|
export type BitcoinConnectionInfo = {
|
|
@@ -9,10 +9,14 @@ export type BitcoinConnectionInfo = {
|
|
|
9
9
|
headers?: {
|
|
10
10
|
[key: string]: string
|
|
11
11
|
}
|
|
12
|
-
auth
|
|
12
|
+
auth?: {
|
|
13
|
+
username: string
|
|
14
|
+
password: string
|
|
15
|
+
}
|
|
13
16
|
}
|
|
14
|
-
api
|
|
17
|
+
api: {
|
|
15
18
|
enabled?: boolean
|
|
19
|
+
token?: string
|
|
16
20
|
provider: string
|
|
17
21
|
}
|
|
18
22
|
}
|
|
@@ -40,7 +44,7 @@ class BitcoinTransactionBuilder extends BaseTransactionBuilder {
|
|
|
40
44
|
}))
|
|
41
45
|
}
|
|
42
46
|
|
|
43
|
-
async _getFeeRate(speed:
|
|
47
|
+
async _getFeeRate(speed: "normal" | "slow" | "fast" = "normal") {
|
|
44
48
|
return this.btcInterface.getFeeRate(speed)
|
|
45
49
|
}
|
|
46
50
|
|
|
@@ -36,6 +36,7 @@ export type SignerInfo = {
|
|
|
36
36
|
addressType: string
|
|
37
37
|
derivationPath?: string
|
|
38
38
|
masterFingerprint?: string
|
|
39
|
+
includeHex?: boolean
|
|
39
40
|
}
|
|
40
41
|
export type ExtendedUtxo = {
|
|
41
42
|
signerInfo: SignerInfo
|
|
@@ -54,6 +55,13 @@ export type TargetScript = {
|
|
|
54
55
|
value: number
|
|
55
56
|
}
|
|
56
57
|
export type Target = TargetAddress | TargetScript
|
|
58
|
+
export type ChangeTarget = TargetAddress & {
|
|
59
|
+
bip32Derivation?: {
|
|
60
|
+
path: string
|
|
61
|
+
pubkey: Buffer
|
|
62
|
+
masterFingerprint: Buffer
|
|
63
|
+
}[]
|
|
64
|
+
}
|
|
57
65
|
|
|
58
66
|
export type BitcoinJSInputInfo = ExtendedUtxo & {
|
|
59
67
|
bip32Derivation?: {
|
|
@@ -146,7 +154,7 @@ class BaseBitcoinLikeTransaction {
|
|
|
146
154
|
network: this.network,
|
|
147
155
|
})
|
|
148
156
|
return {
|
|
149
|
-
script: embed.output
|
|
157
|
+
script: embed.output!,
|
|
150
158
|
value: 0,
|
|
151
159
|
}
|
|
152
160
|
}
|
|
@@ -167,13 +175,19 @@ class BaseBitcoinLikeTransaction {
|
|
|
167
175
|
targets,
|
|
168
176
|
extendedUtxo,
|
|
169
177
|
feeRate,
|
|
170
|
-
|
|
178
|
+
changeObject,
|
|
171
179
|
selectType = "normal", // "accumulative" | "normal" | "full"
|
|
172
180
|
}: {
|
|
173
181
|
extendedUtxo: ExtendedUtxo[]
|
|
174
182
|
targets: Target[]
|
|
175
183
|
feeRate: number
|
|
176
|
-
|
|
184
|
+
changeObject?: {
|
|
185
|
+
address: string
|
|
186
|
+
publicKey?: string
|
|
187
|
+
addressType?: string
|
|
188
|
+
derivationPath?: string
|
|
189
|
+
masterFingerprint?: string
|
|
190
|
+
}
|
|
177
191
|
selectType?: "normal" | "accumulative" | "full"
|
|
178
192
|
}) {
|
|
179
193
|
let selectResponse
|
|
@@ -217,12 +231,26 @@ class BaseBitcoinLikeTransaction {
|
|
|
217
231
|
throw new Error("not enough balance")
|
|
218
232
|
}
|
|
219
233
|
let changeIndex = outputs.findIndex((x) => !x?.address && !x.script && (x.value || 0) > 0)
|
|
220
|
-
let change:
|
|
234
|
+
let change: ChangeTarget | undefined
|
|
221
235
|
if (changeIndex >= 0) {
|
|
222
|
-
if (!
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
236
|
+
if (!changeObject) throw new Error("change not exist")
|
|
237
|
+
if (changeObject.derivationPath && changeObject.masterFingerprint && changeObject.publicKey) {
|
|
238
|
+
change = {
|
|
239
|
+
address: changeObject.address,
|
|
240
|
+
value: outputs[changeIndex].value,
|
|
241
|
+
bip32Derivation: [
|
|
242
|
+
{
|
|
243
|
+
path: changeObject.derivationPath,
|
|
244
|
+
pubkey: Buffer.from(changeObject.publicKey, "hex"),
|
|
245
|
+
masterFingerprint: Buffer.from(changeObject.masterFingerprint, "hex"),
|
|
246
|
+
},
|
|
247
|
+
],
|
|
248
|
+
}
|
|
249
|
+
} else {
|
|
250
|
+
change = {
|
|
251
|
+
address: changeObject.address,
|
|
252
|
+
value: outputs[changeIndex].value,
|
|
253
|
+
}
|
|
226
254
|
}
|
|
227
255
|
outputs.splice(changeIndex, 1)
|
|
228
256
|
}
|
|
@@ -231,21 +259,27 @@ class BaseBitcoinLikeTransaction {
|
|
|
231
259
|
inputs,
|
|
232
260
|
fee,
|
|
233
261
|
outputs: outputs as Target[],
|
|
234
|
-
change
|
|
262
|
+
change,
|
|
235
263
|
}
|
|
236
264
|
}
|
|
237
265
|
|
|
238
266
|
async filterAndConvertTxDataToStandardFormat({
|
|
239
267
|
extendedUtxo,
|
|
240
268
|
targets,
|
|
241
|
-
|
|
269
|
+
changeObject,
|
|
242
270
|
feeRate,
|
|
243
271
|
selectType,
|
|
244
272
|
}: {
|
|
245
273
|
extendedUtxo: ExtendedUtxo[]
|
|
246
274
|
targets: Target[]
|
|
247
275
|
feeRate: number
|
|
248
|
-
|
|
276
|
+
changeObject?: {
|
|
277
|
+
address: string
|
|
278
|
+
publicKey?: string
|
|
279
|
+
addressType?: string
|
|
280
|
+
derivationPath?: string
|
|
281
|
+
masterFingerprint?: string
|
|
282
|
+
}
|
|
249
283
|
selectType?: "normal" | "accumulative" | "full"
|
|
250
284
|
}) {
|
|
251
285
|
let {
|
|
@@ -257,7 +291,7 @@ class BaseBitcoinLikeTransaction {
|
|
|
257
291
|
targets,
|
|
258
292
|
extendedUtxo,
|
|
259
293
|
feeRate,
|
|
260
|
-
|
|
294
|
+
changeObject,
|
|
261
295
|
selectType,
|
|
262
296
|
})
|
|
263
297
|
|
|
@@ -274,7 +308,9 @@ class BaseBitcoinLikeTransaction {
|
|
|
274
308
|
|
|
275
309
|
// ?note : we can extend this class and change this method for network other than bitcoin
|
|
276
310
|
async convertExtendedUtxoToInputs(baseInputs: ExtendedUtxo[] = []) {
|
|
277
|
-
let inputs: BitcoinJSInputInfo
|
|
311
|
+
let inputs: (BitcoinJSInputInfo & {
|
|
312
|
+
signerInfo: SignerInfo
|
|
313
|
+
})[] = baseInputs
|
|
278
314
|
let transactionId: string | null = null
|
|
279
315
|
let transactionHex: string | null = null
|
|
280
316
|
for (let i in inputs) {
|
|
@@ -310,6 +346,16 @@ class BaseBitcoinLikeTransaction {
|
|
|
310
346
|
script: addressObject.output,
|
|
311
347
|
value: inputs[i].value,
|
|
312
348
|
}
|
|
349
|
+
|
|
350
|
+
if (inputs[i].signerInfo.includeHex) {
|
|
351
|
+
if (transactionHex && transactionId === inputs[i].hash) {
|
|
352
|
+
inputs[i].nonWitnessUtxo = Buffer.from(transactionHex, "hex")
|
|
353
|
+
} else {
|
|
354
|
+
transactionHex = await this._getTransactionHex(inputs[i].hash)
|
|
355
|
+
transactionId = inputs[i].hash
|
|
356
|
+
inputs[i].nonWitnessUtxo = Buffer.from(transactionHex, "hex")
|
|
357
|
+
}
|
|
358
|
+
}
|
|
313
359
|
} else if (addressType === "p2sh-p2wpkh") {
|
|
314
360
|
// add p2sh-p2wpkh data
|
|
315
361
|
if (!addressObject.output) throw new Error("invalid signer info")
|
|
@@ -319,6 +365,16 @@ class BaseBitcoinLikeTransaction {
|
|
|
319
365
|
}
|
|
320
366
|
if (!addressObject?.redeem?.output) throw new Error("invalid signer info for p2sh address")
|
|
321
367
|
inputs[i].redeemScript = addressObject.redeem.output
|
|
368
|
+
|
|
369
|
+
if (inputs[i].signerInfo.includeHex) {
|
|
370
|
+
if (transactionHex && transactionId === inputs[i].hash) {
|
|
371
|
+
inputs[i].nonWitnessUtxo = Buffer.from(transactionHex, "hex")
|
|
372
|
+
} else {
|
|
373
|
+
transactionHex = await this._getTransactionHex(inputs[i].hash)
|
|
374
|
+
transactionId = inputs[i].hash
|
|
375
|
+
inputs[i].nonWitnessUtxo = Buffer.from(transactionHex, "hex")
|
|
376
|
+
}
|
|
377
|
+
}
|
|
322
378
|
} else if (addressType === "p2tr") {
|
|
323
379
|
if (!addressObject.output) throw new Error("invalid signer info")
|
|
324
380
|
inputs[i].witnessUtxo = {
|
|
@@ -328,6 +384,16 @@ class BaseBitcoinLikeTransaction {
|
|
|
328
384
|
if (!addressObject.pubkey) throw new Error("invalid signer info for p2tr address (pubkey)")
|
|
329
385
|
// todo: fix after update to p2tr
|
|
330
386
|
inputs[i].tapInternalKey = Buffer.from(publicKey, "hex")
|
|
387
|
+
|
|
388
|
+
if (inputs[i].signerInfo.includeHex) {
|
|
389
|
+
if (transactionHex && transactionId === inputs[i].hash) {
|
|
390
|
+
inputs[i].nonWitnessUtxo = Buffer.from(transactionHex, "hex")
|
|
391
|
+
} else {
|
|
392
|
+
transactionHex = await this._getTransactionHex(inputs[i].hash)
|
|
393
|
+
transactionId = inputs[i].hash
|
|
394
|
+
inputs[i].nonWitnessUtxo = Buffer.from(transactionHex, "hex")
|
|
395
|
+
}
|
|
396
|
+
}
|
|
331
397
|
}
|
|
332
398
|
}
|
|
333
399
|
|
|
@@ -344,7 +410,7 @@ class BaseBitcoinLikeTransaction {
|
|
|
344
410
|
}: {
|
|
345
411
|
inputs: BitcoinJSInputInfo[]
|
|
346
412
|
outputs: Target[]
|
|
347
|
-
change?:
|
|
413
|
+
change?: ChangeTarget
|
|
348
414
|
fee: number
|
|
349
415
|
feeRate: number
|
|
350
416
|
}) {
|
|
@@ -372,10 +438,13 @@ class BaseBitcoinLikeTransaction {
|
|
|
372
438
|
hash: input.hash,
|
|
373
439
|
index: Number(input.index),
|
|
374
440
|
witnessUtxo: input.witnessUtxo,
|
|
441
|
+
// we dont need nonWitnessUtxo. bud some application force nonWitnessUtxo
|
|
442
|
+
nonWitnessUtxo: input.nonWitnessUtxo,
|
|
375
443
|
sequence: 0xffffffff - 1,
|
|
376
444
|
bip32Derivation: input.bip32Derivation,
|
|
377
445
|
}
|
|
378
446
|
if (!i.bip32Derivation) delete i.bip32Derivation
|
|
447
|
+
if (!i.nonWitnessUtxo) delete i.nonWitnessUtxo
|
|
379
448
|
newPsbt.addInput(i)
|
|
380
449
|
break
|
|
381
450
|
}
|
|
@@ -384,11 +453,14 @@ class BaseBitcoinLikeTransaction {
|
|
|
384
453
|
hash: input.hash,
|
|
385
454
|
index: Number(input.index),
|
|
386
455
|
witnessUtxo: input.witnessUtxo,
|
|
456
|
+
// we dont need nonWitnessUtxo. bud some application force nonWitnessUtxo
|
|
457
|
+
nonWitnessUtxo: input.nonWitnessUtxo,
|
|
387
458
|
redeemScript: input.redeemScript,
|
|
388
459
|
sequence: 0xffffffff - 1,
|
|
389
460
|
bip32Derivation: input.bip32Derivation,
|
|
390
461
|
}
|
|
391
462
|
if (!i.bip32Derivation) delete i.bip32Derivation
|
|
463
|
+
if (!i.nonWitnessUtxo) delete i.nonWitnessUtxo
|
|
392
464
|
newPsbt.addInput(i)
|
|
393
465
|
break
|
|
394
466
|
}
|
|
@@ -397,11 +469,14 @@ class BaseBitcoinLikeTransaction {
|
|
|
397
469
|
hash: input.hash,
|
|
398
470
|
index: Number(input.index),
|
|
399
471
|
witnessUtxo: input.witnessUtxo,
|
|
472
|
+
// we dont need nonWitnessUtxo. bud some application force nonWitnessUtxo
|
|
473
|
+
nonWitnessUtxo: input.nonWitnessUtxo,
|
|
400
474
|
tapInternalKey: input.tapInternalKey,
|
|
401
475
|
sequence: 0xffffffff - 1,
|
|
402
476
|
bip32Derivation: input.bip32Derivation,
|
|
403
477
|
}
|
|
404
478
|
if (!i.bip32Derivation) delete i.bip32Derivation
|
|
479
|
+
if (!i.nonWitnessUtxo) delete i.nonWitnessUtxo
|
|
405
480
|
newPsbt.addInput(i)
|
|
406
481
|
break
|
|
407
482
|
}
|
|
@@ -412,15 +487,12 @@ class BaseBitcoinLikeTransaction {
|
|
|
412
487
|
|
|
413
488
|
// add outputs
|
|
414
489
|
for (const target of outputs) {
|
|
415
|
-
newPsbt.addOutput(target)
|
|
490
|
+
newPsbt.addOutput({ ...target })
|
|
416
491
|
}
|
|
417
492
|
|
|
418
493
|
// add changeAddress
|
|
419
494
|
if (change && Object.keys(change).length !== 0) {
|
|
420
|
-
newPsbt.addOutput(
|
|
421
|
-
address: change.address,
|
|
422
|
-
value: Number(change.value),
|
|
423
|
-
})
|
|
495
|
+
newPsbt.addOutput(change)
|
|
424
496
|
}
|
|
425
497
|
|
|
426
498
|
// check created outputs with targets
|
|
@@ -428,9 +500,9 @@ class BaseBitcoinLikeTransaction {
|
|
|
428
500
|
if (newPsbt.txOutputs[outputs.length].address !== change.address) {
|
|
429
501
|
throw new Error("error change address")
|
|
430
502
|
}
|
|
431
|
-
if (newPsbt.txOutputs[outputs.length].value !== change.value) {
|
|
432
|
-
|
|
433
|
-
}
|
|
503
|
+
// if (newPsbt.txOutputs[outputs.length].value !== change.value) {
|
|
504
|
+
// throw new Error("error change value")
|
|
505
|
+
// }
|
|
434
506
|
}
|
|
435
507
|
|
|
436
508
|
const unsignedPsbtBaseText = newPsbt.toBase64()
|
|
@@ -461,17 +533,22 @@ class BaseBitcoinLikeTransaction {
|
|
|
461
533
|
targets: Target[]
|
|
462
534
|
feeRate: number
|
|
463
535
|
|
|
464
|
-
changeAddress?: string
|
|
536
|
+
changeAddress?: string | SignerInfo
|
|
465
537
|
fullAmount?: boolean
|
|
466
538
|
selfTransaction?: boolean
|
|
467
539
|
selectType?: "normal" | "accumulative" | "full"
|
|
468
540
|
}) {
|
|
469
541
|
if (!selfTransaction && targets.length === 0) throw new Error("no target")
|
|
470
|
-
|
|
542
|
+
let changeObject =
|
|
543
|
+
typeof changeAddress === "string"
|
|
544
|
+
? {
|
|
545
|
+
address: changeAddress,
|
|
546
|
+
}
|
|
547
|
+
: changeAddress
|
|
471
548
|
const { inputs, outputs, change, fee } = await this.filterAndConvertTxDataToStandardFormat({
|
|
472
549
|
extendedUtxo,
|
|
473
550
|
targets,
|
|
474
|
-
|
|
551
|
+
changeObject,
|
|
475
552
|
feeRate,
|
|
476
553
|
selectType: fullAmount ? "full" : selectType,
|
|
477
554
|
})
|
|
@@ -1,31 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const networks
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
1
|
+
import * as bitcoinLib from "bitcoinjs-lib"
|
|
2
|
+
|
|
3
|
+
const networks: {
|
|
4
|
+
[key: string]: bitcoinLib.Network
|
|
5
|
+
} = {
|
|
6
|
+
bitcoin: bitcoinLib.networks.bitcoin,
|
|
7
|
+
bitcoin_testnet: bitcoinLib.networks.testnet,
|
|
8
|
+
|
|
9
|
+
litecoin: {
|
|
10
|
+
messagePrefix: "\x19Litecoin Signed Message:\n",
|
|
11
|
+
bech32: "ltc",
|
|
12
|
+
bip32: {
|
|
13
|
+
public: 0x0488b21e,
|
|
14
|
+
private: 0x0488ade4,
|
|
15
|
+
},
|
|
16
|
+
pubKeyHash: 0x30,
|
|
17
|
+
scriptHash: 0x32,
|
|
18
|
+
wif: 0xb0,
|
|
19
|
+
},
|
|
20
|
+
litecoin_testnet: {
|
|
21
|
+
messagePrefix: "\x18Litecoin Signed Message:\n",
|
|
22
|
+
bech32: "tltc",
|
|
23
|
+
bip32: {
|
|
24
|
+
public: 0x043587cf,
|
|
25
|
+
private: 0x04358394,
|
|
26
|
+
},
|
|
27
|
+
pubKeyHash: 0x6f,
|
|
28
|
+
scriptHash: 0x3a, // old 0xc4 -> 2 deprecated
|
|
29
|
+
wif: 0xef,
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export default networks
|
|
@@ -1,72 +1,80 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const sleep =
|
|
5
|
-
|
|
6
|
-
async function runWithRetries(
|
|
7
|
-
action,
|
|
8
|
-
config = {
|
|
9
|
-
maxTries: 2,
|
|
10
|
-
retrySleep: 1000,
|
|
11
|
-
},
|
|
12
|
-
) {
|
|
13
|
-
const maxTries = config.maxTries || 2
|
|
14
|
-
const retrySleep = config.retrySleep || 1000 // milliseconds
|
|
15
|
-
let lastError
|
|
16
|
-
for (let count = 0; count < maxTries; count += 1) {
|
|
17
|
-
try {
|
|
18
|
-
return await action()
|
|
19
|
-
} catch (error) {
|
|
20
|
-
lastError = error
|
|
21
|
-
}
|
|
22
|
-
await sleep(retrySleep)
|
|
23
|
-
}
|
|
24
|
-
throw lastError || new Error("function failed after retries")
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function getRandomInteger(min, max) {
|
|
28
|
-
return Math.floor(Math.random() * (max - min)) + min
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function getAxiosInstance({
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
1
|
+
import { promisify } from "util"
|
|
2
|
+
import axios from "axios"
|
|
3
|
+
|
|
4
|
+
const sleep = promisify(setTimeout)
|
|
5
|
+
|
|
6
|
+
async function runWithRetries(
|
|
7
|
+
action: () => any,
|
|
8
|
+
config = {
|
|
9
|
+
maxTries: 2,
|
|
10
|
+
retrySleep: 1000,
|
|
11
|
+
},
|
|
12
|
+
) {
|
|
13
|
+
const maxTries = config.maxTries || 2
|
|
14
|
+
const retrySleep = config.retrySleep || 1000 // milliseconds
|
|
15
|
+
let lastError
|
|
16
|
+
for (let count = 0; count < maxTries; count += 1) {
|
|
17
|
+
try {
|
|
18
|
+
return await action()
|
|
19
|
+
} catch (error: any) {
|
|
20
|
+
lastError = error
|
|
21
|
+
}
|
|
22
|
+
await sleep(retrySleep)
|
|
23
|
+
}
|
|
24
|
+
throw lastError || new Error("function failed after retries")
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function getRandomInteger(min: number, max: number) {
|
|
28
|
+
return Math.floor(Math.random() * (max - min)) + min
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function getAxiosInstance({
|
|
32
|
+
baseUrl,
|
|
33
|
+
timeout = 10000,
|
|
34
|
+
headers = {},
|
|
35
|
+
auth,
|
|
36
|
+
}: {
|
|
37
|
+
baseUrl: string
|
|
38
|
+
timeout?: number
|
|
39
|
+
headers?: { [key: string]: string }
|
|
40
|
+
auth?: {
|
|
41
|
+
username: string
|
|
42
|
+
password: string
|
|
43
|
+
}
|
|
44
|
+
}) {
|
|
45
|
+
let host = baseUrl
|
|
46
|
+
let instance
|
|
47
|
+
|
|
48
|
+
instance = axios.create({
|
|
49
|
+
baseURL: host,
|
|
50
|
+
timeout,
|
|
51
|
+
auth,
|
|
52
|
+
headers: {
|
|
53
|
+
...headers,
|
|
54
|
+
},
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
// Add a response interceptor
|
|
58
|
+
instance.interceptors.response.use(
|
|
59
|
+
(response) => response,
|
|
60
|
+
(error) => {
|
|
61
|
+
// todo : fix this part
|
|
62
|
+
if (error.response) {
|
|
63
|
+
const serviceError = new Error(
|
|
64
|
+
JSON.stringify({ data: error.response.data, message: error.message }),
|
|
65
|
+
)
|
|
66
|
+
return Promise.reject(serviceError)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (error.request) {
|
|
70
|
+
const serviceError = new Error(error.message)
|
|
71
|
+
return Promise.reject(serviceError)
|
|
72
|
+
}
|
|
73
|
+
return Promise.reject(error)
|
|
74
|
+
},
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
return instance
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export { sleep, runWithRetries, getRandomInteger, getAxiosInstance }
|
package/tsconfig.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "../../tsconfig.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"rootDir": "src" /* Specify the root folder within your source files. */,
|
|
5
|
-
"outDir": "dist" /* Specify an output folder for all emitted files. */,
|
|
6
|
-
"baseUrl": "./src" /* Specify the base directory to resolve non-relative module names. */
|
|
7
|
-
},
|
|
8
|
-
"
|
|
9
|
-
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"rootDir": "src" /* Specify the root folder within your source files. */,
|
|
5
|
+
"outDir": "dist" /* Specify an output folder for all emitted files. */,
|
|
6
|
+
"baseUrl": "./src" /* Specify the base directory to resolve non-relative module names. */
|
|
7
|
+
},
|
|
8
|
+
"include": ["src"],
|
|
9
|
+
"exclude": ["node_modules", "dist"]
|
|
10
|
+
}
|