@btc-vision/wallet-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +24 -0
  3. package/es/bundle.js +2 -0
  4. package/es/bundle.js.LICENSE.txt +48 -0
  5. package/lib/address/index.d.ts +37 -0
  6. package/lib/address/index.js +235 -0
  7. package/lib/bitcoin-core.d.ts +5 -0
  8. package/lib/bitcoin-core.js +37 -0
  9. package/lib/constants.d.ts +1 -0
  10. package/lib/constants.js +5 -0
  11. package/lib/error.d.ts +20 -0
  12. package/lib/error.js +29 -0
  13. package/lib/index.d.ts +14 -0
  14. package/lib/index.js +50 -0
  15. package/lib/keyring/hd-keyring.d.ts +50 -0
  16. package/lib/keyring/hd-keyring.js +238 -0
  17. package/lib/keyring/index.d.ts +4 -0
  18. package/lib/keyring/index.js +20 -0
  19. package/lib/keyring/interfaces/SimpleKeyringOptions.d.ts +53 -0
  20. package/lib/keyring/interfaces/SimpleKeyringOptions.js +85 -0
  21. package/lib/keyring/keystone-keyring.d.ts +82 -0
  22. package/lib/keyring/keystone-keyring.js +377 -0
  23. package/lib/keyring/simple-keyring.d.ts +11 -0
  24. package/lib/keyring/simple-keyring.js +66 -0
  25. package/lib/message/bip322-simple.d.ts +19 -0
  26. package/lib/message/bip322-simple.js +182 -0
  27. package/lib/message/deterministic-ecdsa.d.ts +2 -0
  28. package/lib/message/deterministic-ecdsa.js +83 -0
  29. package/lib/message/ecdsa.d.ts +3 -0
  30. package/lib/message/ecdsa.js +32 -0
  31. package/lib/message/index.d.ts +3 -0
  32. package/lib/message/index.js +19 -0
  33. package/lib/network/index.d.ts +14 -0
  34. package/lib/network/index.js +40 -0
  35. package/lib/runes/index.d.ts +1 -0
  36. package/lib/runes/index.js +17 -0
  37. package/lib/runes/rund_id.d.ts +11 -0
  38. package/lib/runes/rund_id.js +30 -0
  39. package/lib/runes/varint.d.ts +15 -0
  40. package/lib/runes/varint.js +45 -0
  41. package/lib/src/address/index.d.ts +37 -0
  42. package/lib/src/bitcoin-core.d.ts +5 -0
  43. package/lib/src/constants.d.ts +1 -0
  44. package/lib/src/error.d.ts +20 -0
  45. package/lib/src/index.d.ts +14 -0
  46. package/lib/src/keyring/hd-keyring.d.ts +50 -0
  47. package/lib/src/keyring/index.d.ts +4 -0
  48. package/lib/src/keyring/interfaces/SimpleKeyringOptions.d.ts +53 -0
  49. package/lib/src/keyring/keystone-keyring.d.ts +82 -0
  50. package/lib/src/keyring/simple-keyring.d.ts +11 -0
  51. package/lib/src/message/bip322-simple.d.ts +19 -0
  52. package/lib/src/message/deterministic-ecdsa.d.ts +2 -0
  53. package/lib/src/message/ecdsa.d.ts +3 -0
  54. package/lib/src/message/index.d.ts +3 -0
  55. package/lib/src/network/index.d.ts +14 -0
  56. package/lib/src/runes/index.d.ts +1 -0
  57. package/lib/src/runes/rund_id.d.ts +11 -0
  58. package/lib/src/runes/varint.d.ts +15 -0
  59. package/lib/src/transaction/index.d.ts +3 -0
  60. package/lib/src/transaction/inscription-utxo.d.ts +33 -0
  61. package/lib/src/transaction/transaction.d.ts +52 -0
  62. package/lib/src/transaction/utxo.d.ts +35 -0
  63. package/lib/src/tx-helpers/index.d.ts +8 -0
  64. package/lib/src/tx-helpers/send-atomicals-ft.d.ts +16 -0
  65. package/lib/src/tx-helpers/send-atomicals-nft.d.ts +14 -0
  66. package/lib/src/tx-helpers/send-btc.d.ts +28 -0
  67. package/lib/src/tx-helpers/send-inscription.d.ts +16 -0
  68. package/lib/src/tx-helpers/send-inscriptions.d.ts +14 -0
  69. package/lib/src/tx-helpers/send-runes.d.ts +19 -0
  70. package/lib/src/tx-helpers/split-inscription-utxo.d.ts +15 -0
  71. package/lib/src/types.d.ts +59 -0
  72. package/lib/src/utils.d.ts +23 -0
  73. package/lib/src/wallet/abstract-wallet.d.ts +6 -0
  74. package/lib/src/wallet/estimate-wallet.d.ts +23 -0
  75. package/lib/src/wallet/index.d.ts +3 -0
  76. package/lib/src/wallet/local-wallet.d.ts +23 -0
  77. package/lib/test/address/address.test.d.ts +1 -0
  78. package/lib/test/keyring/hd-keyring.test.d.ts +1 -0
  79. package/lib/test/keyring/keystone-keyring.test.d.ts +1 -0
  80. package/lib/test/keyring/simple-keyring.test.d.ts +1 -0
  81. package/lib/test/message/message.test.d.ts +1 -0
  82. package/lib/test/runes/varint.test.d.ts +1 -0
  83. package/lib/test/transaction/transaction.test.d.ts +1 -0
  84. package/lib/test/transaction/utxo.test.d.ts +1 -0
  85. package/lib/test/tx-helpers/send-atomicals-ft.test.d.ts +1 -0
  86. package/lib/test/tx-helpers/send-atomicals-nft.test.d.ts +1 -0
  87. package/lib/test/tx-helpers/send-btc.test.d.ts +1 -0
  88. package/lib/test/tx-helpers/send-inscription.test.d.ts +1 -0
  89. package/lib/test/tx-helpers/send-inscriptions.test.d.ts +1 -0
  90. package/lib/test/tx-helpers/send-runes.test.d.ts +1 -0
  91. package/lib/test/tx-helpers/split-inscription-utxo.test.d.ts +1 -0
  92. package/lib/test/tx-helpers/utils.d.ts +217 -0
  93. package/lib/test/utils.d.ts +4 -0
  94. package/lib/test/wallet/local-wallet.test.d.ts +1 -0
  95. package/lib/transaction/index.d.ts +3 -0
  96. package/lib/transaction/index.js +19 -0
  97. package/lib/transaction/inscription-utxo.d.ts +33 -0
  98. package/lib/transaction/inscription-utxo.js +120 -0
  99. package/lib/transaction/transaction.d.ts +52 -0
  100. package/lib/transaction/transaction.js +358 -0
  101. package/lib/transaction/utxo.d.ts +35 -0
  102. package/lib/transaction/utxo.js +107 -0
  103. package/lib/tx-helpers/index.d.ts +8 -0
  104. package/lib/tx-helpers/index.js +18 -0
  105. package/lib/tx-helpers/send-atomicals-ft.d.ts +16 -0
  106. package/lib/tx-helpers/send-atomicals-ft.js +66 -0
  107. package/lib/tx-helpers/send-atomicals-nft.d.ts +14 -0
  108. package/lib/tx-helpers/send-atomicals-nft.js +45 -0
  109. package/lib/tx-helpers/send-btc.d.ts +28 -0
  110. package/lib/tx-helpers/send-btc.js +78 -0
  111. package/lib/tx-helpers/send-inscription.d.ts +16 -0
  112. package/lib/tx-helpers/send-inscription.js +49 -0
  113. package/lib/tx-helpers/send-inscriptions.d.ts +14 -0
  114. package/lib/tx-helpers/send-inscriptions.js +45 -0
  115. package/lib/tx-helpers/send-runes.d.ts +19 -0
  116. package/lib/tx-helpers/send-runes.js +101 -0
  117. package/lib/tx-helpers/split-inscription-utxo.d.ts +15 -0
  118. package/lib/tx-helpers/split-inscription-utxo.js +58 -0
  119. package/lib/types.d.ts +59 -0
  120. package/lib/types.js +15 -0
  121. package/lib/utils.d.ts +23 -0
  122. package/lib/utils.js +71 -0
  123. package/lib/wallet/abstract-wallet.d.ts +6 -0
  124. package/lib/wallet/abstract-wallet.js +2 -0
  125. package/lib/wallet/estimate-wallet.d.ts +23 -0
  126. package/lib/wallet/estimate-wallet.js +174 -0
  127. package/lib/wallet/index.d.ts +3 -0
  128. package/lib/wallet/index.js +19 -0
  129. package/lib/wallet/local-wallet.d.ts +23 -0
  130. package/lib/wallet/local-wallet.js +183 -0
  131. package/package.json +97 -0
