@dynamic-labs/sdk-react-core 4.66.0 → 4.67.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/package.cjs +3 -3
  3. package/package.js +3 -3
  4. package/package.json +14 -14
  5. package/src/index.d.ts +1 -1
  6. package/src/lib/client/extension/functions/hasElevatedAccessToken/hasElevatedAccessToken.cjs +18 -0
  7. package/src/lib/client/extension/functions/hasElevatedAccessToken/hasElevatedAccessToken.d.ts +1 -0
  8. package/src/lib/client/extension/functions/hasElevatedAccessToken/hasElevatedAccessToken.js +14 -0
  9. package/src/lib/client/extension/functions/hasElevatedAccessToken/index.d.ts +1 -0
  10. package/src/lib/client/extension/index.d.ts +1 -0
  11. package/src/lib/context/DynamicContext/DynamicContext.cjs +20 -19
  12. package/src/lib/context/DynamicContext/DynamicContext.js +20 -19
  13. package/src/lib/context/DynamicContext/types/SettingsOverrides.d.ts +10 -0
  14. package/src/lib/styles/index.shadow.cjs +1 -1
  15. package/src/lib/styles/index.shadow.js +1 -1
  16. package/src/lib/utils/constants/values.cjs +2 -0
  17. package/src/lib/utils/constants/values.js +2 -0
  18. package/src/lib/utils/functions/compareChains/compareChains.cjs +1 -0
  19. package/src/lib/utils/functions/compareChains/compareChains.js +1 -0
  20. package/src/lib/utils/hooks/index.d.ts +1 -1
  21. package/src/lib/utils/hooks/useDynamicWaas/useDynamicWaas.cjs +2 -1
  22. package/src/lib/utils/hooks/useDynamicWaas/useDynamicWaas.d.ts +2 -1
  23. package/src/lib/utils/hooks/useDynamicWaas/useDynamicWaas.js +2 -1
  24. package/src/lib/utils/hooks/useNetworkConfigurationsFromProjectSettings/useNetworkConfigurationsFromProjectSettings.cjs +7 -2
  25. package/src/lib/utils/hooks/useNetworkConfigurationsFromProjectSettings/useNetworkConfigurationsFromProjectSettings.d.ts +2 -1
  26. package/src/lib/utils/hooks/useNetworkConfigurationsFromProjectSettings/useNetworkConfigurationsFromProjectSettings.js +7 -2
  27. package/src/lib/utils/hooks/useStepUpAuthentication/index.d.ts +1 -1
  28. package/src/lib/utils/hooks/useStepUpAuthentication/useStepUpAuthentication.cjs +102 -23
  29. package/src/lib/utils/hooks/useStepUpAuthentication/useStepUpAuthentication.d.ts +35 -15
  30. package/src/lib/utils/hooks/useStepUpAuthentication/useStepUpAuthentication.js +103 -24
  31. package/src/lib/utils/hooks/useWalletConnectorNetwork/useWalletConnectorNetwork.cjs +3 -2
  32. package/src/lib/utils/hooks/useWalletConnectorNetwork/useWalletConnectorNetwork.js +3 -2
  33. package/src/lib/views/CollectUserDataView/UserDataFields/UserPhoneField/UserPhoneField.cjs +10 -6
  34. package/src/lib/views/CollectUserDataView/UserDataFields/UserPhoneField/UserPhoneField.js +11 -7
  35. package/src/lib/views/SendBalanceView/SendBalanceView.cjs +1 -0
  36. package/src/lib/views/SendBalanceView/SendBalanceView.js +1 -0
  37. package/src/lib/views/TransactionConfirmationView/TransactionConfirmationView.cjs +21 -1
  38. package/src/lib/views/TransactionConfirmationView/TransactionConfirmationView.js +21 -1
  39. package/src/lib/views/WalletList/data.cjs +1 -0
  40. package/src/lib/views/WalletList/data.d.ts +1 -1
  41. package/src/lib/views/WalletList/data.js +1 -0
@@ -1,7 +1,7 @@
1
1
  'use client'
2
2
  import { __awaiter } from '../../../../../_virtual/_tslib.js';
3
3
  import { useState, useRef, useCallback } from 'react';
