Estoy tratando de ejecutar un método desde mi contrato inteligente ubicado en la red de prueba de ropsten, pero me encuentro con el siguiente error en mi función getBalance():
Error de tiempo de ejecución no controlado TypeError: no se pueden leer las propiedades de undefined (leyendo 'métodos')
46 | async function getBalance() { > 47 | const tempBal = await window.contract.methods.balanceOf(account.data).call() | ^ 48 | setBalance(tempBal) 49 | }Conectando mi contrato:
export default function ConnectContract() { async function loadWeb3() { if (window.ethereum) { window.web3 = new Web3(window.ethereum) window.ethereum.enable() } } async function loadContract() { const tempContract = await new window.web3.eth.Contract(ABI, ContractAddress) return tempContract } async function load() { await loadWeb3(); window.contract = await loadContract(); } load(); }Actualmente las funciones se llaman así:
export default function Page() { ConnectContract(); getBalance(); }Otra forma en que lo llamé anteriormente que no dio como resultado el error indefinido fue mediante el uso de una función onClick dentro de un botón para obtener el saldo:
<div><button onClick={() => getBalance}>Get Balance</button></div>Sé que llamarlos así hace que se llame al método de función getBalance antes de que el contrato se conecte al sitio web, pero con el código actual, funciona después de la actualización de 1 página. Pero no he podido encontrar una solución para que se cargue el contrato, por lo que el método se define en el momento en que se llama a getBalance.
He intentado hacer la función onLoad y las funciones window.load() sin éxito. También intenté llamar a mi función ConnectContract en _app.js para cargarla cuando se inicia el sitio web, pero tampoco tuve éxito.
Tienes que llamar a la función loadWeb3 dentro del gancho useEffect . useEffect se utiliza para preparar el estado del componente cuando se monta. para realizar un seguimiento del estado, use useState hook
const [web3,setWeb3]=useState('') const [contract,setContract]=useState('') async function loadWeb3() { if (window.ethereum) { window.ethereum.enable() setWeb3(new Web3(window.ethereum)) } } // [] array means we want this useEffect code run only when the compoenent rerenders // Since loadWeb3 is async function, call it inside try/catch block useEffect(()=>{loadWeb3()},[])A continuación, debe preparar el contrato de la misma manera.
async function loadContract() { const tempContract = await new web3.eth.Contract(ABI, ContractAddress) setContract(tempContract) } También debe llamar a esto en useEffect pero esta vez sus dependencias son diferentes. Porque para conseguir el contrato, nos basamos en web3
// Since loadContract is async function, call it inside try/catch block useEffect(()=>{loadContract},[web3]) cuando el componente se procesa, primero useEffect se ejecutará y configurará web3 . Dado que web3 ha cambiado, el componente se volverá a representar de nuevo, se ejecutará este useEffect. Entonces, cuando su componente esté montado, tendrá web3 y un conjunto de contract para que pueda usarlos.
Su problema está en este código aquí mismo:
46 | async function getBalance() { > 47 | const tempBal = await window.contract.methods.balanceOf(account.data).call() | ^ 48 | setBalance(tempBal) 49 | }Supongo que el contrato de ventana no existe o no se carga antes de que se llame. Tal vez se lo llame en un lugar del servidor donde la ventana no existe o intente envolverlo en una función if para que verifique que existe antes de llamarlo