Hey guys
I’m having issues with the approve and list buttons on my opensea clone I cant approve and list NFT’s for sale… I’ve narrowed it down to there is a error in the smart contract or Abi. Can someone please help me find a solution. I’ve been stuck on this for several hours and want to figure it out
NFTBalance.jsx
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
},
};
console.log("ops : ", ops)
await contractProcessor.fetch({
params: ops,
onSuccess: () => {
console.log("Approval Received");
setLoading(false);
setVisibility(false);
succApprove();
},
onError: (error) => {
setLoading(false);
failApprove();
console.log(error)
},
});
}
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
key={index}
hoverable
actions={[
<Tooltip title="View On Blockexplorer" key={index}>
<FileSearchOutlined
key={index}
onClick={() =>
window.open(
`${getExplorer(chainId)}address/${nft.token_address}`,
"_blank"
)
}
/>
</Tooltip>,
<Tooltip title="List NFT for sale" key={index}>
<ShoppingCartOutlined onClick={() => handleSellClick(nft)} key={index}/>
</Tooltip>,
]}
style={{ width: 240, border: "2px solid #e7eaf3" }}
cover={
<Image
key={index}
preview={false}
src={nft?.image || "error"}
fallback="data:image/png;base64,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"
alt=""
style={{ height: "240px" }}
/>
}
>
<Meta title={nft.name} description={nft.contract_type} key={index} />
</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 (
<Tag color={color} key={tag}>
{status.toUpperCase()}
</Tag>
);
})}
</>
),
},
{
title: "Price",
key: "price",
dataIndex: "price",
render: (e) => (
<Space size="middle">
<PolygonCurrency/>
<span>{e}</span>
</Space>
),
}
];
const data = fetchMarketItems?.map((item, index) => ({
key: index,
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",
}
];
![Screenshot 2022-07-26 105849 Smart Contract issue to send to glad and john|493x500](upload://b3WFas8F8hSIVw9Zvg8IPyMdbhy.png)