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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/package.cjs +1 -1
  3. package/package.js +1 -1
  4. package/package.json +12 -12
  5. package/src/index.d.ts +1 -1
  6. package/src/lib/components/SendBalancePageLayout/components/TokensBalanceDropdown/TokensBalanceDropdown.cjs +31 -11
  7. package/src/lib/components/SendBalancePageLayout/components/TokensBalanceDropdown/TokensBalanceDropdown.js +31 -11
  8. package/src/lib/shared/utils/functions/chain/getChainIcon.cjs +1 -0
  9. package/src/lib/shared/utils/functions/chain/getChainIcon.js +2 -1
  10. package/src/lib/styles/index.shadow.cjs +1 -1
  11. package/src/lib/styles/index.shadow.js +1 -1
  12. package/src/lib/utils/hooks/index.d.ts +1 -1
  13. package/src/lib/utils/hooks/useAuthenticatePasskeyMFA/useAuthenticatePasskeyMFA.d.ts +2 -1
  14. package/src/lib/utils/hooks/useMfa/useMfa.cjs +6 -3
  15. package/src/lib/utils/hooks/useMfa/useMfa.d.ts +5 -3
  16. package/src/lib/utils/hooks/useMfa/useMfa.js +6 -3
  17. package/src/lib/utils/hooks/usePromptMfaAuth/usePromptMfaAuth.cjs +14 -185
  18. package/src/lib/utils/hooks/usePromptMfaAuth/usePromptMfaAuth.d.ts +15 -3
  19. package/src/lib/utils/hooks/usePromptMfaAuth/usePromptMfaAuth.js +14 -185
  20. package/src/lib/utils/hooks/useStepUpAuthentication/index.d.ts +1 -1
  21. package/src/lib/utils/hooks/useStepUpAuthentication/useStepUpAuthentication.cjs +195 -24
  22. package/src/lib/utils/hooks/useStepUpAuthentication/useStepUpAuthentication.d.ts +10 -0
  23. package/src/lib/utils/hooks/useStepUpAuthentication/useStepUpAuthentication.js +189 -18
  24. package/src/lib/views/EmbeddedReveal/EmbeddedRevealView/EmbeddedRevealView.cjs +10 -9
  25. package/src/lib/views/EmbeddedReveal/EmbeddedRevealView/EmbeddedRevealView.js +10 -9
  26. package/src/lib/views/MfaChooseDeviceView/MfaChooseDeviceView.cjs +4 -3
  27. package/src/lib/views/MfaChooseDeviceView/MfaChooseDeviceView.d.ts +2 -0
  28. package/src/lib/views/MfaChooseDeviceView/MfaChooseDeviceView.js +4 -3
  29. package/src/lib/views/MfaVerificationView/MfaVerificationView.cjs +3 -1
  30. package/src/lib/views/MfaVerificationView/MfaVerificationView.d.ts +3 -2
  31. package/src/lib/views/MfaVerificationView/MfaVerificationView.js +3 -1
  32. package/src/lib/views/Passkey/ConfirmPasskeyView/ConfirmPasskeyView.cjs +2 -1
  33. package/src/lib/views/Passkey/ConfirmPasskeyView/ConfirmPasskeyView.d.ts +3 -1
  34. package/src/lib/views/Passkey/ConfirmPasskeyView/ConfirmPasskeyView.js +2 -1
  35. package/src/lib/views/viewToComponentMap.d.ts +3 -2
@@ -5,18 +5,18 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
6
  var _tslib = require('../../../../../_virtual/_tslib.cjs');
7
7
  var React = require('react');
8
- var client = require('@dynamic-labs-sdk/client');
8
+ var client$1 = require('@dynamic-labs-sdk/client');
9
9
  var sdkApiCore = require('@dynamic-labs/sdk-api-core');
10
+ var utils = require('@dynamic-labs/utils');
10
11
  require('@dynamic-labs-sdk/client/core');
11
- require('../../../client/client.cjs');
12
+ var client = require('../../../client/client.cjs');
12
13
  require('../../../config/ApiEndpoint.cjs');
13
14
  require('@dynamic-labs/iconic');
14
15
  require('@dynamic-labs/wallet-connector-core');
15
16
  require('react/jsx-runtime');
16
- require('../../../context/ViewContext/ViewContext.cjs');
17
+ var ViewContext = require('../../../context/ViewContext/ViewContext.cjs');
17
18
  var logger = require('../../../shared/logger.cjs');
18
19
  require('@dynamic-labs/wallet-book');
19
- require('@dynamic-labs/utils');
20
20
  require('../../constants/colors.cjs');
21
21
  require('../../constants/values.cjs');
22
22
  require('../../../shared/consts/index.cjs');
