0

I'm trying to build a blockchain NFT Marketplace app and two of the things I'm trying to do is getting the balance of tokens present from the user's account and finding the owner history for each of the NFT assets listed for sale or present within a user's inventory. However, in both cases, I get these two errors appearing on my inspect tool continuously without stopping:

Error 1:

Error fetching assets: Error: could not decode result data (value="0x", info={ "method": "getAllAssetIDs", "signature": "getAllAssetIDs()" }, code=BAD_DATA, version=6.13.1) makeError errors.ts:694 

Error 2:

SES_UNHANDLED_REJECTION: Error: could not decode result data (value="0x", info={ "method": "balanceOf", "signature": "balanceOf(address,uint256)" }, code=BAD_DATA, version=6.13.1) 

I am unsure what could be causing both issues, maybe I'm not handling the promise right but my Metamask processes the other transactions properly so it couldn't be how I've configured the address or network.

Here's the Marketplace.sol file containing my smart contracts.

// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; pragma experimental ABIEncoderV2; contract Marketplace is ERC1155 { uint256 private _assetTokenIDs; // non-fungible uint256 constant MONEY_TOKEN_ID = 0; // fungible uint256 public constant RATE = 1000; // number of money tokens per ether uint256 private _currentAssetID; struct Asset { string name; uint256 price; address owner; address[] ownerHistory; bool forSale; } mapping(uint256 => Asset) private _assets; constructor() ERC1155("") { _currentAssetID = 1; } . // other functions . . function getAssetHistory( uint256 assetID ) public view returns (address[] memory) { return _assets[assetID].ownerHistory; } function getAssetDetails( uint256 assetID ) public view returns (string memory, uint256, address, bool) { Asset storage asset = _assets[assetID]; return (asset.name, asset.price, asset.owner, asset.forSale); } function getAllAssetIDs() external view returns (uint256[] memory) { uint256[] memory assetIDs = new uint256[](_currentAssetID - 1); for (uint256 i = 1; i < _currentAssetID; i++) { assetIDs[i - 1] = i; } return assetIDs; } } 

The backend app.js file with the backend code:

require("dotenv").config(); const cors = require("cors"); const express = require("express"); const bodyParser = require("body-parser"); const { ethers } = require("ethers"); const MarketplaceABI = require("./artifacts/contracts/Marketplace.sol/Marketplace.json").abi; const app = express(); app.use(bodyParser.json()); const rpcUrl = process.env.PROVIDER_URL; const provider = new ethers.JsonRpcProvider(rpcUrl); const walletSigner = new ethers.Wallet(process.env.PRIVATE_KEY, provider); const contractAddress = require("./deployedAddress.json").address; const marketplace = new ethers.Contract(contractAddress, MarketplaceABI, walletSigner); app.use(cors()); app.use(express.json()); // Helper function to get signer based on the user address async function getAccountSigner(userAddress) { const accounts = await provider.listAccounts(); const matchingAccount = accounts.find(acc => acc.toLowerCase() === userAddress.toLowerCase()); if (!matchingAccount) { throw new Error("Account not found"); } return provider.getSigner(matchingAccount); } // other functions app.get("/asset-history/:assetID", async (req, res) => { try { const { assetID } = req.params; const history = await marketplace.getAssetHistory(assetID); res.send(history); } catch (error) { console.error(error); res.status(500).send({ error: error.message }); } }); app.get("/asset-details/:assetID", async (req, res) => { try { const { assetID } = req.params; const details = await marketplace.getAssetDetails(assetID); res.send(details); } catch (error) { console.error(error); res.status(500).send({ error: error.message }); } }); app.get("/all-asset-ids", async (req, res) => { try { const assetIDs = await marketplace.getAllAssetIDs(); const numberedAssets = assetIDs.map(id => Number(id)); res.send(numberedAssets); } catch (error) { console.error(error); res.status(500).send({ error: error.message }); } }); 

Here's my frontend jsx:

