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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/CHANGELOG.md +33 -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/components/SendBalancePageLayout/components/TokensBalanceDropdown/TokensBalanceDropdown.cjs +31 -11
  12. package/src/lib/components/SendBalancePageLayout/components/TokensBalanceDropdown/TokensBalanceDropdown.js +31 -11
  13. package/src/lib/context/DynamicContext/DynamicContext.cjs +20 -19
  14. package/src/lib/context/DynamicContext/DynamicContext.js +20 -19
  15. package/src/lib/context/DynamicContext/types/SettingsOverrides.d.ts +10 -0
  16. package/src/lib/shared/utils/functions/chain/getChainIcon.cjs +1 -0
  17. package/src/lib/shared/utils/functions/chain/getChainIcon.js +2 -1
  18. package/src/lib/styles/index.shadow.cjs +1 -1
  19. package/src/lib/styles/index.shadow.js +1 -1
  20. package/src/lib/utils/constants/values.cjs +2 -0
  21. package/src/lib/utils/constants/values.js +2 -0
  22. package/src/lib/utils/functions/compareChains/compareChains.cjs +1 -0
  23. package/src/lib/utils/functions/compareChains/compareChains.js +1 -0
  24. package/src/lib/utils/hooks/index.d.ts +1 -1
  25. package/src/lib/utils/hooks/useAuthenticatePasskeyMFA/useAuthenticatePasskeyMFA.d.ts +2 -1
  26. package/src/lib/utils/hooks/useDynamicWaas/useDynamicWaas.cjs +2 -1
  27. package/src/lib/utils/hooks/useDynamicWaas/useDynamicWaas.d.ts +2 -1
  28. package/src/lib/utils/hooks/useDynamicWaas/useDynamicWaas.js +2 -1
  29. package/src/lib/utils/hooks/useMfa/useMfa.cjs +6 -3
  30. package/src/lib/utils/hooks/useMfa/useMfa.d.ts +5 -3
  31. package/src/lib/utils/hooks/useMfa/useMfa.js +6 -3
  32. package/src/lib/utils/hooks/useNetworkConfigurationsFromProjectSettings/useNetworkConfigurationsFromProjectSettings.cjs +7 -2
  33. package/src/lib/utils/hooks/useNetworkConfigurationsFromProjectSettings/useNetworkConfigurationsFromProjectSettings.d.ts +2 -1
  34. package/src/lib/utils/hooks/useNetworkConfigurationsFromProjectSettings/useNetworkConfigurationsFromProjectSettings.js +7 -2
  35. package/src/lib/utils/hooks/usePromptMfaAuth/usePromptMfaAuth.cjs +14 -185
  36. package/src/lib/utils/hooks/usePromptMfaAuth/usePromptMfaAuth.d.ts +15 -3
  37. package/src/lib/utils/hooks/usePromptMfaAuth/usePromptMfaAuth.js +14 -185
  38. package/src/lib/utils/hooks/useStepUpAuthentication/index.d.ts +1 -1
  39. package/src/lib/utils/hooks/useStepUpAuthentication/useStepUpAuthentication.cjs +283 -33
  40. package/src/lib/utils/hooks/useStepUpAuthentication/useStepUpAuthentication.d.ts +45 -15
  41. package/src/lib/utils/hooks/useStepUpAuthentication/useStepUpAuthentication.js +279 -29
  42. package/src/lib/utils/hooks/useWalletConnectorNetwork/useWalletConnectorNetwork.cjs +3 -2
  43. package/src/lib/utils/hooks/useWalletConnectorNetwork/useWalletConnectorNetwork.js +3 -2
  44. package/src/lib/views/CollectUserDataView/UserDataFields/UserPhoneField/UserPhoneField.cjs +10 -6
  45. package/src/lib/views/CollectUserDataView/UserDataFields/UserPhoneField/UserPhoneField.js +11 -7
  46. package/src/lib/views/EmbeddedReveal/EmbeddedRevealView/EmbeddedRevealView.cjs +10 -9
  47. package/src/lib/views/EmbeddedReveal/EmbeddedRevealView/EmbeddedRevealView.js +10 -9
  48. package/src/lib/views/MfaChooseDeviceView/MfaChooseDeviceView.cjs +4 -3
  49. package/src/lib/views/MfaChooseDeviceView/MfaChooseDeviceView.d.ts +2 -0
  50. package/src/lib/views/MfaChooseDeviceView/MfaChooseDeviceView.js +4 -3
  51. package/src/lib/views/MfaVerificationView/MfaVerificationView.cjs +3 -1
  52. package/src/lib/views/MfaVerificationView/MfaVerificationView.d.ts +3 -2
  53. package/src/lib/views/MfaVerificationView/MfaVerificationView.js +3 -1
  54. package/src/lib/views/Passkey/ConfirmPasskeyView/ConfirmPasskeyView.cjs +2 -1
  55. package/src/lib/views/Passkey/ConfirmPasskeyView/ConfirmPasskeyView.d.ts +3 -1
  56. package/src/lib/views/Passkey/ConfirmPasskeyView/ConfirmPasskeyView.js +2 -1
  57. package/src/lib/views/SendBalanceView/SendBalanceView.cjs +1 -0
  58. package/src/lib/views/SendBalanceView/SendBalanceView.js +1 -0
  59. package/src/lib/views/TransactionConfirmationView/TransactionConfirmationView.cjs +21 -1
  60. package/src/lib/views/TransactionConfirmationView/TransactionConfirmationView.js +21 -1
  61. package/src/lib/views/WalletList/data.cjs +1 -0
  62. package/src/lib/views/WalletList/data.d.ts +1 -1
  63. package/src/lib/views/WalletList/data.js +1 -0
  64. package/src/lib/views/viewToComponentMap.d.ts +3 -2