@@ -28,18 +28,95 @@ var dynamicContextProps = require('../../../store/state/dynamicContextProps/dyna
28
28
  require('../../../store/state/primaryWalletId/primaryWalletId.cjs');
29
29
  require('../../../store/state/connectedWalletsInfo/connectedWalletsInfo.cjs');
30
30
  require('../../functions/getWaasAddressTypeLabel/getWaasAddressTypeLabel.cjs');
31
- require('../../../events/dynamicEvents.cjs');
31
+ var dynamicEvents = require('../../../events/dynamicEvents.cjs');
32
32
  var useUser = require('../../../client/extension/user/useUser/useUser.cjs');
33
33
  var hasElevatedAccessToken = require('../../../client/extension/functions/hasElevatedAccessToken/hasElevatedAccessToken.cjs');
34
+ require('../../../context/DynamicContext/DynamicContext.cjs');
35
+ require('../../../store/state/loadingAndLifecycle/loadingAndLifecycle.cjs');
34
36
  var useConnectAndSign = require('../authenticationHooks/useConnectAndSign/useConnectAndSign.cjs');
37
+ require('../../../context/ErrorContext/ErrorContext.cjs');
38
+ require('../../../context/AccessDeniedContext/AccessDeniedContext.cjs');
39
+ require('../../../context/AccountExistsContext/AccountExistsContext.cjs');
35
40
  var UserWalletsContext = require('../../../context/UserWalletsContext/UserWalletsContext.cjs');
41
+ require('../../../store/state/authMode/authMode.cjs');
42
+ require('../../../context/CaptchaContext/CaptchaContext.cjs');
43
+ require('../../../context/VerificationContext/VerificationContext.cjs');
44
+ require('react-dom');
45
+ require('../../functions/compareChains/compareChains.cjs');
46
+ require('../../../views/Passkey/utils/findPrimaryEmbeddedChain/findPrimaryEmbeddedChain.cjs');
47
+ require('../../../context/ThemeContext/ThemeContext.cjs');
48
+ require('../useUserUpdateRequest/useUpdateUser/userFieldsSchema.cjs');
49
+ require('bs58');
50
+ require('@dynamic-labs/types');
51
+ require('../../../context/SocialRedirectContext/SocialRedirectContext.cjs');
52
+ require('../../../context/LoadingContext/LoadingContext.cjs');
53
+ require('../../../context/WalletContext/WalletContext.cjs');
54
+ require('../useEmbeddedWallet/useSecureEnclaveEmbeddedWallet/constants.cjs');
55
+ require('yup');
56
+ require('../../../context/MockContext/MockContext.cjs');
57
+ require('../../../views/CollectUserDataView/useFields.cjs');
58
+ require('../../../context/FieldsStateContext/FieldsStateContext.cjs');
59
+ require('../../../context/UserFieldEditorContext/UserFieldEditorContext.cjs');
60
+ require('@dynamic-labs/rpc-providers');
61
+ require('../../../store/state/walletOptions/walletOptions.cjs');
62
+ require('react-i18next');
63
+ require('../../../components/Accordion/components/AccordionItem/AccordionItem.cjs');
64
+ require('../../../components/Alert/Alert.cjs');
65
+ require('../../../components/ShadowDOM/ShadowDOM.cjs');
66
+ require('../../../components/IconButton/IconButton.cjs');
67
+ require('../../../components/InlineWidget/InlineWidget.cjs');
68
+ require('../../../components/Input/Input.cjs');
69
+ require('../../../components/IsBrowser/IsBrowser.cjs');
70
+ require('../../../components/MenuList/Dropdown/Dropdown.cjs');
71
+ require('../../../components/OverlayCard/OverlayCard.cjs');
72
+ require('../../../components/Transition/ZoomTransition/ZoomTransition.cjs');
73
+ require('../../../components/Transition/SlideInUpTransition/SlideInUpTransition.cjs');
74
+ require('../../../components/Transition/OpacityTransition/OpacityTransition.cjs');
75
+ require('../../../components/PasskeyCreatedSuccessBanner/PasskeyCreatedSuccessBanner.cjs');
76
+ require('../../../components/Popper/Popper/Popper.cjs');
77
+ require('../../../components/Popper/PopperContext/PopperContext.cjs');
78
+ require('react-focus-lock');
79
+ require('qrcode');
80
+ require('formik');
81
+ require('../useSubdomainCheck/useSubdomainCheck.cjs');
82
+ require('../../../context/WalletGroupContext/WalletGroupContext.cjs');
83
+ require('../../../widgets/DynamicWidget/context/DynamicWidgetContext.cjs');
84
+ require('../useWalletBackup/useWalletBackup.cjs');
85
+ require('../useWalletBackup/types.cjs');
86
+ require('../useWalletBackup/cloudProviders.cjs');
87
+ require('../../../context/IpConfigurationContext/IpConfigurationContext.cjs');
88
+ require('../../../context/ConnectWithOtpContext/ConnectWithOtpContext.cjs');
89
+ require('../../../widgets/DynamicBridgeWidget/views/WalletsView/components/SecondaryWallets/SecondaryWallets.cjs');
90
+ require('@hcaptcha/react-hcaptcha');
91
+ require('../../../widgets/DynamicWidget/helpers/convertExchangeKeyAndProviderEnum.cjs');
92
+ require('../../../views/ExchangeWhitelistWarning/ExchangeWhitelistWarning.cjs');
93
+ require('../../../context/ErrorContext/hooks/useErrorText/useErrorText.cjs');
94
+ require('../../../context/FooterAnimationContext/index.cjs');
95
+ require('../../../views/MfaChooseDeviceView/useGetMfaOptions/useGetMfaOptions.cjs');
96
+ require('../../../context/PasskeyContext/PasskeyContext.cjs');
97
+ require('../../../context/OnrampContext/OnrampContext.cjs');
98
+ require('../../../store/state/sendBalances.cjs');
99
+ require('../../../store/state/connectorsInitializing/connectorsInitializing.cjs');
100
+ require('../../../components/OverlayCardBase/OverlayCardTarget/OverlayCardTarget.cjs');
101
+ require('../../../widgets/DynamicWidget/components/DynamicWidgetHeader/DynamicWidgetHeader.cjs');
102
+ require('../../../views/TransactionConfirmationView/TransactionConfirmationView.cjs');
103
+ require('../../../widgets/DynamicWidget/components/PasskeyCard/PasskeyCard.cjs');
104
+ require('../../../widgets/DynamicWidget/views/CryptoComOnramp/CryptoComOnramp.cjs');
105
+ require('../../../../index.cjs');
106
+ require('../../../widgets/DynamicWidget/views/ReceiveWalletFunds/ReceiveWalletFunds.cjs');
107
+ require('../../../store/state/tokenBalances.cjs');
108
+ require('../../../store/state/multichainBalances.cjs');
109
+ var useGetUserMfaMethods = require('../useGetUserMfaMethods/useGetUserMfaMethods.cjs');
110
+ var useAuthenticatePasskeyMFA = require('../useAuthenticatePasskeyMFA/useAuthenticatePasskeyMFA.cjs');
111
+ require('../../../shared/utils/functions/getInitialUrl/getInitialUrl.cjs');
112
+ var useInternalDynamicContext = require('../../../context/DynamicContext/useDynamicContext/useInternalDynamicContext/useInternalDynamicContext.cjs');
36
113
 
37
114
  const INITIAL_STATE = {
38
115
  error: null,
39
116
  isLoading: false,
40
117
  otpVerification: null,
41
118
  };
42
- const isCountryCode = (value) => value !== undefined && value in client.supportedCountries;
119
+ const isCountryCode = (value) => value !== undefined && value in client$1.supportedCountries;
43
120
  const isOtpCapableCredential = (cred) => cred.format === sdkApiCore.JwtVerifiedCredentialFormatEnum.Email ||
44
121
  cred.format === sdkApiCore.JwtVerifiedCredentialFormatEnum.PhoneNumber;
45
122
  const resolveTargetCredential = (credentials, credentialId) => {
@@ -53,19 +130,19 @@ const sendEmailOtp = (credential) => _tslib.__awaiter(void 0, void 0, void 0, fu
53
130
  if (!credential.email) {
54
131
  throw new Error('Email credential is missing email address');
55
132
  }
56
- return client.sendEmailOTP({ email: credential.email });
133
+ return client$1.sendEmailOTP({ email: credential.email });
57
134
  });
58
135
  const sendSmsOtp = (credential) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
59
136
  var _a;
60
137
  const normalizedPhoneCountryCode = (_a = credential.phoneCountryCode) === null || _a === void 0 ? void 0 : _a.replace(/^\+/, '');
61
- const matchedCountryCode = Object.keys(client.supportedCountries).find((key) => client.supportedCountries[key].code === normalizedPhoneCountryCode);
138
+ const matchedCountryCode = Object.keys(client$1.supportedCountries).find((key) => client$1.supportedCountries[key].code === normalizedPhoneCountryCode);
62
139
  const isoCountryCode = isCountryCode(credential.isoCountryCode)
63
140
  ? credential.isoCountryCode
64
141
  : matchedCountryCode;
65
142
  if (!credential.phoneNumber || !isoCountryCode) {
66
143
  throw new Error('SMS credential is missing phone number or country code');
67
144
  }
68
- return client.sendSmsOTP({ isoCountryCode, phoneNumber: credential.phoneNumber });
145
+ return client$1.sendSmsOTP({ isoCountryCode, phoneNumber: credential.phoneNumber });
69
146
  });
