@dynamic-labs/sdk-react-core 3.0.0-alpha.34 → 3.0.0-alpha.36

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 (51) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/package.cjs +2 -2
  3. package/package.js +2 -2
  4. package/package.json +12 -12
  5. package/src/index.cjs +5 -1
  6. package/src/index.d.ts +1 -1
  7. package/src/index.js +1 -1
  8. package/src/lib/components/OTPVerificationView/OTPVerificationView.cjs +2 -2
  9. package/src/lib/components/OTPVerificationView/OTPVerificationView.js +2 -2
  10. package/src/lib/data/api/mfa/mfa.cjs +9 -4
  11. package/src/lib/data/api/mfa/mfa.js +9 -4
  12. package/src/lib/locale/en/translation.cjs +14 -8
  13. package/src/lib/locale/en/translation.d.ts +12 -6
  14. package/src/lib/locale/en/translation.js +14 -8
  15. package/src/lib/styles/index.shadow.cjs +1 -1
  16. package/src/lib/styles/index.shadow.js +1 -1
  17. package/src/lib/utils/functions/index.d.ts +1 -0
  18. package/src/lib/utils/functions/isValidMfaRecoveryCode/index.d.ts +1 -0
  19. package/src/lib/utils/functions/isValidMfaRecoveryCode/isValidMfaRecoveryCode.cjs +11 -0
  20. package/src/lib/utils/functions/isValidMfaRecoveryCode/isValidMfaRecoveryCode.d.ts +1 -0
  21. package/src/lib/utils/functions/isValidMfaRecoveryCode/isValidMfaRecoveryCode.js +7 -0
  22. package/src/lib/utils/hooks/useAuthLayoutChecks/useAuthLayoutChecks.cjs +3 -1
  23. package/src/lib/utils/hooks/useAuthLayoutChecks/useAuthLayoutChecks.js +3 -1
  24. package/src/lib/utils/hooks/useEmbeddedWallet/index.d.ts +1 -0
  25. package/src/lib/utils/hooks/useEmbeddedWallet/useEmbeddedWallet.cjs +4 -3
  26. package/src/lib/utils/hooks/useEmbeddedWallet/useEmbeddedWallet.d.ts +1 -1
  27. package/src/lib/utils/hooks/useEmbeddedWallet/useEmbeddedWallet.js +4 -3
  28. package/src/lib/utils/hooks/useEmbeddedWallet/useSecureEnclaveEmbeddedWallet/index.d.ts +1 -0
  29. package/src/lib/utils/hooks/useSocialAuth/useSocialAuth.cjs +8 -5
  30. package/src/lib/utils/hooks/useSocialAuth/useSocialAuth.js +8 -5
  31. package/src/lib/utils/hooks/useSyncMfaFlow/useSyncMfaFlow.cjs +5 -1
  32. package/src/lib/utils/hooks/useSyncMfaFlow/useSyncMfaFlow.js +5 -1
  33. package/src/lib/views/MfaChooseDeviceView/MfaChooseDeviceView.cjs +27 -12
  34. package/src/lib/views/MfaChooseDeviceView/MfaChooseDeviceView.d.ts +5 -2
  35. package/src/lib/views/MfaChooseDeviceView/MfaChooseDeviceView.js +28 -13
  36. package/src/lib/views/MfaChooseDeviceView/getMfaOptions/getMfaOptions.cjs +29 -0
  37. package/src/lib/views/MfaChooseDeviceView/getMfaOptions/getMfaOptions.d.ts +11 -0
  38. package/src/lib/views/MfaChooseDeviceView/getMfaOptions/getMfaOptions.js +25 -0
  39. package/src/lib/views/MfaChooseDeviceView/getMfaOptions/index.d.ts +1 -0
  40. package/src/lib/views/MfaRecoveryView/MfaRecoveryView.cjs +12 -12
  41. package/src/lib/views/MfaRecoveryView/MfaRecoveryView.js +13 -13
  42. package/src/lib/views/MfaSecureDeviceView/MfaSecureDeviceView.cjs +1 -1
  43. package/src/lib/views/MfaSecureDeviceView/MfaSecureDeviceView.js +1 -1
  44. package/src/lib/views/MfaVerificationView/MfaVerificationView.cjs +10 -2
  45. package/src/lib/views/MfaVerificationView/MfaVerificationView.d.ts +3 -1
  46. package/src/lib/views/MfaVerificationView/MfaVerificationView.js +11 -3
  47. package/src/lib/views/viewToComponentMap.d.ts +2 -2
  48. package/src/lib/utils/functions/validateMfaRecoveryCode/index.d.ts +0 -1
  49. package/src/lib/utils/functions/validateMfaRecoveryCode/validateMfaRecoveryCode.cjs +0 -11
  50. package/src/lib/utils/functions/validateMfaRecoveryCode/validateMfaRecoveryCode.d.ts +0 -1
  51. package/src/lib/utils/functions/validateMfaRecoveryCode/validateMfaRecoveryCode.js +0 -7
@@ -79,3 +79,4 @@ export * from './getSupportedCountriesForVerificationFromProjectSettings';
79
79
  export * from './getDefaultCountriesIfEmpty';
80
80
  export * from './logVerboseTroubleshootingMessage';
81
81
  export * from './getPlatformForConnector';