@@ -12,40 +12,70 @@ export type VerifyOtpParams = {
12
12
  export type VerifyWalletParams = {
13
13
  requestedScopes?: TokenScope[];
14
14
  };
15
+ export type VerifyPasskeyMfaParams = {
16
+ requestedScopes?: TokenScope[];
17
+ };
18
+ export type VerifyTotpMfaParams = {
19
+ code: string;
20
+ deviceId?: string;
21
+ requestedScopes?: TokenScope[];
22
+ };
23
+ export type VerifyRecoveryCodeParams = {
24
+ code: string;
25
+ requestedScopes?: TokenScope[];
26
+ };
27
+ export type IsStepUpRequiredParams = {
28
+ scope: TokenScope;
29
+ };
15
30
  export type UseStepUpAuthenticationParams = {
16
31
  credentialId?: string;
17
32
  };
18
33
  export type UseStepUpAuthenticationReturn = {
34
+ isStepUpRequired: (params: IsStepUpRequiredParams) => boolean;
35
+ promptMfa: (props?: PromptMfaParams) => Promise<string | undefined>;
19
36
  resetState: () => void;
20
37
  sendOtp: () => Promise<OTPVerification | null>;
21
38
  state: StepUpAuthenticationState;
22
39
  verifyOtp: (params: VerifyOtpParams) => Promise<VerifyResponse | null>;
40
+ verifyPasskeyMfa: (params: VerifyPasskeyMfaParams) => Promise<VerifyResponse | null>;
41
+ verifyRecoveryCode: (params: VerifyRecoveryCodeParams) => Promise<VerifyResponse | null>;
42
+ verifyTotpMfa: (params: VerifyTotpMfaParams) => Promise<VerifyResponse | null>;
23
43
  verifyWallet: (params: VerifyWalletParams) => Promise<void>;
24
44
  };
45
+ export type PromptMfaParams = {
46
+ createMfaToken?: boolean;
47
+ requestedScopes?: TokenScope[];
48
+ };
25
49
  /**
26
- * Perform step-up authentication for an already-authenticated user via OTP.
50
+ * Perform step-up authentication for an already-authenticated user.
27
51
  *
28
- * Automatically selects the first sign-in enabled email or SMS credential on
29
- * the user, or targets a specific credential when `credentialId` is provided.
52
+ * Supports multiple verification methods:
53
+ * - **OTP** (email/SMS): `sendOtp()` then `verifyOtp()`
54
+ * - **Wallet**: `verifyWallet()` for wallet signature verification
55
+ * - **Passkey MFA**: `verifyPasskeyMfa()` for passkey-based MFA
56
+ * - **TOTP MFA**: `verifyTotpMfa()` for authenticator app codes
30
57
  *
31
- * @param params.credentialId - Optional id of a specific verified credential to
32
- * use. Must be an email or SMS credential. Defaults to the first sign-in
33
- * enabled email or SMS credential on the authenticated user.
58
+ * For OTP and wallet methods, automatically selects the first sign-in enabled
59
+ * credential, or targets a specific one when `credentialId` is provided.
34
60
  *
35
- * @returns `sendOtp` sends the OTP to the resolved credential.
36
- * @returns `verifyOtp` verifies the OTP code supplied by the user.
37
- * @returns `state` current loading / error / otpVerification state.
38
- * @returns `resetState` – resets state back to its initial value.
61
+ * @param params.credentialId - Optional id of a specific verified credential or
62
+ * wallet to use. For OTP, must be an email or SMS credential. Defaults to the
63
+ * first sign-in enabled email or SMS credential on the authenticated user.
39
64
  *
40
65
  * @example
41
66
  * ```tsx
42
- * const { sendOtp, verifyOtp, state } = useStepUpAuthentication();
43
- *
44
- * // Step 1: send OTP
67
+ * // OTP flow
68
+ * const { sendOtp, verifyOtp } = useStepUpAuthentication();
45
69
  * await sendOtp();
70
+ * const result = await verifyOtp({ verificationToken: '123456', requestedScopes: ['wallet:export'] });
71
+ *
72
+ * // Passkey MFA flow
73
+ * const { verifyPasskeyMfa } = useStepUpAuthentication();
74
+ * const result = await verifyPasskeyMfa({ requestedScopes: ['wallet:export'] });
46
75
  *
47
- * // Step 2: after the user enters the code
48
- * const result = await verifyOtp({ verificationToken: '123456' });
76
+ * // TOTP MFA flow
77
+ * const { verifyTotpMfa } = useStepUpAuthentication();
78
+ * const result = await verifyTotpMfa({ code: '123456', requestedScopes: ['wallet:export'] });
49
79
  * ```
50
80
  */
51
81
  export declare const useStepUpAuthentication: ({ credentialId, }?: UseStepUpAuthenticationParams) => UseStepUpAuthenticationReturn;
@@ -1,18 +1,18 @@
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';
5
- import { JwtVerifiedCredentialFormatEnum } from '@dynamic-labs/sdk-api-core';
4
+ import { verifyOTP, authenticatePasskeyMFA, authenticateTotpMfaDevice, authenticateMfaRecoveryCode, onEvent, sendEmailOTP, supportedCountries, sendSmsOTP } from '@dynamic-labs-sdk/client';
5
+ import { MFADeviceType, JwtVerifiedCredentialFormatEnum } from '@dynamic-labs/sdk-api-core';
6
+ import { DeferredPromise } from '@dynamic-labs/utils';
6
7
  import '@dynamic-labs-sdk/client/core';
7
- import '../../../client/client.js';
8
+ import { useDynamicClient } from '../../../client/client.js';
8
9
  import '../../../config/ApiEndpoint.js';
9
10
  import '@dynamic-labs/iconic';
10
11
  import '@dynamic-labs/wallet-connector-core';
11
12
  import 'react/jsx-runtime';
12
- import '../../../context/ViewContext/ViewContext.js';
13
+ import { useViewContext } from '../../../context/ViewContext/ViewContext.js';
13
14
  import { logger } from '../../../shared/logger.js';
14
15
  import '@dynamic-labs/wallet-book';
15
- import '@dynamic-labs/utils';
16
16
  import '../../constants/colors.js';
17
17
  import '../../constants/values.js';
18
18
  import '../../../shared/consts/index.js';
@@ -20,14 +20,92 @@ 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
- import '../../../events/dynamicEvents.js';
27
+ import { dynamicEvents } from '../../../events/dynamicEvents.js';
28
28
  import { useUser } from '../../../client/extension/user/useUser/useUser.js';
29
+ import { hasElevatedAccessToken } from '../../../client/extension/functions/hasElevatedAccessToken/hasElevatedAccessToken.js';
30
+ import '../../../context/DynamicContext/DynamicContext.js';
31
+ import '../../../store/state/loadingAndLifecycle/loadingAndLifecycle.js';
29
32
  import { useConnectAndSign } from '../authenticationHooks/useConnectAndSign/useConnectAndSign.js';
33
+ import '../../../context/ErrorContext/ErrorContext.js';
34
+ import '../../../context/AccessDeniedContext/AccessDeniedContext.js';
35
+ import '../../../context/AccountExistsContext/AccountExistsContext.js';
30
36
  import { useInternalUserWallets } from '../../../context/UserWalletsContext/UserWalletsContext.js';
37
+ import '../../../store/state/authMode/authMode.js';
38
+ import '../../../context/CaptchaContext/CaptchaContext.js';
39
+ import '../../../context/VerificationContext/VerificationContext.js';
40
+ import 'react-dom';
41
+ import '../../functions/compareChains/compareChains.js';
42
+ import '../../../views/Passkey/utils/findPrimaryEmbeddedChain/findPrimaryEmbeddedChain.js';
43
+ import '../../../context/ThemeContext/ThemeContext.js';
44
+ import '../useUserUpdateRequest/useUpdateUser/userFieldsSchema.js';
45
+ import 'bs58';
46
+ import '@dynamic-labs/types';
47
+ import '../../../context/SocialRedirectContext/SocialRedirectContext.js';
48
+ import '../../../context/LoadingContext/LoadingContext.js';
49
+ import '../../../context/WalletContext/WalletContext.js';
50
+ import '../useEmbeddedWallet/useSecureEnclaveEmbeddedWallet/constants.js';
51
+ import 'yup';
52
+ import '../../../context/MockContext/MockContext.js';
53
+ import '../../../views/CollectUserDataView/useFields.js';
54
+ import '../../../context/FieldsStateContext/FieldsStateContext.js';
55
+ import '../../../context/UserFieldEditorContext/UserFieldEditorContext.js';
56
+ import '@dynamic-labs/rpc-providers';
57
+ import '../../../store/state/walletOptions/walletOptions.js';
58
+ import 'react-i18next';
59
+ import '../../../components/Accordion/components/AccordionItem/AccordionItem.js';
60
+ import '../../../components/Alert/Alert.js';
61
+ import '../../../components/ShadowDOM/ShadowDOM.js';
62
+ import '../../../components/IconButton/IconButton.js';
63
+ import '../../../components/InlineWidget/InlineWidget.js';
64
+ import '../../../components/Input/Input.js';
65
+ import '../../../components/IsBrowser/IsBrowser.js';
66
+ import '../../../components/MenuList/Dropdown/Dropdown.js';
67
+ import '../../../components/OverlayCard/OverlayCard.js';
68
+ import '../../../components/Transition/ZoomTransition/ZoomTransition.js';
69
+ import '../../../components/Transition/SlideInUpTransition/SlideInUpTransition.js';
70
+ import '../../../components/Transition/OpacityTransition/OpacityTransition.js';
71
+ import '../../../components/PasskeyCreatedSuccessBanner/PasskeyCreatedSuccessBanner.js';
72
+ import '../../../components/Popper/Popper/Popper.js';
73
+ import '../../../components/Popper/PopperContext/PopperContext.js';
74
+ import 'react-focus-lock';
75
+ import 'qrcode';
76
+ import 'formik';
77
+ import '../useSubdomainCheck/useSubdomainCheck.js';
78
+ import '../../../context/WalletGroupContext/WalletGroupContext.js';
79
+ import '../../../widgets/DynamicWidget/context/DynamicWidgetContext.js';
80
+ import '../useWalletBackup/useWalletBackup.js';
81
+ import '../useWalletBackup/types.js';
82
+ import '../useWalletBackup/cloudProviders.js';
83
+ import '../../../context/IpConfigurationContext/IpConfigurationContext.js';
84
+ import '../../../context/ConnectWithOtpContext/ConnectWithOtpContext.js';
85
+ import '../../../widgets/DynamicBridgeWidget/views/WalletsView/components/SecondaryWallets/SecondaryWallets.js';
86
+ import '@hcaptcha/react-hcaptcha';
87
+ import '../../../widgets/DynamicWidget/helpers/convertExchangeKeyAndProviderEnum.js';
88
+ import '../../../views/ExchangeWhitelistWarning/ExchangeWhitelistWarning.js';
89
+ import '../../../context/ErrorContext/hooks/useErrorText/useErrorText.js';
90
+ import '../../../context/FooterAnimationContext/index.js';
91
+ import '../../../views/MfaChooseDeviceView/useGetMfaOptions/useGetMfaOptions.js';
92
+ import '../../../context/PasskeyContext/PasskeyContext.js';
93
+ import '../../../context/OnrampContext/OnrampContext.js';
94
+ import '../../../store/state/sendBalances.js';
95
+ import '../../../store/state/connectorsInitializing/connectorsInitializing.js';
96
+ import '../../../components/OverlayCardBase/OverlayCardTarget/OverlayCardTarget.js';
97
+ import '../../../widgets/DynamicWidget/components/DynamicWidgetHeader/DynamicWidgetHeader.js';
98
+ import '../../../views/TransactionConfirmationView/TransactionConfirmationView.js';
99
+ import '../../../widgets/DynamicWidget/components/PasskeyCard/PasskeyCard.js';
100
+ import '../../../widgets/DynamicWidget/views/CryptoComOnramp/CryptoComOnramp.js';
101
+ import '../../../../index.js';
102
+ import '../../../widgets/DynamicWidget/views/ReceiveWalletFunds/ReceiveWalletFunds.js';
103
+ import '../../../store/state/tokenBalances.js';
104
+ import '../../../store/state/multichainBalances.js';
105
+ import { useGetUserMfaMethods } from '../useGetUserMfaMethods/useGetUserMfaMethods.js';
106
+ import { useAuthenticatePasskeyMFA } from '../useAuthenticatePasskeyMFA/useAuthenticatePasskeyMFA.js';
107
+ import '../../../shared/utils/functions/getInitialUrl/getInitialUrl.js';
108
+ import { useInternalDynamicContext } from '../../../context/DynamicContext/useDynamicContext/useInternalDynamicContext/useInternalDynamicContext.js';
31
109
 
32
110
  const INITIAL_STATE = {
33
111
  error: null,
@@ -68,47 +146,60 @@ const dispatchOtp = (credential) => __awaiter(void 0, void 0, void 0, function*
68
146
  : sendSmsOtp(credential);
69
147
  });
70
148
  /**
71
- * Perform step-up authentication for an already-authenticated user via OTP.
149
+ * Perform step-up authentication for an already-authenticated user.
72
150
  *
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.
151
+ * Supports multiple verification methods:
152
+ * - **OTP** (email/SMS): `sendOtp()` then `verifyOtp()`
153
+ * - **Wallet**: `verifyWallet()` for wallet signature verification
154
+ * - **Passkey MFA**: `verifyPasskeyMfa()` for passkey-based MFA
155
+ * - **TOTP MFA**: `verifyTotpMfa()` for authenticator app codes
75
156
  *
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.
157
+ * For OTP and wallet methods, automatically selects the first sign-in enabled
158
+ * credential, or targets a specific one when `credentialId` is provided.
79
159
  *
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.
160
+ * @param params.credentialId - Optional id of a specific verified credential or
161
+ * wallet to use. For OTP, must be an email or SMS credential. Defaults to the
162
+ * first sign-in enabled email or SMS credential on the authenticated user.
84
163
  *
85
164
  * @example
86
165
  * ```tsx
87
- * const { sendOtp, verifyOtp, state } = useStepUpAuthentication();
88
- *
89
- * // Step 1: send OTP
166
+ * // OTP flow
167
+ * const { sendOtp, verifyOtp } = useStepUpAuthentication();
90
168
  * await sendOtp();
169
+ * const result = await verifyOtp({ verificationToken: '123456', requestedScopes: ['wallet:export'] });
170
+ *
171
+ * // Passkey MFA flow
172
+ * const { verifyPasskeyMfa } = useStepUpAuthentication();
173
+ * const result = await verifyPasskeyMfa({ requestedScopes: ['wallet:export'] });
91
174
  *
92
- * // Step 2: after the user enters the code
93
- * const result = await verifyOtp({ verificationToken: '123456' });
175
+ * // TOTP MFA flow
176
+ * const { verifyTotpMfa } = useStepUpAuthentication();
177
+ * const result = await verifyTotpMfa({ code: '123456', requestedScopes: ['wallet:export'] });
94
178
  * ```
95
179
  */
96
180
  const useStepUpAuthentication = ({ credentialId, } = {}) => {
97
181
  const user = useUser();
182
+ const environmentId = useEnvironmentId();
98
183
  const [state, setState] = useState(INITIAL_STATE);
99
184
  const connectAndSign = useConnectAndSign();
100
185
  const { userWallets } = useInternalUserWallets();
186
+ const { setShowAuthFlow } = useInternalDynamicContext();
187
+ const { pushView } = useViewContext();
188
+ const getUserMfaMethods = useGetUserMfaMethods();
189
+ const authenticatePasskeyMFA$1 = useAuthenticatePasskeyMFA();
190
+ const dynamicClient = useDynamicClient();
101
191
  // Ref keeps the latest otpVerification available inside the verifyOtp
102
192
  // callback without creating a stale closure over state.
103
193
  const otpVerificationRef = useRef(null);
194
+ const isStepUpRequired = useCallback(({ scope }) => !hasElevatedAccessToken(scope), []);
104
195
  const resetState = useCallback(() => {
105
196
  otpVerificationRef.current = null;
106
197
  setState(INITIAL_STATE);
107
198
  }, []);
108
199
  const setError = useCallback((errorMessage) => {
109
200
  setState((prev) => (Object.assign(Object.assign({}, prev), { error: errorMessage, isLoading: false })));
110
- logger.error(errorMessage);
111
- }, []);
201
+ logger.error(errorMessage, { environmentId, userId: user === null || user === void 0 ? void 0 : user.id });
202
+ }, [environmentId, user === null || user === void 0 ? void 0 : user.id]);
112
203
  const sendOtp = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
