otx-btc-wallet-connectors 0.1.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 (142) hide show
  1. package/README.md +554 -0
  2. package/dist/base-IAFq7sd8.d.mts +53 -0
  3. package/dist/base-IAFq7sd8.d.ts +53 -0
  4. package/dist/binance/index.d.mts +81 -0
  5. package/dist/binance/index.d.ts +81 -0
  6. package/dist/binance/index.js +13 -0
  7. package/dist/binance/index.js.map +1 -0
  8. package/dist/binance/index.mjs +4 -0
  9. package/dist/binance/index.mjs.map +1 -0
  10. package/dist/bitget/index.d.mts +84 -0
  11. package/dist/bitget/index.d.ts +84 -0
  12. package/dist/bitget/index.js +13 -0
  13. package/dist/bitget/index.js.map +1 -0
  14. package/dist/bitget/index.mjs +4 -0
  15. package/dist/bitget/index.mjs.map +1 -0
  16. package/dist/chunk-5Z5Q2Y75.mjs +91 -0
  17. package/dist/chunk-5Z5Q2Y75.mjs.map +1 -0
  18. package/dist/chunk-7KK2LZLZ.mjs +208 -0
  19. package/dist/chunk-7KK2LZLZ.mjs.map +1 -0
  20. package/dist/chunk-AW2JZIHR.mjs +753 -0
  21. package/dist/chunk-AW2JZIHR.mjs.map +1 -0
  22. package/dist/chunk-EIJOSZXZ.js +331 -0
  23. package/dist/chunk-EIJOSZXZ.js.map +1 -0
  24. package/dist/chunk-EQHR7P7G.js +541 -0
  25. package/dist/chunk-EQHR7P7G.js.map +1 -0
  26. package/dist/chunk-EWRXLZO4.mjs +539 -0
  27. package/dist/chunk-EWRXLZO4.mjs.map +1 -0
  28. package/dist/chunk-FISNQZZ7.js +802 -0
  29. package/dist/chunk-FISNQZZ7.js.map +1 -0
  30. package/dist/chunk-HL4WDMGS.js +200 -0
  31. package/dist/chunk-HL4WDMGS.js.map +1 -0
  32. package/dist/chunk-IPYWR76I.js +314 -0
  33. package/dist/chunk-IPYWR76I.js.map +1 -0
  34. package/dist/chunk-JYYNWR5G.js +142 -0
  35. package/dist/chunk-JYYNWR5G.js.map +1 -0
  36. package/dist/chunk-LNKTYZJM.js +701 -0
  37. package/dist/chunk-LNKTYZJM.js.map +1 -0
  38. package/dist/chunk-LVZMONQL.mjs +699 -0
  39. package/dist/chunk-LVZMONQL.mjs.map +1 -0
  40. package/dist/chunk-MFXLQWOE.js +93 -0
  41. package/dist/chunk-MFXLQWOE.js.map +1 -0
  42. package/dist/chunk-NBIA4TTE.mjs +204 -0
  43. package/dist/chunk-NBIA4TTE.mjs.map +1 -0
  44. package/dist/chunk-O4DD2XJ2.js +206 -0
  45. package/dist/chunk-O4DD2XJ2.js.map +1 -0
  46. package/dist/chunk-P7HVBU2B.mjs +140 -0
  47. package/dist/chunk-P7HVBU2B.mjs.map +1 -0
  48. package/dist/chunk-Q7QVQYEB.js +210 -0
  49. package/dist/chunk-Q7QVQYEB.js.map +1 -0
  50. package/dist/chunk-RLZEG6KL.mjs +329 -0
  51. package/dist/chunk-RLZEG6KL.mjs.map +1 -0
  52. package/dist/chunk-SYLDBJ75.mjs +246 -0
  53. package/dist/chunk-SYLDBJ75.mjs.map +1 -0
  54. package/dist/chunk-TTEUU3CI.mjs +198 -0
  55. package/dist/chunk-TTEUU3CI.mjs.map +1 -0
  56. package/dist/chunk-V66BXDTR.mjs +292 -0
  57. package/dist/chunk-V66BXDTR.mjs.map +1 -0
  58. package/dist/chunk-X77ZT4OI.js +268 -0
  59. package/dist/chunk-X77ZT4OI.js.map +1 -0
  60. package/dist/imtoken/index.d.mts +116 -0
  61. package/dist/imtoken/index.d.ts +116 -0
  62. package/dist/imtoken/index.js +14 -0
  63. package/dist/imtoken/index.js.map +1 -0
  64. package/dist/imtoken/index.mjs +5 -0
  65. package/dist/imtoken/index.mjs.map +1 -0
  66. package/dist/index.d.mts +14 -0
  67. package/dist/index.d.ts +14 -0
  68. package/dist/index.js +170 -0
  69. package/dist/index.js.map +1 -0
  70. package/dist/index.mjs +13 -0
  71. package/dist/index.mjs.map +1 -0
  72. package/dist/ledger/index.d.mts +290 -0
  73. package/dist/ledger/index.d.ts +290 -0
  74. package/dist/ledger/index.js +14 -0
  75. package/dist/ledger/index.js.map +1 -0
  76. package/dist/ledger/index.mjs +5 -0
  77. package/dist/ledger/index.mjs.map +1 -0
  78. package/dist/okx/index.d.mts +88 -0
  79. package/dist/okx/index.d.ts +88 -0
  80. package/dist/okx/index.js +13 -0
  81. package/dist/okx/index.js.map +1 -0
  82. package/dist/okx/index.mjs +4 -0
  83. package/dist/okx/index.mjs.map +1 -0
  84. package/dist/phantom/index.d.mts +96 -0
  85. package/dist/phantom/index.d.ts +96 -0
  86. package/dist/phantom/index.js +14 -0
  87. package/dist/phantom/index.js.map +1 -0
  88. package/dist/phantom/index.mjs +5 -0
  89. package/dist/phantom/index.mjs.map +1 -0
  90. package/dist/psbt-builder-CFOs69Z5.d.mts +131 -0
  91. package/dist/psbt-builder-CFOs69Z5.d.ts +131 -0
  92. package/dist/trezor/index.d.mts +155 -0
  93. package/dist/trezor/index.d.ts +155 -0
  94. package/dist/trezor/index.js +14 -0
  95. package/dist/trezor/index.js.map +1 -0
  96. package/dist/trezor/index.mjs +5 -0
  97. package/dist/trezor/index.mjs.map +1 -0
  98. package/dist/unisat/index.d.mts +75 -0
  99. package/dist/unisat/index.d.ts +75 -0
  100. package/dist/unisat/index.js +13 -0
  101. package/dist/unisat/index.js.map +1 -0
  102. package/dist/unisat/index.mjs +4 -0
  103. package/dist/unisat/index.mjs.map +1 -0
  104. package/dist/utils/index.d.mts +398 -0
  105. package/dist/utils/index.d.ts +398 -0
  106. package/dist/utils/index.js +120 -0
  107. package/dist/utils/index.js.map +1 -0
  108. package/dist/utils/index.mjs +3 -0
  109. package/dist/utils/index.mjs.map +1 -0
  110. package/dist/xverse/index.d.mts +79 -0
  111. package/dist/xverse/index.d.ts +79 -0
  112. package/dist/xverse/index.js +13 -0
  113. package/dist/xverse/index.js.map +1 -0
  114. package/dist/xverse/index.mjs +4 -0
  115. package/dist/xverse/index.mjs.map +1 -0
  116. package/package.json +108 -0
  117. package/src/base.ts +132 -0
  118. package/src/binance/BinanceConnector.ts +307 -0
  119. package/src/binance/index.ts +1 -0
  120. package/src/bitget/BitgetConnector.ts +301 -0
  121. package/src/bitget/index.ts +1 -0
  122. package/src/imtoken/ImTokenConnector.ts +420 -0
  123. package/src/imtoken/index.ts +2 -0
  124. package/src/index.ts +78 -0
  125. package/src/ledger/LedgerConnector.ts +1019 -0
  126. package/src/ledger/index.ts +8 -0
  127. package/src/okx/OKXConnector.ts +230 -0
  128. package/src/okx/index.ts +1 -0
  129. package/src/phantom/PhantomConnector.ts +381 -0
  130. package/src/phantom/index.ts +2 -0
  131. package/src/trezor/TrezorConnector.ts +824 -0
  132. package/src/trezor/index.ts +6 -0
  133. package/src/unisat/UnisatConnector.ts +312 -0
  134. package/src/unisat/index.ts +1 -0
  135. package/src/utils/blockstream.ts +230 -0
  136. package/src/utils/btc-service.ts +364 -0
  137. package/src/utils/index.ts +56 -0
  138. package/src/utils/mempool.ts +232 -0
  139. package/src/utils/psbt-builder.ts +492 -0
  140. package/src/utils/types.ts +183 -0
  141. package/src/xverse/XverseConnector.ts +479 -0
  142. package/src/xverse/index.ts +1 -0