@@ -0,0 +1,358 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.Transaction = void 0;
13
+ const address_1 = require("../address");
14
+ const bitcoin_core_1 = require("../bitcoin-core");
15
+ const constants_1 = require("../constants");
16
+ const error_1 = require("../error");
17
+ const network_1 = require("../network");
18
+ const types_1 = require("../types");
19
+ const utils_1 = require("../utils");
20
+ const wallet_1 = require("../wallet");
21
+ const utxo_1 = require("./utxo");
22
+ /**
23
+ * Convert UnspentOutput to PSBT TxInput
24
+ */
25
+ function utxoToInput(utxo, estimate) {
26
+ if (utxo.addressType === types_1.AddressType.P2TR || utxo.addressType === types_1.AddressType.M44_P2TR) {
27
+ const data = {
28
+ hash: utxo.txid,
29
+ index: utxo.vout,
30
+ witnessUtxo: {
31
+ value: utxo.satoshis,
32
+ script: Buffer.from(utxo.scriptPk, 'hex')
33
+ },
34
+ tapInternalKey: (0, utils_1.toXOnly)(Buffer.from(utxo.pubkey, 'hex'))
35
+ };
36
+ return {
37
+ data,
38
+ utxo
39
+ };
40
+ }
41
+ else if (utxo.addressType === types_1.AddressType.P2WPKH || utxo.addressType === types_1.AddressType.M44_P2WPKH) {
42
+ const data = {
43
+ hash: utxo.txid,
44
+ index: utxo.vout,
45
+ witnessUtxo: {
46
+ value: utxo.satoshis,
47
+ script: Buffer.from(utxo.scriptPk, 'hex')
48
+ }
49
+ };
50
+ return {
51
+ data,
52
+ utxo
53
+ };
54
+ }
55
+ else if (utxo.addressType === types_1.AddressType.P2PKH) {
56
+ if (!utxo.rawtx || estimate) {
57
+ const data = {
58
+ hash: utxo.txid,
59
+ index: utxo.vout,
60
+ witnessUtxo: {
61
+ value: utxo.satoshis,
62
+ script: Buffer.from(utxo.scriptPk, 'hex')
63
+ }
64
+ };
65
+ return {
66
+ data,
67
+ utxo
68
+ };
69
+ }
70
+ else {
71
+ const data = {
72
+ hash: utxo.txid,
73
+ index: utxo.vout,
74
+ nonWitnessUtxo: Buffer.from(utxo.rawtx, 'hex')
75
+ };
76
+ return {
77
+ data,
78
+ utxo
79
+ };
80
+ }
81
+ }
82
+ else if (utxo.addressType === types_1.AddressType.P2SH_P2WPKH) {
83
+ const redeemData = bitcoin_core_1.bitcoin.payments.p2wpkh({
84
+ pubkey: Buffer.from(utxo.pubkey, 'hex')
85
+ });
86
+ const data = {
87
+ hash: utxo.txid,
88
+ index: utxo.vout,
89
+ witnessUtxo: {
90
+ value: utxo.satoshis,
91
+ script: Buffer.from(utxo.scriptPk, 'hex')
92
+ },
93
+ redeemScript: redeemData.output
94
+ };
95
+ return {
96
+ data,
97
+ utxo
98
+ };
99
+ }
100
+ }
101
+ /**
102
+ * Transaction
103
+ */
104
+ class Transaction {
105
+ constructor() {
106
+ this.utxos = [];
107
+ this.inputs = [];
108
+ this.outputs = [];
109
+ this.changeOutputIndex = -1;
110
+ this.enableRBF = true;
111
+ this._cacheNetworkFee = 0;
112
+ this._cacheBtcUtxos = [];
113
+ this._cacheToSignInputs = [];
114
+ }
115
+ setNetworkType(network) {
116
+ this.networkType = network;
117
+ }
118
+ setEnableRBF(enable) {
119
+ this.enableRBF = enable;
120
+ }
121
+ setFeeRate(feeRate) {
122
+ this.feeRate = feeRate;
123
+ }
124
+ setChangeAddress(address) {
125
+ this.changedAddress = address;
126
+ }
127
+ addInput(utxo) {
128
+ this.utxos.push(utxo);
129
+ this.inputs.push(utxoToInput(utxo));
130
+ }
131
+ removeLastInput() {
132
+ this.utxos = this.utxos.slice(0, -1);
133
+ this.inputs = this.inputs.slice(0, -1);
134
+ }
135
+ getTotalInput() {
136
+ return this.inputs.reduce((pre, cur) => pre + cur.utxo.satoshis, 0);
137
+ }
138
+ getTotalOutput() {
139
+ return this.outputs.reduce((pre, cur) => pre + cur.value, 0);
140
+ }
141
+ getUnspent() {
142
+ return this.getTotalInput() - this.getTotalOutput();
143
+ }
144
+ calNetworkFee() {
145
+ return __awaiter(this, void 0, void 0, function* () {
146
+ const psbt = yield this.createEstimatePsbt();
147
+ const txSize = psbt.extractTransaction(true).virtualSize();
148
+ const fee = Math.ceil(txSize * this.feeRate);
149
+ return fee;
150
+ });
151
+ }
152
+ addOutput(address, value) {
153
+ this.outputs.push({
154
+ address,
155
+ value
156
+ });
157
+ }
158
+ addOpreturn(data) {
159
+ const embed = bitcoin_core_1.bitcoin.payments.embed({ data });
160
+ this.outputs.push({
161
+ script: embed.output,
162
+ value: 0
163
+ });
164
+ }
165
+ addScriptOutput(script, value) {
166
+ this.outputs.push({
167
+ script,
168
+ value
169
+ });
170
+ }
171
+ getOutput(index) {
172
+ return this.outputs[index];
173
+ }
174
+ addChangeOutput(value) {
175
+ this.outputs.push({
176
+ address: this.changedAddress,
177
+ value
178
+ });
179
+ this.changeOutputIndex = this.outputs.length - 1;
180
+ }
181
+ getChangeOutput() {
182
+ return this.outputs[this.changeOutputIndex];
183
+ }
184
+ getChangeAmount() {
185
+ const output = this.getChangeOutput();
186
+ return output ? output.value : 0;
187
+ }
188
+ removeChangeOutput() {
189
+ this.outputs.splice(this.changeOutputIndex, 1);
190
+ this.changeOutputIndex = -1;
191
+ }
192
+ removeRecentOutputs(count) {
193
+ this.outputs.splice(-count);
194
+ }
195
+ toPsbt() {
196
+ const network = (0, network_1.toPsbtNetwork)(this.networkType);
197
+ const psbt = new bitcoin_core_1.bitcoin.Psbt({ network });
198
+ this.inputs.forEach((v, index) => {
199
+ if (v.utxo.addressType === types_1.AddressType.P2PKH) {
200
+ if (v.data.witnessUtxo) {
201
+ //@ts-ignore
202
+ psbt.__CACHE.__UNSAFE_SIGN_NONSEGWIT = true;
203
+ }
204
+ }
205
+ psbt.data.addInput(v.data);
206
+ if (this.enableRBF) {
207
+ psbt.setInputSequence(index, 0xfffffffd);
208
+ }
209
+ });
210
+ this.outputs.forEach((v) => {
211
+ if (v.address) {
212
+ psbt.addOutput({
213
+ address: v.address,
214
+ value: v.value
215
+ });
216
+ }
217
+ else if (v.script) {
218
+ psbt.addOutput({
219
+ script: v.script,
220
+ value: v.value
221
+ });
222
+ }
223
+ });
224
+ return psbt;
225
+ }
226
+ clone() {
227
+ const tx = new Transaction();
228
+ tx.setNetworkType(this.networkType);
229
+ tx.setFeeRate(this.feeRate);
230
+ tx.setEnableRBF(this.enableRBF);
231
+ tx.setChangeAddress(this.changedAddress);
232
+ tx.utxos = this.utxos.map((v) => Object.assign({}, v));
233
+ tx.inputs = this.inputs.map((v) => v);
234
+ tx.outputs = this.outputs.map((v) => v);
235
+ return tx;
236
+ }
237
+ createEstimatePsbt() {
238
+ return __awaiter(this, void 0, void 0, function* () {
239
+ const estimateWallet = wallet_1.EstimateWallet.fromRandom(this.inputs[0].utxo.addressType, this.networkType);
240
+ const scriptPk = (0, address_1.addressToScriptPk)(estimateWallet.address, this.networkType).toString('hex');
241
+ const tx = this.clone();
242
+ tx.utxos.forEach((v) => {
243
+ v.pubkey = estimateWallet.pubkey;
244
+ v.scriptPk = scriptPk;
245
+ });
246
+ tx.inputs = [];
247
+ tx.utxos.forEach((v) => {
248
+ const input = utxoToInput(v, true);
249
+ tx.inputs.push(input);
250
+ });
251
+ const psbt = tx.toPsbt();
252
+ const toSignInputs = tx.inputs.map((v, index) => ({
253
+ index,
254
+ publicKey: estimateWallet.pubkey
255
+ }));
256
+ yield estimateWallet.signPsbt(psbt, {
257
+ autoFinalized: true,
258
+ toSignInputs: toSignInputs
259
+ });
260
+ return psbt;
261
+ });
262
+ }
263
+ selectBtcUtxos() {
264
+ const totalInput = this.getTotalInput();
265
+ const totalOutput = this.getTotalOutput() + this._cacheNetworkFee;
266
+ if (totalInput < totalOutput) {
267
+ const { selectedUtxos, remainingUtxos } = utxo_1.utxoHelper.selectBtcUtxos(this._cacheBtcUtxos, totalOutput - totalInput);
268
+ if (selectedUtxos.length == 0) {
269
+ throw new error_1.WalletUtilsError(error_1.ErrorCodes.INSUFFICIENT_BTC_UTXO);
270
+ }
271
+ selectedUtxos.forEach((v) => {
272
+ this.addInput(v);
273
+ this._cacheToSignInputs.push({
274
+ index: this.inputs.length - 1,
275
+ publicKey: v.pubkey
276
+ });
277
+ this._cacheNetworkFee += utxo_1.utxoHelper.getAddedVirtualSize(v.addressType) * this.feeRate;
278
+ });
279
+ this._cacheBtcUtxos = remainingUtxos;
280
+ this.selectBtcUtxos();
281
+ }
282
+ }
283
+ addSufficientUtxosForFee(btcUtxos, forceAsFee) {
284
+ return __awaiter(this, void 0, void 0, function* () {
285
+ if (btcUtxos.length > 0) {
286
+ this._cacheBtcUtxos = btcUtxos;
287
+ const dummyBtcUtxo = Object.assign({}, btcUtxos[0]);
288
+ dummyBtcUtxo.satoshis = 2100000000000000;
289
+ this.addInput(dummyBtcUtxo);
290
+ this.addChangeOutput(0);
291
+ const networkFee = yield this.calNetworkFee();
292
+ const dummyBtcUtxoSize = utxo_1.utxoHelper.getAddedVirtualSize(dummyBtcUtxo.addressType);
293
+ this._cacheNetworkFee = networkFee - dummyBtcUtxoSize * this.feeRate;
294
+ this.removeLastInput();
295
+ this.selectBtcUtxos();
296
+ }
297
+ else {
298
+ if (forceAsFee) {
299
+ throw new error_1.WalletUtilsError(error_1.ErrorCodes.INSUFFICIENT_BTC_UTXO);
300
+ }
301
+ if (this.getTotalInput() < this.getTotalOutput()) {
302
+ throw new error_1.WalletUtilsError(error_1.ErrorCodes.INSUFFICIENT_BTC_UTXO);
303
+ }
304
+ this._cacheNetworkFee = yield this.calNetworkFee();
305
+ }
306
+ const changeAmount = this.getTotalInput() - this.getTotalOutput() - Math.ceil(this._cacheNetworkFee);
307
+ if (changeAmount > constants_1.UTXO_DUST) {
308
+ this.removeChangeOutput();
309
+ this.addChangeOutput(changeAmount);
310
+ }
311
+ else {
312
+ this.removeChangeOutput();
313
+ }
314
+ return this._cacheToSignInputs;
315
+ });
316
+ }
317
+ dumpTx(psbt) {
318
+ return __awaiter(this, void 0, void 0, function* () {
319
+ const tx = psbt.extractTransaction();
320
+ const feeRate = psbt.getFeeRate();
321
+ console.log(`
322
+ =============================================================================================
323
+ Summary
324
+ txid: ${tx.getId()}
325
+ Size: ${tx.byteLength()}
326
+ Fee Paid: ${psbt.getFee()}
327
+ Fee Rate: ${feeRate} sat/vB
328
+ Detail: ${psbt.txInputs.length} Inputs, ${psbt.txOutputs.length} Outputs
329
+ ----------------------------------------------------------------------------------------------
330
+ Inputs
331
+ ${this.inputs
332
+ .map((input, index) => {
333
+ const str = `
334
+ =>${index} ${input.data.witnessUtxo.value} Sats
335
+ lock-size: ${input.data.witnessUtxo.script.length}
336
+ via ${input.data.hash} [${input.data.index}]
337
+ `;
338
+ return str;
339
+ })
340
+ .join('')}
341
+ total: ${this.getTotalInput()} Sats
342
+ ----------------------------------------------------------------------------------------------
343
+ Outputs
344
+ ${this.outputs
345
+ .map((output, index) => {
346
+ const str = `
347
+ =>${index} ${output.address} ${output.value} Sats`;
348
+ return str;
349
+ })
350
+ .join('')}
351
+
352
+ total: ${this.getTotalOutput()} Sats
353
+ =============================================================================================
354
+ `);
355
+ });
356
+ }
357
+ }
358
+ exports.Transaction = Transaction;
@@ -0,0 +1,35 @@
1
+ import { NetworkType } from '../network';
2
+ import { AddressType, UnspentOutput } from '../types';
3
+ declare function hasInscription(utxos: UnspentOutput[]): boolean;
4
+ declare function hasAtomicalsFT(utxos: UnspentOutput[]): boolean;
5
+ declare function hasAtomicalsNFT(utxos: UnspentOutput[]): boolean;
6
+ declare function hasAtomicals(utxos: UnspentOutput[]): boolean;
7
+ declare function hasAnyAssets(utxos: UnspentOutput[]): boolean;
8
+ /**
9
+ * select utxos so that the total amount of utxos is greater than or equal to targetAmount
10
+ * return the selected utxos and the unselected utxos
11
+ * @param utxos
12
+ * @param targetAmount
13
+ */
14
+ declare function selectBtcUtxos(utxos: UnspentOutput[], targetAmount: number): {
15
+ selectedUtxos: UnspentOutput[];
16
+ remainingUtxos: UnspentOutput[];
17
+ };
18
+ /**
19
+ * return the added virtual size of the utxo
20
+ */
21
+ declare function getAddedVirtualSize(addressType: AddressType): number;
22
+ export declare function getUtxoDust(addressType: AddressType): 546 | 294 | 330;
23
+ export declare function getAddressUtxoDust(address: string, networkType?: NetworkType): number;
24
+ export declare const utxoHelper: {
25
+ hasAtomicalsFT: typeof hasAtomicalsFT;
26
+ hasAtomicalsNFT: typeof hasAtomicalsNFT;
27
+ hasAtomicals: typeof hasAtomicals;
28
+ hasInscription: typeof hasInscription;
29
+ hasAnyAssets: typeof hasAnyAssets;
30
+ selectBtcUtxos: typeof selectBtcUtxos;
31
+ getAddedVirtualSize: typeof getAddedVirtualSize;
32
+ getUtxoDust: typeof getUtxoDust;
33
+ getAddressUtxoDust: typeof getAddressUtxoDust;
34
+ };
35
+ export {};
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.utxoHelper = exports.getAddressUtxoDust = exports.getUtxoDust = void 0;
4
+ const address_1 = require("../address");
5
+ const network_1 = require("../network");
6
+ const types_1 = require("../types");
7
+ function hasInscription(utxos) {
8
+ if (utxos.find((v) => v.inscriptions.length > 0)) {
9
+ return true;
10
+ }
11
+ return false;
12
+ }
13
+ function hasAtomicalsFT(utxos) {
14
+ if (utxos.find((v) => v.atomicals.find((w) => w.type === 'FT'))) {
15
+ return true;
16
+ }
17
+ return false;
18
+ }
19
+ function hasAtomicalsNFT(utxos) {
20
+ if (utxos.find((v) => v.atomicals.find((w) => w.type === 'NFT'))) {
21
+ return true;
22
+ }
23
+ return false;
24
+ }
25
+ function hasAtomicals(utxos) {
26
+ if (utxos.find((v) => v.atomicals.length > 0)) {
27
+ return true;
28
+ }
29
+ return false;
30
+ }
31
+ function hasAnyAssets(utxos) {
32
+ if (utxos.find((v) => v.inscriptions.length > 0 || v.atomicals.length > 0)) {
33
+ return true;
34
+ }
35
+ return false;
36
+ }
37
+ /**
38
+ * select utxos so that the total amount of utxos is greater than or equal to targetAmount
39
+ * return the selected utxos and the unselected utxos
40
+ * @param utxos
41
+ * @param targetAmount
42
+ */
43
+ function selectBtcUtxos(utxos, targetAmount) {
44
+ let selectedUtxos = [];
45
+ let remainingUtxos = [];
46
+ let totalAmount = 0;
47
+ for (const utxo of utxos) {
48
+ if (totalAmount < targetAmount) {
49
+ totalAmount += utxo.satoshis;
50
+ selectedUtxos.push(utxo);
51
+ }
52
+ else {
53
+ remainingUtxos.push(utxo);
54
+ }
55
+ }
56
+ return {
57
+ selectedUtxos,
58
+ remainingUtxos
59
+ };
60
+ }
61
+ /**
62
+ * return the added virtual size of the utxo
63
+ */
64
+ function getAddedVirtualSize(addressType) {
65
+ if (addressType === types_1.AddressType.P2WPKH || addressType === types_1.AddressType.M44_P2WPKH) {
66
+ return 41 + (1 + 1 + 72 + 1 + 33) / 4;
67
+ }
68
+ else if (addressType === types_1.AddressType.P2TR || addressType === types_1.AddressType.M44_P2TR) {
69
+ return 41 + (1 + 1 + 64) / 4;
70
+ }
71
+ else if (addressType === types_1.AddressType.P2PKH) {
72
+ return 41 + 1 + 1 + 72 + 1 + 33;
73
+ }
74
+ else if (addressType === types_1.AddressType.P2SH_P2WPKH) {
75
+ return 41 + 24 + (1 + 1 + 72 + 1 + 33) / 4;
76
+ }
77
+ throw new Error('unknown address type');
78
+ }
79
+ function getUtxoDust(addressType) {
80
+ if (addressType === types_1.AddressType.P2WPKH || addressType === types_1.AddressType.M44_P2WPKH) {
81
+ return 294;
82
+ }
83
+ else if (addressType === types_1.AddressType.P2TR || addressType === types_1.AddressType.M44_P2TR) {
84
+ return 330;
85
+ }
86
+ else {
87
+ return 546;
88
+ }
89
+ }
90
+ exports.getUtxoDust = getUtxoDust;
91
+ // deprecated
92
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
93
+ function getAddressUtxoDust(address, networkType = network_1.NetworkType.MAINNET) {
94
+ return (0, address_1.decodeAddress)(address).dust;
95
+ }
96
+ exports.getAddressUtxoDust = getAddressUtxoDust;
97
+ exports.utxoHelper = {
98
+ hasAtomicalsFT,
99
+ hasAtomicalsNFT,
100
+ hasAtomicals,
101
+ hasInscription,
102
+ hasAnyAssets,
103
+ selectBtcUtxos,
104
+ getAddedVirtualSize,
105
+ getUtxoDust,
106
+ getAddressUtxoDust
107
+ };
@@ -0,0 +1,8 @@
1
+ import { sendAtomicalsFT } from './send-atomicals-ft';
2
+ import { sendAtomicalsNFT } from './send-atomicals-nft';
3
+ import { sendAllBTC, sendBTC } from './send-btc';
4
+ import { sendInscription } from './send-inscription';
5
+ import { sendInscriptions } from './send-inscriptions';
6
+ import { sendRunes } from './send-runes';
7
+ import { splitInscriptionUtxo } from './split-inscription-utxo';
8
+ export { sendAllBTC, sendAtomicalsFT, sendAtomicalsNFT, sendBTC, sendInscription, sendInscriptions, sendRunes, splitInscriptionUtxo };
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.splitInscriptionUtxo = exports.sendRunes = exports.sendInscriptions = exports.sendInscription = exports.sendBTC = exports.sendAtomicalsNFT = exports.sendAtomicalsFT = exports.sendAllBTC = void 0;
4
+ const send_atomicals_ft_1 = require("./send-atomicals-ft");
5
+ Object.defineProperty(exports, "sendAtomicalsFT", { enumerable: true, get: function () { return send_atomicals_ft_1.sendAtomicalsFT; } });
6
+ const send_atomicals_nft_1 = require("./send-atomicals-nft");
7
+ Object.defineProperty(exports, "sendAtomicalsNFT", { enumerable: true, get: function () { return send_atomicals_nft_1.sendAtomicalsNFT; } });
8
+ const send_btc_1 = require("./send-btc");
9
+ Object.defineProperty(exports, "sendAllBTC", { enumerable: true, get: function () { return send_btc_1.sendAllBTC; } });
10
+ Object.defineProperty(exports, "sendBTC", { enumerable: true, get: function () { return send_btc_1.sendBTC; } });
11
+ const send_inscription_1 = require("./send-inscription");
12
+ Object.defineProperty(exports, "sendInscription", { enumerable: true, get: function () { return send_inscription_1.sendInscription; } });
13
+ const send_inscriptions_1 = require("./send-inscriptions");
14
+ Object.defineProperty(exports, "sendInscriptions", { enumerable: true, get: function () { return send_inscriptions_1.sendInscriptions; } });
15
+ const send_runes_1 = require("./send-runes");
16
+ Object.defineProperty(exports, "sendRunes", { enumerable: true, get: function () { return send_runes_1.sendRunes; } });
17
+ const split_inscription_utxo_1 = require("./split-inscription-utxo");
18
+ Object.defineProperty(exports, "splitInscriptionUtxo", { enumerable: true, get: function () { return split_inscription_utxo_1.splitInscriptionUtxo; } });
@@ -0,0 +1,16 @@
1
+ import { NetworkType } from '../network';
2
+ import { ToSignInput, UnspentOutput } from '../types';
3
+ export declare function sendAtomicalsFT(params: {
4
+ assetUtxos: UnspentOutput[];
5
+ btcUtxos: UnspentOutput[];
6
+ toAddress: string;
7
+ networkType: NetworkType;
8
+ changeAssetAddress: string;
9
+ sendAmount: number;
10
+ changeAddress: string;
11
+ feeRate: number;
12
+ enableRBF?: boolean;
13
+ }): Promise<{
14
+ psbt: import("bitcoinjs-lib").Psbt;
15
+ toSignInputs: ToSignInput[];
16
+ }>;
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.sendAtomicalsFT = void 0;
13
+ const error_1 = require("../error");
14
+ const transaction_1 = require("../transaction");
15
+ // only one arc20 can be send
16
+ function sendAtomicalsFT(params) {
17
+ return __awaiter(this, void 0, void 0, function* () {
18
+ const { assetUtxos, btcUtxos, toAddress, networkType, changeAssetAddress, sendAmount, changeAddress, feeRate, enableRBF = true } = params;
19
+ // safe check
20
+ if (transaction_1.utxoHelper.hasAtomicalsNFT(assetUtxos) || transaction_1.utxoHelper.hasInscription(assetUtxos)) {
21
+ throw new error_1.WalletUtilsError(error_1.ErrorCodes.NOT_SAFE_UTXOS);
22
+ }
23
+ if (transaction_1.utxoHelper.hasAnyAssets(btcUtxos)) {
24
+ throw new error_1.WalletUtilsError(error_1.ErrorCodes.NOT_SAFE_UTXOS);
25
+ }
26
+ const tx = new transaction_1.Transaction();
27
+ tx.setNetworkType(networkType);
28
+ tx.setFeeRate(feeRate);
29
+ tx.setEnableRBF(enableRBF);
30
+ tx.setChangeAddress(changeAddress);
31
+ const toSignInputs = [];
32
+ let totalInputFTAmount = 0;
33
+ assetUtxos.forEach((v) => {
34
+ if (v.atomicals.length > 1) {
35
+ throw new error_1.WalletUtilsError(error_1.ErrorCodes.ONLY_ONE_ARC20_CAN_BE_SENT);
36
+ }
37
+ v.atomicals.forEach((w) => {
38
+ if (!w.atomicalValue) {
39
+ w.atomicalValue = v.satoshis;
40
+ }
41
+ totalInputFTAmount += w.atomicalValue;
42
+ });
43
+ });
44
+ if (sendAmount > totalInputFTAmount) {
45
+ throw new error_1.WalletUtilsError(error_1.ErrorCodes.INSUFFICIENT_ASSET_UTXO);
46
+ }
47
+ // add assets
48
+ assetUtxos.forEach((v, index) => {
49
+ tx.addInput(v);
50
+ toSignInputs.push({ index, publicKey: v.pubkey });
51
+ });
52
+ // add receiver
53
+ tx.addOutput(toAddress, sendAmount);
54
+ // add change
55
+ const changeArc20Amount = totalInputFTAmount - sendAmount;
56
+ if (changeArc20Amount > 0) {
57
+ tx.addOutput(changeAssetAddress, changeArc20Amount);
58
+ }
59
+ // add btc
60
+ const _toSignInputs = yield tx.addSufficientUtxosForFee(btcUtxos, true);
61
+ toSignInputs.push(..._toSignInputs);
62
+ const psbt = tx.toPsbt();
63
+ return { psbt, toSignInputs };
64
+ });
65
+ }
66
+ exports.sendAtomicalsFT = sendAtomicalsFT;
@@ -0,0 +1,14 @@
1
+ import { NetworkType } from '../network';
2
+ import { ToSignInput, UnspentOutput } from '../types';
3
+ export declare function sendAtomicalsNFT(params: {
4
+ assetUtxo: UnspentOutput;
5
+ btcUtxos: UnspentOutput[];
6
+ toAddress: string;
7
+ networkType: NetworkType;
8
+ changeAddress: string;
9
+ feeRate: number;
10
+ enableRBF?: boolean;
11
+ }): Promise<{
12
+ psbt: import("bitcoinjs-lib").Psbt;
13
+ toSignInputs: ToSignInput[];
14
+ }>;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.sendAtomicalsNFT = void 0;
13
+ const error_1 = require("../error");
14
+ const transaction_1 = require("../transaction");
15
+ function sendAtomicalsNFT(params) {
16
+ return __awaiter(this, void 0, void 0, function* () {
17
+ const { assetUtxo, btcUtxos, toAddress, networkType, changeAddress, feeRate, enableRBF = true } = params;
18
+ // safe check
19
+ if (transaction_1.utxoHelper.hasAtomicalsFT([assetUtxo]) || transaction_1.utxoHelper.hasInscription([assetUtxo])) {
20
+ throw new error_1.WalletUtilsError(error_1.ErrorCodes.NOT_SAFE_UTXOS);
21
+ }
22
+ if (transaction_1.utxoHelper.hasAnyAssets(btcUtxos)) {
23
+ throw new error_1.WalletUtilsError(error_1.ErrorCodes.NOT_SAFE_UTXOS);
24
+ }
25
+ if (assetUtxo.atomicals.length !== 1) {
26
+ throw new error_1.WalletUtilsError(error_1.ErrorCodes.NOT_SAFE_UTXOS);
27
+ }
28
+ const tx = new transaction_1.Transaction();
29
+ tx.setNetworkType(networkType);
30
+ tx.setFeeRate(feeRate);
31
+ tx.setEnableRBF(enableRBF);
32
+ tx.setChangeAddress(changeAddress);
33
+ const toSignInputs = [];
34
+ // add asset
35
+ tx.addInput(assetUtxo);
36
+ toSignInputs.push({ index: 0, publicKey: assetUtxo.pubkey });
37
+ tx.addOutput(toAddress, assetUtxo.satoshis);
38
+ // add btc
39
+ const _toSignInputs = yield tx.addSufficientUtxosForFee(btcUtxos, true);
40
+ toSignInputs.push(..._toSignInputs);
41
+ const psbt = tx.toPsbt();
42
+ return { psbt, toSignInputs };
43
+ });
44
+ }
45
+ exports.sendAtomicalsNFT = sendAtomicalsNFT;