@teleportdao/bitcoin 2.0.4 → 2.0.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.
Files changed (78) 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 +101 -101
  4. package/dist/bitcoin-interface-teleswap.d.ts.map +1 -1
  5. package/dist/bitcoin-interface-teleswap.js +176 -165
  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 +28 -28
  10. package/dist/bitcoin-interface-wallet.js +125 -125
  11. package/dist/bitcoin-interface.d.ts +66 -66
  12. package/dist/bitcoin-interface.js +119 -119
  13. package/dist/bitcoin-utils.d.ts +96 -96
  14. package/dist/bitcoin-utils.js +514 -514
  15. package/dist/bitcoin-wallet-base.d.ts +111 -111
  16. package/dist/bitcoin-wallet-base.js +258 -258
  17. package/dist/helper/brc20-helper.d.ts +42 -42
  18. package/dist/helper/brc20-helper.js +127 -127
  19. package/dist/helper/index.d.ts +3 -3
  20. package/dist/helper/index.js +29 -29
  21. package/dist/helper/ordinal-helper.d.ts +12 -12
  22. package/dist/helper/ordinal-helper.js +129 -129
  23. package/dist/helper/teleswap-helper.d.ts +95 -95
  24. package/dist/helper/teleswap-helper.js +186 -186
  25. package/dist/index.d.ts +12 -12
  26. package/dist/index.js +41 -41
  27. package/dist/ordinal-wallet.d.ts +495 -495
  28. package/dist/ordinal-wallet.js +386 -386
  29. package/dist/sign/index.d.ts +1 -1
  30. package/dist/sign/index.js +8 -8
  31. package/dist/sign/sign-transaction.d.ts +12 -12
  32. package/dist/sign/sign-transaction.js +82 -82
  33. package/dist/teleswap-wallet.d.ts +45 -45
  34. package/dist/teleswap-wallet.js +68 -68
  35. package/dist/transaction-builder/bitcoin-transaction-builder.d.ts +9 -9
  36. package/dist/transaction-builder/bitcoin-transaction-builder.js +54 -54
  37. package/dist/transaction-builder/index.d.ts +3 -3
  38. package/dist/transaction-builder/index.js +19 -19
  39. package/dist/transaction-builder/ordinal-transaction-builder.d.ts +63 -63
  40. package/dist/transaction-builder/ordinal-transaction-builder.js +125 -125
  41. package/dist/transaction-builder/transaction-builder.d.ts +223 -223
  42. package/dist/transaction-builder/transaction-builder.js +447 -447
  43. package/dist/type.d.ts +61 -61
  44. package/dist/type.js +2 -2
  45. package/dist/utils/networks.d.ts +5 -5
  46. package/dist/utils/networks.js +53 -53
  47. package/dist/utils/tools.d.ts +18 -18
  48. package/dist/utils/tools.js +74 -74
  49. package/package.json +4 -4
  50. package/src/bitcoin-interface-ordinal.ts +185 -185
  51. package/src/bitcoin-interface-teleswap.ts +251 -237
  52. package/src/bitcoin-interface-utils.ts +60 -60
  53. package/src/bitcoin-interface-wallet.ts +114 -114
  54. package/src/bitcoin-interface.ts +156 -156
  55. package/src/bitcoin-utils.ts +591 -591
  56. package/src/bitcoin-wallet-base.ts +344 -344
  57. package/src/helper/brc20-helper.ts +179 -179
  58. package/src/helper/ordinal-helper.ts +118 -118
  59. package/src/index.ts +15 -15
  60. package/src/ordinal-wallet.ts +659 -659
  61. package/src/sign/index.ts +1 -1
  62. package/src/sign/sign-transaction.ts +108 -108
  63. package/src/teleswap-wallet.ts +133 -133
  64. package/src/transaction-builder/bitcoin-transaction-builder.ts +26 -26
  65. package/src/transaction-builder/index.ts +3 -3
  66. package/src/transaction-builder/ordinal-transaction-builder.ts +139 -139
  67. package/src/transaction-builder/transaction-builder.ts +690 -690
  68. package/src/type.ts +74 -74
  69. package/src/utils/networks.ts +33 -33
  70. package/src/utils/tools.ts +92 -92
  71. package/tsconfig.json +9 -9
  72. package/webpack.config.js +16 -16
  73. package/.tmp/block-parser.ts +0 -58
  74. package/.tmp/check.ts +0 -101
  75. package/.tmp/ordinal-helper.ts +0 -133
  76. package/.tmp/ordinal.ts +0 -25
  77. package/.tmp/psbt/sign-transaction.ts +0 -121
  78. package/.tmp/rbf.ts +0 -45