@@ -0,0 +1,753 @@
1
+ import * as bitcoin from 'bitcoinjs-lib';
2
+
3
+ // src/utils/mempool.ts
4
+ var DEFAULT_MEMPOOL_ENDPOINTS = {
5
+ mainnet: "https://mempool.space/api",
6
+ testnet: "https://mempool.space/testnet/api",
7
+ testnet4: "https://mempool.space/testnet4/api",
8
+ signet: "https://mempool.space/signet/api"
9
+ };
10
+ async function fetchWithTimeout(url, options, timeout = 1e4) {
11
+ const controller = new AbortController();
12
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
13
+ try {
14
+ const response = await fetch(url, {
15
+ ...options,
16
+ signal: controller.signal
17
+ });
18
+ clearTimeout(timeoutId);
19
+ return response;
20
+ } catch (error) {
21
+ clearTimeout(timeoutId);
22
+ throw error;
23
+ }
24
+ }
25
+ var MempoolService = class {
26
+ constructor(network = "mainnet", customEndpoints) {
27
+ this.name = "mempool";
28
+ this._network = network;
29
+ this._customEndpoints = customEndpoints ?? {};
30
+ }
31
+ get network() {
32
+ return this._network;
33
+ }
34
+ get baseUrl() {
35
+ return this._customEndpoints[this._network] ?? DEFAULT_MEMPOOL_ENDPOINTS[this._network];
36
+ }
37
+ setNetwork(network) {
38
+ this._network = network;
39
+ }
40
+ /**
41
+ * Set custom endpoints for this service
42
+ */
43
+ setCustomEndpoints(endpoints) {
44
+ this._customEndpoints = { ...this._customEndpoints, ...endpoints };
45
+ }
46
+ /**
47
+ * Get current endpoints configuration
48
+ */
49
+ getEndpoints() {
50
+ return {
51
+ mainnet: this._customEndpoints.mainnet ?? DEFAULT_MEMPOOL_ENDPOINTS.mainnet,
52
+ testnet: this._customEndpoints.testnet ?? DEFAULT_MEMPOOL_ENDPOINTS.testnet,
53
+ testnet4: this._customEndpoints.testnet4 ?? DEFAULT_MEMPOOL_ENDPOINTS.testnet4,
54
+ signet: this._customEndpoints.signet ?? DEFAULT_MEMPOOL_ENDPOINTS.signet
55
+ };
56
+ }
57
+ // ============ UTXO Methods ============
58
+ async getUtxos(address2) {
59
+ const response = await fetchWithTimeout(`${this.baseUrl}/address/${address2}/utxo`);
60
+ if (!response.ok) {
61
+ throw new Error(`Mempool API error: ${response.status} ${response.statusText}`);
62
+ }
63
+ return response.json();
64
+ }
65
+ async getUtxosWithTxHex(address2) {
66
+ const utxos = await this.getUtxos(address2);
67
+ const utxosWithTx = await Promise.all(
68
+ utxos.map(async (utxo) => {
69
+ const txHex = await this.getTxHex(utxo.txid);
70
+ return { ...utxo, txHex };
71
+ })
72
+ );
73
+ return utxosWithTx;
74
+ }
75
+ // ============ Transaction Methods ============
76
+ async getTxHex(txid) {
77
+ const response = await fetchWithTimeout(`${this.baseUrl}/tx/${txid}/hex`);
78
+ if (!response.ok) {
79
+ throw new Error(`Mempool API error: ${response.status} ${response.statusText}`);
80
+ }
81
+ return response.text();
82
+ }
83
+ async getTransaction(txid) {
84
+ const response = await fetchWithTimeout(`${this.baseUrl}/tx/${txid}`);
85
+ if (!response.ok) {
86
+ throw new Error(`Mempool API error: ${response.status} ${response.statusText}`);
87
+ }
88
+ return response.json();
89
+ }
90
+ async getFullTransaction(txid) {
91
+ const response = await fetchWithTimeout(`${this.baseUrl}/tx/${txid}`);
92
+ if (!response.ok) {
93
+ throw new Error(`Mempool API error: ${response.status} ${response.statusText}`);
94
+ }
95
+ return response.json();
96
+ }
97
+ async broadcastTransaction(txHex) {
98
+ const response = await fetchWithTimeout(
99
+ `${this.baseUrl}/tx`,
100
+ {
101
+ method: "POST",
102
+ body: txHex,
103
+ headers: { "Content-Type": "text/plain" }
104
+ },
105
+ 3e4
106
+ );
107
+ if (!response.ok) {
108
+ const error = await response.text();
109
+ throw new Error(`Mempool broadcast error: ${error}`);
110
+ }
111
+ return response.text();
112
+ }
113
+ // ============ Address Methods ============
114
+ async getAddressInfo(address2) {
115
+ const response = await fetchWithTimeout(`${this.baseUrl}/address/${address2}`);
116
+ if (!response.ok) {
117
+ throw new Error(`Mempool API error: ${response.status} ${response.statusText}`);
118
+ }
119
+ return response.json();
120
+ }
121
+ async getBalance(address2) {
122
+ const info = await this.getAddressInfo(address2);
123
+ const confirmedBalance = info.chain_stats.funded_txo_sum - info.chain_stats.spent_txo_sum;
124
+ const unconfirmedBalance = info.mempool_stats.funded_txo_sum - info.mempool_stats.spent_txo_sum;
125
+ return confirmedBalance + unconfirmedBalance;
126
+ }
127
+ async getConfirmedBalance(address2) {
128
+ const info = await this.getAddressInfo(address2);
129
+ return info.chain_stats.funded_txo_sum - info.chain_stats.spent_txo_sum;
130
+ }
131
+ // ============ Fee Methods ============
132
+ async getFeeRates() {
133
+ const response = await fetchWithTimeout(`${this.baseUrl}/v1/fees/recommended`);
134
+ if (!response.ok) {
135
+ throw new Error(`Mempool API error: ${response.status} ${response.statusText}`);
136
+ }
137
+ const fees = await response.json();
138
+ return {
139
+ fastest: fees.fastestFee,
140
+ halfHour: fees.halfHourFee,
141
+ hour: fees.hourFee,
142
+ economy: fees.economyFee,
143
+ minimum: fees.minimumFee
144
+ };
145
+ }
146
+ };
147
+
148
+ // src/utils/blockstream.ts
149
+ var DEFAULT_BLOCKSTREAM_ENDPOINTS = {
150
+ mainnet: "https://blockstream.info/api",
151
+ testnet: "https://blockstream.info/testnet/api",
152
+ testnet4: "https://mempool.space/testnet4/api",
153
+ // Fallback to mempool
154
+ signet: "https://mempool.space/signet/api"
155
+ // Fallback to mempool
156
+ };
157
+ async function fetchWithTimeout2(url, options, timeout = 1e4) {
158
+ const controller = new AbortController();
159
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
160
+ try {
161
+ const response = await fetch(url, {
162
+ ...options,
163
+ signal: controller.signal
164
+ });
165
+ clearTimeout(timeoutId);
166
+ return response;
167
+ } catch (error) {
168
+ clearTimeout(timeoutId);
169
+ throw error;
170
+ }
171
+ }
172
+ var BlockstreamService = class {
173
+ constructor(network = "mainnet", customEndpoints) {
174
+ this.name = "blockstream";
175
+ this._network = network;
176
+ this._customEndpoints = customEndpoints ?? {};
177
+ }
178
+ get network() {
179
+ return this._network;
180
+ }
181
+ get baseUrl() {
182
+ return this._customEndpoints[this._network] ?? DEFAULT_BLOCKSTREAM_ENDPOINTS[this._network];
183
+ }
184
+ setNetwork(network) {
185
+ this._network = network;
186
+ }
187
+ /**
188
+ * Set custom endpoints for this service
189
+ */
190
+ setCustomEndpoints(endpoints) {
191
+ this._customEndpoints = { ...this._customEndpoints, ...endpoints };
192
+ }
193
+ /**
194
+ * Get current endpoints configuration
195
+ */
196
+ getEndpoints() {
197
+ return {
198
+ mainnet: this._customEndpoints.mainnet ?? DEFAULT_BLOCKSTREAM_ENDPOINTS.mainnet,
199
+ testnet: this._customEndpoints.testnet ?? DEFAULT_BLOCKSTREAM_ENDPOINTS.testnet,
200
+ testnet4: this._customEndpoints.testnet4 ?? DEFAULT_BLOCKSTREAM_ENDPOINTS.testnet4,
201
+ signet: this._customEndpoints.signet ?? DEFAULT_BLOCKSTREAM_ENDPOINTS.signet
202
+ };
203
+ }
204
+ // ============ UTXO Methods ============
205
+ async getUtxos(address2) {
206
+ const response = await fetchWithTimeout2(`${this.baseUrl}/address/${address2}/utxo`);
207
+ if (!response.ok) {
208
+ throw new Error(`Blockstream API error: ${response.status} ${response.statusText}`);
209
+ }
210
+ return response.json();
211
+ }
212
+ async getUtxosWithTxHex(address2) {
213
+ const utxos = await this.getUtxos(address2);
214
+ const utxosWithTx = await Promise.all(
215
+ utxos.map(async (utxo) => {
216
+ const txHex = await this.getTxHex(utxo.txid);
217
+ return { ...utxo, txHex };
218
+ })
219
+ );
220
+ return utxosWithTx;
221
+ }
222
+ // ============ Transaction Methods ============
223
+ async getTxHex(txid) {
224
+ const response = await fetchWithTimeout2(`${this.baseUrl}/tx/${txid}/hex`);
225
+ if (!response.ok) {
226
+ throw new Error(`Blockstream API error: ${response.status} ${response.statusText}`);
227
+ }
228
+ return response.text();
229
+ }
230
+ async getTransaction(txid) {
231
+ const response = await fetchWithTimeout2(`${this.baseUrl}/tx/${txid}`);
232
+ if (!response.ok) {
233
+ throw new Error(`Blockstream API error: ${response.status} ${response.statusText}`);
234
+ }
235
+ return response.json();
236
+ }
237
+ async getFullTransaction(txid) {
238
+ const response = await fetchWithTimeout2(`${this.baseUrl}/tx/${txid}`);
239
+ if (!response.ok) {
240
+ throw new Error(`Blockstream API error: ${response.status} ${response.statusText}`);
241
+ }
242
+ return response.json();
243
+ }
244
+ async broadcastTransaction(txHex) {
245
+ const response = await fetchWithTimeout2(
246
+ `${this.baseUrl}/tx`,
247
+ {
248
+ method: "POST",
249
+ body: txHex,
250
+ headers: { "Content-Type": "text/plain" }
251
+ },
252
+ 3e4
253
+ );
254
+ if (!response.ok) {
255
+ const error = await response.text();
256
+ throw new Error(`Blockstream broadcast error: ${error}`);
257
+ }
258
+ return response.text();
259
+ }
260
+ // ============ Address Methods ============
261
+ async getAddressInfo(address2) {
262
+ const response = await fetchWithTimeout2(`${this.baseUrl}/address/${address2}`);
263
+ if (!response.ok) {
264
+ throw new Error(`Blockstream API error: ${response.status} ${response.statusText}`);
265
+ }
266
+ return response.json();
267
+ }
268
+ async getBalance(address2) {
269
+ const info = await this.getAddressInfo(address2);
270
+ const confirmedBalance = info.chain_stats.funded_txo_sum - info.chain_stats.spent_txo_sum;
271
+ const unconfirmedBalance = info.mempool_stats.funded_txo_sum - info.mempool_stats.spent_txo_sum;
272
+ return confirmedBalance + unconfirmedBalance;
273
+ }
274
+ async getConfirmedBalance(address2) {
275
+ const info = await this.getAddressInfo(address2);
276
+ return info.chain_stats.funded_txo_sum - info.chain_stats.spent_txo_sum;
277
+ }
278
+ // ============ Fee Methods ============
279
+ async getFeeRates() {
280
+ const response = await fetchWithTimeout2(`${this.baseUrl}/fee-estimates`);
281
+ if (!response.ok) {
282
+ throw new Error(`Blockstream API error: ${response.status} ${response.statusText}`);
283
+ }
284
+ const fees = await response.json();
285
+ return {
286
+ fastest: Math.ceil(fees["1"] || fees["2"] || 10),
287
+ halfHour: Math.ceil(fees["3"] || fees["4"] || 8),
288
+ hour: Math.ceil(fees["6"] || fees["12"] || 5),
289
+ economy: Math.ceil(fees["144"] || fees["504"] || 2),
290
+ minimum: Math.ceil(fees["1008"] || 1)
291
+ };
292
+ }
293
+ };
294
+
295
+ // src/utils/btc-service.ts
296
+ var globalConfig = {};
297
+ function configureBtcService(config) {
298
+ globalConfig = config;
299
+ defaultService = null;
300
+ }
301
+ function getBtcServiceConfig() {
302
+ return { ...globalConfig };
303
+ }
304
+ function race(promises) {
305
+ return Promise.race(promises);
306
+ }
307
+ var BtcService = class {
308
+ constructor(network = "mainnet", config) {
309
+ this.name = "btc-service";
310
+ this._network = network;
311
+ this._config = { ...globalConfig, ...config };
312
+ this._mempool = new MempoolService(network, this._config.mempool);
313
+ this._blockstream = new BlockstreamService(network, this._config.blockstream);
314
+ }
315
+ get network() {
316
+ return this._network;
317
+ }
318
+ /**
319
+ * Get the underlying Mempool service for direct access
320
+ */
321
+ get mempool() {
322
+ return this._mempool;
323
+ }
324
+ /**
325
+ * Get the underlying Blockstream service for direct access
326
+ */
327
+ get blockstream() {
328
+ return this._blockstream;
329
+ }
330
+ /**
331
+ * Get current configuration
332
+ */
333
+ get config() {
334
+ return { ...this._config };
335
+ }
336
+ setNetwork(network) {
337
+ this._network = network;
338
+ this._mempool.setNetwork(network);
339
+ this._blockstream.setNetwork(network);
340
+ }
341
+ /**
342
+ * Update configuration
343
+ */
344
+ setConfig(config) {
345
+ this._config = { ...this._config, ...config };
346
+ if (config.mempool) {
347
+ this._mempool.setCustomEndpoints(config.mempool);
348
+ }
349
+ if (config.blockstream) {
350
+ this._blockstream.setCustomEndpoints(config.blockstream);
351
+ }
352
+ }
353
+ /**
354
+ * Execute method based on preferred provider setting
355
+ */
356
+ async executeWithProvider(mempoolFn, blockstreamFn) {
357
+ const provider = this._config.preferredProvider ?? "race";
358
+ switch (provider) {
359
+ case "mempool":
360
+ return mempoolFn();
361
+ case "blockstream":
362
+ return blockstreamFn();
363
+ case "race":
364
+ default:
365
+ return race([mempoolFn(), blockstreamFn()]);
366
+ }
367
+ }
368
+ // ============ UTXO Methods ============
369
+ async getUtxos(address2) {
370
+ return this.executeWithProvider(
371
+ () => this._mempool.getUtxos(address2),
372
+ () => this._blockstream.getUtxos(address2)
373
+ );
374
+ }
375
+ async getUtxosWithTxHex(address2) {
376
+ return this.executeWithProvider(
377
+ () => this._mempool.getUtxosWithTxHex(address2),
378
+ () => this._blockstream.getUtxosWithTxHex(address2)
379
+ );
380
+ }
381
+ // ============ Transaction Methods ============
382
+ async getTxHex(txid) {
383
+ return this.executeWithProvider(
384
+ () => this._mempool.getTxHex(txid),
385
+ () => this._blockstream.getTxHex(txid)
386
+ );
387
+ }
388
+ async getTransaction(txid) {
389
+ return this.executeWithProvider(
390
+ () => this._mempool.getTransaction(txid),
391
+ () => this._blockstream.getTransaction(txid)
392
+ );
393
+ }
394
+ async getFullTransaction(txid) {
395
+ return this.executeWithProvider(
396
+ () => this._mempool.getFullTransaction(txid),
397
+ () => this._blockstream.getFullTransaction(txid)
398
+ );
399
+ }
400
+ async broadcastTransaction(txHex) {
401
+ return this.executeWithProvider(
402
+ () => this._mempool.broadcastTransaction(txHex),
403
+ () => this._blockstream.broadcastTransaction(txHex)
404
+ );
405
+ }
406
+ // ============ Address Methods ============
407
+ async getAddressInfo(address2) {
408
+ return this.executeWithProvider(
409
+ () => this._mempool.getAddressInfo(address2),
410
+ () => this._blockstream.getAddressInfo(address2)
411
+ );
412
+ }
413
+ async getBalance(address2) {
414
+ return this.executeWithProvider(
415
+ () => this._mempool.getBalance(address2),
416
+ () => this._blockstream.getBalance(address2)
417
+ );
418
+ }
419
+ async getConfirmedBalance(address2) {
420
+ return this.executeWithProvider(
421
+ () => this._mempool.getConfirmedBalance(address2),
422
+ () => this._blockstream.getConfirmedBalance(address2)
423
+ );
424
+ }
425
+ // ============ Fee Methods ============
426
+ async getFeeRates() {
427
+ return this.executeWithProvider(
428
+ () => this._mempool.getFeeRates(),
429
+ () => this._blockstream.getFeeRates()
430
+ );
431
+ }
432
+ };
433
+ var defaultService = null;
434
+ function getDefaultService(network = "mainnet") {
435
+ if (!defaultService || defaultService.network !== network) {
436
+ defaultService = new BtcService(network);
437
+ }
438
+ return defaultService;
439
+ }
440
+ async function getUtxos(address2, network = "mainnet") {
441
+ return getDefaultService(network).getUtxos(address2);
442
+ }
443
+ async function getUtxosWithTxHex(address2, network = "mainnet") {
444
+ return getDefaultService(network).getUtxosWithTxHex(address2);
445
+ }
446
+ async function getTxHex(txid, network = "mainnet") {
447
+ return getDefaultService(network).getTxHex(txid);
448
+ }
449
+ async function getTransaction(txid, network = "mainnet") {
450
+ return getDefaultService(network).getTransaction(txid);
451
+ }
452
+ async function getFullTransaction(txid, network = "mainnet") {
453
+ return getDefaultService(network).getFullTransaction(txid);
454
+ }
455
+ async function broadcastTransaction(txHex, network = "mainnet") {
456
+ return getDefaultService(network).broadcastTransaction(txHex);
457
+ }
458
+ async function getAddressInfo(address2, network = "mainnet") {
459
+ return getDefaultService(network).getAddressInfo(address2);
460
+ }
461
+ async function getBalance(address2, network = "mainnet") {
462
+ return getDefaultService(network).getBalance(address2);
463
+ }
464
+ async function getConfirmedBalance(address2, network = "mainnet") {
465
+ return getDefaultService(network).getConfirmedBalance(address2);
466
+ }
467
+ async function getFeeRates(network = "mainnet") {
468
+ return getDefaultService(network).getFeeRates();
469
+ }
470
+ function hexToBytes(hex) {
471
+ const cleanHex = hex.replace(/^0x/, "");
472
+ const bytes = new Uint8Array(cleanHex.length / 2);
473
+ for (let i = 0; i < bytes.length; i++) {
474
+ bytes[i] = parseInt(cleanHex.substring(i * 2, i * 2 + 2), 16);
475
+ }
476
+ return bytes;
477
+ }
478
+ function bytesToHex(bytes) {
479
+ return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
480
+ }
481
+ function toXOnly(pubKey) {
482
+ return pubKey.subarray(1, 33);
483
+ }
484
+ function getAddressType(address2) {
485
+ if (address2.startsWith("bc1q") || address2.startsWith("tb1q")) {
486
+ return "segwit";
487
+ }
488
+ if (address2.startsWith("bc1p") || address2.startsWith("tb1p")) {
489
+ return "taproot";
490
+ }
491
+ if (address2.startsWith("3") || address2.startsWith("2")) {
492
+ return "nested-segwit";
493
+ }
494
+ return "legacy";
495
+ }
496
+ function getBitcoinJsNetwork(network) {
497
+ switch (network) {
498
+ case "mainnet":
499
+ return bitcoin.networks.bitcoin;
500
+ case "testnet":
501
+ case "testnet4":
502
+ case "signet":
503
+ return bitcoin.networks.testnet;
504
+ default:
505
+ return bitcoin.networks.bitcoin;
506
+ }
507
+ }
508
+ function getInputVBytes(addressType) {
509
+ switch (addressType) {
510
+ case "taproot":
511
+ return 58;
512
+ case "segwit":
513
+ return 68;
514
+ case "nested-segwit":
515
+ return 91;
516
+ default:
517
+ return 148;
518
+ }
519
+ }
520
+ function getOutputVBytes(addressType) {
521
+ switch (addressType) {
522
+ case "taproot":
523
+ return 43;
524
+ case "segwit":
525
+ return 31;
526
+ case "nested-segwit":
527
+ return 32;
528
+ default:
529
+ return 34;
530
+ }
531
+ }
532
+ function getDustThreshold(addressType) {
533
+ return addressType === "legacy" ? 546 : 294;
534
+ }
535
+ function selectUtxos(utxos, fromAddressType, toAddressType, amount, feeRate) {
536
+ const inputVBytes = getInputVBytes(fromAddressType);
537
+ const outputVBytes = getOutputVBytes(toAddressType);
538
+ const baseVBytes = 10.5;
539
+ const sortedUtxos = [...utxos].sort((a, b) => b.value - a.value);
540
+ const selectedUtxos = [];
541
+ let totalValue = 0;
542
+ for (const utxo of sortedUtxos) {
543
+ selectedUtxos.push(utxo);
544
+ totalValue += utxo.value;
545
+ const estimatedVBytes2 = baseVBytes + selectedUtxos.length * inputVBytes + 2 * outputVBytes;
546
+ const estimatedFee2 = Math.ceil(estimatedVBytes2 * feeRate);
547
+ if (totalValue >= amount + estimatedFee2) {
548
+ return { selectedUtxos, totalValue, estimatedFee: estimatedFee2 };
549
+ }
550
+ }
551
+ const estimatedVBytes = baseVBytes + selectedUtxos.length * inputVBytes + 2 * outputVBytes;
552
+ const estimatedFee = Math.ceil(estimatedVBytes * feeRate);
553
+ return { selectedUtxos, totalValue, estimatedFee };
554
+ }
555
+ async function generatePsbtForSend(toAddress, amount, fromAddress, publicKey, network, options) {
556
+ const btcService = new BtcService(network);
557
+ const btcNetwork = getBitcoinJsNetwork(network);
558
+ const allUtxos = await btcService.getUtxos(fromAddress);
559
+ const confirmedUtxos = allUtxos.filter(
560
+ (utxo) => utxo.status?.confirmed !== false
561
+ );
562
+ if (confirmedUtxos.length === 0) {
563
+ throw new Error("No confirmed UTXOs available for spending");
564
+ }
565
+ let feeRate = options?.feeRate;
566
+ if (!feeRate) {
567
+ const feeRates = await btcService.getFeeRates();
568
+ feeRate = feeRates.hour;
569
+ }
570
+ if (options?.feeRateMultiplier) {
571
+ feeRate = Math.ceil(feeRate * options.feeRateMultiplier);
572
+ }
573
+ const fromAddressType = getAddressType(fromAddress);
574
+ const toAddressType = getAddressType(toAddress);
575
+ const { selectedUtxos, totalValue, estimatedFee } = selectUtxos(
576
+ confirmedUtxos,
577
+ fromAddressType,
578
+ toAddressType,
579
+ amount,
580
+ feeRate
581
+ );
582
+ if (totalValue < amount + estimatedFee) {
583
+ throw new Error(
584
+ `Insufficient funds. Available: ${totalValue} sats, Required: ${amount + estimatedFee} sats (including fee)`
585
+ );
586
+ }
587
+ const dustThreshold = getDustThreshold(fromAddressType);
588
+ let changeAmount = totalValue - amount - estimatedFee;
589
+ if (changeAmount > 0 && changeAmount <= dustThreshold) {
590
+ changeAmount = 0;
591
+ }
592
+ const psbt = new bitcoin.Psbt({ network: btcNetwork });
593
+ const publicKeyBytes = hexToBytes(publicKey);
594
+ const inputsToSign = [];
595
+ for (let i = 0; i < selectedUtxos.length; i++) {
596
+ const utxo = selectedUtxos[i];
597
+ const script = bitcoin.address.toOutputScript(fromAddress, btcNetwork);
598
+ if (fromAddressType === "taproot") {
599
+ psbt.addInput({
600
+ hash: utxo.txid,
601
+ index: utxo.vout,
602
+ witnessUtxo: {
603
+ script,
604
+ value: BigInt(utxo.value)
605
+ },
606
+ tapInternalKey: toXOnly(publicKeyBytes)
607
+ });
608
+ } else if (fromAddressType === "segwit") {
609
+ psbt.addInput({
610
+ hash: utxo.txid,
611
+ index: utxo.vout,
612
+ witnessUtxo: {
613
+ script,
614
+ value: BigInt(utxo.value)
615
+ }
616
+ });
617
+ } else if (fromAddressType === "nested-segwit") {
618
+ const p2wpkh = bitcoin.payments.p2wpkh({
619
+ pubkey: publicKeyBytes,
620
+ network: btcNetwork
621
+ });
622
+ if (!p2wpkh.output) {
623
+ throw new Error("Failed to generate P2WPKH redeem script");
624
+ }
625
+ psbt.addInput({
626
+ hash: utxo.txid,
627
+ index: utxo.vout,
628
+ witnessUtxo: {
629
+ script,
630
+ value: BigInt(utxo.value)
631
+ },
632
+ redeemScript: p2wpkh.output
633
+ });
634
+ } else {
635
+ psbt.addInput({
636
+ hash: utxo.txid,
637
+ index: utxo.vout,
638
+ witnessUtxo: {
639
+ script,
640
+ value: BigInt(utxo.value)
641
+ }
642
+ });
643
+ }
644
+ inputsToSign.push({ address: fromAddress, index: i });
645
+ }
646
+ psbt.addOutput({
647
+ address: toAddress,
648
+ value: BigInt(amount)
649
+ });
650
+ if (changeAmount > 0) {
651
+ psbt.addOutput({
652
+ address: fromAddress,
653
+ value: BigInt(Math.floor(changeAmount))
654
+ });
655
+ }
656
+ return {
657
+ psbt,
658
+ psbtHex: psbt.toHex(),
659
+ psbtBase64: psbt.toBase64(),
660
+ btcNetwork,
661
+ selectedUtxos,
662
+ totalInputValue: totalValue,
663
+ estimatedFee,
664
+ changeAmount,
665
+ inputsToSign
666
+ };
667
+ }
668
+ function finalizeAllInputs(signedPsbt, inputCount) {
669
+ for (let i = 0; i < inputCount; i++) {
670
+ try {
671
+ signedPsbt.finalizeInput(i);
672
+ } catch (finalizeError) {
673
+ console.warn(
674
+ `Failed to finalize input ${i}, attempting alternative finalization:`,
675
+ finalizeError
676
+ );
677
+ try {
678
+ signedPsbt.finalizeInput(i, () => ({
679
+ finalScriptSig: void 0,
680
+ finalScriptWitness: void 0
681
+ }));
682
+ } catch {
683
+ console.warn(`Could not finalize input ${i}`);
684
+ }
685
+ }
686
+ }
687
+ }
688
+ async function finalizeAndBroadcast(signedPsbtHex, network, inputCount) {
689
+ const btcNetwork = getBitcoinJsNetwork(network);
690
+ const btcService = new BtcService(network);
691
+ const signedPsbt = bitcoin.Psbt.fromHex(signedPsbtHex, { network: btcNetwork });
692
+ finalizeAllInputs(signedPsbt, inputCount);
693
+ const tx = signedPsbt.extractTransaction();
694
+ const txHex = tx.toHex();
695
+ return await btcService.broadcastTransaction(txHex);
696
+ }
697
+ function deriveAddressFromPublicKey(publicKeyHex, addressType, network) {
698
+ const btcNetwork = getBitcoinJsNetwork(network);
699
+ const publicKeyBytes = hexToBytes(publicKeyHex);
700
+ switch (addressType) {
701
+ case "legacy": {
702
+ const p2pkh = bitcoin.payments.p2pkh({
703
+ pubkey: publicKeyBytes,
704
+ network: btcNetwork
705
+ });
706
+ if (!p2pkh.address) {
707
+ throw new Error("Failed to derive legacy address from public key");
708
+ }
709
+ return p2pkh.address;
710
+ }
711
+ case "nested-segwit": {
712
+ const p2wpkh = bitcoin.payments.p2wpkh({
713
+ pubkey: publicKeyBytes,
714
+ network: btcNetwork
715
+ });
716
+ const p2sh = bitcoin.payments.p2sh({
717
+ redeem: p2wpkh,
718
+ network: btcNetwork
719
+ });
720
+ if (!p2sh.address) {
721
+ throw new Error("Failed to derive nested-segwit address from public key");
722
+ }
723
+ return p2sh.address;
724
+ }
725
+ case "segwit": {
726
+ const p2wpkh = bitcoin.payments.p2wpkh({
727
+ pubkey: publicKeyBytes,
728
+ network: btcNetwork
729
+ });
730
+ if (!p2wpkh.address) {
731
+ throw new Error("Failed to derive segwit address from public key");
732
+ }
733
+ return p2wpkh.address;
734
+ }
735
+ case "taproot": {
736
+ const xOnlyPubKey = toXOnly(publicKeyBytes);
737
+ const p2tr = bitcoin.payments.p2tr({
738
+ internalPubkey: xOnlyPubKey,
739
+ network: btcNetwork
740
+ });
741
+ if (!p2tr.address) {
742
+ throw new Error("Failed to derive taproot address from public key");
743
+ }
744
+ return p2tr.address;
745
+ }
746
+ default:
747
+ throw new Error(`Unsupported address type: ${addressType}`);
748
+ }
749
+ }
750
+
751
+ export { BlockstreamService, BtcService, MempoolService, broadcastTransaction, bytesToHex, configureBtcService, deriveAddressFromPublicKey, finalizeAllInputs, finalizeAndBroadcast, generatePsbtForSend, getAddressInfo, getAddressType, getBalance, getBitcoinJsNetwork, getBtcServiceConfig, getConfirmedBalance, getDustThreshold, getFeeRates, getFullTransaction, getInputVBytes, getOutputVBytes, getTransaction, getTxHex, getUtxos, getUtxosWithTxHex, hexToBytes, selectUtxos, toXOnly };
752
+ //# sourceMappingURL=out.js.map
753
+ //# sourceMappingURL=chunk-AW2JZIHR.mjs.map