@teleportdao/bitcoin 2.0.5 → 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 (76) 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.js +176 -176
  5. package/dist/bitcoin-interface-utils.d.ts +20 -20
  6. package/dist/bitcoin-interface-utils.js +45 -45
  7. package/dist/bitcoin-interface-wallet.d.ts +28 -28
  8. package/dist/bitcoin-interface-wallet.js +125 -125
  9. package/dist/bitcoin-interface.d.ts +66 -66
  10. package/dist/bitcoin-interface.js +119 -119
  11. package/dist/bitcoin-utils.d.ts +96 -96
  12. package/dist/bitcoin-utils.js +514 -514
  13. package/dist/bitcoin-wallet-base.d.ts +111 -111
  14. package/dist/bitcoin-wallet-base.js +258 -258
  15. package/dist/helper/brc20-helper.d.ts +42 -42
  16. package/dist/helper/brc20-helper.js +127 -127
  17. package/dist/helper/index.d.ts +3 -3
  18. package/dist/helper/index.js +29 -29
  19. package/dist/helper/ordinal-helper.d.ts +12 -12
  20. package/dist/helper/ordinal-helper.js +129 -129
  21. package/dist/helper/teleswap-helper.d.ts +95 -95
  22. package/dist/helper/teleswap-helper.js +186 -186
  23. package/dist/index.d.ts +12 -12
  24. package/dist/index.js +41 -41
  25. package/dist/ordinal-wallet.d.ts +495 -495
  26. package/dist/ordinal-wallet.js +386 -386
  27. package/dist/sign/index.d.ts +1 -1
  28. package/dist/sign/index.js +8 -8
  29. package/dist/sign/sign-transaction.d.ts +12 -12
  30. package/dist/sign/sign-transaction.js +82 -82
  31. package/dist/teleswap-wallet.d.ts +45 -45
  32. package/dist/teleswap-wallet.js +68 -68
  33. package/dist/transaction-builder/bitcoin-transaction-builder.d.ts +9 -9
  34. package/dist/transaction-builder/bitcoin-transaction-builder.js +54 -54
  35. package/dist/transaction-builder/index.d.ts +3 -3
  36. package/dist/transaction-builder/index.js +19 -19
  37. package/dist/transaction-builder/ordinal-transaction-builder.d.ts +63 -63
  38. package/dist/transaction-builder/ordinal-transaction-builder.js +125 -125
  39. package/dist/transaction-builder/transaction-builder.d.ts +223 -223
  40. package/dist/transaction-builder/transaction-builder.js +447 -447
  41. package/dist/type.d.ts +61 -61
  42. package/dist/type.js +2 -2
  43. package/dist/utils/networks.d.ts +5 -5
  44. package/dist/utils/networks.js +53 -53
  45. package/dist/utils/tools.d.ts +18 -18
  46. package/dist/utils/tools.js +74 -74
  47. package/package.json +4 -4
  48. package/src/bitcoin-interface-ordinal.ts +185 -185
  49. package/src/bitcoin-interface-teleswap.ts +251 -251
  50. package/src/bitcoin-interface-utils.ts +60 -60
  51. package/src/bitcoin-interface-wallet.ts +114 -114
  52. package/src/bitcoin-interface.ts +156 -156
  53. package/src/bitcoin-utils.ts +591 -591
  54. package/src/bitcoin-wallet-base.ts +344 -344
  55. package/src/helper/brc20-helper.ts +179 -179
  56. package/src/helper/ordinal-helper.ts +118 -118
  57. package/src/index.ts +15 -15
  58. package/src/ordinal-wallet.ts +659 -659
  59. package/src/sign/index.ts +1 -1
  60. package/src/sign/sign-transaction.ts +108 -108
  61. package/src/teleswap-wallet.ts +133 -133
  62. package/src/transaction-builder/bitcoin-transaction-builder.ts +26 -26
  63. package/src/transaction-builder/index.ts +3 -3
  64. package/src/transaction-builder/ordinal-transaction-builder.ts +139 -139
  65. package/src/transaction-builder/transaction-builder.ts +690 -690
  66. package/src/type.ts +74 -74
  67. package/src/utils/networks.ts +33 -33
  68. package/src/utils/tools.ts +92 -92
  69. package/tsconfig.json +9 -9
  70. package/webpack.config.js +16 -16
  71. package/.tmp/block-parser.ts +0 -58
  72. package/.tmp/check.ts +0 -101
  73. package/.tmp/ordinal-helper.ts +0 -133
  74. package/.tmp/ordinal.ts +0 -25
  75. package/.tmp/psbt/sign-transaction.ts +0 -121
  76. 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