@dynamic-labs/bitcoin 4.56.0 → 4.57.1

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.
package/CHANGELOG.md CHANGED
@@ -1,4 +1,24 @@
1
1
 
2
+ ### [4.57.1](https://github.com/dynamic-labs/dynamic-auth/compare/v4.57.0...v4.57.1) (2026-01-22)
3
+
4
+
5
+ ### Bug Fixes
6
+
7
+ * prevent No wallet provider found error when initializating ([#10277](https://github.com/dynamic-labs/dynamic-auth/issues/10277)) ([7427765](https://github.com/dynamic-labs/dynamic-auth/commit/74277654f2c823b6dd66a7cace29ea62f832bb77))
8
+
9
+ ## [4.57.0](https://github.com/dynamic-labs/dynamic-auth/compare/v4.56.0...v4.57.0) (2026-01-20)
10
+
11
+
12
+ ### Features
13
+
14
+ * auto redirect back from wallet connect ([#10257](https://github.com/dynamic-labs/dynamic-auth/issues/10257)) ([92994da](https://github.com/dynamic-labs/dynamic-auth/commit/92994dadaae851e309b5f889c0e415241cb2d00f))
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * metamask console noise when signing in with wallet connect ([#10263](https://github.com/dynamic-labs/dynamic-auth/issues/10263)) ([1861e4a](https://github.com/dynamic-labs/dynamic-auth/commit/1861e4a3e78dd7d7a5a250da32f722a7bf972083))
20
+ * only throw webview did not load error after retries ([#10255](https://github.com/dynamic-labs/dynamic-auth/issues/10255)) ([7c11824](https://github.com/dynamic-labs/dynamic-auth/commit/7c11824c32c9058c12aa5d6998b8cc3fe7e75938))
21
+
2
22
  ## [4.56.0](https://github.com/dynamic-labs/dynamic-auth/compare/v4.55.0...v4.56.0) (2026-01-19)
3
23
 
4
24
 
package/package.cjs CHANGED
@@ -3,6 +3,6 @@
3
3
 
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
- var version = "4.56.0";
6
+ var version = "4.57.1";
7
7
 
8
8
  exports.version = version;
package/package.js CHANGED
@@ -1,4 +1,4 @@
1
1
  'use client'
2
- var version = "4.56.0";
2
+ var version = "4.57.1";
3
3
 
4
4
  export { version };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dynamic-labs/bitcoin",
3
- "version": "4.56.0",
3
+ "version": "4.57.1",
4
4
  "description": "A React SDK for implementing wallet web3 authentication and authorization to your website.",
5
5
  "author": "Dynamic Labs, Inc.",
6
6
  "license": "MIT",
@@ -18,23 +18,23 @@
18
18
  },
19
19
  "homepage": "https://www.dynamic.xyz/",
20
20
  "dependencies": {
21
- "@dynamic-labs-wallet/browser-wallet-client": "0.0.248",
21
+ "@dynamic-labs-wallet/browser-wallet-client": "0.0.252",
22
22
  "@bitcoinerlab/secp256k1": "1.1.1",
23
23
  "@btckit/types": "0.0.19",
24
- "@dynamic-labs/sdk-api-core": "0.0.855",
24
+ "@dynamic-labs/sdk-api-core": "0.0.860",
25
25
  "@wallet-standard/app": "1.0.1",
26
26
  "@wallet-standard/base": "1.0.1",
27
27
  "bitcoinjs-lib": "6.1.5",
28
28
  "ecpair": "2.1.0",
29
29
  "sats-connect": "4.2.1",
30
30
  "jsontokens": "4.0.1",
31
- "@dynamic-labs/assert-package-version": "4.56.0",
32
- "@dynamic-labs/logger": "4.56.0",
33
- "@dynamic-labs/types": "4.56.0",
34
- "@dynamic-labs/utils": "4.56.0",
35
- "@dynamic-labs/waas": "4.56.0",
36
- "@dynamic-labs/wallet-book": "4.56.0",
37
- "@dynamic-labs/wallet-connector-core": "4.56.0",
31
+ "@dynamic-labs/assert-package-version": "4.57.1",
32
+ "@dynamic-labs/logger": "4.57.1",
33
+ "@dynamic-labs/types": "4.57.1",
34
+ "@dynamic-labs/utils": "4.57.1",
35
+ "@dynamic-labs/waas": "4.57.1",
36
+ "@dynamic-labs/wallet-book": "4.57.1",
37
+ "@dynamic-labs/wallet-connector-core": "4.57.1",
38
38
  "eventemitter3": "5.0.1"
39
39
  },
40
40
  "peerDependencies": {}
@@ -17,6 +17,7 @@ var PsbtParser = require('../../utils/psbtParser/PsbtParser.cjs');
17
17
  require('sats-connect');
18
18
  require('jsontokens');
19
19
  var btcToSatoshis = require('../../utils/btcToSatoshis/btcToSatoshis.cjs');
20
+ var BitcoinUiTransaction = require('../../utils/BitcoinUiTransaction/BitcoinUiTransaction.cjs');
20
21
 
21
22
  const logger = new logger$1.Logger('DynamicWaasConnector');
22
23
  /**
@@ -41,6 +42,7 @@ class DynamicWaasBitcoinConnector extends waas.withDynamicWaas(BitcoinWalletConn
41
42
  this.walletUiUtils = props.walletUiUtils;
42
43
  this.mempoolApiService = new MempoolApiService.MempoolApiService();
43
44
  this.psbtBuilderService = new PsbtBuilderService.PsbtBuilderService(this.mempoolApiService);
45
+ this.bitcoinNetworks = props.bitcoinNetworks || [];
44
46
  }
45
47
  set verifiedCredential(verifiedCredential) {
46
48
  this._verifiedCredential = verifiedCredential;
@@ -106,11 +108,45 @@ class DynamicWaasBitcoinConnector extends waas.withDynamicWaas(BitcoinWalletConn
106
108
  }
107
109
  /**
108
110
  * Gets the current Bitcoin network
109
- * @returns The network name ('mainnet' for Bitcoin)
111
+ * Always returns Dynamic's networkId (1 for mainnet)
112
+ * @returns The Dynamic networkId (1) for Bitcoin mainnet
110
113
  */
111
114
  getNetwork() {
112
115
  return _tslib.__awaiter(this, void 0, void 0, function* () {
113
- return 'mainnet';
116
+ return 1;
117
+ });
118
+ }
119
+ /**
120
+ * Maps Dynamic's networkId to BitcoinNetwork enum for internal WaaS API calls
121
+ * Uses the current network from getNetwork() to determine the BitcoinNetwork value
122
+ * @returns The corresponding BitcoinNetwork enum value for the current network
123
+ */
124
+ getBitcoinNetworkEnum() {
125
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
126
+ var _a;
127
+ const networkId = yield this.getNetwork();
128
+ const networkIdToBitcoinNetwork = {
129
+ 1: 'mainnet',
130
+ };
131
+ return ((_a = networkIdToBitcoinNetwork[networkId]) !== null && _a !== void 0 ? _a : 'mainnet');
132
+ });
133
+ }
134
+ /**
135
+ * Get the enabled networks for Bitcoin
136
+ * Returns configured networks from props
137
+ * @returns Array containing Bitcoin network configurations
138
+ */
139
+ getEnabledNetworks() {
140
+ return this.bitcoinNetworks;
141
+ }
142
+ /**
143
+ * Gets block explorer URLs for the current network
144
+ * Returns mempool.space for Bitcoin transactions
145
+ * @returns Array containing mempool.space URL
146
+ */
147
+ getBlockExplorerUrlsForCurrentNetwork() {
148
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
149
+ return ['https://mempool.space/'];
114
150
  });
115
151
  }
116
152
  /**
@@ -228,7 +264,7 @@ class DynamicWaasBitcoinConnector extends waas.withDynamicWaas(BitcoinWalletConn
228
264
  }
229
265
  const finalBitcoinConfig = {
230
266
  addressType: bitcoinConfig.addressType,
231
- network: yield this.getNetwork(),
267
+ network: yield this.getBitcoinNetworkEnum(),
232
268
  };
233
269
  return _super.createWalletAccount.call(this, {
234
270
  bitcoinConfig: finalBitcoinConfig,
@@ -358,6 +394,88 @@ class DynamicWaasBitcoinConnector extends waas.withDynamicWaas(BitcoinWalletConn
358
394
  return this.psbtBuilderService.buildPsbt(buildOptions);
359
395
  });
360
396
  }
397
+ /**
398
+ * Creates a UI transaction for the send balance flow
399
+ * @param from - The address sending the transaction
400
+ * @returns A BitcoinUiTransaction instance
401
+ * @throws {DynamicError} If active account address is not set
402
+ */
403
+ createUiTransaction(from) {
404
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
405
+ logger.debug('[DynamicWaasBitcoinConnector] createUiTransaction called', {
406
+ activeAccountAddress: this.activeAccountAddress,
407
+ from,
408
+ });
409
+ try {
410
+ logger.debug('[DynamicWaasBitcoinConnector] Validating active wallet', {
411
+ from,
412
+ });
413
+ yield this.validateActiveWallet(from);
414
+ logger.debug('[DynamicWaasBitcoinConnector] Active wallet validated successfully');
415
+ }
416
+ catch (error) {
417
+ logger.error('[DynamicWaasBitcoinConnector] Failed to validate active wallet', error);
418
+ throw error;
419
+ }
420
+ if (!this.activeAccountAddress) {
421
+ logger.error('[DynamicWaasBitcoinConnector] Active account address is required but not set');
422
+ throw new utils.DynamicError('Active account address is required');
423
+ }
424
+ logger.debug('[DynamicWaasBitcoinConnector] Creating BitcoinUiTransaction', {
425
+ from: this.activeAccountAddress,
426
+ });
427
+ const uiTransaction = new BitcoinUiTransaction.BitcoinUiTransaction({
428
+ from: this.activeAccountAddress,
429
+ mempoolApiService: this.mempoolApiService,
430
+ onSubmit: (transaction) => _tslib.__awaiter(this, void 0, void 0, function* () {
431
+ var _a;
432
+ logger.debug('[DynamicWaasBitcoinConnector] onSubmit called', {
433
+ amount: (_a = transaction.amount) === null || _a === void 0 ? void 0 : _a.toString(),
434
+ feePriority: transaction.feePriority,
435
+ recipientAddress: transaction.recipientAddress,
436
+ });
437
+ if (!transaction.recipientAddress || !transaction.amount) {
438
+ logger.error('[DynamicWaasBitcoinConnector] Missing required transaction fields', {
439
+ hasAmount: !!transaction.amount,
440
+ hasRecipientAddress: !!transaction.recipientAddress,
441
+ });
442
+ throw new utils.DynamicError('Recipient address and amount are required');
443
+ }
444
+ try {
445
+ logger.debug('[DynamicWaasBitcoinConnector] Calling sendBitcoin', {
446
+ amount: transaction.amount.toString(),
447
+ feePriority: transaction.feePriority || 'medium',
448
+ recipientAddress: transaction.recipientAddress,
449
+ });
450
+ const txHash = yield this.sendBitcoin({
451
+ amount: transaction.amount,
452
+ feePriority: transaction.feePriority || 'medium',
453
+ recipientAddress: transaction.recipientAddress,
454
+ });
455
+ logger.debug('[DynamicWaasBitcoinConnector] sendBitcoin completed', {
456
+ txHash,
457
+ });
458
+ if (!txHash) {
459
+ logger.error('[DynamicWaasBitcoinConnector] sendBitcoin returned undefined');
460
+ throw new utils.DynamicError('Failed to send Bitcoin transaction');
461
+ }
462
+ logger.info('[DynamicWaasBitcoinConnector] Transaction submitted successfully', { txHash });
463
+ return txHash;
464
+ }
465
+ catch (error) {
466
+ logger.error('[DynamicWaasBitcoinConnector] Error in onSubmit handler', error);
467
+ throw error;
468
+ }
469
+ }),
470
+ });
471
+ logger.debug('[DynamicWaasBitcoinConnector] BitcoinUiTransaction created successfully', {
472
+ hasOnSubmit: !!uiTransaction.submit,
473
+ transactionChain: uiTransaction.chain,
474
+ transactionFrom: uiTransaction.from,
475
+ });
476
+ return uiTransaction;
477
+ });
478
+ }
361
479
  /**
362
480
  * Parse a PSBT or finalized transaction and extract transaction information
363
481
  * Auto-detects format (hex/base64) and type (PSBT/finalized transaction)
@@ -458,7 +576,7 @@ class DynamicWaasBitcoinConnector extends waas.withDynamicWaas(BitcoinWalletConn
458
576
  accountAddress: this.activeAccountAddress,
459
577
  authToken: (_c = this.getAuthToken) === null || _c === void 0 ? void 0 : _c.call(this),
460
578
  bitcoinConfig: {
461
- network: yield this.getNetwork(),
579
+ network: yield this.getBitcoinNetworkEnum(),
462
580
  },
463
581
  message,
464
582
  mfaToken,
@@ -1,8 +1,8 @@
1
- import { BitcoinConfig, BitcoinNetwork } from '@dynamic-labs-wallet/browser-wallet-client';
1
+ import { BitcoinConfig } from '@dynamic-labs-wallet/browser-wallet-client';
2
2
  import { JwtVerifiedCredential, MFAAction, SignMessageContext } from '@dynamic-labs/sdk-api-core';
3
3
  import { Logger } from '@dynamic-labs/logger';
4
- import { WalletUiUtils } from '@dynamic-labs/types';
5
- import { IDynamicWaasConnector, InternalWalletConnector, Chain, BitcoinSignPsbtResponse } from '@dynamic-labs/wallet-connector-core';
4
+ import { WalletUiUtils, IUITransaction, GenericNetwork } from '@dynamic-labs/types';
5
+ import { IDynamicWaasConnector, InternalWalletConnector, Chain, BitcoinSignPsbtResponse, ISendBalanceWalletConnector } from '@dynamic-labs/wallet-connector-core';
6
6
  import { BitcoinTransaction, EmbeddedWalletSignPsbtRequest } from '../../types';
7
7
  import { BitcoinWalletConnector } from '../BitcoinWalletConnector';
8
8
  import type { ParsedTransaction, DynamicWaasBitcoinConnectorProps } from '../../types';
@@ -57,11 +57,7 @@ declare const DynamicWaasBitcoinConnector_base: (abstract new (...args: any[]) =
57
57
  thresholdSignatureScheme?: string | undefined;
58
58
  publicAddressCheck?: string | undefined;
59
59
  addressType?: string | undefined;
60
- legacyWalletId?: string | undefined; /**
61
- * Override setVerifiedCredentials to filter and set Bitcoin WaaS credentials
62
- * Filters for credentials with walletName === 'dynamicwaas' and chain === 'bip122'
63
- * The base class already has verifiedCredentials property, so we just filter and set it
64
- */
60
+ legacyWalletId?: string | undefined;
65
61
  }): Promise<void>;
