mirror of
https://github.com/MetaFam/TheGame.git
synced 2026-04-24 03:00:09 -04:00
* feat: metamask switch network support + fixed dependancy cycle * feat: moved landing to index * feat: updated favicon * fix: fixed landing page issues + scrollSnap * feat: join button * fix: fixed seed script with new prod schema * feat: join button redirects based on user creation date * fix: minor ui bug fixes * feat: connect to mainnet to continue with switch network on metamask * fix: uniform setup screens * fix: fixed XP on dashboard * feat: added start page * fix: fixed issues on landing page * fix: fixed minor issues on dashboard * fix: update idx profile in auth webhook for new players * fix: minor fixes in seed page * fix: player avatar & type * fix: incorporated review comments from @dysbulic & @vidvidvid * fix: more review comments
239 lines
5.5 KiB
TypeScript
239 lines
5.5 KiB
TypeScript
import { EthereumAuthProvider, ThreeIdConnect } from '@3id/connect';
|
|
import ThreeIdResolver from '@ceramicnetwork/3id-did-resolver';
|
|
import type { CeramicApi } from '@ceramicnetwork/common';
|
|
import { CeramicClient } from '@ceramicnetwork/http-client';
|
|
import { did, Maybe } from '@metafam/utils';
|
|
import { CONFIG } from 'config';
|
|
import { DID } from 'dids';
|
|
import { providers } from 'ethers';
|
|
import {
|
|
clearToken,
|
|
clearWalletConnect,
|
|
getTokenFromStore,
|
|
setTokenInStore,
|
|
} from 'lib/auth';
|
|
import { clearJotaiState } from 'lib/jotaiState';
|
|
import React, {
|
|
createContext,
|
|
useCallback,
|
|
useEffect,
|
|
useMemo,
|
|
useState,
|
|
} from 'react';
|
|
import { providerOptions } from 'utils/walletOptions';
|
|
import Web3Modal from 'web3modal';
|
|
|
|
export type Web3ContextType = {
|
|
provider: Maybe<providers.Web3Provider>;
|
|
ceramic: Maybe<CeramicApi>;
|
|
address: Maybe<string>;
|
|
chainId: Maybe<string>;
|
|
authToken: Maybe<string>;
|
|
connect: () => Promise<void>;
|
|
disconnect: () => void;
|
|
connecting: boolean;
|
|
connected: boolean;
|
|
isMetaMask: boolean;
|
|
};
|
|
|
|
export const Web3Context = createContext<Web3ContextType>({
|
|
provider: null,
|
|
ceramic: null,
|
|
address: null,
|
|
chainId: null,
|
|
authToken: null,
|
|
connect: async () => undefined,
|
|
disconnect: () => undefined,
|
|
connecting: false,
|
|
connected: false,
|
|
isMetaMask: false,
|
|
});
|
|
|
|
const [web3Modal, ceramic, threeIdConnect] =
|
|
typeof window === 'undefined'
|
|
? [null, null, null]
|
|
: [
|
|
new Web3Modal({
|
|
network: 'mainnet',
|
|
cacheProvider: true,
|
|
providerOptions,
|
|
}),
|
|
new CeramicClient(CONFIG.ceramicURL),
|
|
new ThreeIdConnect(CONFIG.ceramicNetwork),
|
|
];
|
|
|
|
export async function getExistingAuth(
|
|
ethersProvider: providers.Web3Provider,
|
|
connectedAddress: string,
|
|
): Promise<Maybe<string>> {
|
|
const token = getTokenFromStore();
|
|
if (!token) return null;
|
|
|
|
try {
|
|
await did.verifyToken(token, ethersProvider, connectedAddress);
|
|
return token;
|
|
} catch (e) {
|
|
clearToken();
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export async function authenticateWallet(
|
|
ethersProvider: providers.Web3Provider,
|
|
): Promise<string> {
|
|
const token = await did.createToken(ethersProvider);
|
|
setTokenInStore(token);
|
|
return token;
|
|
}
|
|
|
|
interface Web3ContextProviderOptions {
|
|
resetUrqlClient?: () => void;
|
|
}
|
|
|
|
type Web3State = {
|
|
wallet: Maybe<Web3Modal>;
|
|
provider: Maybe<providers.Web3Provider>;
|
|
address: Maybe<string>;
|
|
chainId: Maybe<string>;
|
|
authToken: Maybe<string>;
|
|
};
|
|
|
|
export const Web3ContextProvider: React.FC<Web3ContextProviderOptions> = ({
|
|
resetUrqlClient,
|
|
children,
|
|
}) => {
|
|
const [
|
|
{ wallet, provider, chainId, address, authToken },
|
|
setWeb3State,
|
|
] = useState<Web3State>({
|
|
wallet: null,
|
|
provider: null,
|
|
address: null,
|
|
chainId: null,
|
|
authToken: null,
|
|
});
|
|
const [connecting, setConnecting] = useState(!!web3Modal?.cachedProvider);
|
|
|
|
const connected = useMemo(
|
|
() =>
|
|
!!wallet &&
|
|
!!provider &&
|
|
!!address &&
|
|
!!chainId &&
|
|
!!authToken &&
|
|
!connecting,
|
|
[wallet, provider, address, authToken, chainId, connecting],
|
|
);
|
|
|
|
const disconnect = useCallback(() => {
|
|
if (web3Modal === null) return;
|
|
|
|
web3Modal.clearCachedProvider();
|
|
ceramic?.close();
|
|
clearWalletConnect();
|
|
clearToken();
|
|
clearJotaiState();
|
|
setWeb3State({
|
|
wallet: null,
|
|
provider: null,
|
|
address: null,
|
|
chainId: null,
|
|
authToken: null,
|
|
});
|
|
setConnecting(false);
|
|
resetUrqlClient?.();
|
|
}, [resetUrqlClient]);
|
|
|
|
const updateWeb3State = useCallback(
|
|
async (prov) => {
|
|
const web3Provider = new providers.Web3Provider(prov);
|
|
const addr = await web3Provider.getSigner().getAddress();
|
|
|
|
let token = await getExistingAuth(web3Provider, addr);
|
|
|
|
if (!token) {
|
|
token = await authenticateWallet(web3Provider);
|
|
}
|
|
|
|
const { chainId: networkId } = prov;
|
|
|
|
if (ceramic && threeIdConnect) {
|
|
const authProvider = new EthereumAuthProvider(prov, addr);
|
|
await threeIdConnect.connect(authProvider);
|
|
ceramic.did = new DID({
|
|
provider: threeIdConnect.getDidProvider(),
|
|
resolver: ThreeIdResolver.getResolver(ceramic),
|
|
});
|
|
}
|
|
|
|
setWeb3State({
|
|
wallet: prov,
|
|
provider: web3Provider,
|
|
chainId: networkId,
|
|
address: addr,
|
|
authToken: token,
|
|
});
|
|
|
|
resetUrqlClient?.();
|
|
},
|
|
[resetUrqlClient],
|
|
);
|
|
|
|
const connect = useCallback(async () => {
|
|
if (web3Modal == null) return;
|
|
|
|
setConnecting(true);
|
|
|
|
try {
|
|
const prov = await web3Modal.connect();
|
|
await updateWeb3State(prov);
|
|
|
|
prov.on('accountsChanged', () => {
|
|
disconnect();
|
|
window.location.reload();
|
|
});
|
|
prov.on('chainChanged', () => {
|
|
updateWeb3State(prov);
|
|
});
|
|
} catch (error) {
|
|
console.error('`connect` Error', error); // eslint-disable-line no-console
|
|
disconnect();
|
|
} finally {
|
|
setConnecting(false);
|
|
}
|
|
}, [disconnect, updateWeb3State]);
|
|
|
|
useEffect(() => {
|
|
if (web3Modal?.cachedProvider) {
|
|
connect();
|
|
}
|
|
}, [connect]);
|
|
|
|
const isMetaMask = useMemo(
|
|
() =>
|
|
typeof window !== 'undefined' &&
|
|
window.ethereum?.isMetaMask === true &&
|
|
provider?.connection?.url === 'metamask',
|
|
[provider],
|
|
);
|
|
|
|
return (
|
|
<Web3Context.Provider
|
|
value={{
|
|
provider,
|
|
ceramic,
|
|
connect,
|
|
disconnect,
|
|
connected,
|
|
connecting,
|
|
address,
|
|
authToken,
|
|
chainId,
|
|
isMetaMask,
|
|
}}
|
|
>
|
|
{children}
|
|
</Web3Context.Provider>
|
|
);
|
|
};
|