113
204
  const credentials = user === null || user === void 0 ? void 0 : user.verifiedCredentials;
114
205
  if (!(credentials === null || credentials === void 0 ? void 0 : credentials.length)) {
@@ -134,10 +225,20 @@ const useStepUpAuthentication = ({ credentialId, } = {}) => {
134
225
  catch (error) {
135
226
  const errorMessage = error instanceof Error ? error.message : 'Failed to send OTP';
136
227
  setState((prev) => (Object.assign(Object.assign({}, prev), { error: errorMessage, isLoading: false })));
137
- logger.error('Failed to send OTP for step-up authentication', { error });
228
+ logger.error('Failed to send OTP for step-up authentication', {
229
+ environmentId,
230
+ error,
231
+ userId: user === null || user === void 0 ? void 0 : user.id,
232
+ });
138
233
  return null;
139
234
  }
140
- }), [credentialId, setError, user === null || user === void 0 ? void 0 : user.verifiedCredentials]);
235
+ }), [
236
+ credentialId,
237
+ environmentId,
238
+ setError,
239
+ user === null || user === void 0 ? void 0 : user.id,
240
+ user === null || user === void 0 ? void 0 : user.verifiedCredentials,
241
+ ]);
141
242
  const verifyOtp = useCallback((_a) => __awaiter(void 0, [_a], void 0, function* ({ requestedScopes, verificationToken, }) {
142
243
  const otpVerification = otpVerificationRef.current;
143
244
  if (!otpVerification) {
@@ -158,11 +259,13 @@ const useStepUpAuthentication = ({ credentialId, } = {}) => {
158
259
  const errorMessage = error instanceof Error ? error.message : 'Failed to verify OTP';
159
260
  setState((prev) => (Object.assign(Object.assign({}, prev), { error: errorMessage, isLoading: false })));
160
261
  logger.error('Failed to verify OTP for step-up authentication', {
262
+ environmentId,
161
263
  error,
264
+ userId: user === null || user === void 0 ? void 0 : user.id,
162
265
  });
163
266
  return null;
164
267
  }
165
- }), [setError]);
268
+ }), [environmentId, setError, user === null || user === void 0 ? void 0 : user.id]);
166
269
  const verifyWallet = useCallback((_b) => __awaiter(void 0, [_b], void 0, function* ({ requestedScopes }) {
167
270
  setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, isLoading: true })));
