/kiwi-dApp

🥝 A training dApp project.

Primary LanguageTypeScript

Kiwi

Kiwi dApp

A training frontend project for Tailwindcss, Web3 and Metamask integrations.

forthebadge

Deploy your own

Deploy the example using Vercel

Deploy with Vercel

Demo

Click on the logo to test the demo deployed with Vercel

Code Notes

Web3 usage

This is the way web3 is instantiated.
Replace givenProvider by a custom RCP URI if needed.

import Web3 from "web3";

const web3 = new Web3(Web3.givenProvider);

Web3 Metamask setup

There are the main functions to setup for a minimal Metamask Onboarding.

  • Checking if the extension is installed
  • Connect the user
  • And get the accounts: address and balance

More documentation about Metamask Onboarding here.

const checkAccounts = async () => {
    //we use eth_accounts because it returns a list of addresses owned by us.
    if (typeof window !== undefined) {
      const mmAccounts = await window.ethereum.request({method: 'eth_accounts'});
      setAccounts(mmAccounts);
      dispatch({
        type: 'SET_ACCOUNTS',
        payload: {
          accounts: mmAccounts,
        },
      });
      await getBalance();
    } else {
      setAccounts(await []);
    }
};

//This will start the onboarding proccess
const onClickInstall = () => {
    //On this object we have startOnboarding which will start the onboarding process for our end user
    onboarding.startOnboarding();
};

//This will request a connection to Metamask and launch checkAccounts()
const onClickConnect = async () => {
    try {
      // Will open the MetaMask UI
      if (typeof window !== undefined) await window.ethereum.request({method: 'eth_requestAccounts'});
      await checkAccounts();
    } catch (error) {
      console.error(error);
    }
};

//This will provide the balances on accounts' update (via useEffect)
const getBalance = async () => {
    let address: any, wei, mmBalance;
    address = accounts[0];
    wei = promisify((cb: any) => web3.eth.getBalance(address, cb));
    try {
      mmBalance = web3.utils.fromWei(await wei as string, 'ether');
      setBalance(mmBalance);
    } catch (error) {
      console.log(error);
    }
};

useEffect(() => {
    if(accounts.length > 0 && typeof window !== undefined){
      (async function() {
        try {
          await getBalance();
        } catch (e) {
          console.error(e);
        }
      })();
    }
}, [accounts]);

promisify

Util function used to resolve and manage web3 Promises.

const promisify = (inner: any) =>
  new Promise((resolve, reject) =>
    inner((err: any, res: any) => {
      if (err) {
        reject(err);
      } else {
        resolve(res);
      }
    })
  );

window + nextJs turnaround

NextJs uses SSR and SSG. While serving the frontend, on the SSR phase, there is no window element, like on a client's browser.
Hence the turnaround.

if (typeof window !== undefined)

ERC20 token balances

Function to use o get balances for other ERC20 tokens on the connected wallet (where ERC20_JSON is the JSON interface).

async function checkERC20Amount(web3: any, userAddress: string, erc20Address: string) {
  const	erc20Json = new web3.eth.Contract(ERC20_JSON, erc20Address);
  const	balanceRightNow = await erc20Json.methods.balanceOf(userAddress).call().then((e: any) => e);
  return web3.utils.fromWei(balanceRightNow);
}

Dependencies

Next TypeScript Redux TailwindCSS web3 Metamask