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