4
- import { verifyOTP, sendEmailOTP, supportedCountries, sendSmsOTP } from '@dynamic-labs-sdk/client';
4
+ import { verifyOTP, authenticatePasskeyMFA, authenticateTotpMfaDevice, sendEmailOTP, supportedCountries, sendSmsOTP } from '@dynamic-labs-sdk/client';
5
5
  import { JwtVerifiedCredentialFormatEnum } from '@dynamic-labs/sdk-api-core';
6
6
  import '@dynamic-labs-sdk/client/core';
7
7
  import '../../../client/client.js';
@@ -20,12 +20,13 @@ import '@dynamic-labs/multi-wallet';
20
20
  import 'react-international-phone';
21
21
  import '../../../store/state/nonce/nonce.js';
22
22
  import '@dynamic-labs/locale';
23
- import '../../../store/state/dynamicContextProps/dynamicContextProps.js';
23
+ import { useEnvironmentId } from '../../../store/state/dynamicContextProps/dynamicContextProps.js';
24
24
  import '../../../store/state/primaryWalletId/primaryWalletId.js';
25
25
  import '../../../store/state/connectedWalletsInfo/connectedWalletsInfo.js';
26
26
  import '../../functions/getWaasAddressTypeLabel/getWaasAddressTypeLabel.js';
27
27
  import '../../../events/dynamicEvents.js';
28
28
  import { useUser } from '../../../client/extension/user/useUser/useUser.js';
29
+ import { hasElevatedAccessToken } from '../../../client/extension/functions/hasElevatedAccessToken/hasElevatedAccessToken.js';
29
30
  import { useConnectAndSign } from '../authenticationHooks/useConnectAndSign/useConnectAndSign.js';
30
31
  import { useInternalUserWallets } from '../../../context/UserWalletsContext/UserWalletsContext.js';
31
32
 
@@ -68,47 +69,55 @@ const dispatchOtp = (credential) => __awaiter(void 0, void 0, void 0, function*
68
69
  : sendSmsOtp(credential);
69
70
  });
70
71
  /**
71
- * Perform step-up authentication for an already-authenticated user via OTP.
72
+ * Perform step-up authentication for an already-authenticated user.
72
73
  *
73
- * Automatically selects the first sign-in enabled email or SMS credential on
74
- * the user, or targets a specific credential when `credentialId` is provided.
74
+ * Supports multiple verification methods:
75
+ * - **OTP** (email/SMS): `sendOtp()` then `verifyOtp()`
76
+ * - **Wallet**: `verifyWallet()` for wallet signature verification
77
+ * - **Passkey MFA**: `verifyPasskeyMfa()` for passkey-based MFA
78
+ * - **TOTP MFA**: `verifyTotpMfa()` for authenticator app codes
75
79
  *
76
- * @param params.credentialId - Optional id of a specific verified credential to
77
- * use. Must be an email or SMS credential. Defaults to the first sign-in
78
- * enabled email or SMS credential on the authenticated user.
80
+ * For OTP and wallet methods, automatically selects the first sign-in enabled
81
+ * credential, or targets a specific one when `credentialId` is provided.
79
82
  *
80
- * @returns `sendOtp` sends the OTP to the resolved credential.
81
- * @returns `verifyOtp` verifies the OTP code supplied by the user.
82
- * @returns `state` current loading / error / otpVerification state.
83
- * @returns `resetState` – resets state back to its initial value.
83
+ * @param params.credentialId - Optional id of a specific verified credential or
84
+ * wallet to use. For OTP, must be an email or SMS credential. Defaults to the
85
+ * first sign-in enabled email or SMS credential on the authenticated user.
84
86
  *
85
87
  * @example
86
88
  * ```tsx
87
- * const { sendOtp, verifyOtp, state } = useStepUpAuthentication();
88
- *
89
- * // Step 1: send OTP
89
+ * // OTP flow
90
+ * const { sendOtp, verifyOtp } = useStepUpAuthentication();
90
91
  * await sendOtp();
92
+ * const result = await verifyOtp({ verificationToken: '123456', requestedScopes: ['wallet:export'] });
93
+ *
94
+ * // Passkey MFA flow
95
+ * const { verifyPasskeyMfa } = useStepUpAuthentication();
96
+ * const result = await verifyPasskeyMfa({ requestedScopes: ['wallet:export'] });
91
97
  *
92
- * // Step 2: after the user enters the code
93
- * const result = await verifyOtp({ verificationToken: '123456' });
98
+ * // TOTP MFA flow
99
+ * const { verifyTotpMfa } = useStepUpAuthentication();
100
+ * const result = await verifyTotpMfa({ code: '123456', requestedScopes: ['wallet:export'] });
94
101
  * ```
95
102
  */
