@dynamic-labs/sdk-react-core 3.0.0-alpha.46 → 3.0.0-alpha.47
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 +25 -0
- package/package.cjs +2 -2
- package/package.js +2 -2
- package/package.json +13 -13
- package/src/index.cjs +2 -2
- 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.d.ts +1 -0
- package/src/lib/components/OTPVerificationView/OTPVerificationView.js +2 -2
- package/src/lib/components/PinField/PinField.cjs +2 -2
- package/src/lib/components/PinField/PinField.d.ts +1 -1
- package/src/lib/components/PinField/PinField.js +2 -2
- package/src/lib/components/SendBalanceForm/SendBalanceForm.cjs +1 -1
- package/src/lib/components/SendBalanceForm/SendBalanceForm.js +1 -1
- package/src/lib/components/SendBalancePageLayout/SendBalancePageLayout.cjs +3 -3
- package/src/lib/components/SendBalancePageLayout/SendBalancePageLayout.js +3 -3
- package/src/lib/components/TransactionConfirmationPageLayout/TransactionConfirmationPageLayout.cjs +3 -3
- package/src/lib/components/TransactionConfirmationPageLayout/TransactionConfirmationPageLayout.js +3 -3
- package/src/lib/components/TransactionStatusLayout/TransactionStatusLayout.cjs +1 -1
- package/src/lib/components/TransactionStatusLayout/TransactionStatusLayout.js +1 -1
- package/src/lib/components/UserProfile/parts/UserProfileSocialAccount/UserProfileSocialAccount.cjs +1 -1
- package/src/lib/components/UserProfile/parts/UserProfileSocialAccount/UserProfileSocialAccount.js +1 -1
- package/src/lib/context/DynamicContext/useDynamicContext/useDynamicContext.cjs +1 -2
- package/src/lib/context/DynamicContext/useDynamicContext/useDynamicContext.d.ts +1 -1
- package/src/lib/context/DynamicContext/useDynamicContext/useDynamicContext.js +1 -2
- package/src/lib/data/api/mfa/mfa.cjs +5 -1
- package/src/lib/data/api/mfa/mfa.d.ts +2 -1
- package/src/lib/data/api/mfa/mfa.js +6 -2
- package/src/lib/locale/en/translation.cjs +3 -1
- package/src/lib/locale/en/translation.d.ts +2 -0
- package/src/lib/locale/en/translation.js +3 -1
- package/src/lib/styles/index.shadow.cjs +1 -1
- package/src/lib/styles/index.shadow.js +1 -1
- package/src/lib/utils/hooks/index.d.ts +1 -1
- package/src/lib/utils/hooks/useMfa/useMfa.cjs +2 -1
- package/src/lib/utils/hooks/useMfa/useMfa.d.ts +1 -1
- package/src/lib/utils/hooks/useMfa/useMfa.js +2 -1
- package/src/lib/utils/hooks/useOnlyConnectedMode/useOnlyConnectedMode.d.ts +0 -1
- package/src/lib/utils/hooks/useSocialAuth/useSocialAuth.cjs +7 -13
- package/src/lib/utils/hooks/useSocialAuth/useSocialAuth.js +7 -13
- package/src/lib/utils/hooks/useUserAuth/useUserAuth.cjs +2 -1
- package/src/lib/utils/hooks/useUserAuth/useUserAuth.js +3 -2
- package/src/lib/utils/hooks/useWalletOptions/index.d.ts +1 -0
- package/src/lib/utils/hooks/{useSelectWalletOption/useSelectWalletOption.cjs → useWalletOptions/useWalletOptions.cjs} +31 -4
- package/src/lib/utils/hooks/useWalletOptions/useWalletOptions.d.ts +9 -0
- package/src/lib/utils/hooks/{useSelectWalletOption/useSelectWalletOption.js → useWalletOptions/useWalletOptions.js} +32 -5
- package/src/lib/views/MfaVerificationView/MfaVerificationView.cjs +10 -3
- package/src/lib/views/MfaVerificationView/MfaVerificationView.js +11 -4
- package/src/lib/widgets/DynamicWidget/views/ManageMfaWidgetView/ManageMfaWidgetView.cjs +20 -6
- package/src/lib/widgets/DynamicWidget/views/ManageMfaWidgetView/ManageMfaWidgetView.js +21 -7
- package/src/lib/widgets/DynamicWidget/views/ManageMfaWidgetView/components/UserDeviceTile.cjs +3 -4
- package/src/lib/widgets/DynamicWidget/views/ManageMfaWidgetView/components/UserDeviceTile.d.ts +2 -1
- package/src/lib/widgets/DynamicWidget/views/ManageMfaWidgetView/components/UserDeviceTile.js +3 -4
- package/src/lib/widgets/DynamicWidget/views/ManageMfaWidgetView/components/utils/sort.cjs +2 -8
- package/src/lib/widgets/DynamicWidget/views/ManageMfaWidgetView/components/utils/sort.d.ts +1 -1
- package/src/lib/widgets/DynamicWidget/views/ManageMfaWidgetView/components/utils/sort.js +2 -8
- package/src/lib/utils/hooks/useSelectWalletOption/index.d.ts +0 -1
- package/src/lib/utils/hooks/useSelectWalletOption/useSelectWalletOption.d.ts +0 -3
|
@@ -60,6 +60,6 @@ export { useSyncEmbeddedWalletFlow } from './useSyncEmbeddedWalletFlow';
|
|
|
60
60
|
export { useSyncOnboardingFlow } from './useSyncOnboardingFlow';
|
|
61
61
|
export { useExternalAuth } from './useExternalAuth';
|
|
62
62
|
export { useRefreshUser } from './useRefreshUser';
|
|
63
|
-
export {
|
|
63
|
+
export { useWalletOptions } from './useWalletOptions';
|
|
64
64
|
export { useResetCookieLocalStorage } from './useResetCookieLocalStorage';
|
|
65
65
|
export { useSyncMfaFlow } from './useSyncMfaFlow';
|
|
@@ -112,12 +112,13 @@ const useMfa = () => {
|
|
|
112
112
|
mfaDeviceId: deviceId,
|
|
113
113
|
});
|
|
114
114
|
});
|
|
115
|
-
const deleteUserDevice = (deviceId) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
115
|
+
const deleteUserDevice = (deviceId, mfaAuthToken) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
116
116
|
if (!verifiedUser) {
|
|
117
117
|
throw new Error(errors.USER_NOT_LOGGED_IN);
|
|
118
118
|
}
|
|
119
119
|
yield mfa.deleteMfaDevice({
|
|
120
120
|
environmentId,
|
|
121
|
+
mfaAuthToken,
|
|
121
122
|
mfaDeviceId: deviceId,
|
|
122
123
|
});
|
|
123
124
|
});
|
|
@@ -7,7 +7,7 @@ export declare const useMfa: () => {
|
|
|
7
7
|
}>;
|
|
8
8
|
readonly authDevice: (code: string, type?: MFADeviceType, deviceId?: string) => Promise<boolean>;
|
|
9
9
|
readonly authRecoveryCode: (code: string) => Promise<boolean>;
|
|
10
|
-
readonly deleteUserDevice: (deviceId: string) => Promise<void>;
|
|
10
|
+
readonly deleteUserDevice: (deviceId: string, mfaAuthToken: string) => Promise<void>;
|
|
11
11
|
readonly getRecoveryCodes: (generateNewCodes?: boolean) => Promise<string[]>;
|
|
12
12
|
readonly getUserDevices: () => Promise<MFADevice[]>;
|
|
13
13
|
readonly updateUserDevice: (deviceId: string) => Promise<void>;
|
|
@@ -108,12 +108,13 @@ const useMfa = () => {
|
|
|
108
108
|
mfaDeviceId: deviceId,
|
|
109
109
|
});
|
|
110
110
|
});
|
|
111
|
-
const deleteUserDevice = (deviceId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
111
|
+
const deleteUserDevice = (deviceId, mfaAuthToken) => __awaiter(void 0, void 0, void 0, function* () {
|
|
112
112
|
if (!verifiedUser) {
|
|
113
113
|
throw new Error(USER_NOT_LOGGED_IN);
|
|
114
114
|
}
|
|
115
115
|
yield deleteMfaDevice({
|
|
116
116
|
environmentId,
|
|
117
|
+
mfaAuthToken,
|
|
117
118
|
mfaDeviceId: deviceId,
|
|
118
119
|
});
|
|
119
120
|
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const useOnlyConnectedMode: () => boolean;
|
|
@@ -228,29 +228,23 @@ const useSocialAuth = ({ sessionTimeout, onSettled, onError, onFarcasterUrl, })
|
|
|
228
228
|
oauthLoginUrl.searchParams.set('code_challenge_method', 'S256');
|
|
229
229
|
}
|
|
230
230
|
const isMobile = utils.isMobile();
|
|
231
|
-
const effectiveRedirectUrl = redirectUrl !== null && redirectUrl !== void 0 ? redirectUrl : defaultRedirectUrl;
|
|
232
231
|
try {
|
|
233
232
|
const authCode = yield utils.Oauth2Service.getOauthCode({
|
|
234
233
|
apiProvider: getProviderByType.getProviderByType((_c = projectSettings === null || projectSettings === void 0 ? void 0 : projectSettings.providers) !== null && _c !== void 0 ? _c : [], provider),
|
|
235
234
|
getOAuthResultFromApi: () => oauth.getOAuthResult(environmentId, provider, {
|
|
236
235
|
state,
|
|
237
236
|
}),
|
|
238
|
-
initWebAuth: () => {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
? removeDynamicOauthParamsFromUrl(mobileRedirectUrl)
|
|
245
|
-
: undefined,
|
|
246
|
-
state,
|
|
247
|
-
});
|
|
248
|
-
},
|
|
237
|
+
initWebAuth: ({ redirectUrl } = {}) => oauth.initAuth(environmentId, provider, {
|
|
238
|
+
redirectUrl: redirectUrl
|
|
239
|
+
? removeDynamicOauthParamsFromUrl(redirectUrl)
|
|
240
|
+
: undefined,
|
|
241
|
+
state,
|
|
242
|
+
}),
|
|
249
243
|
isMobile,
|
|
250
244
|
oauthLoginUrl,
|
|
251
245
|
onSettled,
|
|
252
246
|
provider,
|
|
253
|
-
redirectUrl:
|
|
247
|
+
redirectUrl: redirectUrl !== null && redirectUrl !== void 0 ? redirectUrl : defaultRedirectUrl,
|
|
254
248
|
sessionTimeout,
|
|
255
249
|
setIsProcessing,
|
|
256
250
|
state,
|
|
@@ -224,29 +224,23 @@ const useSocialAuth = ({ sessionTimeout, onSettled, onError, onFarcasterUrl, })
|
|
|
224
224
|
oauthLoginUrl.searchParams.set('code_challenge_method', 'S256');
|
|
225
225
|
}
|
|
226
226
|
const isMobile$1 = isMobile();
|
|
227
|
-
const effectiveRedirectUrl = redirectUrl !== null && redirectUrl !== void 0 ? redirectUrl : defaultRedirectUrl;
|
|
228
227
|
try {
|
|
229
228
|
const authCode = yield Oauth2Service.getOauthCode({
|
|
230
229
|
apiProvider: getProviderByType((_c = projectSettings === null || projectSettings === void 0 ? void 0 : projectSettings.providers) !== null && _c !== void 0 ? _c : [], provider),
|
|
231
230
|
getOAuthResultFromApi: () => getOAuthResult(environmentId, provider, {
|
|
232
231
|
state,
|
|
233
232
|
}),
|
|
234
|
-
initWebAuth: () => {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
? removeDynamicOauthParamsFromUrl(mobileRedirectUrl)
|
|
241
|
-
: undefined,
|
|
242
|
-
state,
|
|
243
|
-
});
|
|
244
|
-
},
|
|
233
|
+
initWebAuth: ({ redirectUrl } = {}) => initAuth(environmentId, provider, {
|
|
234
|
+
redirectUrl: redirectUrl
|
|
235
|
+
? removeDynamicOauthParamsFromUrl(redirectUrl)
|
|
236
|
+
: undefined,
|
|
237
|
+
state,
|
|
238
|
+
}),
|
|
245
239
|
isMobile: isMobile$1,
|
|
246
240
|
oauthLoginUrl,
|
|
247
241
|
onSettled,
|
|
248
242
|
provider,
|
|
249
|
-
redirectUrl:
|
|
243
|
+
redirectUrl: redirectUrl !== null && redirectUrl !== void 0 ? redirectUrl : defaultRedirectUrl,
|
|
250
244
|
sessionTimeout,
|
|
251
245
|
setIsProcessing,
|
|
252
246
|
state,
|
|
@@ -166,7 +166,8 @@ const useUserAuth = ({ authMethod, }) => {
|
|
|
166
166
|
});
|
|
167
167
|
const handleAuthError = (error, { options = {}, onError, }) => {
|
|
168
168
|
var _a;
|
|
169
|
-
if (error instanceof utils.MfaInvalidOtpError
|
|
169
|
+
if (error instanceof utils.MfaInvalidOtpError ||
|
|
170
|
+
error instanceof utils.MfaRateLimitedError) {
|
|
170
171
|
throw error;
|
|
171
172
|
}
|
|
172
173
|
// these get caught in onboarding form and handled there
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
import { __awaiter } from '../../../../../_virtual/_tslib.js';
|
|
3
|
-
import { DynamicError, MfaInvalidOtpError, EmailAlreadyExistsError, CustomFieldNotUniqueError, UsernameAlreadyExistsError, TooManyEmailVerificationsError, InvalidPhoneNumberError, NoAccessError, AccountExistsError, SandboxMaximumThresholdReachedError, UserHasAccountWithEmailError, sleep } from '@dynamic-labs/utils';
|
|
3
|
+
import { DynamicError, MfaInvalidOtpError, MfaRateLimitedError, EmailAlreadyExistsError, CustomFieldNotUniqueError, UsernameAlreadyExistsError, TooManyEmailVerificationsError, InvalidPhoneNumberError, NoAccessError, AccountExistsError, SandboxMaximumThresholdReachedError, UserHasAccountWithEmailError, sleep } from '@dynamic-labs/utils';
|
|
4
4
|
import { MfaBackupCodeAcknowledgement } from '@dynamic-labs/sdk-api-core';
|
|
5
5
|
import { useAccountExistsContext } from '../../../context/AccountExistsContext/AccountExistsContext.js';
|
|
6
6
|
import 'react';
|
|
@@ -162,7 +162,8 @@ const useUserAuth = ({ authMethod, }) => {
|
|
|
162
162
|
});
|
|
163
163
|
const handleAuthError = (error, { options = {}, onError, }) => {
|
|
164
164
|
var _a;
|
|
165
|
-
if (error instanceof MfaInvalidOtpError
|
|
165
|
+
if (error instanceof MfaInvalidOtpError ||
|
|
166
|
+
error instanceof MfaRateLimitedError) {
|
|
166
167
|
throw error;
|
|
167
168
|
}
|
|
168
169
|
// these get caught in onboarding form and handled there
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useWalletOptions } from './useWalletOptions';
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
5
|
|
|
6
6
|
var _tslib = require('../../../../../_virtual/_tslib.cjs');
|
|
7
|
+
var React = require('react');
|
|
7
8
|
var walletConnectorCore = require('@dynamic-labs/wallet-connector-core');
|
|
8
9
|
var walletBook = require('@dynamic-labs/wallet-book');
|
|
9
10
|
var utils = require('@dynamic-labs/utils');
|
|
10
|
-
require('react');
|
|
11
11
|
require('../../../context/DynamicContext/DynamicContext.cjs');
|
|
12
12
|
require('@dynamic-labs/sdk-api-core');
|
|
13
13
|
require('../../../shared/logger.cjs');
|
|
@@ -93,16 +93,42 @@ require('../../../context/ConnectWithOtpContext/constants.cjs');
|
|
|
93
93
|
require('../../../context/ReinitializeContext/ReinitializeContextProvider.cjs');
|
|
94
94
|
var useInternalDynamicContext = require('../../../context/DynamicContext/useDynamicContext/useInternalDynamicContext.cjs');
|
|
95
95
|
|
|
96
|
-
const
|
|
96
|
+
const embeddedWalletsKeys = [
|
|
97
|
+
'magicemailotp',
|
|
98
|
+
'magiclink',
|
|
99
|
+
'magicsocial',
|
|
100
|
+
'turnkey',
|
|
101
|
+
'turnkeyhd',
|
|
102
|
+
'coinbasempc',
|
|
103
|
+
'zerodev',
|
|
104
|
+
];
|
|
105
|
+
const useWalletOptions = () => {
|
|
97
106
|
const { walletConnectorOptions, setShowAuthFlow } = useInternalDynamicContext.useInternalDynamicContext();
|
|
98
107
|
const { walletBook: walletBook$1 } = walletBook.useWalletBookContext();
|
|
99
108
|
const { setView } = ViewContext.useViewContext();
|
|
100
109
|
const { navigateToWalletGroup } = WalletGroupContext.useWalletGroupContext();
|
|
101
110
|
const { handleWalletItemClick } = useWalletItemActions.useWalletItemActions();
|
|
111
|
+
const walletOptions = React.useMemo(() => {
|
|
112
|
+
var _a;
|
|
113
|
+
return (_a = walletConnectorOptions === null || walletConnectorOptions === void 0 ? void 0 : walletConnectorOptions.filter((option) => !embeddedWalletsKeys.includes(option.walletConnector.key)).map((option) => {
|
|
114
|
+
const groupName = option.group
|
|
115
|
+
? walletBook.getWalletGroup(walletBook$1, option.group).name
|
|
116
|
+
: undefined;
|
|
117
|
+
return {
|
|
118
|
+
group: option.group,
|
|
119
|
+
groupName,
|
|
120
|
+
key: option.walletConnector.key,
|
|
121
|
+
name: option.name,
|
|
122
|
+
};
|
|
123
|
+
})) !== null && _a !== void 0 ? _a : [];
|
|
124
|
+
}, [walletBook$1, walletConnectorOptions]);
|
|
102
125
|
const selectWalletOption = (walletKey) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
103
126
|
const group = groupWalletOptions.groupWalletOptions(walletBook$1, walletConnectorOptions);
|
|
104
127
|
const walletOption = group.find((wallet) => wallet.key === walletKey);
|
|
105
|
-
logVerboseTroubleshootingMessage.logVerboseTroubleshootingMessage('[
|
|
128
|
+
logVerboseTroubleshootingMessage.logVerboseTroubleshootingMessage('[useWalletOptions] selectWalletOption', {
|
|
129
|
+
walletKey,
|
|
130
|
+
walletOption: walletOption === null || walletOption === void 0 ? void 0 : walletOption.key,
|
|
131
|
+
});
|
|
106
132
|
if (!walletOption) {
|
|
107
133
|
throw new utils.DynamicError('Invalid wallet option key provided.');
|
|
108
134
|
}
|
|
@@ -123,7 +149,8 @@ const useSelectWalletOption = () => {
|
|
|
123
149
|
});
|
|
124
150
|
return {
|
|
125
151
|
selectWalletOption,
|
|
152
|
+
walletOptions,
|
|
126
153
|
};
|
|
127
154
|
};
|
|
128
155
|
|
|
129
|
-
exports.
|
|
156
|
+
exports.useWalletOptions = useWalletOptions;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
import { __awaiter } from '../../../../../_virtual/_tslib.js';
|
|
3
|
+
import { useMemo } from 'react';
|
|
3
4
|
import { isHardwareWalletConnector } from '@dynamic-labs/wallet-connector-core';
|
|
4
|
-
import { useWalletBookContext } from '@dynamic-labs/wallet-book';
|
|
5
|
+
import { useWalletBookContext, getWalletGroup } from '@dynamic-labs/wallet-book';
|
|
5
6
|
import { DynamicError } from '@dynamic-labs/utils';
|
|
6
|
-
import 'react';
|
|
7
7
|
import '../../../context/DynamicContext/DynamicContext.js';
|
|
8
8
|
import '@dynamic-labs/sdk-api-core';
|
|
9
9
|
import '../../../shared/logger.js';
|
|
@@ -89,16 +89,42 @@ import '../../../context/ConnectWithOtpContext/constants.js';
|
|
|
89
89
|
import '../../../context/ReinitializeContext/ReinitializeContextProvider.js';
|
|
90
90
|
import { useInternalDynamicContext } from '../../../context/DynamicContext/useDynamicContext/useInternalDynamicContext.js';
|
|
91
91
|
|
|
92
|
-
const
|
|
92
|
+
const embeddedWalletsKeys = [
|
|
93
|
+
'magicemailotp',
|
|
94
|
+
'magiclink',
|
|
95
|
+
'magicsocial',
|
|
96
|
+
'turnkey',
|
|
97
|
+
'turnkeyhd',
|
|
98
|
+
'coinbasempc',
|
|
99
|
+
'zerodev',
|
|
100
|
+
];
|
|
101
|
+
const useWalletOptions = () => {
|
|
93
102
|
const { walletConnectorOptions, setShowAuthFlow } = useInternalDynamicContext();
|
|
94
103
|
const { walletBook } = useWalletBookContext();
|
|
95
104
|
const { setView } = useViewContext();
|
|
96
105
|
const { navigateToWalletGroup } = useWalletGroupContext();
|
|
97
106
|
const { handleWalletItemClick } = useWalletItemActions();
|
|
107
|
+
const walletOptions = useMemo(() => {
|
|
108
|
+
var _a;
|
|
109
|
+
return (_a = walletConnectorOptions === null || walletConnectorOptions === void 0 ? void 0 : walletConnectorOptions.filter((option) => !embeddedWalletsKeys.includes(option.walletConnector.key)).map((option) => {
|
|
110
|
+
const groupName = option.group
|
|
111
|
+
? getWalletGroup(walletBook, option.group).name
|
|
112
|
+
: undefined;
|
|
113
|
+
return {
|
|
114
|
+
group: option.group,
|
|
115
|
+
groupName,
|
|
116
|
+
key: option.walletConnector.key,
|
|
117
|
+
name: option.name,
|
|
118
|
+
};
|
|
119
|
+
})) !== null && _a !== void 0 ? _a : [];
|
|
120
|
+
}, [walletBook, walletConnectorOptions]);
|
|
98
121
|
const selectWalletOption = (walletKey) => __awaiter(void 0, void 0, void 0, function* () {
|
|
99
122
|
const group = groupWalletOptions(walletBook, walletConnectorOptions);
|
|
100
123
|
const walletOption = group.find((wallet) => wallet.key === walletKey);
|
|
101
|
-
logVerboseTroubleshootingMessage('[
|
|
124
|
+
logVerboseTroubleshootingMessage('[useWalletOptions] selectWalletOption', {
|
|
125
|
+
walletKey,
|
|
126
|
+
walletOption: walletOption === null || walletOption === void 0 ? void 0 : walletOption.key,
|
|
127
|
+
});
|
|
102
128
|
if (!walletOption) {
|
|
103
129
|
throw new DynamicError('Invalid wallet option key provided.');
|
|
104
130
|
}
|
|
@@ -119,7 +145,8 @@ const useSelectWalletOption = () => {
|
|
|
119
145
|
});
|
|
120
146
|
return {
|
|
121
147
|
selectWalletOption,
|
|
148
|
+
walletOptions,
|
|
122
149
|
};
|
|
123
150
|
};
|
|
124
151
|
|
|
125
|
-
export {
|
|
152
|
+
export { useWalletOptions };
|
|
@@ -100,11 +100,18 @@ const MfaVerificationView = ({ type, isInitialSetup = false, showBackButton = fa
|
|
|
100
100
|
const { authDevice } = useMfa.useMfa();
|
|
101
101
|
const [code, setCode] = React.useState('');
|
|
102
102
|
const [error, setError] = React.useState();
|
|
103
|
+
const [isRateLimited, setIsRateLimited] = React.useState(false);
|
|
103
104
|
const { data: isValid, isLoading } = usePromise.usePromise(() => authDevice(code, type, deviceId), {
|
|
104
105
|
deps: [code],
|
|
105
106
|
enabled: (code === null || code === void 0 ? void 0 : code.length) === 6,
|
|
106
|
-
onReject: () => {
|
|
107
|
-
|
|
107
|
+
onReject: (err) => {
|
|
108
|
+
if (err instanceof utils.MfaRateLimitedError) {
|
|
109
|
+
setIsRateLimited(true);
|
|
110
|
+
setError(new utils.DynamicError(t('dyn_mfa.otp_verification_view.rate_limit_error')));
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
setError(new utils.DynamicError(t('dyn_mfa.otp_verification_view.error')));
|
|
114
|
+
}
|
|
108
115
|
},
|
|
109
116
|
onResolve: () => _tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
110
117
|
const user = userActions.getUser();
|
|
@@ -128,7 +135,7 @@ const MfaVerificationView = ({ type, isInitialSetup = false, showBackButton = fa
|
|
|
128
135
|
}
|
|
129
136
|
setView('mfa-secure-device', { isInitialSetup, type });
|
|
130
137
|
};
|
|
131
|
-
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(OTPVerificationView.OTPVerificationView, { MainIcon: passwordHero.ReactComponent, error: error, isLoading: isLoading, onPinComplete: onSubmit, isValid: Boolean(isValid), onPinChange: onCodeChange, description: t('dyn_mfa.otp_verification_view.body'), onClickBack: showBackButton ? onClickBack : undefined }), !isInitialSetup && (jsxRuntime.jsx("div", { className: 'mfa-verification-view__choose-another-method', children: jsxRuntime.jsx(TextButton.TextButton, { className: 'mfa-verification-view__choose-another-method-button', onClick: () => setView('mfa-choose-device', { isInitialSetup }), copykey: 'dyn_mfa.otp_verification_view.choose_another_method', children: t('dyn_mfa.otp_verification_view.choose_another_method') }) }))] }));
|
|
138
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(OTPVerificationView.OTPVerificationView, { MainIcon: passwordHero.ReactComponent, error: error, isLoading: isLoading, onPinComplete: onSubmit, isValid: Boolean(isValid), onPinChange: onCodeChange, description: t('dyn_mfa.otp_verification_view.body'), onClickBack: showBackButton ? onClickBack : undefined, disabled: isRateLimited }), !isInitialSetup && (jsxRuntime.jsx("div", { className: 'mfa-verification-view__choose-another-method', children: jsxRuntime.jsx(TextButton.TextButton, { className: 'mfa-verification-view__choose-another-method-button', onClick: () => setView('mfa-choose-device', { isInitialSetup }), copykey: 'dyn_mfa.otp_verification_view.choose_another_method', children: t('dyn_mfa.otp_verification_view.choose_another_method') }) }))] }));
|
|
132
139
|
};
|
|
133
140
|
|
|
134
141
|
exports.MfaVerificationView = MfaVerificationView;
|
|
@@ -3,7 +3,7 @@ import { __awaiter } from '../../../../_virtual/_tslib.js';
|
|
|
3
3
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
4
4
|
import { useState } from 'react';
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
6
|
-
import { DynamicError } from '@dynamic-labs/utils';
|
|
6
|
+
import { MfaRateLimitedError, DynamicError } from '@dynamic-labs/utils';
|
|
7
7
|
import { MfaBackupCodeAcknowledgement } from '@dynamic-labs/sdk-api-core';
|
|
8
8
|
import '@dynamic-labs/store';
|
|
9
9
|
import '../../utils/constants/colors.js';
|
|
@@ -96,11 +96,18 @@ const MfaVerificationView = ({ type, isInitialSetup = false, showBackButton = fa
|
|
|
96
96
|
const { authDevice } = useMfa();
|
|
97
97
|
const [code, setCode] = useState('');
|
|
98
98
|
const [error, setError] = useState();
|
|
99
|
+
const [isRateLimited, setIsRateLimited] = useState(false);
|
|
99
100
|
const { data: isValid, isLoading } = usePromise(() => authDevice(code, type, deviceId), {
|
|
100
101
|
deps: [code],
|
|
101
102
|
enabled: (code === null || code === void 0 ? void 0 : code.length) === 6,
|
|
102
|
-
onReject: () => {
|
|
103
|
-
|
|
103
|
+
onReject: (err) => {
|
|
104
|
+
if (err instanceof MfaRateLimitedError) {
|
|
105
|
+
setIsRateLimited(true);
|
|
106
|
+
setError(new DynamicError(t('dyn_mfa.otp_verification_view.rate_limit_error')));
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
setError(new DynamicError(t('dyn_mfa.otp_verification_view.error')));
|
|
110
|
+
}
|
|
104
111
|
},
|
|
105
112
|
onResolve: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
106
113
|
const user = getUser();
|
|
@@ -124,7 +131,7 @@ const MfaVerificationView = ({ type, isInitialSetup = false, showBackButton = fa
|
|
|
124
131
|
}
|
|
125
132
|
setView('mfa-secure-device', { isInitialSetup, type });
|
|
126
133
|
};
|
|
127
|
-
return (jsxs(Fragment, { children: [jsx(OTPVerificationView, { MainIcon: SvgPasswordHero, error: error, isLoading: isLoading, onPinComplete: onSubmit, isValid: Boolean(isValid), onPinChange: onCodeChange, description: t('dyn_mfa.otp_verification_view.body'), onClickBack: showBackButton ? onClickBack : undefined }), !isInitialSetup && (jsx("div", { className: 'mfa-verification-view__choose-another-method', children: jsx(TextButton, { className: 'mfa-verification-view__choose-another-method-button', onClick: () => setView('mfa-choose-device', { isInitialSetup }), copykey: 'dyn_mfa.otp_verification_view.choose_another_method', children: t('dyn_mfa.otp_verification_view.choose_another_method') }) }))] }));
|
|
134
|
+
return (jsxs(Fragment, { children: [jsx(OTPVerificationView, { MainIcon: SvgPasswordHero, error: error, isLoading: isLoading, onPinComplete: onSubmit, isValid: Boolean(isValid), onPinChange: onCodeChange, description: t('dyn_mfa.otp_verification_view.body'), onClickBack: showBackButton ? onClickBack : undefined, disabled: isRateLimited }), !isInitialSetup && (jsx("div", { className: 'mfa-verification-view__choose-another-method', children: jsx(TextButton, { className: 'mfa-verification-view__choose-another-method-button', onClick: () => setView('mfa-choose-device', { isInitialSetup }), copykey: 'dyn_mfa.otp_verification_view.choose_another_method', children: t('dyn_mfa.otp_verification_view.choose_another_method') }) }))] }));
|
|
128
135
|
};
|
|
129
136
|
|
|
130
137
|
export { MfaVerificationView };
|
|
@@ -27,6 +27,7 @@ require('../../../../shared/utils/classes/storage/localStorage.cjs');
|
|
|
27
27
|
require('../../../../shared/utils/classes/storage/sessionStorage.cjs');
|
|
28
28
|
var useEffectOnce = require('../../../../shared/utils/hooks/useEffectOnce/useEffectOnce.cjs');
|
|
29
29
|
require('../../../../shared/consts/index.cjs');
|
|
30
|
+
var useInternalDynamicContext = require('../../../../context/DynamicContext/useDynamicContext/useInternalDynamicContext.cjs');
|
|
30
31
|
require('../../../../context/CaptchaContext/CaptchaContext.cjs');
|
|
31
32
|
require('../../../../context/ErrorContext/ErrorContext.cjs');
|
|
32
33
|
require('@dynamic-labs/multi-wallet');
|
|
@@ -101,32 +102,45 @@ require('../../../../components/InlineWidget/InlineWidget.cjs');
|
|
|
101
102
|
require('qrcode');
|
|
102
103
|
|
|
103
104
|
const ManageMfaWidgetView = () => {
|
|
105
|
+
var _a;
|
|
104
106
|
const [userDevices, setUserDevices] = React.useState([]);
|
|
107
|
+
const [mfaMethod, setMfaMethod] = React.useState();
|
|
105
108
|
const [loading, setLoading] = React.useState(false);
|
|
106
109
|
const { setDynamicWidgetView } = DynamicWidgetContext.useWidgetContext();
|
|
107
|
-
const { setShowMfaQRCode } = useDynamicModals.useDynamicModals();
|
|
110
|
+
const { setShowMfaQRCode, setShowOTPVerification } = useDynamicModals.useDynamicModals();
|
|
108
111
|
const { getUserDevices, deleteUserDevice } = useMfa.useMfa();
|
|
109
112
|
const { t } = reactI18next.useTranslation();
|
|
113
|
+
const { projectSettings } = useInternalDynamicContext.useInternalDynamicContext();
|
|
114
|
+
const isMfaRequired = Boolean((_a = projectSettings === null || projectSettings === void 0 ? void 0 : projectSettings.security.mfa) === null || _a === void 0 ? void 0 : _a.required);
|
|
110
115
|
const getDevices = React.useCallback(() => _tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
111
116
|
setLoading(true);
|
|
112
117
|
const devices = yield getUserDevices();
|
|
113
118
|
// set the user devices with the default device first
|
|
114
|
-
setUserDevices(sort.
|
|
119
|
+
setUserDevices(sort.sortDevices(devices));
|
|
115
120
|
setLoading(false);
|
|
116
121
|
}), [getUserDevices]);
|
|
117
122
|
// re-fetch devices when a new device is added
|
|
118
|
-
useDynamicEvents.useDynamicEvents('mfaCompletionSuccess', () =>
|
|
123
|
+
useDynamicEvents.useDynamicEvents('mfaCompletionSuccess', (_b) => _tslib.__awaiter(void 0, [_b], void 0, function* ({ mfaToken }) {
|
|
124
|
+
if (mfaToken) {
|
|
125
|
+
// we now require an MFA token to delete a device which is an async operation
|
|
126
|
+
if ((mfaMethod === null || mfaMethod === void 0 ? void 0 : mfaMethod.action) === 'remove') {
|
|
127
|
+
yield deleteUserDevice(mfaMethod.params.deviceId, mfaToken);
|
|
128
|
+
setMfaMethod(undefined);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
getDevices();
|
|
132
|
+
}));
|
|
119
133
|
// delete device and then re-fetch devices
|
|
120
134
|
const deleteDevice = (id) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
121
|
-
|
|
122
|
-
|
|
135
|
+
setMfaMethod({ action: 'remove', params: { deviceId: id } });
|
|
136
|
+
setShowOTPVerification(true);
|
|
123
137
|
});
|
|
124
138
|
// load devices on initial page load
|
|
125
139
|
useEffectOnce.useEffectOnce(() => {
|
|
126
140
|
getDevices();
|
|
127
141
|
});
|
|
128
142
|
const backButton = (jsxRuntime.jsx(IconButton.IconButton, { type: 'button', onClick: () => setDynamicWidgetView('settings'), "data-testid": 'back-button', children: jsxRuntime.jsx(chevronLeft.ReactComponent, {}) }));
|
|
129
|
-
return (jsxRuntime.jsxs("div", { className: 'manage-mfa-widget-view', children: [jsxRuntime.jsx(ModalHeader.ModalHeader, { leading: backButton, children: jsxRuntime.jsx("div", { className: 'send-balance-page-layout__header-content', children: jsxRuntime.jsx(Typography.Typography, { variant: 'title', color: 'primary', copykey: 'dyn_manage_mfa.title', children: t('dyn_manage_mfa.title') }) }) }), jsxRuntime.jsxs("div", { className: 'manage-mfa-widget-view__scroll-container', children: [loading && jsxRuntime.jsx(MfaDeviceTileSkeleton.MfaDeviceTileSkeleton, {}), !loading && userDevices.length === 0 && (jsxRuntime.jsx(Typography.Typography, { className: 'manage-mfa-widget-view__no-devices', variant: 'body_normal', color: 'secondary', copykey: 'dyn_manage_mfa.no_devices', children: t('dyn_manage_mfa.no_devices') })), userDevices.map((device, index) => (jsxRuntime.jsx(UserDeviceTile.UserDeviceTile, { userDevice: device, index: index, deleteDevice: deleteDevice }, device.id)))] }), userDevices.length > 0 || (jsxRuntime.jsx("div", { className: 'manage-mfa-widget-view__add-mfa-button-container', children: jsxRuntime.jsx(TypographyButton.TypographyButton, { buttonClassName: 'manage-mfa-widget-view__add-mfa-button-container__button', onClick: () => setShowMfaQRCode(true), copykey: 'dyn_manage_mfa.add_mfa_button', startSlot: jsxRuntime.jsx(add.ReactComponent, {}), children: t('dyn_manage_mfa.add_mfa_button') }) }))] }));
|
|
143
|
+
return (jsxRuntime.jsxs("div", { className: 'manage-mfa-widget-view', children: [jsxRuntime.jsx(ModalHeader.ModalHeader, { leading: backButton, children: jsxRuntime.jsx("div", { className: 'send-balance-page-layout__header-content', children: jsxRuntime.jsx(Typography.Typography, { variant: 'title', color: 'primary', copykey: 'dyn_manage_mfa.title', children: t('dyn_manage_mfa.title') }) }) }), jsxRuntime.jsxs("div", { className: 'manage-mfa-widget-view__scroll-container', children: [loading && jsxRuntime.jsx(MfaDeviceTileSkeleton.MfaDeviceTileSkeleton, {}), !loading && userDevices.length === 0 && (jsxRuntime.jsx(Typography.Typography, { className: 'manage-mfa-widget-view__no-devices', variant: 'body_normal', color: 'secondary', copykey: 'dyn_manage_mfa.no_devices', children: t('dyn_manage_mfa.no_devices') })), userDevices.map((device, index) => (jsxRuntime.jsx(UserDeviceTile.UserDeviceTile, { isMfaRequired: isMfaRequired, userDevice: device, index: index, deleteDevice: deleteDevice }, device.id)))] }), userDevices.length > 0 || (jsxRuntime.jsx("div", { className: 'manage-mfa-widget-view__add-mfa-button-container', children: jsxRuntime.jsx(TypographyButton.TypographyButton, { buttonClassName: 'manage-mfa-widget-view__add-mfa-button-container__button', onClick: () => setShowMfaQRCode(true), copykey: 'dyn_manage_mfa.add_mfa_button', startSlot: jsxRuntime.jsx(add.ReactComponent, {}), children: t('dyn_manage_mfa.add_mfa_button') }) }))] }));
|
|
130
144
|
};
|
|
131
145
|
|
|
132
146
|
exports.ManageMfaWidgetView = ManageMfaWidgetView;
|
|
@@ -23,6 +23,7 @@ import '../../../../shared/utils/classes/storage/localStorage.js';
|
|
|
23
23
|
import '../../../../shared/utils/classes/storage/sessionStorage.js';
|
|
24
24
|
import { useEffectOnce } from '../../../../shared/utils/hooks/useEffectOnce/useEffectOnce.js';
|
|
25
25
|
import '../../../../shared/consts/index.js';
|
|
26
|
+
import { useInternalDynamicContext } from '../../../../context/DynamicContext/useDynamicContext/useInternalDynamicContext.js';
|
|
26
27
|
import '../../../../context/CaptchaContext/CaptchaContext.js';
|
|
27
28
|
import '../../../../context/ErrorContext/ErrorContext.js';
|
|
28
29
|
import '@dynamic-labs/multi-wallet';
|
|
@@ -71,7 +72,7 @@ import '../../../../context/PasskeyContext/PasskeyContext.js';
|
|
|
71
72
|
import '../ManagePasskeysWidgetView/PasskeyCard/PasskeyCard.js';
|
|
72
73
|
import { MfaDeviceTileSkeleton } from '../../../../components/MfaDeviceTileSkeleton/MfaDeviceTileSkeleton.js';
|
|
73
74
|
import { UserDeviceTile } from './components/UserDeviceTile.js';
|
|
74
|
-
import {
|
|
75
|
+
import { sortDevices } from './components/utils/sort.js';
|
|
75
76
|
import '../../../../../polyfills.js';
|
|
76
77
|
import '../../../../context/ErrorBoundary/ErrorBoundaryBase.js';
|
|
77
78
|
import '../../../../context/ErrorBoundary/ErrorBoundaryContext.js';
|
|
@@ -97,32 +98,45 @@ import '../../../../components/InlineWidget/InlineWidget.js';
|
|
|
97
98
|
import 'qrcode';
|
|
98
99
|
|
|
99
100
|
const ManageMfaWidgetView = () => {
|
|
101
|
+
var _a;
|
|
100
102
|
const [userDevices, setUserDevices] = useState([]);
|
|
103
|
+
const [mfaMethod, setMfaMethod] = useState();
|
|
101
104
|
const [loading, setLoading] = useState(false);
|
|
102
105
|
const { setDynamicWidgetView } = useWidgetContext();
|
|
103
|
-
const { setShowMfaQRCode } = useDynamicModals();
|
|
106
|
+
const { setShowMfaQRCode, setShowOTPVerification } = useDynamicModals();
|
|
104
107
|
const { getUserDevices, deleteUserDevice } = useMfa();
|
|
105
108
|
const { t } = useTranslation();
|
|
109
|
+
const { projectSettings } = useInternalDynamicContext();
|
|
110
|
+
const isMfaRequired = Boolean((_a = projectSettings === null || projectSettings === void 0 ? void 0 : projectSettings.security.mfa) === null || _a === void 0 ? void 0 : _a.required);
|
|
106
111
|
const getDevices = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
107
112
|
setLoading(true);
|
|
108
113
|
const devices = yield getUserDevices();
|
|
109
114
|
// set the user devices with the default device first
|
|
110
|
-
setUserDevices(
|
|
115
|
+
setUserDevices(sortDevices(devices));
|
|
111
116
|
setLoading(false);
|
|
112
117
|
}), [getUserDevices]);
|
|
113
118
|
// re-fetch devices when a new device is added
|
|
114
|
-
useDynamicEvents('mfaCompletionSuccess', () =>
|
|
119
|
+
useDynamicEvents('mfaCompletionSuccess', (_b) => __awaiter(void 0, [_b], void 0, function* ({ mfaToken }) {
|
|
120
|
+
if (mfaToken) {
|
|
121
|
+
// we now require an MFA token to delete a device which is an async operation
|
|
122
|
+
if ((mfaMethod === null || mfaMethod === void 0 ? void 0 : mfaMethod.action) === 'remove') {
|
|
123
|
+
yield deleteUserDevice(mfaMethod.params.deviceId, mfaToken);
|
|
124
|
+
setMfaMethod(undefined);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
getDevices();
|
|
128
|
+
}));
|
|
115
129
|
// delete device and then re-fetch devices
|
|
116
130
|
const deleteDevice = (id) => __awaiter(void 0, void 0, void 0, function* () {
|
|
117
|
-
|
|
118
|
-
|
|
131
|
+
setMfaMethod({ action: 'remove', params: { deviceId: id } });
|
|
132
|
+
setShowOTPVerification(true);
|
|
119
133
|
});
|
|
120
134
|
// load devices on initial page load
|
|
121
135
|
useEffectOnce(() => {
|
|
122
136
|
getDevices();
|
|
123
137
|
});
|
|
124
138
|
const backButton = (jsx(IconButton, { type: 'button', onClick: () => setDynamicWidgetView('settings'), "data-testid": 'back-button', children: jsx(SvgChevronLeft, {}) }));
|
|
125
|
-
return (jsxs("div", { className: 'manage-mfa-widget-view', children: [jsx(ModalHeader, { leading: backButton, children: jsx("div", { className: 'send-balance-page-layout__header-content', children: jsx(Typography, { variant: 'title', color: 'primary', copykey: 'dyn_manage_mfa.title', children: t('dyn_manage_mfa.title') }) }) }), jsxs("div", { className: 'manage-mfa-widget-view__scroll-container', children: [loading && jsx(MfaDeviceTileSkeleton, {}), !loading && userDevices.length === 0 && (jsx(Typography, { className: 'manage-mfa-widget-view__no-devices', variant: 'body_normal', color: 'secondary', copykey: 'dyn_manage_mfa.no_devices', children: t('dyn_manage_mfa.no_devices') })), userDevices.map((device, index) => (jsx(UserDeviceTile, { userDevice: device, index: index, deleteDevice: deleteDevice }, device.id)))] }), userDevices.length > 0 || (jsx("div", { className: 'manage-mfa-widget-view__add-mfa-button-container', children: jsx(TypographyButton, { buttonClassName: 'manage-mfa-widget-view__add-mfa-button-container__button', onClick: () => setShowMfaQRCode(true), copykey: 'dyn_manage_mfa.add_mfa_button', startSlot: jsx(SvgAdd, {}), children: t('dyn_manage_mfa.add_mfa_button') }) }))] }));
|
|
139
|
+
return (jsxs("div", { className: 'manage-mfa-widget-view', children: [jsx(ModalHeader, { leading: backButton, children: jsx("div", { className: 'send-balance-page-layout__header-content', children: jsx(Typography, { variant: 'title', color: 'primary', copykey: 'dyn_manage_mfa.title', children: t('dyn_manage_mfa.title') }) }) }), jsxs("div", { className: 'manage-mfa-widget-view__scroll-container', children: [loading && jsx(MfaDeviceTileSkeleton, {}), !loading && userDevices.length === 0 && (jsx(Typography, { className: 'manage-mfa-widget-view__no-devices', variant: 'body_normal', color: 'secondary', copykey: 'dyn_manage_mfa.no_devices', children: t('dyn_manage_mfa.no_devices') })), userDevices.map((device, index) => (jsx(UserDeviceTile, { isMfaRequired: isMfaRequired, userDevice: device, index: index, deleteDevice: deleteDevice }, device.id)))] }), userDevices.length > 0 || (jsx("div", { className: 'manage-mfa-widget-view__add-mfa-button-container', children: jsx(TypographyButton, { buttonClassName: 'manage-mfa-widget-view__add-mfa-button-container__button', onClick: () => setShowMfaQRCode(true), copykey: 'dyn_manage_mfa.add_mfa_button', startSlot: jsx(SvgAdd, {}), children: t('dyn_manage_mfa.add_mfa_button') }) }))] }));
|
|
126
140
|
};
|
|
127
141
|
|
|
128
142
|
export { ManageMfaWidgetView };
|
package/src/lib/widgets/DynamicWidget/views/ManageMfaWidgetView/components/UserDeviceTile.cjs
CHANGED
|
@@ -83,7 +83,6 @@ require('../../../../../components/Popper/PopperContext/PopperContext.cjs');
|
|
|
83
83
|
require('../../../../../views/WalletList/WalletList.cjs');
|
|
84
84
|
require('../../../../DynamicBridgeWidget/views/WalletsView/components/SecondaryWallets/SecondaryWallets.cjs');
|
|
85
85
|
require('@hcaptcha/react-hcaptcha');
|
|
86
|
-
var Badge = require('../../../../../components/Badge/Badge.cjs');
|
|
87
86
|
require('../../../../../context/IpConfigurationContext/IpConfigurationContext.cjs');
|
|
88
87
|
require('../../../../../components/PasskeyCreatedSuccessBanner/PasskeyCreatedSuccessBanner.cjs');
|
|
89
88
|
require('../../../../../context/SendBalanceContext/SendBalanceContext.cjs');
|
|
@@ -93,7 +92,7 @@ require('../../../../../context/ReinitializeContext/ReinitializeContextProvider.
|
|
|
93
92
|
require('../../../../../components/InlineWidget/InlineWidget.cjs');
|
|
94
93
|
require('qrcode');
|
|
95
94
|
|
|
96
|
-
const UserDeviceTile = ({ userDevice, deleteDevice, }) => {
|
|
95
|
+
const UserDeviceTile = ({ userDevice, deleteDevice, isMfaRequired, }) => {
|
|
97
96
|
const optionsMenu = [
|
|
98
97
|
{
|
|
99
98
|
Icon: null,
|
|
@@ -102,10 +101,10 @@ const UserDeviceTile = ({ userDevice, deleteDevice, }) => {
|
|
|
102
101
|
},
|
|
103
102
|
];
|
|
104
103
|
const timeSinceCreated = userDevice.verifiedAt && getTimeSince.getTimeSince(new Date(userDevice.verifiedAt));
|
|
105
|
-
return (jsxRuntime.jsxs("div", { className: 'manage-mfa-widget-view__list-tile', children: [jsxRuntime.jsx(authenticator.ReactComponent, { className: 'manage-mfa-widget-view__list-tile__icon' }), jsxRuntime.jsxs("div", { className: 'manage-mfa-widget-view__list-tile__details', children: [jsxRuntime.
|
|
104
|
+
return (jsxRuntime.jsxs("div", { className: 'manage-mfa-widget-view__list-tile', children: [jsxRuntime.jsx(authenticator.ReactComponent, { className: 'manage-mfa-widget-view__list-tile__icon' }), jsxRuntime.jsxs("div", { className: 'manage-mfa-widget-view__list-tile__details', children: [jsxRuntime.jsx("div", { className: 'manage-mfa-widget-view__list-tile__details__title', children: jsxRuntime.jsx(Typography.Typography, { variant: 'body_normal', color: 'primary', children: userDevice.alias || 'Authenticator App' }) }), timeSinceCreated && (jsxRuntime.jsxs(Typography.Typography, { variant: 'body_small', color: 'secondary', children: ["Created ", timeSinceCreated.value, " ", timeSinceCreated.unit, " ago"] }))] }), isMfaRequired || (jsxRuntime.jsx("div", { style: {
|
|
106
105
|
cursor: 'pointer',
|
|
107
106
|
display: 'flex',
|
|
108
|
-
}, children: jsxRuntime.jsx(DotsMenu.DotsMenu, { direction: 'left', "data-testid": 'dots-menu', options: optionsMenu, buttonClassName: 'manage-mfa-widget-view__list-tile__dots-menu', buttonClassNameWithOpenMenu: 'manage-mfa-widget-view__list-tile__dots-menu' }) })] }, userDevice.id));
|
|
107
|
+
}, children: jsxRuntime.jsx(DotsMenu.DotsMenu, { direction: 'left', "data-testid": 'dots-menu', options: optionsMenu, buttonClassName: 'manage-mfa-widget-view__list-tile__dots-menu', buttonClassNameWithOpenMenu: 'manage-mfa-widget-view__list-tile__dots-menu' }) }))] }, userDevice.id));
|
|
109
108
|
};
|
|
110
109
|
|
|
111
110
|
exports.UserDeviceTile = UserDeviceTile;
|
package/src/lib/widgets/DynamicWidget/views/ManageMfaWidgetView/components/UserDeviceTile.d.ts
CHANGED
|
@@ -4,5 +4,6 @@ export type UserDeviceTileProps = {
|
|
|
4
4
|
userDevice: MFADevice;
|
|
5
5
|
index: number;
|
|
6
6
|
deleteDevice: (id: string) => void;
|
|
7
|
+
isMfaRequired: boolean;
|
|
7
8
|
};
|
|
8
|
-
export declare const UserDeviceTile: ({ userDevice, deleteDevice, }: UserDeviceTileProps) => JSX.Element;
|
|
9
|
+
export declare const UserDeviceTile: ({ userDevice, deleteDevice, isMfaRequired, }: UserDeviceTileProps) => JSX.Element;
|
package/src/lib/widgets/DynamicWidget/views/ManageMfaWidgetView/components/UserDeviceTile.js
CHANGED
|
@@ -79,7 +79,6 @@ import '../../../../../components/Popper/PopperContext/PopperContext.js';
|
|
|
79
79
|
import '../../../../../views/WalletList/WalletList.js';
|
|
80
80
|
import '../../../../DynamicBridgeWidget/views/WalletsView/components/SecondaryWallets/SecondaryWallets.js';
|
|
81
81
|
import '@hcaptcha/react-hcaptcha';
|
|
82
|
-
import { Badge } from '../../../../../components/Badge/Badge.js';
|
|
83
82
|
import '../../../../../context/IpConfigurationContext/IpConfigurationContext.js';
|
|
84
83
|
import '../../../../../components/PasskeyCreatedSuccessBanner/PasskeyCreatedSuccessBanner.js';
|
|
85
84
|
import '../../../../../context/SendBalanceContext/SendBalanceContext.js';
|
|
@@ -89,7 +88,7 @@ import '../../../../../context/ReinitializeContext/ReinitializeContextProvider.j
|
|
|
89
88
|
import '../../../../../components/InlineWidget/InlineWidget.js';
|
|
90
89
|
import 'qrcode';
|
|
91
90
|
|
|
92
|
-
const UserDeviceTile = ({ userDevice, deleteDevice, }) => {
|
|
91
|
+
const UserDeviceTile = ({ userDevice, deleteDevice, isMfaRequired, }) => {
|
|
93
92
|
const optionsMenu = [
|
|
94
93
|
{
|
|
95
94
|
Icon: null,
|
|
@@ -98,10 +97,10 @@ const UserDeviceTile = ({ userDevice, deleteDevice, }) => {
|
|
|
98
97
|
},
|
|
99
98
|
];
|
|
100
99
|
const timeSinceCreated = userDevice.verifiedAt && getTimeSince(new Date(userDevice.verifiedAt));
|
|
101
|
-
return (jsxs("div", { className: 'manage-mfa-widget-view__list-tile', children: [jsx(SvgAuthenticator, { className: 'manage-mfa-widget-view__list-tile__icon' }), jsxs("div", { className: 'manage-mfa-widget-view__list-tile__details', children: [
|
|
100
|
+
return (jsxs("div", { className: 'manage-mfa-widget-view__list-tile', children: [jsx(SvgAuthenticator, { className: 'manage-mfa-widget-view__list-tile__icon' }), jsxs("div", { className: 'manage-mfa-widget-view__list-tile__details', children: [jsx("div", { className: 'manage-mfa-widget-view__list-tile__details__title', children: jsx(Typography, { variant: 'body_normal', color: 'primary', children: userDevice.alias || 'Authenticator App' }) }), timeSinceCreated && (jsxs(Typography, { variant: 'body_small', color: 'secondary', children: ["Created ", timeSinceCreated.value, " ", timeSinceCreated.unit, " ago"] }))] }), isMfaRequired || (jsx("div", { style: {
|
|
102
101
|
cursor: 'pointer',
|
|
103
102
|
display: 'flex',
|
|
104
|
-
}, children: jsx(DotsMenu, { direction: 'left', "data-testid": 'dots-menu', options: optionsMenu, buttonClassName: 'manage-mfa-widget-view__list-tile__dots-menu', buttonClassNameWithOpenMenu: 'manage-mfa-widget-view__list-tile__dots-menu' }) })] }, userDevice.id));
|
|
103
|
+
}, children: jsx(DotsMenu, { direction: 'left', "data-testid": 'dots-menu', options: optionsMenu, buttonClassName: 'manage-mfa-widget-view__list-tile__dots-menu', buttonClassNameWithOpenMenu: 'manage-mfa-widget-view__list-tile__dots-menu' }) }))] }, userDevice.id));
|
|
105
104
|
};
|
|
106
105
|
|
|
107
106
|
export { UserDeviceTile };
|
|
@@ -10,14 +10,8 @@ const sortDevicesByVerifiedDateDesc = (a, b) => {
|
|
|
10
10
|
const dateB = b.verifiedAt ? new Date(b.verifiedAt).getTime() : 0;
|
|
11
11
|
return dateA - dateB;
|
|
12
12
|
};
|
|
13
|
-
const
|
|
14
|
-
.sort(sortDevicesByVerifiedDateDesc)
|
|
15
|
-
.map((device, index) => {
|
|
16
|
-
device.alias = device.alias || `Authenticator App ${index + 1}`;
|
|
17
|
-
return device;
|
|
18
|
-
})
|
|
19
|
-
.sort(sortDevicesByDefault);
|
|
13
|
+
const sortDevices = (devices) => devices.sort(sortDevicesByVerifiedDateDesc).sort(sortDevicesByDefault);
|
|
20
14
|
|
|
21
|
-
exports.
|
|
15
|
+
exports.sortDevices = sortDevices;
|
|
22
16
|
exports.sortDevicesByDefault = sortDevicesByDefault;
|
|
23
17
|
exports.sortDevicesByVerifiedDateDesc = sortDevicesByVerifiedDateDesc;
|