@dynamic-labs/sdk-react-core 4.101.0 → 4.102.0

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 CHANGED
@@ -1,4 +1,6 @@
1
1
 
2
+ ## [4.102.0](https://github.com/dynamic-labs/dynamic-auth/compare/v4.101.0...v4.102.0) (2026-10-16)
3
+
2
4
  ## [4.101.0](https://github.com/dynamic-labs/dynamic-auth/compare/v4.100.5...v4.101.0) (2026-10-16)
3
5
 
4
6
 
package/package.cjs CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
- var version = "4.101.0";
6
+ var version = "4.102.0";
7
7
  var dependencies = {
8
8
  "@dynamic-labs/sdk-api-core": "0.104.0",
9
9
  "@dynamic-labs-sdk/client": "1.41.0",
package/package.js CHANGED
@@ -1,5 +1,5 @@
1
1
  'use client'
2
- var version = "4.101.0";
2
+ var version = "4.102.0";
3
3
  var dependencies = {
4
4
  "@dynamic-labs/sdk-api-core": "0.104.0",
5
5
  "@dynamic-labs-sdk/client": "1.41.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dynamic-labs/sdk-react-core",
3
- "version": "4.101.0",
3
+ "version": "4.102.0",
4
4
  "dependencies": {
5
5
  "@dynamic-labs/sdk-api-core": "0.104.0",
6
6
  "@dynamic-labs-sdk/client": "1.41.0",
@@ -18,17 +18,17 @@
18
18
  "react-i18next": "13.5.0",
19
19
  "react-international-phone": "4.5.0",
20
20
  "yup": "0.32.11",
21
- "@dynamic-labs/assert-package-version": "4.101.0",
22
- "@dynamic-labs/iconic": "4.101.0",
23
- "@dynamic-labs/locale": "4.101.0",
24
- "@dynamic-labs/logger": "4.101.0",
25
- "@dynamic-labs/multi-wallet": "4.101.0",
26
- "@dynamic-labs/rpc-providers": "4.101.0",
27
- "@dynamic-labs/store": "4.101.0",
28
- "@dynamic-labs/types": "4.101.0",
29
- "@dynamic-labs/utils": "4.101.0",
30
- "@dynamic-labs/wallet-book": "4.101.0",
31
- "@dynamic-labs/wallet-connector-core": "4.101.0",
21
+ "@dynamic-labs/assert-package-version": "4.102.0",
22
+ "@dynamic-labs/iconic": "4.102.0",
23
+ "@dynamic-labs/locale": "4.102.0",
24
+ "@dynamic-labs/logger": "4.102.0",
25
+ "@dynamic-labs/multi-wallet": "4.102.0",
26
+ "@dynamic-labs/rpc-providers": "4.102.0",
27
+ "@dynamic-labs/store": "4.102.0",
28
+ "@dynamic-labs/types": "4.102.0",
29
+ "@dynamic-labs/utils": "4.102.0",
30
+ "@dynamic-labs/wallet-book": "4.102.0",
31
+ "@dynamic-labs/wallet-connector-core": "4.102.0",
32
32
  "eventemitter3": "5.0.1"
33
33
  },
34
34
  "devDependencies": {
@@ -8,6 +8,7 @@ export type StepUpAuthenticationState = {
8
8
  };
9
9
  export type SendOtpParams = {
10
10
  credentialId?: string;
11
+ requestedScopes?: TokenScope[];
11
12
  };
12
13
  export type VerifyOtpParams = {
13
14
  requestedScopes?: TokenScope[];
@@ -42,11 +42,14 @@ const resolveTargetCredential = (credentials, credentialId) => {
42
42
  }
43
43
  return ((_b = credentials.find((cred) => cred.signInEnabled && isOtpCapableCredential(cred))) !== null && _b !== void 0 ? _b : 'No sign-in enabled email or SMS credential found for step-up authentication');
44
44
  };
45
- const sendEmailOtp = (credential) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
45
+ const sendEmailOtp = (credential, purpose) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
46
46
  if (!credential.email) {
47
47
  throw new Error('Email credential is missing email address');
48
48
  }
49
- return client.sendEmailOTP({ email: credential.email });
49
+ // `purpose` lets the API tailor the verification email to the step-up
50
+ // operation; client versions predating the param ignore it.
51
+ const params = Object.assign({ email: credential.email }, (purpose !== undefined && { purpose }));
52
+ return client.sendEmailOTP(params);
50
53
  });
51
54
  const sendSmsOtp = (credential) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
52
55
  var _a;
@@ -60,21 +63,22 @@ const sendSmsOtp = (credential) => _tslib.__awaiter(void 0, void 0, void 0, func
60
63
  }
61
64
  return client.sendSmsOTP({ isoCountryCode, phoneNumber: credential.phoneNumber });
62
65
  });