96
103
  const useStepUpAuthentication = ({ credentialId, } = {}) => {
97
104
  const user = useUser();
105
+ const environmentId = useEnvironmentId();
98
106
  const [state, setState] = useState(INITIAL_STATE);
99
107
  const connectAndSign = useConnectAndSign();
100
108
  const { userWallets } = useInternalUserWallets();
101
109
  // Ref keeps the latest otpVerification available inside the verifyOtp
102
110
  // callback without creating a stale closure over state.
103
111
  const otpVerificationRef = useRef(null);
112
+ const isStepUpRequired = useCallback(({ scope }) => !hasElevatedAccessToken(scope), []);
104
113
  const resetState = useCallback(() => {
105
114
  otpVerificationRef.current = null;
106
115
  setState(INITIAL_STATE);
107
116
  }, []);
108
117
  const setError = useCallback((errorMessage) => {
109
118
  setState((prev) => (Object.assign(Object.assign({}, prev), { error: errorMessage, isLoading: false })));
110
- logger.error(errorMessage);
111
- }, []);
119
+ logger.error(errorMessage, { environmentId, userId: user === null || user === void 0 ? void 0 : user.id });
120
+ }, [environmentId, user === null || user === void 0 ? void 0 : user.id]);
112
121
  const sendOtp = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
113
122
  const credentials = user === null || user === void 0 ? void 0 : user.verifiedCredentials;
114
123
  if (!(credentials === null || credentials === void 0 ? void 0 : credentials.length)) {
@@ -134,10 +143,20 @@ const useStepUpAuthentication = ({ credentialId, } = {}) => {
134
143
  catch (error) {
135
144
  const errorMessage = error instanceof Error ? error.message : 'Failed to send OTP';
136
145
  setState((prev) => (Object.assign(Object.assign({}, prev), { error: errorMessage, isLoading: false })));
137
- logger.error('Failed to send OTP for step-up authentication', { error });
146
+ logger.error('Failed to send OTP for step-up authentication', {
147
+ environmentId,
148
+ error,
149
+ userId: user === null || user === void 0 ? void 0 : user.id,
150
+ });
138
151
  return null;
139
152
  }
140
- }), [credentialId, setError, user === null || user === void 0 ? void 0 : user.verifiedCredentials]);
153
+ }), [
154
+ credentialId,
155
+ environmentId,
156
+ setError,
157
+ user === null || user === void 0 ? void 0 : user.id,
158
+ user === null || user === void 0 ? void 0 : user.verifiedCredentials,
159
+ ]);
141
160
  const verifyOtp = useCallback((_a) => __awaiter(void 0, [_a], void 0, function* ({ requestedScopes, verificationToken, }) {
142
161
  const otpVerification = otpVerificationRef.current;
143
162
  if (!otpVerification) {
@@ -158,11 +177,13 @@ const useStepUpAuthentication = ({ credentialId, } = {}) => {
158
177
  const errorMessage = error instanceof Error ? error.message : 'Failed to verify OTP';
159
178
  setState((prev) => (Object.assign(Object.assign({}, prev), { error: errorMessage, isLoading: false })));
160
179
  logger.error('Failed to verify OTP for step-up authentication', {
180
+ environmentId,
161
181
  error,
182
+ userId: user === null || user === void 0 ? void 0 : user.id,
162
183
  });
163
184
  return null;
164
185
  }
165
- }), [setError]);
186
+ }), [environmentId, setError, user === null || user === void 0 ? void 0 : user.id]);
166
187
  const verifyWallet = useCallback((_b) => __awaiter(void 0, [_b], void 0, function* ({ requestedScopes }) {
167
188
  setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, isLoading: true })));
168
189
  const wallet = userWallets.find((w) => w.id === credentialId);