70
147
  const dispatchOtp = (credential) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
71
148
  return credential.format === sdkApiCore.JwtVerifiedCredentialFormatEnum.Email
@@ -110,6 +187,11 @@ const useStepUpAuthentication = ({ credentialId, } = {}) => {
110
187
  const [state, setState] = React.useState(INITIAL_STATE);
111
188
  const connectAndSign = useConnectAndSign.useConnectAndSign();
112
189
  const { userWallets } = UserWalletsContext.useInternalUserWallets();
190
+ const { setShowAuthFlow } = useInternalDynamicContext.useInternalDynamicContext();
191
+ const { pushView } = ViewContext.useViewContext();
192
+ const getUserMfaMethods = useGetUserMfaMethods.useGetUserMfaMethods();
193
+ const authenticatePasskeyMFA = useAuthenticatePasskeyMFA.useAuthenticatePasskeyMFA();
194
+ const dynamicClient = client.useDynamicClient();
113
195
  // Ref keeps the latest otpVerification available inside the verifyOtp
114
196
  // callback without creating a stale closure over state.
115
197
  const otpVerificationRef = React.useRef(null);
@@ -169,7 +251,7 @@ const useStepUpAuthentication = ({ credentialId, } = {}) => {
169
251
  }
170
252
  setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, isLoading: true })));
