Auto sign in using laconic wallet
All checks were successful
Lint / lint (20.x) (pull_request) Successful in 1m43s

This commit is contained in:
Shreerang Kale 2025-02-07 15:05:55 +05:30
parent a51765dae5
commit b5b52df06f
5 changed files with 177 additions and 12 deletions

View File

@ -11,7 +11,7 @@ import ProjectSearchLayout from './layouts/ProjectSearch';
import Index from './pages';
import AuthPage from './pages/AuthPage';
import { DashboardLayout } from './pages/org-slug/layout';
import Web3Provider from 'context/Web3Provider';
// import Web3Provider from 'context/Web3Provider';
import { BASE_URL } from 'utils/constants';
const router = createBrowserRouter([
@ -75,9 +75,9 @@ function App() {
}, []);
return (
<Web3Provider>
// <Web3Provider>
<RouterProvider router={router} />
</Web3Provider>
// </Web3Provider>
);
}

View File

@ -2,7 +2,7 @@ import { useCallback, useEffect, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { User } from 'gql-client';
import { motion } from 'framer-motion';
import { useDisconnect } from 'wagmi';
// import { useDisconnect } from 'wagmi';
import { useGQLClient } from 'context/GQLClientContext';
import {
@ -32,7 +32,7 @@ export const Sidebar = ({ mobileOpen }: SidebarProps) => {
const isDesktop = useMediaQuery('(min-width: 960px)');
const [user, setUser] = useState<User>();
const { disconnect } = useDisconnect();
// const { disconnect } = useDisconnect();
const fetchUser = useCallback(async () => {
const { user } = await client.getUser();
@ -49,9 +49,9 @@ export const Sidebar = ({ mobileOpen }: SidebarProps) => {
credentials: 'include',
});
localStorage.clear();
disconnect();
// disconnect();
navigate('/login');
}, [disconnect, navigate]);
}, [navigate]);
return (
<motion.nav

View File

@ -0,0 +1,164 @@
import { useCallback, useEffect } from 'react';
import { Box, Modal } from '@mui/material';
import {
BASE_URL,
VITE_WALLET_IFRAME_URL,
} from 'utils/constants';
import { generateNonce, SiweMessage } from 'siwe';
import axios from 'axios';
import { useNavigate } from 'react-router-dom';
const axiosInstance = axios.create({
baseURL: BASE_URL,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
withCredentials: true,
});
const AutoSignInIFrameModal = (
// {
// setAccounts,
// setIsDataReceived,
// isVisible,
// }: {
// setAccounts: (accounts: string[]) => void;
// setIsDataReceived: (isReceived: boolean) => void;
// isVisible: boolean;
// }
) => {
const navigate = useNavigate();
useEffect(() => {
const handleMessage = async (event: MessageEvent) => {
if (event.origin !== VITE_WALLET_IFRAME_URL) return;
// setIsDataReceived(true);
if (event.data.type === 'SIGN_IN_RESPONSE') {
try {
const { success } = (
await axiosInstance.post('/auth/validate', {
message: event.data.data.message,
signature: event.data.data.signature,
})
).data;
if(success) {
navigate("/")
}
return success;
} catch (error) {
return false;
}
// setAccounts(event.data.data);
} else if (event.data.type === 'ERROR') {
console.error('Error from wallet:', event.data.message);
}
};
window.addEventListener('message', handleMessage);
return () => {
window.removeEventListener('message', handleMessage);
};
}, []);
useEffect(() => {
const handleInitiateAutoSignIn = async (event: MessageEvent) => {
if (event.origin !== VITE_WALLET_IFRAME_URL) return;
if (event.data.type === 'ACCOUNT_ADDRESS_RESPONSE') {
const iframe = document.getElementById('autoSignInFrame') as HTMLIFrameElement;
if (!iframe.contentWindow) {
console.error('Iframe not found or not loaded');
return;
}
const message = new SiweMessage({
version: '1',
domain: window.location.host,
uri: window.location.origin,
chainId: 1,
address: event.data.data,
nonce: generateNonce(),
// Human-readable ASCII assertion that the user will sign, and it must not contain `\n`.
statement: 'Sign in With Ethereum.',
}).prepareMessage()
iframe.contentWindow.postMessage(
{
type: 'AUTO_SIGN_IN',
chainId: '1',
message,
},
VITE_WALLET_IFRAME_URL,
);
// setAccounts(event.data.data);
} else if (event.data.type === 'ERROR') {
console.error('Error from wallet:', event.data.message);
}
};
window.addEventListener('message', handleInitiateAutoSignIn);
return () => {
window.removeEventListener('message', handleInitiateAutoSignIn);
};
}, []);
// /////////////////////////////////////////////////
const getAddressFromWallet = useCallback(() => {
const iframe = document.getElementById('autoSignInFrame') as HTMLIFrameElement;
if (!iframe.contentWindow) {
console.error('Iframe not found or not loaded');
return;
}
iframe.contentWindow.postMessage(
{
type: 'GET_ACCOUNT_ADDRESS',
chainId: '1',
},
VITE_WALLET_IFRAME_URL,
);
}, []);
return (
<Modal open={true} disableEscapeKeyDown keepMounted>
<Box
sx={{
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: '90%',
maxWidth: '1200px',
height: '600px',
maxHeight: '80vh',
overflow: 'auto',
boxShadow: 24,
borderRadius: '8px',
outline: 'none',
bgcolor: 'background.paper',
}}
>
<iframe
onLoad={getAddressFromWallet}
id="autoSignInFrame"
src={`${VITE_WALLET_IFRAME_URL}/auto-sign-in`}
width="100%"
height="100%"
sandbox="allow-scripts allow-same-origin"
className="border rounded-md shadow-sm"
></iframe>
</Box>
</Modal>
);
};
export default AutoSignInIFrameModal;

View File

@ -14,7 +14,7 @@ import { SERVER_GQL_PATH } from './constants';
import { Toaster } from 'components/shared/Toast';
import { LogErrorBoundary } from 'utils/log-error';
import { BASE_URL } from 'utils/constants';
import Web3ModalProvider from './context/Web3Provider';
// import Web3ModalProvider from './context/Web3Provider';
import './index.css';
console.log(`v-0.0.9`);
@ -32,12 +32,12 @@ root.render(
<LogErrorBoundary>
<React.StrictMode>
<ThemeProvider>
<Web3ModalProvider>
{/* <Web3ModalProvider> */}
<GQLClientProvider client={gqlClient}>
<App />
<Toaster />
</GQLClientProvider>
</Web3ModalProvider>
{/* </Web3ModalProvider> */}
</ThemeProvider>
</React.StrictMode>
</LogErrorBoundary>,

View File

@ -1,4 +1,5 @@
import { Login } from './auth/Login';
import AutoSignInIFrameModal from 'components/shared/auth/AutoSignInIFrameModal';
// import { Login } from './auth/Login';
const AuthPage = () => {
return (
@ -14,7 +15,7 @@ const AuthPage = () => {
</div>
<div className="pb-12 relative z-10 flex-1 flex-center">
<div className="max-w-[520px] w-full dark:bg-overlay bg-white rounded-xl shadow">
<Login />
<AutoSignInIFrameModal />
</div>
</div>
</div>