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