import MarketplaceABIJson from '../../artifacts/contracts/Marketplace.sol/Marketplace.json'; const MarketplaceABI = MarketplaceABIJson.abi; import contractAddressJson from "../../deployedAddress.json"; const contractAddress = contractAddressJson.address; function App() { const [isRegistered, setIsRegistered] = useState(false); const [provider, setProvider] = useState(null); const [signer, setSigner] = useState(null); const [contract, setContract] = useState(null); const [account, setAccount] = useState(''); const [balance, setBalance] = useState(0); const [myAssets, setMyAssets] = useState([]); const [availableAssets, setAvailableAssets] = useState([]); useEffect(() => { const init = async () => { if (typeof window.ethereum !== 'undefined') { const provider = new ethers.BrowserProvider(window.ethereum); const signer = await provider.getSigner(); const contract = new ethers.Contract(contractAddress, MarketplaceABI, signer); setProvider(provider); setSigner(signer); setContract(contract); const address = await signer.getAddress(); setAccount(address); await updateBalance(contract, address); await fetchAssets(contract, address); window.ethereum.on('accountsChanged', handleAccountChange); } }; const checkRegistration = async () => { if (contract && account) { const balance = await contract.balanceOf(account, 0); setIsRegistered(balance.gt(0)); } }; init(); checkRegistration(); return () => { window.ethereum.removeListener('accountsChanged', handleAccountChange); }; return () => clearInterval(intervalId); }, [contract, account]); const updateBalance = async (contract, address) => { if (contract && account) { try { const balance = await contract.balanceOf(address, 0); const formattedBalance = ethers.formatEther(balance); setBalance(formattedBalance); } catch (error) { console.error("Error fetching balance:", error); } } }; const fetchAssets = async (contract, address) => { try { // Fetch all asset IDs const assetIDs = await contract.getAllAssetIDs(); const myAssets = []; const availableAssets = []; for (let id of assetIDs) { const details = await contract.getAssetDetails(id); const history = await contract.getAssetHistory(id); const asset = { id: id.toString(), name: details[0], price: ethers.formatEther(details[1]), owner: details[2], forSale: details[3], ownerHistory: history }; if (asset.owner.toLowerCase() === address.toLowerCase()) { myAssets.push(asset); } else if (asset.forSale) { availableAssets.push(asset); } } setMyAssets(myAssets); setAvailableAssets(availableAssets); } catch (error) { console.error("Error fetching assets:", error); } }; 

My guess is that I'm mishandling the data coming into the frontend somehow, but I can't tell for sure beyond the mismanaged promise. Hope you can help.

3
  • As, you'd marked as accepted, but now you've marked it as unaccepted. So, I guess that it didn't solve your problem. Can you please describe by implementing the solution that I proposed, what are the issues that you're facing? Commented Aug 7, 2024 at 8:42
  • Yes, sorry if I've been unresponsive for a day or two. I've just been trying to understand what's going on so I can better articulate my issues here and its been taking some time. I think I managed to fix it finally, it had to do with my hardhat deployment and how my address wasn't being read globally plus how there was a problem with my useEffect and it continually calling those functions in an infinite loop. I still wanted to thank you for helping me out with this. I was expecting to write up another question and link it to you in the comments but it doesn't seem like I need to :) Commented Aug 9, 2024 at 20:22
  • Okay. It's good to know that your issue is resolved. Feel free to ask a new question and share the url, if you face any problem further. Commented Aug 9, 2024 at 23:47

1 Answer 1

0

The error is due to the fact that you haven't converted the BigNumber type to integer in your frontend, as the assetIDs (i.e., fetched by calling getAllAssetIDs() function of the contract) is an array containing the ids of type uint256, and similarly the balanceOf() function is returning the balance of type uint256.

And, the uint256 type is stored as BigNumber in JS, that's why it needs formatting in terms of converting from BigNumber to integer or float depending on the required type.

So, in the fetchAssets() function of your frontend, you can do:

const assetIDs = await contract.getAllAssetIDs(); // Map through the array and apply parseInt to each element const parsedAssetIDs = assetIDs.map(assetID => parseInt(assetID.toString())); const myAssets = []; const availableAssets = []; // Use parsedAssetIDs instead of assetIDs for (let id of parsedAssetIDs) { // Body of the for loop } // Rest of the code 

And, in the checkRegistration() function of your frontend, you can do:

const checkRegistration = async () => { if (contract && account) { const balance = parseInt((await contract.balanceOf(account, 0)).toString()); setIsRegistered(balance.gt(0)); } }; 
5
  • This worked great! Thank you so much, I didn't realise I had to convert it into a different number type before and thought it was handled. Though I'm running into other issues now like my frontend simply not appearing and getting an unexpected token error within my browser with no source. The contracts and functions work though, so that helps. Commented Aug 2, 2024 at 9:59
  • That might be something related to ReactJS and the corresponding dependencies. Can you open a separate question and share screenshots of the error there? Commented Aug 2, 2024 at 10:50
  • Feel free to share the url of the question over here. I’ll be happy to debug that alongside you. Commented Aug 2, 2024 at 10:50
  • Actually hang on, I'm getting the error again. I thought I had to import openzeppelin but that can't be used outside of solidity and .toString() is actually from ethers.js which I have imported. I don't understand why it isn't recognising it though. I'm using v6 and parseInt is detected just fine. Commented Aug 2, 2024 at 12:12
  • .toString() is available by-default in JS. Commented Aug 2, 2024 at 14:09

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.