@@ -183,11 +204,69 @@ const useStepUpAuthentication = ({ credentialId, } = {}) => {
183
204
  : 'Failed to verify wallet for step-up authentication';
184
205
  setState((prev) => (Object.assign(Object.assign({}, prev), { error: errorMessage, isLoading: false })));
185
206
  logger.error('Failed to verify wallet for step-up authentication', {
207
+ environmentId,
186
208
  error,
209
+ userId: user === null || user === void 0 ? void 0 : user.id,
210
+ });
211
+ }
212
+ }), [
213
+ connectAndSign,
214
+ credentialId,
215
+ environmentId,
216
+ setError,
217
+ user === null || user === void 0 ? void 0 : user.id,
218
+ userWallets,
219
+ ]);
220
+ const verifyPasskeyMfa = useCallback((_c) => __awaiter(void 0, [_c], void 0, function* ({ requestedScopes, }) {
221
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, isLoading: true })));
222
+ try {
223
+ // requestedScopes is available in @dynamic-labs-sdk/client >= 0.14.0
224
+ const response = yield authenticatePasskeyMFA({
225
+ requestedScopes,
187
226
  });
227
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, isLoading: false })));
228
+ return response;
229
+ }
230
+ catch (error) {
231
+ const errorMessage = error instanceof Error
232
+ ? error.message
233
+ : 'Failed to authenticate passkey for step-up authentication';
234
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: errorMessage, isLoading: false })));
235
+ logger.error('Failed to authenticate passkey for step-up authentication', { environmentId, error, userId: user === null || user === void 0 ? void 0 : user.id });
236
+ return null;
237
+ }
238
+ }), [environmentId, user === null || user === void 0 ? void 0 : user.id]);
239
+ const verifyTotpMfa = useCallback((_d) => __awaiter(void 0, [_d], void 0, function* ({ code, deviceId, requestedScopes, }) {
240
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, isLoading: true })));
241
+ try {
242
+ // requestedScopes is available in @dynamic-labs-sdk/client >= 0.14.0
243
+ const response = yield authenticateTotpMfaDevice({
244
+ code,
245
+ deviceId,
246
+ requestedScopes,
247
+ });
248
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, isLoading: false })));
249
+ return response;
250
+ }
251
+ catch (error) {
252
+ const errorMessage = error instanceof Error
253
+ ? error.message
254
+ : 'Failed to authenticate TOTP device for step-up authentication';
255
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: errorMessage, isLoading: false })));
256
+ logger.error('Failed to authenticate TOTP device for step-up authentication', { environmentId, error, userId: user === null || user === void 0 ? void 0 : user.id });
257
+ return null;
188
258
  }
189
- }), [connectAndSign, credentialId, setError, userWallets]);
190
- return { resetState, sendOtp, state, verifyOtp, verifyWallet };
259
+ }), [environmentId, user === null || user === void 0 ? void 0 : user.id]);
260
+ return {
261
+ isStepUpRequired,
262
+ resetState,
263
+ sendOtp,
264
+ state,
265
+ verifyOtp,
266
+ verifyPasskeyMfa,
267
+ verifyTotpMfa,
268
+ verifyWallet,
269
+ };
191
270
  };
192
271
 
193
272
  export { useStepUpAuthentication };
@@ -50,9 +50,10 @@ const useWalletConnectorNetwork = (walletConnector, { onChange } = { onChange: (
50
50
  },
51
51
  });
