import './Login.css' ; import React , { useState } from 'react' ; import Web3 from 'web3' ; import { Auth } from '../types' ; interface Props { onLoggedIn : ( auth : Auth ) => void ; } let web3 = undefined ; export const Login = ( { onLoggedIn } ) : JSX . Element => { const [ loading , setLoading ] = useState ( false ) ; const handleAuthenticate = ( { publicAddress , signature , } ) => fetch ( `${ process . env . REACT_APP_BACKEND_URL }/auth` , { body : JSON . stringify ( { publicAddress , signature } ) , headers : { 'Content-Type' : 'application/json' , } , method : 'POST' , } ) . then ( ( response ) => response . json ( ) ) ; const handleSignMessage = async ( { publicAddress , nonce , } ) => { try { const signature = await web3 ! . eth . personal . sign ( `I am signing my one-time nonce: ${ nonce }` , publicAddress , '' ) ; return { publicAddress , signature } ; } catch ( err ) { throw new Error ( 'You need to sign the message to be able to log in.' ) ; } } ; const handleSignup = ( publicAddress ) => fetch ( `${ process . env . REACT_APP_BACKEND_URL }/users` , { body : JSON . stringify ( { publicAddress } ) , headers : { 'Content-Type' : 'application/json' , } , method : 'POST' , } ) . then ( ( response ) => response . json ( ) ) ; const handleClick = async ( ) => { if ( ! ( window as any ) . ethereum ) { window . alert ( 'Please install MetaMask first.' ) ; return ; } if ( ! web3 ) { try { await ( window as any ) . ethereum . enable ( ) ; web3 = new Web3 ( ( window as any ) . ethereum ) ; } catch ( error ) { window . alert ( 'You need to allow MetaMask.' ) ; return ; } } const coinbase = await web3 . eth . getCoinbase ( ) ; if ( ! coinbase ) { window . alert ( 'Please activate MetaMask first.' ) ; return ; } const publicAddress = coinbase . toLowerCase ( ) ; setLoading ( true ) ; fetch ( `${ process . env . REACT_APP_BACKEND_URL }/users?publicAddress=${ publicAddress }` ) . then ( ( response ) => response . json ( ) ) . then ( ( users ) => users . length ? users [ 0 ] : handleSignup ( publicAddress ) ) . then ( handleSignMessage ) . then ( handleAuthenticate ) . then ( onLoggedIn ) . catch ( ( err ) => { window . alert ( err ) ; setLoading ( false ) ; } ) ; } ; return ( < div > < p > Please select your login method . < br / > For the purpose of this demo , only MetaMask login is implemented . < /p> < button className = "Login-button Login-mm" onClick = { handleClick } > { loading ? 'Loading...' : 'Login with MetaMask' } < /button> < button className = "Login-button Login-fb" disabled > Login with Facebook < /button> < button className = "Login-button Login-email" disabled > Login with Email < /button> < /div>); } ;