2

this is my first post here. I have spent the requisite day+ on my own trying all I know with my limited abilities at present, but all to no avail. I come here seeking aid with the following issue then:

I have finished a web3 development site. Everything is good to go except actually making the transactions submit to the blockchain when I click the 'send payment' button. To do that part I was following this tutorial: https://www.youtube.com/watch?v=Wn_Kb3MR_cU. That tutorial uses React however, I am using NextJS.

I have been using ethers but went so far as to completely go another route using web3 and detectEthereumProvider npm package.

I have console logged and seen that I am in fact getting a provider and a contract, everything seems to be working, however every time I click the little blue payment button I get the same deflating response - Error: No Ethereum Object!

Please help me to get this last piece of my puzzle in place, it is quite a keystone as it turns out.

My code is below, with unnecessary filler removed such as unrelated UI imports, tailwinds CSS classes, ect. Thank you very much for helping me and taking the time out of your busy day's (or nights). I look forward to becoming an active member of this community.

I KNOW that the window object is not available on NextJS - I am using NextJS so please keep that in mind with any assistance given and thank you very much again and apologies if my code here looks busted/ugly!!!

import { createContext, useEffect, useState } from "react";
import {ethers} from 'ethers'
import { contractABI, contractAddress } from "@utils/constants";

export const TransactionContext = createContext()

const getEthereumContract = () => {
    const provider = new ethers.providers.Web3Provider(window.ethereum)
    console.log(ethereum);
    const signer = provider.getSigner()
    const transactionContract = new ethers.Contract(contractAddress, contractABI, signer)

    return transactionContract    
}

export const TransactionProvider = ({children}) => {
    const [currentAccount, setCurrentAccount] = useState("");
    const [formData, setFormData] = useState({
        addressTo: "",
        amount: "",
        message: ""
    })

    const [isLoading1, setIsLoading1] = useState(false)
    const [transactionCount, setTransactionCount] = useState(0)

    const handleChange = (e, name) => {
        setFormData((prevState) => ({
            ...prevState,
             [name]:e.target.value }))
    }
    
    useEffect(() => {
        if(typeof window.ethereum !== 'undefined' || (typeof window.web3 !== "undefined")){
            const {ethereum} = window
        }
     },[])

     const checkIfWalletIsConnected = async () => {
     try {
        if(!ethereum) return alert("You must install MetaMask.")
        const accounts = await ethereum.request({method: 'eth_accounts'})
        
        if(accounts.length){
            setCurrentAccount(accounts[0])
            
        }

        //get all TXs
     } catch (error) {
         throw new Error("No ethereum object!")
     }

     }

     const sendTransaction1 = async () => {
         try {
            if(!ethereum) return alert("You must install MetaMask.")
            const { addressTo, amount, message} = formData
            const transactionContract = getEthereumContract()
            const parsedAmount = ethers.utils.parseEther(amount)

            await ethereum.request({
                method: 'eth_sendTransaction', 
                params: [{
                    from: currentAccount,
                    to: addressTo, 
                    gas: '0x5208',//hex form
                    value: parsedAmount._hex, 
                }]
            })

            const transactionHash = await transactionContract.addToBlockchain(addressTo, parsedAmount, message)

            setIsLoading1(true)
            console.log(`Loading ${transactionHash.hash}`);
            await transactionHash.wait()
            setIsLoading1(false)
            console.log(`Success ${transactionHash.hash}`);

            const transactionCount = await transactionContract.getTransactionCount()
            setTransactionCount(transactionCount.toNumber())
       
         } catch (error) {
            throw new Error("No ethereum object!")

         }
     }

     useEffect(()=>{
         checkIfWalletIsConnected()
     },[])
    return (

    <TransactionContext.Provider value={{formData, setFormData, handleChange, sendTransaction1}}>
        {children}
    </TransactionContext.Provider>
    )
}

That is all the relevant code from the TransactionContext.jsx file. Now you can see the code inside the Hero.jsx where I am importing the context values and trying to use them along with the button and handleSubmit function shown below:

import { useContext, useState} from 'react'
import { TransactionContext } from '@components/providers/TransactionContext'

    const Hero = () => {
        const {formData, sendTransaction1, handleChange} = useContext(TransactionContext)

        const handleSubmit = (e) => {
            const { addressTo, amount} = formData
            e.preventDefault()
            if(!addressTo || !amount ) return 
            console.log("Hello");
            sendTransaction1()

    return (
 <ButtonSend
                          
                          disabled={formState.isDisabled}
                          type="button"
                          onClick={handleSubmit}                   
                         >
                         Send Now
                           
                         </ButtonSend>
)
        }
}

That is all of the code - now you can view the live website to see the issue in real time as well - Where to see the problem bodiaugustus.com

If for any reason the inputs are needed please let me know and I will redit this posting.

1 Answer 1

0

Actually, it is possible to access the ethereum object from the window object from inside a useEffect hook, but your conditional statement is validating as true before ethereum has been injected since there is no web3 property for window which would evaluate to true when ! compared to undefined. Also, you aren't setting ethereum to a component level scoped state variable so it wouldn't be accessible in your other functions anyway.

1
  • Hello Oatrick, thank you very much for your response, I do greatly appreciate it. Would you be willing to perhaps elucidate further upon a few of your points? The conditional statement was used from reading a stack overflow response, would it be best to remove it or change it? I understand what you say, I thought the same - Ethereum is not getting enough time to load. So, I get that once I get it called I should hold its value in a new state. I'm just confused how to call it.. I would greatly appreciate any further help but regardless thank you very much for the time you put in already. Commented Jan 22, 2022 at 23:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.