0

I have an async function outside of my react component which retrieves 2 token balances from 2 addresses. I want to render out the balances of the 2 addresses, in the commented out HTML lines. Specifically linkBalance and balance. The useContext hook I think maybe I could solve my problem using context but I'm not sure.

import { ethers } from 'ethers'
const { ethereum } = window


const provider = new ethers.providers.Web3Provider(window.ethereum);
const linkAddress = '0xa36085F69e2889c224210F603D836748e7dC0088'
const linkABI = require('../constants/erc20.json')
const linkContract = new ethers.Contract(linkAddress, linkABI, provider);

(async() => {
    const accounts = await ethereum.request({ method: 'eth_accounts' })
    const account = accounts[0]
    const balance = await provider.getBalance(account)
    console.log(ethers.utils.formatUnits(balance, 18))
    const linkBalance = await linkContract.balanceOf(contractAddress)
    console.log(ethers.utils.formatUnits(linkBalance, 18))
})()


const Main = () => {

    const { connectWallet, currentAccount } = useContext(PackPlayersContext)

    return(
        <>
            <div>
                {currentAccount && (<p>Current Address: {currentAccount}</p>)}
                {!currentAccount && (
                    <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" onClick={connectWallet}>Connect Wallet</button>
                )}

                <input className="shadow appearance-none border rounded w-half py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="username" type="text" placeholder="Price"/>
                <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded mb-4 mt-4">Buy Pack</button>

            {/* 
            <div>
                <p>Current link balance of contract: {linkBalance}</p>
                <p>Your KETH balance: {balance}</p>
            </div>
            */}
            </div>
        </>
    )
}
export default Main
Mario Petrovic
  • 7,500
  • 14
  • 42
  • 62
  • 1
    Any reason why the async function has to be outside the react component? – wxker Jan 07 '22 at 00:41
  • 1
    you can either pass data into a component as [props](https://reactjs.org/docs/components-and-props.html) or use something like [redux](https://react-redux.js.org/introduction/getting-started) to handle a data store. – about14sheep Jan 07 '22 at 00:42
  • 1
    why are you setting your async function outside the component? I assume you wanna run your function before rendering your component, if that's the case you should use the useEffect hook to do it. – vbotio Jan 07 '22 at 00:48
  • 1
    You can cheat and define variables like this, window.newvariable = "hello"; and all functions can see this scoped at the highest level. – BGPHiJACK Jan 07 '22 at 00:58
  • I seem to have solved the issue, take a look below, I'm not sure if I did it in the most efficient way possible. – Arslan Amir Jan 07 '22 at 02:12

1 Answers1

0

I have returned victorious.

I create a separate file to place my async function, and use it as a context provider, in that context provider I updated a state which holds my token balances. I then passed in as context to my html.

Here is the context file

import React, { useState, useEffect} from 'react'
import { contractAddress } from '../constants/constants'
import { ethers } from 'ethers'
const { ethereum } = window

export const BalancesContext = React.createContext()

const provider = new ethers.providers.Web3Provider(window.ethereum);
const linkAddress = '0xa36085F69e2889c224210F603D836748e7dC0088'
const linkABI = require('../constants/erc20.json')
const linkContract = new ethers.Contract(linkAddress, linkABI, provider);


export const BalancesProvider = ({ children }) => {
    const[currentLinkBalance, setCurrentLinkBalance] = useState()
    const[currentKethBalance, setCurrentKethBalance] = useState()

    const getBalances = async () => {
        const accounts = await ethereum.request({ method: 'eth_accounts' })
        const account = accounts[0]
        const balance = await provider.getBalance(account)
        console.log(ethers.utils.formatUnits(balance, 18))
        setCurrentKethBalance(ethers.utils.formatUnits(balance, 18))
        const linkBalance = await linkContract.balanceOf(contractAddress)
        console.log(ethers.utils.formatUnits(linkBalance, 18))
        setCurrentLinkBalance(ethers.utils.formatUnits(linkBalance, 18))
    }

    useEffect(() => {
        getBalances()
    }, [])

    return (
        <BalancesContext.Provider value ={{ currentLinkBalance, currentKethBalance }}>
            {children}
        </BalancesContext.Provider>
    )
}

And here is the new Main component

import { PackPlayersContext } from "../context/PackPlayersContext"
import React, { useContext, useState } from 'react'
import { BalancesContext } from "../context/BalancesContext"

const Main = () => {
    const { connectWallet, currentAccount } = useContext(PackPlayersContext)
    const { currentLinkBalance, currentKethBalance } = useContext(BalancesContext)

    return(
        <>
            <div>
                {currentAccount && (<p>Current Address: {currentAccount}</p>)}
                {!currentAccount && (
                    <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" onClick={connectWallet}>Connect Wallet</button>
                )}

                <input className="shadow appearance-none border rounded w-half py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="username" type="text" placeholder="Price"/>
                <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded mb-4 mt-4">Buy Pack</button>
            <div>
                <p>Current link balance of contract: {currentLinkBalance}</p>
                <p>Your KETH balance: {currentKethBalance}</p>
            </div>
            </div>
        </>
    )
}
export default Main

Thank you all for your help and suggestions. Lastly, I'm new to react and js so I honestly have no idea if this was a stupid way to do it but it works correctly. But, I'm always open to learning best practices so please comment if anything is done wrong or stupidly.