171
253
  try {
172
- const response = yield client.verifyOTP({
254
+ const response = yield client$1.verifyOTP({
173
255
  otpVerification,
174
256
  requestedScopes,
175
257
  verificationToken,
@@ -213,19 +295,11 @@ const useStepUpAuthentication = ({ credentialId, } = {}) => {
213
295
  userId: user === null || user === void 0 ? void 0 : user.id,
214
296
  });
215
297
  }
216
- }), [
217
- connectAndSign,
218
- credentialId,
219
- environmentId,
220
- setError,
221
- user === null || user === void 0 ? void 0 : user.id,
222
- userWallets,
223
- ]);
298
+ }), [connectAndSign, credentialId, environmentId, setError, user, userWallets]);
224
299
  const verifyPasskeyMfa = React.useCallback((_c) => _tslib.__awaiter(void 0, [_c], void 0, function* ({ requestedScopes, }) {
225
300
  setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, isLoading: true })));
226
301
  try {
227
- // requestedScopes is available in @dynamic-labs-sdk/client >= 0.14.0
228
- const response = yield client.authenticatePasskeyMFA({
302
+ const response = yield client$1.authenticatePasskeyMFA({
229
303
  requestedScopes,
230
304
  });
231
305
  setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, isLoading: false })));
@@ -239,12 +313,11 @@ const useStepUpAuthentication = ({ credentialId, } = {}) => {
239
313
  logger.logger.error('Failed to authenticate passkey for step-up authentication', { environmentId, error, userId: user === null || user === void 0 ? void 0 : user.id });
240
314
  return null;
241
315
  }
242
- }), [environmentId, user === null || user === void 0 ? void 0 : user.id]);
316
+ }), [environmentId, user]);
243
317
  const verifyTotpMfa = React.useCallback((_d) => _tslib.__awaiter(void 0, [_d], void 0, function* ({ code, deviceId, requestedScopes, }) {
244
318
  setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, isLoading: true })));
245
319
  try {
246
- // requestedScopes is available in @dynamic-labs-sdk/client >= 0.14.0
247
- const response = yield client.authenticateTotpMfaDevice({
320
+ const response = yield client$1.authenticateTotpMfaDevice({
248
321
  code,
249
322
  deviceId,
250
323
  requestedScopes,
@@ -260,14 +333,112 @@ const useStepUpAuthentication = ({ credentialId, } = {}) => {
260
333
  logger.logger.error('Failed to authenticate TOTP device for step-up authentication', { environmentId, error, userId: user === null || user === void 0 ? void 0 : user.id });
261
334
  return null;
262
335
  }
263
- }), [environmentId, user === null || user === void 0 ? void 0 : user.id]);
336
+ }), [environmentId, user]);
337
+ const verifyRecoveryCode = React.useCallback((_e) => _tslib.__awaiter(void 0, [_e], void 0, function* ({ code, requestedScopes, }) {
338
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, isLoading: true })));
339
+ try {
340
+ const response = yield client$1.authenticateMfaRecoveryCode({
341
+ code,
342
+ requestedScopes,
343
+ });
344
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, isLoading: false })));
345
+ return response;
346
+ }
347
+ catch (error) {
348
+ const errorMessage = error instanceof Error
349
+ ? error.message
350
+ : 'Failed to authenticate recovery code for step-up authentication';
351
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: errorMessage, isLoading: false })));
352
+ logger.logger.error('Failed to authenticate recovery code for step-up authentication', { environmentId, error, userId: user === null || user === void 0 ? void 0 : user.id });
353
+ return null;
354
+ }
355
+ }), [environmentId, user]);
356
+ const promptMfa = React.useCallback((props) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
357
+ var _f;
358
+ const methods = yield getUserMfaMethods();
359
+ const allMethods = [
360
+ ...methods.passkeys.map((passkey) => (Object.assign(Object.assign({}, passkey), { type: sdkApiCore.MFADeviceType.Passkey }))),
361
+ ...methods.devices.map((device) => (Object.assign(Object.assign({}, device), { type: sdkApiCore.MFADeviceType.Totp }))),
362
+ ];
363
+ if (!methods.userHasVerifiedMfaMethods || allMethods.length === 0) {
364
+ setShowAuthFlow(true);
365
+ pushView('mfa-choose-device', {
366
+ createMfaToken: props === null || props === void 0 ? void 0 : props.createMfaToken,
367
+ requestedScopes: props === null || props === void 0 ? void 0 : props.requestedScopes,
368
+ });
369
+ return;
370
+ }
371
+ const lastCreatedMethod = allMethods.reduce((a, b) => {
372
+ if (!a)
373
+ return b;
374
+ if (!b)
375
+ return a;
376
+ if (a.createdAt && b.createdAt) {
377
+ return a.createdAt >= b.createdAt ? a : b;
378
+ }
379
+ if (b.createdAt) {
380
+ return b;
381
+ }
382
+ return a;
383
+ }, allMethods[0]);
384
+ switch (lastCreatedMethod.type) {
385
+ case sdkApiCore.MFADeviceType.Passkey: {
386
+ const createMfaTokenOptions = (props === null || props === void 0 ? void 0 : props.createMfaToken)
387
+ ? { singleUse: true }
388
+ : undefined;
389
+ const authenticatePasskeyPromise = authenticatePasskeyMFA({
390
+ createMfaToken: createMfaTokenOptions,
391
+ requestedScopes: props === null || props === void 0 ? void 0 : props.requestedScopes,
392
+ });
393
+ setShowAuthFlow(true);
394
+ pushView('passkey-confirm', {
395
+ authenticatePasskeyPromise,
396
+ createMfaToken: props === null || props === void 0 ? void 0 : props.createMfaToken,
397
+ requestedScopes: props === null || props === void 0 ? void 0 : props.requestedScopes,
398
+ });
399
+ return authenticatePasskeyPromise;
400
+ }
401
+ case sdkApiCore.MFADeviceType.Totp: {
402
+ if ((dynamicClient === null || dynamicClient === void 0 ? void 0 : dynamicClient.mfaToken) && !((_f = props === null || props === void 0 ? void 0 : props.requestedScopes) === null || _f === void 0 ? void 0 : _f.length)) {
403
+ return dynamicClient === null || dynamicClient === void 0 ? void 0 : dynamicClient.mfaToken;
404
+ }
405
+ const deferred = new utils.DeferredPromise();
406
+ setShowAuthFlow(true);
407
+ pushView('mfa-verification', {
408
+ createMfaToken: props === null || props === void 0 ? void 0 : props.createMfaToken,
409
+ requestedScopes: props === null || props === void 0 ? void 0 : props.requestedScopes,
410
+ });
411
+ const mfaCompletionSuccessOff = client$1.onEvent({
412
+ event: 'mfaCompletionSuccess',
413
+ listener: ({ mfaToken }) => deferred.resolve(mfaToken),
414
+ }, dynamicClient);
415
+ const onAuthFlowCloseHandler = () => deferred.reject(new Error('MFA view closed'));
416
+ dynamicEvents.dynamicEvents.on('authFlowClose', onAuthFlowCloseHandler);
417
+ deferred.promise.finally(() => {
418
+ mfaCompletionSuccessOff();
419
+ dynamicEvents.dynamicEvents.off('authFlowClose', onAuthFlowCloseHandler);
420
+ });
421
+ return deferred.promise;
422
+ }
423
+ default:
424
+ throw new Error('Error determining MFA method to use');
425
+ }
426
+ }), [
427
+ authenticatePasskeyMFA,
428
+ dynamicClient,
429
+ getUserMfaMethods,
430
+ pushView,
431
+ setShowAuthFlow,
432
+ ]);
264
433
  return {
265
434
  isStepUpRequired,
435
+ promptMfa,
266
436
  resetState,
267
437
  sendOtp,
268
438
  state,
269
439
  verifyOtp,
270
440
  verifyPasskeyMfa,
441
+ verifyRecoveryCode,
271
442
  verifyTotpMfa,
272
443
  verifyWallet,
273
444
  };
