Skip to main content

Ethereum Component


Here we learn how to sign in to any application using Ethereum

Let's add the imports that we will need for our Ethereum component to function

Edit Ethereum.tsx

import { Payload as SIWPayload, SIWWeb3 } from "@web3auth/sign-in-with-web3";
import React, { useState } from "react";
import Swal from "sweetalert2";
import Web3 from "web3";
import styles from "../public/css/ethereum.module.css";
import EthereumLogo from "../public/ethereum-logo.png";

declare global {
interface Window {
ethereum: any;
web3: any;
}
}

const Ethereum: React.FC = () => {
return <></>;
};

export default Ethereum;

Define the variables that we require

...
const Ethereum: React.FC = () => {

// State variables
const [siwwMessage, setSiwwMessage] = useState<SIWWeb3|null>();
const [sign, setSignature] = useState("");
const [publicKey, setPublicKey] = useState("");
const [currentProvider, setProvider] = useState<any>();

// Domain and origin
const domain = window.location.host;
const origin = window.location.origin;
let statement = "Sign in with Ethereum to the app.";

}

Writing code to detect the current providers

const Ethereum: React.FC = () => {

...
...

// Function that detects the current provider
const detectCurrentProvider = () => {
let provider;
if (window.ethereum) {
provider = window.ethereum;
} else if (window.web3) {
provider = window.web3.currentProvider;
} else {
console.log("Non-Ethereum browser detected. You should consider trying MetaMask!");
}
return provider;
};

};

Let's write the function to connect the wallet to the app

const Ethereum: React.FC = () => {

...
...

async function connectWallet() {
try {
setProvider(detectCurrentProvider());
if (currentProvider) {
if (currentProvider !== window.ethereum) {
Swal.fire(
'Non-Ethereum browser detected. You should consider trying MetaMask!'
);
}
await currentProvider.request({ method: 'eth_requestAccounts' });
const web3 = new Web3(currentProvider);
const userAccount = await web3.eth.getAccounts();
if (userAccount.length === 0) {
console.log('Please connect to meta mask');
} else {
setPublicKey(userAccount[0])
}
}
} catch (err) {
console.log(
'There was an error fetching your accounts. Make sure your Ethereum client is configured correctly.'
);
}
}
}

Now we need to write the function that creates the SIWWeb3 Message and perform the signing

const Ethereum: React.FC = () => {

...
...

// Generate a message for signing
// The nonce is generated on the server side
function createEthereumMessage() {
const payload = new SIWPayload();
payload.domain = domain;
payload.address = publicKey;
payload.uri = origin;
payload.statement = statement;
payload.version = "1";
payload.chainId = 1;
const header = {
t : "eip191"
};
const network = "ethereum"
let message = new SIWWeb3({ header, payload ,network});
setSiwwMessage(message);
const messageText = message.prepareMessage();
const web3 = new Web3(currentProvider);

web3.eth.personal.sign(messageText, publicKey, "", (err, result) => {
if (err) {
console.log(err);
} else {
setSignature(result);
}
});
}
}

Now we have all the functions that we need. Let's add the jsx code and render the application frontend.

const Ethereum: React.FC = () => {

...
...

return (
<>
{publicKey!="" &&
sign == "" &&
<span>
<p className={styles.center}>Sign Transaction</p>
<input className={styles.publicKey} type="text" id="publicKey" value={publicKey} />
<button className={styles.web3auth} id='w3aBtn' onClick={createEthereumMessage} > Sign In With Ethereum</button>
</span>
}
{
publicKey == "" &&
sign=="" &&
<div>
<div className={styles.wrapper}>
<img className={styles.ethereumlogo} src={EthereumLogo} />
</div>
<p className={styles.sign}>Sign in With Ethereum</p>
<button className={styles.web3auth} id='w3aBtn' onClick={connectWallet} >Connect Wallet</button>
</div>
}

{
sign &&
<>
<p className={styles.center}>Verify Signature</p>
<input className={styles.signature} type="text" id="signature" value={sign} onChange={ e=> setSignature(e.target.value)} />
<button className={styles.web3auth} id='verify' onClick={e => {
const signature = {
t: "eip191",
s: sign
}
const payload = siwwMessage!.payload;
siwwMessage!.verify(payload, signature).then((resp: any) => {
if (resp.success == true) {
Swal.fire("Success","Signature Verified","success")
} else {
Swal.fire("Error",resp.error!.type,"error")
}
});
}}>Verify</button>
<button className={styles.web3auth} id='verify' onClick={e => {
setSiwwMessage(null);
setSignature("")
}}>Back to Wallet</button>
</>
}

</>
);
}

Full code available here

Let's run the application now :-

npm start

Let's add that the Solana component