@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.
- package/CHANGELOG.md +16 -0
- package/package.cjs +2 -2
- package/package.js +2 -2
- package/package.json +12 -12
- package/src/index.cjs +5 -1
- package/src/index.d.ts +1 -1
- package/src/index.js +1 -1
- package/src/lib/components/OTPVerificationView/OTPVerificationView.cjs +2 -2
- package/src/lib/components/OTPVerificationView/OTPVerificationView.js +2 -2
- package/src/lib/data/api/mfa/mfa.cjs +9 -4
- package/src/lib/data/api/mfa/mfa.js +9 -4
- package/src/lib/locale/en/translation.cjs +14 -8
- package/src/lib/locale/en/translation.d.ts +12 -6
- package/src/lib/locale/en/translation.js +14 -8
- package/src/lib/styles/index.shadow.cjs +1 -1
- package/src/lib/styles/index.shadow.js +1 -1
- package/src/lib/utils/functions/index.d.ts +1 -0
- package/src/lib/utils/functions/isValidMfaRecoveryCode/index.d.ts +1 -0
- package/src/lib/utils/functions/isValidMfaRecoveryCode/isValidMfaRecoveryCode.cjs +11 -0
- package/src/lib/utils/functions/isValidMfaRecoveryCode/isValidMfaRecoveryCode.d.ts +1 -0
- package/src/lib/utils/functions/isValidMfaRecoveryCode/isValidMfaRecoveryCode.js +7 -0
- package/src/lib/utils/hooks/useAuthLayoutChecks/useAuthLayoutChecks.cjs +3 -1
- package/src/lib/utils/hooks/useAuthLayoutChecks/useAuthLayoutChecks.js +3 -1
- package/src/lib/utils/hooks/useEmbeddedWallet/index.d.ts +1 -0
- package/src/lib/utils/hooks/useEmbeddedWallet/useEmbeddedWallet.cjs +4 -3
- package/src/lib/utils/hooks/useEmbeddedWallet/useEmbeddedWallet.d.ts +1 -1
- package/src/lib/utils/hooks/useEmbeddedWallet/useEmbeddedWallet.js +4 -3
- package/src/lib/utils/hooks/useEmbeddedWallet/useSecureEnclaveEmbeddedWallet/index.d.ts +1 -0
- package/src/lib/utils/hooks/useSocialAuth/useSocialAuth.cjs +8 -5
- package/src/lib/utils/hooks/useSocialAuth/useSocialAuth.js +8 -5
- package/src/lib/utils/hooks/useSyncMfaFlow/useSyncMfaFlow.cjs +5 -1
- package/src/lib/utils/hooks/useSyncMfaFlow/useSyncMfaFlow.js +5 -1
- package/src/lib/views/MfaChooseDeviceView/MfaChooseDeviceView.cjs +27 -12
- package/src/lib/views/MfaChooseDeviceView/MfaChooseDeviceView.d.ts +5 -2
- package/src/lib/views/MfaChooseDeviceView/MfaChooseDeviceView.js +28 -13
- package/src/lib/views/MfaChooseDeviceView/getMfaOptions/getMfaOptions.cjs +29 -0
- package/src/lib/views/MfaChooseDeviceView/getMfaOptions/getMfaOptions.d.ts +11 -0
- package/src/lib/views/MfaChooseDeviceView/getMfaOptions/getMfaOptions.js +25 -0
- package/src/lib/views/MfaChooseDeviceView/getMfaOptions/index.d.ts +1 -0
- package/src/lib/views/MfaRecoveryView/MfaRecoveryView.cjs +12 -12
- package/src/lib/views/MfaRecoveryView/MfaRecoveryView.js +13 -13
- package/src/lib/views/MfaSecureDeviceView/MfaSecureDeviceView.cjs +1 -1
- package/src/lib/views/MfaSecureDeviceView/MfaSecureDeviceView.js +1 -1
- package/src/lib/views/MfaVerificationView/MfaVerificationView.cjs +10 -2
- package/src/lib/views/MfaVerificationView/MfaVerificationView.d.ts +3 -1
- package/src/lib/views/MfaVerificationView/MfaVerificationView.js +11 -3
- package/src/lib/views/viewToComponentMap.d.ts +2 -2
- package/src/lib/utils/functions/validateMfaRecoveryCode/index.d.ts +0 -1
- package/src/lib/utils/functions/validateMfaRecoveryCode/validateMfaRecoveryCode.cjs +0 -11
- package/src/lib/utils/functions/validateMfaRecoveryCode/validateMfaRecoveryCode.d.ts +0 -1
- package/src/lib/utils/functions/validateMfaRecoveryCode/validateMfaRecoveryCode.js +0 -7
|
@@ -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;
|
|
@@ -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("
|
|
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
|
|
@@ -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, {
|
|
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
|
|
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:
|
|
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, {
|
|
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
|
|
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:
|
|
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('
|
|
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 '
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
2
|
-
export
|
|
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
|
-
|
|
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(
|
|
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 [
|
|
105
|
+
const [isLoading, setIsLoading] = React.useState(false);
|
|
103
106
|
const [error, setError] = React.useState('');
|
|
104
|
-
const
|
|
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
|
-
|
|
121
|
-
setIsValid(true);
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
setIsValid(false);
|
|
125
|
-
setError('');
|
|
126
|
-
}
|
|
126
|
+
setError('');
|
|
127
127
|
};
|
|
128
|
-
return (jsxRuntime.jsxs(
|
|
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;
|