66
62
  exportPrivateKey({ accountAddress, displayContainer, password, }?: {
67
63
  accountAddress?: string | undefined;
@@ -131,7 +127,7 @@ declare const DynamicWaasBitcoinConnector_base: (abstract new (...args: any[]) =
131
127
  * Bitcoin connector for Dynamic WaaS (Wallet as a Service)
132
128
  * Extends BitcoinWalletConnector with WaaS functionality for Bitcoin transactions
133
129
  */
134
- export declare class DynamicWaasBitcoinConnector extends DynamicWaasBitcoinConnector_base implements IDynamicWaasConnector {
130
+ export declare class DynamicWaasBitcoinConnector extends DynamicWaasBitcoinConnector_base implements IDynamicWaasConnector, ISendBalanceWalletConnector {
135
131
  name: string;
136
132
  logger: Logger;
137
133
  overrideKey: string;
@@ -147,6 +143,7 @@ export declare class DynamicWaasBitcoinConnector extends DynamicWaasBitcoinConne
147
143
  private _verifiedCredential;
148
144
  private mempoolApiService;
149
145
  private psbtBuilderService;
146
+ private bitcoinNetworks;
150
147
  /**
151
148
  * @param props - Constructor properties including walletUiUtils
152
149
  */
@@ -173,9 +170,28 @@ export declare class DynamicWaasBitcoinConnector extends DynamicWaasBitcoinConne
173
170
  getConnectedAccounts(): Promise<string[]>;
174
171
  /**
175
172
  * Gets the current Bitcoin network
176
- * @returns The network name ('mainnet' for Bitcoin)
173
+ * Always returns Dynamic's networkId (1 for mainnet)
174
+ * @returns The Dynamic networkId (1) for Bitcoin mainnet
177
175
  */
178
- getNetwork(): Promise<BitcoinNetwork>;
176
+ getNetwork(): Promise<number>;
177
+ /**
178
+ * Maps Dynamic's networkId to BitcoinNetwork enum for internal WaaS API calls
179
+ * Uses the current network from getNetwork() to determine the BitcoinNetwork value
180
+ * @returns The corresponding BitcoinNetwork enum value for the current network
181
+ */
182
+ private getBitcoinNetworkEnum;
183
+ /**
184
+ * Get the enabled networks for Bitcoin
185
+ * Returns configured networks from props
186
+ * @returns Array containing Bitcoin network configurations
187
+ */
188
+ getEnabledNetworks(): GenericNetwork[];
189
+ /**
190
+ * Gets block explorer URLs for the current network
191
+ * Returns mempool.space for Bitcoin transactions
192
+ * @returns Array containing mempool.space URL
193
+ */
194
+ getBlockExplorerUrlsForCurrentNetwork(): Promise<string[]>;
179
195
  /**
180
196
  * Signs a message using the wallet UI utils for user interaction
181
197
  * @param message - The message to sign
@@ -283,6 +299,13 @@ export declare class DynamicWaasBitcoinConnector extends DynamicWaasBitcoinConne
283
299
  * @throws {DynamicError} If no active account address, insufficient funds, or other errors
284
300
  */
285
301
  buildPsbt(transaction: BitcoinTransaction): Promise<string>;
302
+ /**
303
+ * Creates a UI transaction for the send balance flow
304
+ * @param from - The address sending the transaction
305
+ * @returns A BitcoinUiTransaction instance
306
+ * @throws {DynamicError} If active account address is not set
307
+ */
308
+ createUiTransaction(from: string): Promise<IUITransaction>;
286
309
  /**
287
310
  * Parse a PSBT or finalized transaction and extract transaction information
288
311
  * Auto-detects format (hex/base64) and type (PSBT/finalized transaction)
@@ -13,6 +13,7 @@ import { PsbtParser } from '../../utils/psbtParser/PsbtParser.js';
13
13
  import 'sats-connect';
14
14
  import 'jsontokens';
15
15
  import { btcToSatoshis } from '../../utils/btcToSatoshis/btcToSatoshis.js';
16
+ import { BitcoinUiTransaction } from '../../utils/BitcoinUiTransaction/BitcoinUiTransaction.js';
16
17
 
17
18
  const logger = new Logger('DynamicWaasConnector');
18
19
  /**
@@ -37,6 +38,7 @@ class DynamicWaasBitcoinConnector extends withDynamicWaas(BitcoinWalletConnector
37
38
  this.walletUiUtils = props.walletUiUtils;
38
39
  this.mempoolApiService = new MempoolApiService();
39
40
  this.psbtBuilderService = new PsbtBuilderService(this.mempoolApiService);
41
+ this.bitcoinNetworks = props.bitcoinNetworks || [];
40
42
  }
41
43
  set verifiedCredential(verifiedCredential) {
42
44
  this._verifiedCredential = verifiedCredential;
@@ -102,11 +104,45 @@ class DynamicWaasBitcoinConnector extends withDynamicWaas(BitcoinWalletConnector
102
104
  }
103
105
  /**
104
106
  * Gets the current Bitcoin network
105
- * @returns The network name ('mainnet' for Bitcoin)
107
+ * Always returns Dynamic's networkId (1 for mainnet)
108
+ * @returns The Dynamic networkId (1) for Bitcoin mainnet
106
109
  */
107
110
  getNetwork() {
108
111
  return __awaiter(this, void 0, void 0, function* () {
109
- return 'mainnet';
112
+ return 1;
113
+ });
114
+ }
115
+ /**
116
+ * Maps Dynamic's networkId to BitcoinNetwork enum for internal WaaS API calls
117
+ * Uses the current network from getNetwork() to determine the BitcoinNetwork value
118
+ * @returns The corresponding BitcoinNetwork enum value for the current network
119
+ */
120
+ getBitcoinNetworkEnum() {
121
+ return __awaiter(this, void 0, void 0, function* () {
122
+ var _a;
123
+ const networkId = yield this.getNetwork();
124
+ const networkIdToBitcoinNetwork = {
125
+ 1: 'mainnet',
126
+ };
127
+ return ((_a = networkIdToBitcoinNetwork[networkId]) !== null && _a !== void 0 ? _a : 'mainnet');
128
+ });
129
+ }
130
+ /**
131
+ * Get the enabled networks for Bitcoin
132
+ * Returns configured networks from props
133
+ * @returns Array containing Bitcoin network configurations
134
+ */
135
+ getEnabledNetworks() {
136
+ return this.bitcoinNetworks;
137
+ }
138
+ /**
139
+ * Gets block explorer URLs for the current network
140
+ * Returns mempool.space for Bitcoin transactions
141
+ * @returns Array containing mempool.space URL
142
+ */
143
+ getBlockExplorerUrlsForCurrentNetwork() {
144
+ return __awaiter(this, void 0, void 0, function* () {
145
+ return ['https://mempool.space/'];
110
146
  });
111
147
  }
112
148
  /**
@@ -224,7 +260,7 @@ class DynamicWaasBitcoinConnector extends withDynamicWaas(BitcoinWalletConnector
224
260
  }
225
261
  const finalBitcoinConfig = {
226
262
  addressType: bitcoinConfig.addressType,
227
- network: yield this.getNetwork(),
263
+ network: yield this.getBitcoinNetworkEnum(),
228
264
  };
229
265
  return _super.createWalletAccount.call(this, {
230
266
  bitcoinConfig: finalBitcoinConfig,
@@ -354,6 +390,88 @@ class DynamicWaasBitcoinConnector extends withDynamicWaas(BitcoinWalletConnector
354
390
  return this.psbtBuilderService.buildPsbt(buildOptions);
355
391
  });
356
392
  }
393
+ /**
394
+ * Creates a UI transaction for the send balance flow
395
+ * @param from - The address sending the transaction
396
+ * @returns A BitcoinUiTransaction instance
397
+ * @throws {DynamicError} If active account address is not set
398
+ */
399
+ createUiTransaction(from) {
400
+ return __awaiter(this, void 0, void 0, function* () {
401
+ logger.debug('[DynamicWaasBitcoinConnector] createUiTransaction called', {
402
+ activeAccountAddress: this.activeAccountAddress,
403
+ from,
404
+ });
405
+ try {
406
+ logger.debug('[DynamicWaasBitcoinConnector] Validating active wallet', {
407
+ from,
408
+ });
409
+ yield this.validateActiveWallet(from);
410
+ logger.debug('[DynamicWaasBitcoinConnector] Active wallet validated successfully');
411
+ }
412
+ catch (error) {
413
+ logger.error('[DynamicWaasBitcoinConnector] Failed to validate active wallet', error);
414
+ throw error;
415
+ }
416
+ if (!this.activeAccountAddress) {
417
+ logger.error('[DynamicWaasBitcoinConnector] Active account address is required but not set');
418
+ throw new DynamicError('Active account address is required');
419
+ }
420
+ logger.debug('[DynamicWaasBitcoinConnector] Creating BitcoinUiTransaction', {
421
+ from: this.activeAccountAddress,
422
+ });
423
+ const uiTransaction = new BitcoinUiTransaction({
424
+ from: this.activeAccountAddress,
425
+ mempoolApiService: this.mempoolApiService,
426
+ onSubmit: (transaction) => __awaiter(this, void 0, void 0, function* () {
427
+ var _a;
428
+ logger.debug('[DynamicWaasBitcoinConnector] onSubmit called', {
429
+ amount: (_a = transaction.amount) === null || _a === void 0 ? void 0 : _a.toString(),
430
+ feePriority: transaction.feePriority,
431
+ recipientAddress: transaction.recipientAddress,
432
+ });
433
+ if (!transaction.recipientAddress || !transaction.amount) {
434
+ logger.error('[DynamicWaasBitcoinConnector] Missing required transaction fields', {
435
+ hasAmount: !!transaction.amount,
436
+ hasRecipientAddress: !!transaction.recipientAddress,
437
+ });
438
+ throw new DynamicError('Recipient address and amount are required');
439
+ }
440
+ try {
441
+ logger.debug('[DynamicWaasBitcoinConnector] Calling sendBitcoin', {
442
+ amount: transaction.amount.toString(),
443
+ feePriority: transaction.feePriority || 'medium',
444
+ recipientAddress: transaction.recipientAddress,
445
+ });
446
+ const txHash = yield this.sendBitcoin({
447
+ amount: transaction.amount,
448
+ feePriority: transaction.feePriority || 'medium',
449
+ recipientAddress: transaction.recipientAddress,
450
+ });
451
+ logger.debug('[DynamicWaasBitcoinConnector] sendBitcoin completed', {
452
+ txHash,
453
+ });
454
+ if (!txHash) {
455
+ logger.error('[DynamicWaasBitcoinConnector] sendBitcoin returned undefined');
456
+ throw new DynamicError('Failed to send Bitcoin transaction');
457
+ }
458
+ logger.info('[DynamicWaasBitcoinConnector] Transaction submitted successfully', { txHash });
459
+ return txHash;
460
+ }
461
+ catch (error) {
462
+ logger.error('[DynamicWaasBitcoinConnector] Error in onSubmit handler', error);
463
+ throw error;
464
+ }
465
+ }),
466
+ });
467
+ logger.debug('[DynamicWaasBitcoinConnector] BitcoinUiTransaction created successfully', {
468
+ hasOnSubmit: !!uiTransaction.submit,
469
+ transactionChain: uiTransaction.chain,
470
+ transactionFrom: uiTransaction.from,
471
+ });
472
+ return uiTransaction;
473
+ });
474
+ }
357
475
  /**
358
476
  * Parse a PSBT or finalized transaction and extract transaction information
359
477
  * Auto-detects format (hex/base64) and type (PSBT/finalized transaction)
@@ -454,7 +572,7 @@ class DynamicWaasBitcoinConnector extends withDynamicWaas(BitcoinWalletConnector
454
572
  accountAddress: this.activeAccountAddress,
455
573
  authToken: (_c = this.getAuthToken) === null || _c === void 0 ? void 0 : _c.call(this),
456
574
  bitcoinConfig: {
457
- network: yield this.getNetwork(),
575
+ network: yield this.getBitcoinNetworkEnum(),
458
576
  },
459
577
  message,
460
578
  mfaToken,
package/src/types.d.ts CHANGED
@@ -2,7 +2,7 @@ import { BitcoinProvider, InputToSign as SatsConnectInputToSign } from 'sats-con
2
2
  import { SignPsbtResponse as BtcKitSignPsbtResponse } from '@btckit/types';
3
3
  import { IdentifierString, WalletAccount } from '@wallet-standard/base';
4
4
  import type { Network } from 'bitcoinjs-lib';
5
- import type { WalletUiUtils } from '@dynamic-labs/types';
5
+ import type { GenericNetwork, WalletUiUtils } from '@dynamic-labs/types';
6
6
  import type { InternalWalletConnector } from '@dynamic-labs/wallet-connector-core';
7
7
  import type { WalletAdditionalAddress } from '@dynamic-labs/sdk-api-core';
8
8
  import type { BitcoinWalletConnectorOpts } from './connectors';
@@ -159,6 +159,7 @@ export interface ProviderWithBalance {
159
159
  }
160
160
  export type DynamicWaasBitcoinConnectorProps = BitcoinWalletConnectorOpts & {
161
161
  walletUiUtils: WalletUiUtils<InternalWalletConnector>;
162
+ bitcoinNetworks?: GenericNetwork[];
162
163
  };
163
164
  export interface UTXO {
164
165
  txid: string;
@@ -0,0 +1,158 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ var _tslib = require('../../../_virtual/_tslib.cjs');
7
+ var utils = require('@dynamic-labs/utils');
8
+ var _const = require('../../const.cjs');
9
+
10
+ class BitcoinUiTransaction {
11
+ constructor({ onSubmit, from, mempoolApiService, }) {
12
+ this.chain = 'BTC';
13
+ this.data = undefined;
14
+ this.fee = { gas: undefined };
15
+ this.feePriority = 'medium';
16
+ /**
17
+ * Formats the value into a string for the UI for non-native tokens
18
+ * @param value - The value to format
19
+ * @param decimals - The number of decimals for the non-native token
20
+ * @returns The formatted value
21
+ */
22
+ this.formatNonNativeToken = (value, decimals) => (Number(value) / Number(Math.pow(10, decimals))).toString();
23
+ this.from = from;
24
+ this.onSubmit = onSubmit;
25
+ this.mempoolApiService = mempoolApiService;
26
+ }
27
+ /**
28
+ * Updates the fee priority and recalculates the fee
29
+ * @param priority - The new fee priority (high/medium/low)
30
+ */
31
+ updateFeePriority(priority) {
32
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
33
+ if (this.feePriority === priority) {
34
+ return;
35
+ }
36
+ this.feePriority = priority;
37
+ this.fee.gas = undefined;
38
+ this.lastFeePriority = undefined;
39
+ if (this.to && this.value) {
40
+ yield this.fetchFee();
41
+ }
42
+ });
43
+ }
44
+ /**
45
+ * Fetches the estimated transaction fee
46
+ */
47
+ fetchFee() {
48
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
49
+ const shouldRecalculate = !this.fee.gas || this.lastFeePriority !== this.feePriority;
50
+ if (!shouldRecalculate) {
51
+ return;
52
+ }
53
+ if (!this.to || !this.value) {
54
+ return;
55
+ }
56
+ try {
57
+ const estimatedFee = yield this.mempoolApiService.estimateTransactionFee(this.from, 1, 1, this.feePriority);
58
+ this.fee.gas = BigInt(estimatedFee);
59
+ this.lastFeePriority = this.feePriority;
60
+ }
61
+ catch (error) {
62
+ // If fee estimation fails, leave it undefined
63
+ // The actual fee will be calculated when building the PSBT
64
+ this.fee.gas = undefined;
65
+ this.lastFeePriority = undefined;
66
+ }
67
+ });
68
+ }
69
+ /**
70
+ * Parses the input string into a bigint value in satoshis
71
+ * @param input - The input string to parse
72
+ * @returns The parsed value in satoshis
73
+ */
74
+ parse(input) {
75
+ const floatValue = parseFloat(input);
76
+ if (isNaN(floatValue)) {
77
+ return BigInt(0);
78
+ }
79
+ const satoshis = Math.round(floatValue * _const.SATOSHIS_PER_BTC);
80
+ return BigInt(satoshis);
81
+ }
82
+ /**
83
+ * Parses the input string into a bigint value in non-native tokens
84
+ * @param input - The input string to parse
85
+ * @param decimals - The number of decimals for the non-native token
86
+ * @returns The parsed value in non-native tokens
87
+ */
88
+ parseNonNativeToken(input, decimals) {
89
+ return BigInt(Math.floor(Number(input) * Math.pow(10, decimals)));
90
+ }
91
+ /**
92
+ * Formats the value into a string for the UI
93
+ * @param value - The value to format
94
+ * @param precision - The precision for the formatted value
95
+ * @returns The formatted value
96
+ */
97
+ format(value, { precision } = {}) {
98
+ const btcValue = Number(value) / _const.SATOSHIS_PER_BTC;
99
+ const decimalString = btcValue.toLocaleString('fullwide', {
100
+ maximumFractionDigits: 20,
101
+ minimumFractionDigits: 0,
102
+ useGrouping: false,
103
+ });
104
+ return utils.formatNumberText(decimalString, { precision });
105
+ }
106
+ /**
107
+ * Submits the transaction
108
+ * @returns The transaction hash
109
+ */
110
+ submit() {
111
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
112
+ if (!this.to) {
113
+ throw new Error('Recipient address is required');
114
+ }
115
+ if (!this.value || this.value <= BigInt(0)) {
116
+ throw new Error('Amount must be greater than 0');
117
+ }
118
+ const txHash = yield this.onSubmit({
119
+ amount: this.value,
120
+ feePriority: this.feePriority,
121
+ recipientAddress: this.to,
122
+ });
123
+ if (!txHash) {
124
+ throw new Error('Transaction failed - no transaction hash returned');
125
+ }
126
+ return txHash;
127
+ });
128
+ }
129
+ /**
130
+ * Fetches the balance of the sender in satoshis
131
+ * @returns The balance in satoshis
132
+ */
133
+ getBalance() {
134
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
135
+ try {
136
+ const balance = yield this.mempoolApiService.getUTXOs(this.from);
137
+ const totalBalance = balance.reduce((sum, utxo) => sum + utxo.value, 0);
138
+ return BigInt(totalBalance);
139
+ }
140
+ catch (error) {
141
+ return BigInt(0);
142
+ }
143
+ });
144
+ }
145
+ /**
146
+ * Validates the address format
147
+ * @param address - The address to validate
148
+ * @returns True if the address is valid, false otherwise
149
+ */
150
+ validateAddressFormat(address) {
151
+ if (address === 'dyn_send_transaction.multiple_recipients') {
152
+ return true;
153
+ }
154
+ return /^(bc1|[13]|tb1)[a-zA-HJ-NP-Z0-9]{25,62}$/.test(address);
155
+ }
156
+ }
157
+
158
+ exports.BitcoinUiTransaction = BitcoinUiTransaction;
@@ -0,0 +1,82 @@
1
+ import { IUITransaction, IUITransactionFormatOptions } from '@dynamic-labs/types';
2
+ import { MempoolApiService } from '../../services/MempoolApiService';
3
+ import type { FeePriority } from '../../types';
4
+ type BitcoinUiTransactionProps = {
5
+ from: string;
6
+ onSubmit: (transaction: {
7
+ amount: bigint;
8
+ recipientAddress: string;
9
+ feePriority?: FeePriority;
10
+ }) => Promise<string>;
11
+ mempoolApiService: MempoolApiService;
12
+ };
13
+ export declare class BitcoinUiTransaction implements IUITransaction {
14
+ to: string | undefined;
15
+ from: string;
16
+ value: bigint | undefined;
17
+ chain: string;
18
+ receipt: string | undefined;
19
+ data: undefined;
20
+ fee: {
21
+ gas: bigint | undefined;
22
+ };
23
+ nativePrice?: number;
24
+ feePriority: FeePriority;
25
+ private lastFeePriority?;
26
+ private onSubmit;
27
+ private mempoolApiService;
28
+ constructor({ onSubmit, from, mempoolApiService, }: BitcoinUiTransactionProps);
29
+ /**
30
+ * Updates the fee priority and recalculates the fee
31
+ * @param priority - The new fee priority (high/medium/low)
32
+ */
33
+ updateFeePriority(priority: FeePriority): Promise<void>;
34
+ /**
35
+ * Fetches the estimated transaction fee
36
+ */
37
+ fetchFee(): Promise<void>;
38
+ /**
39
+ * Parses the input string into a bigint value in satoshis
40
+ * @param input - The input string to parse
41
+ * @returns The parsed value in satoshis
42
+ */
43
+ parse(input: string): bigint;
44
+ /**
45
+ * Parses the input string into a bigint value in non-native tokens
46
+ * @param input - The input string to parse
47
+ * @param decimals - The number of decimals for the non-native token
48
+ * @returns The parsed value in non-native tokens
49
+ */
50
+ parseNonNativeToken(input: string, decimals: number): bigint;
51
+ /**
52
+ * Formats the value into a string for the UI for non-native tokens
53
+ * @param value - The value to format
54
+ * @param decimals - The number of decimals for the non-native token
55
+ * @returns The formatted value
56
+ */
57
+ formatNonNativeToken: (value: bigint, decimals: number) => string;
58
+ /**
59
+ * Formats the value into a string for the UI
60
+ * @param value - The value to format
61
+ * @param precision - The precision for the formatted value
62
+ * @returns The formatted value
63
+ */
64
+ format(value: bigint, { precision }?: IUITransactionFormatOptions): string;
65
+ /**
66
+ * Submits the transaction
67
+ * @returns The transaction hash
68
+ */
69
+ submit(): Promise<string>;
70
+ /**
71
+ * Fetches the balance of the sender in satoshis
72
+ * @returns The balance in satoshis
73
+ */
74
+ getBalance(): Promise<bigint>;
75
+ /**
76
+ * Validates the address format
77
+ * @param address - The address to validate
78
+ * @returns True if the address is valid, false otherwise
79
+ */
80
+ validateAddressFormat(address: string): boolean;
81
+ }
82
+ export {};
@@ -0,0 +1,154 @@
1
+ 'use client'
2
+ import { __awaiter } from '../../../_virtual/_tslib.js';
3
+ import { formatNumberText } from '@dynamic-labs/utils';
4
+ import { SATOSHIS_PER_BTC } from '../../const.js';
5
+
6
+ class BitcoinUiTransaction {
7
+ constructor({ onSubmit, from, mempoolApiService, }) {
8
+ this.chain = 'BTC';
9
+ this.data = undefined;
10
+ this.fee = { gas: undefined };
11
+ this.feePriority = 'medium';
12
+ /**
13
+ * Formats the value into a string for the UI for non-native tokens
14
+ * @param value - The value to format
15
+ * @param decimals - The number of decimals for the non-native token
16
+ * @returns The formatted value
17
+ */
18
+ this.formatNonNativeToken = (value, decimals) => (Number(value) / Number(Math.pow(10, decimals))).toString();
19
+ this.from = from;
20
+ this.onSubmit = onSubmit;
21
+ this.mempoolApiService = mempoolApiService;
22
+ }
23
+ /**
24
+ * Updates the fee priority and recalculates the fee
25
+ * @param priority - The new fee priority (high/medium/low)
26
+ */
27
+ updateFeePriority(priority) {
28
+ return __awaiter(this, void 0, void 0, function* () {
29
+ if (this.feePriority === priority) {
30
+ return;
31
+ }
32
+ this.feePriority = priority;
33
+ this.fee.gas = undefined;
34
+ this.lastFeePriority = undefined;
35
+ if (this.to && this.value) {
36
+ yield this.fetchFee();
37
+ }
38
+ });
39
+ }
40
+ /**
41
+ * Fetches the estimated transaction fee
42
+ */
43
+ fetchFee() {
44
+ return __awaiter(this, void 0, void 0, function* () {
45
+ const shouldRecalculate = !this.fee.gas || this.lastFeePriority !== this.feePriority;
46
+ if (!shouldRecalculate) {
47
+ return;
48
+ }
49
+ if (!this.to || !this.value) {
50
+ return;
51
+ }
52
+ try {
53
+ const estimatedFee = yield this.mempoolApiService.estimateTransactionFee(this.from, 1, 1, this.feePriority);
54
+ this.fee.gas = BigInt(estimatedFee);
55
+ this.lastFeePriority = this.feePriority;
56
+ }
57
+ catch (error) {
58
+ // If fee estimation fails, leave it undefined
59
+ // The actual fee will be calculated when building the PSBT
60
+ this.fee.gas = undefined;
61
+ this.lastFeePriority = undefined;
62
+ }
63
+ });
64
+ }
65
+ /**
66
+ * Parses the input string into a bigint value in satoshis
67
+ * @param input - The input string to parse
68
+ * @returns The parsed value in satoshis
69
+ */
70
+ parse(input) {
71
+ const floatValue = parseFloat(input);
72
+ if (isNaN(floatValue)) {
73
+ return BigInt(0);
74
+ }
75
+ const satoshis = Math.round(floatValue * SATOSHIS_PER_BTC);
76
+ return BigInt(satoshis);
77
+ }
78
+ /**
79
+ * Parses the input string into a bigint value in non-native tokens
80
+ * @param input - The input string to parse
81
+ * @param decimals - The number of decimals for the non-native token
82
+ * @returns The parsed value in non-native tokens
83
+ */
84
+ parseNonNativeToken(input, decimals) {
85
+ return BigInt(Math.floor(Number(input) * Math.pow(10, decimals)));
86
+ }
87
+ /**
88
+ * Formats the value into a string for the UI
89
+ * @param value - The value to format
90
+ * @param precision - The precision for the formatted value
91
+ * @returns The formatted value
92
+ */
93
+ format(value, { precision } = {}) {
94
+ const btcValue = Number(value) / SATOSHIS_PER_BTC;
95
+ const decimalString = btcValue.toLocaleString('fullwide', {
96
+ maximumFractionDigits: 20,
97
+ minimumFractionDigits: 0,
98
+ useGrouping: false,
99
+ });
100
+ return formatNumberText(decimalString, { precision });
101
+ }
102
+ /**
103
+ * Submits the transaction
104
+ * @returns The transaction hash
105
+ */
106
+ submit() {
107
+ return __awaiter(this, void 0, void 0, function* () {
108
+ if (!this.to) {
109
+ throw new Error('Recipient address is required');
110
+ }
111
+ if (!this.value || this.value <= BigInt(0)) {
112
+ throw new Error('Amount must be greater than 0');
113
+ }
114
+ const txHash = yield this.onSubmit({
115
+ amount: this.value,
116
+ feePriority: this.feePriority,
117
+ recipientAddress: this.to,
118
+ });
119
+ if (!txHash) {
120
+ throw new Error('Transaction failed - no transaction hash returned');
121
+ }
122
+ return txHash;
123
+ });
124
+ }
125
+ /**
126
+ * Fetches the balance of the sender in satoshis
127
+ * @returns The balance in satoshis
128
+ */
129
+ getBalance() {
130
+ return __awaiter(this, void 0, void 0, function* () {
131
+ try {
132
+ const balance = yield this.mempoolApiService.getUTXOs(this.from);
133
+ const totalBalance = balance.reduce((sum, utxo) => sum + utxo.value, 0);
134
+ return BigInt(totalBalance);
135
+ }
136
+ catch (error) {
137
+ return BigInt(0);
138
+ }
139
+ });
140
+ }
141
+ /**
142
+ * Validates the address format
143
+ * @param address - The address to validate
144
+ * @returns True if the address is valid, false otherwise
145
+ */
146
+ validateAddressFormat(address) {
147
+ if (address === 'dyn_send_transaction.multiple_recipients') {
148
+ return true;
149
+ }
150
+ return /^(bc1|[13]|tb1)[a-zA-HJ-NP-Z0-9]{25,62}$/.test(address);
151
+ }
152
+ }
153
+
154
+ export { BitcoinUiTransaction };
@@ -0,0 +1 @@
1
+ export { BitcoinUiTransaction } from './BitcoinUiTransaction';