@dynamic-labs/stellar 4.67.3-device-registration.0 → 4.69.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 +15 -10
- package/package.cjs +1 -1
- package/package.js +1 -1
- package/package.json +8 -8
- package/src/StellarLocalStorageCache.cjs +17 -0
- package/src/StellarLocalStorageCache.d.ts +7 -0
- package/src/StellarLocalStorageCache.js +17 -0
- package/src/connectors/StellarWalletConnector/StellarWalletConnector.cjs +71 -31
- package/src/connectors/StellarWalletConnector/StellarWalletConnector.d.ts +10 -0
- package/src/connectors/StellarWalletConnector/StellarWalletConnector.js +72 -32
package/CHANGELOG.md
CHANGED
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
2
|
+
## [4.69.0](https://github.com/dynamic-labs/dynamic-auth/compare/v4.68.0...v4.69.0) (2026-03-19)
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
### Features
|
|
6
6
|
|
|
7
|
-
* add
|
|
8
|
-
* add
|
|
9
|
-
*
|
|
10
|
-
* add step-up auth for email and SMS credential updates ([#10676](https://github.com/dynamic-labs/dynamic-auth/issues/10676)) ([4c7f0a5](https://github.com/dynamic-labs/dynamic-auth/commit/4c7f0a5330e557aea4db85359f7ac10d3c7545a5))
|
|
11
|
-
* add step-up auth for wallet link and unlink ([#10678](https://github.com/dynamic-labs/dynamic-auth/issues/10678)) ([8a015ca](https://github.com/dynamic-labs/dynamic-auth/commit/8a015ca0fd0bda71559c21b811b7e6acb43a7909))
|
|
12
|
-
* add TrustedDevicesSection and ManageTrustedDevicesView ([#10639](https://github.com/dynamic-labs/dynamic-auth/issues/10639)) ([17df870](https://github.com/dynamic-labs/dynamic-auth/commit/17df870caa34a8428d65510e5b3c9e9c7b93cea2))
|
|
13
|
-
* add useSyncDeviceRegistrationFlow ([#10640](https://github.com/dynamic-labs/dynamic-auth/issues/10640)) ([8c7752d](https://github.com/dynamic-labs/dynamic-auth/commit/8c7752d7a8afedaa3cc99fad83091586f7b6107e))
|
|
14
|
-
* **sdk-react-core:** prompt step-up auth before export private key ([#10647](https://github.com/dynamic-labs/dynamic-auth/issues/10647)) ([a39d886](https://github.com/dynamic-labs/dynamic-auth/commit/a39d88643af83484aae09332adcd05df8c0f923c))
|
|
15
|
-
* **step-up:** reauth flow with signInCredentialId and choose-method UI ([#10644](https://github.com/dynamic-labs/dynamic-auth/issues/10644)) ([086a97f](https://github.com/dynamic-labs/dynamic-auth/commit/086a97f27d908780b17f49f8a85ce88c34f61ed8))
|
|
7
|
+
* add MoonPay icon to iconic ([#10666](https://github.com/dynamic-labs/dynamic-auth/issues/10666)) ([19d437b](https://github.com/dynamic-labs/dynamic-auth/commit/19d437b1a55e2b7800d65f375217b735f29d10eb))
|
|
8
|
+
* add step-up auth for OAuth and email credential link and unlink ([#10679](https://github.com/dynamic-labs/dynamic-auth/issues/10679)) ([ba48be8](https://github.com/dynamic-labs/dynamic-auth/commit/ba48be874e44c033563ae107e46a1b90f3c307d6))
|
|
9
|
+
* replace React session chaining with pure SDK implementation ([#10423](https://github.com/dynamic-labs/dynamic-auth/issues/10423)) ([2279421](https://github.com/dynamic-labs/dynamic-auth/commit/227942153828192d316d19295a69d9e7a5baa85c))
|
|
16
10
|
|
|
17
11
|
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* csp nonce global styles ([#10591](https://github.com/dynamic-labs/dynamic-auth/issues/10591)) ([6ea9c14](https://github.com/dynamic-labs/dynamic-auth/commit/6ea9c141055b3a337d8841dbebec00c7a3cb5d93))
|
|
15
|
+
|
|
16
|
+
## [4.68.0](https://github.com/dynamic-labs/dynamic-auth/compare/v4.67.2...v4.68.0) (2026-03-19)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Features
|
|
20
|
+
|
|
21
|
+
* add freighter ledger support on stellar ([#10665](https://github.com/dynamic-labs/dynamic-auth/issues/10665)) ([dedbaa6](https://github.com/dynamic-labs/dynamic-auth/commit/dedbaa6038f282b9e41b9166cad3ad6d5032948d))
|
|
22
|
+
|
|
18
23
|
### Bug Fixes
|
|
19
24
|
|
|
20
25
|
* close auth flow on re-login when user already has embedded wallets ([#10641](https://github.com/dynamic-labs/dynamic-auth/issues/10641)) ([1aab930](https://github.com/dynamic-labs/dynamic-auth/commit/1aab9307c904f79bc0534026547fc112c55f6dc9))
|
package/package.cjs
CHANGED
package/package.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs/stellar",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.69.0",
|
|
4
4
|
"description": "A React SDK for implementing Stellar wallet web3 authentication and authorization to your website.",
|
|
5
5
|
"author": "Dynamic Labs, Inc.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -20,15 +20,15 @@
|
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@dynamic-labs/sdk-api-core": "0.0.907",
|
|
22
22
|
"@stellar/stellar-sdk": "14.4.3",
|
|
23
|
-
"@dynamic-labs/wallet-connector-core": "4.
|
|
24
|
-
"@dynamic-labs/assert-package-version": "4.
|
|
23
|
+
"@dynamic-labs/wallet-connector-core": "4.69.0",
|
|
24
|
+
"@dynamic-labs/assert-package-version": "4.69.0",
|
|
25
25
|
"@lobstrco/signer-extension-api": "2.0.0",
|
|
26
26
|
"@stellar/freighter-api": "6.0.1",
|
|
27
|
-
"@dynamic-labs/logger": "4.
|
|
28
|
-
"@dynamic-labs/types": "4.
|
|
29
|
-
"@dynamic-labs/utils": "4.
|
|
30
|
-
"@dynamic-labs/waas": "4.
|
|
31
|
-
"@dynamic-labs/wallet-book": "4.
|
|
27
|
+
"@dynamic-labs/logger": "4.69.0",
|
|
28
|
+
"@dynamic-labs/types": "4.69.0",
|
|
29
|
+
"@dynamic-labs/utils": "4.69.0",
|
|
30
|
+
"@dynamic-labs/waas": "4.69.0",
|
|
31
|
+
"@dynamic-labs/wallet-book": "4.69.0",
|
|
32
32
|
"eventemitter3": "5.0.1"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {}
|
|
@@ -9,6 +9,7 @@ var utils = require('@dynamic-labs/utils');
|
|
|
9
9
|
class StellarLocalStorageCache {
|
|
10
10
|
constructor(key) {
|
|
11
11
|
this.CONNECTED_ACCOUNTS_KEY = `stellar_${key}_connectedAccounts`;
|
|
12
|
+
this.NETWORK_KEY = `stellar_${key}_network`;
|
|
12
13
|
}
|
|
13
14
|
getActiveAccount() {
|
|
14
15
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
@@ -60,6 +61,22 @@ class StellarLocalStorageCache {
|
|
|
60
61
|
return utils.removeItemAsync(this.CONNECTED_ACCOUNTS_KEY);
|
|
61
62
|
});
|
|
62
63
|
}
|
|
64
|
+
getStoredNetwork() {
|
|
65
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
66
|
+
const stored = yield utils.getItemAsync(this.NETWORK_KEY);
|
|
67
|
+
return stored !== null && stored !== void 0 ? stored : undefined;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
setStoredNetwork(networkId) {
|
|
71
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
72
|
+
return utils.setItemAsync(this.NETWORK_KEY, networkId);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
clearStoredNetwork() {
|
|
76
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
77
|
+
return utils.removeItemAsync(this.NETWORK_KEY);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
63
80
|
}
|
|
64
81
|
|
|
65
82
|
exports.StellarLocalStorageCache = StellarLocalStorageCache;
|
|
@@ -12,18 +12,25 @@ type StellarActiveAccount = {
|
|
|
12
12
|
};
|
|
13
13
|
export declare class StellarLocalStorageCache implements IStellarSessionCache {
|
|
14
14
|
private readonly CONNECTED_ACCOUNTS_KEY;
|
|
15
|
+
private readonly NETWORK_KEY;
|
|
15
16
|
constructor(key: string);
|
|
16
17
|
getActiveAccount(): Promise<StellarActiveAccount | undefined>;
|
|
17
18
|
getConnectedAccounts(): Promise<StellarConnectedAccounts | undefined>;
|
|
18
19
|
getConnectedAccount(address: string): Promise<StellarConnectedAccount | undefined>;
|
|
19
20
|
setConnectedAccount(address: string, account: StellarConnectedAccount): Promise<void>;
|
|
20
21
|
clearConnectedAcccounts(): Promise<void>;
|
|
22
|
+
getStoredNetwork(): Promise<string | undefined>;
|
|
23
|
+
setStoredNetwork(networkId: string): Promise<void>;
|
|
24
|
+
clearStoredNetwork(): Promise<void>;
|
|
21
25
|
}
|
|
22
26
|
export interface IStellarSessionCache {
|
|
23
27
|
clearConnectedAcccounts(): Promise<void>;
|
|
28
|
+
clearStoredNetwork(): Promise<void>;
|
|
24
29
|
getActiveAccount(): Promise<StellarActiveAccount | undefined>;
|
|
25
30
|
getConnectedAccount(address: string): Promise<StellarConnectedAccount | undefined>;
|
|
26
31
|
getConnectedAccounts(): Promise<StellarConnectedAccounts | undefined>;
|
|
32
|
+
getStoredNetwork(): Promise<string | undefined>;
|
|
27
33
|
setConnectedAccount(address: string, account: StellarConnectedAccount): Promise<void>;
|
|
34
|
+
setStoredNetwork(networkId: string): Promise<void>;
|
|
28
35
|
}
|
|
29
36
|
export {};
|
|
@@ -5,6 +5,7 @@ import { getItemAsync, setItemAsync, removeItemAsync } from '@dynamic-labs/utils
|
|
|
5
5
|
class StellarLocalStorageCache {
|
|
6
6
|
constructor(key) {
|
|
7
7
|
this.CONNECTED_ACCOUNTS_KEY = `stellar_${key}_connectedAccounts`;
|
|
8
|
+
this.NETWORK_KEY = `stellar_${key}_network`;
|
|
8
9
|
}
|
|
9
10
|
getActiveAccount() {
|
|
10
11
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -56,6 +57,22 @@ class StellarLocalStorageCache {
|
|
|
56
57
|
return removeItemAsync(this.CONNECTED_ACCOUNTS_KEY);
|
|
57
58
|
});
|
|
58
59
|
}
|
|
60
|
+
getStoredNetwork() {
|
|
61
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
62
|
+
const stored = yield getItemAsync(this.NETWORK_KEY);
|
|
63
|
+
return stored !== null && stored !== void 0 ? stored : undefined;
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
setStoredNetwork(networkId) {
|
|
67
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
68
|
+
return setItemAsync(this.NETWORK_KEY, networkId);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
clearStoredNetwork() {
|
|
72
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
73
|
+
return removeItemAsync(this.NETWORK_KEY);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
59
76
|
}
|
|
60
77
|
|
|
61
78
|
export { StellarLocalStorageCache };
|
|
@@ -9,9 +9,8 @@ var logger = require('@dynamic-labs/logger');
|
|
|
9
9
|
var utils = require('@dynamic-labs/utils');
|
|
10
10
|
var walletConnectorCore = require('@dynamic-labs/wallet-connector-core');
|
|
11
11
|
var StellarWallet = require('../../wallet/StellarWallet.cjs');
|
|
12
|
-
var getNetworkFromAddress = require('../../utils/getNetworkFromAddress.cjs');
|
|
13
|
-
var StellarUiTransaction = require('../../utils/StellarUiTransaction/StellarUiTransaction.cjs');
|
|
14
12
|
var StellarLocalStorageCache = require('../../StellarLocalStorageCache.cjs');
|
|
13
|
+
var StellarUiTransaction = require('../../utils/StellarUiTransaction/StellarUiTransaction.cjs');
|
|
15
14
|
|
|
16
15
|
const HORIZON_MAINNET_URL = 'https://horizon.stellar.org';
|
|
17
16
|
const HORIZON_TESTNET_URL = 'https://horizon-testnet.stellar.org';
|
|
@@ -37,12 +36,17 @@ class StellarWalletConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
37
36
|
this.isConnecting = false;
|
|
38
37
|
/** Flag to track if connection was cancelled by disconnect */
|
|
39
38
|
this.connectionCancelled = false;
|
|
39
|
+
this.isHardwareWalletEnabled = false;
|
|
40
40
|
this.name = name;
|
|
41
41
|
this.logger = new logger.Logger(this.name);
|
|
42
42
|
this.stellarNetworks = (_a = opts.stellarNetworks) !== null && _a !== void 0 ? _a : [];
|
|
43
43
|
this.overrideKey = this.key;
|
|
44
44
|
this.cache = new StellarLocalStorageCache.StellarLocalStorageCache(this.overrideKey);
|
|
45
45
|
}
|
|
46
|
+
canConnectWithHardwareWallet() {
|
|
47
|
+
var _a;
|
|
48
|
+
return Boolean((_a = this.metadata.supportedHardwareWallets) === null || _a === void 0 ? void 0 : _a.includes('ledger'));
|
|
49
|
+
}
|
|
46
50
|
getEnabledNetworks() {
|
|
47
51
|
return this.stellarNetworks;
|
|
48
52
|
}
|
|
@@ -61,50 +65,35 @@ class StellarWalletConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
61
65
|
const network = this.stellarNetworks.find((n) => { var _a, _b; return ((_a = n.chainId) === null || _a === void 0 ? void 0 : _a.toString()) === idStr || ((_b = n.networkId) === null || _b === void 0 ? void 0 : _b.toString()) === idStr; });
|
|
62
66
|
if (network) {
|
|
63
67
|
this.selectedNetwork = network;
|
|
68
|
+
yield this.cache.setStoredNetwork(String(network.chainId));
|
|
64
69
|
this.emit('chainChange', { chain: String(network.chainId) });
|
|
65
70
|
}
|
|
66
71
|
});
|
|
67
72
|
}
|
|
68
73
|
getNetwork() {
|
|
69
74
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
70
|
-
var _a;
|
|
71
75
|
if (!this.stellarNetworks.length) {
|
|
72
76
|
return undefined;
|
|
73
77
|
}
|
|
74
|
-
// If selectedNetwork is already set, return its chainId
|
|
75
78
|
if (this.selectedNetwork) {
|
|
76
79
|
return String(this.selectedNetwork.chainId);
|
|
77
80
|
}
|
|
78
|
-
//
|
|
79
|
-
const
|
|
80
|
-
if (
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
const detectedChainId = yield getNetworkFromAddress.getNetworkFromAddress(address, this.stellarNetworks[0]);
|
|
84
|
-
if (!detectedChainId) {
|
|
85
|
-
return undefined;
|
|
86
|
-
}
|
|
87
|
-
// Find and set the selectedNetwork based on detected chainId
|
|
88
|
-
this.selectedNetwork = this.stellarNetworks.find((n) => n.chainId.toString() === detectedChainId);
|
|
89
|
-
// If no exact match found, determine if it's testnet or mainnet based on the chainId
|
|
90
|
-
// and select the appropriate network from stellarNetworks
|
|
91
|
-
if (!this.selectedNetwork) {
|
|
92
|
-
// Testnet chainId starts with 'cee0302d', mainnet with '7ac33997'
|
|
93
|
-
const isTestnet = detectedChainId.startsWith('cee0302d');
|
|
94
|
-
this.selectedNetwork = this.stellarNetworks.find((n) => {
|
|
81
|
+
// Check localStorage cache for a previously stored network ID
|
|
82
|
+
const storedNetworkId = yield this.cache.getStoredNetwork();
|
|
83
|
+
if (storedNetworkId) {
|
|
84
|
+
const cachedNetwork = this.stellarNetworks.find((n) => {
|
|
95
85
|
var _a, _b;
|
|
96
|
-
return
|
|
97
|
-
|
|
98
|
-
: !((_b = n.name) === null || _b === void 0 ? void 0 : _b.toLowerCase().includes('testnet'));
|
|
86
|
+
return ((_a = n.chainId) === null || _a === void 0 ? void 0 : _a.toString()) === storedNetworkId ||
|
|
87
|
+
((_b = n.networkId) === null || _b === void 0 ? void 0 : _b.toString()) === storedNetworkId;
|
|
99
88
|
});
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
89
|
+
if (cachedNetwork) {
|
|
90
|
+
this.selectedNetwork = cachedNetwork;
|
|
91
|
+
return String(cachedNetwork.chainId);
|
|
103
92
|
}
|
|
104
93
|
}
|
|
105
|
-
//
|
|
106
|
-
|
|
107
|
-
return String(
|
|
94
|
+
// Fall back to the first configured network
|
|
95
|
+
[this.selectedNetwork] = this.stellarNetworks;
|
|
96
|
+
return String(this.selectedNetwork.chainId);
|
|
108
97
|
});
|
|
109
98
|
}
|
|
110
99
|
/**
|
|
@@ -195,8 +184,10 @@ class StellarWalletConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
195
184
|
if (!provider) {
|
|
196
185
|
// Still clear state even if no provider
|
|
197
186
|
this.connectedPublicKey = undefined;
|
|
187
|
+
this.selectedNetwork = undefined;
|
|
198
188
|
this.getAddressPromise = undefined;
|
|
199
189
|
yield this.cache.clearConnectedAcccounts();
|
|
190
|
+
yield this.cache.clearStoredNetwork();
|
|
200
191
|
return;
|
|
201
192
|
}
|
|
202
193
|
try {
|
|
@@ -207,8 +198,10 @@ class StellarWalletConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
207
198
|
}
|
|
208
199
|
// Clear all cached state
|
|
209
200
|
this.connectedPublicKey = undefined;
|
|
201
|
+
this.selectedNetwork = undefined;
|
|
210
202
|
this.getAddressPromise = undefined;
|
|
211
203
|
yield this.cache.clearConnectedAcccounts();
|
|
204
|
+
yield this.cache.clearStoredNetwork();
|
|
212
205
|
});
|
|
213
206
|
}
|
|
214
207
|
/**
|
|
@@ -228,8 +221,40 @@ class StellarWalletConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
228
221
|
});
|
|
229
222
|
});
|
|
230
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* Signs a message using a Stellar ManageData transaction.
|
|
226
|
+
* Used as a fallback for hardware wallets (e.g. Ledger via Freighter) that
|
|
227
|
+
* cannot sign arbitrary data directly. Returns the signed transaction XDR.
|
|
228
|
+
*/
|
|
229
|
+
signMessageViaTransaction(message) {
|
|
230
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
231
|
+
const address = yield this.getAddress();
|
|
232
|
+
if (!address) {
|
|
233
|
+
throw new utils.DynamicError('No connected address for hardware wallet signing');
|
|
234
|
+
}
|
|
235
|
+
const horizonServer = yield this.getHorizonServer();
|
|
236
|
+
const networkPassphrase = yield this.getNetworkPassphrase();
|
|
237
|
+
const account = yield horizonServer.loadAccount(address);
|
|
238
|
+
const messageBytes = Buffer.from(message);
|
|
239
|
+
// ManageData value is limited to 64 bytes; hash longer messages with SHA-256
|
|
240
|
+
const value = messageBytes.length > 64 ? stellarSdk.hash(messageBytes) : messageBytes;
|
|
241
|
+
const transaction = new stellarSdk.TransactionBuilder(account, {
|
|
242
|
+
fee: '100',
|
|
243
|
+
networkPassphrase,
|
|
244
|
+
})
|
|
245
|
+
.addOperation(stellarSdk.Operation.manageData({
|
|
246
|
+
name: 'dynamic:auth',
|
|
247
|
+
value,
|
|
248
|
+
}))
|
|
249
|
+
.setTimeout(30)
|
|
250
|
+
.build();
|
|
251
|
+
return this.signTransaction(transaction.toXDR());
|
|
252
|
+
});
|
|
253
|
+
}
|
|
231
254
|
/**
|
|
232
255
|
* Signs a message.
|
|
256
|
+
* For hardware wallets (e.g. Ledger via Freighter), falls back to signing a
|
|
257
|
+
* ManageData transaction because hardware wallets cannot sign arbitrary data.
|
|
233
258
|
*/
|
|
234
259
|
signMessage(messageToSign) {
|
|
235
260
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
@@ -237,7 +262,20 @@ class StellarWalletConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
237
262
|
if (!provider) {
|
|
238
263
|
return undefined;
|
|
239
264
|
}
|
|
240
|
-
|
|
265
|
+
if (this.isHardwareWalletEnabled) {
|
|
266
|
+
return this.signMessageViaTransaction(messageToSign);
|
|
267
|
+
}
|
|
268
|
+
try {
|
|
269
|
+
return yield provider.signMessage(messageToSign);
|
|
270
|
+
}
|
|
271
|
+
catch (error) {
|
|
272
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
273
|
+
if (errorMessage.toLowerCase().includes('hardware wallet')) {
|
|
274
|
+
this.isHardwareWalletEnabled = true;
|
|
275
|
+
return this.signMessageViaTransaction(messageToSign);
|
|
276
|
+
}
|
|
277
|
+
throw error;
|
|
278
|
+
}
|
|
241
279
|
});
|
|
242
280
|
}
|
|
243
281
|
getHorizonServer() {
|
|
@@ -459,9 +497,11 @@ class StellarWalletConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
459
497
|
endSession() {
|
|
460
498
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
461
499
|
this.connectedPublicKey = undefined;
|
|
500
|
+
this.selectedNetwork = undefined;
|
|
462
501
|
this.getAddressPromise = undefined;
|
|
463
502
|
this.connectionCancelled = false;
|
|
464
503
|
yield this.cache.clearConnectedAcccounts();
|
|
504
|
+
yield this.cache.clearStoredNetwork();
|
|
465
505
|
});
|
|
466
506
|
}
|
|
467
507
|
/**
|
|
@@ -30,8 +30,10 @@ export declare abstract class StellarWalletConnector extends WalletConnectorBase
|
|
|
30
30
|
/** Promise cache to prevent multiple simultaneous getAddress calls */
|
|
31
31
|
private getAddressPromise;
|
|
32
32
|
private selectedNetwork;
|
|
33
|
+
isHardwareWalletEnabled: boolean;
|
|
33
34
|
stellarNetworks: GenericNetwork[];
|
|
34
35
|
constructor(name: string, opts: StellarWalletConnectorProps);
|
|
36
|
+
canConnectWithHardwareWallet(): boolean;
|
|
35
37
|
/**
|
|
36
38
|
* Abstract method to get the wallet provider.
|
|
37
39
|
* Must be implemented by concrete connector classes.
|
|
@@ -61,8 +63,16 @@ export declare abstract class StellarWalletConnector extends WalletConnectorBase
|
|
|
61
63
|
* Signs a Stellar transaction XDR.
|
|
62
64
|
*/
|
|
63
65
|
signTransaction(transactionXdr: string): Promise<string>;
|
|
66
|
+
/**
|
|
67
|
+
* Signs a message using a Stellar ManageData transaction.
|
|
68
|
+
* Used as a fallback for hardware wallets (e.g. Ledger via Freighter) that
|
|
69
|
+
* cannot sign arbitrary data directly. Returns the signed transaction XDR.
|
|
70
|
+
*/
|
|
71
|
+
private signMessageViaTransaction;
|
|
64
72
|
/**
|
|
65
73
|
* Signs a message.
|
|
74
|
+
* For hardware wallets (e.g. Ledger via Freighter), falls back to signing a
|
|
75
|
+
* ManageData transaction because hardware wallets cannot sign arbitrary data.
|
|
66
76
|
*/
|
|
67
77
|
signMessage(messageToSign: string): Promise<string | undefined>;
|
|
68
78
|
getHorizonServer(): Promise<Horizon.Server>;
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
import { __awaiter } from '../../../_virtual/_tslib.js';
|
|
3
|
-
import { Horizon, Networks
|
|
3
|
+
import { hash, TransactionBuilder, Operation, Horizon, Networks } from '@stellar/stellar-sdk';
|
|
4
4
|
import { Logger } from '@dynamic-labs/logger';
|
|
5
5
|
import { DynamicError } from '@dynamic-labs/utils';
|
|
6
6
|
import { WalletConnectorBase } from '@dynamic-labs/wallet-connector-core';
|
|
7
7
|
import { StellarWallet } from '../../wallet/StellarWallet.js';
|
|
8
|
-
import { getNetworkFromAddress } from '../../utils/getNetworkFromAddress.js';
|
|
9
|
-
import { StellarUiTransaction } from '../../utils/StellarUiTransaction/StellarUiTransaction.js';
|
|
10
8
|
import { StellarLocalStorageCache } from '../../StellarLocalStorageCache.js';
|
|
9
|
+
import { StellarUiTransaction } from '../../utils/StellarUiTransaction/StellarUiTransaction.js';
|
|
11
10
|
|
|
12
11
|
const HORIZON_MAINNET_URL = 'https://horizon.stellar.org';
|
|
13
12
|
const HORIZON_TESTNET_URL = 'https://horizon-testnet.stellar.org';
|
|
@@ -33,12 +32,17 @@ class StellarWalletConnector extends WalletConnectorBase {
|
|
|
33
32
|
this.isConnecting = false;
|
|
34
33
|
/** Flag to track if connection was cancelled by disconnect */
|
|
35
34
|
this.connectionCancelled = false;
|
|
35
|
+
this.isHardwareWalletEnabled = false;
|
|
36
36
|
this.name = name;
|
|
37
37
|
this.logger = new Logger(this.name);
|
|
38
38
|
this.stellarNetworks = (_a = opts.stellarNetworks) !== null && _a !== void 0 ? _a : [];
|
|
39
39
|
this.overrideKey = this.key;
|
|
40
40
|
this.cache = new StellarLocalStorageCache(this.overrideKey);
|
|
41
41
|
}
|
|
42
|
+
canConnectWithHardwareWallet() {
|
|
43
|
+
var _a;
|
|
44
|
+
return Boolean((_a = this.metadata.supportedHardwareWallets) === null || _a === void 0 ? void 0 : _a.includes('ledger'));
|
|
45
|
+
}
|
|
42
46
|
getEnabledNetworks() {
|
|
43
47
|
return this.stellarNetworks;
|
|
44
48
|
}
|
|
@@ -57,50 +61,35 @@ class StellarWalletConnector extends WalletConnectorBase {
|
|
|
57
61
|
const network = this.stellarNetworks.find((n) => { var _a, _b; return ((_a = n.chainId) === null || _a === void 0 ? void 0 : _a.toString()) === idStr || ((_b = n.networkId) === null || _b === void 0 ? void 0 : _b.toString()) === idStr; });
|
|
58
62
|
if (network) {
|
|
59
63
|
this.selectedNetwork = network;
|
|
64
|
+
yield this.cache.setStoredNetwork(String(network.chainId));
|
|
60
65
|
this.emit('chainChange', { chain: String(network.chainId) });
|
|
61
66
|
}
|
|
62
67
|
});
|
|
63
68
|
}
|
|
64
69
|
getNetwork() {
|
|
65
70
|
return __awaiter(this, void 0, void 0, function* () {
|
|
66
|
-
var _a;
|
|
67
71
|
if (!this.stellarNetworks.length) {
|
|
68
72
|
return undefined;
|
|
69
73
|
}
|
|
70
|
-
// If selectedNetwork is already set, return its chainId
|
|
71
74
|
if (this.selectedNetwork) {
|
|
72
75
|
return String(this.selectedNetwork.chainId);
|
|
73
76
|
}
|
|
74
|
-
//
|
|
75
|
-
const
|
|
76
|
-
if (
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
const detectedChainId = yield getNetworkFromAddress(address, this.stellarNetworks[0]);
|
|
80
|
-
if (!detectedChainId) {
|
|
81
|
-
return undefined;
|
|
82
|
-
}
|
|
83
|
-
// Find and set the selectedNetwork based on detected chainId
|
|
84
|
-
this.selectedNetwork = this.stellarNetworks.find((n) => n.chainId.toString() === detectedChainId);
|
|
85
|
-
// If no exact match found, determine if it's testnet or mainnet based on the chainId
|
|
86
|
-
// and select the appropriate network from stellarNetworks
|
|
87
|
-
if (!this.selectedNetwork) {
|
|
88
|
-
// Testnet chainId starts with 'cee0302d', mainnet with '7ac33997'
|
|
89
|
-
const isTestnet = detectedChainId.startsWith('cee0302d');
|
|
90
|
-
this.selectedNetwork = this.stellarNetworks.find((n) => {
|
|
77
|
+
// Check localStorage cache for a previously stored network ID
|
|
78
|
+
const storedNetworkId = yield this.cache.getStoredNetwork();
|
|
79
|
+
if (storedNetworkId) {
|
|
80
|
+
const cachedNetwork = this.stellarNetworks.find((n) => {
|
|
91
81
|
var _a, _b;
|
|
92
|
-
return
|
|
93
|
-
|
|
94
|
-
: !((_b = n.name) === null || _b === void 0 ? void 0 : _b.toLowerCase().includes('testnet'));
|
|
82
|
+
return ((_a = n.chainId) === null || _a === void 0 ? void 0 : _a.toString()) === storedNetworkId ||
|
|
83
|
+
((_b = n.networkId) === null || _b === void 0 ? void 0 : _b.toString()) === storedNetworkId;
|
|
95
84
|
});
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
85
|
+
if (cachedNetwork) {
|
|
86
|
+
this.selectedNetwork = cachedNetwork;
|
|
87
|
+
return String(cachedNetwork.chainId);
|
|
99
88
|
}
|
|
100
89
|
}
|
|
101
|
-
//
|
|
102
|
-
|
|
103
|
-
return String(
|
|
90
|
+
// Fall back to the first configured network
|
|
91
|
+
[this.selectedNetwork] = this.stellarNetworks;
|
|
92
|
+
return String(this.selectedNetwork.chainId);
|
|
104
93
|
});
|
|
105
94
|
}
|
|
106
95
|
/**
|
|
@@ -191,8 +180,10 @@ class StellarWalletConnector extends WalletConnectorBase {
|
|
|
191
180
|
if (!provider) {
|
|
192
181
|
// Still clear state even if no provider
|
|
193
182
|
this.connectedPublicKey = undefined;
|
|
183
|
+
this.selectedNetwork = undefined;
|
|
194
184
|
this.getAddressPromise = undefined;
|
|
195
185
|
yield this.cache.clearConnectedAcccounts();
|
|
186
|
+
yield this.cache.clearStoredNetwork();
|
|
196
187
|
return;
|
|
197
188
|
}
|
|
198
189
|
try {
|
|
@@ -203,8 +194,10 @@ class StellarWalletConnector extends WalletConnectorBase {
|
|
|
203
194
|
}
|
|
204
195
|
// Clear all cached state
|
|
205
196
|
this.connectedPublicKey = undefined;
|
|
197
|
+
this.selectedNetwork = undefined;
|
|
206
198
|
this.getAddressPromise = undefined;
|
|
207
199
|
yield this.cache.clearConnectedAcccounts();
|
|
200
|
+
yield this.cache.clearStoredNetwork();
|
|
208
201
|
});
|
|
209
202
|
}
|
|
210
203
|
/**
|
|
@@ -224,8 +217,40 @@ class StellarWalletConnector extends WalletConnectorBase {
|
|
|
224
217
|
});
|
|
225
218
|
});
|
|
226
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* Signs a message using a Stellar ManageData transaction.
|
|
222
|
+
* Used as a fallback for hardware wallets (e.g. Ledger via Freighter) that
|
|
223
|
+
* cannot sign arbitrary data directly. Returns the signed transaction XDR.
|
|
224
|
+
*/
|
|
225
|
+
signMessageViaTransaction(message) {
|
|
226
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
227
|
+
const address = yield this.getAddress();
|
|
228
|
+
if (!address) {
|
|
229
|
+
throw new DynamicError('No connected address for hardware wallet signing');
|
|
230
|
+
}
|
|
231
|
+
const horizonServer = yield this.getHorizonServer();
|
|
232
|
+
const networkPassphrase = yield this.getNetworkPassphrase();
|
|
233
|
+
const account = yield horizonServer.loadAccount(address);
|
|
234
|
+
const messageBytes = Buffer.from(message);
|
|
235
|
+
// ManageData value is limited to 64 bytes; hash longer messages with SHA-256
|
|
236
|
+
const value = messageBytes.length > 64 ? hash(messageBytes) : messageBytes;
|
|
237
|
+
const transaction = new TransactionBuilder(account, {
|
|
238
|
+
fee: '100',
|
|
239
|
+
networkPassphrase,
|
|
240
|
+
})
|
|
241
|
+
.addOperation(Operation.manageData({
|
|
242
|
+
name: 'dynamic:auth',
|
|
243
|
+
value,
|
|
244
|
+
}))
|
|
245
|
+
.setTimeout(30)
|
|
246
|
+
.build();
|
|
247
|
+
return this.signTransaction(transaction.toXDR());
|
|
248
|
+
});
|
|
249
|
+
}
|
|
227
250
|
/**
|
|
228
251
|
* Signs a message.
|
|
252
|
+
* For hardware wallets (e.g. Ledger via Freighter), falls back to signing a
|
|
253
|
+
* ManageData transaction because hardware wallets cannot sign arbitrary data.
|
|
229
254
|
*/
|
|
230
255
|
signMessage(messageToSign) {
|
|
231
256
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -233,7 +258,20 @@ class StellarWalletConnector extends WalletConnectorBase {
|
|
|
233
258
|
if (!provider) {
|
|
234
259
|
return undefined;
|
|
235
260
|
}
|
|
236
|
-
|
|
261
|
+
if (this.isHardwareWalletEnabled) {
|
|
262
|
+
return this.signMessageViaTransaction(messageToSign);
|
|
263
|
+
}
|
|
264
|
+
try {
|
|
265
|
+
return yield provider.signMessage(messageToSign);
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
269
|
+
if (errorMessage.toLowerCase().includes('hardware wallet')) {
|
|
270
|
+
this.isHardwareWalletEnabled = true;
|
|
271
|
+
return this.signMessageViaTransaction(messageToSign);
|
|
272
|
+
}
|
|
273
|
+
throw error;
|
|
274
|
+
}
|
|
237
275
|
});
|
|
238
276
|
}
|
|
239
277
|
getHorizonServer() {
|
|
@@ -455,9 +493,11 @@ class StellarWalletConnector extends WalletConnectorBase {
|
|
|
455
493
|
endSession() {
|
|
456
494
|
return __awaiter(this, void 0, void 0, function* () {
|
|
457
495
|
this.connectedPublicKey = undefined;
|
|
496
|
+
this.selectedNetwork = undefined;
|
|
458
497
|
this.getAddressPromise = undefined;
|
|
459
498
|
this.connectionCancelled = false;
|
|
460
499
|
yield this.cache.clearConnectedAcccounts();
|
|
500
|
+
yield this.cache.clearStoredNetwork();
|
|
461
501
|
});
|
|
462
502
|
}
|
|
463
503
|
/**
|