Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: using enum instead of strings for auth step types #1251

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
12 changes: 6 additions & 6 deletions account-kit/react/src/components/auth/card/add-passkey.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
import { ReactLogger } from "../../../metrics.js";
import { ls } from "../../../strings.js";
import { Button } from "../../button.js";
import { useAuthContext } from "../context.js";
import { AuthStepType, useAuthContext } from "../context.js";
import { ConnectionError } from "./error/connection-error.js";
import { ConnectionFailed as PasskeyConnectionFailed } from "../../../icons/connectionFailed.js";

Expand All @@ -25,18 +25,18 @@ const BENEFITS = [
];

export const AddPasskey = () => {
const { setAuthStep, authStep } = useAuthContext("passkey_create");
const { setAuthStep, authStep } = useAuthContext(AuthStepType.PasskeyCreate);
const { addPasskey, isAddingPasskey } = useAddPasskey({
onSuccess: () => {
ReactLogger.trackEvent({
name: "add_passkey_on_signup_success",
});

setAuthStep({ type: "passkey_create_success" });
setAuthStep({ type: AuthStepType.PasskeyCreateSuccess });
},
onError: () => {
setAuthStep({
type: "passkey_create",
type: AuthStepType.PasskeyCreate,
error: new Error("Failed to add passkey"),
});
},
Expand All @@ -50,7 +50,7 @@ export const AddPasskey = () => {
icon={<PasskeyConnectionFailed />}
shouldDisconnect={false}
handleTryAgain={addPasskey}
handleSkip={() => setAuthStep({ type: "complete" })}
handleSkip={() => setAuthStep({ type: AuthStepType.Complete })}
/>
);
}
Expand Down Expand Up @@ -91,7 +91,7 @@ export const AddPasskey = () => {
ReactLogger.trackEvent({
name: "add_passkey_on_signup_skip",
});
setAuthStep({ type: "complete" });
setAuthStep({ type: AuthStepType.Complete });
}}
disabled={isAddingPasskey}
>
Expand Down
28 changes: 16 additions & 12 deletions account-kit/react/src/components/auth/card/eoa.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Spinner } from "../../../icons/spinner.js";
import { WalletConnectIcon } from "../../../icons/walletConnectIcon.js";
import { ls } from "../../../strings.js";
import { Button } from "../../button.js";
import { useAuthContext } from "../context.js";
import { AuthStepType, useAuthContext } from "../context.js";
import { useConnectEOA } from "../hooks/useConnectEOA.js";
import { useWalletConnectAuthConfig } from "../hooks/useWalletConnectAuthConfig.js";
import { CardContent } from "./content.js";
Expand All @@ -14,7 +14,7 @@ import { WalletIcon } from "./error/icons/wallet-icon.js";
export const WALLET_CONNECT = "walletConnect";

export const EoaConnectCard = () => {
const { setAuthStep, authStep } = useAuthContext("eoa_connect");
const { setAuthStep, authStep } = useAuthContext(AuthStepType.EoaConnect);
const { connect } = useConnectEOA();
const { chain } = useChain();

Expand All @@ -31,7 +31,7 @@ export const EoaConnectCard = () => {
tryAgainCTA={errorMessage.tryAgainCTA}
handleTryAgain={() => {
setAuthStep({
type: "eoa_connect",
type: AuthStepType.EoaConnect,
connector: authStep.connector,
});

Expand All @@ -41,7 +41,9 @@ export const EoaConnectCard = () => {
chainId: chain.id,
});
}}
handleUseAnotherMethod={() => setAuthStep({ type: "pick_eoa" })}
handleUseAnotherMethod={() =>
setAuthStep({ type: AuthStepType.PickEoa })
}
/>
);
}
Expand Down Expand Up @@ -69,15 +71,15 @@ export const EoaConnectCard = () => {
secondaryButton={{
title: "Cancel",
onClick: async () => {
setAuthStep({ type: "initial" });
setAuthStep({ type: AuthStepType.Initial });
},
}}
/>
);
};

