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

feat: adding delay after OTP code validation #1288

Merged
merged 11 commits into from
Jan 27, 2025
7 changes: 0 additions & 7 deletions account-kit/react/src/components/auth/card/loading/otp.tsx
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at this file a bit... seems like a few things are at play potentially.

If calling authenticate with the OTP code is hitting both onSuccess and isConnected == true then that should be a logged in user. If the user is not logged in, then isConnected shouldn't be true and should likely still be in an authenticating state (similar to how magic link used to be in an email_authenticating state). I imagine the signer would similarly be in an email_awaiting_otp state and once authenticate returns successfully, it should update the SignerStatus to complete

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just tried it out on a local branch with the delay removed altogether and seems to work without issue, so this might actually just be me missing context. Is this is a it's "too fast" situation?

Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ import { AuthStepStatus, useAuthContext } from "../../context.js";
import { useAuthenticate } from "../../../../hooks/useAuthenticate.js";
import { useSignerStatus } from "../../../../hooks/useSignerStatus.js";

const AUTH_DELAY = 3000;

export const LoadingOtp = () => {
const { isConnected } = useSignerStatus();
const { setAuthStep, authStep } = useAuthContext("otp_verify");
Expand All @@ -37,11 +35,6 @@ export const LoadingOtp = () => {
if (isConnected) {
setAuthStep({ ...authStep, status: AuthStepStatus.success });
setTitleText(ls.loadingOtp.verified);

// Wait 3 seconds before completing the auth step
setTimeout(() => {
setAuthStep({ type: "complete" });
}, AUTH_DELAY);
}
},
});
Expand Down
32 changes: 32 additions & 0 deletions account-kit/signer/src/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,38 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
};
});

/**
* Gets the current logged in user session type
* If a user has an ongoing session, it will use that session and
* return the session type
*
* @example
* ```ts
* import { AlchemyWebSigner } from "@account-kit/signer";
*
* const signer = new AlchemyWebSigner({
* client: {
* connection: {
* rpcUrl: "/api/rpc",
* },
* iframeConfig: {
* iframeContainerId: "alchemy-signer-iframe-container",
* },
* },
* });
*
* // throws if not logged in
* const sessionType = await signer.getSessionType();
* ```
*
* @returns {Promise<string | null>} the current user session type
*/
getSessionType = async (): Promise<string | null> => {
const sessionType = await this.sessionManager.getSessionType();

return sessionType;
};

/**
* Adds a passkey to the user's account
*
Expand Down
10 changes: 10 additions & 0 deletions account-kit/signer/src/session/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,16 @@ export class SessionManager {
return session;
};

public getSessionType = (): string | null => {
const session = this.store.getState().session ?? null;

if (!session) {
return null;
}

return session.type;
};

private setSession = (
session_:
| Omit<
Expand Down
39 changes: 35 additions & 4 deletions examples/ui-demo/src/components/preview/AuthCardWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
"use client";

import { useEffect, useState } from "react";
import { cn } from "@/lib/utils";
import { useTheme } from "@/state/useTheme";
import { AuthCard, useUser } from "@account-kit/react";
import { AuthCard, useUser, useSigner } from "@account-kit/react";
import { EOAPostLogin } from "../shared/eoa-post-login/EOAPostLogin";
import { MintCard } from "../shared/mint-card/MintCard";

const OTP_AUTH_DELAY = 3000;

export function AuthCardWrapper({ className }: { className?: string }) {
const theme = useTheme();

Expand All @@ -26,9 +29,37 @@ export function AuthCardWrapper({ className }: { className?: string }) {

const RenderContent = () => {
const user = useUser();
const hasUser = !!user;
const signer = useSigner();
const [showAuthCard, setShowAuthCard] = useState(() => !user);

useEffect(() => {
const hasUser = !!user;

const getAuthDetails = async () => {
const sessionType = await signer?.getSessionType();

// Delay showing the auth card for OTP authenticated users
if (sessionType === "otp") {
setTimeout(() => {
setShowAuthCard(!hasUser);
}, OTP_AUTH_DELAY);
} else {
// Hide auth card for non-OTP authenticated users
setShowAuthCard(!hasUser);
}
};

// Show auth card for unauthenticated users
if (!hasUser) {
setShowAuthCard(true);

// Get auth details for authenticated users
} else if (signer && hasUser) {
getAuthDetails();
}
}, [signer, user]);

if (!hasUser) {
if (showAuthCard) {
return (
<div className="flex flex-col gap-2 w-[368px]">
<div
Expand All @@ -44,7 +75,7 @@ const RenderContent = () => {
);
}

const isEOAUser = user.type === "eoa";
const isEOAUser = user?.type === "eoa";

if (isEOAUser) {
return (
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading