Skip to content
Snippets Groups Projects
login.tsx 4.47 KiB
Newer Older
Niklas P's avatar
Niklas P committed
import { useState } from "react";
Niklas P's avatar
Niklas P committed

Niklas P's avatar
Niklas P committed
import { useSession, signIn, signOut, getCsrfToken } from "next-auth/react"
import AccountSelect from "./account-select";
Niklas P's avatar
Niklas P committed

Niklas P's avatar
Niklas P committed
import { useRouter } from "next/router";
Niklas P's avatar
Niklas P committed

Niklas P's avatar
Niklas P committed
import styles from '@/styles/Home.module.css'
import { Inter } from "next/font/google";
import Link from "next/link";
Niklas P's avatar
Niklas P committed
import { usePolkadotExtensionWithContext } from "@/context/polkadotExtensionContext";
Niklas P's avatar
Niklas P committed
const inter = Inter({ subsets: ['latin'] })
Niklas P's avatar
Niklas P committed

Niklas P's avatar
Niklas P committed
export default function LoginButton() {
Niklas P's avatar
Niklas P committed
  const router = useRouter()
  const [error, setError] = useState<string | undefined>(undefined)
  const [isLoading, setIsLoading] = useState( false )
Niklas P's avatar
Niklas P committed

Niklas P's avatar
Niklas P committed
  const { accounts, actingAccount, injector } = usePolkadotExtensionWithContext()
  // we can use web3FromSource which will return an InjectedExtension type
Niklas P's avatar
Niklas P committed

Niklas P's avatar
Niklas P committed
  const handleLogin = async () => {
    try {
      setIsLoading( true )
      let signature = ''
      const message = {
Niklas P's avatar
Niklas P committed
        domain: window.location.host,
Niklas P's avatar
Niklas P committed
        address: actingAccount?.address,
        statement: 'Sign in with polkadot extension to the example tokengated example dApp',
Niklas P's avatar
Niklas P committed
        uri: window.location.origin,
Niklas P's avatar
Niklas P committed
        version: '1',
        nonce: await getCsrfToken(),
      }
Niklas P's avatar
Niklas P committed

Niklas P's avatar
Niklas P committed
      const signRaw = injector?.signer?.signRaw;
Niklas P's avatar
Niklas P committed

Niklas P's avatar
Niklas P committed
      if (!!signRaw && !!actingAccount) {
          // after making sure that signRaw is defined
          // we can use it to sign our message
          const data = await signRaw({
            address: actingAccount.address,
            data: JSON.stringify(message),
            type: "bytes"
          });
Niklas P's avatar
Niklas P committed

Niklas P's avatar
Niklas P committed
          signature = data.signature
      }
Niklas P's avatar
Niklas P committed

Niklas P's avatar
Niklas P committed
      // will return a promise https://next-auth.js.org/getting-started/client#using-the-redirect-false-option
      const result = await signIn('credentials', {
        redirect: false,
Niklas P's avatar
Niklas P committed
        callbackUrl: '/protected-api',
Niklas P's avatar
Niklas P committed
        message: JSON.stringify(message),
        name: actingAccount?.meta?.name,
Niklas P's avatar
Niklas P committed
        signature,
        address: actingAccount?.address
      })
Niklas P's avatar
Niklas P committed

Niklas P's avatar
Niklas P committed
      // take the user to the protected page if they are allowed
Niklas P's avatar
Niklas P committed
      if(result?.url) {
Niklas P's avatar
Niklas P committed
        router.push("/protected-api");
Niklas P's avatar
Niklas P committed
      }
Niklas P's avatar
Niklas P committed

Niklas P's avatar
Niklas P committed
      setError( result?.error )
      setIsLoading( false )

Niklas P's avatar
Niklas P committed
    } catch (error) {
      setError( 'Cancelled Signature' )
      setIsLoading( false )
    }
  }

Niklas P's avatar
Niklas P committed
  const { data: session } = useSession()
Niklas P's avatar
Niklas P committed
  
Niklas P's avatar
Niklas P committed
  return (
    <>
Niklas P's avatar
Niklas P committed
      { accounts && accounts.length > 0 ?
Niklas P's avatar
Niklas P committed
      <>
Niklas P's avatar
Niklas P committed
        <div className={ styles.cardWrap }>
          <div className={ styles.dropDownWrap }>
            { ! session &&
Niklas P's avatar
Niklas P committed
              <AccountSelect/> 
Niklas P's avatar
Niklas P committed
            }
Niklas P's avatar
Niklas P committed
          </div>
Niklas P's avatar
Niklas P committed
          { session ?
            <>
              <Link
Niklas P's avatar
Niklas P committed
                href="/protected-api"
Niklas P's avatar
Niklas P committed
                className={styles.card}
              >
                <h2 className={inter.className}>
Niklas P's avatar
Niklas P committed
                  🎉 View Tokengated Route <span>-&gt;</span>
Niklas P's avatar
Niklas P committed
                </h2>
                <p className={inter.className}>
Niklas P's avatar
Niklas P committed
                  You passed the tokengate { session.user?.name }. You can now view the protected route.
Niklas P's avatar
Niklas P committed
                </p>
              </Link>
              <div
                role="button"
                onClick={() => signOut()}
                className={styles.card}
              >
                <h2 className={inter.className}>
                  Sign Out <span>-&gt;</span>
                </h2>
                <p className={inter.className}>
                  Click here to sign out your account { session.user?.name }.
                </p>
              </div>
            </>
Niklas P's avatar
Niklas P committed
              : 
Niklas P's avatar
Niklas P committed
              <div
                role="button"
                onClick={() => handleLogin()}
                className={styles.card}
              >
                <h2 className={inter.className}>
                  🔑 Let me in <span>-&gt;</span>
                </h2>
                <p className={inter.className}>
Niklas P's avatar
Niklas P committed
                  Click here to sign in with your selected account and check if 
Niklas P's avatar
Niklas P committed
                  you can view the tokengated content. <br></br>
                  You need &gt; 1 KSM free balance.
                </p>
              </div>
            }
          </div>
Niklas P's avatar
Niklas P committed
          { isLoading ? <>Signing In ...</> : <span className={ styles.error }> { error } </span> }
Niklas P's avatar
Niklas P committed
        </>
Niklas P's avatar
Niklas P committed
        : 
Niklas P's avatar
Niklas P committed
        <div className={ styles.walletInfo }>
          <p>Please <a className={ styles.colorA } href="https://polkadot.js.org/extension/">install a polkadot wallet browser extension</a> to test this dApp.</p>
Niklas P's avatar
Niklas P committed
          <p>If you have already installed it allow this application to access it.</p>
Niklas P's avatar
Niklas P committed
        </div>
      }
    </>
  )
Niklas P's avatar
Niklas P committed
}