82
+ export * from './isValidMfaRecoveryCode';
@@ -0,0 +1 @@
1
+ export { isValidMfaRecoveryCode } from './isValidMfaRecoveryCode';
@@ -0,0 +1,11 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ const isValidMfaRecoveryCode = (text) => {
7
+ const regex = /^[a-zA-Z0-9]{10}$/;
8
+ return regex.test(text);
9
+ };
10
+
11
+ exports.isValidMfaRecoveryCode = isValidMfaRecoveryCode;
@@ -0,0 +1 @@
1
+ export declare const isValidMfaRecoveryCode: (text: string) => boolean;
@@ -0,0 +1,7 @@
1
+ 'use client'
2
+ const isValidMfaRecoveryCode = (text) => {
3
+ const regex = /^[a-zA-Z0-9]{10}$/;
4
+ return regex.test(text);
5
+ };
6
+
7
+ export { isValidMfaRecoveryCode };
@@ -141,7 +141,9 @@ const useAuthLayoutChecks = () => {
141
141
  view.type !== 'create-password-view' &&
142
142
  view.type !== 'embedded-wallet-auth-choice' &&
143
143
  view.type !== 'wallet-claim-intro' &&
144
- view.type !== 'passkey-recovery-add-email';
144
+ view.type !== 'passkey-recovery-add-email' &&
145
+ view.type !== 'mfa-choose-device' &&
146
+ view.type !== 'mfa-verification';
145
147
  const showConnectedWalletProgress = isBridgeFlow &&
146
148
  (view.type === 'wallet-list' ||
147
149
  view.type === 'qr-code' ||
@@ -137,7 +137,9 @@ const useAuthLayoutChecks = () => {
137
137
  view.type !== 'create-password-view' &&
138
138
  view.type !== 'embedded-wallet-auth-choice' &&
139
139
  view.type !== 'wallet-claim-intro' &&
140
- view.type !== 'passkey-recovery-add-email';
140
+ view.type !== 'passkey-recovery-add-email' &&
141
+ view.type !== 'mfa-choose-device' &&
142
+ view.type !== 'mfa-verification';
141
143
  const showConnectedWalletProgress = isBridgeFlow &&
142
144
  (view.type === 'wallet-list' ||
143
145
  view.type === 'qr-code' ||
@@ -1,3 +1,4 @@
1
1
  export { useEmbeddedWallet } from './useEmbeddedWallet';
2
2
  export { useSecureEnclaveEmbeddedWallet } from './useSecureEnclaveEmbeddedWallet';
3
3
  export { useMPCEmbeddedWallet } from './useMPCEmbeddedWallet';
4
+ export { EmbeddedWalletVersion } from './useSecureEnclaveEmbeddedWallet';
@@ -42,6 +42,7 @@ var findPrimaryEmbeddedChain = require('../../../views/Passkey/utils/findPrimary
42
42
  var WalletContext = require('../../../context/WalletContext/WalletContext.cjs');
43
43
  var useIsTurnkeyWallet = require('../useIsTurnkeyWallet/useIsTurnkeyWallet.cjs');
44
44
  var useSecureEnclaveEmbeddedWallet = require('./useSecureEnclaveEmbeddedWallet/useSecureEnclaveEmbeddedWallet.cjs');
45
+ require('./useSecureEnclaveEmbeddedWallet/constants.cjs');
45
46
  var useMPCEmbeddedWallet = require('./useMPCEmbeddedWallet/useMPCEmbeddedWallet.cjs');
46
47
  require('../../../context/ThemeContext/ThemeContext.cjs');
47
48
  require('../useUserUpdateRequest/useUpdateUser/userFieldsSchema.cjs');
@@ -119,8 +120,8 @@ const useEmbeddedWallet = () => {
119
120
  const { createEmbeddedWallet: createMPCWallet, canCreateMPCWallet, createPassword, revealEmbeddedWalletKey: revealCoinbaseMPCEmbeddedWalletKey, } = useMPCEmbeddedWallet.useMPCEmbeddedWallet();
120
121
  const { createEmbeddedWallet: createTurnkeyEmbeddedWallet, createOrRestoreSession, createPasskey, revealEmbeddedWalletKey: revealTurnkeyEmbeddedWalletKey, getPasskeys, isSessionActive, sendOneTimeCode, getWalletVersion: getTurnkeyWalletVersion, } = useSecureEnclaveEmbeddedWallet.useSecureEnclaveEmbeddedWallet();
121
122
  const { isLoadingEmbeddedWallet } = WalletContext.useWalletContext();
122
- const userHasEmbeddedWallet = () => hasEmbeddedWallet.hasEmbeddedWallet(user);
123
- const getWalletVersion = () => {
123
+ const userHasEmbeddedWallet = React.useCallback(() => hasEmbeddedWallet.hasEmbeddedWallet(user), [user]);
124
+ const getWalletVersion = React.useCallback(() => {
124
125
  if (!user) {
125
126
  throw new utils.DynamicError(errors.USER_NOT_LOGGED_IN);
126
127
  }
@@ -131,7 +132,7 @@ const useEmbeddedWallet = () => {
131
132
  return getTurnkeyWalletVersion();
132
133
  }
133
134
  return undefined;
134
- };
135
+ }, [getTurnkeyWalletVersion, isTurnkeyWallet, user, userHasEmbeddedWallet]);
135
136
  /**
136
137
  * Creates Dynamic embedded wallet according to the settings
137
138
  * @param chains - array of chains to create the wallet for
@@ -27,7 +27,7 @@ export declare const useEmbeddedWallet: () => {
27
27
  } | undefined) => Promise<import("dist/packages/wallet-connector-core/src").WebAuthnAttestation>;
28
28
  readonly createPassword: (showIntro?: boolean | undefined) => Promise<string>;
29
29
  readonly getPasskeys: () => Promise<import("@dynamic-labs/sdk-api-core").UserPasskey[]>;
30
- readonly getWalletVersion: () => import("./useSecureEnclaveEmbeddedWallet/constants").EmbeddedWalletVersion | undefined;
30
+ readonly getWalletVersion: () => import(".").EmbeddedWalletVersion | undefined;
31
31
  readonly isLoadingEmbeddedWallet: boolean;
32
32
  readonly isSessionActive: string | boolean | undefined;
33
33
  readonly revealWalletKey: (options?: {
@@ -38,6 +38,7 @@ import { findPrimaryEmbeddedChain } from '../../../views/Passkey/utils/findPrima
38
38
  import { useWalletContext } from '../../../context/WalletContext/WalletContext.js';
39
39
  import { useIsTurnkeyWallet } from '../useIsTurnkeyWallet/useIsTurnkeyWallet.js';
40
40
  import { useSecureEnclaveEmbeddedWallet } from './useSecureEnclaveEmbeddedWallet/useSecureEnclaveEmbeddedWallet.js';
41
+ import './useSecureEnclaveEmbeddedWallet/constants.js';
41
42
  import { useMPCEmbeddedWallet } from './useMPCEmbeddedWallet/useMPCEmbeddedWallet.js';
42
43
  import '../../../context/ThemeContext/ThemeContext.js';
43
44
  import '../useUserUpdateRequest/useUpdateUser/userFieldsSchema.js';
@@ -115,8 +116,8 @@ const useEmbeddedWallet = () => {
115
116
  const { createEmbeddedWallet: createMPCWallet, canCreateMPCWallet, createPassword, revealEmbeddedWalletKey: revealCoinbaseMPCEmbeddedWalletKey, } = useMPCEmbeddedWallet();
116
117
  const { createEmbeddedWallet: createTurnkeyEmbeddedWallet, createOrRestoreSession, createPasskey, revealEmbeddedWalletKey: revealTurnkeyEmbeddedWalletKey, getPasskeys, isSessionActive, sendOneTimeCode, getWalletVersion: getTurnkeyWalletVersion, } = useSecureEnclaveEmbeddedWallet();
117
118
  const { isLoadingEmbeddedWallet } = useWalletContext();
118
- const userHasEmbeddedWallet = () => hasEmbeddedWallet(user);
119
- const getWalletVersion = () => {
119
+ const userHasEmbeddedWallet = useCallback(() => hasEmbeddedWallet(user), [user]);
120
+ const getWalletVersion = useCallback(() => {
120
121
  if (!user) {
121
122
  throw new DynamicError(USER_NOT_LOGGED_IN);
122
123
  }
@@ -127,7 +128,7 @@ const useEmbeddedWallet = () => {
127
128
  return getTurnkeyWalletVersion();
128
129
  }
129
130
  return undefined;
130
- };
131
+ }, [getTurnkeyWalletVersion, isTurnkeyWallet, user, userHasEmbeddedWallet]);
131
132
  /**
132
133
  * Creates Dynamic embedded wallet according to the settings
133
134
  * @param chains - array of chains to create the wallet for
@@ -1,2 +1,3 @@
1
1
  export { useSecureEnclaveEmbeddedWallet } from './useSecureEnclaveEmbeddedWallet';
2
2
  export { useTurnkey } from './useTurnkey';
3
+ export { EmbeddedWalletVersion } from './constants';
@@ -115,7 +115,7 @@ const socialProviders = [
115
115
  const providersRequiringPkce = ['twitter', 'github'];
116
116
  // Hook to handle common social auth logic (for social linking and social sign in)
117
117
  const useSocialAuth = ({ sessionTimeout, onSettled, onError, onFarcasterUrl, }) => {
118
- const { environmentId, setShowAuthFlow, projectSettings, consumeNonce, redirectUrl, } = useInternalDynamicContext.useInternalDynamicContext();
118
+ const { environmentId, setShowAuthFlow, projectSettings, consumeNonce, redirectUrl: defaultRedirectUrl, } = useInternalDynamicContext.useInternalDynamicContext();
119
119
  const { setErrorMessage, setError: setContextError } = ErrorContext.useErrorContext();
120
120
  const { initAuth } = useUserAuth.useUserAuth({
121
121
  authMethod: 'social',
@@ -199,7 +199,10 @@ const useSocialAuth = ({ sessionTimeout, onSettled, onError, onFarcasterUrl, })
199
199
  type: 'social',
200
200
  });
201
201
  if (provider === sdkApiCore.ProviderEnum.Farcaster)
202
- return connectWithFarcaster(authMode, { captchaToken, redirectUrl });
202
+ return connectWithFarcaster(authMode, {
203
+ captchaToken,
204
+ redirectUrl,
205
+ });
203
206
  const state = randomString.randomString(32);
204
207
  const verifier = randomString.randomString(43);
205
208
  const loginUrlString = getOauthLoginUrl.getOauthLoginUrl((_b = projectSettings === null || projectSettings === void 0 ? void 0 : projectSettings.providers) !== null && _b !== void 0 ? _b : [], provider);
@@ -225,7 +228,7 @@ const useSocialAuth = ({ sessionTimeout, onSettled, onError, onFarcasterUrl, })
225
228
  oauthLoginUrl,
226
229
  onSettled,
227
230
  provider,
228
- redirectUrl,
231
+ redirectUrl: redirectUrl || defaultRedirectUrl,
229
232
  sessionTimeout,
230
233
  setIsProcessing,
231
234
  state,
@@ -275,13 +278,13 @@ const useSocialAuth = ({ sessionTimeout, onSettled, onError, onFarcasterUrl, })
275
278
  }
276
279
  }
277
280
  });
278
- const connectWithFarcaster = (authMode_1, _d) => _tslib.__awaiter(void 0, [authMode_1, _d], void 0, function* (authMode, { captchaToken, redirectUrl: redirectUrlOverride, }) {
281
+ const connectWithFarcaster = (authMode_1, _d) => _tslib.__awaiter(void 0, [authMode_1, _d], void 0, function* (authMode, { captchaToken, redirectUrl }) {
279
282
  const dynamicNonce = consumeNonce();
280
283
  const domain = utils.PlatformService.getHost();
281
284
  const data = yield farcaster.connect({
282
285
  domain,
283
286
  nonce: dynamicNonce,
284
- redirectUrl: redirectUrlOverride !== null && redirectUrlOverride !== void 0 ? redirectUrlOverride : redirectUrl,
287
+ redirectUrl: redirectUrl || defaultRedirectUrl,
285
288
  siweUri: utils.PlatformService.getOrigin(),
286
289
  });
287
290
  if (!(data === null || data === void 0 ? void 0 : data.url) || !(data === null || data === void 0 ? void 0 : data.channelToken)) {
@@ -111,7 +111,7 @@ const socialProviders = [
111
111
  const providersRequiringPkce = ['twitter', 'github'];
112
112
  // Hook to handle common social auth logic (for social linking and social sign in)
113
113
  const useSocialAuth = ({ sessionTimeout, onSettled, onError, onFarcasterUrl, }) => {
114
- const { environmentId, setShowAuthFlow, projectSettings, consumeNonce, redirectUrl, } = useInternalDynamicContext();
114
+ const { environmentId, setShowAuthFlow, projectSettings, consumeNonce, redirectUrl: defaultRedirectUrl, } = useInternalDynamicContext();
115
115
  const { setErrorMessage, setError: setContextError } = useErrorContext();
116
116
  const { initAuth } = useUserAuth({
117
117
  authMethod: 'social',
@@ -195,7 +195,10 @@ const useSocialAuth = ({ sessionTimeout, onSettled, onError, onFarcasterUrl, })
195
195
  type: 'social',
196
196
  });
197
197
  if (provider === ProviderEnum.Farcaster)
198
- return connectWithFarcaster(authMode, { captchaToken, redirectUrl });
198
+ return connectWithFarcaster(authMode, {
199
+ captchaToken,
200
+ redirectUrl,
201
+ });
199
202
  const state = randomString(32);
200
203
  const verifier = randomString(43);
201
204
  const loginUrlString = getOauthLoginUrl((_b = projectSettings === null || projectSettings === void 0 ? void 0 : projectSettings.providers) !== null && _b !== void 0 ? _b : [], provider);
@@ -221,7 +224,7 @@ const useSocialAuth = ({ sessionTimeout, onSettled, onError, onFarcasterUrl, })
221
224
  oauthLoginUrl,
222
225
  onSettled,
223
226
  provider,
224
- redirectUrl,
227
+ redirectUrl: redirectUrl || defaultRedirectUrl,
225
228
  sessionTimeout,
226
229
  setIsProcessing,
227
230
  state,
@@ -271,13 +274,13 @@ const useSocialAuth = ({ sessionTimeout, onSettled, onError, onFarcasterUrl, })
271
274
  }
272
275
  }
273
276
  });
274
- const connectWithFarcaster = (authMode_1, _d) => __awaiter(void 0, [authMode_1, _d], void 0, function* (authMode, { captchaToken, redirectUrl: redirectUrlOverride, }) {
277
+ const connectWithFarcaster = (authMode_1, _d) => __awaiter(void 0, [authMode_1, _d], void 0, function* (authMode, { captchaToken, redirectUrl }) {
275
278
  const dynamicNonce = consumeNonce();
276
279
  const domain = PlatformService.getHost();
277
280
  const data = yield connect({
278
281
  domain,
279
282
  nonce: dynamicNonce,
280
- redirectUrl: redirectUrlOverride !== null && redirectUrlOverride !== void 0 ? redirectUrlOverride : redirectUrl,
283
+ redirectUrl: redirectUrl || defaultRedirectUrl,
281
284
  siweUri: PlatformService.getOrigin(),
282
285
  });
283
286
  if (!(data === null || data === void 0 ? void 0 : data.url) || !(data === null || data === void 0 ? void 0 : data.channelToken)) {
@@ -19,7 +19,7 @@ require('../../../shared/utils/classes/storage/sessionStorage.cjs');
19
19
  var hasPendingMfaAction = require('../../../shared/utils/functions/hasPendingMfaAction/hasPendingMfaAction.cjs');
20
20
  require('@dynamic-labs/utils');
21
21
  require('../../../shared/consts/index.cjs');
22
- require('../../../events/dynamicEvents.cjs');
22
+ var useDynamicEvents = require('../events/useDynamicEvents/useDynamicEvents.cjs');
23
23
  require('../../../../../_virtual/_tslib.cjs');
24
24
  require('../../../context/CaptchaContext/CaptchaContext.cjs');
25
25
  require('../../../context/ErrorContext/ErrorContext.cjs');
@@ -31,6 +31,7 @@ require('../../../locale/locale.cjs');
31
31
  require('../../../context/AccessDeniedContext/AccessDeniedContext.cjs');
32
32
  require('../../../context/AccountExistsContext/AccountExistsContext.cjs');
33
33
  require('../../../context/UserWalletsContext/UserWalletsContext.cjs');
34
+ require('../../../events/dynamicEvents.cjs');
34
35
  require('../../../context/VerificationContext/VerificationContext.cjs');
35
36
  require('react-dom');
36
37
  require('../../../context/WalletContext/WalletContext.cjs');
@@ -100,6 +101,9 @@ const useSyncMfaFlow = () => {
100
101
  const { getUserDevices } = useMfa.useMfa();
101
102
  // this is used to make sure we only trigger the effect once
102
103
  const triggered = React.useRef(false);
104
+ useDynamicEvents.useInternalDynamicEvents('logout', () => {
105
+ triggered.current = false;
106
+ });
103
107
  React.useEffect(() => {
104
108
  var _a;
105
109
  // boilterplate: we don't want to run the sync logic if the sdk hasn't finished loading,
@@ -15,7 +15,7 @@ import '../../../shared/utils/classes/storage/sessionStorage.js';
15
15
  import { hasPendingMfaAction } from '../../../shared/utils/functions/hasPendingMfaAction/hasPendingMfaAction.js';
16
16
  import '@dynamic-labs/utils';
17
17
  import '../../../shared/consts/index.js';
18
- import '../../../events/dynamicEvents.js';
18
+ import { useInternalDynamicEvents } from '../events/useDynamicEvents/useDynamicEvents.js';
19
19
  import '../../../../../_virtual/_tslib.js';
20
20
  import '../../../context/CaptchaContext/CaptchaContext.js';
21
21
  import '../../../context/ErrorContext/ErrorContext.js';
@@ -27,6 +27,7 @@ import '../../../locale/locale.js';
27
27
  import '../../../context/AccessDeniedContext/AccessDeniedContext.js';
28
28
  import '../../../context/AccountExistsContext/AccountExistsContext.js';
29
29
  import '../../../context/UserWalletsContext/UserWalletsContext.js';
30
+ import '../../../events/dynamicEvents.js';
30
31
  import '../../../context/VerificationContext/VerificationContext.js';
31
32
  import 'react-dom';
32
33
  import '../../../context/WalletContext/WalletContext.js';
@@ -96,6 +97,9 @@ const useSyncMfaFlow = () => {
96
97
  const { getUserDevices } = useMfa();
97
98
  // this is used to make sure we only trigger the effect once
98
99
  const triggered = useRef(false);
100
+ useInternalDynamicEvents('logout', () => {
101
+ triggered.current = false;
102
+ });
99
103
  useEffect(() => {
100
104
  var _a;
101
105
  // boilterplate: we don't want to run the sync logic if the sdk hasn't finished loading,
@@ -5,7 +5,6 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
  var reactI18next = require('react-i18next');
8
- var sdkApiCore = require('@dynamic-labs/sdk-api-core');
9
8
  require('react');
10
9
  var secureAccount = require('../../assets/secure-account.cjs');
11
10
  require('../../components/Accordion/components/AccordionItem/AccordionItem.cjs');
@@ -14,6 +13,7 @@ require('../../events/dynamicEvents.cjs');
14
13
  require('../../../../_virtual/_tslib.cjs');
15
14
  require('@dynamic-labs/utils');
16
15
  require('../../context/DynamicContext/DynamicContext.cjs');
16
+ require('@dynamic-labs/sdk-api-core');
17
17
  require('../../shared/logger.cjs');
18
18
  require('@dynamic-labs/iconic');
19
19
  require('@dynamic-labs/wallet-connector-core');
@@ -67,6 +67,7 @@ require('../../components/MenuList/Dropdown/Dropdown.cjs');
67
67
  require('formik');
68
68
  var Button = require('../../components/Button/Button.cjs');
69
69
  require('../TransactionConfirmationView/helpers/transactionErrorMessage.cjs');
70
+ var ModalHeader = require('../../components/ModalHeader/ModalHeader.cjs');
70
71
  require('../../components/Input/Input.cjs');
71
72
  require('../../components/PasskeyCreatedSuccessBanner/PasskeyCreatedSuccessBanner.cjs');
72
73
  require('../../context/PasskeyContext/PasskeyContext.cjs');
@@ -84,6 +85,7 @@ require('../../components/Popper/PopperContext/PopperContext.cjs');
84
85
  require('../WalletList/WalletList.cjs');
85
86
  require('../../widgets/DynamicBridgeWidget/views/WalletsView/components/SecondaryWallets/SecondaryWallets.cjs');
86
87
  require('@hcaptcha/react-hcaptcha');
88
+ var getMfaOptions = require('./getMfaOptions/getMfaOptions.cjs');
87
89
  require('../../context/IpConfigurationContext/IpConfigurationContext.cjs');
88
90
  require('../../context/SendBalanceContext/SendBalanceContext.cjs');
89
91
  require('../../context/ConnectWithOtpContext/ConnectWithOtpContext.cjs');
@@ -92,21 +94,34 @@ require('../../context/ReinitializeContext/ReinitializeContextProvider.cjs');
92
94
  require('../../components/InlineWidget/InlineWidget.cjs');
93
95
  require('qrcode');
94
96
 
95
- const MfaChooseDeviceView = () => {
97
+ const MfaChooseDeviceView = ({ isInitialSetup = true, }) => {
96
98
  const { t } = reactI18next.useTranslation();
97
99
  const { setView } = ViewContext.useViewContext();
98
- const mfaOptions = [
99
- {
100
- Icon: undefined,
101
- description: t('dyn_mfa.choose_device_view.authenticator_app_description'),
102
- label: t('dyn_mfa.choose_device_view.authenticator_app'),
103
- type: sdkApiCore.MFADeviceType.Totp,
104
- },
105
- ];
100
+ const mfaOptions = getMfaOptions.getMfaOptions(isInitialSetup);
106
101
  const handleClick = (option) => {
107
- setView('mfa-secure-device', { type: option.type });
102
+ if (option.type === 'backupCode') {
103
+ setView('mfa-recovery', undefined, {
104
+ onBackClick: () => {
105
+ setView('mfa-choose-device', { isInitialSetup: false });
106
+ },
107
+ });
108
+ return;
109
+ }
110
+ if (isInitialSetup) {
111
+ setView('mfa-secure-device', { type: option.type });
112
+ return;
113
+ }
114
+ setView('mfa-verification', {
115
+ isInitialSetup,
116
+ showBackButton: true,
117
+ type: option.type,
118
+ });
108
119
  };
109
- return (jsxRuntime.jsxs("div", { className: 'mfa-choose-device-view__body', "data-testid": 'mfa-choose-device-view', children: [jsxRuntime.jsx(secureAccount.ReactComponent, {}), jsxRuntime.jsx(Typography.Typography, { className: 'mfa-choose-device-view__copy', variant: 'body_normal', weight: 'regular', color: 'secondary', children: t('dyn_mfa.choose_device_view.select_options') }), mfaOptions.map((option) => (jsxRuntime.jsxs(Button.Button, { buttonClassName: 'mfa-choose-device-view__button', expanded: true, onClick: () => handleClick(option), children: [jsxRuntime.jsxs("div", { className: 'mfa-choose-device-view__button__header', children: [jsxRuntime.jsx(Typography.Typography, { children: option.label }), jsxRuntime.jsx(chevronLeft.ReactComponent, { className: 'mfa-choose-device-view__icon--rotate' })] }), jsxRuntime.jsx(Typography.Typography, { className: 'mfa-choose-device-view__button__description', color: 'secondary', children: option.description })] }, option.type)))] }));
120
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ModalHeader.ModalHeader, { alignContent: 'bottom', children: jsxRuntime.jsx("div", { className: 'otp-verification-view__status-header', children: jsxRuntime.jsx(Typography.Typography, { weight: 'medium', variant: 'title', color: 'primary', className: 'otp-verification-view__title', children: isInitialSetup
121
+ ? t('dyn_mfa.choose_device_view.title')
122
+ : t('dyn_mfa.choose_device_view.choose_another_method') }) }) }), jsxRuntime.jsxs("div", { className: 'mfa-choose-device-view__body', "data-testid": 'mfa-choose-device-view', children: [jsxRuntime.jsx(secureAccount.ReactComponent, {}), jsxRuntime.jsx(Typography.Typography, { className: 'mfa-choose-device-view__copy', variant: 'body_normal', weight: 'regular', color: 'secondary', children: isInitialSetup
123
+ ? t('dyn_mfa.choose_device_view.select_options')
124
+ : t('dyn_mfa.choose_device_view.choose_another_method_description') }), mfaOptions.map((option) => (jsxRuntime.jsxs(Button.Button, { buttonClassName: 'mfa-choose-device-view__button', expanded: true, onClick: () => handleClick(option), children: [jsxRuntime.jsxs("div", { className: 'mfa-choose-device-view__button__header', children: [jsxRuntime.jsx(Typography.Typography, { copykey: option.labelKey, children: t(option.labelKey) }), jsxRuntime.jsx(chevronLeft.ReactComponent, { className: 'mfa-choose-device-view__icon--rotate' })] }), jsxRuntime.jsx(Typography.Typography, { className: 'mfa-choose-device-view__button__description', color: 'secondary', copykey: option.descriptionKey, children: t(option.descriptionKey) })] }, option.type)))] })] }));
110
125
  };
111
126
 
112
127
  exports.MfaChooseDeviceView = MfaChooseDeviceView;
@@ -1,2 +1,5 @@
1
- /// <reference types="react" />
2
- export declare const MfaChooseDeviceView: () => JSX.Element;
1
+ import { FC } from 'react';
2
+ export type MfaChooseDeviceViewProps = {
3
+ isInitialSetup?: boolean;
4
+ };
5
+ export declare const MfaChooseDeviceView: FC<MfaChooseDeviceViewProps>;
@@ -1,7 +1,6 @@
1
1
  'use client'
2
- import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
3
3
  import { useTranslation } from 'react-i18next';
4
- import { MFADeviceType } from '@dynamic-labs/sdk-api-core';
5
4
  import 'react';
6
5
  import { ReactComponent as SvgSecureAccount } from '../../assets/secure-account.js';
7
6
  import '../../components/Accordion/components/AccordionItem/AccordionItem.js';
@@ -10,6 +9,7 @@ import '../../events/dynamicEvents.js';
10
9
  import '../../../../_virtual/_tslib.js';
11
10
  import '@dynamic-labs/utils';
12
11
  import '../../context/DynamicContext/DynamicContext.js';
12
+ import '@dynamic-labs/sdk-api-core';
13
13
  import '../../shared/logger.js';
14
14
  import '@dynamic-labs/iconic';
15
15
  import '@dynamic-labs/wallet-connector-core';
@@ -63,6 +63,7 @@ import '../../components/MenuList/Dropdown/Dropdown.js';
63
63
  import 'formik';
64
64
  import { Button } from '../../components/Button/Button.js';
65
65
  import '../TransactionConfirmationView/helpers/transactionErrorMessage.js';
66
+ import { ModalHeader } from '../../components/ModalHeader/ModalHeader.js';
66
67
  import '../../components/Input/Input.js';
67
68
  import '../../components/PasskeyCreatedSuccessBanner/PasskeyCreatedSuccessBanner.js';
68
69
  import '../../context/PasskeyContext/PasskeyContext.js';
@@ -80,6 +81,7 @@ import '../../components/Popper/PopperContext/PopperContext.js';
80
81
  import '../WalletList/WalletList.js';
81
82
  import '../../widgets/DynamicBridgeWidget/views/WalletsView/components/SecondaryWallets/SecondaryWallets.js';
82
83
  import '@hcaptcha/react-hcaptcha';
84
+ import { getMfaOptions } from './getMfaOptions/getMfaOptions.js';
83
85
  import '../../context/IpConfigurationContext/IpConfigurationContext.js';
84
86
  import '../../context/SendBalanceContext/SendBalanceContext.js';
85
87
  import '../../context/ConnectWithOtpContext/ConnectWithOtpContext.js';
@@ -88,21 +90,34 @@ import '../../context/ReinitializeContext/ReinitializeContextProvider.js';
88
90
  import '../../components/InlineWidget/InlineWidget.js';
89
91
  import 'qrcode';
90
92
 
91
- const MfaChooseDeviceView = () => {
93
+ const MfaChooseDeviceView = ({ isInitialSetup = true, }) => {
92
94
  const { t } = useTranslation();
93
95
  const { setView } = useViewContext();
94
- const mfaOptions = [
95
- {
96
- Icon: undefined,
97
- description: t('dyn_mfa.choose_device_view.authenticator_app_description'),
98
- label: t('dyn_mfa.choose_device_view.authenticator_app'),
99
- type: MFADeviceType.Totp,
100
- },
101
- ];
96
+ const mfaOptions = getMfaOptions(isInitialSetup);
102
97
  const handleClick = (option) => {
103
- setView('mfa-secure-device', { type: option.type });
98
+ if (option.type === 'backupCode') {
99
+ setView('mfa-recovery', undefined, {
100
+ onBackClick: () => {
101
+ setView('mfa-choose-device', { isInitialSetup: false });
102
+ },
103
+ });
104
+ return;
105
+ }
106
+ if (isInitialSetup) {
107
+ setView('mfa-secure-device', { type: option.type });
108
+ return;
109
+ }
110
+ setView('mfa-verification', {
111
+ isInitialSetup,
112
+ showBackButton: true,
113
+ type: option.type,
114
+ });
104
115
  };
105
- return (jsxs("div", { className: 'mfa-choose-device-view__body', "data-testid": 'mfa-choose-device-view', children: [jsx(SvgSecureAccount, {}), jsx(Typography, { className: 'mfa-choose-device-view__copy', variant: 'body_normal', weight: 'regular', color: 'secondary', children: t('dyn_mfa.choose_device_view.select_options') }), mfaOptions.map((option) => (jsxs(Button, { buttonClassName: 'mfa-choose-device-view__button', expanded: true, onClick: () => handleClick(option), children: [jsxs("div", { className: 'mfa-choose-device-view__button__header', children: [jsx(Typography, { children: option.label }), jsx(SvgChevronLeft, { className: 'mfa-choose-device-view__icon--rotate' })] }), jsx(Typography, { className: 'mfa-choose-device-view__button__description', color: 'secondary', children: option.description })] }, option.type)))] }));
116
+ return (jsxs(Fragment, { children: [jsx(ModalHeader, { alignContent: 'bottom', children: jsx("div", { className: 'otp-verification-view__status-header', children: jsx(Typography, { weight: 'medium', variant: 'title', color: 'primary', className: 'otp-verification-view__title', children: isInitialSetup
117
+ ? t('dyn_mfa.choose_device_view.title')
118
+ : t('dyn_mfa.choose_device_view.choose_another_method') }) }) }), jsxs("div", { className: 'mfa-choose-device-view__body', "data-testid": 'mfa-choose-device-view', children: [jsx(SvgSecureAccount, {}), jsx(Typography, { className: 'mfa-choose-device-view__copy', variant: 'body_normal', weight: 'regular', color: 'secondary', children: isInitialSetup
119
+ ? t('dyn_mfa.choose_device_view.select_options')
120
+ : t('dyn_mfa.choose_device_view.choose_another_method_description') }), mfaOptions.map((option) => (jsxs(Button, { buttonClassName: 'mfa-choose-device-view__button', expanded: true, onClick: () => handleClick(option), children: [jsxs("div", { className: 'mfa-choose-device-view__button__header', children: [jsx(Typography, { copykey: option.labelKey, children: t(option.labelKey) }), jsx(SvgChevronLeft, { className: 'mfa-choose-device-view__icon--rotate' })] }), jsx(Typography, { className: 'mfa-choose-device-view__button__description', color: 'secondary', copykey: option.descriptionKey, children: t(option.descriptionKey) })] }, option.type)))] })] }));
106
121
  };
107
122
 
108
123
  export { MfaChooseDeviceView };
@@ -0,0 +1,29 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ var sdkApiCore = require('@dynamic-labs/sdk-api-core');
7
+
8
+ const getMfaOptions = (isInitialSetup) => {
9
+ const mfaOptions = [
10
+ {
11
+ Icon: undefined,
12
+ descriptionKey: 'dyn_mfa.choose_device_view.authenticator_app_description',
13
+ labelKey: 'dyn_mfa.choose_device_view.authenticator_app',
14
+ type: sdkApiCore.MFADeviceType.Totp,
15
+ },
16
+ ];
17
+ if (!isInitialSetup) {
18
+ const backupCodeOption = {
19
+ Icon: undefined,
20
+ descriptionKey: 'dyn_mfa.choose_device_view.backup_code_description',
21
+ labelKey: 'dyn_mfa.choose_device_view.backup_code',
22
+ type: 'backupCode',
23
+ };
24
+ mfaOptions.push(backupCodeOption);
25
+ }
26
+ return mfaOptions;
27
+ };
28
+
29
+ exports.getMfaOptions = getMfaOptions;
@@ -0,0 +1,11 @@
1
+ /// <reference types="react" />
2
+ import { MFADeviceType } from '@dynamic-labs/sdk-api-core';
3
+ type MFAAuthType = MFADeviceType | 'backupCode';
4
+ export type MfaOption = {
5
+ Icon?: React.ReactNode;
6
+ descriptionKey: string;
7
+ labelKey: string;
8
+ type: MFAAuthType;
9
+ };
10
+ export declare const getMfaOptions: (isInitialSetup: boolean) => MfaOption[];
11
+ export {};
@@ -0,0 +1,25 @@
1
+ 'use client'
2
+ import { MFADeviceType } from '@dynamic-labs/sdk-api-core';
3
+
4
+ const getMfaOptions = (isInitialSetup) => {
5
+ const mfaOptions = [
6
+ {
7
+ Icon: undefined,
8
+ descriptionKey: 'dyn_mfa.choose_device_view.authenticator_app_description',
9
+ labelKey: 'dyn_mfa.choose_device_view.authenticator_app',
10
+ type: MFADeviceType.Totp,
11
+ },
12
+ ];
13
+ if (!isInitialSetup) {
14
+ const backupCodeOption = {
15
+ Icon: undefined,
16
+ descriptionKey: 'dyn_mfa.choose_device_view.backup_code_description',
17
+ labelKey: 'dyn_mfa.choose_device_view.backup_code',
18
+ type: 'backupCode',
19
+ };
20
+ mfaOptions.push(backupCodeOption);
21
+ }
22
+ return mfaOptions;
23
+ };
24
+
25
+ export { getMfaOptions };
@@ -0,0 +1 @@
1
+ export * from './getMfaOptions';
@@ -23,6 +23,7 @@ require('../../utils/constants/values.cjs');
23
23
  require('../../shared/utils/classes/storage/localStorage.cjs');
24
24
  require('../../shared/utils/classes/storage/sessionStorage.cjs');
25
25
  require('../../shared/consts/index.cjs');
26
+ var useInternalDynamicContext = require('../../context/DynamicContext/useDynamicContext/useInternalDynamicContext.cjs');
26
27
  require('../../context/CaptchaContext/CaptchaContext.cjs');
27
28
  require('../../context/ErrorContext/ErrorContext.cjs');
28
29
  require('@dynamic-labs/multi-wallet');
@@ -30,6 +31,7 @@ require('react-international-phone');
30
31
  require('../../config/ApiEndpoint.cjs');
31
32
  require('@dynamic-labs/store');
32
33
  require('../../locale/locale.cjs');
34
+ var isValidMfaRecoveryCode = require('../../utils/functions/isValidMfaRecoveryCode/isValidMfaRecoveryCode.cjs');
33
35
  require('../../context/AccessDeniedContext/AccessDeniedContext.cjs');
34
36
  require('../../context/AccountExistsContext/AccountExistsContext.cjs');
35
37
  require('../../context/UserWalletsContext/UserWalletsContext.cjs');
@@ -86,7 +88,6 @@ require('../../widgets/DynamicBridgeWidget/views/WalletsView/components/Secondar
86
88
  require('@hcaptcha/react-hcaptcha');
87
89
  var useMfa = require('../../utils/hooks/useMfa/useMfa.cjs');
88
90
  require('../../context/IpConfigurationContext/IpConfigurationContext.cjs');
89
- var validateMfaRecoveryCode = require('../../utils/functions/validateMfaRecoveryCode/validateMfaRecoveryCode.cjs');
90
91
  require('../../context/SendBalanceContext/SendBalanceContext.cjs');
91
92
  require('../../context/ConnectWithOtpContext/ConnectWithOtpContext.cjs');
92
93
  require('../../context/ConnectWithOtpContext/constants.cjs');
@@ -96,36 +97,35 @@ require('../../components/InlineWidget/InlineWidget.cjs');
96
97
  require('qrcode');
97
98
 
98
99
  const MfaRecoveryView = () => {
100
+ var _a;
99
101
  const { t } = reactI18next.useTranslation();
102
+ const { projectSettings } = useInternalDynamicContext.useInternalDynamicContext();
100
103
  const { authRecoveryCode } = useMfa.useMfa();
101
104
  const [code, setCode] = React.useState('');
102
- const [isValid, setIsValid] = React.useState(false);
105
+ const [isLoading, setIsLoading] = React.useState(false);
103
106
  const [error, setError] = React.useState('');
104
- const openHelp = () => undefined;
107
+ const supportEmail = (_a = projectSettings === null || projectSettings === void 0 ? void 0 : projectSettings.general) === null || _a === void 0 ? void 0 : _a.supportEmail;
105
108
  const handleRecovery = () => _tslib.__awaiter(void 0, void 0, void 0, function* () {
106
109
  if (!code) {
107
- setIsValid(false);
108
110
  return;
109
111
  }
110
112
  try {
113
+ setIsLoading(true);
111
114
  yield authRecoveryCode(code);
112
115
  }
113
116
  catch (e) {
114
117
  setError(e.message || 'Something went wrong');
115
118
  }
119
+ finally {
120
+ setIsLoading(false);
121
+ }
116
122
  });
117
123
  const handleCodeChanged = (event) => {
118
124
  const inputCode = event.target.value;
119
125
  setCode(inputCode);
120
- if (validateMfaRecoveryCode.validateMfaRecoveryCode(inputCode)) {
121
- setIsValid(true);
122
- }
123
- else {
124
- setIsValid(false);
125
- setError('');
126
- }
126
+ setError('');
127
127
  };
128
- return (jsxRuntime.jsxs("div", { className: 'mfa-recovery-view', children: [error && jsxRuntime.jsx(ErrorContainer.ErrorContainer, { children: error }), !error && !isValid && (jsxRuntime.jsx(IconWithSpinner.IconWithSpinner, { Icon: MfaRecoveryIcon.MfaRecoveryScreenIcon, isSpinning: !error && !isValid, iconSize: 96 })), jsxRuntime.jsx("div", { className: 'mfa-recovery-view__body', children: jsxRuntime.jsx(Typography.Typography, { variant: 'body_normal', weight: 'regular', color: 'secondary', children: t('dyn_mfa.recovery_view.body') }) }), jsxRuntime.jsxs("div", { className: 'mfa-recovery-view__actions', children: [jsxRuntime.jsx(Input.Input, { id: 'mfa-recovery-input', "data-testid": 'mfa-recovery-input', label: t('dyn_mfa.recovery_view.input_label'), onChange: handleCodeChanged, value: code }), jsxRuntime.jsx(Button.Button, { expanded: true, buttonVariant: 'brand-primary', disabled: !isValid, onClick: handleRecovery, dataTestId: 'mfa-recovery-submit', children: jsxRuntime.jsx(Typography.Typography, { children: t('dyn_mfa.recovery_view.button_label') }) })] }), jsxRuntime.jsxs("div", { className: 'mfa-recovery-view__get-help', children: [jsxRuntime.jsx(Typography.Typography, { variant: 'body_small', color: 'secondary', children: t('dyn_mfa.recovery_view.get_help.description') }), jsxRuntime.jsx("button", { onClick: openHelp, children: jsxRuntime.jsx(Typography.Typography, { variant: 'body_small', color: 'link', children: t('dyn_mfa.recovery_view.get_help.button_label') }) })] })] }));
128
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [error && jsxRuntime.jsx(ErrorContainer.ErrorContainer, { children: error }), jsxRuntime.jsxs("div", { className: 'mfa-recovery-view', children: [jsxRuntime.jsx(IconWithSpinner.IconWithSpinner, { Icon: MfaRecoveryIcon.MfaRecoveryScreenIcon, isSpinning: isLoading, iconSize: 96 }), jsxRuntime.jsx("div", { className: 'mfa-recovery-view__body', children: jsxRuntime.jsx(Typography.Typography, { variant: 'body_normal', weight: 'regular', color: 'secondary', children: t('dyn_mfa.recovery_view.body') }) }), jsxRuntime.jsxs("div", { className: 'mfa-recovery-view__actions', children: [jsxRuntime.jsx(Input.Input, { id: 'mfa-recovery-input', "data-testid": 'mfa-recovery-input', label: t('dyn_mfa.recovery_view.input_label'), onChange: handleCodeChanged, value: code }), jsxRuntime.jsx(Button.Button, { expanded: true, buttonVariant: 'brand-primary', disabled: isLoading || !isValidMfaRecoveryCode.isValidMfaRecoveryCode(code), onClick: handleRecovery, dataTestId: 'mfa-recovery-submit', children: jsxRuntime.jsx(Typography.Typography, { children: t('dyn_mfa.recovery_view.button_label') }) })] }), supportEmail && (jsxRuntime.jsxs("div", { className: 'mfa-recovery-view__get-help', children: [jsxRuntime.jsx(Typography.Typography, { variant: 'body_small', color: 'secondary', children: t('dyn_mfa.recovery_view.get_help.description') }), jsxRuntime.jsx(Typography.Typography, { variant: 'body_small', color: 'link', children: jsxRuntime.jsx("a", { href: `mailto:${supportEmail}`, children: t('dyn_mfa.recovery_view.get_help.button_label') }) })] }))] })] }));
129
129
  };
130
130
 
131
131
  exports.MfaRecoveryView = MfaRecoveryView;