@teleportdao/bitcoin 1.4.3 → 1.4.6

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 (69) hide show
  1. package/dist/bitcoin-base.d.ts +66 -53
  2. package/dist/bitcoin-base.d.ts.map +1 -1
  3. package/dist/bitcoin-base.js +47 -38
  4. package/dist/bitcoin-base.js.map +1 -1
  5. package/dist/bitcoin-interface-utils.d.ts +12 -10
  6. package/dist/bitcoin-interface-utils.d.ts.map +1 -1
  7. package/dist/bitcoin-interface-utils.js +16 -10
  8. package/dist/bitcoin-interface-utils.js.map +1 -1
  9. package/dist/bitcoin-interface.d.ts +206 -50
  10. package/dist/bitcoin-interface.d.ts.map +1 -1
  11. package/dist/bitcoin-interface.js +42 -27
  12. package/dist/bitcoin-interface.js.map +1 -1
  13. package/dist/bitcoin-utils.d.ts +111 -41
  14. package/dist/bitcoin-utils.d.ts.map +1 -1
  15. package/dist/bitcoin-utils.js +215 -156
  16. package/dist/bitcoin-utils.js.map +1 -1
  17. package/dist/bundle.js +13 -0
  18. package/dist/index.d.ts +5 -6
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +32 -12
  21. package/dist/index.js.map +1 -1
  22. package/dist/sign/sign-transaction.d.ts +9 -5
  23. package/dist/sign/sign-transaction.d.ts.map +1 -1
  24. package/dist/sign/sign-transaction.js +14 -11
  25. package/dist/sign/sign-transaction.js.map +1 -1
  26. package/dist/teleport-dao-payments.d.ts +68 -89
  27. package/dist/teleport-dao-payments.d.ts.map +1 -1
  28. package/dist/teleport-dao-payments.js +16 -4
  29. package/dist/teleport-dao-payments.js.map +1 -1
  30. package/dist/transaction-builder/bitcoin-transaction-builder.d.ts +30 -11
  31. package/dist/transaction-builder/bitcoin-transaction-builder.d.ts.map +1 -1
  32. package/dist/transaction-builder/bitcoin-transaction-builder.js +37 -9
  33. package/dist/transaction-builder/bitcoin-transaction-builder.js.map +1 -1
  34. package/dist/transaction-builder/transaction-builder.d.ts +198 -9
  35. package/dist/transaction-builder/transaction-builder.d.ts.map +1 -1
  36. package/dist/transaction-builder/transaction-builder.js +291 -38
  37. package/dist/transaction-builder/transaction-builder.js.map +1 -1
  38. package/dist/utils/networks.d.ts +5 -35
  39. package/dist/utils/networks.d.ts.map +1 -1
  40. package/dist/utils/networks.js +26 -2
  41. package/dist/utils/networks.js.map +1 -1
  42. package/dist/utils/tools.d.ts +15 -9
  43. package/dist/utils/tools.d.ts.map +1 -1
  44. package/dist/utils/tools.js +14 -11
  45. package/dist/utils/tools.js.map +1 -1
  46. package/package.json +8 -6
  47. package/src/{bitcoin-base.js → bitcoin-base.ts} +248 -219
  48. package/src/{bitcoin-interface-utils.js → bitcoin-interface-utils.ts} +59 -53
  49. package/src/{bitcoin-interface.js → bitcoin-interface.ts} +420 -350
  50. package/src/{bitcoin-utils.js → bitcoin-utils.ts} +608 -483
  51. package/src/helper/teleport-request-helper.js +179 -179
  52. package/src/index.ts +5 -0
  53. package/src/sign/sign-transaction.ts +96 -0
  54. package/src/{teleport-dao-payments.js → teleport-dao-payments.ts} +341 -280
  55. package/src/transaction-builder/bitcoin-transaction-builder.ts +61 -0
  56. package/src/transaction-builder/transaction-builder.ts +567 -0
  57. package/src/utils/{networks.js → networks.ts} +33 -31
  58. package/src/utils/{tools.js → tools.ts} +80 -72
  59. package/tsconfig.json +10 -9
  60. package/webpack.config.js +16 -0
  61. package/dist/transaction-builder/transaction-builder-common.d.ts +0 -57
  62. package/dist/transaction-builder/transaction-builder-common.d.ts.map +0 -1
  63. package/dist/transaction-builder/transaction-builder-common.js +0 -183
  64. package/dist/transaction-builder/transaction-builder-common.js.map +0 -1
  65. package/src/index.js +0 -15
  66. package/src/sign/sign-transaction.js +0 -36
  67. package/src/transaction-builder/bitcoin-transaction-builder.js +0 -37
  68. package/src/transaction-builder/transaction-builder-common.js +0 -236
  69. package/src/transaction-builder/transaction-builder.js +0 -159
