I getting this error, when calling multiple function at same timeā¦ some time if once executed code is not completedā¦ How can i handle this?
If i am trying to use try catch - i am getting this error
Error: Missing web3 instance, make sure to call Moralis.enableWeb3() or Moralis.authenticate()
As mentioned, make sure you call Moralis.enableWeb3()
or with an authenticated user authenticating Moralis.authenticate()
.
Do you have code snippet of where you are calling enableWeb3?
Hi i have created a class where i am writing all web3 execution code that named web3Services.js, and another page index.js in click item i am calling one of my function Buy itemā¦
so my web3Services Code is like thisā¦remember this is master codeā¦i want my developer call from hereā¦
case :- sometime ā¦user is already connected their wallet with my app and sometime they are not connectedā¦ and trying to call buy function directlyā¦so i want that time connect first and execute next code,ā¦
import { ethers } from "ethers";
export const Moralis = require('moralis');
/*
* You can write all web3 based call here
* so, no need to rewrite in every page, like mint function
*/
export class Web3Service {
/*
// Better practice to use this thing from .env, find solution
CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS
SIGNER_KEY = process.env.PRIVATE_KEY
CHAIN_ID = process.env.CHAIN_ID
*/
CONTRACT_ADDRESS = "XXXXXX"
PRIVATE_KEY = "XXXXXX"
CHAIN_ID = 4
CHAIN_HASH = "0x4"
//Connected User Data
getWei = async (price) => {
return Moralis.Units.ETH(price, 18)
}
enableWeb3 = async () => {
try{
await Moralis.enableWeb3();
} catch(err){
console.error("Error enableWeb3", err)
}
}
//check if web3 is enable, either enable it
//Call this function always
isWeb3Enable = async () => {
if(Moralis.isWeb3Enabled() == false) {
try{
await Moralis.enableWeb3();
} catch(err){
console.error("Error isWeb3Enable", err)
}
}
}
//return connected user and chain id
getWallet = async (providerName="metamask", verifyChain=false) => {
try {
if(verifyChain){
await this.verifyChain()
}
const web3Provider = await Moralis.enableWeb3({ provider: providerName });
if(web3Provider.provider.constructor.name === "WalletConnectProvider"){
return [web3Provider.provider.accounts[0], ethers.utils.hexValue(web3Provider.provider.chainId), providerName]
}
return [web3Provider.provider.selectedAddress, web3Provider.provider.chainId, providerName]
} catch(err) {
console.error("Error getWallet: Web3 Initialization Execption", err)
return []
}
}
//return web3Provider
getChain = async () => {
try {
const chainId = await Moralis.chainId;
return chainId
} catch(err) {
console.error("Error getChain: Web3 Initialization Execption", err)
return null
}
}
verifyChain = async () => {
const chainId = await Moralis.chainId;
if(parseInt(chainId)!=this.CHAIN_ID){
await this.switchChain(this.CHAIN_HASH)
}
}
//return web3Provider
switchChain = async (chainId) => {
try {
await Moralis.switchNetwork(chainId);
return chainId
} catch(err) {
console.error("Error switchChain: Web3 Initialization Execption", err)
return chainId
}
}
//execute when user change acccount on metamask
metamaskAccountChange = async () => {
ethereum.on('accountsChanged', (accounts) => {
return accounts
});
return null
}
//execute when user change chain on metamask
metamaskChainChange = async () => {
ethereum.on('chainChanged', (chain) => {
return chain
});
return null
}
isMetamaskUnlocked = async () => {
ethereum._metamask.isUnlocked().then((res)=> {
console.log("is metamask connected: ", res)
return res
})
}
/*
* Return current gas price
*/
getGasPrice = async (provider="metamask") => {
const web3Provider = await Moralis.enableWeb3({ provider: provider });
return await web3Provider.getGasPrice();
}
//function to check if contract is approved to access token
// You can modify condition as per your need
isApprovedForAll = async (account, operator, provider = "metamask") => {
const ABI = [{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]
const readOptions = {
contractAddress: this.CONTRACT_ADDRESS,
chainId: this.CHAIN_ID,
functionName: "isApprovedForAll",
abi: ABI,
params: {
account: account,
operator: operator
}
};
await this.enableWeb3()
return await Moralis.executeFunction(readOptions);
}
//function to approve to access token
// You can modify condition as per your need
// if operator address is constant, no need to pass in argument, but declare here
setApprovalForAll = async (account, operator, approved = true, providerName = "metamask") => {
if(!this.isApprovedForAll(account, operator)){
const ABI = [{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"}]
const writeOptions = {
contractAddress: this.CONTRACT_ADDRESS,
chainId: this.CHAIN_ID,
functionName: "setApprovalForAll",
abi: ABI,
params: {
operator: operator,
approved: approved
}
};
const receipt = await Moralis.executeFunction(writeOptions)
await receipt.wait()
return receipt
} else {
return "already aproved"
}
}
getTokenNo = async (creator, amount, nonce, collectionId) => {
//first verify .. selected chain is as above define
const readOptions = {
contractAddress: this.CONTRACT_ADDRESS,
functionName: "genTokenHash",
abi: [{"inputs":[{"internalType":"address","name":"_creator","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_nonce","type":"uint256"},{"internalType":"string","name":"_collectionId","type":"string"}],"name":"genTokenHash","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],
params: {
_creator: creator,
_amount: amount,
_nonce: nonce,
_collectionId: collectionId
}
};
await this.enableWeb3()
const message = await Moralis.executeFunction(readOptions);
//console.log(message, "Token Details")
return message
}
//function to approve to access token
// You can modify condition as per your need
// if operator address is constant, no need to pass in argument, but declare here
buy = async (tokenNo, price, amount, buyer, seller, paytoken, nonce, tuple, trade_type, providerName = "metamask") => {
try{
const ABI = [{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_buyer","type":"address"},{"internalType":"address payable","name":"_seller","type":"address"},{"internalType":"address","name":"_pToken","type":"address"},{"internalType":"uint256","name":"_nonce","type":"uint256"},{"components":[{"internalType":"string","name":"tokenURI","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"collectionId","type":"string"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint256","name":"blockTime","type":"uint256"}],"internalType":"struct Marketplace.Token","name":"_token","type":"tuple"},{"internalType":"uint8","name":"_tradeType","type":"uint8"}],"name":"buyAndAccept","outputs":[],"stateMutability":"payable","type":"function"}];
const writeOptions = {
contractAddress: this.CONTRACT_ADDRESS,
functionName: "buyAndAccept",
abi: ABI,
params: {
_tokenId: tokenNo,
_price: price,
_amount: amount,
_buyer: buyer,
_seller: seller,
_pToken: paytoken,
_nonce: nonce, //read from db
_token: tuple,
_tradeType: trade_type
},
msgValue: paytoken != "0x0000000000000000000000000000000000000000"? 0: price * amount
};
await this.enableWeb3()
const tx = await Moralis.executeFunction(writeOptions);
console.log("Before wait: ", tx)
await tx.wait();
return [true, tx ]
} catch(err) {
return [false, err ]
}
}
}
My index.html code is like this
const buy = async () => {
//always call this first
//await web3Service.enableWeb3()
await connectWallet() //check here ..first trying to login
const paytoken = "0x0000000000000000000000000000000000000000"
const trade_type = 0
const price = await web3Service.getWei(0.001) //check here
const amount = 4
const seller = "xxxxxxxxxxxxxxxxxxx"
const buyer = wallet
const collectionId = "xxxxxxxxxxxxxxxxxx"
const nonce = new Date().getTime()
const tokenArr = await web3Service.getTokenNo(seller, amount, nonce, collectionId) //chjeck here
const tokenBlock = tokenArr[0]
const tokenTime = tokenArr[1]
const tokenNo = tokenArr[2]
const tuple = [
"https://gateway.ipfs.io/ipfs/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
amount,
collectionId,
seller,
tokenBlock,
tokenTime
]
web3Service.buy(tokenNo, price, amount, buyer, seller, paytoken, nonce, tuple, trade_type).then((res)=> {
if(res[0]){
console.log("transaction success", res[1])
setMsg(res[1])
} else {
console.error("transaction failed", res[1])
setMsg(res[1])
}
}).catch((err)=>{
console.error(err)
setMsg(err)
})
}
and login code is in index.html
const connectWallet = async () => {
await web3Service.enableWeb3()
web3Service.getWallet(selectedProvider).then(async (connection) => {
if(connection.length > 0){
setWallet(connection[0])
setChain(connection[1])
setProvider(connection[2])
setMsg(`Connect wallet address is ${connection[0]} & chain id ${connection[1]} & provider is ${connection[2]}`)
}
})
}
and this my useEffect
useEffect(() => {
//code to change account if
web3Service.metamaskAccountChange().then((res)=>{ setWallet(res) })
web3Service.metamaskChainChange().then((res)=>{ setChain(res) })
web3Service.isMetamaskUnlocked().then((res)=> {
if(provider === "metamask" && res === false){
disconnect()
}
});
}, [])
how can i manage code , so my frontend team can call these function directly on their codeā¦instead of wrting same thing everytimeā¦ i am getting these error - first
Error enableWeb3 Error: Cannot execute Moralis.enableWeb3(), as Moralis Moralis.enableWeb3() already has been called, but is not finished yet
second in same call
Uncaught (in promise) Error: Missing web3 instance, make sure to call Moralis.enableWeb3() or Moralis.authenticate()
if i have already calledā¦why is it asking for again execute that function???
You can check if web3 is enabled with Moralis.isWeb3Enabled()
before you enableWeb3
can you make a minimal code example that replicates this error?
I donāt know how to consistently replicate it
Minimal code, Okay check this
in index.js, i have written this on page load
step 1 - in page load
//some required code in page laod
useEffect(() => {
//code to change account if
web3Service.isWeb3Enable(); //here i have enable web3 instance
web3Service.metamaskAccountChange().then((res)=>{ setWallet(res) }) //this contains metamask docs code
web3Service.metamaskChainChange().then((res)=>{ setChain(res) }) //this contains metamask docs code
web3Service.isMetamaskUnlocked().then((res)=> {
if(provider === "metamask" && res === false){
disconnect()
}
});
}, [])
Now my isWeb3Enable code is
//check if web3 is enable, either enable it
//Call this function always
isWeb3Enable = async () => {
if(Moralis.isWeb3Enabled() == false) {
try{
await this.enableWeb3()
} catch(err){
console.error("Error isWeb3Enable", err)
}
}
}
Now i am calling buy functionā¦which execute
/*
* Here need to read data from database
*/
const buy = async () => {
//verify selected chain must be 0x4 in live 0x1
await web3Service.verifyChain()
//always call this first
//await web3Service.enableWeb3()
await connectWallet() //because i need connected user... below called buyer, useState wallet, so i will login
//write as per your need
const paytoken = "0x0000000000000000000000000000000000000000"
const trade_type = 0
const price = await web3Service.getWei(0.001)
const amount = 4
const seller = "0x00000000000000000000000000000000"
const buyer = wallet //value set on connectWallet
const collectionId = "00000000000000000000"
const nonce = new Date().getTime()
const tokenArr = await web3Service.getTokenNo(seller, amount, nonce, collectionId)
const tokenBlock = tokenArr[0]
const tokenTime = tokenArr[1]
const tokenNo = tokenArr[2]
const tuple = [
"https://gateway.ipfs.io/ipfs/00000000000000000000000000",
amount,
collectionId,
seller,
tokenBlock,
tokenTime
]
web3Service.buy(tokenNo, price, amount, buyer, seller, paytoken, nonce, tuple, trade_type).then((res)=> {
if(res[0]){
console.log("transaction success", res[1])
setMsg(`Success transaction no. is ${res[1]}}`)
} else {
console.error("transaction failed", res[1])
setMsg('Transaction is failed, retry.')
}
}).catch((err)=>{
console.error(err)
setMsg(err)
})
}
i need this connect wallet to verify or read connected user wallet addressā¦ this line ( await connectWallet()), inside this function, i am saving setWallet(āit returned wallet addressā)ā¦this address i have to pass to buyer variable aboveā¦
Step 2: web3Service.js
enableWeb3 = async () => {
await Moralis.enableWeb3();
}
//check if web3 is enable, either enable it
//Call this function always
isWeb3Enable = async () => {
if(Moralis.isWeb3Enabled() == false) {
try{
await this.enableWeb3()
} catch(err){
console.error("Error isWeb3Enable", err)
}
}
}
//to get connected user
//return connected user and chain id
getWallet = async (providerName="metamask", verifyChain=false) => {
try {
if(verifyChain){
await this.verifyChain()
}
const web3Provider = await Moralis.enableWeb3({ provider: providerName });
if(web3Provider.provider.constructor.name === "WalletConnectProvider"){
return [web3Provider.provider.accounts[0], ethers.utils.hexValue(web3Provider.provider.chainId), providerName]
}
return [web3Provider.provider.selectedAddress, web3Provider.provider.chainId, providerName]
} catch(err) {
console.error("Error getWallet: Web3 Initialization Execption", err)
return []
}
}
verifyChain = async () => {
const chainId = await Moralis.chainId;
if(parseInt(chainId)!=this.CHAIN_ID){
await this.switchChain(this.CHAIN_HASH)
}
}
//return web3Provider
switchChain = async (chainId) => {
try {
await Moralis.switchNetwork(chainId);
await this.enableWeb3() //need to call due to relogin after network change
return chainId
} catch(err) {
console.error("Error switchChain: Web3 Initialization Execption", err)
return chainId
}
}
//execute when user change acccount on metamask
metamaskAccountChange = async () => {
ethereum.on('accountsChanged', (accounts) => {
return accounts
});
return null
}
//execute when user change chain on metamask
metamaskChainChange = async () => {
ethereum.on('chainChanged', (chain) => {
return chain
});
return null
}
isMetamaskUnlocked = async () => {
ethereum._metamask.isUnlocked().then((res)=> {
console.log("is metamask connected: ", res)
return res
})
}
getTokenNo = async (creator, amount, nonce, collectionId) => {
//first verify .. selected chain is as above define
const readOptions = {
contractAddress: this.CONTRACT_ADDRESS,
functionName: "genTokenHash",
abi: [{"inputs":[{"internalType":"address","name":"_creator","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_nonce","type":"uint256"},{"internalType":"string","name":"_collectionId","type":"string"}],"name":"genTokenHash","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],
params: {
_creator: creator,
_amount: amount,
_nonce: nonce,
_collectionId: collectionId
}
};
const message = await Moralis.executeFunction(readOptions);
//console.log(message, "Token Details")
return message
}
//function to approve to access token
// You can modify condition as per your need
// if operator address is constant, no need to pass in argument, but declare here
buy = async (tokenNo, price, amount, buyer, seller, paytoken, nonce, tuple, trade_type, providerName = "metamask") => {
try{
const ABI = [{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_buyer","type":"address"},{"internalType":"address payable","name":"_seller","type":"address"},{"internalType":"address","name":"_pToken","type":"address"},{"internalType":"uint256","name":"_nonce","type":"uint256"},{"components":[{"internalType":"string","name":"tokenURI","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"collectionId","type":"string"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint256","name":"blockTime","type":"uint256"}],"internalType":"struct Marketplace.Token","name":"_token","type":"tuple"},{"internalType":"uint8","name":"_tradeType","type":"uint8"}],"name":"buyAndAccept","outputs":[],"stateMutability":"payable","type":"function"}];
const writeOptions = {
contractAddress: this.CONTRACT_ADDRESS,
functionName: "buyAndAccept",
abi: ABI,
params: {
_tokenId: tokenNo,
_price: price,
_amount: amount,
_buyer: buyer,
_seller: seller,
_pToken: paytoken,
_nonce: nonce, //read from db
_token: tuple,
_tradeType: trade_type
},
msgValue: paytoken != "0x0000000000000000000000000000000000000000"? 0: price * amount
};
const tx = await Moralis.executeFunction(writeOptions);
console.log("Before wait: ", tx)
await tx.wait();
return [true, tx.hash ]
} catch(err) {
return [false, err ]
}
}
i have removed enableWeb3ā¦so my first error in page loadā¦
Error isWeb3Enable Error: Cannot execute Moralis.enableWeb3(), as Moralis Moralis.enableWeb3() already has been called, but is not finished yet
same on buy also
in useEffect, ihave not used await withy web3Service.isWeb3Enable();ā¦becauseā¦i dont want to wait but run this on backgroundā¦ am i bad in react programming?..i have never faced this issues on angular and vanilla jsā¦
also i want to update hereā¦sometime buy function is workingā¦but if i will refresh and again execute buy,i will get enable web3 require based errorā¦you can see in login i am running web3ā¦
minimal codeā¦if i have to execute one function onlyā¦its working fineā¦
issue is only when i need to relogin or if i am calling web3Enable again as per requirements ā¦if i will write this code in one place so i can use this on every projectsā¦what in erc721 and erc1155 ā¦there is onlyā¦mint, transfer, approve is mostly used functionā¦ need to change only abi in every project
I think that this was solved in discord (by not making so many calls to enableWeb3 at the same time), do you still have issues?
Hi, I checkedā¦if i am writing enable web3 in page loadā¦it is working fineā¦but need to be write once onlyā¦so now in my codeā¦in use effectā¦i am writing this enable web3 ā¦and then only running other codesā¦
Sorry i am waiting for issue if again i will faceā¦ bcz i have already done code like thisā¦but i had faced no web3 enable issue ā¦ i am just checking when i had faced that errorā¦
it works fine now for you?
yesā¦its okay fr now