@dynamic-labs/bitcoin 4.91.2 → 4.91.4
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 +20 -0
- package/package.cjs +1 -1
- package/package.js +1 -1
- package/package.json +8 -8
- package/src/connectors/BitcoinWalletConnector.cjs +17 -6
- package/src/connectors/BitcoinWalletConnector.js +17 -6
- package/src/connectors/DynamicWaasBitcoinConnector/DynamicWaasBitcoinConnector.cjs +21 -20
- package/src/connectors/DynamicWaasBitcoinConnector/DynamicWaasBitcoinConnector.d.ts +1 -5
- package/src/connectors/DynamicWaasBitcoinConnector/DynamicWaasBitcoinConnector.js +21 -20
- package/src/connectors/MagicEdenConnector/MagicEdenConnector.cjs +1 -1
- package/src/connectors/MagicEdenConnector/MagicEdenConnector.js +1 -1
- package/src/index.cjs +1 -0
- package/src/index.js +1 -1
- package/src/services/MempoolApiService.cjs +4 -4
- package/src/services/MempoolApiService.js +4 -4
- package/src/services/PsbtBuilderService.cjs +8 -8
- package/src/services/PsbtBuilderService.js +8 -8
- package/src/utils/btcToSatoshis/btcToSatoshis.cjs +1 -1
- package/src/utils/btcToSatoshis/btcToSatoshis.js +1 -1
- package/src/utils/fetchSatsConnectConnectors/fetchSatsConnectConnectors.cjs +75 -4
- package/src/utils/fetchSatsConnectConnectors/fetchSatsConnectConnectors.d.ts +5 -0
- package/src/utils/fetchSatsConnectConnectors/fetchSatsConnectConnectors.js +75 -5
- package/src/utils/psbt/validator/validateAddress.cjs +2 -2
- package/src/utils/psbt/validator/validateAddress.js +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,24 @@
|
|
|
1
1
|
|
|
2
|
+
### [4.91.4](https://github.com/dynamic-labs/dynamic-auth/compare/v4.91.3...v4.91.4) (2026-07-01)
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
### Bug Fixes
|
|
6
|
+
|
|
7
|
+
* conditionally use /op/ route for AA transactions based on block explorer support ([#11628](https://github.com/dynamic-labs/dynamic-auth/issues/11628)) ([95822dc](https://github.com/dynamic-labs/dynamic-auth/commit/95822dc0edbcd739afe870f0b3881555fdb17eb6))
|
|
8
|
+
* require error codes in all SDK error classes ([#11761](https://github.com/dynamic-labs/dynamic-auth/issues/11761)) ([5744811](https://github.com/dynamic-labs/dynamic-auth/commit/5744811efdd1e415aaf51eec5b3300b323ec1347))
|
|
9
|
+
|
|
10
|
+
### [4.91.3](https://github.com/dynamic-labs/dynamic-auth/compare/v4.91.2...v4.91.3) (2026-06-30)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* **bitcoin:** detect late-registering wallet-standard wallets (DYNT-1210) ([#11747](https://github.com/dynamic-labs/dynamic-auth/issues/11747)) ([17809f6](https://github.com/dynamic-labs/dynamic-auth/commit/17809f6e811fe101367cc31a2d899a8d0b0d107e))
|
|
16
|
+
* fetch onramp providers lazily instead of eagerly on mount ([#11767](https://github.com/dynamic-labs/dynamic-auth/issues/11767)) ([3ee6708](https://github.com/dynamic-labs/dynamic-auth/commit/3ee67087142ae1942f865e0ab37b7108700b3327))
|
|
17
|
+
* **iframe-setup:** sync parent URL to iframe on pushState/replaceState ([#11751](https://github.com/dynamic-labs/dynamic-auth/issues/11751)) ([c8be3af](https://github.com/dynamic-labs/dynamic-auth/commit/c8be3afc301f77b349f23398bed940ce40f93b73))
|
|
18
|
+
* **nonce:** fetch nonce on demand when missing before wallet verification ([#11753](https://github.com/dynamic-labs/dynamic-auth/issues/11753)) ([4f01a21](https://github.com/dynamic-labs/dynamic-auth/commit/4f01a21b6081c852f32868c8a5e04d70aaf280a2)), closes [#1](https://github.com/dynamic-labs/dynamic-auth/issues/1)
|
|
19
|
+
* **react-native-extension:** arm loading timer before setUrl to cover pre-onLoadStart gap ([#11764](https://github.com/dynamic-labs/dynamic-auth/issues/11764)) ([31f2015](https://github.com/dynamic-labs/dynamic-auth/commit/31f20151a4b59279f9c133b723e50de771b06436))
|
|
20
|
+
* **webview-controller:** unwrap ZeroDev smart wallet for native gasless ([#11758](https://github.com/dynamic-labs/dynamic-auth/issues/11758)) ([989714e](https://github.com/dynamic-labs/dynamic-auth/commit/989714e414556868c8e0c54401aac1ed7354331b))
|
|
21
|
+
|
|
2
22
|
### [4.91.2](https://github.com/dynamic-labs/dynamic-auth/compare/v4.91.1...v4.91.2) (2026-06-26)
|
|
3
23
|
|
|
4
24
|
|
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.91.
|
|
3
|
+
"version": "4.91.4",
|
|
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",
|
|
@@ -29,13 +29,13 @@
|
|
|
29
29
|
"ecpair": "2.1.0",
|
|
30
30
|
"sats-connect": "4.2.1",
|
|
31
31
|
"jsontokens": "4.0.1",
|
|
32
|
-
"@dynamic-labs/assert-package-version": "4.91.
|
|
33
|
-
"@dynamic-labs/logger": "4.91.
|
|
34
|
-
"@dynamic-labs/types": "4.91.
|
|
35
|
-
"@dynamic-labs/utils": "4.91.
|
|
36
|
-
"@dynamic-labs/waas": "4.91.
|
|
37
|
-
"@dynamic-labs/wallet-book": "4.91.
|
|
38
|
-
"@dynamic-labs/wallet-connector-core": "4.91.
|
|
32
|
+
"@dynamic-labs/assert-package-version": "4.91.4",
|
|
33
|
+
"@dynamic-labs/logger": "4.91.4",
|
|
34
|
+
"@dynamic-labs/types": "4.91.4",
|
|
35
|
+
"@dynamic-labs/utils": "4.91.4",
|
|
36
|
+
"@dynamic-labs/waas": "4.91.4",
|
|
37
|
+
"@dynamic-labs/wallet-book": "4.91.4",
|
|
38
|
+
"@dynamic-labs/wallet-connector-core": "4.91.4",
|
|
39
39
|
"eventemitter3": "5.0.1"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {}
|
|
@@ -54,8 +54,19 @@ class BitcoinWalletConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
54
54
|
return Boolean((_a = this.metadata.supportedHardwareWallets) === null || _a === void 0 ? void 0 : _a.includes('ledger'));
|
|
55
55
|
}
|
|
56
56
|
isInstalledOnBrowser() {
|
|
57
|
-
var _a;
|
|
58
|
-
|
|
57
|
+
var _a, _b, _c;
|
|
58
|
+
// Re-run the wallet-standard lookup on each call so that a wallet which
|
|
59
|
+
// registered after the constructor ran (late injection via wallet-standard)
|
|
60
|
+
// is picked up by the existing useReconcileInstalledWallets poll.
|
|
61
|
+
if (!this.wallet) {
|
|
62
|
+
const found = (_a = this.bitcoinProviderHelper) === null || _a === void 0 ? void 0 : _a.findWallet();
|
|
63
|
+
if (found) {
|
|
64
|
+
this.wallet = found;
|
|
65
|
+
this.walletMethods =
|
|
66
|
+
(_b = this.bitcoinProviderHelper) === null || _b === void 0 ? void 0 : _b.getWalletMethods(found);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return (Boolean(this.wallet) || Boolean((_c = this.bitcoinProviderHelper) === null || _c === void 0 ? void 0 : _c.getProvider()));
|
|
59
70
|
}
|
|
60
71
|
getDeepLink() {
|
|
61
72
|
return undefined;
|
|
@@ -167,11 +178,11 @@ class BitcoinWalletConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
167
178
|
sendRawTransaction(rawTransaction) {
|
|
168
179
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
169
180
|
if (!rawTransaction) {
|
|
170
|
-
throw new utils.DynamicError('No transaction specified!');
|
|
181
|
+
throw new utils.DynamicError('No transaction specified!', 'no_transaction_specified');
|
|
171
182
|
}
|
|
172
183
|
const [connectedAddress] = yield this.getConnectedAccounts();
|
|
173
184
|
if (!connectedAddress) {
|
|
174
|
-
throw new utils.DynamicError('No connected address found!');
|
|
185
|
+
throw new utils.DynamicError('No connected address found!', 'no_connected_address_found');
|
|
175
186
|
}
|
|
176
187
|
const API_URL = getMempoolApiUrl.getMempoolApiUrl(connectedAddress);
|
|
177
188
|
const response = yield fetch(`${API_URL}/tx`, {
|
|
@@ -183,11 +194,11 @@ class BitcoinWalletConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
183
194
|
});
|
|
184
195
|
if (!response.ok) {
|
|
185
196
|
if (response.status === _const.HTTP_STATUS_TOO_MANY_REQUESTS) {
|
|
186
|
-
throw new utils.DynamicError('sendRawTransaction - mempool api rate limit exceeded');
|
|
197
|
+
throw new utils.DynamicError('sendRawTransaction - mempool api rate limit exceeded', 'sendrawtransaction_mempool_api_rate_limit_exceeded');
|
|
187
198
|
}
|
|
188
199
|
const error = yield response.text();
|
|
189
200
|
walletConnectorCore.logger.debug(`sendRawTransaction - response not ok: ${JSON.stringify(error)}`);
|
|
190
|
-
throw new utils.DynamicError('sendRawTransaction - failed to send transaction');
|
|
201
|
+
throw new utils.DynamicError('sendRawTransaction - failed to send transaction', 'sendrawtransaction_failed_to_send_transaction');
|
|
191
202
|
}
|
|
192
203
|
// this endpoint returns the transaction ID
|
|
193
204
|
return response.text();
|
|
@@ -50,8 +50,19 @@ class BitcoinWalletConnector extends WalletConnectorBase {
|
|
|
50
50
|
return Boolean((_a = this.metadata.supportedHardwareWallets) === null || _a === void 0 ? void 0 : _a.includes('ledger'));
|
|
51
51
|
}
|
|
52
52
|
isInstalledOnBrowser() {
|
|
53
|
-
var _a;
|
|
54
|
-
|
|
53
|
+
var _a, _b, _c;
|
|
54
|
+
// Re-run the wallet-standard lookup on each call so that a wallet which
|
|
55
|
+
// registered after the constructor ran (late injection via wallet-standard)
|
|
56
|
+
// is picked up by the existing useReconcileInstalledWallets poll.
|
|
57
|
+
if (!this.wallet) {
|
|
58
|
+
const found = (_a = this.bitcoinProviderHelper) === null || _a === void 0 ? void 0 : _a.findWallet();
|
|
59
|
+
if (found) {
|
|
60
|
+
this.wallet = found;
|
|
61
|
+
this.walletMethods =
|
|
62
|
+
(_b = this.bitcoinProviderHelper) === null || _b === void 0 ? void 0 : _b.getWalletMethods(found);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return (Boolean(this.wallet) || Boolean((_c = this.bitcoinProviderHelper) === null || _c === void 0 ? void 0 : _c.getProvider()));
|
|
55
66
|
}
|
|
56
67
|
getDeepLink() {
|
|
57
68
|
return undefined;
|
|
@@ -163,11 +174,11 @@ class BitcoinWalletConnector extends WalletConnectorBase {
|
|
|
163
174
|
sendRawTransaction(rawTransaction) {
|
|
164
175
|
return __awaiter(this, void 0, void 0, function* () {
|
|
165
176
|
if (!rawTransaction) {
|
|
166
|
-
throw new DynamicError('No transaction specified!');
|
|
177
|
+
throw new DynamicError('No transaction specified!', 'no_transaction_specified');
|
|
167
178
|
}
|
|
168
179
|
const [connectedAddress] = yield this.getConnectedAccounts();
|
|
169
180
|
if (!connectedAddress) {
|
|
170
|
-
throw new DynamicError('No connected address found!');
|
|
181
|
+
throw new DynamicError('No connected address found!', 'no_connected_address_found');
|
|
171
182
|
}
|
|
172
183
|
const API_URL = getMempoolApiUrl(connectedAddress);
|
|
173
184
|
const response = yield fetch(`${API_URL}/tx`, {
|
|
@@ -179,11 +190,11 @@ class BitcoinWalletConnector extends WalletConnectorBase {
|
|
|
179
190
|
});
|
|
180
191
|
if (!response.ok) {
|
|
181
192
|
if (response.status === HTTP_STATUS_TOO_MANY_REQUESTS) {
|
|
182
|
-
throw new DynamicError('sendRawTransaction - mempool api rate limit exceeded');
|
|
193
|
+
throw new DynamicError('sendRawTransaction - mempool api rate limit exceeded', 'sendrawtransaction_mempool_api_rate_limit_exceeded');
|
|
183
194
|
}
|
|
184
195
|
const error = yield response.text();
|
|
185
196
|
logger.debug(`sendRawTransaction - response not ok: ${JSON.stringify(error)}`);
|
|
186
|
-
throw new DynamicError('sendRawTransaction - failed to send transaction');
|
|
197
|
+
throw new DynamicError('sendRawTransaction - failed to send transaction', 'sendrawtransaction_failed_to_send_transaction');
|
|
187
198
|
}
|
|
188
199
|
// this endpoint returns the transaction ID
|
|
189
200
|
return response.text();
|
|
@@ -14,6 +14,7 @@ var MempoolApiService = require('../../services/MempoolApiService.cjs');
|
|
|
14
14
|
var PsbtBuilderService = require('../../services/PsbtBuilderService.cjs');
|
|
15
15
|
require('sats-connect');
|
|
16
16
|
var BitcoinWalletConnector = require('../BitcoinWalletConnector.cjs');
|
|
17
|
+
require('@wallet-standard/app');
|
|
17
18
|
require('jsontokens');
|
|
18
19
|
var btcToSatoshis = require('../../utils/btcToSatoshis/btcToSatoshis.cjs');
|
|
19
20
|
var PsbtParser = require('../../utils/psbtParser/PsbtParser.cjs');
|
|
@@ -89,7 +90,7 @@ class DynamicWaasBitcoinConnector extends waas.withDynamicWaas(BitcoinWalletConn
|
|
|
89
90
|
this.setActiveAccount(address);
|
|
90
91
|
return address;
|
|
91
92
|
}
|
|
92
|
-
throw new utils.DynamicError('No active wallet address found');
|
|
93
|
+
throw new utils.DynamicError('No active wallet address found', 'no_active_wallet_address_found');
|
|
93
94
|
}
|
|
94
95
|
return activeAccount.address;
|
|
95
96
|
});
|
|
@@ -179,11 +180,11 @@ class DynamicWaasBitcoinConnector extends waas.withDynamicWaas(BitcoinWalletConn
|
|
|
179
180
|
var _a, _b, _c, _d;
|
|
180
181
|
const walletClient = yield this.getWaasWalletClient();
|
|
181
182
|
if (!this.activeAccountAddress) {
|
|
182
|
-
throw new utils.DynamicError('Active account address is required');
|
|
183
|
+
throw new utils.DynamicError('Active account address is required', 'active_account_address_is_required');
|
|
183
184
|
}
|
|
184
185
|
const signedSessionId = yield ((_a = this.getSignedSessionId) === null || _a === void 0 ? void 0 : _a.call(this));
|
|
185
186
|
if (!signedSessionId) {
|
|
186
|
-
throw new utils.DynamicError('Signed session ID is required');
|
|
187
|
+
throw new utils.DynamicError('Signed session ID is required', 'signed_session_id_is_required');
|
|
187
188
|
}
|
|
188
189
|
const mfaToken = yield ((_b = this.getMfaToken) === null || _b === void 0 ? void 0 : _b.call(this, {
|
|
189
190
|
mfaAction: sdkApiCore.MFAAction.WalletWaasSign,
|
|
@@ -217,7 +218,7 @@ class DynamicWaasBitcoinConnector extends waas.withDynamicWaas(BitcoinWalletConn
|
|
|
217
218
|
sendRawTransaction(rawTransaction) {
|
|
218
219
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
219
220
|
if (!this.activeAccountAddress) {
|
|
220
|
-
throw new utils.DynamicError('Active account address is required');
|
|
221
|
+
throw new utils.DynamicError('Active account address is required', 'active_account_address_is_required');
|
|
221
222
|
}
|
|
222
223
|
return this.mempoolApiService.sendRawTransaction(this.activeAccountAddress, rawTransaction);
|
|
223
224
|
});
|
|
@@ -232,7 +233,7 @@ class DynamicWaasBitcoinConnector extends waas.withDynamicWaas(BitcoinWalletConn
|
|
|
232
233
|
sendBitcoin(transaction) {
|
|
233
234
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
234
235
|
if (!this.activeAccountAddress) {
|
|
235
|
-
throw new utils.DynamicError('Active account address is required');
|
|
236
|
+
throw new utils.DynamicError('Active account address is required', 'active_account_address_is_required');
|
|
236
237
|
}
|
|
237
238
|
// Step 1: Build the PSBT
|
|
238
239
|
const unsignedPsbt = yield this.buildPsbt(transaction);
|
|
@@ -241,7 +242,7 @@ class DynamicWaasBitcoinConnector extends waas.withDynamicWaas(BitcoinWalletConn
|
|
|
241
242
|
unsignedPsbtBase64: unsignedPsbt,
|
|
242
243
|
});
|
|
243
244
|
if (!signedPsbtResponse) {
|
|
244
|
-
throw new utils.DynamicError('Failed to sign PSBT');
|
|
245
|
+
throw new utils.DynamicError('Failed to sign PSBT', 'sign_psbt_failed');
|
|
245
246
|
}
|
|
246
247
|
// Step 3: Finalize the signed PSBT and extract the raw transaction
|
|
247
248
|
const network = this.activeAccountAddress.startsWith('t')
|
|
@@ -296,11 +297,11 @@ class DynamicWaasBitcoinConnector extends waas.withDynamicWaas(BitcoinWalletConn
|
|
|
296
297
|
});
|
|
297
298
|
return _tslib.__awaiter(this, arguments, void 0, function* ({ privateKey, thresholdSignatureScheme = 'TWO_OF_TWO', publicAddressCheck, addressType, legacyWalletId, }) {
|
|
298
299
|
if (!addressType) {
|
|
299
|
-
throw new utils.DynamicError('addressType is required for BTC importPrivateKey');
|
|
300
|
+
throw new utils.DynamicError('addressType is required for BTC importPrivateKey', 'addresstype_is_required_for_btc_importprivatekey');
|
|
300
301
|
}
|
|
301
302
|
const validAddressTypes = ['native_segwit', 'taproot'];
|
|
302
303
|
if (!validAddressTypes.includes(addressType)) {
|
|
303
|
-
throw new utils.DynamicError(`Invalid addressType: ${addressType}. Must be one of: ${validAddressTypes.join(', ')}
|
|
304
|
+
throw new utils.DynamicError(`Invalid addressType: ${addressType}. Must be one of: ${validAddressTypes.join(', ')}`, 'invalid_addresstype_must_be_one_of');
|
|
304
305
|
}
|
|
305
306
|
return _super.importPrivateKey.call(this, {
|
|
306
307
|
addressType,
|
|
@@ -346,7 +347,7 @@ class DynamicWaasBitcoinConnector extends waas.withDynamicWaas(BitcoinWalletConn
|
|
|
346
347
|
signedSessionId: '',
|
|
347
348
|
});
|
|
348
349
|
if (!targetWallet) {
|
|
349
|
-
throw new utils.DynamicError('Account not found');
|
|
350
|
+
throw new utils.DynamicError('Account not found', 'account_not_found');
|
|
350
351
|
}
|
|
351
352
|
const isWalletActive = walletConnectorCore.isSameAddress(targetWallet.accountAddress, this.activeAccountAddress || '', this.connectedChain);
|
|
352
353
|
if (!isWalletActive) {
|
|
@@ -367,11 +368,11 @@ class DynamicWaasBitcoinConnector extends waas.withDynamicWaas(BitcoinWalletConn
|
|
|
367
368
|
var _b, _c, _d, _e;
|
|
368
369
|
const walletClient = yield this.getWaasWalletClient();
|
|
369
370
|
if (!this.activeAccountAddress) {
|
|
370
|
-
throw new utils.DynamicError('Active account address is required');
|
|
371
|
+
throw new utils.DynamicError('Active account address is required', 'active_account_address_is_required');
|
|
371
372
|
}
|
|
372
373
|
const signedSessionId = yield ((_b = this.getSignedSessionId) === null || _b === void 0 ? void 0 : _b.call(this));
|
|
373
374
|
if (!signedSessionId) {
|
|
374
|
-
throw new utils.DynamicError('Signed session ID is required');
|
|
375
|
+
throw new utils.DynamicError('Signed session ID is required', 'signed_session_id_is_required');
|
|
375
376
|
}
|
|
376
377
|
const mfaToken = yield ((_c = this.getMfaToken) === null || _c === void 0 ? void 0 : _c.call(this, {
|
|
377
378
|
mfaAction: sdkApiCore.MFAAction.WalletWaasSign,
|
|
@@ -404,7 +405,7 @@ class DynamicWaasBitcoinConnector extends waas.withDynamicWaas(BitcoinWalletConn
|
|
|
404
405
|
buildPsbt(transaction) {
|
|
405
406
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
406
407
|
if (!this.activeAccountAddress) {
|
|
407
|
-
throw new utils.DynamicError('Active account address is required');
|
|
408
|
+
throw new utils.DynamicError('Active account address is required', 'active_account_address_is_required');
|
|
408
409
|
}
|
|
409
410
|
const publicKeyHex = yield this.getPublicKey();
|
|
410
411
|
const buildOptions = PsbtBuilderService.PsbtBuilderService.createBuildOptions(this.activeAccountAddress, transaction, publicKeyHex, transaction.feePriority || 'medium');
|
|
@@ -436,7 +437,7 @@ class DynamicWaasBitcoinConnector extends waas.withDynamicWaas(BitcoinWalletConn
|
|
|
436
437
|
}
|
|
437
438
|
if (!this.activeAccountAddress) {
|
|
438
439
|
logger.error('[DynamicWaasBitcoinConnector] Active account address is required but not set');
|
|
439
|
-
throw new utils.DynamicError('Active account address is required');
|
|
440
|
+
throw new utils.DynamicError('Active account address is required', 'active_account_address_is_required');
|
|
440
441
|
}
|
|
441
442
|
logger.debug('[DynamicWaasBitcoinConnector] Creating BitcoinUiTransaction', {
|
|
442
443
|
from: this.activeAccountAddress,
|
|
@@ -456,7 +457,7 @@ class DynamicWaasBitcoinConnector extends waas.withDynamicWaas(BitcoinWalletConn
|
|
|
456
457
|
hasAmount: Boolean(transaction.amount),
|
|
457
458
|
hasRecipientAddress: Boolean(transaction.recipientAddress),
|
|
458
459
|
});
|
|
459
|
-
throw new utils.DynamicError('Recipient address and amount are required');
|
|
460
|
+
throw new utils.DynamicError('Recipient address and amount are required', 'recipient_address_and_amount_are_required');
|
|
460
461
|
}
|
|
461
462
|
try {
|
|
462
463
|
logger.debug('[DynamicWaasBitcoinConnector] Calling sendBitcoin', {
|
|
@@ -474,7 +475,7 @@ class DynamicWaasBitcoinConnector extends waas.withDynamicWaas(BitcoinWalletConn
|
|
|
474
475
|
});
|
|
475
476
|
if (!txHash) {
|
|
476
477
|
logger.error('[DynamicWaasBitcoinConnector] sendBitcoin returned undefined');
|
|
477
|
-
throw new utils.DynamicError('Failed to send Bitcoin transaction');
|
|
478
|
+
throw new utils.DynamicError('Failed to send Bitcoin transaction', 'send_bitcoin_transaction');
|
|
478
479
|
}
|
|
479
480
|
logger.info('[DynamicWaasBitcoinConnector] Transaction submitted successfully', { txHash });
|
|
480
481
|
return txHash;
|
|
@@ -529,11 +530,11 @@ class DynamicWaasBitcoinConnector extends waas.withDynamicWaas(BitcoinWalletConn
|
|
|
529
530
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
530
531
|
var _a;
|
|
531
532
|
if (!this.activeAccountAddress) {
|
|
532
|
-
throw new utils.DynamicError('No active account address');
|
|
533
|
+
throw new utils.DynamicError('No active account address', 'no_active_account_address');
|
|
533
534
|
}
|
|
534
535
|
const allCredentials = (_a = this.verifiedCredentials) !== null && _a !== void 0 ? _a : [];
|
|
535
536
|
if (allCredentials.length === 0) {
|
|
536
|
-
throw new utils.DynamicError(`No verified credentials found. The address ${this.activeAccountAddress} may not be properly registered
|
|
537
|
+
throw new utils.DynamicError(`No verified credentials found. The address ${this.activeAccountAddress} may not be properly registered.`, 'no_verified_credentials_found_the_address');
|
|
537
538
|
}
|
|
538
539
|
for (const credential of allCredentials) {
|
|
539
540
|
const { walletAdditionalAddresses } = credential !== null && credential !== void 0 ? credential : {};
|
|
@@ -549,7 +550,7 @@ class DynamicWaasBitcoinConnector extends waas.withDynamicWaas(BitcoinWalletConn
|
|
|
549
550
|
.flatMap((cred) => { var _a; return (_a = cred.walletAdditionalAddresses) !== null && _a !== void 0 ? _a : []; })
|
|
550
551
|
.map((addr) => addr.address)
|
|
551
552
|
.join(', ');
|
|
552
|
-
throw new utils.DynamicError(`No additional address found for ${this.activeAccountAddress}. Available addresses: ${allAvailableAddresses || 'none'}
|
|
553
|
+
throw new utils.DynamicError(`No additional address found for ${this.activeAccountAddress}. Available addresses: ${allAvailableAddresses || 'none'}`, 'no_additional_address_found_for_available');
|
|
553
554
|
});
|
|
554
555
|
}
|
|
555
556
|
/**
|
|
@@ -580,11 +581,11 @@ class DynamicWaasBitcoinConnector extends waas.withDynamicWaas(BitcoinWalletConn
|
|
|
580
581
|
var _a, _b, _c, _d;
|
|
581
582
|
const walletClient = yield this.getWaasWalletClient();
|
|
582
583
|
if (!this.activeAccountAddress) {
|
|
583
|
-
throw new utils.DynamicError('Active account address is required');
|
|
584
|
+
throw new utils.DynamicError('Active account address is required', 'active_account_address_is_required');
|
|
584
585
|
}
|
|
585
586
|
const signedSessionId = yield ((_a = this.getSignedSessionId) === null || _a === void 0 ? void 0 : _a.call(this));
|
|
586
587
|
if (!signedSessionId) {
|
|
587
|
-
throw new utils.DynamicError('Signed session ID is required');
|
|
588
|
+
throw new utils.DynamicError('Signed session ID is required', 'signed_session_id_is_required');
|
|
588
589
|
}
|
|
589
590
|
const mfaToken = yield ((_b = this.getMfaToken) === null || _b === void 0 ? void 0 : _b.call(this, {
|
|
590
591
|
mfaAction: sdkApiCore.MFAAction.WalletWaasSign,
|
|
@@ -120,11 +120,7 @@ declare const DynamicWaasBitcoinConnector_base: (abstract new (...args: any[]) =
|
|
|
120
120
|
hideICloudSignIn(): Promise<void>;
|
|
121
121
|
isICloudAuthenticated(): Promise<boolean>;
|
|
122
122
|
refreshWalletAccountShares({ accountAddress, password, }: {
|
|
123
|
-
accountAddress: string;
|
|
124
|
-
* Gets block explorer URLs for the current network
|
|
125
|
-
* Returns mempool.space for Bitcoin transactions
|
|
126
|
-
* @returns Array containing mempool.space URL
|
|
127
|
-
*/
|
|
123
|
+
accountAddress: string;
|
|
128
124
|
password?: string | undefined;
|
|
129
125
|
}): Promise<void>;
|
|
130
126
|
reshareWalletAccountShares({ accountAddress, thresholdSignatureScheme, password, }: {
|
|
@@ -10,6 +10,7 @@ import { MempoolApiService } from '../../services/MempoolApiService.js';
|
|
|
10
10
|
import { PsbtBuilderService } from '../../services/PsbtBuilderService.js';
|
|
11
11
|
import 'sats-connect';
|
|
12
12
|
import { BitcoinWalletConnector } from '../BitcoinWalletConnector.js';
|
|
13
|
+
import '@wallet-standard/app';
|
|
13
14
|
import 'jsontokens';
|
|
14
15
|
import { btcToSatoshis } from '../../utils/btcToSatoshis/btcToSatoshis.js';
|
|
15
16
|
import { PsbtParser } from '../../utils/psbtParser/PsbtParser.js';
|
|
@@ -85,7 +86,7 @@ class DynamicWaasBitcoinConnector extends withDynamicWaas(BitcoinWalletConnector
|
|
|
85
86
|
this.setActiveAccount(address);
|
|
86
87
|
return address;
|
|
87
88
|
}
|
|
88
|
-
throw new DynamicError('No active wallet address found');
|
|
89
|
+
throw new DynamicError('No active wallet address found', 'no_active_wallet_address_found');
|
|
89
90
|
}
|
|
90
91
|
return activeAccount.address;
|
|
91
92
|
});
|
|
@@ -175,11 +176,11 @@ class DynamicWaasBitcoinConnector extends withDynamicWaas(BitcoinWalletConnector
|
|
|
175
176
|
var _a, _b, _c, _d;
|
|
176
177
|
const walletClient = yield this.getWaasWalletClient();
|
|
177
178
|
if (!this.activeAccountAddress) {
|
|
178
|
-
throw new DynamicError('Active account address is required');
|
|
179
|
+
throw new DynamicError('Active account address is required', 'active_account_address_is_required');
|
|
179
180
|
}
|
|
180
181
|
const signedSessionId = yield ((_a = this.getSignedSessionId) === null || _a === void 0 ? void 0 : _a.call(this));
|
|
181
182
|
if (!signedSessionId) {
|
|
182
|
-
throw new DynamicError('Signed session ID is required');
|
|
183
|
+
throw new DynamicError('Signed session ID is required', 'signed_session_id_is_required');
|
|
183
184
|
}
|
|
184
185
|
const mfaToken = yield ((_b = this.getMfaToken) === null || _b === void 0 ? void 0 : _b.call(this, {
|
|
185
186
|
mfaAction: MFAAction.WalletWaasSign,
|
|
@@ -213,7 +214,7 @@ class DynamicWaasBitcoinConnector extends withDynamicWaas(BitcoinWalletConnector
|
|
|
213
214
|
sendRawTransaction(rawTransaction) {
|
|
214
215
|
return __awaiter(this, void 0, void 0, function* () {
|
|
215
216
|
if (!this.activeAccountAddress) {
|
|
216
|
-
throw new DynamicError('Active account address is required');
|
|
217
|
+
throw new DynamicError('Active account address is required', 'active_account_address_is_required');
|
|
217
218
|
}
|
|
218
219
|
return this.mempoolApiService.sendRawTransaction(this.activeAccountAddress, rawTransaction);
|
|
219
220
|
});
|
|
@@ -228,7 +229,7 @@ class DynamicWaasBitcoinConnector extends withDynamicWaas(BitcoinWalletConnector
|
|
|
228
229
|
sendBitcoin(transaction) {
|
|
229
230
|
return __awaiter(this, void 0, void 0, function* () {
|
|
230
231
|
if (!this.activeAccountAddress) {
|
|
231
|
-
throw new DynamicError('Active account address is required');
|
|
232
|
+
throw new DynamicError('Active account address is required', 'active_account_address_is_required');
|
|
232
233
|
}
|
|
233
234
|
// Step 1: Build the PSBT
|
|
234
235
|
const unsignedPsbt = yield this.buildPsbt(transaction);
|
|
@@ -237,7 +238,7 @@ class DynamicWaasBitcoinConnector extends withDynamicWaas(BitcoinWalletConnector
|
|
|
237
238
|
unsignedPsbtBase64: unsignedPsbt,
|
|
238
239
|
});
|
|
239
240
|
if (!signedPsbtResponse) {
|
|
240
|
-
throw new DynamicError('Failed to sign PSBT');
|
|
241
|
+
throw new DynamicError('Failed to sign PSBT', 'sign_psbt_failed');
|
|
241
242
|
}
|
|
242
243
|
// Step 3: Finalize the signed PSBT and extract the raw transaction
|
|
243
244
|
const network = this.activeAccountAddress.startsWith('t')
|
|
@@ -292,11 +293,11 @@ class DynamicWaasBitcoinConnector extends withDynamicWaas(BitcoinWalletConnector
|
|
|
292
293
|
});
|
|
293
294
|
return __awaiter(this, arguments, void 0, function* ({ privateKey, thresholdSignatureScheme = 'TWO_OF_TWO', publicAddressCheck, addressType, legacyWalletId, }) {
|
|
294
295
|
if (!addressType) {
|
|
295
|
-
throw new DynamicError('addressType is required for BTC importPrivateKey');
|
|
296
|
+
throw new DynamicError('addressType is required for BTC importPrivateKey', 'addresstype_is_required_for_btc_importprivatekey');
|
|
296
297
|
}
|
|
297
298
|
const validAddressTypes = ['native_segwit', 'taproot'];
|
|
298
299
|
if (!validAddressTypes.includes(addressType)) {
|
|
299
|
-
throw new DynamicError(`Invalid addressType: ${addressType}. Must be one of: ${validAddressTypes.join(', ')}
|
|
300
|
+
throw new DynamicError(`Invalid addressType: ${addressType}. Must be one of: ${validAddressTypes.join(', ')}`, 'invalid_addresstype_must_be_one_of');
|
|
300
301
|
}
|
|
301
302
|
return _super.importPrivateKey.call(this, {
|
|
302
303
|
addressType,
|
|
@@ -342,7 +343,7 @@ class DynamicWaasBitcoinConnector extends withDynamicWaas(BitcoinWalletConnector
|
|
|
342
343
|
signedSessionId: '',
|
|
343
344
|
});
|
|
344
345
|
if (!targetWallet) {
|
|
345
|
-
throw new DynamicError('Account not found');
|
|
346
|
+
throw new DynamicError('Account not found', 'account_not_found');
|
|
346
347
|
}
|
|
347
348
|
const isWalletActive = isSameAddress(targetWallet.accountAddress, this.activeAccountAddress || '', this.connectedChain);
|
|
348
349
|
if (!isWalletActive) {
|
|
@@ -363,11 +364,11 @@ class DynamicWaasBitcoinConnector extends withDynamicWaas(BitcoinWalletConnector
|
|
|
363
364
|
var _b, _c, _d, _e;
|
|
364
365
|
const walletClient = yield this.getWaasWalletClient();
|
|
365
366
|
if (!this.activeAccountAddress) {
|
|
366
|
-
throw new DynamicError('Active account address is required');
|
|
367
|
+
throw new DynamicError('Active account address is required', 'active_account_address_is_required');
|
|
367
368
|
}
|
|
368
369
|
const signedSessionId = yield ((_b = this.getSignedSessionId) === null || _b === void 0 ? void 0 : _b.call(this));
|
|
369
370
|
if (!signedSessionId) {
|
|
370
|
-
throw new DynamicError('Signed session ID is required');
|
|
371
|
+
throw new DynamicError('Signed session ID is required', 'signed_session_id_is_required');
|
|
371
372
|
}
|
|
372
373
|
const mfaToken = yield ((_c = this.getMfaToken) === null || _c === void 0 ? void 0 : _c.call(this, {
|
|
373
374
|
mfaAction: MFAAction.WalletWaasSign,
|
|
@@ -400,7 +401,7 @@ class DynamicWaasBitcoinConnector extends withDynamicWaas(BitcoinWalletConnector
|
|
|
400
401
|
buildPsbt(transaction) {
|
|
401
402
|
return __awaiter(this, void 0, void 0, function* () {
|
|
402
403
|
if (!this.activeAccountAddress) {
|
|
403
|
-
throw new DynamicError('Active account address is required');
|
|
404
|
+
throw new DynamicError('Active account address is required', 'active_account_address_is_required');
|
|
404
405
|
}
|
|
405
406
|
const publicKeyHex = yield this.getPublicKey();
|
|
406
407
|
const buildOptions = PsbtBuilderService.createBuildOptions(this.activeAccountAddress, transaction, publicKeyHex, transaction.feePriority || 'medium');
|
|
@@ -432,7 +433,7 @@ class DynamicWaasBitcoinConnector extends withDynamicWaas(BitcoinWalletConnector
|
|
|
432
433
|
}
|
|
433
434
|
if (!this.activeAccountAddress) {
|
|
434
435
|
logger.error('[DynamicWaasBitcoinConnector] Active account address is required but not set');
|
|
435
|
-
throw new DynamicError('Active account address is required');
|
|
436
|
+
throw new DynamicError('Active account address is required', 'active_account_address_is_required');
|
|
436
437
|
}
|
|
437
438
|
logger.debug('[DynamicWaasBitcoinConnector] Creating BitcoinUiTransaction', {
|
|
438
439
|
from: this.activeAccountAddress,
|
|
@@ -452,7 +453,7 @@ class DynamicWaasBitcoinConnector extends withDynamicWaas(BitcoinWalletConnector
|
|
|
452
453
|
hasAmount: Boolean(transaction.amount),
|
|
453
454
|
hasRecipientAddress: Boolean(transaction.recipientAddress),
|
|
454
455
|
});
|
|
455
|
-
throw new DynamicError('Recipient address and amount are required');
|
|
456
|
+
throw new DynamicError('Recipient address and amount are required', 'recipient_address_and_amount_are_required');
|
|
456
457
|
}
|
|
457
458
|
try {
|
|
458
459
|
logger.debug('[DynamicWaasBitcoinConnector] Calling sendBitcoin', {
|
|
@@ -470,7 +471,7 @@ class DynamicWaasBitcoinConnector extends withDynamicWaas(BitcoinWalletConnector
|
|
|
470
471
|
});
|
|
471
472
|
if (!txHash) {
|
|
472
473
|
logger.error('[DynamicWaasBitcoinConnector] sendBitcoin returned undefined');
|
|
473
|
-
throw new DynamicError('Failed to send Bitcoin transaction');
|
|
474
|
+
throw new DynamicError('Failed to send Bitcoin transaction', 'send_bitcoin_transaction');
|
|
474
475
|
}
|
|
475
476
|
logger.info('[DynamicWaasBitcoinConnector] Transaction submitted successfully', { txHash });
|
|
476
477
|
return txHash;
|
|
@@ -525,11 +526,11 @@ class DynamicWaasBitcoinConnector extends withDynamicWaas(BitcoinWalletConnector
|
|
|
525
526
|
return __awaiter(this, void 0, void 0, function* () {
|
|
526
527
|
var _a;
|
|
527
528
|
if (!this.activeAccountAddress) {
|
|
528
|
-
throw new DynamicError('No active account address');
|
|
529
|
+
throw new DynamicError('No active account address', 'no_active_account_address');
|
|
529
530
|
}
|
|
530
531
|
const allCredentials = (_a = this.verifiedCredentials) !== null && _a !== void 0 ? _a : [];
|
|
531
532
|
if (allCredentials.length === 0) {
|
|
532
|
-
throw new DynamicError(`No verified credentials found. The address ${this.activeAccountAddress} may not be properly registered
|
|
533
|
+
throw new DynamicError(`No verified credentials found. The address ${this.activeAccountAddress} may not be properly registered.`, 'no_verified_credentials_found_the_address');
|
|
533
534
|
}
|
|
534
535
|
for (const credential of allCredentials) {
|
|
535
536
|
const { walletAdditionalAddresses } = credential !== null && credential !== void 0 ? credential : {};
|
|
@@ -545,7 +546,7 @@ class DynamicWaasBitcoinConnector extends withDynamicWaas(BitcoinWalletConnector
|
|
|
545
546
|
.flatMap((cred) => { var _a; return (_a = cred.walletAdditionalAddresses) !== null && _a !== void 0 ? _a : []; })
|
|
546
547
|
.map((addr) => addr.address)
|
|
547
548
|
.join(', ');
|
|
548
|
-
throw new DynamicError(`No additional address found for ${this.activeAccountAddress}. Available addresses: ${allAvailableAddresses || 'none'}
|
|
549
|
+
throw new DynamicError(`No additional address found for ${this.activeAccountAddress}. Available addresses: ${allAvailableAddresses || 'none'}`, 'no_additional_address_found_for_available');
|
|
549
550
|
});
|
|
550
551
|
}
|
|
551
552
|
/**
|
|
@@ -576,11 +577,11 @@ class DynamicWaasBitcoinConnector extends withDynamicWaas(BitcoinWalletConnector
|
|
|
576
577
|
var _a, _b, _c, _d;
|
|
577
578
|
const walletClient = yield this.getWaasWalletClient();
|
|
578
579
|
if (!this.activeAccountAddress) {
|
|
579
|
-
throw new DynamicError('Active account address is required');
|
|
580
|
+
throw new DynamicError('Active account address is required', 'active_account_address_is_required');
|
|
580
581
|
}
|
|
581
582
|
const signedSessionId = yield ((_a = this.getSignedSessionId) === null || _a === void 0 ? void 0 : _a.call(this));
|
|
582
583
|
if (!signedSessionId) {
|
|
583
|
-
throw new DynamicError('Signed session ID is required');
|
|
584
|
+
throw new DynamicError('Signed session ID is required', 'signed_session_id_is_required');
|
|
584
585
|
}
|
|
585
586
|
const mfaToken = yield ((_b = this.getMfaToken) === null || _b === void 0 ? void 0 : _b.call(this, {
|
|
586
587
|
mfaAction: MFAAction.WalletWaasSign,
|
|
@@ -174,7 +174,7 @@ class MagicEdenConnector extends BitcoinSatsConnectConnector.BitcoinSatsConnectC
|
|
|
174
174
|
// to ensure we use it rather than the general Sats Connect API for this method
|
|
175
175
|
const provider = this.getProvider();
|
|
176
176
|
if (!provider)
|
|
177
|
-
throw new utils.DynamicError('signTransactions failed: Magic Eden provider not found');
|
|
177
|
+
throw new utils.DynamicError('signTransactions failed: Magic Eden provider not found', 'signtransactions_failed_magic_eden_provider_not');
|
|
178
178
|
return provider.signMultipleTransactions(request);
|
|
179
179
|
});
|
|
180
180
|
}
|
|
@@ -170,7 +170,7 @@ class MagicEdenConnector extends BitcoinSatsConnectConnector {
|
|
|
170
170
|
// to ensure we use it rather than the general Sats Connect API for this method
|
|
171
171
|
const provider = this.getProvider();
|
|
172
172
|
if (!provider)
|
|
173
|
-
throw new DynamicError('signTransactions failed: Magic Eden provider not found');
|
|
173
|
+
throw new DynamicError('signTransactions failed: Magic Eden provider not found', 'signtransactions_failed_magic_eden_provider_not');
|
|
174
174
|
return provider.signMultipleTransactions(request);
|
|
175
175
|
});
|
|
176
176
|
}
|
package/src/index.cjs
CHANGED
|
@@ -58,6 +58,7 @@ exports.UnisatConnector = UnisatConnector.UnisatConnector;
|
|
|
58
58
|
exports.DynamicWaasBitcoinConnector = DynamicWaasBitcoinConnector.DynamicWaasBitcoinConnector;
|
|
59
59
|
exports.fetchBtcKitConnectors = fetchBtcKitConnectors.fetchBtcKitConnectors;
|
|
60
60
|
exports.fetchSatsConnectConnectors = fetchSatsConnectConnectors.fetchSatsConnectConnectors;
|
|
61
|
+
exports.stopBitcoinSatsConnectDiscovery = fetchSatsConnectConnectors.stopBitcoinSatsConnectDiscovery;
|
|
61
62
|
exports.hasSatsConnectFeature = hasSatsConnectFeature.hasSatsConnectFeature;
|
|
62
63
|
exports.getMempoolApiUrl = getMempoolApiUrl.getMempoolApiUrl;
|
|
63
64
|
exports.createPsbtOptions = createSignPsbtOptions.createPsbtOptions;
|
package/src/index.js
CHANGED
|
@@ -23,7 +23,7 @@ import { BitgetConnector } from './connectors/BitgetConnector/BitgetConnector.js
|
|
|
23
23
|
import { fetchBtcKitConnectors } from './utils/fetchBtcKitConnectors/fetchBtcKitConnectors.js';
|
|
24
24
|
export { fetchBtcKitConnectors } from './utils/fetchBtcKitConnectors/fetchBtcKitConnectors.js';
|
|
25
25
|
import { fetchSatsConnectConnectors } from './utils/fetchSatsConnectConnectors/fetchSatsConnectConnectors.js';
|
|
26
|
-
export { fetchSatsConnectConnectors } from './utils/fetchSatsConnectConnectors/fetchSatsConnectConnectors.js';
|
|
26
|
+
export { fetchSatsConnectConnectors, stopBitcoinSatsConnectDiscovery } from './utils/fetchSatsConnectConnectors/fetchSatsConnectConnectors.js';
|
|
27
27
|
export { hasSatsConnectFeature } from './utils/hasSatsConnectFeature.js';
|
|
28
28
|
export { getMempoolApiUrl } from './utils/getMempoolApiUrl.js';
|
|
29
29
|
export { createPsbtOptions } from './utils/psbt/createSignPsbtOptions.js';
|
|
@@ -42,13 +42,13 @@ class MempoolApiService {
|
|
|
42
42
|
const baseUrl = this.getBaseUrl(address);
|
|
43
43
|
const response = yield fetch(`${baseUrl}/address/${address}/utxo`);
|
|
44
44
|
if (!response.ok) {
|
|
45
|
-
throw new utils.DynamicError(`Failed to fetch UTXOs: ${response.statusText}
|
|
45
|
+
throw new utils.DynamicError(`Failed to fetch UTXOs: ${response.statusText}`, 'fetch_utxos_failed');
|
|
46
46
|
}
|
|
47
47
|
return response.json();
|
|
48
48
|
}
|
|
49
49
|
catch (error) {
|
|
50
50
|
logger.error('Error fetching UTXOs:', error);
|
|
51
|
-
throw new utils.DynamicError('Failed to fetch UTXOs');
|
|
51
|
+
throw new utils.DynamicError('Failed to fetch UTXOs', 'fetch_utxos_failed');
|
|
52
52
|
}
|
|
53
53
|
});
|
|
54
54
|
}
|
|
@@ -127,7 +127,7 @@ class MempoolApiService {
|
|
|
127
127
|
sendRawTransaction(address, rawTransaction) {
|
|
128
128
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
129
129
|
if (!rawTransaction) {
|
|
130
|
-
throw new utils.DynamicError('No transaction specified!');
|
|
130
|
+
throw new utils.DynamicError('No transaction specified!', 'no_transaction_specified');
|
|
131
131
|
}
|
|
132
132
|
const baseUrl = this.getBaseUrl(address);
|
|
133
133
|
const response = yield fetch(`${baseUrl}/tx`, {
|
|
@@ -140,7 +140,7 @@ class MempoolApiService {
|
|
|
140
140
|
if (!response.ok) {
|
|
141
141
|
const error = yield response.text();
|
|
142
142
|
logger.debug(`sendRawTransaction - response not ok: ${JSON.stringify(error)}`);
|
|
143
|
-
throw new utils.DynamicError('sendRawTransaction - failed to send transaction');
|
|
143
|
+
throw new utils.DynamicError('sendRawTransaction - failed to send transaction', 'sendrawtransaction_failed_to_send_transaction');
|
|
144
144
|
}
|
|
145
145
|
return response.text();
|
|
146
146
|
});
|
|
@@ -38,13 +38,13 @@ class MempoolApiService {
|
|
|
38
38
|
const baseUrl = this.getBaseUrl(address);
|
|
39
39
|
const response = yield fetch(`${baseUrl}/address/${address}/utxo`);
|
|
40
40
|
if (!response.ok) {
|
|
41
|
-
throw new DynamicError(`Failed to fetch UTXOs: ${response.statusText}
|
|
41
|
+
throw new DynamicError(`Failed to fetch UTXOs: ${response.statusText}`, 'fetch_utxos_failed');
|
|
42
42
|
}
|
|
43
43
|
return response.json();
|
|
44
44
|
}
|
|
45
45
|
catch (error) {
|
|
46
46
|
logger.error('Error fetching UTXOs:', error);
|
|
47
|
-
throw new DynamicError('Failed to fetch UTXOs');
|
|
47
|
+
throw new DynamicError('Failed to fetch UTXOs', 'fetch_utxos_failed');
|
|
48
48
|
}
|
|
49
49
|
});
|
|
50
50
|
}
|
|
@@ -123,7 +123,7 @@ class MempoolApiService {
|
|
|
123
123
|
sendRawTransaction(address, rawTransaction) {
|
|
124
124
|
return __awaiter(this, void 0, void 0, function* () {
|
|
125
125
|
if (!rawTransaction) {
|
|
126
|
-
throw new DynamicError('No transaction specified!');
|
|
126
|
+
throw new DynamicError('No transaction specified!', 'no_transaction_specified');
|
|
127
127
|
}
|
|
128
128
|
const baseUrl = this.getBaseUrl(address);
|
|
129
129
|
const response = yield fetch(`${baseUrl}/tx`, {
|
|
@@ -136,7 +136,7 @@ class MempoolApiService {
|
|
|
136
136
|
if (!response.ok) {
|
|
137
137
|
const error = yield response.text();
|
|
138
138
|
logger.debug(`sendRawTransaction - response not ok: ${JSON.stringify(error)}`);
|
|
139
|
-
throw new DynamicError('sendRawTransaction - failed to send transaction');
|
|
139
|
+
throw new DynamicError('sendRawTransaction - failed to send transaction', 'sendrawtransaction_failed_to_send_transaction');
|
|
140
140
|
}
|
|
141
141
|
return response.text();
|
|
142
142
|
});
|
|
@@ -36,7 +36,7 @@ class PsbtBuilderService {
|
|
|
36
36
|
if (accountAddress.toLowerCase().startsWith('bc1p') ||
|
|
37
37
|
accountAddress.toLowerCase().startsWith('tb1p')) {
|
|
38
38
|
logger.warn(`Account address ${accountAddress} appears to be Taproot. Only Native SegWit (P2WPKH) is supported.`);
|
|
39
|
-
throw new utils.DynamicError('Taproot addresses are not supported. Only Native SegWit (P2WPKH) addresses are allowed.');
|
|
39
|
+
throw new utils.DynamicError('Taproot addresses are not supported. Only Native SegWit (P2WPKH) addresses are allowed.', 'taproot_addresses_are_not_supported_only');
|
|
40
40
|
}
|
|
41
41
|
return utxos;
|
|
42
42
|
}
|
|
@@ -90,11 +90,11 @@ class PsbtBuilderService {
|
|
|
90
90
|
if (selectedUTXOs.length < allUTXOs.length) {
|
|
91
91
|
const allTotal = this.calculateUTXOTotal(allUTXOs);
|
|
92
92
|
if (allTotal < requiredAmount) {
|
|
93
|
-
throw new utils.DynamicError(`Insufficient funds. Available: ${allTotal / _const.SATOSHIS_PER_BTC} BTC (${allTotal} satoshis), Required: ${amountInSatoshisNumber / _const.SATOSHIS_PER_BTC} BTC (${amountInSatoshisNumber} satoshis) + fees
|
|
93
|
+
throw new utils.DynamicError(`Insufficient funds. Available: ${allTotal / _const.SATOSHIS_PER_BTC} BTC (${allTotal} satoshis), Required: ${amountInSatoshisNumber / _const.SATOSHIS_PER_BTC} BTC (${amountInSatoshisNumber} satoshis) + fees`, 'insufficient_funds_available_btc_satoshis_required');
|
|
94
94
|
}
|
|
95
95
|
return allUTXOs;
|
|
96
96
|
}
|
|
97
|
-
throw new utils.DynamicError(`Insufficient funds. Available: ${selectedTotal / _const.SATOSHIS_PER_BTC} BTC (${selectedTotal} satoshis), Required: ${amountInSatoshisNumber / _const.SATOSHIS_PER_BTC} BTC (${amountInSatoshisNumber} satoshis) + fees
|
|
97
|
+
throw new utils.DynamicError(`Insufficient funds. Available: ${selectedTotal / _const.SATOSHIS_PER_BTC} BTC (${selectedTotal} satoshis), Required: ${amountInSatoshisNumber / _const.SATOSHIS_PER_BTC} BTC (${amountInSatoshisNumber} satoshis) + fees`, 'insufficient_funds_available_btc_satoshis_required');
|
|
98
98
|
}
|
|
99
99
|
/**
|
|
100
100
|
* Calculates fee estimate and change amount, handling dust limit
|
|
@@ -148,7 +148,7 @@ class PsbtBuilderService {
|
|
|
148
148
|
pubkey: publicKeyPair.publicKey,
|
|
149
149
|
}).output;
|
|
150
150
|
if (!outputScript) {
|
|
151
|
-
throw new utils.DynamicError('Failed to create segwit output script');
|
|
151
|
+
throw new utils.DynamicError('Failed to create segwit output script', 'create_segwit_output_script');
|
|
152
152
|
}
|
|
153
153
|
// Convert txid from hex string to Buffer and reverse it (Bitcoin uses little-endian)
|
|
154
154
|
// The txid from the API is in big-endian format, but bitcoinjs-lib expects little-endian
|
|
@@ -176,7 +176,7 @@ class PsbtBuilderService {
|
|
|
176
176
|
*/
|
|
177
177
|
addOutputsToPsbt(psbt, recipientAddress, accountAddress, amountInSatoshisNumber, changeAmountNumber, hasChangeOutput, network) {
|
|
178
178
|
if (amountInSatoshisNumber < _const.DUST_LIMIT) {
|
|
179
|
-
throw new utils.DynamicError(`Amount is below dust limit of ${_const.DUST_LIMIT} satoshis (${_const.DUST_LIMIT / _const.SATOSHIS_PER_BTC} BTC)
|
|
179
|
+
throw new utils.DynamicError(`Amount is below dust limit of ${_const.DUST_LIMIT} satoshis (${_const.DUST_LIMIT / _const.SATOSHIS_PER_BTC} BTC)`, 'amount_is_below_dust_limit_of');
|
|
180
180
|
}
|
|
181
181
|
psbt.addOutput({
|
|
182
182
|
script: bitcoinjsLib.address.toOutputScript(recipientAddress, network),
|
|
@@ -201,11 +201,11 @@ class PsbtBuilderService {
|
|
|
201
201
|
const { accountAddress, recipientAddress, amountInSatoshis, publicKeyHex, network, feePriority = 'medium', } = options;
|
|
202
202
|
logger.debug(`buildPsbt called with feePriority: ${feePriority}, amount: ${amountInSatoshis} satoshis`);
|
|
203
203
|
if (amountInSatoshis <= BigInt(0)) {
|
|
204
|
-
throw new utils.DynamicError('Amount must be greater than 0');
|
|
204
|
+
throw new utils.DynamicError('Amount must be greater than 0', 'amount_must_be_greater_than_0');
|
|
205
205
|
}
|
|
206
206
|
const allUTXOs = yield this.mempoolApiService.getUTXOs(accountAddress);
|
|
207
207
|
if (allUTXOs.length === 0) {
|
|
208
|
-
throw new utils.DynamicError('No UTXOs found for this address');
|
|
208
|
+
throw new utils.DynamicError('No UTXOs found for this address', 'no_utxos_found_for_this_address');
|
|
209
209
|
}
|
|
210
210
|
const utxos = this.filterTaprootUTXOs(accountAddress, allUTXOs);
|
|
211
211
|
const publicKeyBuffer = Buffer.from(publicKeyHex, 'hex');
|
|
@@ -229,7 +229,7 @@ class PsbtBuilderService {
|
|
|
229
229
|
// Final check: ensure we have enough after final fee calculation
|
|
230
230
|
const maxToSpend = selectedTotalValue - feeEstimate;
|
|
231
231
|
if (maxToSpend < amountInSatoshisNumber) {
|
|
232
|
-
throw new utils.DynamicError(`Insufficient funds. Available: ${maxToSpend / _const.SATOSHIS_PER_BTC} BTC (${maxToSpend} satoshis), Required: ${amountInSatoshisNumber / _const.SATOSHIS_PER_BTC} BTC (${amountInSatoshisNumber} satoshis)
|
|
232
|
+
throw new utils.DynamicError(`Insufficient funds. Available: ${maxToSpend / _const.SATOSHIS_PER_BTC} BTC (${maxToSpend} satoshis), Required: ${amountInSatoshisNumber / _const.SATOSHIS_PER_BTC} BTC (${amountInSatoshisNumber} satoshis)`, 'insufficient_funds_available_btc_satoshis_required');
|
|
233
233
|
}
|
|
234
234
|
// Create PSBT and add inputs/outputs
|
|
235
235
|
const psbt = new bitcoinjsLib.Psbt({ network });
|
|
@@ -28,7 +28,7 @@ class PsbtBuilderService {
|
|
|
28
28
|
if (accountAddress.toLowerCase().startsWith('bc1p') ||
|
|
29
29
|
accountAddress.toLowerCase().startsWith('tb1p')) {
|
|
30
30
|
logger.warn(`Account address ${accountAddress} appears to be Taproot. Only Native SegWit (P2WPKH) is supported.`);
|
|
31
|
-
throw new DynamicError('Taproot addresses are not supported. Only Native SegWit (P2WPKH) addresses are allowed.');
|
|
31
|
+
throw new DynamicError('Taproot addresses are not supported. Only Native SegWit (P2WPKH) addresses are allowed.', 'taproot_addresses_are_not_supported_only');
|
|
32
32
|
}
|
|
33
33
|
return utxos;
|
|
34
34
|
}
|
|
@@ -82,11 +82,11 @@ class PsbtBuilderService {
|
|
|
82
82
|
if (selectedUTXOs.length < allUTXOs.length) {
|
|
83
83
|
const allTotal = this.calculateUTXOTotal(allUTXOs);
|
|
84
84
|
if (allTotal < requiredAmount) {
|
|
85
|
-
throw new DynamicError(`Insufficient funds. Available: ${allTotal / SATOSHIS_PER_BTC} BTC (${allTotal} satoshis), Required: ${amountInSatoshisNumber / SATOSHIS_PER_BTC} BTC (${amountInSatoshisNumber} satoshis) + fees
|
|
85
|
+
throw new DynamicError(`Insufficient funds. Available: ${allTotal / SATOSHIS_PER_BTC} BTC (${allTotal} satoshis), Required: ${amountInSatoshisNumber / SATOSHIS_PER_BTC} BTC (${amountInSatoshisNumber} satoshis) + fees`, 'insufficient_funds_available_btc_satoshis_required');
|
|
86
86
|
}
|
|
87
87
|
return allUTXOs;
|
|
88
88
|
}
|
|
89
|
-
throw new DynamicError(`Insufficient funds. Available: ${selectedTotal / SATOSHIS_PER_BTC} BTC (${selectedTotal} satoshis), Required: ${amountInSatoshisNumber / SATOSHIS_PER_BTC} BTC (${amountInSatoshisNumber} satoshis) + fees
|
|
89
|
+
throw new DynamicError(`Insufficient funds. Available: ${selectedTotal / SATOSHIS_PER_BTC} BTC (${selectedTotal} satoshis), Required: ${amountInSatoshisNumber / SATOSHIS_PER_BTC} BTC (${amountInSatoshisNumber} satoshis) + fees`, 'insufficient_funds_available_btc_satoshis_required');
|
|
90
90
|
}
|
|
91
91
|
/**
|
|
92
92
|
* Calculates fee estimate and change amount, handling dust limit
|
|
@@ -140,7 +140,7 @@ class PsbtBuilderService {
|
|
|
140
140
|
pubkey: publicKeyPair.publicKey,
|
|
141
141
|
}).output;
|
|
142
142
|
if (!outputScript) {
|
|
143
|
-
throw new DynamicError('Failed to create segwit output script');
|
|
143
|
+
throw new DynamicError('Failed to create segwit output script', 'create_segwit_output_script');
|
|
144
144
|
}
|
|
145
145
|
// Convert txid from hex string to Buffer and reverse it (Bitcoin uses little-endian)
|
|
146
146
|
// The txid from the API is in big-endian format, but bitcoinjs-lib expects little-endian
|
|
@@ -168,7 +168,7 @@ class PsbtBuilderService {
|
|
|
168
168
|
*/
|
|
169
169
|
addOutputsToPsbt(psbt, recipientAddress, accountAddress, amountInSatoshisNumber, changeAmountNumber, hasChangeOutput, network) {
|
|
170
170
|
if (amountInSatoshisNumber < DUST_LIMIT) {
|
|
171
|
-
throw new DynamicError(`Amount is below dust limit of ${DUST_LIMIT} satoshis (${DUST_LIMIT / SATOSHIS_PER_BTC} BTC)
|
|
171
|
+
throw new DynamicError(`Amount is below dust limit of ${DUST_LIMIT} satoshis (${DUST_LIMIT / SATOSHIS_PER_BTC} BTC)`, 'amount_is_below_dust_limit_of');
|
|
172
172
|
}
|
|
173
173
|
psbt.addOutput({
|
|
174
174
|
script: address.toOutputScript(recipientAddress, network),
|
|
@@ -193,11 +193,11 @@ class PsbtBuilderService {
|
|
|
193
193
|
const { accountAddress, recipientAddress, amountInSatoshis, publicKeyHex, network, feePriority = 'medium', } = options;
|
|
194
194
|
logger.debug(`buildPsbt called with feePriority: ${feePriority}, amount: ${amountInSatoshis} satoshis`);
|
|
195
195
|
if (amountInSatoshis <= BigInt(0)) {
|
|
196
|
-
throw new DynamicError('Amount must be greater than 0');
|
|
196
|
+
throw new DynamicError('Amount must be greater than 0', 'amount_must_be_greater_than_0');
|
|
197
197
|
}
|
|
198
198
|
const allUTXOs = yield this.mempoolApiService.getUTXOs(accountAddress);
|
|
199
199
|
if (allUTXOs.length === 0) {
|
|
200
|
-
throw new DynamicError('No UTXOs found for this address');
|
|
200
|
+
throw new DynamicError('No UTXOs found for this address', 'no_utxos_found_for_this_address');
|
|
201
201
|
}
|
|
202
202
|
const utxos = this.filterTaprootUTXOs(accountAddress, allUTXOs);
|
|
203
203
|
const publicKeyBuffer = Buffer.from(publicKeyHex, 'hex');
|
|
@@ -221,7 +221,7 @@ class PsbtBuilderService {
|
|
|
221
221
|
// Final check: ensure we have enough after final fee calculation
|
|
222
222
|
const maxToSpend = selectedTotalValue - feeEstimate;
|
|
223
223
|
if (maxToSpend < amountInSatoshisNumber) {
|
|
224
|
-
throw new DynamicError(`Insufficient funds. Available: ${maxToSpend / SATOSHIS_PER_BTC} BTC (${maxToSpend} satoshis), Required: ${amountInSatoshisNumber / SATOSHIS_PER_BTC} BTC (${amountInSatoshisNumber} satoshis)
|
|
224
|
+
throw new DynamicError(`Insufficient funds. Available: ${maxToSpend / SATOSHIS_PER_BTC} BTC (${maxToSpend} satoshis), Required: ${amountInSatoshisNumber / SATOSHIS_PER_BTC} BTC (${amountInSatoshisNumber} satoshis)`, 'insufficient_funds_available_btc_satoshis_required');
|
|
225
225
|
}
|
|
226
226
|
// Create PSBT and add inputs/outputs
|
|
227
227
|
const psbt = new Psbt({ network });
|
|
@@ -14,7 +14,7 @@ var _const = require('../../const.cjs');
|
|
|
14
14
|
*/
|
|
15
15
|
const btcToSatoshis = (btcAmount) => {
|
|
16
16
|
if (btcAmount < 0) {
|
|
17
|
-
throw new utils.DynamicError('BTC amount cannot be negative');
|
|
17
|
+
throw new utils.DynamicError('BTC amount cannot be negative', 'btc_amount_cannot_be_negative');
|
|
18
18
|
}
|
|
19
19
|
// Convert to satoshis and return as BigInt
|
|
20
20
|
const satoshis = Math.floor(btcAmount * _const.SATOSHIS_PER_BTC);
|
|
@@ -10,7 +10,7 @@ import { SATOSHIS_PER_BTC } from '../../const.js';
|
|
|
10
10
|
*/
|
|
11
11
|
const btcToSatoshis = (btcAmount) => {
|
|
12
12
|
if (btcAmount < 0) {
|
|
13
|
-
throw new DynamicError('BTC amount cannot be negative');
|
|
13
|
+
throw new DynamicError('BTC amount cannot be negative', 'btc_amount_cannot_be_negative');
|
|
14
14
|
}
|
|
15
15
|
// Convert to satoshis and return as BigInt
|
|
16
16
|
const satoshis = Math.floor(btcAmount * SATOSHIS_PER_BTC);
|
|
@@ -3,22 +3,92 @@
|
|
|
3
3
|
|
|
4
4
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
5
|
|
|
6
|
+
var app = require('@wallet-standard/app');
|
|
7
|
+
var walletConnectorCore = require('@dynamic-labs/wallet-connector-core');
|
|
6
8
|
require('../../../_virtual/_tslib.cjs');
|
|
7
9
|
require('sats-connect');
|
|
8
|
-
require('@dynamic-labs/wallet-connector-core');
|
|
9
10
|
require('@dynamic-labs/wallet-book');
|
|
10
11
|
require('@dynamic-labs/utils');
|
|
11
12
|
require('@dynamic-labs/sdk-api-core');
|
|
12
|
-
require('@wallet-standard/app');
|
|
13
13
|
var _const = require('../../const.cjs');
|
|
14
14
|
require('bitcoinjs-lib');
|
|
15
15
|
var BitcoinSatsConnectConnector = require('../../connectors/BitcoinSatsConnectConnector/BitcoinSatsConnectConnector.cjs');
|
|
16
16
|
require('jsontokens');
|
|
17
17
|
require('../../connectors/DynamicWaasBitcoinConnector/DynamicWaasBitcoinConnector.cjs');
|
|
18
|
+
var hasSatsConnectFeature = require('../hasSatsConnectFeature.cjs');
|
|
18
19
|
|
|
20
|
+
const BITCOIN_SATSCONNECT_POLL_INTERVAL_MS = 300;
|
|
21
|
+
const BITCOIN_SATSCONNECT_POLL_DURATION_MS = 5000;
|
|
22
|
+
let teardownBitcoinSatsConnectDiscovery = null;
|
|
23
|
+
/**
|
|
24
|
+
* Stops the active SatsConnect wallet-standard discovery (register listener + poll).
|
|
25
|
+
* @internal - Exposed for test cleanup.
|
|
26
|
+
*/
|
|
27
|
+
const stopBitcoinSatsConnectDiscovery = () => {
|
|
28
|
+
teardownBitcoinSatsConnectDiscovery === null || teardownBitcoinSatsConnectDiscovery === void 0 ? void 0 : teardownBitcoinSatsConnectDiscovery();
|
|
29
|
+
teardownBitcoinSatsConnectDiscovery = null;
|
|
30
|
+
};
|
|
31
|
+
const findSatsConnectWalletBookEntry = (walletName, walletBook) => {
|
|
32
|
+
var _a;
|
|
33
|
+
return Object.entries((_a = walletBook === null || walletBook === void 0 ? void 0 : walletBook.wallets) !== null && _a !== void 0 ? _a : {}).find(([, walletData]) => {
|
|
34
|
+
var _a;
|
|
35
|
+
return (_a = walletData.injectedConfig) === null || _a === void 0 ? void 0 : _a.some((config) => {
|
|
36
|
+
var _a, _b;
|
|
37
|
+
return config.chain === 'btc' &&
|
|
38
|
+
((_a = config.walletStandard) === null || _a === void 0 ? void 0 : _a.features.includes(_const.SATSCONNECT_FEATURE)) &&
|
|
39
|
+
((_b = config.walletStandard) === null || _b === void 0 ? void 0 : _b.providerId) &&
|
|
40
|
+
walletData.name === walletName;
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
const setupBitcoinSatsConnectDiscovery = (walletBook) => {
|
|
45
|
+
if (typeof window === 'undefined')
|
|
46
|
+
return;
|
|
47
|
+
teardownBitcoinSatsConnectDiscovery === null || teardownBitcoinSatsConnectDiscovery === void 0 ? void 0 : teardownBitcoinSatsConnectDiscovery();
|
|
48
|
+
const discoveredWallets = new Set();
|
|
49
|
+
const { get, on } = app.getWallets();
|
|
50
|
+
const initialWallets = get();
|
|
51
|
+
// Seed already-present wallets so the listener and poll skip them.
|
|
52
|
+
initialWallets.forEach((wallet) => {
|
|
53
|
+
if (hasSatsConnectFeature.hasSatsConnectFeature(wallet.features) &&
|
|
54
|
+
findSatsConnectWalletBookEntry(wallet.name, walletBook)) {
|
|
55
|
+
discoveredWallets.add(wallet.name);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
const handleWallet = (wallet) => {
|
|
59
|
+
if (discoveredWallets.has(wallet.name))
|
|
60
|
+
return;
|
|
61
|
+
if (!hasSatsConnectFeature.hasSatsConnectFeature(wallet.features))
|
|
62
|
+
return;
|
|
63
|
+
const entry = findSatsConnectWalletBookEntry(wallet.name, walletBook);
|
|
64
|
+
if (!entry)
|
|
65
|
+
return;
|
|
66
|
+
discoveredWallets.add(wallet.name);
|
|
67
|
+
const [key, walletData] = entry;
|
|
68
|
+
const connectorName = walletData.shortName || walletData.name;
|
|
69
|
+
const injectedConnectorConstructor = class extends BitcoinSatsConnectConnector.BitcoinSatsConnectConnector {
|
|
70
|
+
constructor(props) {
|
|
71
|
+
super(Object.assign(Object.assign({}, props), { overrideKey: key, walletData }));
|
|
72
|
+
this.name = connectorName;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
walletConnectorCore.walletConnectorEvents.emit('providerInjected', {
|
|
76
|
+
injectedConnectorConstructor,
|
|
77
|
+
});
|
|
78
|
+
};
|
|
79
|
+
const removeRegisterListener = on('register', handleWallet);
|
|
80
|
+
const pollIntervalId = setInterval(() => get().forEach(handleWallet), BITCOIN_SATSCONNECT_POLL_INTERVAL_MS);
|
|
81
|
+
const pollTimeoutId = setTimeout(() => clearInterval(pollIntervalId), BITCOIN_SATSCONNECT_POLL_DURATION_MS);
|
|
82
|
+
teardownBitcoinSatsConnectDiscovery = () => {
|
|
83
|
+
removeRegisterListener === null || removeRegisterListener === void 0 ? void 0 : removeRegisterListener();
|
|
84
|
+
clearInterval(pollIntervalId);
|
|
85
|
+
clearTimeout(pollTimeoutId);
|
|
86
|
+
};
|
|
87
|
+
};
|
|
19
88
|
const fetchSatsConnectConnectors = ({ walletBook, }) => {
|
|
20
89
|
var _a;
|
|
21
|
-
|
|
90
|
+
setupBitcoinSatsConnectDiscovery(walletBook);
|
|
91
|
+
return (Object.entries((_a = walletBook === null || walletBook === void 0 ? void 0 : walletBook.wallets) !== null && _a !== void 0 ? _a : {})
|
|
22
92
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
23
93
|
.filter(([_, wallet]) => {
|
|
24
94
|
var _a;
|
|
@@ -38,7 +108,8 @@ const fetchSatsConnectConnectors = ({ walletBook, }) => {
|
|
|
38
108
|
this.name = name;
|
|
39
109
|
}
|
|
40
110
|
};
|
|
41
|
-
});
|
|
111
|
+
}));
|
|
42
112
|
};
|
|
43
113
|
|
|
44
114
|
exports.fetchSatsConnectConnectors = fetchSatsConnectConnectors;
|
|
115
|
+
exports.stopBitcoinSatsConnectDiscovery = stopBitcoinSatsConnectDiscovery;
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { WalletBookSchema } from '@dynamic-labs/wallet-book';
|
|
2
2
|
import { WalletConnectorConstructor } from '@dynamic-labs/wallet-connector-core';
|
|
3
|
+
/**
|
|
4
|
+
* Stops the active SatsConnect wallet-standard discovery (register listener + poll).
|
|
5
|
+
* @internal - Exposed for test cleanup.
|
|
6
|
+
*/
|
|
7
|
+
export declare const stopBitcoinSatsConnectDiscovery: () => void;
|
|
3
8
|
export declare const fetchSatsConnectConnectors: ({ walletBook, }: {
|
|
4
9
|
walletBook: WalletBookSchema;
|
|
5
10
|
}) => WalletConnectorConstructor[];
|
|
@@ -1,20 +1,90 @@
|
|
|
1
1
|
'use client'
|
|
2
|
+
import { getWallets } from '@wallet-standard/app';
|
|
3
|
+
import { walletConnectorEvents } from '@dynamic-labs/wallet-connector-core';
|
|
2
4
|
import '../../../_virtual/_tslib.js';
|
|
3
5
|
import 'sats-connect';
|
|
4
|
-
import '@dynamic-labs/wallet-connector-core';
|
|
5
6
|
import '@dynamic-labs/wallet-book';
|
|
6
7
|
import '@dynamic-labs/utils';
|
|
7
8
|
import '@dynamic-labs/sdk-api-core';
|
|
8
|
-
import '@wallet-standard/app';
|
|
9
9
|
import { SATSCONNECT_FEATURE } from '../../const.js';
|
|
10
10
|
import 'bitcoinjs-lib';
|
|
11
11
|
import { BitcoinSatsConnectConnector } from '../../connectors/BitcoinSatsConnectConnector/BitcoinSatsConnectConnector.js';
|
|
12
12
|
import 'jsontokens';
|
|
13
13
|
import '../../connectors/DynamicWaasBitcoinConnector/DynamicWaasBitcoinConnector.js';
|
|
14
|
+
import { hasSatsConnectFeature } from '../hasSatsConnectFeature.js';
|
|
14
15
|
|
|
16
|
+
const BITCOIN_SATSCONNECT_POLL_INTERVAL_MS = 300;
|
|
17
|
+
const BITCOIN_SATSCONNECT_POLL_DURATION_MS = 5000;
|
|
18
|
+
let teardownBitcoinSatsConnectDiscovery = null;
|
|
19
|
+
/**
|
|
20
|
+
* Stops the active SatsConnect wallet-standard discovery (register listener + poll).
|
|
21
|
+
* @internal - Exposed for test cleanup.
|
|
22
|
+
*/
|
|
23
|
+
const stopBitcoinSatsConnectDiscovery = () => {
|
|
24
|
+
teardownBitcoinSatsConnectDiscovery === null || teardownBitcoinSatsConnectDiscovery === void 0 ? void 0 : teardownBitcoinSatsConnectDiscovery();
|
|
25
|
+
teardownBitcoinSatsConnectDiscovery = null;
|
|
26
|
+
};
|
|
27
|
+
const findSatsConnectWalletBookEntry = (walletName, walletBook) => {
|
|
28
|
+
var _a;
|
|
29
|
+
return Object.entries((_a = walletBook === null || walletBook === void 0 ? void 0 : walletBook.wallets) !== null && _a !== void 0 ? _a : {}).find(([, walletData]) => {
|
|
30
|
+
var _a;
|
|
31
|
+
return (_a = walletData.injectedConfig) === null || _a === void 0 ? void 0 : _a.some((config) => {
|
|
32
|
+
var _a, _b;
|
|
33
|
+
return config.chain === 'btc' &&
|
|
34
|
+
((_a = config.walletStandard) === null || _a === void 0 ? void 0 : _a.features.includes(SATSCONNECT_FEATURE)) &&
|
|
35
|
+
((_b = config.walletStandard) === null || _b === void 0 ? void 0 : _b.providerId) &&
|
|
36
|
+
walletData.name === walletName;
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
const setupBitcoinSatsConnectDiscovery = (walletBook) => {
|
|
41
|
+
if (typeof window === 'undefined')
|
|
42
|
+
return;
|
|
43
|
+
teardownBitcoinSatsConnectDiscovery === null || teardownBitcoinSatsConnectDiscovery === void 0 ? void 0 : teardownBitcoinSatsConnectDiscovery();
|
|
44
|
+
const discoveredWallets = new Set();
|
|
45
|
+
const { get, on } = getWallets();
|
|
46
|
+
const initialWallets = get();
|
|
47
|
+
// Seed already-present wallets so the listener and poll skip them.
|
|
48
|
+
initialWallets.forEach((wallet) => {
|
|
49
|
+
if (hasSatsConnectFeature(wallet.features) &&
|
|
50
|
+
findSatsConnectWalletBookEntry(wallet.name, walletBook)) {
|
|
51
|
+
discoveredWallets.add(wallet.name);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
const handleWallet = (wallet) => {
|
|
55
|
+
if (discoveredWallets.has(wallet.name))
|
|
56
|
+
return;
|
|
57
|
+
if (!hasSatsConnectFeature(wallet.features))
|
|
58
|
+
return;
|
|
59
|
+
const entry = findSatsConnectWalletBookEntry(wallet.name, walletBook);
|
|
60
|
+
if (!entry)
|
|
61
|
+
return;
|
|
62
|
+
discoveredWallets.add(wallet.name);
|
|
63
|
+
const [key, walletData] = entry;
|
|
64
|
+
const connectorName = walletData.shortName || walletData.name;
|
|
65
|
+
const injectedConnectorConstructor = class extends BitcoinSatsConnectConnector {
|
|
66
|
+
constructor(props) {
|
|
67
|
+
super(Object.assign(Object.assign({}, props), { overrideKey: key, walletData }));
|
|
68
|
+
this.name = connectorName;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
walletConnectorEvents.emit('providerInjected', {
|
|
72
|
+
injectedConnectorConstructor,
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
const removeRegisterListener = on('register', handleWallet);
|
|
76
|
+
const pollIntervalId = setInterval(() => get().forEach(handleWallet), BITCOIN_SATSCONNECT_POLL_INTERVAL_MS);
|
|
77
|
+
const pollTimeoutId = setTimeout(() => clearInterval(pollIntervalId), BITCOIN_SATSCONNECT_POLL_DURATION_MS);
|
|
78
|
+
teardownBitcoinSatsConnectDiscovery = () => {
|
|
79
|
+
removeRegisterListener === null || removeRegisterListener === void 0 ? void 0 : removeRegisterListener();
|
|
80
|
+
clearInterval(pollIntervalId);
|
|
81
|
+
clearTimeout(pollTimeoutId);
|
|
82
|
+
};
|
|
83
|
+
};
|
|
15
84
|
const fetchSatsConnectConnectors = ({ walletBook, }) => {
|
|
16
85
|
var _a;
|
|
17
|
-
|
|
86
|
+
setupBitcoinSatsConnectDiscovery(walletBook);
|
|
87
|
+
return (Object.entries((_a = walletBook === null || walletBook === void 0 ? void 0 : walletBook.wallets) !== null && _a !== void 0 ? _a : {})
|
|
18
88
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
19
89
|
.filter(([_, wallet]) => {
|
|
20
90
|
var _a;
|
|
@@ -34,7 +104,7 @@ const fetchSatsConnectConnectors = ({ walletBook, }) => {
|
|
|
34
104
|
this.name = name;
|
|
35
105
|
}
|
|
36
106
|
};
|
|
37
|
-
});
|
|
107
|
+
}));
|
|
38
108
|
};
|
|
39
109
|
|
|
40
|
-
export { fetchSatsConnectConnectors };
|
|
110
|
+
export { fetchSatsConnectConnectors, stopBitcoinSatsConnectDiscovery };
|
|
@@ -11,9 +11,9 @@ const validateAddress = (psbt, signingAddress, index, inputAtIndex) => {
|
|
|
11
11
|
// to be able to compare it to the address provided in the request for the current index
|
|
12
12
|
const extractedAddress = extractAddressFromInput.extractAddressFromInput(psbt, index, inputAtIndex);
|
|
13
13
|
if (!extractedAddress)
|
|
14
|
-
throw new utils.DynamicError(`validateAddress - input not found for the given address: ${signingAddress}
|
|
14
|
+
throw new utils.DynamicError(`validateAddress - input not found for the given address: ${signingAddress}`, 'validateaddress_input_not_found_for_the');
|
|
15
15
|
if (extractedAddress !== signingAddress)
|
|
16
|
-
throw new utils.DynamicError('validateAddress - address mismatch with index');
|
|
16
|
+
throw new utils.DynamicError('validateAddress - address mismatch with index', 'validateaddress_address_mismatch_with_index');
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
exports.validateAddress = validateAddress;
|
|
@@ -7,9 +7,9 @@ const validateAddress = (psbt, signingAddress, index, inputAtIndex) => {
|
|
|
7
7
|
// to be able to compare it to the address provided in the request for the current index
|
|
8
8
|
const extractedAddress = extractAddressFromInput(psbt, index, inputAtIndex);
|
|
9
9
|
if (!extractedAddress)
|
|
10
|
-
throw new DynamicError(`validateAddress - input not found for the given address: ${signingAddress}
|
|
10
|
+
throw new DynamicError(`validateAddress - input not found for the given address: ${signingAddress}`, 'validateaddress_input_not_found_for_the');
|
|
11
11
|
if (extractedAddress !== signingAddress)
|
|
12
|
-
throw new DynamicError('validateAddress - address mismatch with index');
|
|
12
|
+
throw new DynamicError('validateAddress - address mismatch with index', 'validateaddress_address_mismatch_with_index');
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
export { validateAddress };
|