@@ -0,0 +1,61 @@
1
+ import BaseTransactionBuilder from "./transaction-builder"
2
+ import { BitcoinInterface } from "../bitcoin-interface"
3
+ import * as bitcoin from "bitcoinjs-lib"
4
+
5
+ export type BitcoinConnectionInfo = {
6
+ rpc?: {
7
+ enabled?: boolean
8
+ url: string
9
+ headers?: {
10
+ [key: string]: string
11
+ }
12
+ auth?: {
13
+ username: string
14
+ password: string
15
+ }
16
+ }
17
+ api: {
18
+ enabled?: boolean
19
+ token?: string
20
+ provider: string
21
+ }
22
+ }
23
+ class BitcoinTransactionBuilder extends BaseTransactionBuilder {
24
+ btcInterface: BitcoinInterface
25
+ constructor(
26
+ connectionInfo: BitcoinConnectionInfo,
27
+ networkName: string,
28
+ network = bitcoin.networks.bitcoin,
29
+ ) {
30
+ super({
31
+ network,
32
+ testnet: networkName?.includes("_testnet"),
33
+ dustLimit: 1000,
34
+ })
35
+ this.btcInterface = new BitcoinInterface(connectionInfo, networkName)
36
+ }
37
+
38
+ async _getUtxo(userAddress: string) {
39
+ let utxos = await this.btcInterface.getAddressesUtxo([userAddress])
40
+ return utxos.map((tx) => ({
41
+ hash: tx.txId as string,
42
+ value: +tx.value,
43
+ index: +tx.index,
44
+ }))
45
+ }
46
+
47
+ async _getFeeRate(speed: "normal" | "slow" | "fast" = "normal") {
48
+ return this.btcInterface.getFeeRate(speed)
49
+ }
50
+
51
+ async _getTransactionHex(transactionId: string): Promise<string> {
52
+ return this.btcInterface.provider.getRawTransaction(transactionId)
53
+ }
54
+
55
+ async sendTx(txHex: string): Promise<string> {
56
+ let txId = await this.btcInterface.provider.sendRawTransaction(txHex)
57
+ return txId
58
+ }
59
+ }
60
+
61
+ export default BitcoinTransactionBuilder
@@ -0,0 +1,567 @@
1
+ /* eslint-disable no-underscore-dangle */
2
+ import * as bitcoin from "bitcoinjs-lib"
3
+
4
+ import { createAddressObjectByPublicKey, getAddressType } from "../bitcoin-utils"
5
+
6
+ const coinselect = require("coinselect")
7
+ const coinselectSplit = require("coinselect/split")
8
+ const coinselectAccumulative = require("coinselect/accumulative")
9
+
10
+ const TX_EMPTY_SIZE = 4 + 1 + 1 + 4
11
+ const TX_INPUT_BASE = 32 + 4 + 1 + 4
12
+ const TX_INPUT_P2PKH = 107
13
+ const TX_INPUT_P2SH_P2PKH = 50
14
+ const TX_INPUT_P2WPKH = 47
15
+ const TX_OUTPUT_BASE = 8 + 1
16
+ const TX_OUTPUT_P2PKH = 25
17
+
18
+ const componentBytes = {
19
+ bytePerInput: {
20
+ p2pkh: TX_INPUT_BASE + TX_INPUT_P2PKH,
21
+ p2wpkh: TX_INPUT_BASE + TX_INPUT_P2WPKH,
22
+ p2shp2wpkh: TX_INPUT_BASE + TX_INPUT_P2SH_P2PKH,
23
+ },
24
+ baseTxBytes: TX_EMPTY_SIZE,
25
+ bytePerOutput: TX_OUTPUT_BASE + TX_OUTPUT_P2PKH,
26
+ }
27
+
28
+ export type Utxo = {
29
+ hash: string
30
+ value: number
31
+ index: number
32
+ }
33
+ export type SignerInfo = {
34
+ address: string
35
+ publicKey: string
36
+ addressType: string
37
+ derivationPath?: string
38
+ masterFingerprint?: string
39
+ includeHex?: boolean
40
+ }
41
+ export type ExtendedUtxo = {
42
+ signerInfo: SignerInfo
43
+ hash: string
44
+ value: number
45
+ index: number
46
+ }
47
+
48
+ export type TargetAddress = {
49
+ address: string
50
+ value: number
51
+ }
52
+
53
+ export type TargetScript = {
54
+ script: Buffer
55
+ value: number
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
+ }
65
+
66
+ export type BitcoinJSInputInfo = ExtendedUtxo & {
67
+ bip32Derivation?: {
68
+ path: string
69
+ pubkey: Buffer
70
+ masterFingerprint: Buffer
71
+ }[]
72
+ nonWitnessUtxo?: Buffer
73
+ witnessUtxo?: {
74
+ script: Buffer
75
+ value: number
76
+ }
77
+ redeemScript?: Buffer
78
+ tapInternalKey?: Buffer
79
+ }
80
+
81
+ export type ExtendedUnsignedTransaction = {
82
+ unsignedTransaction: string
83
+ outputs: Target[]
84
+ inputs: {
85
+ hash: string
86
+ value: number
87
+ index: number
88
+ signerInfo: SignerInfo
89
+ }[]
90
+ fee: number
91
+ change: TargetAddress | undefined
92
+ }
93
+
94
+ class BaseBitcoinLikeTransaction {
95
+ testnet: boolean
96
+ network: bitcoin.Network
97
+ maximumNumberOfOutputsInTransaction: number
98
+ feeMin: number
99
+ dustLimit: number
100
+ // abstract
101
+ constructor({
102
+ network,
103
+ testnet,
104
+ feeMin = 0,
105
+ dustLimit,
106
+ maximumNumberOfOutputsInTransaction = 50,
107
+ }: {
108
+ network: bitcoin.Network
109
+ testnet: boolean
110
+ feeMin?: number
111
+ dustLimit?: number
112
+ maximumNumberOfOutputsInTransaction?: number
113
+ }) {
114
+ this.testnet = testnet
115
+ this.network = network
116
+ this.maximumNumberOfOutputsInTransaction = maximumNumberOfOutputsInTransaction
117
+ this.feeMin = feeMin
118
+ this.dustLimit = dustLimit || 1 * 2 * componentBytes.bytePerInput.p2pkh
119
+ }
120
+
121
+ // eslint-disable-next-line no-unused-vars, class-methods-use-this
122
+ async _getUtxo(userAddress: string): Promise<Utxo[]> {
123
+ // The child has implemented this method.
124
+ throw new Error("Do not call abstract method directly")
125
+ // return utxo
126
+ }
127
+
128
+ // eslint-disable-next-line no-unused-vars, class-methods-use-this
129
+ async _getTransactionHex(transactionId: string): Promise<string> {
130
+ // The child has implemented this method.
131
+ throw new Error("Do not call abstract method directly")
132
+ // return utxo
133
+ }
134
+
135
+ // eslint-disable-next-line no-unused-vars, class-methods-use-this
136
+ createAddressObject(input: { addressType: string; publicKey: Buffer }) {
137
+ return createAddressObjectByPublicKey(input, this.network)
138
+ }
139
+
140
+ // methods
141
+ validateAddress(address: string) {
142
+ try {
143
+ getAddressType(address)
144
+ return true
145
+ } catch (error) {
146
+ return false
147
+ }
148
+ }
149
+
150
+ getOpReturnTarget(dataHex: string) {
151
+ if (!(dataHex.length > 0)) throw new Error("invalid data in hex")
152
+ const embed = bitcoin.payments.embed({
153
+ data: [Buffer.from(dataHex, "hex")],
154
+ network: this.network,
155
+ })
156
+ return {
157
+ script: embed.output!,
158
+ value: 0,
159
+ }
160
+ }
161
+
162
+ async getExtendedUtxo(signerInfo: SignerInfo) {
163
+ let utxo = await this._getUtxo(signerInfo.address)
164
+ const extendedUtxo = utxo.map((input) => ({
165
+ ...input,
166
+ signerInfo,
167
+ }))
168
+ if (!extendedUtxo || extendedUtxo.length === 0) {
169
+ throw new Error("no utxo found")
170
+ }
171
+ return extendedUtxo
172
+ }
173
+
174
+ static helperHandleInputsAndOutputs({
175
+ targets,
176
+ extendedUtxo,
177
+ feeRate,
178
+ changeObject,
179
+ selectType = "normal", // "accumulative" | "normal" | "full"
180
+ }: {
181
+ extendedUtxo: ExtendedUtxo[]
182
+ targets: Target[]
183
+ feeRate: number
184
+ changeObject?: {
185
+ address: string
186
+ publicKey?: string
187
+ addressType?: string
188
+ derivationPath?: string
189
+ masterFingerprint?: string
190
+ }
191
+ selectType?: "normal" | "accumulative" | "full"
192
+ }) {
193
+ let selectResponse
194
+ switch (selectType) {
195
+ case "normal":
196
+ selectResponse = coinselect(extendedUtxo, targets, Math.round(feeRate))
197
+
198
+ break
199
+ case "accumulative":
200
+ selectResponse = coinselectAccumulative(extendedUtxo, targets, Math.round(feeRate))
201
+ break
202
+ case "full":
203
+ if (!(targets[0] as TargetAddress).address) {
204
+ throw new Error()
205
+ }
206
+ selectResponse = coinselectSplit(
207
+ extendedUtxo,
208
+ [{ address: (targets[0] as TargetAddress).address }],
209
+ Math.round(feeRate),
210
+ )
211
+ break
212
+
213
+ default:
214
+ break
215
+ }
216
+ let {
217
+ inputs,
218
+ outputs,
219
+ fee,
220
+ }: {
221
+ inputs?: ExtendedUtxo[]
222
+ outputs?: {
223
+ script?: Buffer
224
+ address?: Buffer
225
+ value: number
226
+ }[]
227
+ fee: number
228
+ } = selectResponse
229
+
230
+ if (!inputs || !outputs) {
231
+ throw new Error("not enough balance")
232
+ }
233
+ let changeIndex = outputs.findIndex((x) => !x?.address && !x.script && (x.value || 0) > 0)
234
+ let change: ChangeTarget | undefined
235
+ if (changeIndex >= 0) {
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
+ }
254
+ }
255
+ outputs.splice(changeIndex, 1)
256
+ }
257
+
258
+ return {
259
+ inputs,
260
+ fee,
261
+ outputs: outputs as Target[],
262
+ change,
263
+ }
264
+ }
265
+
266
+ async filterAndConvertTxDataToStandardFormat({
267
+ extendedUtxo,
268
+ targets,
269
+ changeObject,
270
+ feeRate,
271
+ selectType,
272
+ }: {
273
+ extendedUtxo: ExtendedUtxo[]
274
+ targets: Target[]
275
+ feeRate: number
276
+ changeObject?: {
277
+ address: string
278
+ publicKey?: string
279
+ addressType?: string
280
+ derivationPath?: string
281
+ masterFingerprint?: string
282
+ }
283
+ selectType?: "normal" | "accumulative" | "full"
284
+ }) {
285
+ let {
286
+ inputs: filteredInputs,
287
+ outputs,
288
+ change,
289
+ fee,
290
+ } = BaseBitcoinLikeTransaction.helperHandleInputsAndOutputs({
291
+ targets,
292
+ extendedUtxo,
293
+ feeRate,
294
+ changeObject,
295
+ selectType,
296
+ })
297
+
298
+ let inputs = await this.convertExtendedUtxoToInputs(filteredInputs)
299
+
300
+ return {
301
+ inputs,
302
+ outputs,
303
+ change,
304
+ fee,
305
+ feeRate,
306
+ }
307
+ }
308
+
309
+ // ?note : we can extend this class and change this method for network other than bitcoin
310
+ async convertExtendedUtxoToInputs(baseInputs: ExtendedUtxo[] = []) {
311
+ let inputs: (BitcoinJSInputInfo & {
312
+ signerInfo: SignerInfo
313
+ })[] = baseInputs
314
+ let transactionId: string | null = null
315
+ let transactionHex: string | null = null
316
+ for (let i in inputs) {
317
+ let { address, publicKey, derivationPath, masterFingerprint, addressType } =
318
+ inputs[i].signerInfo
319
+ // todo : support without publicKey
320
+ let addressObject = this.createAddressObject({
321
+ publicKey: Buffer.from(publicKey, "hex"),
322
+ addressType,
323
+ })
324
+ if (derivationPath && masterFingerprint && addressObject.pubkey) {
325
+ inputs[i].bip32Derivation = [
326
+ {
327
+ path: derivationPath,
328
+ pubkey: addressObject.pubkey,
329
+ masterFingerprint: Buffer.from(masterFingerprint, "hex"),
330
+ },
331
+ ]
332
+ }
333
+ if (addressType === "p2pkh") {
334
+ // add p2pkh data
335
+ if (transactionHex && transactionId === inputs[i].hash) {
336
+ inputs[i].nonWitnessUtxo = Buffer.from(transactionHex, "hex")
337
+ } else {
338
+ transactionHex = await this._getTransactionHex(inputs[i].hash)
339
+ transactionId = inputs[i].hash
340
+ inputs[i].nonWitnessUtxo = Buffer.from(transactionHex, "hex")
341
+ }
342
+ } else if (addressType === "p2wpkh") {
343
+ // add p2wpkh data
344
+ if (!addressObject.output) throw new Error("invalid signer info")
345
+ inputs[i].witnessUtxo = {
346
+ script: addressObject.output,
347
+ value: inputs[i].value,
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
+ }
359
+ } else if (addressType === "p2sh-p2wpkh") {
360
+ // add p2sh-p2wpkh data
361
+ if (!addressObject.output) throw new Error("invalid signer info")
362
+ inputs[i].witnessUtxo = {
363
+ script: addressObject.output,
364
+ value: inputs[i].value,
365
+ }
366
+ if (!addressObject?.redeem?.output) throw new Error("invalid signer info for p2sh address")
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
+ }
378
+ } else if (addressType === "p2tr") {
379
+ if (!addressObject.output) throw new Error("invalid signer info")
380
+ inputs[i].witnessUtxo = {
381
+ script: addressObject.output,
382
+ value: inputs[i].value,
383
+ }
384
+ if (!addressObject.pubkey) throw new Error("invalid signer info for p2tr address (pubkey)")
385
+ // todo: fix after update to p2tr
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
+ }
397
+ }
398
+ }
399
+
400
+ return inputs
401
+ }
402
+
403
+ // ?note : we can extend this class and change this method for network other than bitcoin
404
+ createUnsignedTransaction({
405
+ inputs,
406
+ outputs,
407
+ change,
408
+ fee, // not used in this section - just returned
409
+ feeRate,
410
+ }: {
411
+ inputs: BitcoinJSInputInfo[]
412
+ outputs: Target[]
413
+ change?: ChangeTarget
414
+ fee: number
415
+ feeRate: number
416
+ }) {
417
+ const { network } = this
418
+ const newPsbt = new bitcoin.Psbt({ network })
419
+ newPsbt.setMaximumFeeRate(+(feeRate + feeRate / 100).toFixed())
420
+ // add input
421
+ for (const input of inputs) {
422
+ let { addressType } = input.signerInfo
423
+ switch (addressType) {
424
+ case "p2pkh": {
425
+ let i = {
426
+ hash: input.hash,
427
+ index: Number(input.index),
428
+ nonWitnessUtxo: input.nonWitnessUtxo,
429
+ sequence: 0xffffffff - 1,
430
+ bip32Derivation: input.bip32Derivation,
431
+ }
432
+ if (!i.bip32Derivation) delete i.bip32Derivation
433
+ newPsbt.addInput(i)
434
+ break
435
+ }
436
+ case "p2wpkh": {
437
+ let i = {
438
+ hash: input.hash,
439
+ index: Number(input.index),
440
+ witnessUtxo: input.witnessUtxo,
441
+ // we dont need nonWitnessUtxo. bud some application force nonWitnessUtxo
442
+ nonWitnessUtxo: input.nonWitnessUtxo,
443
+ sequence: 0xffffffff - 1,
444
+ bip32Derivation: input.bip32Derivation,
445
+ }
446
+ if (!i.bip32Derivation) delete i.bip32Derivation
447
+ if (!i.nonWitnessUtxo) delete i.nonWitnessUtxo
448
+ newPsbt.addInput(i)
449
+ break
450
+ }
451
+ case "p2sh-p2wpkh": {
452
+ let i = {
453
+ hash: input.hash,
454
+ index: Number(input.index),
455
+ witnessUtxo: input.witnessUtxo,
456
+ // we dont need nonWitnessUtxo. bud some application force nonWitnessUtxo
457
+ nonWitnessUtxo: input.nonWitnessUtxo,
458
+ redeemScript: input.redeemScript,
459
+ sequence: 0xffffffff - 1,
460
+ bip32Derivation: input.bip32Derivation,
461
+ }
462
+ if (!i.bip32Derivation) delete i.bip32Derivation
463
+ if (!i.nonWitnessUtxo) delete i.nonWitnessUtxo
464
+ newPsbt.addInput(i)
465
+ break
466
+ }
467
+ case "p2tr": {
468
+ let i = {
469
+ hash: input.hash,
470
+ index: Number(input.index),
471
+ witnessUtxo: input.witnessUtxo,
472
+ // we dont need nonWitnessUtxo. bud some application force nonWitnessUtxo
473
+ nonWitnessUtxo: input.nonWitnessUtxo,
474
+ tapInternalKey: input.tapInternalKey,
475
+ sequence: 0xffffffff - 1,
476
+ bip32Derivation: input.bip32Derivation,
477
+ }
478
+ if (!i.bip32Derivation) delete i.bip32Derivation
479
+ if (!i.nonWitnessUtxo) delete i.nonWitnessUtxo
480
+ newPsbt.addInput(i)
481
+ break
482
+ }
483
+ default:
484
+ throw new Error("address type is incorrect")
485
+ }
486
+ }
487
+
488
+ // add outputs
489
+ for (const target of outputs) {
490
+ newPsbt.addOutput({ ...target })
491
+ }
492
+
493
+ // add changeAddress
494
+ if (change && Object.keys(change).length !== 0) {
495
+ newPsbt.addOutput(change)
496
+ }
497
+
498
+ // check created outputs with targets
499
+ if (change && Object.keys(change).length !== 0) {
500
+ if (newPsbt.txOutputs[outputs.length].address !== change.address) {
501
+ throw new Error("error change address")
502
+ }
503
+ // if (newPsbt.txOutputs[outputs.length].value !== change.value) {
504
+ // throw new Error("error change value")
505
+ // }
506
+ }
507
+
508
+ const unsignedPsbtBaseText = newPsbt.toBase64()
509
+ return {
510
+ unsignedTransaction: unsignedPsbtBaseText,
511
+ outputs,
512
+ inputs: inputs.map((utx) => ({
513
+ hash: utx.hash,
514
+ value: Number(utx.value),
515
+ index: utx.index,
516
+ signerInfo: utx.signerInfo,
517
+ })),
518
+ fee,
519
+ change,
520
+ }
521
+ }
522
+
523
+ async processUnsignedTransaction({
524
+ extendedUtxo,
525
+ targets = [],
526
+ changeAddress = undefined,
527
+ fullAmount = false,
528
+ feeRate,
529
+ selfTransaction = false,
530
+ selectType = "normal",
531
+ }: {
532
+ extendedUtxo: ExtendedUtxo[]
533
+ targets: Target[]
534
+ feeRate: number
535
+
536
+ changeAddress?: string | SignerInfo
537
+ fullAmount?: boolean
538
+ selfTransaction?: boolean
539
+ selectType?: "normal" | "accumulative" | "full"
540
+ }) {
541
+ if (!selfTransaction && targets.length === 0) throw new Error("no target")
542
+ let changeObject =
543
+ typeof changeAddress === "string"
544
+ ? {
545
+ address: changeAddress,
546
+ }
547
+ : changeAddress
548
+ const { inputs, outputs, change, fee } = await this.filterAndConvertTxDataToStandardFormat({
549
+ extendedUtxo,
550
+ targets,
551
+ changeObject,
552
+ feeRate,
553
+ selectType: fullAmount ? "full" : selectType,
554
+ })
555
+ let unsignedTransaction = this.createUnsignedTransaction({
556
+ inputs,
557
+ outputs,
558
+ change,
559
+ fee,
560
+ feeRate,
561
+ })
562
+
563
+ return unsignedTransaction
564
+ }
565
+ }
566
+
567
+ export default BaseBitcoinLikeTransaction
@@ -1,31 +1,33 @@
1
- const bitcoinLib = require("bitcoinjs-lib")
2
-
3
- const networks = {
4
- bitcoin: bitcoinLib.networks.bitcoin,
5
- bitcoin_testnet: bitcoinLib.networks.testnet,
6
-
7
- litecoin: {
8
- messagePrefix: "\x19Litecoin Signed Message:\n",
9
- bech32: "ltc",
10
- bip32: {
11
- public: 0x0488b21e,
12
- private: 0x0488ade4,
13
- },
14
- pubKeyHash: 0x30,
15
- scriptHash: 0x32,
16
- wif: 0xb0,
17
- },
18
- litecoin_testnet: {
19
- messagePrefix: "\x18Litecoin Signed Message:\n",
20
- bech32: "tltc",
21
- bip32: {
22
- public: 0x043587cf,
23
- private: 0x04358394,
24
- },
25
- pubKeyHash: 0x6f,
26
- scriptHash: 0x3a, // old 0xc4 -> 2 deprecated
27
- wif: 0xef,
28
- },
29
- }
30
-
31
- module.exports = networks
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