snowballtools-base/packages/frontend/src/components/shared/auth/AutoSignInIFrameModal.tsx
2025-02-11 14:22:51 +05:30

155 lines
3.9 KiB
TypeScript

import { useCallback, useEffect, useState } from 'react';
import { generateNonce, SiweMessage } from 'siwe';
import axios from 'axios';
import { useNavigate } from 'react-router-dom';
import { Box, Modal } from '@mui/material';
import { BASE_URL, VITE_WALLET_IFRAME_URL } from 'utils/constants';
const axiosInstance = axios.create({
baseURL: BASE_URL,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
withCredentials: true,
});
const AutoSignInIFrameModal = () => {
const navigate = useNavigate();
const [accountAddress, setAccountAddress] = useState();
useEffect(() => {
const handleSignInResponse = async (event: MessageEvent) => {
if (event.origin !== VITE_WALLET_IFRAME_URL) return;
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 === true) {
navigate('/');
}
} catch (error) {
console.error('Error signing in:', error);
}
}
};
window.addEventListener('message', handleSignInResponse);
return () => {
window.removeEventListener('message', handleSignInResponse);
};
}, []);
useEffect(() => {
const initiateAutoSignIn = async () => {
if (!accountAddress) return;
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: accountAddress,
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,
);
};
initiateAutoSignIn();
}, [accountAddress]);
useEffect(() => {
const handleAccountsDataResponse = async (event: MessageEvent) => {
if (event.origin !== VITE_WALLET_IFRAME_URL) return;
if (event.data.type === 'WALLET_ACCOUNTS_DATA') {
setAccountAddress(event.data.data[0].address);
}
};
window.addEventListener('message', handleAccountsDataResponse);
return () => {
window.removeEventListener('message', handleAccountsDataResponse);
};
}, []);
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: 'REQUEST_CREATE_OR_GET_ACCOUNTS',
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',
outline: 'none',
}}
>
<iframe
onLoad={getAddressFromWallet}
id="autoSignInFrame"
src={`${VITE_WALLET_IFRAME_URL}/auto-sign-in`}
width="100%"
height="100%"
sandbox="allow-scripts allow-same-origin"
></iframe>
</Box>
</Modal>
);
};
export default AutoSignInIFrameModal;