Search code examples
reactjsnext.jsethereumsmartcontractsethers.js

How to use ethers.js-JsonRpcProvider with Next.js to retrieve onchain data?


I'm trying to read some on-chain data with ethers.js JsonRpcProvider. I'm calling it with an Alchemy key, stored in a .env file.

edit : Making this variable only visible to server side is intentionnal, because I do not want to share this "sensible" information. Maybe it's not the right way to do this, I don't know...

I can't load my data on the client side, but on the server side, everything seems fine :/

What I'm doing wrong?

// ALCHEMY_API_KEY_URL is in .env file
const passiveProvider = new ethers.providers.JsonRpcProvider(process.env.ALCHEMY_API_KEY_URL)

// everything's fine on server side
console.log(passiveProvider)

const whiteListContract = new ethers.Contract(WHITELIST_CONTRACT_ADDRESS, abi, passiveProvider)

export default function Home() {
    const [value, setValue] = React.useState("")

    React.useEffect(() => {
        async function getNumAddressesWhitelisted(contract) {
            try {
                // we're in useEffect, client-side, nothing works here :/
                
                // dunno if this executes
                const clientTx = await contract.numAddressesWhitelisted()

                console.log("numAddressesWhitelisted : ", clientTx)
                setValue(clientTx)
            } catch (err) {
                // we drop here each time
                console.log("there is an error ! ",err)
                // error message dropped :
                // there is an error !  Error: could not detect network (event="noNetwork", code=NETWORK_ERROR, version=providers/5.7.0)
                //    at Logger.makeError (index.js?dd68:224:1)
                //    at Logger.throwError (index.js?dd68:233:1)
                //    at JsonRpcProvider.eval (json-rpc-provider.js?8679:442:1)
                //    at Generator.throw (<anonymous>)
                //    at rejected (json-rpc-provider.js?8679:6:42)
            }

        }
        getNumAddressesWhitelisted(whiteListContract)
    }, [])

    return (
        <div>
            {value}
        </div>
    )
}

Solution

  • Ok, I think I've figured out a righter/cleaner way to do this by far :

    I needed getServerSideProps. getServerSideProps can only exist in a next.js page, executes code on server side only, and returns props passed to the page.

    The logs appears only on server side too, as expected :

    export async function getServerSideProps() {
        // ALCHEMY_API_KEY_URL is defined in .env file, it's visible only from server side
        const passiveProvider = new ethers.providers.JsonRpcProvider(process.env.ALCHEMY_API_KEY_URL)
        console.log("passive provider : ", passiveProvider)
        const whiteListContract = new ethers.Contract(WHITELIST_CONTRACT_ADDRESS, abi, passiveProvider)
        const clientTx = await whiteListContract.numAddressesWhitelisted()
        console.log("numAddressesWhitelisted : ", clientTx)
    
        return { props: { clientTx } }
    }
    
    export default function Home({ clientTx }) {
    
        return (
            <div>
                {clientTx}
            </div>
        )
    }