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.