@@ -1,448 +1,448 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
- return new (P || (P = Promise))(function (resolve, reject) {
28
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
- step((generator = generator.apply(thisArg, _arguments || [])).next());
32
- });
33
- };
34
- Object.defineProperty(exports, "__esModule", { value: true });
35
- exports.BaseTransactionBuilder = exports.DUST = exports.componentBytes = void 0;
36
- const bitcoin = __importStar(require("bitcoinjs-lib"));
37
- const bitcoin_utils_1 = require("../bitcoin-utils");
38
- const coinselect = require("coinselect");
39
- const coinselectSplit = require("coinselect/split");
40
- const coinselectAccumulative = require("coinselect/accumulative");
41
- exports.componentBytes = {
42
- bytePerInput: {
43
- p2pkh: 148,
44
- p2wpkh: 68,
45
- "p2sh-p2wpkh": 91,
46
- p2tr: 58,
47
- default: 100,
48
- },
49
- baseTxBytes: 10 + 5,
50
- bytePerOutput: {
51
- p2pkh: 34,
52
- p2wpkh: 31,
53
- p2sh: 32,
54
- p2tr: 43,
55
- default: 35,
56
- max: 45,
57
- },
58
- scriptExtraBytes: {
59
- lessThan255: 12,
60
- moreThan255: 15,
61
- },
62
- };
63
- exports.DUST = 1000;
64
- function coinSelectInOrder(utxos, outputs, feeRate) {
65
- let response = coinselectAccumulative(utxos, outputs, 1);
66
- return Object.assign(Object.assign({}, response), { fee: +(+response.fee * feeRate).toFixed() });
67
- }
68
- class BaseTransactionBuilder {
69
- constructor({ network, testnet, feeMin = 0, dustLimit, maximumNumberOfOutputsInTransaction = 50, }) {
70
- this.testnet = testnet;
71
- this.network = network;
72
- this.maximumNumberOfOutputsInTransaction = maximumNumberOfOutputsInTransaction;
73
- this.feeMin = feeMin;
74
- this.dustLimit = dustLimit || 1 * 2 * exports.componentBytes.bytePerInput.p2pkh;
75
- }
76
- _getTransactionHex(transactionId) {
77
- return __awaiter(this, void 0, void 0, function* () {
78
- throw new Error("Do not call abstract method directly");
79
- });
80
- }
81
- createAddressObject(input) {
82
- return (0, bitcoin_utils_1.createAddressObjectByPublicKey)(input, this.network);
83
- }
84
- validateAddress(address) {
85
- try {
86
- (0, bitcoin_utils_1.getAddressType)(address, this.network);
87
- return true;
88
- }
89
- catch (error) {
90
- return false;
91
- }
92
- }
93
- getOpReturnTarget(dataHex) {
94
- if (!(dataHex.length > 0))
95
- throw new Error("invalid data in hex");
96
- const embed = bitcoin.payments.embed({
97
- data: [Buffer.from(dataHex, "hex")],
98
- network: this.network,
99
- });
100
- return {
101
- script: embed.output,
102
- value: 0,
103
- };
104
- }
105
- calculateTxSize(inputTypes, outputs, changeAddressType = "default") {
106
- const inputsSizes = inputTypes.map((addressType) => exports.componentBytes.bytePerInput[addressType]);
107
- const outputSizes = outputs.map((outP) => {
108
- if (outP.address) {
109
- let addressType = "default";
110
- try {
111
- addressType = (0, bitcoin_utils_1.getAddressType)(outP.address, this.network);
112
- }
113
- catch (_a) {
114
- addressType = "default";
115
- }
116
- return exports.componentBytes.bytePerOutput[addressType];
117
- }
118
- if (outP.script) {
119
- if (outP.script.byteLength < 255) {
120
- return outP.script.byteLength + exports.componentBytes.scriptExtraBytes.lessThan255;
121
- }
122
- return outP.script.byteLength + exports.componentBytes.scriptExtraBytes.moreThan255;
123
- }
124
- return exports.componentBytes.bytePerOutput[changeAddressType];
125
- });
126
- const txSize = exports.componentBytes.baseTxBytes +
127
- inputsSizes.reduce((a, c) => a + c, 0) +
128
- outputSizes.reduce((a, c) => a + c, 0);
129
- return txSize;
130
- }
131
- helperHandleInputsAndOutputs({ targets, extendedUtxo, feeRate, changeObject, selectType = "normal", }) {
132
- const filteredUtxo = extendedUtxo.filter((u) => u.value >
133
- +feeRate *
134
- exports.componentBytes.bytePerInput[u.signerInfo.addressType]);
135
- let selectResponse;
136
- switch (selectType) {
137
- case "normal":
138
- selectResponse = coinselect(filteredUtxo, targets, Math.round(feeRate));
139
- break;
140
- case "accumulative":
141
- selectResponse = coinselectAccumulative(filteredUtxo, targets, Math.round(feeRate));
142
- break;
143
- case "inOrder":
144
- selectResponse = coinSelectInOrder(filteredUtxo, targets, Math.round(feeRate));
145
- break;
146
- case "full":
147
- if (!targets[0].address) {
148
- throw new Error();
149
- }
150
- selectResponse = coinselectSplit(filteredUtxo, [{ address: targets[0].address }], Math.round(feeRate));
151
- break;
152
- default:
153
- break;
154
- }
155
- let { inputs, outputs, fee, } = selectResponse;
156
- if (!inputs || !outputs) {
157
- inputs = filteredUtxo;
158
- outputs = targets;
159
- fee = inputs.reduce((a, b) => a + b.value, 0) - outputs.reduce((a, b) => a + b.value, 0);
160
- }
161
- let changeAddressType = "default";
162
- try {
163
- changeAddressType = (0, bitcoin_utils_1.getAddressType)((changeObject === null || changeObject === void 0 ? void 0 : changeObject.address) || "", this.network);
164
- }
165
- catch (_a) {
166
- changeAddressType = "default";
167
- }
168
- const txSize = this.calculateTxSize(inputs.map((i) => i.signerInfo.addressType), outputs, changeAddressType) + exports.componentBytes.bytePerOutput.default;
169
- let txFee = Math.round(txSize * feeRate);
170
- if (Math.round(feeRate) === 1) {
171
- txFee = Math.round(txFee + txFee * 0.1);
172
- }
173
- if (inputs.reduce((a, b) => a + b.value, 0) -
174
- outputs.filter((o) => o.address || o.script).reduce((a, b) => a + b.value, 0) -
175
- txFee <
176
- 0) {
177
- let spendableBalance = inputs.reduce((a, b) => a + b.value, 0);
178
- let totalOutputAmount = outputs
179
- .filter((o) => o.address || o.script)
180
- .reduce((a, b) => a + b.value, 0);
181
- let need = spendableBalance - totalOutputAmount - txFee;
182
- throw new Error(`not enough balance. details: ${JSON.stringify({ spendableBalance, totalOutputAmount, txFee, need }, null, 2)}`);
183
- }
184
- let diff = fee - txFee;
185
- let changeIndex = outputs.findIndex((x) => !(x === null || x === void 0 ? void 0 : x.address) && !x.script && (x.value || 0) > 0);
186
- let change;
187
- if (changeIndex >= 0 || diff > exports.DUST) {
188
- if (changeIndex >= 0) {
189
- diff = diff + exports.componentBytes.bytePerOutput.default * Math.round(feeRate);
190
- }
191
- if (diff < 0) {
192
- diff = 0;
193
- }
194
- if (selectType === "full") {
195
- outputs[0].value = outputs[0].value + diff;
196
- fee = fee - diff;
197
- }
198
- else {
199
- if (!changeObject)
200
- throw new Error("change not exist");
201
- change = {
202
- address: changeObject.address,
203
- value: changeIndex >= 0 ? outputs[changeIndex].value + diff : diff,
204
- };
205
- fee = fee - diff;
206
- }
207
- if (changeIndex >= 0) {
208
- outputs.splice(changeIndex, 1);
209
- }
210
- }
211
- return {
212
- inputs,
213
- fee,
214
- outputs: outputs,
215
- change,
216
- };
217
- }
218
- filterAndConvertTxDataToStandardFormat({ extendedUtxo, targets, changeObject, feeRate, selectType, }) {
219
- return __awaiter(this, void 0, void 0, function* () {
220
- let { inputs: filteredInputs, outputs, change, fee, } = this.helperHandleInputsAndOutputs({
221
- targets,
222
- extendedUtxo,
223
- feeRate,
224
- changeObject,
225
- selectType,
226
- });
227
- let inputs = yield this.convertExtendedUtxoToInputs(filteredInputs);
228
- return {
229
- inputs,
230
- outputs,
231
- change,
232
- fee,
233
- feeRate,
234
- };
235
- });
236
- }
237
- convertExtendedUtxoToInputs(baseInputs = []) {
238
- var _a;
239
- return __awaiter(this, void 0, void 0, function* () {
240
- let inputs = baseInputs;
241
- const transactionHex = {};
242
- for (let i in inputs) {
243
- let { address, publicKey, derivationPath, masterFingerprint, addressType } = inputs[i].signerInfo;
244
- let addressObject = this.createAddressObject({
245
- publicKey: Buffer.from(publicKey, "hex"),
246
- addressType,
247
- });
248
- if (derivationPath && masterFingerprint && addressObject.pubkey) {
249
- inputs[i].bip32Derivation = [
250
- {
251
- path: derivationPath,
252
- pubkey: addressObject.pubkey,
253
- masterFingerprint: Buffer.from(masterFingerprint, "hex"),
254
- },
255
- ];
256
- }
257
- if (addressType === "p2pkh") {
258
- const txHex = transactionHex[inputs[i].hash] || (yield this._getTransactionHex(inputs[i].hash));
259
- transactionHex[inputs[i].hash] = txHex;
260
- inputs[i].nonWitnessUtxo = Buffer.from(txHex, "hex");
261
- }
262
- else if (addressType === "p2wpkh") {
263
- if (!addressObject.output)
264
- throw new Error("invalid signer info");
265
- inputs[i].witnessUtxo = {
266
- script: addressObject.output,
267
- value: inputs[i].value,
268
- };
269
- if (inputs[i].signerInfo.includeHex) {
270
- const txHex = transactionHex[inputs[i].hash] || (yield this._getTransactionHex(inputs[i].hash));
271
- transactionHex[inputs[i].hash] = txHex;
272
- inputs[i].nonWitnessUtxo = Buffer.from(txHex, "hex");
273
- }
274
- }
275
- else if (addressType === "p2sh-p2wpkh") {
276
- if (!addressObject.output)
277
- throw new Error("invalid signer info");
278
- inputs[i].witnessUtxo = {
279
- script: addressObject.output,
280
- value: inputs[i].value,
281
- };
282
- if (!((_a = addressObject === null || addressObject === void 0 ? void 0 : addressObject.redeem) === null || _a === void 0 ? void 0 : _a.output))
283
- throw new Error("invalid signer info for p2sh address");
284
- inputs[i].redeemScript = addressObject.redeem.output;
285
- if (inputs[i].signerInfo.includeHex) {
286
- const txHex = transactionHex[inputs[i].hash] || (yield this._getTransactionHex(inputs[i].hash));
287
- transactionHex[inputs[i].hash] = txHex;
288
- inputs[i].nonWitnessUtxo = Buffer.from(txHex, "hex");
289
- }
290
- }
291
- else if (addressType === "p2tr") {
292
- if (!addressObject.output)
293
- throw new Error("invalid signer info");
294
- inputs[i].witnessUtxo = {
295
- script: addressObject.output,
296
- value: inputs[i].value,
297
- };
298
- if (!addressObject.pubkey)
299
- throw new Error("invalid signer info for p2tr address (pubkey)");
300
- inputs[i].tapInternalKey = addressObject.internalPubkey;
301
- if (inputs[i].signerInfo.includeHex) {
302
- const txHex = transactionHex[inputs[i].hash] || (yield this._getTransactionHex(inputs[i].hash));
303
- transactionHex[inputs[i].hash] = txHex;
304
- inputs[i].nonWitnessUtxo = Buffer.from(txHex, "hex");
305
- }
306
- }
307
- }
308
- return inputs;
309
- });
310
- }
311
- createUnsignedTransaction({ inputs, outputs, change, fee, feeRate, }) {
312
- const sequence = 0xffffffff - 2;
313
- const { network } = this;
314
- const newPsbt = new bitcoin.Psbt({ network });
315
- newPsbt.setMaximumFeeRate(+(feeRate + feeRate / 100).toFixed());
316
- for (const input of inputs) {
317
- let { addressType } = input.signerInfo;
318
- switch (addressType) {
319
- case "p2pkh": {
320
- let i = {
321
- hash: input.hash,
322
- index: Number(input.index),
323
- nonWitnessUtxo: input.nonWitnessUtxo,
324
- sequence,
325
- bip32Derivation: input.bip32Derivation,
326
- };
327
- if (!i.bip32Derivation)
328
- delete i.bip32Derivation;
329
- newPsbt.addInput(i);
330
- break;
331
- }
332
- case "p2wpkh": {
333
- let i = {
334
- hash: input.hash,
335
- index: Number(input.index),
336
- witnessUtxo: input.witnessUtxo,
337
- nonWitnessUtxo: input.nonWitnessUtxo,
338
- sequence,
339
- bip32Derivation: input.bip32Derivation,
340
- };
341
- if (!i.bip32Derivation)
342
- delete i.bip32Derivation;
343
- if (!i.nonWitnessUtxo)
344
- delete i.nonWitnessUtxo;
345
- newPsbt.addInput(i);
346
- break;
347
- }
348
- case "p2sh-p2wpkh": {
349
- let i = {
350
- hash: input.hash,
351
- index: Number(input.index),
352
- witnessUtxo: input.witnessUtxo,
353
- nonWitnessUtxo: input.nonWitnessUtxo,
354
- redeemScript: input.redeemScript,
355
- sequence,
356
- bip32Derivation: input.bip32Derivation,
357
- };
358
- if (!i.bip32Derivation)
359
- delete i.bip32Derivation;
360
- if (!i.nonWitnessUtxo)
361
- delete i.nonWitnessUtxo;
362
- newPsbt.addInput(i);
363
- break;
364
- }
365
- case "p2tr": {
366
- let i = {
367
- hash: input.hash,
368
- index: Number(input.index),
369
- witnessUtxo: input.witnessUtxo,
370
- nonWitnessUtxo: input.nonWitnessUtxo,
371
- tapInternalKey: input.tapInternalKey,
372
- sequence,
373
- bip32Derivation: input.bip32Derivation,
374
- };
375
- if (!i.bip32Derivation)
376
- delete i.bip32Derivation;
377
- if (!i.nonWitnessUtxo)
378
- delete i.nonWitnessUtxo;
379
- newPsbt.addInput(i);
380
- break;
381
- }
382
- default:
383
- throw new Error("address type is incorrect");
384
- }
385
- }
386
- for (const target of outputs) {
387
- newPsbt.addOutput(target);
388
- }
389
- if (change && Object.keys(change).length !== 0) {
390
- newPsbt.addOutput(change);
391
- }
392
- if (change && Object.keys(change).length !== 0) {
393
- if (newPsbt.txOutputs[outputs.length].address !== change.address) {
394
- throw new Error("error change address");
395
- }
396
- }
397
- const unsignedPsbtBaseText = newPsbt.toBase64();
398
- const safeAddressTypeForPossibleTxId = ["p2wpkh", "p2tr"];
399
- const isPossibleTxId = inputs.reduce((a, b) => a && safeAddressTypeForPossibleTxId.includes(b.signerInfo.addressType), true);
400
- return {
401
- unsignedTransaction: unsignedPsbtBaseText,
402
- outputs,
403
- inputs: inputs.map((utx) => ({
404
- hash: utx.hash,
405
- value: Number(utx.value),
406
- index: utx.index,
407
- signerInfo: utx.signerInfo,
408
- })),
409
- fee,
410
- change,
411
- possibleTxId: isPossibleTxId ? this.getUnsignedPsbtTxId(unsignedPsbtBaseText) : undefined,
412
- };
413
- }
414
- processUnsignedTransaction({ extendedUtxo, targets = [], changeAddress = undefined, fullAmount = false, feeRate, selectType = "normal", }) {
415
- return __awaiter(this, void 0, void 0, function* () {
416
- if (!changeAddress && targets.length === 0)
417
- throw new Error("no target");
418
- let changeObject = typeof changeAddress === "string"
419
- ? {
420
- address: changeAddress,
421
- }
422
- : changeAddress;
423
- const { inputs, outputs, change, fee } = yield this.filterAndConvertTxDataToStandardFormat({
424
- extendedUtxo,
425
- targets,
426
- changeObject,
427
- feeRate,
428
- selectType: fullAmount ? "full" : selectType,
429
- });
430
- let unsignedTransaction = this.createUnsignedTransaction({
431
- inputs,
432
- outputs,
433
- change,
434
- fee,
435
- feeRate,
436
- });
437
- return unsignedTransaction;
438
- });
439
- }
440
- getUnsignedPsbtTxId(unsignedPsbt) {
441
- let psbt = bitcoin.Psbt.fromBase64(unsignedPsbt, {
442
- network: this.network,
443
- });
444
- return psbt.__CACHE.__TX.getId();
445
- }
446
- }
447
- exports.BaseTransactionBuilder = BaseTransactionBuilder;
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ exports.BaseTransactionBuilder = exports.DUST = exports.componentBytes = void 0;
36
+ const bitcoin = __importStar(require("bitcoinjs-lib"));
37
+ const bitcoin_utils_1 = require("../bitcoin-utils");
38
+ const coinselect = require("coinselect");
39
+ const coinselectSplit = require("coinselect/split");
40
+ const coinselectAccumulative = require("coinselect/accumulative");
41
+ exports.componentBytes = {
42
+ bytePerInput: {
43
+ p2pkh: 148,
44
+ p2wpkh: 68,
45
+ "p2sh-p2wpkh": 91,
46
+ p2tr: 58,
47
+ default: 100,
48
+ },
49
+ baseTxBytes: 10 + 5,
50
+ bytePerOutput: {
51
+ p2pkh: 34,
52
+ p2wpkh: 31,
53
+ p2sh: 32,
54
+ p2tr: 43,
55
+ default: 35,
56
+ max: 45,
57
+ },
58
+ scriptExtraBytes: {
59
+ lessThan255: 12,
60
+ moreThan255: 15,
61
+ },
62
+ };
63
+ exports.DUST = 1000;
64
+ function coinSelectInOrder(utxos, outputs, feeRate) {
65
+ let response = coinselectAccumulative(utxos, outputs, 1);
66
+ return Object.assign(Object.assign({}, response), { fee: +(+response.fee * feeRate).toFixed() });
67
+ }
68
+ class BaseTransactionBuilder {
69
+ constructor({ network, testnet, feeMin = 0, dustLimit, maximumNumberOfOutputsInTransaction = 50, }) {
70
+ this.testnet = testnet;
71
+ this.network = network;
72
+ this.maximumNumberOfOutputsInTransaction = maximumNumberOfOutputsInTransaction;
73
+ this.feeMin = feeMin;
74
+ this.dustLimit = dustLimit || 1 * 2 * exports.componentBytes.bytePerInput.p2pkh;
75
+ }
76
+ _getTransactionHex(transactionId) {
77
+ return __awaiter(this, void 0, void 0, function* () {
78
+ throw new Error("Do not call abstract method directly");
79
+ });
80
+ }
81
+ createAddressObject(input) {
82
+ return (0, bitcoin_utils_1.createAddressObjectByPublicKey)(input, this.network);
83
+ }
84
+ validateAddress(address) {
85
+ try {
86
+ (0, bitcoin_utils_1.getAddressType)(address, this.network);
87
+ return true;
88
+ }
89
+ catch (error) {
90
+ return false;
91
+ }
92
+ }
93
+ getOpReturnTarget(dataHex) {
94
+ if (!(dataHex.length > 0))
95
+ throw new Error("invalid data in hex");
96
+ const embed = bitcoin.payments.embed({
97
+ data: [Buffer.from(dataHex, "hex")],
98
+ network: this.network,
99
+ });
100
+ return {
101
+ script: embed.output,
102
+ value: 0,
103
+ };
104
+ }
105
+ calculateTxSize(inputTypes, outputs, changeAddressType = "default") {
106
+ const inputsSizes = inputTypes.map((addressType) => exports.componentBytes.bytePerInput[addressType]);
107
+ const outputSizes = outputs.map((outP) => {
108
+ if (outP.address) {
109
+ let addressType = "default";
110
+ try {
111
+ addressType = (0, bitcoin_utils_1.getAddressType)(outP.address, this.network);
112
+ }
113
+ catch (_a) {
114
+ addressType = "default";
115
+ }
116
+ return exports.componentBytes.bytePerOutput[addressType];
117
+ }
118
+ if (outP.script) {
119
+ if (outP.script.byteLength < 255) {
120
+ return outP.script.byteLength + exports.componentBytes.scriptExtraBytes.lessThan255;
121
+ }
122
+ return outP.script.byteLength + exports.componentBytes.scriptExtraBytes.moreThan255;
123
+ }
124
+ return exports.componentBytes.bytePerOutput[changeAddressType];
125
+ });
126
+ const txSize = exports.componentBytes.baseTxBytes +
127
+ inputsSizes.reduce((a, c) => a + c, 0) +
128
+ outputSizes.reduce((a, c) => a + c, 0);
129
+ return txSize;
130
+ }
131
+ helperHandleInputsAndOutputs({ targets, extendedUtxo, feeRate, changeObject, selectType = "normal", }) {
132
+ const filteredUtxo = extendedUtxo.filter((u) => u.value >
133
+ +feeRate *
134
+ exports.componentBytes.bytePerInput[u.signerInfo.addressType]);
135
+ let selectResponse;
136
+ switch (selectType) {
137
+ case "normal":
138
+ selectResponse = coinselect(filteredUtxo, targets, Math.round(feeRate));
139
+ break;
140
+ case "accumulative":
141
+ selectResponse = coinselectAccumulative(filteredUtxo, targets, Math.round(feeRate));
142
+ break;
143
+ case "inOrder":
144
+ selectResponse = coinSelectInOrder(filteredUtxo, targets, Math.round(feeRate));
145
+ break;
146
+ case "full":
147
+ if (!targets[0].address) {
148
+ throw new Error();
149
+ }
150
+ selectResponse = coinselectSplit(filteredUtxo, [{ address: targets[0].address }], Math.round(feeRate));
151
+ break;
152
+ default:
153
+ break;
154
+ }
155
+ let { inputs, outputs, fee, } = selectResponse;
156
+ if (!inputs || !outputs) {
157
+ inputs = filteredUtxo;
158
+ outputs = targets;
159
+ fee = inputs.reduce((a, b) => a + b.value, 0) - outputs.reduce((a, b) => a + b.value, 0);
160
+ }
161
+ let changeAddressType = "default";
162
+ try {
163
+ changeAddressType = (0, bitcoin_utils_1.getAddressType)((changeObject === null || changeObject === void 0 ? void 0 : changeObject.address) || "", this.network);
164
+ }
165
+ catch (_a) {
166
+ changeAddressType = "default";
167
+ }
168
+ const txSize = this.calculateTxSize(inputs.map((i) => i.signerInfo.addressType), outputs, changeAddressType) + exports.componentBytes.bytePerOutput.default;
169
+ let txFee = Math.round(txSize * feeRate);
170
+ if (Math.round(feeRate) === 1) {
171
+ txFee = Math.round(txFee + txFee * 0.1);
172
+ }
173
+ if (inputs.reduce((a, b) => a + b.value, 0) -
174
+ outputs.filter((o) => o.address || o.script).reduce((a, b) => a + b.value, 0) -
175
+ txFee <
176
+ 0) {
177
+ let spendableBalance = inputs.reduce((a, b) => a + b.value, 0);
178
+ let totalOutputAmount = outputs
179
+ .filter((o) => o.address || o.script)
180
+ .reduce((a, b) => a + b.value, 0);
181
+ let need = spendableBalance - totalOutputAmount - txFee;
182
+ throw new Error(`not enough balance. details: ${JSON.stringify({ spendableBalance, totalOutputAmount, txFee, need }, null, 2)}`);
183
+ }
184
+ let diff = fee - txFee;
185
+ let changeIndex = outputs.findIndex((x) => !(x === null || x === void 0 ? void 0 : x.address) && !x.script && (x.value || 0) > 0);
186
+ let change;
187
+ if (changeIndex >= 0 || diff > exports.DUST) {
188
+ if (changeIndex >= 0) {
189
+ diff = diff + exports.componentBytes.bytePerOutput.default * Math.round(feeRate);
190
+ }
191
+ if (diff < 0) {
192
+ diff = 0;
193
+ }
194
+ if (selectType === "full") {
195
+ outputs[0].value = outputs[0].value + diff;
196
+ fee = fee - diff;
197
+ }
198
+ else {
199
+ if (!changeObject)
200
+ throw new Error("change not exist");
201
+ change = {
202
+ address: changeObject.address,
203
+ value: changeIndex >= 0 ? outputs[changeIndex].value + diff : diff,
204
+ };
205
+ fee = fee - diff;
206
+ }
207
+ if (changeIndex >= 0) {
208
+ outputs.splice(changeIndex, 1);
209
+ }
210
+ }
211
+ return {
212
+ inputs,
213
+ fee,
214
+ outputs: outputs,
215
+ change,
216
+ };
217
+ }
218
+ filterAndConvertTxDataToStandardFormat({ extendedUtxo, targets, changeObject, feeRate, selectType, }) {
219
+ return __awaiter(this, void 0, void 0, function* () {
220
+ let { inputs: filteredInputs, outputs, change, fee, } = this.helperHandleInputsAndOutputs({
221
+ targets,
222
+ extendedUtxo,
223
+ feeRate,
224
+ changeObject,
225
+ selectType,
226
+ });
227
+ let inputs = yield this.convertExtendedUtxoToInputs(filteredInputs);
228
+ return {
229
+ inputs,
230
+ outputs,
231
+ change,
232
+ fee,
233
+ feeRate,
234
+ };
235
+ });
236
+ }
237
+ convertExtendedUtxoToInputs(baseInputs = []) {
238
+ var _a;
239
+ return __awaiter(this, void 0, void 0, function* () {
240
+ let inputs = baseInputs;
241
+ const transactionHex = {};
242
+ for (let i in inputs) {
243
+ let { address, publicKey, derivationPath, masterFingerprint, addressType } = inputs[i].signerInfo;
244
+ let addressObject = this.createAddressObject({
245
+ publicKey: Buffer.from(publicKey, "hex"),
246
+ addressType,
247
+ });
248
+ if (derivationPath && masterFingerprint && addressObject.pubkey) {
249
+ inputs[i].bip32Derivation = [
250
+ {
251
+ path: derivationPath,
252
+ pubkey: addressObject.pubkey,
253
+ masterFingerprint: Buffer.from(masterFingerprint, "hex"),
254
+ },
255
+ ];
256
+ }
257
+ if (addressType === "p2pkh") {
258
+ const txHex = transactionHex[inputs[i].hash] || (yield this._getTransactionHex(inputs[i].hash));
259
+ transactionHex[inputs[i].hash] = txHex;
260
+ inputs[i].nonWitnessUtxo = Buffer.from(txHex, "hex");
261
+ }
262
+ else if (addressType === "p2wpkh") {
263
+ if (!addressObject.output)
264
+ throw new Error("invalid signer info");
265
+ inputs[i].witnessUtxo = {
266
+ script: addressObject.output,
267
+ value: inputs[i].value,
268
+ };
269
+ if (inputs[i].signerInfo.includeHex) {
270
+ const txHex = transactionHex[inputs[i].hash] || (yield this._getTransactionHex(inputs[i].hash));
271
+ transactionHex[inputs[i].hash] = txHex;
272
+ inputs[i].nonWitnessUtxo = Buffer.from(txHex, "hex");
273
+ }
274
+ }
275
+ else if (addressType === "p2sh-p2wpkh") {
276
+ if (!addressObject.output)
277
+ throw new Error("invalid signer info");
278
+ inputs[i].witnessUtxo = {
279
+ script: addressObject.output,
280
+ value: inputs[i].value,
281
+ };
282
+ if (!((_a = addressObject === null || addressObject === void 0 ? void 0 : addressObject.redeem) === null || _a === void 0 ? void 0 : _a.output))
283
+ throw new Error("invalid signer info for p2sh address");
284
+ inputs[i].redeemScript = addressObject.redeem.output;
285
+ if (inputs[i].signerInfo.includeHex) {
286
+ const txHex = transactionHex[inputs[i].hash] || (yield this._getTransactionHex(inputs[i].hash));
287
+ transactionHex[inputs[i].hash] = txHex;
288
+ inputs[i].nonWitnessUtxo = Buffer.from(txHex, "hex");
289
+ }
290
+ }
291
+ else if (addressType === "p2tr") {
292
+ if (!addressObject.output)
293
+ throw new Error("invalid signer info");
294
+ inputs[i].witnessUtxo = {
295
+ script: addressObject.output,
296
+ value: inputs[i].value,
297
+ };
298
+ if (!addressObject.pubkey)
299
+ throw new Error("invalid signer info for p2tr address (pubkey)");
300
+ inputs[i].tapInternalKey = addressObject.internalPubkey;
301
+ if (inputs[i].signerInfo.includeHex) {
302
+ const txHex = transactionHex[inputs[i].hash] || (yield this._getTransactionHex(inputs[i].hash));
303
+ transactionHex[inputs[i].hash] = txHex;
304
+ inputs[i].nonWitnessUtxo = Buffer.from(txHex, "hex");
305
+ }
306
+ }
307
+ }
308
+ return inputs;
309
+ });
310
+ }
311
+ createUnsignedTransaction({ inputs, outputs, change, fee, feeRate, }) {
312
+ const sequence = 0xffffffff - 2;
313
+ const { network } = this;
314
+ const newPsbt = new bitcoin.Psbt({ network });
315
+ newPsbt.setMaximumFeeRate(+(feeRate + feeRate / 100).toFixed());
316
+ for (const input of inputs) {
317
+ let { addressType } = input.signerInfo;
318
+ switch (addressType) {
319
+ case "p2pkh": {
320
+ let i = {
321
+ hash: input.hash,
322
+ index: Number(input.index),
323
+ nonWitnessUtxo: input.nonWitnessUtxo,
324
+ sequence,
325
+ bip32Derivation: input.bip32Derivation,
326
+ };
327
+ if (!i.bip32Derivation)
328
+ delete i.bip32Derivation;
329
+ newPsbt.addInput(i);
330
+ break;
331
+ }
332
+ case "p2wpkh": {
333
+ let i = {
334
+ hash: input.hash,
335
+ index: Number(input.index),
336
+ witnessUtxo: input.witnessUtxo,
337
+ nonWitnessUtxo: input.nonWitnessUtxo,
338
+ sequence,
339
+ bip32Derivation: input.bip32Derivation,
340
+ };
341
+ if (!i.bip32Derivation)
342
+ delete i.bip32Derivation;
343
+ if (!i.nonWitnessUtxo)
344
+ delete i.nonWitnessUtxo;
345
+ newPsbt.addInput(i);
346
+ break;
347
+ }
348
+ case "p2sh-p2wpkh": {
349
+ let i = {
350
+ hash: input.hash,
351
+ index: Number(input.index),
352
+ witnessUtxo: input.witnessUtxo,
353
+ nonWitnessUtxo: input.nonWitnessUtxo,
354
+ redeemScript: input.redeemScript,
355
+ sequence,
356
+ bip32Derivation: input.bip32Derivation,
357
+ };
358
+ if (!i.bip32Derivation)
359
+ delete i.bip32Derivation;
360
+ if (!i.nonWitnessUtxo)
361
+ delete i.nonWitnessUtxo;
362
+ newPsbt.addInput(i);
363
+ break;
364
+ }
365
+ case "p2tr": {
366
+ let i = {
367
+ hash: input.hash,
368
+ index: Number(input.index),
369
+ witnessUtxo: input.witnessUtxo,
370
+ nonWitnessUtxo: input.nonWitnessUtxo,
371
+ tapInternalKey: input.tapInternalKey,
372
+ sequence,
373
+ bip32Derivation: input.bip32Derivation,
374
+ };
375
+ if (!i.bip32Derivation)
376
+ delete i.bip32Derivation;
377
+ if (!i.nonWitnessUtxo)
378
+ delete i.nonWitnessUtxo;
379
+ newPsbt.addInput(i);
380
+ break;
381
+ }
382
+ default:
383
+ throw new Error("address type is incorrect");
384
+ }
385
+ }
386
+ for (const target of outputs) {
387
+ newPsbt.addOutput(target);
388
+ }
389
+ if (change && Object.keys(change).length !== 0) {
390
+ newPsbt.addOutput(change);
391
+ }
392
+ if (change && Object.keys(change).length !== 0) {
393
+ if (newPsbt.txOutputs[outputs.length].address !== change.address) {
394
+ throw new Error("error change address");
395
+ }
396
+ }
397
+ const unsignedPsbtBaseText = newPsbt.toBase64();
398
+ const safeAddressTypeForPossibleTxId = ["p2wpkh", "p2tr"];
399
+ const isPossibleTxId = inputs.reduce((a, b) => a && safeAddressTypeForPossibleTxId.includes(b.signerInfo.addressType), true);
400
+ return {
401
+ unsignedTransaction: unsignedPsbtBaseText,
402
+ outputs,
403
+ inputs: inputs.map((utx) => ({
404
+ hash: utx.hash,
405
+ value: Number(utx.value),
406
+ index: utx.index,
407
+ signerInfo: utx.signerInfo,
408
+ })),
409
+ fee,
410
+ change,
411
+ possibleTxId: isPossibleTxId ? this.getUnsignedPsbtTxId(unsignedPsbtBaseText) : undefined,
412
+ };
413
+ }
414
+ processUnsignedTransaction({ extendedUtxo, targets = [], changeAddress = undefined, fullAmount = false, feeRate, selectType = "normal", }) {
415
+ return __awaiter(this, void 0, void 0, function* () {
416
+ if (!changeAddress && targets.length === 0)
417
+ throw new Error("no target");
418
+ let changeObject = typeof changeAddress === "string"
419
+ ? {
420
+ address: changeAddress,
421
+ }
422
+ : changeAddress;
423
+ const { inputs, outputs, change, fee } = yield this.filterAndConvertTxDataToStandardFormat({
424
+ extendedUtxo,
425
+ targets,
426
+ changeObject,
427
+ feeRate,
428
+ selectType: fullAmount ? "full" : selectType,
429
+ });
430
+ let unsignedTransaction = this.createUnsignedTransaction({
431
+ inputs,
432
+ outputs,
433
+ change,
434
+ fee,
435
+ feeRate,
436
+ });
437
+ return unsignedTransaction;
438
+ });
439
+ }
440
+ getUnsignedPsbtTxId(unsignedPsbt) {
441
+ let psbt = bitcoin.Psbt.fromBase64(unsignedPsbt, {
442
+ network: this.network,
443
+ });
444
+ return psbt.__CACHE.__TX.getId();
445
+ }
446
+ }
447
+ exports.BaseTransactionBuilder = BaseTransactionBuilder;
448
448
  //# sourceMappingURL=transaction-builder.js.map