Okay ill try that now. I’m making a github repo aswell for this
Im getting no other errors just the same one as before
Hey @alex
I’ve gone to the final code and done the steps to set it up and the GitHub repo itself has some errors and 1 of them is the one I’m having trouble with. Does anyone update the repos overtime or nah? Ill continue trying to fix this its just taking up alot of time.
How do you replicate it? I’m not seeing the key warning on my end if I go to any of the pages if I clone the project. For now you could just ignore it. As mentioned previously, a lot of the 400 errors can be ignored also as they are existing issues.
The NFT boilerplate is based on the Ethereum Boilerplate which hasn’t received updates in some time. There is a version 2 in the works.
I forked it and then did git clone in my terminal to get the code into vs code. I’m ignoring the 400 errors, I just have the unique key issue because it was passed a child from NFTBalance. I can ignore it for now but I will need to fix it soon so the project can be completed.
Just the Moralis SDK version that is specified in the project’s package.json. Did you use yarn to install?
Try to isolate where the warning is coming from by commenting out parts/map functions of the app. You can share a repo, this is slightly different, I’m not sure why you’re getting these by default.
Hey @alex
Yes I would have the correct Moralis SDK from yarn install. Ok Ill try isolating it with this new error. I find it weird that I get them by default. It wouldn’t have anything to do with my computer would it? I know that’s weird but I don’t get why I have them by default. My mate who is doing this project sitting next to me has the same error too.
Cheers
maybe its to do with the Database? do you have a repo of yours that works?
Hey @alex
I’ve been able to isolate the error and I’m pretty sure the error has something to do with the <ShoppingCartOutlined onClick={ () => handleSellClick(nft)} /> line of code. At the top of my NFTBalances page isn’t light blue which could be something to do with it or it is the nft unique key?
When I uncomment that incorrect line the import turns light blue so its not that but I still think its that <ShoppingCartOutlined onClick={ () => handleSellClick(nft)} /> . I’m defiantly getting close.
Cheers
I’m thinking its something to do with the unique key (nft). I’m not 100% sure but it points to there when I break down the issue.
My mate has said it could be the useWeb3ExecuteFunction, what do you guys think?
Cheers
When a imported component is not used, VScode shows the component with different color. You can ignore it, if it is not causing any errors.
Are you getting any new errors?
Hey @johnversus
I’m now getting the same error except it says to check the render method of ‘Content’ instead of ‘Panel’.
Is this error coming up due to the nft unique key or maybe the useWeb3ExecuteFunction?
I’ve been stuck on this for several hours and wonder why I can’t find the solution.
Thanks in advance.
NFTBalance
import React, { useState } from "react";
import { useMoralis } from "react-moralis";
import { Card, Image, Tooltip, Modal, Input, Alert, Spin, Button } from "antd";
import { useNFTBalance } from "hooks/useNFTBalance";
import { FileSearchOutlined, ShoppingCartOutlined } from "@ant-design/icons";
import { useMoralisDapp } from "providers/MoralisDappProvider/MoralisDappProvider";
import { getExplorer } from "helpers/networks";
import { useWeb3ExecuteFunction } from "react-moralis";
const { Meta } = Card;
const styles = {
NFTs: {
display: "flex",
flexWrap: "wrap",
WebkitBoxPack: "start",
justifyContent: "flex-start",
margin: "0 auto",
maxWidth: "1000px",
gap: "10px",
},
};
function NFTBalance() {
const { NFTBalance, fetchSuccess } = useNFTBalance();
const { chainId, marketAddress, contractABI } = useMoralisDapp();
const { Moralis } = useMoralis();
const [visible, setVisibility] = useState(false);
const [nftToSend, setNftToSend] = useState(null);
const [price, setPrice] = useState(1);
const [loading, setLoading] = useState(false);
const contractProcessor = useWeb3ExecuteFunction();
const contractABIJson = JSON.parse(contractABI);
const listItemFunction = "createMarketItem";
const ItemImage = Moralis.Object.extend("ItemImages");
async function list(nft, listPrice) {
setLoading(true);
const p = listPrice * ("1e" + 18);
const ops = {
contractAddress: marketAddress,
functionName: listItemFunction,
abi: contractABIJson,
params: {
nftContract: nft.token_address,
tokenId: nft.token_id,
price: String(p),
},
};
await contractProcessor.fetch({
params: ops,
onSuccess: () => {
console.log("success");
setLoading(false);
setVisibility(false);
addItemImage();
succList();
},
onError: (error) => {
setLoading(false);
failList();
},
});
}
async function approveAll(nft) {
setLoading(true);
console.log("nft: ", nft)
const ops = {
contractAddress: nft.token_address,
functionName: "setApprovalForAll",
abi: [{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"}],
params: {
operator: marketAddress,
approved: true
},
};
await contractProcessor.fetch({
params: ops,
onSuccess: () => {
console.log("Approval Received");
setLoading(false);
setVisibility(false);
succApprove();
},
onError: (error) => {
setLoading(false);
failApprove();
},
});
}
const handleSellClick = (nft) => {
setNftToSend(nft);
setVisibility(true);
};
function succList() {
let secondsToGo = 5;
const modal = Modal.success({
title: "Success!",
content: `Your NFT was listed on the marketplace`,
});
setTimeout(() => {
modal.destroy();
}, secondsToGo * 1000);
}
function succApprove() {
let secondsToGo = 5;
const modal = Modal.success({
title: "Success!",
content: `Approval is now set, you may list your NFT`,
});
setTimeout(() => {
modal.destroy();
}, secondsToGo * 1000);
}
function failList() {
let secondsToGo = 5;
const modal = Modal.error({
title: "Error!",
content: `There was a problem listing your NFT`,
});
setTimeout(() => {
modal.destroy();
}, secondsToGo * 1000);
}
function failApprove() {
let secondsToGo = 5;
const modal = Modal.error({
title: "Error!",
content: `There was a problem with setting approval`,
});
setTimeout(() => {
modal.destroy();
}, secondsToGo * 1000);
}
function addItemImage() {
const itemImage = new ItemImage();
itemImage.set("image", nftToSend.image);
itemImage.set("nftContract", nftToSend.token_address);
itemImage.set("tokenId", nftToSend.token_id);
itemImage.set("name", nftToSend.name);
itemImage.save();
}
return (
<>
<div style={styles.NFTs}>
{contractABIJson.noContractDeployed && (
<>
<Alert
message="No Smart Contract Details Provided. Please deploy smart contract and provide address + ABI in the MoralisDappProvider.js file"
type="error"
/>
<div style={{ marginBottom: "10px" }}></div>
</>
)}
{!fetchSuccess && (
<>
<Alert
message="Unable to fetch all NFT metadata... We are searching for a solution, please try again later!"
type="warning"
/>
<div style={{ marginBottom: "10px" }}></div>
</>
)}
{NFTBalance &&
NFTBalance.map((nft, index) => (
<Card
hoverable
actions={[
<Tooltip title="View On Blockexplorer">
<FileSearchOutlined
onClick={() =>
window.open(
`${getExplorer(chainId)}address/${nft.token_address}`,
"_blank"
)
}
/>
</Tooltip>,
<Tooltip title="List NFT for sale">
<ShoppingCartOutlined onClick={() => handleSellClick(nft)} />
</Tooltip>,
]}
style={{ width: 240, border: "2px solid #e7eaf3" }}
cover={
<Image
preview={false}
src={nft?.image || "error"}
fallback="data:image/png;base64,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"
alt=""
style={{ height: "240px" }}
/>
}
key={index}
>
<Meta title={nft.name} description={nft.contract_type} />
</Card>
))}
</div>
<Modal
title={`List ${nftToSend?.name} #${nftToSend?.token_id} For Sale`}
visible={visible}
onCancel={() => setVisibility(false)}
onOk={() => list(nftToSend, price)}
okText="List"
footer={[
<Button onClick={() => setVisibility(false)}>
Cancel
</Button>,
<Button onClick={() => approveAll(nftToSend)} type="primary">
Approve
</Button>,
<Button onClick={() => list(nftToSend, price)} type="primary">
List
</Button>
]}
>
<Spin spinning={loading}>
<img
src={`${nftToSend?.image}`}
style={{
width: "250px",
margin: "auto",
borderRadius: "10px",
marginBottom: "15px",
}}
/>
<Input
autoFocus
placeholder="Listing Price in ETH"
onChange={(e) => setPrice(e.target.value)}
/>
</Spin>
</Modal>
</>
);
}
export default NFTBalance;
NFTMarketTransactions
import React, { useState } from "react";
import { useMoralis, useMoralisQuery } from "react-moralis";
import { useMoralisDapp } from "providers/MoralisDappProvider/MoralisDappProvider";
import { Table, Tag, Space } from "antd";
import { PolygonCurrency} from "./Chains/Logos";
import moment from "moment";
const styles = {
table: {
margin: "0 auto",
width: "1000px",
},
};
function NFTMarketTransactions() {
const { walletAddress } = useMoralisDapp();
const { Moralis } = useMoralis();
const queryItemImages = useMoralisQuery("ItemImages");
const fetchItemImages = JSON.parse(
JSON.stringify(queryItemImages.data, [
"nftContract",
"tokenId",
"name",
"image",
])
);
const queryMarketItems = useMoralisQuery("MarketItems");
const fetchMarketItems = JSON.parse(
JSON.stringify(queryMarketItems.data, [
"updatedAt",
"price",
"nftContract",
"itemId",
"sold",
"tokenId",
"seller",
"owner",
])
)
.filter(
(item) => item.seller === walletAddress || item.owner === walletAddress
)
.sort((a, b) =>
a.updatedAt < b.updatedAt ? 1 : b.updatedAt < a.updatedAt ? -1 : 0
);
function getImage(addrs, id) {
const img = fetchItemImages.find(
(element) =>
element.nftContract === addrs &&
element.tokenId === id
);
return img?.image;
}
function getName(addrs, id) {
const nme = fetchItemImages.find(
(element) =>
element.nftContract === addrs &&
element.tokenId === id
);
return nme?.name;
}
const columns = [
{
title: "Date",
dataIndex: "date",
key: "date",
},
{
title: "Item",
key: "item",
render: (text, record) => (
<Space size="middle">
<img src={getImage(record.collection, record.item)} style={{ width: "40px", borderRadius:"4px"}} />
<span>#{record.item}</span>
</Space>
),
},
{
title: "Collection",
key: "collection",
render: (text, record) => (
<Space size="middle">
<span>{getName(record.collection, record.item)}</span>
</Space>
),
},
{
title: "Transaction Status",
key: "tags",
dataIndex: "tags",
render: (tags) => (
<>
{tags.map((tag) => {
let color = "geekblue";
let status = "BUY";
if (tag === false) {
color = "volcano";
status = "waiting";
} else if (tag === true) {
color = "green";
status = "confirmed";
}
if (tag === walletAddress) {
status = "SELL";
}
return (
<React.Fragment>
<Tag color={color} key={tag}>
{status.toUpperCase()}
</Tag>
</React.Fragment>
);
})}
</>
),
},
{
title: "Price",
key: "price",
dataIndex: "price",
render: (e) => (
<Space size="middle">
<PolygonCurrency/>
<span>{e}</span>
</Space>
),
}
];
const data = fetchMarketItems?.map((item) => ({
key: item,
date: moment(item.updatedAt).format("DD-MM-YYYY HH:mm"),
collection: item.nftContract,
item: item.tokenId,
tags: [item.seller, item.sold],
price: item.price / ("1e" + 18)
}));
return (
<>
<div>
<div style={styles.table}>
<Table columns={columns} dataSource={data} />
</div>
</div>
</>
);
}
export default NFTMarketTransactions;
const columns = [
{
title: "Date",
dataIndex: "date",
key: "date",
},
{
title: "Item",
key: "item",
},
{
title: "Collection",
key: "collection",
},
{
title: "Transaction Status",
key: "tags",
dataIndex: "tags",
},
{
title: "Price",
key: "price",
dataIndex: "price",
}
];
I have the same suggestions as glad suggested.
Try adding key={index}
in the child components of NFTBalance. (Example in meta compoent: <Meta key={index} title={nft.name} description={nft.contract_type} />
)
And also check the pages where NFTBalance
component is imported and add a key value there. (for example: It is imported in app.js page. so you can add a key value in the component as <NFTBalance key={"nftbalance"} />
)
@johnversus Ok ill try that. Thank you for your help. Ill message later if I happen to struggle.
Cheers