@dynamic-labs-sdk/bitcoin 0.23.2 → 0.23.3

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 (37) hide show
  1. package/dist/{addBitcoinInjectedWalletsExtension-DoK6Bz_8.cjs.js → addBitcoinInjectedWalletsExtension-CLSKGEnn.cjs.js} +36 -296
  2. package/dist/addBitcoinInjectedWalletsExtension-CLSKGEnn.cjs.js.map +1 -0
  3. package/dist/{addBitcoinInjectedWalletsExtension-Blf31mFB.esm.js → addBitcoinInjectedWalletsExtension-Cfb9iZNA.esm.js} +17 -217
  4. package/dist/addBitcoinInjectedWalletsExtension-Cfb9iZNA.esm.js.map +1 -0
  5. package/dist/addWaasBitcoinExtension-BGV8KNdF.esm.js +707 -0
  6. package/dist/addWaasBitcoinExtension-BGV8KNdF.esm.js.map +1 -0
  7. package/dist/addWaasBitcoinExtension-DsAO3xoD.cjs.js +758 -0
  8. package/dist/addWaasBitcoinExtension-DsAO3xoD.cjs.js.map +1 -0
  9. package/dist/bitcoinTransferAmount-ChA9XwDs.cjs.js +288 -0
  10. package/dist/bitcoinTransferAmount-ChA9XwDs.cjs.js.map +1 -0
  11. package/dist/bitcoinTransferAmount-DLbPaIMH.esm.js +222 -0
  12. package/dist/bitcoinTransferAmount-DLbPaIMH.esm.js.map +1 -0
  13. package/dist/index.cjs.js +13 -741
  14. package/dist/index.cjs.js.map +1 -1
  15. package/dist/index.esm.js +5 -704
  16. package/dist/index.esm.js.map +1 -1
  17. package/dist/injected.cjs.js +4 -3
  18. package/dist/injected.cjs.js.map +1 -1
  19. package/dist/injected.esm.js +2 -1
  20. package/dist/injected.esm.js.map +1 -1
  21. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  22. package/dist/utils/bitcoinExecuteSwapTransaction/bitcoinExecuteSwapTransaction.d.ts.map +1 -1
  23. package/dist/utils/convertPsbtToBase64/convertPsbtToBase64.d.ts +3 -0
  24. package/dist/utils/convertPsbtToBase64/convertPsbtToBase64.d.ts.map +1 -0
  25. package/dist/utils/convertPsbtToBase64/index.d.ts +2 -0
  26. package/dist/utils/convertPsbtToBase64/index.d.ts.map +1 -0
  27. package/dist/utils/isHexEncodedPsbt/index.d.ts +2 -0
  28. package/dist/utils/isHexEncodedPsbt/index.d.ts.map +1 -0
  29. package/dist/utils/isHexEncodedPsbt/isHexEncodedPsbt.d.ts +3 -0
  30. package/dist/utils/isHexEncodedPsbt/isHexEncodedPsbt.d.ts.map +1 -0
  31. package/dist/waas.cjs.js +41 -0
  32. package/dist/waas.cjs.js.map +1 -0
  33. package/dist/waas.esm.js +40 -0
  34. package/dist/waas.esm.js.map +1 -0
  35. package/package.json +4 -4
  36. package/dist/addBitcoinInjectedWalletsExtension-Blf31mFB.esm.js.map +0 -1
  37. package/dist/addBitcoinInjectedWalletsExtension-DoK6Bz_8.cjs.js.map +0 -1