@@ -20,6 +20,10 @@ export type VerifyTotpMfaParams = {
20
20
  deviceId?: string;
21
21
  requestedScopes?: TokenScope[];
22
22
  };
23
+ export type VerifyRecoveryCodeParams = {
24
+ code: string;
25
+ requestedScopes?: TokenScope[];
26
+ };
23
27
  export type IsStepUpRequiredParams = {
24
28
  scope: TokenScope;
25
29
  };
@@ -28,14 +32,20 @@ export type UseStepUpAuthenticationParams = {
28
32
  };
29
33
  export type UseStepUpAuthenticationReturn = {
30
34
  isStepUpRequired: (params: IsStepUpRequiredParams) => boolean;
35
+ promptMfa: (props?: PromptMfaParams) => Promise<string | undefined>;
31
36
  resetState: () => void;
32
37
  sendOtp: () => Promise<OTPVerification | null>;
33
38
  state: StepUpAuthenticationState;
34
39
  verifyOtp: (params: VerifyOtpParams) => Promise<VerifyResponse | null>;
35
40
  verifyPasskeyMfa: (params: VerifyPasskeyMfaParams) => Promise<VerifyResponse | null>;
41
+ verifyRecoveryCode: (params: VerifyRecoveryCodeParams) => Promise<VerifyResponse | null>;
36
42
  verifyTotpMfa: (params: VerifyTotpMfaParams) => Promise<VerifyResponse | null>;
37
43
  verifyWallet: (params: VerifyWalletParams) => Promise<void>;
38
44
  };