52
52
  useWalletConnectorEvent.useWalletConnectorEvent(walletConnector || undefined, 'chainChange', ({ chain }) => {
53
- // STARK and STELLAR use string chainIds; others use numeric
53
+ // STARK, STELLAR and ALEO use string chainIds; others use numeric
54
54
  const useChainAsString = (walletConnector === null || walletConnector === void 0 ? void 0 : walletConnector.connectedChain) === 'STARK' ||
55
- (walletConnector === null || walletConnector === void 0 ? void 0 : walletConnector.connectedChain) === 'STELLAR';
55
+ (walletConnector === null || walletConnector === void 0 ? void 0 : walletConnector.connectedChain) === 'STELLAR' ||
56
+ (walletConnector === null || walletConnector === void 0 ? void 0 : walletConnector.connectedChain) === 'ALEO';
56
57
  const parsedChain = useChainAsString ? chain : parseInt(chain);
57
58
  setNetwork(parsedChain);
58
59
  onChange === null || onChange === void 0 ? void 0 : onChange(parsedChain);
@@ -46,9 +46,10 @@ const useWalletConnectorNetwork = (walletConnector, { onChange } = { onChange: (
46
46
  },
47
47
  });
48
48
  useWalletConnectorEvent(walletConnector || undefined, 'chainChange', ({ chain }) => {
49
- // STARK and STELLAR use string chainIds; others use numeric
49
+ // STARK, STELLAR and ALEO use string chainIds; others use numeric
50
50
  const useChainAsString = (walletConnector === null || walletConnector === void 0 ? void 0 : walletConnector.connectedChain) === 'STARK' ||
51
- (walletConnector === null || walletConnector === void 0 ? void 0 : walletConnector.connectedChain) === 'STELLAR';
51
+ (walletConnector === null || walletConnector === void 0 ? void 0 : walletConnector.connectedChain) === 'STELLAR' ||
52
+ (walletConnector === null || walletConnector === void 0 ? void 0 : walletConnector.connectedChain) === 'ALEO';
52
53
  const parsedChain = useChainAsString ? chain : parseInt(chain);
53
54
  setNetwork(parsedChain);
54
55
  onChange === null || onChange === void 0 ? void 0 : onChange(parsedChain);
@@ -114,18 +114,22 @@ require('../../../../components/Popper/PopperContext/PopperContext.cjs');
114
114
  const UserPhoneField = ({ onChange, value: phone, onBlur, disabled, label, required, error, name, verify, }) => {
115
115
  const { selectedPhoneCountry } = FieldsStateContext.useFieldsState();
116
116
  const { projectSettings } = useInternalDynamicContext.useInternalDynamicContext();
117
+ const initialPhoneRef = React.useRef(phone);
118
+ const onChangeRef = React.useRef(onChange);
119
+ const nameRef = React.useRef(name);
120
+ onChangeRef.current = onChange;
121
+ nameRef.current = name;
117
122
  const handleUpdate = React.useCallback(({ country, phone: newPhone }) => {
118
123
  selectedPhoneCountry.current = country;
119
- if (newPhone !== phone)
120
- onChange({
121
- target: { name, value: newPhone },
122
- });
123
- }, [onChange, phone, name, selectedPhoneCountry]);
124
+ onChangeRef.current({
125
+ target: { name: nameRef.current, value: newPhone },
126
+ });
127
+ }, [selectedPhoneCountry]);
124
128
  const countries = React.useMemo(() => {
125
129
  const enabledCountries = getSupportedCountriesForVerificationFromProjectSettings.getSupportedCountriesForVerificationFromProjectSettings(projectSettings);
126
130
  return getCustomCountries.getCustomCountries(verify ? getDefaultCountriesIfEmpty.getDefaultCountriesIfEmpty(enabledCountries) : undefined);
127
131
  }, [verify, projectSettings]);
128
- return (jsxRuntime.jsx(PhoneNumberField.PhoneNumberField, { countries: countries, initialPhone: phone, disabled: disabled, onUpdate: handleUpdate, onBlur: onBlur, label: label, appendRight: !disabled && !required ? (jsxRuntime.jsx(Typography.Typography, { variant: 'body_small', color: 'secondary', className: 'user-phone-field__optional-label', children: "Optional" })) : undefined, error: error }));
132
+ return (jsxRuntime.jsx(PhoneNumberField.PhoneNumberField, { countries: countries, initialPhone: initialPhoneRef.current, disabled: disabled, onUpdate: handleUpdate, onBlur: onBlur, label: label, appendRight: !disabled && !required ? (jsxRuntime.jsx(Typography.Typography, { variant: 'body_small', color: 'secondary', className: 'user-phone-field__optional-label', children: "Optional" })) : undefined, error: error }));
129
133
  };
130
134
 
131
135
  exports.UserPhoneField = UserPhoneField;
@@ -1,6 +1,6 @@
1
1
  'use client'
2
2
  import { jsx } from 'react/jsx-runtime';
3
- import { useCallback, useMemo } from 'react';
3
+ import { useRef, useCallback, useMemo } from 'react';
4
4
  import '@dynamic-labs/utils';
5
5
  import '../../../../components/Accordion/components/AccordionItem/AccordionItem.js';
6
6
  import 'react-i18next';
@@ -110,18 +110,22 @@ import '../../../../components/Popper/PopperContext/PopperContext.js';
110
110
  const UserPhoneField = ({ onChange, value: phone, onBlur, disabled, label, required, error, name, verify, }) => {
111
111
  const { selectedPhoneCountry } = useFieldsState();
112
112
  const { projectSettings } = useInternalDynamicContext();
113
+ const initialPhoneRef = useRef(phone);
114
+ const onChangeRef = useRef(onChange);
115
+ const nameRef = useRef(name);
116
+ onChangeRef.current = onChange;
117
+ nameRef.current = name;
113
118
  const handleUpdate = useCallback(({ country, phone: newPhone }) => {
114
119
  selectedPhoneCountry.current = country;
115
- if (newPhone !== phone)
116
- onChange({
117
- target: { name, value: newPhone },
118
- });
119
- }, [onChange, phone, name, selectedPhoneCountry]);
120
+ onChangeRef.current({
121
+ target: { name: nameRef.current, value: newPhone },
122
+ });
123
+ }, [selectedPhoneCountry]);
120
124
  const countries = useMemo(() => {
121
125
  const enabledCountries = getSupportedCountriesForVerificationFromProjectSettings(projectSettings);
122
126
  return getCustomCountries(verify ? getDefaultCountriesIfEmpty(enabledCountries) : undefined);
123
127
  }, [verify, projectSettings]);
124
- return (jsx(PhoneNumberField, { countries: countries, initialPhone: phone, disabled: disabled, onUpdate: handleUpdate, onBlur: onBlur, label: label, appendRight: !disabled && !required ? (jsx(Typography, { variant: 'body_small', color: 'secondary', className: 'user-phone-field__optional-label', children: "Optional" })) : undefined, error: error }));
128
+ return (jsx(PhoneNumberField, { countries: countries, initialPhone: initialPhoneRef.current, disabled: disabled, onUpdate: handleUpdate, onBlur: onBlur, label: label, appendRight: !disabled && !required ? (jsx(Typography, { variant: 'body_small', color: 'secondary', className: 'user-phone-field__optional-label', children: "Optional" })) : undefined, error: error }));
125
129
  };
