@dynamic-labs/bitcoin 4.56.0 → 4.57.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.
- package/CHANGELOG.md +13 -0
- package/package.cjs +1 -1
- package/package.js +1 -1
- package/package.json +10 -10
- package/src/connectors/DynamicWaasBitcoinConnector/DynamicWaasBitcoinConnector.cjs +122 -4
- package/src/connectors/DynamicWaasBitcoinConnector/DynamicWaasBitcoinConnector.d.ts +34 -11
- package/src/connectors/DynamicWaasBitcoinConnector/DynamicWaasBitcoinConnector.js +122 -4
- package/src/types.d.ts +2 -1
- package/src/utils/BitcoinUiTransaction/BitcoinUiTransaction.cjs +158 -0
- package/src/utils/BitcoinUiTransaction/BitcoinUiTransaction.d.ts +82 -0
- package/src/utils/BitcoinUiTransaction/BitcoinUiTransaction.js +154 -0
- package/src/utils/BitcoinUiTransaction/index.d.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,17 @@
|
|
|
1
1
|
|
|
2
|
+
## [4.57.0](https://github.com/dynamic-labs/dynamic-auth/compare/v4.56.0...v4.57.0) (2026-01-20)
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
* 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))
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Bug Fixes
|
|
11
|
+
|
|
12
|
+
* 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))
|
|
13
|
+
* 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))
|
|
14
|
+
|
|
2
15
|
## [4.56.0](https://github.com/dynamic-labs/dynamic-auth/compare/v4.55.0...v4.56.0) (2026-01-19)
|
|
3
16
|
|
|
4
17
|
|
package/package.cjs
CHANGED
package/package.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs/bitcoin",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.57.0",
|
|
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.
|
|
21
|
+
"@dynamic-labs-wallet/browser-wallet-client": "0.0.250",
|
|
22
22
|
"@bitcoinerlab/secp256k1": "1.1.1",
|
|
23
23
|
"@btckit/types": "0.0.19",
|
|
24
|
-
"@dynamic-labs/sdk-api-core": "0.0.
|
|
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.
|
|
32
|
-
"@dynamic-labs/logger": "4.
|
|
33
|
-
"@dynamic-labs/types": "4.
|
|
34
|
-
"@dynamic-labs/utils": "4.
|
|
35
|
-
"@dynamic-labs/waas": "4.
|
|
36
|
-
"@dynamic-labs/wallet-book": "4.
|
|
37
|
-
"@dynamic-labs/wallet-connector-core": "4.
|
|
31
|
+
"@dynamic-labs/assert-package-version": "4.57.0",
|
|
32
|
+
"@dynamic-labs/logger": "4.57.0",
|
|
33
|
+
"@dynamic-labs/types": "4.57.0",
|
|
34
|
+
"@dynamic-labs/utils": "4.57.0",
|
|
35
|
+
"@dynamic-labs/waas": "4.57.0",
|
|
36
|
+
"@dynamic-labs/wallet-book": "4.57.0",
|
|
37
|
+
"@dynamic-labs/wallet-connector-core": "4.57.0",
|
|
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
|
-
*
|
|
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
|
|
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.
|
|
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.
|
|
579
|
+
network: yield this.getBitcoinNetworkEnum(),
|
|
462
580
|
},
|
|
463
581
|
message,
|
|
464
582
|
mfaToken,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { BitcoinConfig
|
|
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
|
-
*
|
|
173
|
+
* Always returns Dynamic's networkId (1 for mainnet)
|
|
174
|
+
* @returns The Dynamic networkId (1) for Bitcoin mainnet
|
|
177
175
|
*/
|
|
178
|
-
getNetwork(): Promise<
|
|
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
|
-
*
|
|
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
|
|
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.
|
|
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.
|
|
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';
|