-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor Web3Auth integration and Avatar component
- Loading branch information
1 parent
e02c11a
commit 2495fcb
Showing
5 changed files
with
172 additions
and
172 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,21 @@ | ||
import BoringAvatar from 'boring-avatars'; | ||
import type { AvatarComponent } from '@rainbow-me/rainbowkit'; | ||
import BoringAvatar from "boring-avatars"; | ||
import type { AvatarComponent } from "@rainbow-me/rainbowkit"; | ||
|
||
export const CustomAvatar: AvatarComponent = ({ address, ensImage, size }) => { | ||
return ensImage ? ( | ||
<img | ||
src={ensImage} | ||
alt='user' | ||
width={size} | ||
height={size} | ||
style={{ borderRadius: 999 }} | ||
/> | ||
) : ( | ||
<BoringAvatar | ||
size={size} | ||
name={address} | ||
variant='pixel' | ||
colors={['#92A1C6', '#146A7C', '#F0AB3D', '#C271B4', '#C20D90']} | ||
/> | ||
); | ||
return ensImage ? ( | ||
<img | ||
src={ensImage} | ||
alt="user" | ||
width={size} | ||
height={size} | ||
style={{ borderRadius: 999 }} | ||
/> | ||
) : ( | ||
<BoringAvatar | ||
size={size} | ||
name={address} | ||
variant="pixel" | ||
colors={["#92A1C6", "#146A7C", "#F0AB3D", "#C271B4", "#C20D90"]} | ||
/> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,94 +1,94 @@ | ||
import { | ||
getDefaultConfig, | ||
getDefaultWallets, | ||
RainbowKitProvider | ||
} from '@rainbow-me/rainbowkit'; | ||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; | ||
import type React from 'react'; | ||
import { cookieToInitialState, WagmiProvider } from 'wagmi'; | ||
import { polygon } from 'wagmi/chains'; | ||
import { iqTestnet } from '../lib/data/iqTestnet'; | ||
import { iqWikiTheme } from '../lib/data/rainbowKitTheme'; | ||
getDefaultConfig, | ||
getDefaultWallets, | ||
RainbowKitProvider, | ||
} from "@rainbow-me/rainbowkit"; | ||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; | ||
import type React from "react"; | ||
import { cookieToInitialState, WagmiProvider } from "wagmi"; | ||
import { polygon } from "wagmi/chains"; | ||
import { iqTestnet } from "../lib/data/iqTestnet"; | ||
import { iqWikiTheme } from "../lib/data/rainbowKitTheme"; | ||
import { | ||
rainbowWeb3AuthConnector, | ||
createWeb3AuthInstance | ||
} from '../lib/integrations/web3-auth-connector'; | ||
import { structuralSharing } from '@wagmi/core/query'; | ||
import { Web3AuthProvider } from './Web3AuthProvider'; | ||
rainbowWeb3AuthConnector, | ||
createWeb3AuthInstance, | ||
} from "../lib/integrations/web3-auth-connector"; | ||
import { structuralSharing } from "@wagmi/core/query"; | ||
import { Web3AuthProvider } from "./Web3AuthProvider"; | ||
|
||
if (!process.env.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID) { | ||
throw new Error('NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID is not set'); | ||
throw new Error("NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID is not set"); | ||
} | ||
if (!process.env.NEXT_PUBLIC_IS_PRODUCTION) { | ||
console.log('NEXT_PUBLIC_IS_PRODUCTION is not set'); | ||
console.log("NEXT_PUBLIC_IS_PRODUCTION is not set"); | ||
} | ||
|
||
const chain = | ||
process.env.NEXT_PUBLIC_IS_PRODUCTION === 'true' ? polygon : iqTestnet; | ||
process.env.NEXT_PUBLIC_IS_PRODUCTION === "true" ? polygon : iqTestnet; | ||
const web3AuthInstance = createWeb3AuthInstance(chain); | ||
|
||
export const defaultConfig = getDefaultConfig({ | ||
appName: 'IQ.Wiki AI Editor', | ||
projectId: process.env.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID, | ||
chains: [chain], | ||
wallets: [ | ||
...getDefaultWallets({ | ||
appName: 'IQ.Wiki AI Editor', | ||
projectId: process.env.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID | ||
}).wallets, | ||
{ | ||
groupName: 'More', | ||
wallets: [() => rainbowWeb3AuthConnector({ web3AuthInstance })] | ||
} | ||
], | ||
multiInjectedProviderDiscovery: false, | ||
ssr: true | ||
appName: "IQ.Wiki AI Editor", | ||
projectId: process.env.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID, | ||
chains: [chain], | ||
wallets: [ | ||
...getDefaultWallets({ | ||
appName: "IQ.Wiki AI Editor", | ||
projectId: process.env.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID, | ||
}).wallets, | ||
{ | ||
groupName: "More", | ||
wallets: [() => rainbowWeb3AuthConnector({ web3AuthInstance })], | ||
}, | ||
], | ||
multiInjectedProviderDiscovery: false, | ||
ssr: true, | ||
}); | ||
|
||
function makeQueryClient() { | ||
return new QueryClient({ | ||
defaultOptions: { | ||
queries: { | ||
// With SSR, we usually want to set some default staleTime | ||
// above 0 to avoid refetching immediately on the client | ||
staleTime: 60 * 1000, | ||
structuralSharing | ||
} | ||
} | ||
}); | ||
return new QueryClient({ | ||
defaultOptions: { | ||
queries: { | ||
// With SSR, we usually want to set some default staleTime | ||
// above 0 to avoid refetching immediately on the client | ||
staleTime: 60 * 1000, | ||
structuralSharing, | ||
}, | ||
}, | ||
}); | ||
} | ||
|
||
let browserQueryClient: QueryClient | undefined = undefined; | ||
|
||
function getQueryClient() { | ||
if (typeof window === 'undefined') { | ||
// Server: always make a new query client | ||
return makeQueryClient(); | ||
} | ||
// Browser: make a new query client if we don't already have one | ||
// This is very important so we don't re-make a new client if React | ||
// suspends during the initial render. This may not be needed if we | ||
// have a suspense boundary BELOW the creation of the query client | ||
if (!browserQueryClient) browserQueryClient = makeQueryClient(); | ||
return browserQueryClient; | ||
if (typeof window === "undefined") { | ||
// Server: always make a new query client | ||
return makeQueryClient(); | ||
} | ||
// Browser: make a new query client if we don't already have one | ||
// This is very important so we don't re-make a new client if React | ||
// suspends during the initial render. This may not be needed if we | ||
// have a suspense boundary BELOW the creation of the query client | ||
if (!browserQueryClient) browserQueryClient = makeQueryClient(); | ||
return browserQueryClient; | ||
} | ||
|
||
export function IqLoginProvider({ | ||
children, | ||
cookie | ||
children, | ||
cookie, | ||
}: Readonly<React.PropsWithChildren> & { cookie?: string }) { | ||
const queryClient = getQueryClient(); | ||
const initialStates = cookieToInitialState(defaultConfig, cookie); | ||
const queryClient = getQueryClient(); | ||
const initialStates = cookieToInitialState(defaultConfig, cookie); | ||
|
||
return ( | ||
<QueryClientProvider client={queryClient}> | ||
<WagmiProvider config={defaultConfig} initialState={initialStates}> | ||
<RainbowKitProvider theme={iqWikiTheme}> | ||
<Web3AuthProvider web3AuthInstance={web3AuthInstance}> | ||
{children} | ||
</Web3AuthProvider> | ||
</RainbowKitProvider> | ||
</WagmiProvider> | ||
</QueryClientProvider> | ||
); | ||
return ( | ||
<QueryClientProvider client={queryClient}> | ||
<WagmiProvider config={defaultConfig} initialState={initialStates}> | ||
<RainbowKitProvider theme={iqWikiTheme}> | ||
<Web3AuthProvider web3AuthInstance={web3AuthInstance}> | ||
{children} | ||
</Web3AuthProvider> | ||
</RainbowKitProvider> | ||
</WagmiProvider> | ||
</QueryClientProvider> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,31 @@ | ||
import { ConnectButton } from '@rainbow-me/rainbowkit'; | ||
import { SignTokenButton } from './SignTokenButton'; | ||
import { ConnectButton } from "@rainbow-me/rainbowkit"; | ||
import { SignTokenButton } from "./SignTokenButton"; | ||
|
||
interface LoginProps { | ||
title: string; | ||
description: string; | ||
handleRedirect?: () => void; | ||
title: string; | ||
description: string; | ||
handleRedirect?: () => void; | ||
} | ||
|
||
export const Login = ({ title, description, handleRedirect }: LoginProps) => { | ||
return ( | ||
<div className='grid min-h-[calc(100vh-250px)] place-items-center py-4 md:p-4'> | ||
<div className='max-w-xl w-full text-center'> | ||
<h1 className='mb-4 text-4xl font-bold'>{title}</h1> | ||
<p className='mb-8 text-lg text-gray-500 dark:text-alpha-900'> | ||
{description} | ||
</p> | ||
<div className='mt-8 rounded-md border bg-gray-100 dark:border-gray-500 dark:bg-gray-700'> | ||
<div className='flex flex-col items-center p-4'> | ||
<h2 className='mb-4 text-xl'>Step 1: Connect your wallet</h2> | ||
<ConnectButton showBalance /> | ||
</div> | ||
<div className='flex flex-col items-center border-t p-4 dark:border-gray-500'> | ||
<h2 className='mb-4 text-xl'>Step 2: Authenticate your wallet</h2> | ||
<SignTokenButton handleRedirect={() => handleRedirect?.()} /> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
return ( | ||
<div className="grid min-h-[calc(100vh-250px)] place-items-center py-4 md:p-4"> | ||
<div className="max-w-xl w-full text-center"> | ||
<h1 className="mb-4 text-4xl font-bold">{title}</h1> | ||
<p className="mb-8 text-lg text-gray-500 dark:text-alpha-900"> | ||
{description} | ||
</p> | ||
<div className="mt-8 rounded-md border bg-gray-100 dark:border-gray-500 dark:bg-gray-700"> | ||
<div className="flex flex-col items-center p-4"> | ||
<h2 className="mb-4 text-xl">Step 1: Connect your wallet</h2> | ||
<ConnectButton showBalance /> | ||
</div> | ||
<div className="flex flex-col items-center border-t p-4 dark:border-gray-500"> | ||
<h2 className="mb-4 text-xl">Step 2: Authenticate your wallet</h2> | ||
<SignTokenButton handleRedirect={() => handleRedirect?.()} /> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,46 +1,46 @@ | ||
import { useAccount } from 'wagmi'; | ||
import { useEffect } from 'react'; | ||
import { useAuth } from '../lib/hooks/useAuth'; | ||
import { useAccount } from "wagmi"; | ||
import { useEffect } from "react"; | ||
import { useAuth } from "../lib/hooks/useAuth"; | ||
|
||
interface SignTokenButtonProps { | ||
handleRedirect: () => void; | ||
handleTokenPass?: (token: string) => Promise<void>; | ||
handleRedirect: () => void; | ||
handleTokenPass?: (token: string) => Promise<void>; | ||
} | ||
|
||
export const SignTokenButton = ({ | ||
handleRedirect, | ||
handleTokenPass | ||
handleRedirect, | ||
handleTokenPass, | ||
}: SignTokenButtonProps) => { | ||
const { isConnected } = useAccount(); | ||
const { token, signToken, loading, error } = useAuth(); | ||
const { isConnected } = useAccount(); | ||
const { token, signToken, loading, error } = useAuth(); | ||
|
||
useEffect(() => { | ||
const handleEffect = async () => { | ||
if (token && isConnected) { | ||
await handleTokenPass?.(token); | ||
handleRedirect(); | ||
} | ||
}; | ||
handleEffect(); | ||
}, [handleRedirect, handleTokenPass, isConnected, token]); | ||
useEffect(() => { | ||
const handleEffect = async () => { | ||
if (token && isConnected) { | ||
await handleTokenPass?.(token); | ||
handleRedirect(); | ||
} | ||
}; | ||
handleEffect(); | ||
}, [handleRedirect, handleTokenPass, isConnected, token]); | ||
|
||
return token && isConnected ? ( | ||
<p className='w-full max-w-md rounded-[4px] bg-white dark:bg-[#2D3748] border-[1px] dark:border-gray-600 px-[14px] py-[8px] text-center text-[16px] font-bold text-gray-800 dark:text-alpha-900'> | ||
{error | ||
? 'Something went wrong. Please try again.' | ||
: loading | ||
? 'You should get a signature request from your wallet, Approve it to continue.' | ||
: 'You are logged in 🚀'} | ||
</p> | ||
) : ( | ||
<button | ||
type='button' | ||
disabled={!isConnected} | ||
className='w-[146px] justify-center rounded-[4px] px-[14px] py-[8px] text-[16px] font-bold shadow-sm duration-200 hover:scale-105 disabled:cursor-not-allowed disabled:bg-gray-300 disabled:text-gray-500 dark:disabled:bg-gray-500 dark:disabled:text-gray-400' | ||
onClick={signToken} | ||
aria-label='Sign Token' | ||
> | ||
Sign Token | ||
</button> | ||
); | ||
return token && isConnected ? ( | ||
<p className="w-full max-w-md rounded-[4px] bg-white dark:bg-[#2D3748] border-[1px] dark:border-gray-600 px-[14px] py-[8px] text-center text-[16px] font-bold text-gray-800 dark:text-alpha-900"> | ||
{error | ||
? "Something went wrong. Please try again." | ||
: loading | ||
? "You should get a signature request from your wallet, Approve it to continue." | ||
: "You are logged in 🚀"} | ||
</p> | ||
) : ( | ||
<button | ||
type="button" | ||
disabled={!isConnected} | ||
className="w-[146px] justify-center rounded-[4px] px-[14px] py-[8px] text-[16px] font-bold shadow-sm duration-200 hover:scale-105 disabled:cursor-not-allowed disabled:bg-gray-300 disabled:text-gray-500 dark:disabled:bg-gray-500 dark:disabled:text-gray-400" | ||
onClick={signToken} | ||
aria-label="Sign Token" | ||
> | ||
Sign Token | ||
</button> | ||
); | ||
}; |
Oops, something went wrong.