126
130
 
127
131
  export { UserPhoneField };
@@ -128,6 +128,7 @@ const getTransactionValue = (transaction, isNativeToken) => {
128
128
  };
129
129
  const getSupportedChainName = (connectedChain) => {
130
130
  const supportedChains = {
131
+ ALEO: sdkApiCore.ChainEnum.Aleo,
131
132
  APTOS: sdkApiCore.ChainEnum.Aptos,
132
133
  BTC: sdkApiCore.ChainEnum.Btc,
133
134
  EVM: sdkApiCore.ChainEnum.Evm,
@@ -124,6 +124,7 @@ const getTransactionValue = (transaction, isNativeToken) => {
124
124
  };
125
125
  const getSupportedChainName = (connectedChain) => {
126
126
  const supportedChains = {
127
+ ALEO: ChainEnum.Aleo,
127
128
  APTOS: ChainEnum.Aptos,
128
129
  BTC: ChainEnum.Btc,
129
130
  EVM: ChainEnum.Evm,
@@ -151,6 +151,8 @@ const TransactionConfirmationView = ({ transaction, onError, onSuccess, mutation
151
151
  status: SimulationStatus.LOADING,
152
152
  });
153
153
  const [recipient, setRecipient] = React.useState(undefined);
154
+ // Pre-submit validation error (e.g., Stellar account activation requirements)
155
+ const [preSubmitValidationError, setPreSubmitValidationError] = React.useState(undefined);
154
156
  const isFetchingSimulationRef = React.useRef(false);
155
157
  const fetchSimulationResult = React.useCallback(() => _tslib.__awaiter(void 0, void 0, void 0, function* () {
156
158
  var _d, _e, _f, _g, _h, _j, _k;
@@ -278,6 +280,18 @@ const TransactionConfirmationView = ({ transaction, onError, onSuccess, mutation
278
280
  }
279
281
  fetchSimulationResult();
280
282
  }, [fetchSimulationResult, primaryWallet === null || primaryWallet === void 0 ? void 0 : primaryWallet.connector, simulationState.status]);
283
+ // Check destination account for chains that require it (e.g., Stellar)
284
+ React.useEffect(() => {
285
+ const checkDestination = () => _tslib.__awaiter(void 0, void 0, void 0, function* () {
286
+ var _a;
287
+ if (transaction.checkDestinationAccount) {
288
+ yield transaction.checkDestinationAccount();
289
+ const error = (_a = transaction.getPreSubmitValidationError) === null || _a === void 0 ? void 0 : _a.call(transaction);
290
+ setPreSubmitValidationError(error);
291
+ }
292
+ });
293
+ checkDestination();
294
+ }, [transaction]);
281
295
  /**
282
296
  * Update transaction fee and trigger a react update
283
297
  * to reflect the new fee on the UI
@@ -348,6 +362,10 @@ const TransactionConfirmationView = ({ transaction, onError, onSuccess, mutation
348
362
  const alert = React.useMemo(() => {
349
363
  if (errorMessage)
350
364
  return null;
365
+ // Check for pre-submit validation errors (e.g., Stellar account activation)
366
+ if (preSubmitValidationError) {
367
+ return (jsxRuntime.jsx(Alert.Alert, { icon: 'error', variant: 'error', children: jsxRuntime.jsx(Typography.Typography, { variant: 'body_small', color: 'current-color', "data-testid": 'presubmit_error_content', children: preSubmitValidationError }) }));
368
+ }
351
369
  // Check for gas sponsorship errors
352
370
  if (utils.TransactionGasCannotBeSponsoredError.isInstance(transactionError)) {
353
371
  return (jsxRuntime.jsx(Alert.Alert, { icon: 'error', variant: 'error', copykey: 'dyn_send_transaction.error_message.gas_not_sponsored', children: t('dyn_send_transaction.error_message.gas_not_sponsored') }));
@@ -389,6 +407,7 @@ const TransactionConfirmationView = ({ transaction, onError, onSuccess, mutation
389
407
  transaction,
390
408
  isGasSponsored,
391
409
  hasInsufficientFunds,
410
+ preSubmitValidationError,
392
411
  t,
393
412
  currency === null || currency === void 0 ? void 0 : currency.symbol,
394
413
  ]);
@@ -413,7 +432,7 @@ const TransactionConfirmationView = ({ transaction, onError, onSuccess, mutation
413
432
  alert,
414
433
  copykey,
415
434
  currentToken,
416
- disableSendButton: isBalanceLoading,
435
+ disableSendButton: isBalanceLoading || Boolean(preSubmitValidationError),
417
436
  displayPoweredByDynamicFooter,
418
437
  error: errorMessage,
419
438
  fetchTransactionFee,
@@ -462,6 +481,7 @@ const TransactionConfirmationView = ({ transaction, onError, onSuccess, mutation
462
481
  simulationState.result,
463
482
  sendBalanceTransaction,
464
483
  fetchTransactionFee,
484
+ preSubmitValidationError,
465
485
  ]);
466
486
  return simulationState.status === SimulationStatus.LOADING ? null : (jsxRuntime.jsx(TransactionConfirmationPageLayout.TransactionConfirmationPageLayout, Object.assign({}, layoutProps)));
467
487
  };
@@ -143,6 +143,8 @@ const TransactionConfirmationView = ({ transaction, onError, onSuccess, mutation
143
143
  status: SimulationStatus.LOADING,
144
144
  });
145
145
  const [recipient, setRecipient] = useState(undefined);
146
+ // Pre-submit validation error (e.g., Stellar account activation requirements)
147
+ const [preSubmitValidationError, setPreSubmitValidationError] = useState(undefined);
146
148
  const isFetchingSimulationRef = useRef(false);
147
149
  const fetchSimulationResult = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
148
150
  var _d, _e, _f, _g, _h, _j, _k;
@@ -270,6 +272,18 @@ const TransactionConfirmationView = ({ transaction, onError, onSuccess, mutation
270
272
  }
271
273
  fetchSimulationResult();
272
274
  }, [fetchSimulationResult, primaryWallet === null || primaryWallet === void 0 ? void 0 : primaryWallet.connector, simulationState.status]);
275
+ // Check destination account for chains that require it (e.g., Stellar)
276
+ useEffect(() => {
277
+ const checkDestination = () => __awaiter(void 0, void 0, void 0, function* () {
278
+ var _a;
279
+ if (transaction.checkDestinationAccount) {
280
+ yield transaction.checkDestinationAccount();
281
+ const error = (_a = transaction.getPreSubmitValidationError) === null || _a === void 0 ? void 0 : _a.call(transaction);
282
+ setPreSubmitValidationError(error);
283
+ }
284
+ });
285
+ checkDestination();
286
+ }, [transaction]);
273
287
  /**
274
288
  * Update transaction fee and trigger a react update
275
289
  * to reflect the new fee on the UI
@@ -340,6 +354,10 @@ const TransactionConfirmationView = ({ transaction, onError, onSuccess, mutation
340
354
  const alert = useMemo(() => {
341
355
  if (errorMessage)
342
356
  return null;
357
+ // Check for pre-submit validation errors (e.g., Stellar account activation)
358
+ if (preSubmitValidationError) {
359
+ return (jsx(Alert, { icon: 'error', variant: 'error', children: jsx(Typography, { variant: 'body_small', color: 'current-color', "data-testid": 'presubmit_error_content', children: preSubmitValidationError }) }));
360
+ }
343
361
  // Check for gas sponsorship errors
344
362
  if (TransactionGasCannotBeSponsoredError.isInstance(transactionError)) {
345
363
  return (jsx(Alert, { icon: 'error', variant: 'error', copykey: 'dyn_send_transaction.error_message.gas_not_sponsored', children: t('dyn_send_transaction.error_message.gas_not_sponsored') }));
@@ -381,6 +399,7 @@ const TransactionConfirmationView = ({ transaction, onError, onSuccess, mutation
381
399
  transaction,
382
400
  isGasSponsored,
383
401
  hasInsufficientFunds,
402
+ preSubmitValidationError,
384
403
  t,
385
404
  currency === null || currency === void 0 ? void 0 : currency.symbol,
386
405
  ]);
@@ -405,7 +424,7 @@ const TransactionConfirmationView = ({ transaction, onError, onSuccess, mutation
405
424
  alert,
406
425
  copykey,
407
426
  currentToken,
408
- disableSendButton: isBalanceLoading,
427
+ disableSendButton: isBalanceLoading || Boolean(preSubmitValidationError),
409
428
  displayPoweredByDynamicFooter,
410
429
  error: errorMessage,
411
430
  fetchTransactionFee,
@@ -454,6 +473,7 @@ const TransactionConfirmationView = ({ transaction, onError, onSuccess, mutation
454
473
  simulationState.result,
455
474
  sendBalanceTransaction,
456
475
  fetchTransactionFee,
476
+ preSubmitValidationError,
457
477
  ]);
458
478
  return simulationState.status === SimulationStatus.LOADING ? null : (jsx(TransactionConfirmationPageLayout, Object.assign({}, layoutProps)));
459
479
  };
@@ -23,6 +23,7 @@ require('../../shared/consts/index.cjs');
23
23
  * getChainInfo differs from the one used in the wallet connectors
24
24
  */
25
25
  const chainInfoOverrides = {
26
+ aleo: 'ALEO',
26
27
  starknet: 'STARK',
27
28
  stellar: 'STELLAR',
28
29
  };
@@ -4,7 +4,7 @@ interface IChain {
4
4
  enabled: boolean;
5
5
  name: string;
6
6
  }
7
- export declare const getEnabledChains: (chains: IChain[]) => ("STARK" | "STELLAR" | "ALGO" | "APTOS" | "ATOM" | "BTC" | "COSMOS" | "ECLIPSE" | "ETH" | "EVM" | "FLOW" | "SOL" | "SPARK" | "SUI" | "TRON" | "TON")[];
7
+ export declare const getEnabledChains: (chains: IChain[]) => ("ALEO" | "STARK" | "STELLAR" | "ALGO" | "APTOS" | "ATOM" | "BTC" | "COSMOS" | "ECLIPSE" | "ETH" | "EVM" | "FLOW" | "SOL" | "SPARK" | "SUI" | "TRON" | "TON")[];
8
8
  type BaseGetSupportedWalletOpts = Omit<GetSupportedWalletsOpts, 'walletConnectProjectId' | 'chainRpcProviders'>;
9
9
  export declare const getWallets: (props: {
10
10
  getSupportedWalletOpts: BaseGetSupportedWalletOpts;
@@ -19,6 +19,7 @@ import '../../shared/consts/index.js';
19
19
  * getChainInfo differs from the one used in the wallet connectors
20
20
  */
21
21
  const chainInfoOverrides = {
22
+ aleo: 'ALEO',
22
23
  starknet: 'STARK',
23
24
  stellar: 'STELLAR',
24
25
  };