@@ -0,0 +1,758 @@
1
+ //#region rolldown:runtime
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) {
13
+ __defProp(to, key, {
14
+ get: ((k) => from[k]).bind(null, key),
15
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
+ });
17
+ }
18
+ }
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
23
+ value: mod,
24
+ enumerable: true
25
+ }) : target, mod));
26
+
27
+ //#endregion
28
+ const require_bitcoinTransferAmount = require('./bitcoinTransferAmount-ChA9XwDs.cjs.js');
29
+ let _dynamic_labs_sdk_client_core = require("@dynamic-labs-sdk/client/core");
30
+ let _dynamic_labs_sdk_client = require("@dynamic-labs-sdk/client");
31
+ let _dynamic_labs_sdk_api_core = require("@dynamic-labs/sdk-api-core");
32
+ let bitcoinjs_lib = require("bitcoinjs-lib");
33
+ let _dynamic_labs_sdk_client_waas_core = require("@dynamic-labs-sdk/client/waas/core");
34
+ let _bitcoinerlab_secp256k1 = require("@bitcoinerlab/secp256k1");
35
+ _bitcoinerlab_secp256k1 = __toESM(_bitcoinerlab_secp256k1);
36
+ let ecpair = require("ecpair");
37
+
38
+ //#region src/errors/TransactionBroadcastFailedError.ts
39
+ var TransactionBroadcastFailedError = class extends _dynamic_labs_sdk_client.BaseError {
40
+ response;
41
+ constructor({ response }) {
42
+ super({
43
+ cause: null,
44
+ code: "transaction_broadcast_failed_error",
45
+ details: `Status: ${response.status} ${response.statusText}`,
46
+ docsUrl: null,
47
+ name: "TransactionBroadcastFailedError",
48
+ shortMessage: "Failed to broadcast transaction to mempool"
49
+ });
50
+ this.response = response;
51
+ }
52
+ };
53
+
54
+ //#endregion
55
+ //#region src/errors/TransactionRequiredError.ts
56
+ var TransactionRequiredError = class extends _dynamic_labs_sdk_client.BaseError {
57
+ constructor() {
58
+ super({
59
+ cause: null,
60
+ code: "transaction_required_error",
61
+ docsUrl: null,
62
+ name: "TransactionRequiredError",
63
+ shortMessage: "No transaction specified for broadcast"
64
+ });
65
+ }
66
+ };
67
+
68
+ //#endregion
69
+ //#region src/waas/constants.ts
70
+ /**
71
+ * Mempool.space API URL for mainnet
72
+ */
73
+ const MEMPOOL_API_URL = "https://mempool.space/api";
74
+ /**
75
+ * Number of satoshis per Bitcoin
76
+ */
77
+ const SATOSHIS_PER_BTC = 1e8;
78
+ /**
79
+ * Bitcoin's dust limit in satoshis
80
+ * Outputs below this value are considered "dust" and will be rejected by nodes
81
+ */
82
+ const DUST_LIMIT = 546;
83
+ /**
84
+ * Accurate vSize constants for Native SegWit (P2WPKH) transactions
85
+ * Used for precise fee estimation
86
+ */
87
+ const VSIZE_OVERHEAD = 10.5;
88
+ const VSIZE_INPUT_P2WPKH = 68;
89
+ const VSIZE_OUTPUT_P2WPKH = 31;
90
+ /**
91
+ * Minimum relay fee in satoshis
92
+ * Added to fee estimate to ensure transaction propagation
93
+ */
94
+ const MIN_RELAY_FEE = 111;
95
+ /**
96
+ * Conservative default fee estimate in satoshis
97
+ * Used as fallback when fee estimation fails
98
+ */
99
+ const DEFAULT_FEE_ESTIMATE = 1e3;
100
+ /**
101
+ * RBF (Replace-By-Fee) sequence number
102
+ * 0xfffffffd = 4294967293 (enables RBF, not final)
103
+ */
104
+ const RBF_SEQUENCE = 4294967293;
105
+
106
+ //#endregion
107
+ //#region src/waas/utils/broadcastTransaction/broadcastTransaction.ts
108
+ /**
109
+ * Sends a raw Bitcoin transaction to the mempool
110
+ *
111
+ * @param rawTransaction - The raw transaction in hex format
112
+ * @returns The transaction ID
113
+ * @throws {TransactionRequiredError} if no transaction is specified
114
+ * @throws {TransactionBroadcastFailedError} if broadcasting fails
115
+ * @not-instrumented
116
+ */
117
+ const broadcastTransaction = async (rawTransaction) => {
118
+ if (!rawTransaction) throw new TransactionRequiredError();
119
+ const response = await fetch(`${MEMPOOL_API_URL}/tx`, {
120
+ body: rawTransaction,
121
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
122
+ method: "POST"
123
+ });
124
+ if (!response.ok) throw new TransactionBroadcastFailedError({ response });
125
+ return response.text();
126
+ };
127
+
128
+ //#endregion
129
+ //#region src/errors/InsufficientFundsError.ts
130
+ var InsufficientFundsError = class extends _dynamic_labs_sdk_client.BaseError {
131
+ availableSatoshis;
132
+ requiredSatoshis;
133
+ constructor({ availableSatoshis, requiredSatoshis }) {
134
+ const availableBtc = availableSatoshis / SATOSHIS_PER_BTC;
135
+ const requiredBtc = requiredSatoshis / SATOSHIS_PER_BTC;
136
+ super({
137
+ cause: null,
138
+ code: "insufficient_funds_error",
139
+ details: `Available: ${availableBtc} BTC (${availableSatoshis} satoshis), Required: ${requiredBtc} BTC (${requiredSatoshis} satoshis)`,
140
+ docsUrl: null,
141
+ name: "InsufficientFundsError",
142
+ shortMessage: "Insufficient funds for transaction"
143
+ });
144
+ this.availableSatoshis = availableSatoshis;
145
+ this.requiredSatoshis = requiredSatoshis;
146
+ }
147
+ };
148
+
149
+ //#endregion
150
+ //#region src/errors/InvalidAmountError.ts
151
+ var InvalidAmountError = class extends _dynamic_labs_sdk_client.BaseError {
152
+ amountInSatoshis;
153
+ constructor({ amountInSatoshis, reason }) {
154
+ super({
155
+ cause: null,
156
+ code: "invalid_amount_error",
157
+ details: `Amount: ${amountInSatoshis} satoshis`,
158
+ docsUrl: null,
159
+ name: "InvalidAmountError",
160
+ shortMessage: reason
161
+ });
162
+ this.amountInSatoshis = amountInSatoshis;
163
+ }
164
+ };
165
+
166
+ //#endregion
167
+ //#region src/errors/NoUTXOsFoundError.ts
168
+ var NoUTXOsFoundError = class extends _dynamic_labs_sdk_client.BaseError {
169
+ address;
170
+ constructor({ address: address$1 }) {
171
+ super({
172
+ cause: null,
173
+ code: "no_utxos_found_error",
174
+ details: `Address: ${address$1}`,
175
+ docsUrl: null,
176
+ name: "NoUTXOsFoundError",
177
+ shortMessage: "No UTXOs found for this address"
178
+ });
179
+ this.address = address$1;
180
+ }
181
+ };
182
+
183
+ //#endregion
184
+ //#region src/errors/SegwitOutputScriptError.ts
185
+ var SegwitOutputScriptError = class extends _dynamic_labs_sdk_client.BaseError {
186
+ constructor() {
187
+ super({
188
+ cause: null,
189
+ code: "segwit_output_script_error",
190
+ docsUrl: null,
191
+ name: "SegwitOutputScriptError",
192
+ shortMessage: "Failed to create segwit output script"
193
+ });
194
+ }
195
+ };
196
+
197
+ //#endregion
198
+ //#region src/waas/utils/addInputsToPsbt/addInputsToPsbt.ts
199
+ /**
200
+ * Adds inputs to PSBT from selected UTXOs
201
+ *
202
+ * @param options.network - Bitcoin network configuration (mainnet or testnet)
203
+ * @param options.psbt - The PSBT instance to add inputs to
204
+ * @param options.publicKeyPair - Key pair containing the public key for witness script
205
+ * @param options.selectedUTXOs - Array of UTXOs to add as inputs
206
+ * @not-instrumented
207
+ */
208
+ const addInputsToPsbt = (options) => {
209
+ const { network, psbt, publicKeyPair, selectedUTXOs } = options;
210
+ for (const utxo of selectedUTXOs) {
211
+ const outputScript = bitcoinjs_lib.payments.p2wpkh({
212
+ network,
213
+ pubkey: publicKeyPair.publicKey
214
+ }).output;
215
+ if (!outputScript) throw new SegwitOutputScriptError();
216
+ const txidBuffer = new Uint8Array((0, _dynamic_labs_sdk_client_core.getBuffer)().from(utxo.txid, "hex").reverse());
217
+ psbt.addInput({
218
+ hash: txidBuffer,
219
+ index: utxo.vout,
220
+ sequence: RBF_SEQUENCE,
221
+ witnessUtxo: {
222
+ script: outputScript,
223
+ value: BigInt(utxo.value)
224
+ }
225
+ });
226
+ }
227
+ };
228
+
229
+ //#endregion
230
+ //#region src/waas/utils/addOutputsToPsbt/addOutputsToPsbt.ts
231
+ /**
232
+ * Adds outputs to PSBT (recipient and optionally change)
233
+ *
234
+ * @param options.accountAddress - The sender's address for receiving change
235
+ * @param options.amountInSatoshis - Amount to send to the recipient in satoshis
236
+ * @param options.changeAmount - Amount to return as change in satoshis
237
+ * @param options.hasChangeOutput - Whether to include a change output
238
+ * @param options.network - Bitcoin network configuration (mainnet or testnet)
239
+ * @param options.psbt - The PSBT instance to add outputs to
240
+ * @param options.recipientAddress - The recipient's Bitcoin address
241
+ * @not-instrumented
242
+ */
243
+ const addOutputsToPsbt = (options) => {
244
+ const { accountAddress, amountInSatoshis, changeAmount, hasChangeOutput, network, psbt, recipientAddress } = options;
245
+ if (amountInSatoshis < DUST_LIMIT) throw new InvalidAmountError({
246
+ amountInSatoshis,
247
+ reason: `Amount is below dust limit of ${DUST_LIMIT} satoshis (${DUST_LIMIT / SATOSHIS_PER_BTC} BTC)`
248
+ });
249
+ psbt.addOutput({
250
+ script: bitcoinjs_lib.address.toOutputScript(recipientAddress, network),
251
+ value: BigInt(amountInSatoshis)
252
+ });
253
+ if (hasChangeOutput) psbt.addOutput({
254
+ script: bitcoinjs_lib.address.toOutputScript(accountAddress, network),
255
+ value: BigInt(changeAmount)
256
+ });
257
+ };
258
+
259
+ //#endregion
260
+ //#region src/errors/FeeRecommendationsFetchError.ts
261
+ var FeeRecommendationsFetchError = class extends _dynamic_labs_sdk_client.BaseError {
262
+ response;
263
+ constructor({ response }) {
264
+ super({
265
+ cause: null,
266
+ code: "fee_recommendations_fetch_error",
267
+ details: `Status: ${response.status} ${response.statusText}`,
268
+ docsUrl: null,
269
+ name: "FeeRecommendationsFetchError",
270
+ shortMessage: "Failed to fetch fee recommendations from mempool"
271
+ });
272
+ this.response = response;
273
+ }
274
+ };
275
+
276
+ //#endregion
277
+ //#region src/waas/utils/getFeeRecommendations/getFeeRecommendations.ts
278
+ /**
279
+ * Gets fee recommendations from mempool.space API
280
+ *
281
+ * @returns Fee recommendation data with rates in sat/vB
282
+ * @throws FeeRecommendationsFetchError if fetching fee recommendations fails
283
+ * @not-instrumented
284
+ */
285
+ const getFeeRecommendations = async () => {
286
+ const response = await fetch(`${MEMPOOL_API_URL}/v1/fees/recommended`);
287
+ if (!response.ok) throw new FeeRecommendationsFetchError({ response });
288
+ return response.json();
289
+ };
290
+
291
+ //#endregion
292
+ //#region src/waas/utils/estimateTransactionFee/estimateTransactionFee.ts
293
+ /**
294
+ * Estimates transaction fees based on number of inputs and outputs using accurate vSize
295
+ *
296
+ * @param options.feePriority - Priority level for fee estimation ('low', 'medium', or 'high')
297
+ * @param options.numInputs - Number of transaction inputs (UTXOs being spent)
298
+ * @param options.numOutputs - Number of transaction outputs
299
+ * @returns Estimated fee in satoshis
300
+ * @not-instrumented
301
+ */
302
+ const estimateTransactionFee = async ({ feePriority = "medium", numInputs, numOutputs }) => {
303
+ try {
304
+ const feeData = await getFeeRecommendations();
305
+ let feePerByte;
306
+ if (feePriority === "high") feePerByte = feeData.fastestFee ?? feeData.halfHourFee ?? 1;
307
+ else if (feePriority === "low") feePerByte = feeData.economyFee ?? feeData.hourFee ?? 1;
308
+ else feePerByte = feeData.halfHourFee ?? feeData.hourFee ?? feeData.economyFee ?? 1;
309
+ const vSize = VSIZE_OVERHEAD + numInputs * VSIZE_INPUT_P2WPKH + numOutputs * VSIZE_OUTPUT_P2WPKH;
310
+ return Math.ceil(feePerByte * vSize) + MIN_RELAY_FEE;
311
+ } catch {
312
+ return DEFAULT_FEE_ESTIMATE;
313
+ }
314
+ };
315
+
316
+ //#endregion
317
+ //#region src/waas/utils/calculateFeeAndChange/calculateFeeAndChange.ts
318
+ /**
319
+ * Calculates fee estimate and change amount, handling dust limit
320
+ *
321
+ * @param options.amountInSatoshis - Amount to send in satoshis
322
+ * @param options.feePriority - Priority level for fee estimation ('low', 'medium', or 'high')
323
+ * @param options.selectedTotalValue - Total value of selected UTXOs in satoshis
324
+ * @param options.selectedUTXOs - Array of selected UTXOs for the transaction
325
+ * @returns Object with feeEstimate, changeAmountNumber, and hasChangeOutput
326
+ * @not-instrumented
327
+ */
328
+ const calculateFeeAndChange = async ({ amountInSatoshis, feePriority, selectedTotalValue, selectedUTXOs }) => {
329
+ let feeEstimate = await estimateTransactionFee({
330
+ feePriority,
331
+ numInputs: selectedUTXOs.length,
332
+ numOutputs: 1
333
+ });
334
+ let maxToSpend = selectedTotalValue - feeEstimate;
335
+ let changeAmount = BigInt(maxToSpend) - amountInSatoshis;
336
+ if (changeAmount > 0 && Number(changeAmount) >= DUST_LIMIT) {
337
+ feeEstimate = await estimateTransactionFee({
338
+ feePriority,
339
+ numInputs: selectedUTXOs.length,
340
+ numOutputs: 2
341
+ });
342
+ maxToSpend = selectedTotalValue - feeEstimate;
343
+ changeAmount = BigInt(maxToSpend) - amountInSatoshis;
344
+ }
345
+ const finalChangeAmountNumber = Number(changeAmount);
346
+ const hasChangeOutput = changeAmount > 0 && finalChangeAmountNumber >= DUST_LIMIT;
347
+ if (changeAmount > 0 && finalChangeAmountNumber < DUST_LIMIT) feeEstimate += finalChangeAmountNumber;
348
+ return {
349
+ changeAmountNumber: finalChangeAmountNumber,
350
+ feeEstimate,
351
+ hasChangeOutput
352
+ };
353
+ };
354
+
355
+ //#endregion
356
+ //#region src/waas/utils/calculateUTXOTotal/calculateUTXOTotal.ts
357
+ /**
358
+ * Calculates the total value of UTXOs
359
+ *
360
+ * @param utxos - Array of UTXOs
361
+ * @returns Total value in satoshis
362
+ * @not-instrumented
363
+ */
364
+ const calculateUTXOTotal = (utxos) => utxos.reduce((total, utxo) => total + utxo.value, 0);
365
+
366
+ //#endregion
367
+ //#region src/errors/UTXOsFetchError.ts
368
+ var UTXOsFetchError = class extends _dynamic_labs_sdk_client.BaseError {
369
+ address;
370
+ response;
371
+ constructor({ address: address$1, response }) {
372
+ super({
373
+ cause: null,
374
+ code: "utxos_fetch_error",
375
+ details: `Address: ${address$1}, Status: ${response.status} ${response.statusText}`,
376
+ docsUrl: null,
377
+ name: "UTXOsFetchError",
378
+ shortMessage: "Failed to fetch UTXOs from mempool"
379
+ });
380
+ this.address = address$1;
381
+ this.response = response;
382
+ }
383
+ };
384
+
385
+ //#endregion
386
+ //#region src/waas/utils/getUTXOs/getUTXOs.ts
387
+ /**
388
+ * Gets UTXOs for a Bitcoin address from mempool.space API
389
+ *
390
+ * @param address - The Bitcoin address to get UTXOs for
391
+ * @returns Array of UTXOs
392
+ * @throws UTXOsFetchError if fetching UTXOs fails
393
+ * @not-instrumented
394
+ */
395
+ const getUTXOs = async (address$1) => {
396
+ const response = await fetch(`${MEMPOOL_API_URL}/address/${address$1}/utxo`);
397
+ if (!response.ok) throw new UTXOsFetchError({
398
+ address: address$1,
399
+ response
400
+ });
401
+ return response.json();
402
+ };
403
+
404
+ //#endregion
405
+ //#region src/waas/utils/selectUTXOsLargestFirst/selectUTXOsLargestFirst.ts
406
+ /**
407
+ * Selects UTXOs using Largest-First (Accumulator) strategy
408
+ * Sorts UTXOs by value (descending) and selects until we have enough to cover amount + fees
409
+ *
410
+ * @param options.targetAmount - Target amount in satoshis (amount + fees + dust limit)
411
+ * @param options.utxos - Array of available UTXOs to select from
412
+ * @returns Selected UTXOs
413
+ * @not-instrumented
414
+ */
415
+ const selectUTXOsLargestFirst = (options) => {
416
+ const { targetAmount, utxos } = options;
417
+ const sortedUTXOs = [...utxos].sort((a, b) => b.value - a.value);
418
+ const selected = [];
419
+ let total = 0;
420
+ for (const utxo of sortedUTXOs) {
421
+ selected.push(utxo);
422
+ total += utxo.value;
423
+ if (total >= targetAmount) break;
424
+ }
425
+ return selected;
426
+ };
427
+
428
+ //#endregion
429
+ //#region src/waas/utils/validateAndSelectUTXOs/validateAndSelectUTXOs.ts
430
+ /**
431
+ * Validates and ensures sufficient funds for the transaction
432
+ *
433
+ * @param options.allUTXOs - Complete array of available UTXOs for the address
434
+ * @param options.amountInSatoshis - Amount to send in satoshis
435
+ * @param options.feeEstimate - Estimated transaction fee in satoshis
436
+ * @param options.selectedTotal - Total value of initially selected UTXOs in satoshis
437
+ * @param options.selectedUTXOs - Array of initially selected UTXOs
438
+ * @returns Validated selected UTXOs
439
+ * @throws InsufficientFundsError if insufficient funds
440
+ * @not-instrumented
441
+ */
442
+ const validateAndSelectUTXOs = (options) => {
443
+ const { allUTXOs, amountInSatoshis, feeEstimate, selectedTotal, selectedUTXOs } = options;
444
+ const requiredAmount = amountInSatoshis + feeEstimate;
445
+ if (selectedTotal >= requiredAmount) return selectedUTXOs;
446
+ if (selectedUTXOs.length < allUTXOs.length) {
447
+ const allTotal = calculateUTXOTotal(allUTXOs);
448
+ if (allTotal < requiredAmount) throw new InsufficientFundsError({
449
+ availableSatoshis: allTotal,
450
+ requiredSatoshis: amountInSatoshis
451
+ });
452
+ return allUTXOs;
453
+ }
454
+ throw new InsufficientFundsError({
455
+ availableSatoshis: selectedTotal,
456
+ requiredSatoshis: amountInSatoshis
457
+ });
458
+ };
459
+
460
+ //#endregion
461
+ //#region src/errors/TaprootAddressNotSupportedError.ts
462
+ var TaprootAddressNotSupportedError = class extends _dynamic_labs_sdk_client.BaseError {
463
+ constructor() {
464
+ super({
465
+ cause: null,
466
+ code: "taproot_address_not_supported",
467
+ docsUrl: null,
468
+ name: "TaprootAddressNotSupportedError",
469
+ shortMessage: "Taproot addresses are not supported for PSBT building. Only Native SegWit (P2WPKH) addresses are allowed."
470
+ });
471
+ }
472
+ };
473
+
474
+ //#endregion
475
+ //#region src/waas/utils/validateNotTaproot/validateNotTaproot.ts
476
+ /**
477
+ * Validates that the address is not a Taproot address
478
+ * Only Native SegWit (P2WPKH) is supported for PSBT building
479
+ *
480
+ * @param accountAddress - The account address to check
481
+ * @throws TaprootAddressNotSupportedError if address is Taproot
482
+ * @not-instrumented
483
+ */
484
+ const validateNotTaproot = (accountAddress) => {
485
+ if (accountAddress.toLowerCase().startsWith("bc1p") || accountAddress.toLowerCase().startsWith("tb1p")) throw new TaprootAddressNotSupportedError();
486
+ };
487
+
488
+ //#endregion
489
+ //#region src/waas/utils/buildPsbt/buildPsbt.ts
490
+ /**
491
+ * Builds a PSBT for a Bitcoin transaction with real UTXOs
492
+ * Uses Largest-First UTXO selection strategy with accurate vSize fee estimation
493
+ *
494
+ * @param options.accountAddress - The sender's Bitcoin address
495
+ * @param options.amountInSatoshis - Amount to send in satoshis
496
+ * @param options.feePriority - Priority level for fee estimation ('low', 'medium', or 'high')
497
+ * @param options.network - Bitcoin network configuration (mainnet or testnet)
498
+ * @param options.publicKeyHex - The sender's public key in hexadecimal format
499
+ * @param options.recipientAddress - The recipient's Bitcoin address
500
+ * @returns A PSBT in Base64 format
501
+ * @throws Error if insufficient funds, no UTXOs, or other errors
502
+ * @not-instrumented
503
+ */
504
+ const buildPsbt = async ({ accountAddress, amountInSatoshis, feePriority = "medium", network, publicKeyHex, recipientAddress }) => {
505
+ if (amountInSatoshis <= BigInt(0)) throw new InvalidAmountError({
506
+ amountInSatoshis: Number(amountInSatoshis),
507
+ reason: "Amount must be greater than 0"
508
+ });
509
+ validateNotTaproot(accountAddress);
510
+ const allUTXOs = await getUTXOs(accountAddress);
511
+ if (allUTXOs.length === 0) throw new NoUTXOsFoundError({ address: accountAddress });
512
+ const publicKeyBuffer = new Uint8Array((0, _dynamic_labs_sdk_client_core.getBuffer)().from(publicKeyHex, "hex"));
513
+ const publicKeyPair = (0, ecpair.ECPairFactory)(_bitcoinerlab_secp256k1.default).fromPublicKey(publicKeyBuffer, { compressed: true });
514
+ const amountInSatoshisNumber = Number(amountInSatoshis);
515
+ const initialFeeEstimate = await estimateTransactionFee({
516
+ feePriority,
517
+ numInputs: 1,
518
+ numOutputs: 1
519
+ });
520
+ let selectedUTXOs = selectUTXOsLargestFirst({
521
+ targetAmount: amountInSatoshisNumber + initialFeeEstimate + DUST_LIMIT,
522
+ utxos: allUTXOs
523
+ });
524
+ selectedUTXOs = validateAndSelectUTXOs({
525
+ allUTXOs,
526
+ amountInSatoshis: amountInSatoshisNumber,
527
+ feeEstimate: initialFeeEstimate,
528
+ selectedTotal: calculateUTXOTotal(selectedUTXOs),
529
+ selectedUTXOs
530
+ });
531
+ const selectedTotalValue = calculateUTXOTotal(selectedUTXOs);
532
+ const { changeAmountNumber, feeEstimate, hasChangeOutput } = await calculateFeeAndChange({
533
+ amountInSatoshis,
534
+ feePriority,
535
+ selectedTotalValue,
536
+ selectedUTXOs
537
+ });
538
+ const maxToSpend = selectedTotalValue - feeEstimate;
539
+ if (maxToSpend < amountInSatoshisNumber) throw new InsufficientFundsError({
540
+ availableSatoshis: maxToSpend,
541
+ requiredSatoshis: amountInSatoshisNumber
542
+ });
543
+ const psbt = new bitcoinjs_lib.Psbt({ network });
544
+ addInputsToPsbt({
545
+ network,
546
+ psbt,
547
+ publicKeyPair,
548
+ selectedUTXOs
549
+ });
550
+ addOutputsToPsbt({
551
+ accountAddress,
552
+ amountInSatoshis: amountInSatoshisNumber,
553
+ changeAmount: changeAmountNumber,
554
+ hasChangeOutput,
555
+ network,
556
+ psbt,
557
+ recipientAddress
558
+ });
559
+ return psbt.toBase64();
560
+ };
561
+
562
+ //#endregion
563
+ //#region src/errors/PublicKeyNotFoundError.ts
564
+ var PublicKeyNotFoundError = class extends _dynamic_labs_sdk_client.BaseError {
565
+ constructor(address$1) {
566
+ super({
567
+ cause: null,
568
+ code: "public_key_not_found_error",
569
+ docsUrl: null,
570
+ name: "PublicKeyNotFoundError",
571
+ shortMessage: `No public key found for address ${address$1}`
572
+ });
573
+ }
574
+ };
575
+
576
+ //#endregion
577
+ //#region src/waas/utils/getPublicKeyForWalletAccount/getPublicKeyForWalletAccount.ts
578
+ /**
579
+ * Gets the public key for a wallet account from the user's verified credentials
580
+ * @not-instrumented
581
+ */
582
+ const getPublicKeyForWalletAccount = (walletAccount, client) => {
583
+ const user = (0, _dynamic_labs_sdk_client_core.getCore)(client).state.get().user;
584
+ for (const credential of user?.verifiedCredentials ?? []) {
585
+ const additionalAddress = credential.walletAdditionalAddresses?.find((addr) => addr.address === walletAccount.address);
586
+ if (additionalAddress?.publicKey) return additionalAddress.publicKey;
587
+ }
588
+ throw new PublicKeyNotFoundError(walletAccount.address);
589
+ };
590
+
591
+ //#endregion
592
+ //#region src/waas/utils/createWalletProviderForWaasBitcoin/createWalletProviderForWaasBitcoin.ts
593
+ /** @not-instrumented */
594
+ const createWalletProviderForWaasBitcoin = (sdkClient) => {
595
+ const chain = "BTC";
596
+ const walletProviderType = _dynamic_labs_sdk_api_core.WalletProviderEnum.EmbeddedWallet;
597
+ const key = (0, _dynamic_labs_sdk_client_core.formatWalletProviderKey)({
598
+ chain,
599
+ displayName: _dynamic_labs_sdk_client_waas_core.DYNAMIC_WAAS_METADATA.displayName,
600
+ walletProviderType
601
+ });
602
+ const waasProvider = (0, _dynamic_labs_sdk_client_waas_core.createWaasProvider)({
603
+ chain,
604
+ sdkClient
605
+ });
606
+ const getActiveNetworkId = async () => (0, _dynamic_labs_sdk_client_core.getActiveNetworkIdFromLastKnownRegistry)({
607
+ client: sdkClient,
608
+ walletProviderKey: key
609
+ });
610
+ const switchActiveNetwork = async ({ networkId }) => (0, _dynamic_labs_sdk_client_core.switchActiveNetworkInLastKnownRegistry)({
611
+ client: sdkClient,
612
+ networkId,
613
+ walletProviderKey: key
614
+ });
615
+ const getConnectedAddresses = async () => {
616
+ return { addresses: (0, _dynamic_labs_sdk_client_waas_core.getAllUserWaasAddressesForChain)({ chain }, sdkClient) };
617
+ };
618
+ const signPsbt = async ({ request, walletAccount }) => {
619
+ (0, _dynamic_labs_sdk_client_core.assertDefined)(walletAccount, "Wallet account is required");
620
+ const waasClient = await waasProvider.getWaasClient();
621
+ const { signature: signedSessionId } = await (0, _dynamic_labs_sdk_client_core.getSignedSessionId)(sdkClient);
622
+ const mfaToken = await (0, _dynamic_labs_sdk_client_core.consumeMfaTokenIfRequiredForAction)({ mfaAction: _dynamic_labs_sdk_api_core.MFAAction.WalletWaasSign }, sdkClient);
623
+ return { signedPsbt: await waasClient.signTransaction({
624
+ authToken: sdkClient.token ?? void 0,
625
+ mfaToken,
626
+ senderAddress: walletAccount.address,
627
+ signedSessionId,
628
+ transaction: request.unsignedPsbtBase64
629
+ }) };
630
+ };
631
+ const signPsbts = async ({ requests, walletAccount }) => {
632
+ (0, _dynamic_labs_sdk_client_core.assertDefined)(walletAccount, "Wallet account is required");
633
+ return { signedPsbts: await Promise.all(requests.map(async (request) => {
634
+ const { signedPsbt } = await signPsbt({
635
+ request,
636
+ walletAccount
637
+ });
638
+ return signedPsbt;
639
+ })) };
640
+ };
641
+ const signMessage = async ({ message, walletAccount }) => {
642
+ (0, _dynamic_labs_sdk_client_core.assertDefined)(walletAccount, "Wallet account is required");
643
+ const waasClient = await waasProvider.getWaasClient();
644
+ const { signature: signedSessionId } = await (0, _dynamic_labs_sdk_client_core.getSignedSessionId)(sdkClient);
645
+ const mfaToken = await (0, _dynamic_labs_sdk_client_core.consumeMfaTokenIfRequiredForAction)({ mfaAction: _dynamic_labs_sdk_api_core.MFAAction.WalletWaasSign }, sdkClient);
646
+ return { signature: await waasClient.signMessage({
647
+ accountAddress: walletAccount.address,
648
+ authToken: sdkClient.token ?? void 0,
649
+ bitcoinConfig: { network: "mainnet" },
650
+ message,
651
+ mfaToken,
652
+ signedSessionId
653
+ }) };
654
+ };
655
+ const buildPsbt$1 = async ({ transaction, walletAccount }) => {
656
+ (0, _dynamic_labs_sdk_client_core.assertDefined)(walletAccount, "Wallet account is required");
657
+ const publicKeyHex = getPublicKeyForWalletAccount(walletAccount, sdkClient);
658
+ return buildPsbt({
659
+ accountAddress: walletAccount.address,
660
+ amountInSatoshis: transaction.amount,
661
+ feePriority: transaction.feePriority ?? "medium",
662
+ network: bitcoinjs_lib.networks.bitcoin,
663
+ publicKeyHex,
664
+ recipientAddress: transaction.recipientAddress
665
+ });
666
+ };
667
+ const sendBitcoin = async ({ transaction, walletAccount }) => {
668
+ (0, _dynamic_labs_sdk_client_core.assertDefined)(walletAccount, "Wallet account is required");
669
+ const { signedPsbt } = await signPsbt({
670
+ request: {
671
+ allowedSighash: [],
672
+ unsignedPsbtBase64: await buildPsbt$1({
673
+ transaction: {
674
+ amount: transaction.amount,
675
+ recipientAddress: transaction.recipientAddress
676
+ },
677
+ walletAccount
678
+ })
679
+ },
680
+ walletAccount
681
+ });
682
+ const psbt = bitcoinjs_lib.Psbt.fromBase64(signedPsbt, { network: bitcoinjs_lib.networks.bitcoin });
683
+ psbt.finalizeAllInputs();
684
+ return { transactionId: await broadcastTransaction(psbt.extractTransaction().toHex()) };
685
+ };
686
+ return {
687
+ ...waasProvider,
688
+ buildPsbt: buildPsbt$1,
689
+ chain,
690
+ executeSwapTransaction: (args) => require_bitcoinTransferAmount.bitcoinExecuteSwapTransaction(args, sdkClient),
691
+ getActiveNetworkId,
692
+ getConnectedAddresses,
693
+ groupKey: (0, _dynamic_labs_sdk_client_core.formatWalletProviderGroupKey)(_dynamic_labs_sdk_client_waas_core.DYNAMIC_WAAS_METADATA.displayName),
694
+ key,
695
+ metadata: {
696
+ displayName: _dynamic_labs_sdk_client_waas_core.DYNAMIC_WAAS_METADATA.displayName,
697
+ icon: _dynamic_labs_sdk_client_waas_core.DYNAMIC_WAAS_METADATA.icon
698
+ },
699
+ sendBitcoin,
700
+ signMessage,
701
+ signPsbt,
702
+ signPsbts,
703
+ switchActiveNetwork,
704
+ transferAmount: (args) => require_bitcoinTransferAmount.bitcoinTransferAmount(args, sdkClient),
705
+ walletProviderType
706
+ };
707
+ };
708
+
709
+ //#endregion
710
+ //#region src/waas/addWaasBitcoinExtension/addWaasBitcoinExtension.ts
711
+ const WAAS_BITCOIN_EXTENSION_KEY = "waasBitcoin";
712
+ /**
713
+ * Adds the Dynamic WaaS (Wallet as a Service) Bitcoin extension to the Dynamic client.
714
+ *
715
+ * This extension enables embedded wallet functionality for Bitcoin blockchain,
716
+ * allowing users to have wallets managed by Dynamic's infrastructure.
717
+ *
718
+ * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.
719
+ * @not-instrumented
720
+ */
721
+ const addWaasBitcoinExtension = (client = (0, _dynamic_labs_sdk_client_core.getDefaultClient)()) => {
722
+ if ((0, _dynamic_labs_sdk_client_core.hasExtension)({ extensionKey: WAAS_BITCOIN_EXTENSION_KEY }, client)) return;
723
+ (0, _dynamic_labs_sdk_client_core.registerExtension)({ extensionKey: WAAS_BITCOIN_EXTENSION_KEY }, client);
724
+ require_bitcoinTransferAmount.registerBitcoinNetworkProviderBuilder(client);
725
+ const walletProviderRegistry = (0, _dynamic_labs_sdk_client_core.getWalletProviderRegistry)(client);
726
+ const walletProvider = createWalletProviderForWaasBitcoin(client);
727
+ walletProviderRegistry.register({
728
+ priority: _dynamic_labs_sdk_client_core.WalletProviderPriority.WALLET_SDK,
729
+ walletProvider
730
+ });
731
+ };
732
+
733
+ //#endregion
734
+ Object.defineProperty(exports, 'TransactionBroadcastFailedError', {
735
+ enumerable: true,
736
+ get: function () {
737
+ return TransactionBroadcastFailedError;
738
+ }
739
+ });
740
+ Object.defineProperty(exports, 'TransactionRequiredError', {
741
+ enumerable: true,
742
+ get: function () {
743
+ return TransactionRequiredError;
744
+ }
745
+ });
746
+ Object.defineProperty(exports, '__toESM', {
747
+ enumerable: true,
748
+ get: function () {
749
+ return __toESM;
750
+ }
751
+ });
752
+ Object.defineProperty(exports, 'addWaasBitcoinExtension', {
753
+ enumerable: true,
754
+ get: function () {
755
+ return addWaasBitcoinExtension;
756
+ }
757
+ });
758
+ //# sourceMappingURL=addWaasBitcoinExtension-DsAO3xoD.cjs.js.map