168
271
  const wallet = userWallets.find((w) => w.id === credentialId);
@@ -183,11 +286,158 @@ const useStepUpAuthentication = ({ credentialId, } = {}) => {
183
286
  : 'Failed to verify wallet for step-up authentication';
184
287
  setState((prev) => (Object.assign(Object.assign({}, prev), { error: errorMessage, isLoading: false })));
185
288
  logger.error('Failed to verify wallet for step-up authentication', {
289
+ environmentId,
186
290
  error,
291
+ userId: user === null || user === void 0 ? void 0 : user.id,
292
+ });
293
+ }
294
+ }), [connectAndSign, credentialId, environmentId, setError, user, userWallets]);
295
+ const verifyPasskeyMfa = useCallback((_c) => __awaiter(void 0, [_c], void 0, function* ({ requestedScopes, }) {
296
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, isLoading: true })));
297
+ try {
298
+ const response = yield authenticatePasskeyMFA({
299
+ requestedScopes,
300
+ });
301
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, isLoading: false })));
302
+ return response;
303
+ }
304
+ catch (error) {
305
+ const errorMessage = error instanceof Error
306
+ ? error.message
307
+ : 'Failed to authenticate passkey for step-up authentication';
308
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: errorMessage, isLoading: false })));
309
+ logger.error('Failed to authenticate passkey for step-up authentication', { environmentId, error, userId: user === null || user === void 0 ? void 0 : user.id });
310
+ return null;
311
+ }
312
+ }), [environmentId, user]);
313
+ const verifyTotpMfa = useCallback((_d) => __awaiter(void 0, [_d], void 0, function* ({ code, deviceId, requestedScopes, }) {
314
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, isLoading: true })));
315
+ try {
316
+ const response = yield authenticateTotpMfaDevice({
317
+ code,
318
+ deviceId,
319
+ requestedScopes,
320
+ });
321
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, isLoading: false })));
322
+ return response;
323
+ }
324
+ catch (error) {
325
+ const errorMessage = error instanceof Error
326
+ ? error.message
327
+ : 'Failed to authenticate TOTP device for step-up authentication';
328
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: errorMessage, isLoading: false })));
329
+ logger.error('Failed to authenticate TOTP device for step-up authentication', { environmentId, error, userId: user === null || user === void 0 ? void 0 : user.id });
330
+ return null;
331
+ }
332
+ }), [environmentId, user]);
333
+ const verifyRecoveryCode = useCallback((_e) => __awaiter(void 0, [_e], void 0, function* ({ code, requestedScopes, }) {
334
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, isLoading: true })));
335
+ try {
336
+ const response = yield authenticateMfaRecoveryCode({
337
+ code,
338
+ requestedScopes,
187
339
  });
340
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, isLoading: false })));
341
+ return response;
342
+ }
343
+ catch (error) {
344
+ const errorMessage = error instanceof Error
345
+ ? error.message
346
+ : 'Failed to authenticate recovery code for step-up authentication';
347
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: errorMessage, isLoading: false })));
348
+ logger.error('Failed to authenticate recovery code for step-up authentication', { environmentId, error, userId: user === null || user === void 0 ? void 0 : user.id });
349
+ return null;
350
+ }
351
+ }), [environmentId, user]);
352
+ const promptMfa = useCallback((props) => __awaiter(void 0, void 0, void 0, function* () {
353
+ var _f;
354
+ const methods = yield getUserMfaMethods();
355
+ const allMethods = [
356
+ ...methods.passkeys.map((passkey) => (Object.assign(Object.assign({}, passkey), { type: MFADeviceType.Passkey }))),
357
+ ...methods.devices.map((device) => (Object.assign(Object.assign({}, device), { type: MFADeviceType.Totp }))),
358
+ ];
359
+ if (!methods.userHasVerifiedMfaMethods || allMethods.length === 0) {
360
+ setShowAuthFlow(true);
361
+ pushView('mfa-choose-device', {
362
+ createMfaToken: props === null || props === void 0 ? void 0 : props.createMfaToken,
363
+ requestedScopes: props === null || props === void 0 ? void 0 : props.requestedScopes,
364
+ });
365
+ return;
366
+ }
367
+ const lastCreatedMethod = allMethods.reduce((a, b) => {
368
+ if (!a)
369
+ return b;
370
+ if (!b)
371
+ return a;
372
+ if (a.createdAt && b.createdAt) {
373
+ return a.createdAt >= b.createdAt ? a : b;
374
+ }
375
+ if (b.createdAt) {
376
+ return b;
377
+ }
378
+ return a;
379
+ }, allMethods[0]);
380
+ switch (lastCreatedMethod.type) {
381
+ case MFADeviceType.Passkey: {
382
+ const createMfaTokenOptions = (props === null || props === void 0 ? void 0 : props.createMfaToken)
383
+ ? { singleUse: true }
384
+ : undefined;
385
+ const authenticatePasskeyPromise = authenticatePasskeyMFA$1({
386
+ createMfaToken: createMfaTokenOptions,
387
+ requestedScopes: props === null || props === void 0 ? void 0 : props.requestedScopes,
388
+ });
389
+ setShowAuthFlow(true);
390
+ pushView('passkey-confirm', {
391
+ authenticatePasskeyPromise,
392
+ createMfaToken: props === null || props === void 0 ? void 0 : props.createMfaToken,
393
+ requestedScopes: props === null || props === void 0 ? void 0 : props.requestedScopes,
394
+ });
395
+ return authenticatePasskeyPromise;
396
+ }
397
+ case MFADeviceType.Totp: {
398
+ if ((dynamicClient === null || dynamicClient === void 0 ? void 0 : dynamicClient.mfaToken) && !((_f = props === null || props === void 0 ? void 0 : props.requestedScopes) === null || _f === void 0 ? void 0 : _f.length)) {
399
+ return dynamicClient === null || dynamicClient === void 0 ? void 0 : dynamicClient.mfaToken;
400
+ }
401
+ const deferred = new DeferredPromise();
402
+ setShowAuthFlow(true);
403
+ pushView('mfa-verification', {
404
+ createMfaToken: props === null || props === void 0 ? void 0 : props.createMfaToken,
405
+ requestedScopes: props === null || props === void 0 ? void 0 : props.requestedScopes,
406
+ });
407
+ const mfaCompletionSuccessOff = onEvent({
408
+ event: 'mfaCompletionSuccess',
409
+ listener: ({ mfaToken }) => deferred.resolve(mfaToken),
410
+ }, dynamicClient);
411
+ const onAuthFlowCloseHandler = () => deferred.reject(new Error('MFA view closed'));
412
+ dynamicEvents.on('authFlowClose', onAuthFlowCloseHandler);
413
+ deferred.promise.finally(() => {
414
+ mfaCompletionSuccessOff();
415
+ dynamicEvents.off('authFlowClose', onAuthFlowCloseHandler);
416
+ });
417
+ return deferred.promise;
418
+ }
419
+ default:
420
+ throw new Error('Error determining MFA method to use');
188
421
  }
189
- }), [connectAndSign, credentialId, setError, userWallets]);
190
- return { resetState, sendOtp, state, verifyOtp, verifyWallet };
422
+ }), [
423
+ authenticatePasskeyMFA$1,
424
+ dynamicClient,
425
+ getUserMfaMethods,
426
+ pushView,
427
+ setShowAuthFlow,
428
+ ]);
429
+ return {
430
+ isStepUpRequired,
431
+ promptMfa,
432
+ resetState,
433
+ sendOtp,
434
+ state,
435
+ verifyOtp,
436
+ verifyPasskeyMfa,
437
+ verifyRecoveryCode,
438
+ verifyTotpMfa,
439
+ verifyWallet,
440
+ };
191
441
  };