export const WalletConnectCard = () => {
const { setAuthStep, authStep } = useAuthContext("wallet_connect");
const { setAuthStep, authStep } = useAuthContext(AuthStepType.WalletConnect);
const { walletConnectParams } = useWalletConnectAuthConfig();
const { chain } = useChain();

Expand All @@ -89,7 +91,7 @@ export const WalletConnectCard = () => {

if (!walletConnectConnector) {
setAuthStep({
type: "wallet_connect",
type: AuthStepType.WalletConnect,
error: new Error("WalletConnect params not found"),
});

Expand All @@ -106,14 +108,16 @@ export const WalletConnectCard = () => {
tryAgainCTA={errorMessage.tryAgainCTA}
icon={<WalletIcon connector={WALLET_CONNECT} />}
handleTryAgain={() => {
setAuthStep({ type: "wallet_connect" });
setAuthStep({ type: AuthStepType.WalletConnect });
// Re-try wallet connect's connection...
connect({
connector: walletConnectConnector,
chainId: chain.id,
});
}}
handleUseAnotherMethod={() => setAuthStep({ type: "pick_eoa" })}
handleUseAnotherMethod={() =>
setAuthStep({ type: AuthStepType.PickEoa })
}
/>
);
}
Expand Down Expand Up @@ -141,7 +145,7 @@ export const WalletConnectCard = () => {
title: "Cancel",
onClick: async () => {
// Ensure to stop all inflight requests
setAuthStep({ type: "initial" });
setAuthStep({ type: AuthStepType.Initial });
},
}}
/>
Expand All @@ -151,7 +155,7 @@ export const WalletConnectCard = () => {
export const EoaPickCard = () => {
const { chain } = useChain();
const { connectors, connect } = useConnectEOA();
const { setAuthStep } = useAuthContext("pick_eoa");
const { setAuthStep } = useAuthContext(AuthStepType.PickEoa);

const { walletConnectParams } = useWalletConnectAuthConfig();

Expand Down Expand Up @@ -203,7 +207,7 @@ export const EoaPickCard = () => {
// If walletConnectConnector is not found, set the error and return
if (!walletConnectConnector) {
return setAuthStep({
type: "wallet_connect",
type: AuthStepType.WalletConnect,
error: new Error("WalletConnect params not found"),
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import { useEffect, useState } from "react";
import { useEffect, useMemo, useState } from "react";
import { useAuthenticate } from "../../../../hooks/useAuthenticate.js";
import { ls } from "../../../../strings.js";
import { useAuthContext, type AuthStep } from "../../context.js";
import {
AuthStepStatus,
AuthStepType,
useAuthContext,
type AuthStep,
} from "../../context.js";
import { Button } from "../../../button.js";

type EmailNotReceivedDisclaimerProps = {
authStep: Extract<AuthStep, { type: "email_verify" | "otp_verify" }>;
authStep: Extract<
AuthStep,
{ type: AuthStepType.EmailVerify | AuthStepType.OtpVerify }
>;
};
export const EmailNotReceivedDisclaimer = ({
authStep,
Expand All @@ -14,10 +22,18 @@ export const EmailNotReceivedDisclaimer = ({
const [emailResent, setEmailResent] = useState(false);
const { authenticate } = useAuthenticate({
onSuccess: () => {
setAuthStep({ type: "complete" });
setAuthStep({ type: AuthStepType.Complete });
},
});

const isOTPVerifying = useMemo(() => {
return (
authStep.type === AuthStepType.OtpVerify &&
(authStep.status === AuthStepStatus.verifying ||
authStep.status === AuthStepStatus.success)
);
}, [authStep]);

useEffect(() => {
if (emailResent) {
// set the text back to "Resend" after 2 seconds
Expand All @@ -29,13 +45,21 @@ export const EmailNotReceivedDisclaimer = ({

return (
<div className="flex flex-row gap-2 justify-center mb-2">
<span className="text-fg-tertiary text-xs">
<span
className={`${
isOTPVerifying ? "text-fg-disabled" : "text-fg-tertiary"
} text-xs`}
>
{ls.loadingEmail.emailNotReceived}
</span>
<Button
variant="link"
className="text-xs font-normal underline"
disabled={emailResent}
className={`text-xs font-normal underline ${
isOTPVerifying
? "text-fg-disabled disabled:opacity-100"
: "text-btn-primary"
}`}
disabled={emailResent || isOTPVerifying}
onClick={() => {
authenticate({
type: "email",
Expand Down
51 changes: 25 additions & 26 deletions account-kit/react/src/components/auth/card/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { useAuthModal } from "../../../hooks/useAuthModal.js";
import { useElementHeight } from "../../../hooks/useElementHeight.js";
import { useSignerStatus } from "../../../hooks/useSignerStatus.js";
import { Navigation } from "../../navigation.js";
import { useAuthContext } from "../context.js";
import { AuthStepType, useAuthContext } from "../context.js";
import { Footer } from "../sections/Footer.js";
import { Step } from "./steps.js";
export type AuthCardProps = {
Expand Down Expand Up @@ -72,35 +72,34 @@ export const AuthCardContent = ({

const canGoBack = useMemo(() => {
return [
"email_verify",
"otp_verify",
"passkey_verify",
"passkey_create",
"pick_eoa",
"wallet_connect",
"eoa_connect",
"oauth_completing",
AuthStepType.EmailVerify,
AuthStepType.OtpVerify,
AuthStepType.PasskeyVerify,
AuthStepType.PasskeyCreate,
AuthStepType.PickEoa,
AuthStepType.WalletConnect,
AuthStepType.EoaConnect,
AuthStepType.OauthCompleting,
].includes(authStep.type);
}, [authStep]);

const onBack = useCallback(() => {
switch (authStep.type) {
case "email_verify":
case "otp_verify":
case "passkey_verify":
case "passkey_create":
case "oauth_completing":
case "otp_completing":
case AuthStepType.EmailVerify:
case AuthStepType.OtpVerify:
case AuthStepType.PasskeyVerify:
case AuthStepType.PasskeyCreate:
case AuthStepType.OauthCompleting:
disconnect(config); // Terminate any inflight authentication
didGoBack.current = true;
setAuthStep({ type: "initial" });
setAuthStep({ type: AuthStepType.Initial });
break;
case "wallet_connect":
case "eoa_connect":
setAuthStep({ type: "pick_eoa" });
case AuthStepType.WalletConnect:
case AuthStepType.EoaConnect:
setAuthStep({ type: AuthStepType.PickEoa });
break;
case "pick_eoa":
setAuthStep({ type: "initial" });
case AuthStepType.PickEoa:
setAuthStep({ type: AuthStepType.Initial });
break;
default:
console.warn("Unhandled back action for auth step", authStep);
Expand All @@ -113,20 +112,20 @@ export const AuthCardContent = ({
disconnect(config);
}

if (authStep.type === "passkey_create") {
setAuthStep({ type: "complete" });
if (authStep.type === AuthStepType.PasskeyCreate) {
setAuthStep({ type: AuthStepType.Complete });
} else {
setAuthStep({ type: "initial" });
setAuthStep({ type: AuthStepType.Initial });
}
closeAuthModal();
}, [isConnected, authStep.type, closeAuthModal, config, setAuthStep]);

useEffect(() => {
if (authStep.type === "complete") {
if (authStep.type === AuthStepType.Complete) {
didGoBack.current = false;
closeAuthModal();
onAuthSuccess?.();
} else if (authStep.type !== "initial") {
} else if (authStep.type !== AuthStepType.Initial) {
didGoBack.current = false;
}
}, [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { useSignerStatus } from "../../../../hooks/useSignerStatus.js";
import { EmailIllustration } from "../../../../icons/illustrations/email.js";
import { Spinner } from "../../../../icons/spinner.js";
import { ls } from "../../../../strings.js";
import { useAuthContext } from "../../context.js";
import { AuthStepType, useAuthContext } from "../../context.js";

// eslint-disable-next-line jsdoc/require-jsdoc
export const LoadingEmail = () => {
const { authStep } = useAuthContext("email_verify");
const { authStep } = useAuthContext(AuthStepType.EmailVerify);
// yup, re-sent and resent. I'm not fixing it
const [emailResent, setEmailResent] = useState(false);

Expand Down Expand Up @@ -39,11 +39,11 @@ export const LoadingEmail = () => {
// eslint-disable-next-line jsdoc/require-jsdoc
export const CompletingEmailAuth = () => {
const { isConnected } = useSignerStatus();
const { setAuthStep } = useAuthContext("email_completing");
const { setAuthStep } = useAuthContext(AuthStepType.EmailCompleting);

useEffect(() => {
if (isConnected) {
setAuthStep({ type: "complete" });
setAuthStep({ type: AuthStepType.Complete });
}
}, [isConnected, setAuthStep]);

Expand Down
14 changes: 9 additions & 5 deletions account-kit/react/src/components/auth/card/loading/oauth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,24 @@ import {
OAuthConnectionFailed,
} from "../../../../icons/oauth.js";
import { capitalize } from "../../../../utils.js";
import { useAuthContext } from "../../context.js";
import { AuthStepType, useAuthContext } from "../../context.js";
import { useOAuthVerify } from "../../hooks/useOAuthVerify.js";
import { ConnectionError } from "../error/connection-error.js";
import { ls } from "../../../../strings.js";

export const CompletingOAuth = () => {
const { isConnected } = useSignerStatus();
const { setAuthStep, authStep } = useAuthContext("oauth_completing");
const { setAuthStep, authStep } = useAuthContext(
AuthStepType.OauthCompleting
);
const { authenticate } = useOAuthVerify({ config: authStep.config });
const oauthWasCancelled = authStep.error instanceof OauthCancelledError;

useEffect(() => {
if (isConnected) {
setAuthStep({ type: "complete" });
setAuthStep({ type: AuthStepType.Complete });
} else if (oauthWasCancelled) {
setAuthStep({ type: "initial" });
setAuthStep({ type: AuthStepType.Initial });
}
}, [isConnected, oauthWasCancelled, setAuthStep]);

Expand All @@ -33,7 +35,9 @@ export const CompletingOAuth = () => {
)}`}
bodyText={ls.error.connection.oauthBody}
handleTryAgain={authenticate}
handleUseAnotherMethod={() => setAuthStep({ type: "initial" })}
handleUseAnotherMethod={() =>
setAuthStep({ type: AuthStepType.Initial })
}
icon={
<OAuthConnectionFailed provider={authStep.config.authProviderId} />
}
Expand Down
Loading
Loading