diff --git a/packages/backend/src/routes/auth.ts b/packages/backend/src/routes/auth.ts index 8e2edbec..2ef917e7 100644 --- a/packages/backend/src/routes/auth.ts +++ b/packages/backend/src/routes/auth.ts @@ -5,19 +5,6 @@ import { authenticateUser, createUser } from '../turnkey-backend'; const router = Router(); -// -// Access Code -// -router.post('/accesscode', async (req, res) => { - console.log('Access Code', req.body); - const { accesscode } = req.body; - if (accesscode === '44444') { - return res.send({ isValid: true }); - } else { - return res.sendStatus(204); - } -}); - // // Turnkey // @@ -59,10 +46,6 @@ router.post('/authenticate', async (req, res) => { } }); -// -// Lit -// - router.post('/validate', async (req, res) => { const { message, signature } = req.body; const { success, data } = await new SiweMessage(message).verify({ diff --git a/packages/frontend/src/context/Web3Provider.tsx b/packages/frontend/src/context/Web3Provider.tsx index ffe84c85..cd456c3d 100644 --- a/packages/frontend/src/context/Web3Provider.tsx +++ b/packages/frontend/src/context/Web3Provider.tsx @@ -1,4 +1,5 @@ -import React, { ReactNode, Suspense } from 'react'; +import { ReactNode } from 'react'; +import assert from 'assert'; import { SiweMessage, generateNonce } from 'siwe'; import { WagmiProvider } from 'wagmi'; import { arbitrum, mainnet } from 'wagmi/chains'; @@ -12,12 +13,16 @@ import type { } from '@web3modal/core'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -// TODO: Use environment variable -const WALLET_CONNECT_ID="d37f5a2f09d22f5e3ccaff4bbc93d37c" +import { VITE_WALLET_CONNECT_ID, baseUrl } from 'utils/constants'; + +if (!VITE_WALLET_CONNECT_ID) { + throw new Error('Error: REACT_APP_WALLET_CONNECT_ID env config is not set'); +} +assert(baseUrl, 'VITE_SERVER_URL is not set in env'); + const queryClient = new QueryClient(); const axiosInstance = axios.create({ - // TODO: Use environment variable - baseURL: 'http://localhost:8000', + baseURL: baseUrl, headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', @@ -33,7 +38,7 @@ const metadata = { const chains = [mainnet, arbitrum] as const; const config = defaultWagmiConfig({ chains, - projectId: WALLET_CONNECT_ID, + projectId: VITE_WALLET_CONNECT_ID, metadata, }); const siweConfig = createSIWEConfig({ @@ -95,7 +100,7 @@ const siweConfig = createSIWEConfig({ createWeb3Modal({ siweConfig, wagmiConfig: config, - projectId: WALLET_CONNECT_ID, + projectId: VITE_WALLET_CONNECT_ID, }); export default function Web3ModalProvider({ children, diff --git a/packages/frontend/src/pages/AuthPage.tsx b/packages/frontend/src/pages/AuthPage.tsx index 68bb3a4b..b72c0af6 100644 --- a/packages/frontend/src/pages/AuthPage.tsx +++ b/packages/frontend/src/pages/AuthPage.tsx @@ -1,5 +1,5 @@ import { CloudyFlow } from 'components/CloudyFlow'; -import { SnowballAuth } from './auth/SnowballAuth'; +import { Login } from './auth/Login'; const AuthPage = () => { return ( @@ -18,7 +18,7 @@ const AuthPage = () => {
- +
diff --git a/packages/frontend/src/pages/auth/AccessCode.tsx b/packages/frontend/src/pages/auth/AccessCode.tsx deleted file mode 100644 index 327647e8..00000000 --- a/packages/frontend/src/pages/auth/AccessCode.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import React, { useState } from 'react'; - -import { Button } from 'components/shared/Button'; -import { - ArrowRightCircleFilledIcon, - LoaderIcon, -} from 'components/shared/CustomIcon'; -import { WavyBorder } from 'components/shared/WavyBorder'; -import { VerifyCodeInput } from 'components/shared/VerifyCodeInput'; -import { verifyAccessCode } from 'utils/accessCode'; - -type AccessMethod = 'accesscode' | 'passkey'; - -type Err = { type: AccessMethod; message: string }; - -type AccessCodeProps = { - onCorrectAccessCode: () => void; -}; - -export const AccessCode: React.FC = ({ - onCorrectAccessCode, -}) => { - const [accessCode, setAccessCode] = useState(' '); - const [error, setError] = useState(); - const [accessMethod, setAccessMethod] = useState(false); - - async function validateAccessCode() { - setAccessMethod('accesscode'); - try { - const isValidAccessCode = await verifyAccessCode(accessCode); - - // add a pause for ux - await new Promise((resolve) => setTimeout(resolve, 250)); - if (isValidAccessCode) { - localStorage.setItem('accessCode', accessCode); - onCorrectAccessCode(); - } else { - setError({ - type: 'accesscode', - message: 'Invalid access code', - }); - } - } catch (err: any) { - setError({ type: 'accesscode', message: err.message }); - } - } - - const loading = accessMethod; - const isValidAccessCodeLength = accessCode.trim().length === 5; - - return ( -
-
-
- Access Code -
-
- -
-
-
- -
- - {error && error.type === 'accesscode' && ( -
-
-
- Error: {error.message}.{' '} - - Try again? - -
-
-
- )} -
-
-
- ); -}; diff --git a/packages/frontend/src/pages/auth/AccessSignUp.tsx b/packages/frontend/src/pages/auth/AccessSignUp.tsx deleted file mode 100644 index d91fb167..00000000 --- a/packages/frontend/src/pages/auth/AccessSignUp.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import React, { useState } from 'react'; - -import { AccessCode } from './AccessCode'; -import { SignUp } from './SignUp'; - -type AccessSignUpProps = { - onDone: () => void; -}; - -export const AccessSignUp: React.FC = ({ onDone }) => { - const [isValidAccessCode, setIsValidAccessCode] = useState( - !!localStorage.getItem('accessCode'), - ); - - return isValidAccessCode ? ( - - ) : ( - setIsValidAccessCode(true)} /> - ); -}; diff --git a/packages/frontend/src/pages/auth/SignUp.tsx b/packages/frontend/src/pages/auth/SignUp.tsx deleted file mode 100644 index f5564e46..00000000 --- a/packages/frontend/src/pages/auth/SignUp.tsx +++ /dev/null @@ -1,287 +0,0 @@ -import { Button } from 'components/shared/Button'; -import { - ArrowRightCircleFilledIcon, - GithubIcon, - LoaderIcon, -} from 'components/shared/CustomIcon'; -import { GoogleIcon } from 'components/shared/CustomIcon/GoogleIcon'; -import { DotBorder } from 'components/shared/DotBorder'; -import { WavyBorder } from 'components/shared/WavyBorder'; -import { useEffect, useState } from 'react'; -import { useSnowball } from 'utils/use-snowball'; -import { Input } from 'components/shared/Input'; -import { AppleIcon } from 'components/shared/CustomIcon/AppleIcon'; -import { Link } from 'react-router-dom'; -import { useToast } from 'components/shared/Toast'; -import { PKPEthersWallet } from '@lit-protocol/pkp-ethers'; -import { signInWithEthereum } from 'utils/siwe'; -import { logError } from 'utils/log-error'; -import { - subOrganizationIdForEmail, - turnkeySignin, - turnkeySignup, -} from 'utils/turnkey-frontend'; -import { verifyAccessCode } from 'utils/accessCode'; - -type Provider = 'google' | 'github' | 'apple' | 'email'; - -type Err = { type: 'email' | 'provider'; message: string }; - -type Props = { - onDone: () => void; -}; - -export const SignUp = ({ onDone }: Props) => { - const [email, setEmail] = useState(''); - const [error, setError] = useState(); - const [provider, setProvider] = useState(false); - - const { toast } = useToast(); - const snowball = useSnowball(); - - async function handleSignupRedirect() { - let wallet: PKPEthersWallet | undefined; - const { google } = snowball.auth; - if (google.canHandleOAuthRedirectBack()) { - setProvider('google'); - try { - await google.handleOAuthRedirectBack(); - // @ts-ignore - wallet = await google.getEthersWallet(); - // @ts-ignore - const result = await signInWithEthereum(1, 'signup', wallet); - if (result.error) { - setError({ type: 'provider', message: result.error }); - setProvider(false); - wallet = undefined; - logError(new Error(result.error)); - return; - } - } catch (err: any) { - setError({ type: 'provider', message: err.message }); - setProvider(false); - logError(err); - return; - } - } - // if (apple.canHandleOAuthRedirectBack()) { - // setProvider('apple'); - // try { - // await apple.handleOAuthRedirectBack(); - // wallet = await apple.getEthersWallet(); - // const result = await signInWithEthereum(1, 'signup', wallet); - // if (result.error) { - // setError({ type: 'provider', message: result.error }); - // setProvider(false); - // wallet = undefined; - // return; - // } - // } catch (err: any) { - // setError({ type: 'provider', message: err.message }); - // setProvider(false); - // return; - // } - // } - - if (wallet) { - onDone(); - } - } - - async function authEmail() { - setProvider('email'); - try { - const orgId = await subOrganizationIdForEmail(email); - console.log('orgId', orgId); - if (orgId) { - await turnkeySignin(orgId); - window.location.href = '/dashboard'; - } else { - await turnkeySignup(email); - onDone(); - } - } catch (err: any) { - setError({ type: 'email', message: err.message }); - } - } - - useEffect(() => { - handleSignupRedirect(); - }, []); - - const loading = provider; - const emailValid = /.@./.test(email); - - useEffect(() => { - const validateAccessCode = async () => { - const accessCode = localStorage.getItem('accessCode'); - if (!accessCode) { - redirectToSignup(); - return; - } - - try { - await verifyAccessCode(accessCode); - } catch (err: any) { - redirectToSignup(); - } - }; - - const redirectToSignup = () => { - localStorage.removeItem('accessCode'); - window.location.href = '/signup'; - }; - - validateAccessCode(); - }, []); - - return ( -
-
-
- Sign up to Snowball -
-
- -
-
- - - - - -
- - {error && error.type === 'provider' && ( -
-
Error: {error.message}
-
- )} - -
- -
- OR -
- -
- -
-
-
- Email -
- setEmail(e.target.value)} - disabled={!!loading} - /> -
- -
- {error && error.type === 'email' && ( -
-
- Error: {error.message} -
-
- )} -
-
- Already an user? -
-
- - Sign in now - -
-
-
-
-
-
- ); -}; diff --git a/packages/frontend/src/pages/auth/SnowballAuth.tsx b/packages/frontend/src/pages/auth/SnowballAuth.tsx deleted file mode 100644 index 0d849a3d..00000000 --- a/packages/frontend/src/pages/auth/SnowballAuth.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import React, { useEffect, useState } from 'react'; - -import { snowball } from 'utils/use-snowball'; -import { Login } from './Login'; -import { Done } from './Done'; -import { AccessSignUp } from './AccessSignUp'; - -type Screen = 'login' | 'signup' | 'success'; - -const DASHBOARD_URL = '/'; - -export const SnowballAuth: React.FC = () => { - const path = window.location.pathname; - const [screen, setScreen] = useState( - path === '/login' ? 'login' : 'signup', - ); - - useEffect(() => { - if (snowball.session) { - window.location.href = DASHBOARD_URL; - } - }, []); - - useEffect(() => { - if (path === '/login') { - setScreen('login'); - } else if (path === '/signup') { - setScreen('signup'); - } - }, [path]); - - if (screen === 'signup') { - return ( - { - setScreen('success'); - }} - /> - ); - } - if (screen === 'login') { - return ( - - ); - } - if (screen === 'success') { - return ; - } -};