63
- const dispatchOtp = (credential) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
66
+ const dispatchOtp = (credential, purpose) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
64
67
  return credential.format === sdkApiCore.JwtVerifiedCredentialFormatEnum.Email
65
- ? sendEmailOtp(credential)
68
+ ? sendEmailOtp(credential, purpose)
66
69
  : sendSmsOtp(credential);
67
70
  });
68
71
  const useStepUpOtp = ({ credentialId, stateActions, }) => {
69
72
  const user = useUser.useUser();
70
73
  const { setError, setLoading, setState, setSuccess } = stateActions;
71
74
  const otpVerificationRef = React.useRef(null);
72
- // Holds the credential whose OTP send is blocked awaiting a captcha token.
73
- const pendingCaptchaCredentialRef = React.useRef(null);
74
- const dispatchAndStoreOtp = React.useCallback((credential) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
75
+ // Holds the credential and send purpose whose OTP send is blocked awaiting
76
+ // a captcha token.
77
+ const pendingCaptchaSendRef = React.useRef(null);
78
+ const dispatchAndStoreOtp = React.useCallback((credential, purpose) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
75
79
  setLoading();
76
80
  try {
77
- const otpVerification = yield dispatchOtp(credential);
81
+ const otpVerification = yield dispatchOtp(credential, purpose);
78
82
  otpVerificationRef.current = otpVerification;
79
83
  setSuccess({ otpVerification });
80
84
  return otpVerification;
@@ -86,7 +90,7 @@ const useStepUpOtp = ({ credentialId, stateActions, }) => {
86
90
  }
87
91
  }), [setError, setLoading, setSuccess]);
88
92
  const sendOtp = React.useCallback((params) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
89
- var _a;
93
+ var _a, _b;
90
94
  const credentials = user === null || user === void 0 ? void 0 : user.verifiedCredentials;
91
95
  if (!(credentials === null || credentials === void 0 ? void 0 : credentials.length)) {
92
96
  setError('No verified credentials found for the authenticated user');
@@ -98,6 +102,9 @@ const useStepUpOtp = ({ credentialId, stateActions, }) => {
98
102
  setError(result);
99
103
  return null;
100
104
  }
105
+ // The first requested scope names the operation (e.g. wallet:export),
106
+ // so the OTP email can describe it instead of a sign-in.
107
+ const purpose = (_b = params === null || params === void 0 ? void 0 : params.requestedScopes) === null || _b === void 0 ? void 0 : _b[0];
101
108
  if (!isOtpCapableCredential(result)) {
102
109
  setError(`Credential format "${result.format}" does not support OTP verification. Only email and SMS credentials are supported`);
103
110
  return null;
@@ -106,11 +113,11 @@ const useStepUpOtp = ({ credentialId, stateActions, }) => {
106
113
  // captcha-enabled environments. Defer the send and surface the challenge
107
114
  // to the UI, which collects a token and completes it via submitCaptchaToken.
108
115
  if (client.isCaptchaRequired()) {
109
- pendingCaptchaCredentialRef.current = result;
116
+ pendingCaptchaSendRef.current = { credential: result, purpose };
110
117
  setState((prev) => (Object.assign(Object.assign({}, prev), { captchaRequired: true, error: null })));
111
118
  return null;
112
119
  }
113
- return dispatchAndStoreOtp(result);
120
+ return dispatchAndStoreOtp(result, purpose);
114
121
  }), [
115
122
  credentialId,
116
123
  dispatchAndStoreOtp,
@@ -119,16 +126,16 @@ const useStepUpOtp = ({ credentialId, stateActions, }) => {
119
126
  user === null || user === void 0 ? void 0 : user.verifiedCredentials,
120
127
  ]);
121
128
  const submitCaptchaToken = React.useCallback((captchaToken) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
122
- const credential = pendingCaptchaCredentialRef.current;
123
- if (!credential) {
129
+ const pending = pendingCaptchaSendRef.current;
130
+ if (!pending) {
124
131
  return null;
125
132
  }
126
- pendingCaptchaCredentialRef.current = null;
133
+ pendingCaptchaSendRef.current = null;
127
134
  client.setCaptchaToken({ captchaToken });
128
135
  setState((prev) => (Object.assign(Object.assign({}, prev), { captchaRequired: false })));
129
- return dispatchAndStoreOtp(credential);
136
+ return dispatchAndStoreOtp(pending.credential, pending.purpose);
130
137
  }), [dispatchAndStoreOtp, setState]);
131
- const verifyOtp = React.useCallback((_b) => _tslib.__awaiter(void 0, [_b], void 0, function* ({ requestedScopes, verificationToken, }) {
138
+ const verifyOtp = React.useCallback((_c) => _tslib.__awaiter(void 0, [_c], void 0, function* ({ requestedScopes, verificationToken, }) {
132
139
  const otpVerification = otpVerificationRef.current;
133
140
  if (!otpVerification) {
134
141
  setError('OTP verification has not been initiated. Call sendOtp() first');
@@ -152,7 +159,7 @@ const useStepUpOtp = ({ credentialId, stateActions, }) => {
152
159
  }), [setError, setLoading, setSuccess]);
153
160
  const resetOtpRef = React.useCallback(() => {
154
161
  otpVerificationRef.current = null;
155
- pendingCaptchaCredentialRef.current = null;
162
+ pendingCaptchaSendRef.current = null;
156
163
  }, []);
157
164
  return { resetOtpRef, sendOtp, submitCaptchaToken, verifyOtp };
158
165
  };
@@ -38,11 +38,14 @@ const resolveTargetCredential = (credentials, credentialId) => {
38
38
  }
39
39
  return ((_b = credentials.find((cred) => cred.signInEnabled && isOtpCapableCredential(cred))) !== null && _b !== void 0 ? _b : 'No sign-in enabled email or SMS credential found for step-up authentication');
40
40
  };
41
- const sendEmailOtp = (credential) => __awaiter(void 0, void 0, void 0, function* () {
41
+ const sendEmailOtp = (credential, purpose) => __awaiter(void 0, void 0, void 0, function* () {
42
42
  if (!credential.email) {
43
43
  throw new Error('Email credential is missing email address');
44
44
  }
45
- return sendEmailOTP({ email: credential.email });
45
+ // `purpose` lets the API tailor the verification email to the step-up
46
+ // operation; client versions predating the param ignore it.
47
+ const params = Object.assign({ email: credential.email }, (purpose !== undefined && { purpose }));
48
+ return sendEmailOTP(params);
46
49
  });
47
50
  const sendSmsOtp = (credential) => __awaiter(void 0, void 0, void 0, function* () {
48
51
  var _a;
@@ -56,21 +59,22 @@ const sendSmsOtp = (credential) => __awaiter(void 0, void 0, void 0, function* (
56
59
  }
57
60
  return sendSmsOTP({ isoCountryCode, phoneNumber: credential.phoneNumber });
58
61
  });
59
- const dispatchOtp = (credential) => __awaiter(void 0, void 0, void 0, function* () {
62
+ const dispatchOtp = (credential, purpose) => __awaiter(void 0, void 0, void 0, function* () {
60
63
  return credential.format === JwtVerifiedCredentialFormatEnum.Email
61
- ? sendEmailOtp(credential)
64
+ ? sendEmailOtp(credential, purpose)
62
65
  : sendSmsOtp(credential);
63
66
  });
64
67
  const useStepUpOtp = ({ credentialId, stateActions, }) => {
65
68
  const user = useUser();
66
69
  const { setError, setLoading, setState, setSuccess } = stateActions;
67
70
  const otpVerificationRef = useRef(null);
68
- // Holds the credential whose OTP send is blocked awaiting a captcha token.
69
- const pendingCaptchaCredentialRef = useRef(null);
70
- const dispatchAndStoreOtp = useCallback((credential) => __awaiter(void 0, void 0, void 0, function* () {
71
+ // Holds the credential and send purpose whose OTP send is blocked awaiting
72
+ // a captcha token.
73
+ const pendingCaptchaSendRef = useRef(null);
74
+ const dispatchAndStoreOtp = useCallback((credential, purpose) => __awaiter(void 0, void 0, void 0, function* () {
71
75
  setLoading();
72
76
  try {
73
- const otpVerification = yield dispatchOtp(credential);
77
+ const otpVerification = yield dispatchOtp(credential, purpose);
74
78
  otpVerificationRef.current = otpVerification;
75
79
  setSuccess({ otpVerification });
76
80
  return otpVerification;
@@ -82,7 +86,7 @@ const useStepUpOtp = ({ credentialId, stateActions, }) => {
82
86
  }
83
87
  }), [setError, setLoading, setSuccess]);
84
88
  const sendOtp = useCallback((params) => __awaiter(void 0, void 0, void 0, function* () {
85
- var _a;
89
+ var _a, _b;
86
90
  const credentials = user === null || user === void 0 ? void 0 : user.verifiedCredentials;
87
91
  if (!(credentials === null || credentials === void 0 ? void 0 : credentials.length)) {
88
92
  setError('No verified credentials found for the authenticated user');
@@ -94,6 +98,9 @@ const useStepUpOtp = ({ credentialId, stateActions, }) => {
94
98
  setError(result);
95
99
  return null;
96
100
  }
101
+ // The first requested scope names the operation (e.g. wallet:export),
102
+ // so the OTP email can describe it instead of a sign-in.
103
+ const purpose = (_b = params === null || params === void 0 ? void 0 : params.requestedScopes) === null || _b === void 0 ? void 0 : _b[0];
97
104
  if (!isOtpCapableCredential(result)) {
98
105
  setError(`Credential format "${result.format}" does not support OTP verification. Only email and SMS credentials are supported`);
99
106
  return null;
@@ -102,11 +109,11 @@ const useStepUpOtp = ({ credentialId, stateActions, }) => {
102
109
  // captcha-enabled environments. Defer the send and surface the challenge
103
110
  // to the UI, which collects a token and completes it via submitCaptchaToken.
104
111
  if (isCaptchaRequired()) {
105
- pendingCaptchaCredentialRef.current = result;
112
+ pendingCaptchaSendRef.current = { credential: result, purpose };
106
113
  setState((prev) => (Object.assign(Object.assign({}, prev), { captchaRequired: true, error: null })));
107
114
  return null;
108
115
  }
109
- return dispatchAndStoreOtp(result);
116
+ return dispatchAndStoreOtp(result, purpose);
110
117
  }), [
111
118
  credentialId,
112
119
  dispatchAndStoreOtp,
@@ -115,16 +122,16 @@ const useStepUpOtp = ({ credentialId, stateActions, }) => {
115
122
  user === null || user === void 0 ? void 0 : user.verifiedCredentials,
116
123
  ]);
117
124
  const submitCaptchaToken = useCallback((captchaToken) => __awaiter(void 0, void 0, void 0, function* () {
118
- const credential = pendingCaptchaCredentialRef.current;
119
- if (!credential) {
125
+ const pending = pendingCaptchaSendRef.current;
126
+ if (!pending) {
120
127
  return null;
121
128
  }
122
- pendingCaptchaCredentialRef.current = null;
129
+ pendingCaptchaSendRef.current = null;
123
130
  setCaptchaToken({ captchaToken });
124
131
  setState((prev) => (Object.assign(Object.assign({}, prev), { captchaRequired: false })));
125
- return dispatchAndStoreOtp(credential);
132
+ return dispatchAndStoreOtp(pending.credential, pending.purpose);
126
133
  }), [dispatchAndStoreOtp, setState]);
127
- const verifyOtp = useCallback((_b) => __awaiter(void 0, [_b], void 0, function* ({ requestedScopes, verificationToken, }) {
134
+ const verifyOtp = useCallback((_c) => __awaiter(void 0, [_c], void 0, function* ({ requestedScopes, verificationToken, }) {
128
135
  const otpVerification = otpVerificationRef.current;
129
136
  if (!otpVerification) {
130
137
  setError('OTP verification has not been initiated. Call sendOtp() first');
@@ -148,7 +155,7 @@ const useStepUpOtp = ({ credentialId, stateActions, }) => {
148
155
  }), [setError, setLoading, setSuccess]);
149
156
  const resetOtpRef = useCallback(() => {
150
157
  otpVerificationRef.current = null;
151
- pendingCaptchaCredentialRef.current = null;
158
+ pendingCaptchaSendRef.current = null;
152
159
  }, []);
153
160
  return { resetOtpRef, sendOtp, submitCaptchaToken, verifyOtp };
154
161
  };
@@ -24,8 +24,8 @@ const StepUpReauthOtpView = ({ credentialId, displayLabel, requestedScopes, type
24
24
  if (hasSentInitialOtpRef.current)
25
25
  return;
26
26
  hasSentInitialOtpRef.current = true;
27
- sendOtp();
28
- }, [sendOtp]);
27
+ sendOtp({ requestedScopes });
28
+ }, [requestedScopes, sendOtp]);
29
29
  const handlePinComplete = (verificationToken) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
30
30
  const response = yield verifyOtp({
31
31
  requestedScopes,
@@ -46,7 +46,7 @@ const StepUpReauthOtpView = ({ credentialId, displayLabel, requestedScopes, type
46
46
  return jsxRuntime.jsx(CaptchaChallenge.CaptchaChallenge, { onSuccess: submitCaptchaToken });
47
47
  }
48
48
  return (jsxRuntime.jsx(OTPVerificationView.OTPVerificationView, { MainIcon: MainIcon, displayedDestination: displayLabel, error: displayError, isLoading: isLoading, isValid: verificationSuccess, onPinComplete: handlePinComplete, retryHandler: () => {
49
- void sendOtp();
49
+ void sendOtp({ requestedScopes });
50
50
  }, successBannerTextKey: 'dyn_otp_verification.verification_succeeded' }));
51
51
  };
52
52
 
@@ -20,8 +20,8 @@ const StepUpReauthOtpView = ({ credentialId, displayLabel, requestedScopes, type
20
20
  if (hasSentInitialOtpRef.current)
21
21
  return;
22
22
  hasSentInitialOtpRef.current = true;
23
- sendOtp();
24
- }, [sendOtp]);
23
+ sendOtp({ requestedScopes });
24
+ }, [requestedScopes, sendOtp]);
25
25
  const handlePinComplete = (verificationToken) => __awaiter(void 0, void 0, void 0, function* () {
26
26
  const response = yield verifyOtp({
27
27
  requestedScopes,
@@ -42,7 +42,7 @@ const StepUpReauthOtpView = ({ credentialId, displayLabel, requestedScopes, type
42
42
  return jsx(CaptchaChallenge, { onSuccess: submitCaptchaToken });
43
43
  }
44
44
  return (jsx(OTPVerificationView, { MainIcon: MainIcon, displayedDestination: displayLabel, error: displayError, isLoading: isLoading, isValid: verificationSuccess, onPinComplete: handlePinComplete, retryHandler: () => {
45
- void sendOtp();
45
+ void sendOtp({ requestedScopes });
46
46
  }, successBannerTextKey: 'dyn_otp_verification.verification_succeeded' }));
47
47
  };
48
48