Skip to content

Commit 1169752

Browse files
committed
[MNY-327] SDK: Display error returned from API in login with phone number UI (#8548)
<!-- ## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes" If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000): ## Notes for the reviewer Anything important to call out? Be sure to also clarify these in your comments. ## How to test Unit tests, playground, etc. --> <!-- start pr-codex --> --- ## PR-Codex overview This PR focuses on improving error handling and state management in the OTP authentication process. It enhances the way error messages are displayed and modifies the structure of `AccountStatus` to accommodate additional information. ### Detailed summary - In `otp.ts`, enhanced error handling by parsing the response for a detailed message. - Updated `AccountStatus` type in `OTPLoginUI.tsx` to an object structure, allowing for an error message. - Modified state management for `accountStatus` to use the new object structure. - Adjusted UI rendering logic to handle the new `AccountStatus` format. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Enhanced error message handling in OTP verification to display detailed server error messages to users instead of generic messages. * Improved error status display in OTP login interface. * **Style** * Updated OTP login UI layout and spacing for better status presentation. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent ff8f413 commit 1169752

2 files changed

Lines changed: 35 additions & 12 deletions

File tree

packages/thirdweb/src/react/web/wallets/shared/OTPLoginUI.tsx

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ type VerificationStatus =
2929
| "valid"
3030
| "idle"
3131
| "payment_required";
32-
type AccountStatus = "sending" | "sent" | "error";
32+
type AccountStatus =
33+
| { type: "sending" }
34+
| { type: "sent" }
35+
| { type: "error"; message: string | undefined };
3336
type ScreenToShow = "base" | "enter-password-or-recovery-code";
3437

3538
/**
@@ -52,7 +55,9 @@ export function OTPLoginUI(props: {
5255
const [otpInput, setOtpInput] = useState("");
5356
const [verifyStatus, setVerifyStatus] = useState<VerificationStatus>("idle");
5457
const [error, setError] = useState<string | undefined>();
55-
const [accountStatus, setAccountStatus] = useState<AccountStatus>("sending");
58+
const [accountStatus, setAccountStatus] = useState<AccountStatus>({
59+
type: "sending",
60+
});
5661
const [countdown, setCountdown] = useState(0);
5762
const ecosystem = isEcosystemWallet(wallet)
5863
? {
@@ -66,7 +71,7 @@ export function OTPLoginUI(props: {
6671
const sendEmailOrSms = useCallback(async () => {
6772
setOtpInput("");
6873
setVerifyStatus("idle");
69-
setAccountStatus("sending");
74+
setAccountStatus({ type: "sending" });
7075

7176
try {
7277
if ("email" in userInfo) {
@@ -76,7 +81,7 @@ export function OTPLoginUI(props: {
7681
email: userInfo.email,
7782
strategy: "email",
7883
});
79-
setAccountStatus("sent");
84+
setAccountStatus({ type: "sent" });
8085
setCountdown(60); // Start 60-second countdown
8186
} else if ("phone" in userInfo) {
8287
await preAuthenticate({
@@ -85,15 +90,18 @@ export function OTPLoginUI(props: {
8590
phoneNumber: userInfo.phone,
8691
strategy: "phone",
8792
});
88-
setAccountStatus("sent");
93+
setAccountStatus({ type: "sent" });
8994
setCountdown(60); // Start 60-second countdown
9095
} else {
9196
throw new Error("Invalid userInfo");
9297
}
9398
} catch (e) {
9499
console.error(e);
95100
setVerifyStatus("idle");
96-
setAccountStatus("error");
101+
setAccountStatus({
102+
type: "error",
103+
message: e instanceof Error ? e.message : undefined,
104+
});
97105
}
98106
}, [props.client, userInfo, ecosystem]);
99107

@@ -317,19 +325,24 @@ export function OTPLoginUI(props: {
317325

318326
{!isWideModal && <Line />}
319327

320-
<Container gap="xs" p={isWideModal ? undefined : "lg"}>
321-
{accountStatus === "error" && (
328+
<Container
329+
gap="sm"
330+
p={isWideModal ? undefined : "lg"}
331+
flex="column"
332+
>
333+
{accountStatus.type === "error" && (
322334
<Text
323335
center
324336
color="danger"
325337
size="sm"
326338
className="tw-screen-error"
327339
>
328-
{locale.emailLoginScreen.failedToSendCode}
340+
{accountStatus.message ||
341+
locale.emailLoginScreen.failedToSendCode}
329342
</Text>
330343
)}
331344

332-
{accountStatus === "sending" && (
345+
{accountStatus.type === "sending" && (
333346
<Container
334347
center="both"
335348
flex="row"
@@ -343,7 +356,7 @@ export function OTPLoginUI(props: {
343356
</Container>
344357
)}
345358

346-
{accountStatus !== "sending" && (
359+
{accountStatus.type !== "sending" && (
347360
<LinkButton
348361
onClick={countdown === 0 ? sendEmailOrSms : undefined}
349362
style={{

packages/thirdweb/src/wallets/in-app/web/lib/auth/otp.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,17 @@ export const sendOtp = async (args: PreAuthArgsType): Promise<void> => {
5151
});
5252

5353
if (!response.ok) {
54-
throw new Error("Failed to send verification code");
54+
const raw = await response.text();
55+
let message: string | undefined;
56+
try {
57+
const parsed = JSON.parse(raw);
58+
if (parsed && typeof parsed.message === "string") {
59+
message = parsed.message;
60+
}
61+
} catch {
62+
// ignore parse errors
63+
}
64+
throw new Error(message || "Failed to send verification code");
5565
}
5666

5767
return await response.json();

0 commit comments

Comments
 (0)