192
442
 
193
443
  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 };
@@ -245,15 +245,16 @@ const EmbeddedRevealView = ({ exportPrivateKey, isPromptForExport = false, }) =>
245
245
  }
246
246
  return baseClass;
247
247
  };
248
- const contentHeader = (jsxRuntime.jsxs("div", { children: [primaryWallet &&
249
- isSmartWallet(primaryWallet) &&
250
- !isLoading &&
251
- data &&
252
- !error && (jsxRuntime.jsxs("div", { className: 'embedded-reveal-view__zerodev-warning', children: [jsxRuntime.jsxs("div", { className: 'embedded-reveal-view__zerodev-warning__title-row', children: [jsxRuntime.jsx(info.ReactComponent, { className: 'embedded-reveal-view__zerodev-warning__icon' }), jsxRuntime.jsx(Typography.Typography, { variant: 'body_normal', weight: 'bold', copykey: 'dyn_embedded_reveal.aa_warning.title', children: t('dyn_embedded_reveal.aa_warning.title') })] }), jsxRuntime.jsxs(Typography.Typography, { variant: 'body_normal', weight: 'regular', copykey: 'dyn_embedded_reveal.aa_warning.subtitle', children: [t('dyn_embedded_reveal.aa_warning.subtitle'), jsxRuntime.jsx("button", { onClick: () => {
253
- setShowAuthFlow(false);
254
- setDynamicWidgetView('send-balance');
255
- }, className: 'embedded-reveal-view__zerodev-warning__link-button', children: jsxRuntime.jsx(Typography.Typography, { variant: 'body_normal', weight: 'regular', color: 'primary', className: 'underline', copykey: 'dyn_embedded_reveal.aa_warning.button', children: t('dyn_embedded_reveal.aa_warning.button') }) })] })] })), jsxRuntime.jsx("div", { className: 'embedded-reveal-view__body__description', children: !hasInjectedCredential && (jsxRuntime.jsx("div", { className: 'embedded-reveal-view__header', children: jsxRuntime.jsx("div", { className: 'embedded-reveal-view__header__hero', children: jsxRuntime.jsx(exportEmbeddedHero.ReactComponent, {}) }) })) })] }));
256
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ModalHeader.ModalHeader, { trailing: isPromptForExport ? null : closeButton, children: jsxRuntime.jsx(Typography.Typography, { as: 'h1', variant: 'title', color: 'primary', "data-testid": 'dynamic-auth-modal-heading', className: 'header__typography', children: title }) }), jsxRuntime.jsx("div", { className: 'embedded-reveal-view', children: jsxRuntime.jsxs("div", { className: getBodyClassName(), children: [(!isWaasWallet ||
248
+ const isEip7702SmartWallet = Boolean(primaryWallet === null || primaryWallet === void 0 ? void 0 : primaryWallet.id.endsWith('-zerodev'));
249
+ const isErc4337SmartWallet = Boolean(primaryWallet && isSmartWallet(primaryWallet)) &&
250
+ !isEip7702SmartWallet;
251
+ const shouldShowAaWarning = isErc4337SmartWallet && !isLoading && Boolean(data) && !error;
252
+ const aaWarning = shouldShowAaWarning && (jsxRuntime.jsxs("div", { className: 'embedded-reveal-view__zerodev-warning', children: [jsxRuntime.jsxs("div", { className: 'embedded-reveal-view__zerodev-warning__title-row', children: [jsxRuntime.jsx(info.ReactComponent, { className: 'embedded-reveal-view__zerodev-warning__icon' }), jsxRuntime.jsx(Typography.Typography, { variant: 'body_normal', weight: 'bold', copykey: 'dyn_embedded_reveal.aa_warning.title', children: t('dyn_embedded_reveal.aa_warning.title') })] }), jsxRuntime.jsxs(Typography.Typography, { variant: 'body_normal', weight: 'regular', copykey: 'dyn_embedded_reveal.aa_warning.subtitle', children: [t('dyn_embedded_reveal.aa_warning.subtitle'), jsxRuntime.jsx("button", { onClick: () => {
253
+ setShowAuthFlow(false);
254
+ setDynamicWidgetView('send-balance');
255
+ }, className: 'embedded-reveal-view__zerodev-warning__link-button', children: jsxRuntime.jsx(Typography.Typography, { variant: 'body_normal', weight: 'regular', color: 'primary', className: 'underline', copykey: 'dyn_embedded_reveal.aa_warning.button', children: t('dyn_embedded_reveal.aa_warning.button') }) })] })] }));
256
+ const contentHeader = (jsxRuntime.jsx("div", { children: jsxRuntime.jsx("div", { className: 'embedded-reveal-view__body__description', children: !hasInjectedCredential && (jsxRuntime.jsx("div", { className: 'embedded-reveal-view__header', children: jsxRuntime.jsx("div", { className: 'embedded-reveal-view__header__hero', children: jsxRuntime.jsx(exportEmbeddedHero.ReactComponent, {}) }) })) }) }));
257
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ModalHeader.ModalHeader, { trailing: isPromptForExport ? null : closeButton, children: jsxRuntime.jsx(Typography.Typography, { as: 'h1', variant: 'title', color: 'primary', "data-testid": 'dynamic-auth-modal-heading', className: 'header__typography', children: title }) }), jsxRuntime.jsx("div", { className: 'embedded-reveal-view', children: jsxRuntime.jsxs("div", { className: getBodyClassName(), children: [aaWarning, (!isWaasWallet ||
257
258
  !hasInjectedCredential ||
258
259
  title !== credentialTitle) &&
259
260
  contentHeader, (isTurnkeyWallet || isWaasWallet) && (jsxRuntime.jsx(EmbeddedWalletExport.EmbeddedWalletExport, { wallet: wallet, isTurnkeyWallet: isTurnkeyWallet, isWaasWallet: isWaasWallet, data: data, onIframeContainerRef: setIframeContainerRef, isVisible: !title.includes('Agree') })), hasInjectedCredential ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(TypographyButton.TypographyButton, { buttonPadding: 'medium', buttonVariant: 'brand-primary', onClick: () => {