45
+ export type PromptMfaParams = {
46
+ createMfaToken?: boolean;
47
+ requestedScopes?: TokenScope[];
48
+ };
39
49
  /**
40
50
  * Perform step-up authentication for an already-authenticated user.
41
51
  *
@@ -1,18 +1,18 @@
1
1
  'use client'
2
2
  import { __awaiter } from '../../../../../_virtual/_tslib.js';
3
3
  import { useState, useRef, useCallback } from 'react';
4
- import { verifyOTP, authenticatePasskeyMFA, authenticateTotpMfaDevice, sendEmailOTP, supportedCountries, sendSmsOTP } from '@dynamic-labs-sdk/client';
5
- import { JwtVerifiedCredentialFormatEnum } from '@dynamic-labs/sdk-api-core';
4
+ import { verifyOTP, authenticatePasskeyMFA, authenticateTotpMfaDevice, authenticateMfaRecoveryCode, onEvent, sendEmailOTP, supportedCountries, sendSmsOTP } from '@dynamic-labs-sdk/client';
5
+ import { MFADeviceType, JwtVerifiedCredentialFormatEnum } from '@dynamic-labs/sdk-api-core';
6
+ import { DeferredPromise } from '@dynamic-labs/utils';
6
7
  import '@dynamic-labs-sdk/client/core';
7
- import '../../../client/client.js';
8
+ import { useDynamicClient } from '../../../client/client.js';
8
9
  import '../../../config/ApiEndpoint.js';
9
10
  import '@dynamic-labs/iconic';
10
11
  import '@dynamic-labs/wallet-connector-core';
11
12
  import 'react/jsx-runtime';
12
- import '../../../context/ViewContext/ViewContext.js';
13
+ import { useViewContext } from '../../../context/ViewContext/ViewContext.js';
13
14
  import { logger } from '../../../shared/logger.js';
14
15
  import '@dynamic-labs/wallet-book';
15
- import '@dynamic-labs/utils';
16
16
  import '../../constants/colors.js';
17
17
  import '../../constants/values.js';
18
18
  import '../../../shared/consts/index.js';
@@ -24,11 +24,88 @@ import { useEnvironmentId } from '../../../store/state/dynamicContextProps/dynam
24
24
  import '../../../store/state/primaryWalletId/primaryWalletId.js';
25
25
  import '../../../store/state/connectedWalletsInfo/connectedWalletsInfo.js';
26
26
  import '../../functions/getWaasAddressTypeLabel/getWaasAddressTypeLabel.js';
27
- import '../../../events/dynamicEvents.js';
27
+ import { dynamicEvents } from '../../../events/dynamicEvents.js';
28
28
  import { useUser } from '../../../client/extension/user/useUser/useUser.js';
29
29
  import { hasElevatedAccessToken } from '../../../client/extension/functions/hasElevatedAccessToken/hasElevatedAccessToken.js';
30
+ import '../../../context/DynamicContext/DynamicContext.js';
31
+ import '../../../store/state/loadingAndLifecycle/loadingAndLifecycle.js';
30
32
  import { useConnectAndSign } from '../authenticationHooks/useConnectAndSign/useConnectAndSign.js';
33
+ import '../../../context/ErrorContext/ErrorContext.js';
34
+ import '../../../context/AccessDeniedContext/AccessDeniedContext.js';
35
+ import '../../../context/AccountExistsContext/AccountExistsContext.js';
31
36
  import { useInternalUserWallets } from '../../../context/UserWalletsContext/UserWalletsContext.js';
37
+ import '../../../store/state/authMode/authMode.js';
38
+ import '../../../context/CaptchaContext/CaptchaContext.js';
39
+ import '../../../context/VerificationContext/VerificationContext.js';
40
+ import 'react-dom';
41
+ import '../../functions/compareChains/compareChains.js';
42
+ import '../../../views/Passkey/utils/findPrimaryEmbeddedChain/findPrimaryEmbeddedChain.js';
43
+ import '../../../context/ThemeContext/ThemeContext.js';
44
+ import '../useUserUpdateRequest/useUpdateUser/userFieldsSchema.js';
45
+ import 'bs58';
46
+ import '@dynamic-labs/types';
47
+ import '../../../context/SocialRedirectContext/SocialRedirectContext.js';
48
+ import '../../../context/LoadingContext/LoadingContext.js';
49
+ import '../../../context/WalletContext/WalletContext.js';
50
+ import '../useEmbeddedWallet/useSecureEnclaveEmbeddedWallet/constants.js';
51
+ import 'yup';
52
+ import '../../../context/MockContext/MockContext.js';
53
+ import '../../../views/CollectUserDataView/useFields.js';
54
+ import '../../../context/FieldsStateContext/FieldsStateContext.js';
55
+ import '../../../context/UserFieldEditorContext/UserFieldEditorContext.js';
56
+ import '@dynamic-labs/rpc-providers';
57
+ import '../../../store/state/walletOptions/walletOptions.js';
58
+ import 'react-i18next';
59
+ import '../../../components/Accordion/components/AccordionItem/AccordionItem.js';
60
+ import '../../../components/Alert/Alert.js';
61
+ import '../../../components/ShadowDOM/ShadowDOM.js';
62
+ import '../../../components/IconButton/IconButton.js';
63
+ import '../../../components/InlineWidget/InlineWidget.js';
64
+ import '../../../components/Input/Input.js';
65
+ import '../../../components/IsBrowser/IsBrowser.js';
66
+ import '../../../components/MenuList/Dropdown/Dropdown.js';
67
+ import '../../../components/OverlayCard/OverlayCard.js';
68
+ import '../../../components/Transition/ZoomTransition/ZoomTransition.js';
69
+ import '../../../components/Transition/SlideInUpTransition/SlideInUpTransition.js';
70
+ import '../../../components/Transition/OpacityTransition/OpacityTransition.js';
71
+ import '../../../components/PasskeyCreatedSuccessBanner/PasskeyCreatedSuccessBanner.js';
72
+ import '../../../components/Popper/Popper/Popper.js';
73
+ import '../../../components/Popper/PopperContext/PopperContext.js';
74
+ import 'react-focus-lock';
75
+ import 'qrcode';
76
+ import 'formik';
77
+ import '../useSubdomainCheck/useSubdomainCheck.js';
78
+ import '../../../context/WalletGroupContext/WalletGroupContext.js';
79
+ import '../../../widgets/DynamicWidget/context/DynamicWidgetContext.js';
80
+ import '../useWalletBackup/useWalletBackup.js';
81
+ import '../useWalletBackup/types.js';
82
+ import '../useWalletBackup/cloudProviders.js';
83
+ import '../../../context/IpConfigurationContext/IpConfigurationContext.js';
84
+ import '../../../context/ConnectWithOtpContext/ConnectWithOtpContext.js';
85
+ import '../../../widgets/DynamicBridgeWidget/views/WalletsView/components/SecondaryWallets/SecondaryWallets.js';
86
+ import '@hcaptcha/react-hcaptcha';
87
+ import '../../../widgets/DynamicWidget/helpers/convertExchangeKeyAndProviderEnum.js';
88
+ import '../../../views/ExchangeWhitelistWarning/ExchangeWhitelistWarning.js';
89
+ import '../../../context/ErrorContext/hooks/useErrorText/useErrorText.js';
90
+ import '../../../context/FooterAnimationContext/index.js';
91
+ import '../../../views/MfaChooseDeviceView/useGetMfaOptions/useGetMfaOptions.js';
92
+ import '../../../context/PasskeyContext/PasskeyContext.js';
93
+ import '../../../context/OnrampContext/OnrampContext.js';
94
+ import '../../../store/state/sendBalances.js';
95
+ import '../../../store/state/connectorsInitializing/connectorsInitializing.js';
96
+ import '../../../components/OverlayCardBase/OverlayCardTarget/OverlayCardTarget.js';
97
+ import '../../../widgets/DynamicWidget/components/DynamicWidgetHeader/DynamicWidgetHeader.js';
98
+ import '../../../views/TransactionConfirmationView/TransactionConfirmationView.js';
99
+ import '../../../widgets/DynamicWidget/components/PasskeyCard/PasskeyCard.js';
100
+ import '../../../widgets/DynamicWidget/views/CryptoComOnramp/CryptoComOnramp.js';
101
+ import '../../../../index.js';
102
+ import '../../../widgets/DynamicWidget/views/ReceiveWalletFunds/ReceiveWalletFunds.js';
103
+ import '../../../store/state/tokenBalances.js';
104
+ import '../../../store/state/multichainBalances.js';
105
+ import { useGetUserMfaMethods } from '../useGetUserMfaMethods/useGetUserMfaMethods.js';
106
+ import { useAuthenticatePasskeyMFA } from '../useAuthenticatePasskeyMFA/useAuthenticatePasskeyMFA.js';
107
+ import '../../../shared/utils/functions/getInitialUrl/getInitialUrl.js';
108
+ import { useInternalDynamicContext } from '../../../context/DynamicContext/useDynamicContext/useInternalDynamicContext/useInternalDynamicContext.js';
32
109
 
33
110
  const INITIAL_STATE = {
34
111
  error: null,
@@ -106,6 +183,11 @@ const useStepUpAuthentication = ({ credentialId, } = {}) => {
106
183
  const [state, setState] = useState(INITIAL_STATE);
107
184
  const connectAndSign = useConnectAndSign();
108
185
  const { userWallets } = useInternalUserWallets();
186
+ const { setShowAuthFlow } = useInternalDynamicContext();
187
+ const { pushView } = useViewContext();
188
+ const getUserMfaMethods = useGetUserMfaMethods();
189
+ const authenticatePasskeyMFA$1 = useAuthenticatePasskeyMFA();
190
+ const dynamicClient = useDynamicClient();
109
191
  // Ref keeps the latest otpVerification available inside the verifyOtp
110
192
  // callback without creating a stale closure over state.
111
193
  const otpVerificationRef = useRef(null);
@@ -209,18 +291,10 @@ const useStepUpAuthentication = ({ credentialId, } = {}) => {
209
291
  userId: user === null || user === void 0 ? void 0 : user.id,
210
292
  });
211
293
  }
212
- }), [
213
- connectAndSign,
214
- credentialId,
215
- environmentId,
216
- setError,
217
- user === null || user === void 0 ? void 0 : user.id,
218
- userWallets,
219
- ]);
294
+ }), [connectAndSign, credentialId, environmentId, setError, user, userWallets]);
220
295
  const verifyPasskeyMfa = useCallback((_c) => __awaiter(void 0, [_c], void 0, function* ({ requestedScopes, }) {
221
296
  setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, isLoading: true })));
222
297
  try {
223
- // requestedScopes is available in @dynamic-labs-sdk/client >= 0.14.0
224
298
  const response = yield authenticatePasskeyMFA({
225
299
  requestedScopes,
226
300
  });
@@ -235,11 +309,10 @@ const useStepUpAuthentication = ({ credentialId, } = {}) => {
235
309
  logger.error('Failed to authenticate passkey for step-up authentication', { environmentId, error, userId: user === null || user === void 0 ? void 0 : user.id });
236
310
  return null;
237
311
  }
238
- }), [environmentId, user === null || user === void 0 ? void 0 : user.id]);
312
+ }), [environmentId, user]);
239
313
  const verifyTotpMfa = useCallback((_d) => __awaiter(void 0, [_d], void 0, function* ({ code, deviceId, requestedScopes, }) {
240
314
  setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, isLoading: true })));
241
315
  try {
242
- // requestedScopes is available in @dynamic-labs-sdk/client >= 0.14.0
243
316
  const response = yield authenticateTotpMfaDevice({
244
317
  code,
245
318
  deviceId,
@@ -256,14 +329,112 @@ const useStepUpAuthentication = ({ credentialId, } = {}) => {
256
329
  logger.error('Failed to authenticate TOTP device for step-up authentication', { environmentId, error, userId: user === null || user === void 0 ? void 0 : user.id });
257
330
  return null;
258
331
  }
259
- }), [environmentId, user === null || user === void 0 ? void 0 : user.id]);
332
+ }), [environmentId, user]);
333
+ const verifyRecoveryCode = useCallback((_e) => __awaiter(void 0, [_e], void 0, function* ({ code, requestedScopes, }) {
334
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, isLoading: true })));
335
+ try {
336
+ const response = yield authenticateMfaRecoveryCode({
337
+ code,
338
+ requestedScopes,
339
+ });
340
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, isLoading: false })));
341
+ return response;
342
+ }
343
+ catch (error) {
344
+ const errorMessage = error instanceof Error
345
+ ? error.message
346
+ : 'Failed to authenticate recovery code for step-up authentication';
347
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: errorMessage, isLoading: false })));
348
+ logger.error('Failed to authenticate recovery code for step-up authentication', { environmentId, error, userId: user === null || user === void 0 ? void 0 : user.id });
349
+ return null;
350
+ }
351
+ }), [environmentId, user]);
352
+ const promptMfa = useCallback((props) => __awaiter(void 0, void 0, void 0, function* () {
353
+ var _f;
354
+ const methods = yield getUserMfaMethods();
355
+ const allMethods = [
356
+ ...methods.passkeys.map((passkey) => (Object.assign(Object.assign({}, passkey), { type: MFADeviceType.Passkey }))),
357
+ ...methods.devices.map((device) => (Object.assign(Object.assign({}, device), { type: MFADeviceType.Totp }))),
358
+ ];
359
+ if (!methods.userHasVerifiedMfaMethods || allMethods.length === 0) {
360
+ setShowAuthFlow(true);
361
+ pushView('mfa-choose-device', {
362
+ createMfaToken: props === null || props === void 0 ? void 0 : props.createMfaToken,
363
+ requestedScopes: props === null || props === void 0 ? void 0 : props.requestedScopes,
364
+ });
365
+ return;
366
+ }
367
+ const lastCreatedMethod = allMethods.reduce((a, b) => {
368
+ if (!a)
369
+ return b;
370
+ if (!b)
371
+ return a;
372
+ if (a.createdAt && b.createdAt) {
373
+ return a.createdAt >= b.createdAt ? a : b;
374
+ }
375
+ if (b.createdAt) {
376
+ return b;
377
+ }
378
+ return a;
379
+ }, allMethods[0]);
380
+ switch (lastCreatedMethod.type) {
381
+ case MFADeviceType.Passkey: {
382
+ const createMfaTokenOptions = (props === null || props === void 0 ? void 0 : props.createMfaToken)
383
+ ? { singleUse: true }
384
+ : undefined;
385
+ const authenticatePasskeyPromise = authenticatePasskeyMFA$1({
386
+ createMfaToken: createMfaTokenOptions,
387
+ requestedScopes: props === null || props === void 0 ? void 0 : props.requestedScopes,
388
+ });
389
+ setShowAuthFlow(true);
390
+ pushView('passkey-confirm', {
391
+ authenticatePasskeyPromise,
392
+ createMfaToken: props === null || props === void 0 ? void 0 : props.createMfaToken,
393
+ requestedScopes: props === null || props === void 0 ? void 0 : props.requestedScopes,
394
+ });
395
+ return authenticatePasskeyPromise;
396
+ }
397
+ case MFADeviceType.Totp: {
398
+ if ((dynamicClient === null || dynamicClient === void 0 ? void 0 : dynamicClient.mfaToken) && !((_f = props === null || props === void 0 ? void 0 : props.requestedScopes) === null || _f === void 0 ? void 0 : _f.length)) {
399
+ return dynamicClient === null || dynamicClient === void 0 ? void 0 : dynamicClient.mfaToken;
400
+ }
401
+ const deferred = new DeferredPromise();
402
+ setShowAuthFlow(true);
403
+ pushView('mfa-verification', {
404
+ createMfaToken: props === null || props === void 0 ? void 0 : props.createMfaToken,
405
+ requestedScopes: props === null || props === void 0 ? void 0 : props.requestedScopes,
406
+ });
407
+ const mfaCompletionSuccessOff = onEvent({
408
+ event: 'mfaCompletionSuccess',
409
+ listener: ({ mfaToken }) => deferred.resolve(mfaToken),
410
+ }, dynamicClient);
411
+ const onAuthFlowCloseHandler = () => deferred.reject(new Error('MFA view closed'));
412
+ dynamicEvents.on('authFlowClose', onAuthFlowCloseHandler);
413
+ deferred.promise.finally(() => {
414
+ mfaCompletionSuccessOff();
415
+ dynamicEvents.off('authFlowClose', onAuthFlowCloseHandler);
416
+ });
417
+ return deferred.promise;
418
+ }
419
+ default:
420
+ throw new Error('Error determining MFA method to use');
421
+ }
422
+ }), [
423
+ authenticatePasskeyMFA$1,
424
+ dynamicClient,
425
+ getUserMfaMethods,
426
+ pushView,
427
+ setShowAuthFlow,
428
+ ]);
260
429
  return {
261
430
  isStepUpRequired,
431
+ promptMfa,
262
432
  resetState,
263
433
  sendOtp,
264
434
  state,
265
435
  verifyOtp,
266
436
  verifyPasskeyMfa,
437
+ verifyRecoveryCode,
267
438
  verifyTotpMfa,
268
439
  verifyWallet,
269
440
  };