1+ import type { Identity } from '@graphprotocol/hypergraph' ;
12import { Auth } from '@graphprotocol/hypergraph-react' ;
2- import { usePrivy } from '@privy-io/react-auth' ;
3- import { Link , createLazyFileRoute } from '@tanstack/react-router' ;
3+ import { usePrivy , useWallets } from '@privy-io/react-auth' ;
4+ import { createLazyFileRoute , useRouter } from '@tanstack/react-router' ;
5+ import { Loader2 } from 'lucide-react' ;
6+ import { useEffect , useState } from 'react' ;
7+ import { createWalletClient , custom } from 'viem' ;
8+ import { mainnet } from 'viem/chains' ;
49
510import { Button } from '@/components/ui/button' ;
611import { availableAccounts } from '@/lib/availableAccounts' ;
@@ -10,52 +15,98 @@ export const Route = createLazyFileRoute('/login')({
1015} ) ;
1116
1217function Login ( ) {
13- const { ready, authenticated, login } = usePrivy ( ) ;
14- // Disable login when Privy is not ready or the user is already authenticated
15- const disableLogin = ! ready || ( ready && authenticated ) ;
16- const { setIdentityAndSessionToken, authenticated : graphAuthenticated } = Auth . useHypergraphAuth ( ) ;
18+ const { ready : privyReady , login : privyLogin , signMessage, authenticated : privyAuthenticated } = usePrivy ( ) ;
19+ const { ready : walletsReady , wallets } = useWallets ( ) ;
20+ const { setIdentityAndSessionToken, login : hypergraphLogin } = Auth . useHypergraphAuth ( ) ;
21+ const { navigate } = useRouter ( ) ;
22+ const [ hypergraphLoginStarted , setHypergraphLoginStarted ] = useState ( false ) ;
23+
24+ useEffect ( ( ) => {
25+ if (
26+ ! hypergraphLoginStarted && // avoid re-running the effect to often
27+ privyAuthenticated && // privy must be authenticated to run it
28+ walletsReady && // wallets must be ready to run it
29+ wallets . length > 0 // wallets must have at least one wallet to run it
30+ ) {
31+ setHypergraphLoginStarted ( true ) ;
32+ ( async ( ) => {
33+ try {
34+ const embeddedWallet = wallets . find ( ( wallet ) => wallet . walletClientType === 'privy' ) || wallets [ 0 ] ;
35+ const privyProvider = await embeddedWallet . getEthereumProvider ( ) ;
36+ const walletClient = createWalletClient ( {
37+ chain : mainnet ,
38+ transport : custom ( privyProvider ) ,
39+ } ) ;
40+
41+ const signer : Identity . Signer = {
42+ getAddress : async ( ) => {
43+ const [ address ] = await walletClient . getAddresses ( ) ;
44+ return address ;
45+ } ,
46+ signMessage : async ( message : string ) => {
47+ if ( embeddedWallet . walletClientType === 'privy' ) {
48+ const { signature } = await signMessage ( { message } ) ;
49+ return signature ;
50+ }
51+ const [ address ] = await walletClient . getAddresses ( ) ;
52+ return await walletClient . signMessage ( { account : address , message } ) ;
53+ } ,
54+ } ;
55+
56+ await hypergraphLogin ( signer ) ;
57+ navigate ( { to : '/' } ) ;
58+ } catch ( error ) {
59+ alert ( 'Failed to login' ) ;
60+ console . error ( error ) ;
61+ }
62+ } ) ( ) ;
63+ }
64+ } , [ hypergraphLoginStarted , walletsReady , wallets , signMessage , hypergraphLogin , navigate , privyAuthenticated ] ) ;
1765
1866 return (
1967 < div className = "flex flex-1 justify-center items-center flex-col gap-4" >
20- { ( ! ready || ! authenticated ) && ! graphAuthenticated ? (
68+ < div >
69+ < Button
70+ disabled = { ! privyReady || hypergraphLoginStarted }
71+ onClick = { ( event ) => {
72+ event . preventDefault ( ) ;
73+ privyLogin ( { } ) ;
74+ } }
75+ >
76+ Log in { hypergraphLoginStarted && < Loader2 className = "ml-2 w-4 h-4 animate-spin" /> }
77+ </ Button >
78+
2179 < div >
22- < Button disabled = { disableLogin } onClick = { login } >
23- Log in
80+ < h1 > Choose account</ h1 >
81+ < Button
82+ onClick = { ( event ) => {
83+ event . preventDefault ( ) ;
84+ setIdentityAndSessionToken ( availableAccounts [ 0 ] ) ;
85+ navigate ( { to : '/' } ) ;
86+ } }
87+ >
88+ { availableAccounts [ 0 ] . accountId . substring ( 0 , 6 ) }
89+ </ Button >
90+ < Button
91+ onClick = { ( event ) => {
92+ event . preventDefault ( ) ;
93+ setIdentityAndSessionToken ( availableAccounts [ 1 ] ) ;
94+ navigate ( { to : '/' } ) ;
95+ } }
96+ >
97+ { availableAccounts [ 1 ] . accountId . substring ( 0 , 6 ) }
98+ </ Button >
99+ < Button
100+ onClick = { ( event ) => {
101+ event . preventDefault ( ) ;
102+ setIdentityAndSessionToken ( availableAccounts [ 2 ] ) ;
103+ navigate ( { to : '/' } ) ;
104+ } }
105+ >
106+ { availableAccounts [ 2 ] . accountId . substring ( 0 , 6 ) }
24107 </ Button >
25-
26- < div >
27- < h1 > Choose account</ h1 >
28- < Button
29- onClick = { ( event ) => {
30- event . preventDefault ( ) ;
31- setIdentityAndSessionToken ( availableAccounts [ 0 ] ) ;
32- } }
33- >
34- { availableAccounts [ 0 ] . accountId . substring ( 0 , 6 ) }
35- </ Button >
36- < Button
37- onClick = { ( event ) => {
38- event . preventDefault ( ) ;
39- setIdentityAndSessionToken ( availableAccounts [ 1 ] ) ;
40- } }
41- >
42- { availableAccounts [ 1 ] . accountId . substring ( 0 , 6 ) }
43- </ Button >
44- < Button
45- onClick = { ( event ) => {
46- event . preventDefault ( ) ;
47- setIdentityAndSessionToken ( availableAccounts [ 2 ] ) ;
48- } }
49- >
50- { availableAccounts [ 2 ] . accountId . substring ( 0 , 6 ) }
51- </ Button >
52- </ div >
53108 </ div >
54- ) : (
55- < Link className = "text-blue-500 hover:text-blue-600 underline" to = "/" >
56- Go to Home
57- </ Link >
58- ) }
109+ </ div >
59110 </ div >
60111 ) ;
61112}
0 commit comments