snowballtools-base/packages/frontend/src/context/Web3ModalProvider.tsx
2024-02-26 16:57:49 -05:00

128 lines
3.2 KiB
TypeScript

import React, { ReactNode } from 'react';
import { SiweMessage } from 'siwe';
import { WagmiProvider } from 'wagmi';
import { arbitrum, mainnet } from 'wagmi/chains';
import axios from 'axios';
import { createWeb3Modal } from '@web3modal/wagmi/react';
import { defaultWagmiConfig } from '@web3modal/wagmi/react/config';
import { createSIWEConfig } from '@web3modal/siwe';
import type {
SIWECreateMessageArgs,
SIWEVerifyMessageArgs,
} from '@web3modal/core';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
const axiosInstance = axios.create({
baseURL: process.env.REACT_APP_SERVER_URL,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
withCredentials: true,
});
const metadata = {
name: 'Web3Modal',
description: 'Snowball Web3Modal',
url: window.location.origin,
icons: [
'https://raw.githubusercontent.com/snowball-tools/mediakit/main/assets/logo.svg',
],
};
const chains = [mainnet, arbitrum] as const;
const config = defaultWagmiConfig({
chains,
projectId: process.env.REACT_APP_WALLET_CONNECT_ID,
metadata,
});
const siweConfig = createSIWEConfig({
createMessage: ({ nonce, address, chainId }: SIWECreateMessageArgs) =>
new SiweMessage({
version: '1',
domain: window.location.host,
uri: window.location.origin,
address,
chainId,
nonce,
// Human-readable ASCII assertion that the user will sign, and it must not contain `\n`.
statement: 'Sign in With Ethereum.',
}).prepareMessage(),
getNonce: async () => {
const nonce = (await axiosInstance.get('/auth/nonce')).data;
if (!nonce) {
throw new Error('Failed to get nonce!');
}
return nonce;
},
getSession: async () => {
try {
const session = (await axiosInstance.get('/auth/session')).data;
const { address, chainId } = session;
return { address, chainId };
} catch (err) {
if (window.location.pathname !== '/login') {
window.location.href = '/login';
}
throw new Error('Failed to get session!');
}
},
verifyMessage: async ({ message, signature }: SIWEVerifyMessageArgs) => {
try {
const { success } = (
await axiosInstance.post('/auth/validate', {
message,
signature,
})
).data;
return success;
} catch (error) {
return false;
}
},
signOut: async () => {
try {
const { success } = (await axiosInstance.post('/auth/logout')).data;
return success;
} catch (error) {
return false;
}
},
onSignOut: () => {
window.location.href = '/login';
},
onSignIn: () => {
window.location.href = '/';
},
});
if (!process.env.REACT_APP_WALLET_CONNECT_ID) {
throw new Error('Error: REACT_APP_WALLET_CONNECT_ID env config is not set');
}
createWeb3Modal({
siweConfig,
wagmiConfig: config,
projectId: process.env.REACT_APP_WALLET_CONNECT_ID,
});
export default function Web3ModalProvider({
children,
}: {
children: ReactNode;
}) {
return (
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
</WagmiProvider>
);
}