From 051d138f1f2d2f68bf66145a26c27ec82b18ec12 Mon Sep 17 00:00:00 2001 From: Joan Date: Wed, 12 Jul 2023 18:27:27 +0200 Subject: [PATCH 1/6] indexer fix + product nft page --- indexer/.env.example | 3 +- indexer/src/client/generate/index.js | 8 +- indexer/src/index.ts | 20 +- indexer/src/utils/apiUtils.ts | 5 +- t3/.env.example | 3 +- t3/next.config.mjs | 2 +- .../api/indexerWebhooks/ItemListedCanceled.ts | 56 ++ .../api/indexerWebhooks/auctionCreated.ts | 4 +- .../pages/api/indexerWebhooks/offerCreated.ts | 7 + t3/src/pages/explore.tsx | 43 -- t3/src/pages/product/[id].tsx | 500 ++++++++++++------ .../ApproveItemEthers.ts} | 29 +- .../CancelListEthers.ts} | 6 +- .../auxFunctions/CreateOffer.ts | 32 ++ .../IsApproved.ts} | 4 +- .../ListItemEthers.ts} | 6 +- .../ReadOwnerOf.ts} | 4 +- 17 files changed, 468 insertions(+), 264 deletions(-) create mode 100644 t3/src/pages/api/indexerWebhooks/ItemListedCanceled.ts rename t3/src/smart-contracts/{hooks/useApproveItemEthers.ts => auxFunctions/ApproveItemEthers.ts} (56%) rename t3/src/smart-contracts/{hooks/useCancelListEthers.ts => auxFunctions/CancelListEthers.ts} (81%) create mode 100644 t3/src/smart-contracts/auxFunctions/CreateOffer.ts rename t3/src/smart-contracts/{hooks/useIsApproved.ts => auxFunctions/IsApproved.ts} (85%) rename t3/src/smart-contracts/{hooks/useListItemEthers.ts => auxFunctions/ListItemEthers.ts} (81%) rename t3/src/smart-contracts/{hooks/useReadOwnerOf.ts => auxFunctions/ReadOwnerOf.ts} (86%) diff --git a/indexer/.env.example b/indexer/.env.example index ee452f2..92446f6 100644 --- a/indexer/.env.example +++ b/indexer/.env.example @@ -1,4 +1,5 @@ -DATABASE_URL="file:./dev.db" +# DATABASE_URL="file:./dev.db" +DATABASE_URL="postgresql://postgres:cWiSgoSVm8I6tkkEqfbh@containers-us-west-48.railway.app:5958/railway" NODE_ENV="development" MUMBAI_RPC_PROVIDER="https://polygon-mumbai.g.alchemy.com/v2/nwCEWjd7yikmP8BLQGEv7J89qEj2FnIg" API_ENDPOINT="http://localhost:3000/api/webhooks/indexerWebhooks/" diff --git a/indexer/src/client/generate/index.js b/indexer/src/client/generate/index.js index 4279106..84b10d2 100644 --- a/indexer/src/client/generate/index.js +++ b/indexer/src/client/generate/index.js @@ -126,7 +126,7 @@ const config = { "value": "prisma-client-js" }, "output": { - "value": "/Users/alex/Desktop/disrup3/fromme/indexer/src/client/generate", + "value": "C:\\Users\\Fuet\\OneDrive\\Desktop\\disrup3_repo\\sprint2\\fromme\\indexer\\src\\client\\generate", "fromEnvVar": null }, "config": { @@ -135,7 +135,7 @@ const config = { "binaryTargets": [ { "fromEnvVar": null, - "value": "darwin-arm64", + "value": "windows", "native": true } ], @@ -183,7 +183,7 @@ const PrismaClient = getPrismaClient(config) exports.PrismaClient = PrismaClient Object.assign(exports, Prisma) -path.join(__dirname, "libquery_engine-darwin-arm64.dylib.node"); -path.join(process.cwd(), "src/client/generate/libquery_engine-darwin-arm64.dylib.node") +path.join(__dirname, "query_engine-windows.dll.node"); +path.join(process.cwd(), "src/client/generate/query_engine-windows.dll.node") path.join(__dirname, "schema.prisma"); path.join(process.cwd(), "src/client/generate/schema.prisma") diff --git a/indexer/src/index.ts b/indexer/src/index.ts index 9d419f1..8fb77f6 100644 --- a/indexer/src/index.ts +++ b/indexer/src/index.ts @@ -24,10 +24,10 @@ const connect = async () => { const trackContractCallback = async () => { const lastBlocks = await prisma.tracker_State.findMany(); - await processFactoryTrackerEvents(lastBlocks[0].lastBlockProcessed, prisma); - await processNftMarketplaceEvents(lastBlocks[0].lastBlockProcessed, prisma); + // await processFactoryTrackerEvents(lastBlocks[0].lastBlockProcessed, prisma); + // await processNftMarketplaceEvents(lastBlocks[0].lastBlockProcessed, prisma); await processDeadEvents(); - setTimeout(() => trackContractCallback(), 2000); // Recursividad de trackeo + setTimeout(() => trackContractCallback(), 20000); // Recursividad de trackeo }; await trackContractCallback(); }; @@ -35,18 +35,22 @@ const connect = async () => { const processDeadEvents = async () => { // checkear si hay eventos muertos const deadEvents = await prisma.dead_events_queue.findMany(); + // console.log('deadEvents', deadEvents) if(!deadEvents.length) return console.log("No hay que recuperar"); // de ser asi, llamar a callApi con esos datos - try { + // try { deadEvents.forEach(async (event: Dead_events_queue) => { console.log(event.eventName) + // console.log(event) const success = await callApi(event.eventName, JSON.parse(event.data), true); - if(success) await prisma.dead_events_queue.delete({where: {id: event.id}}) + console.log(success) + return + // if(success) await prisma.dead_events_queue.delete({where: {id: event.id}}) }); - } catch (error) { - console.log(error); - } + // } catch (error) { + // console.log(error); + // } }; setTimeout(connect, 2000); // Para que el turbo repo no pete \ No newline at end of file diff --git a/indexer/src/utils/apiUtils.ts b/indexer/src/utils/apiUtils.ts index f9af924..ee9a6c5 100644 --- a/indexer/src/utils/apiUtils.ts +++ b/indexer/src/utils/apiUtils.ts @@ -4,7 +4,10 @@ import axios from "axios"; export const callApi = async (endpoint: string, data: any, isDead = false) => { try { console.log("endpoint:", endpoint); - const x =await axios.post(`${process.env.API_ENDPOINT}${endpoint}`, data); + console.log(`${process.env.API_ENDPOINT}${endpoint}`) + console.log("data:", data); + + const x = await axios.post(`${process.env.API_ENDPOINT}${endpoint}`, data); console.log(x.data) console.log("callapi success"); return true diff --git a/t3/.env.example b/t3/.env.example index 70294dc..8aef113 100644 --- a/t3/.env.example +++ b/t3/.env.example @@ -25,7 +25,6 @@ DISCORD_CLIENT_ID="" DISCORD_CLIENT_SECRET="" # Contract address -NFT_FACTORY = "0xBB645BdAFD93Ca5D91B457709e55C0318a6f5449" # No need to delete from .env.example NEXT_PUBLIC_NFT_STORAGE_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkaWQ6ZXRocjoweDY4ZGUxM2E5OUE0YTkyRDdEMTFDNDMxQ0IzNDc2NDZBOWJCZkRCMzQiLCJpc3MiOiJuZnQtc3RvcmFnZSIsImlhdCI6MTY4Njc3MjAwNjM4OCwibmFtZSI6ImZyb21tZS1kZXYifQ.C-6OrEBBh64q1IowVo_bfRphCq5qo388DMwEcoyfyjg # URL Provider @@ -33,3 +32,5 @@ URL_MUMBAI="" # Private keys PRIVATE_KEY="" + +NEXTAUTH_SECRET='Required' \ No newline at end of file diff --git a/t3/next.config.mjs b/t3/next.config.mjs index 4605d24..1b678a8 100644 --- a/t3/next.config.mjs +++ b/t3/next.config.mjs @@ -7,7 +7,7 @@ await import("./src/env.mjs"); /** @type {import("next").NextConfig} */ const config = { images: { - domains: ["ipfs.io"], + domains: ["ipfs.io", "encrypted-tbn0.gstatic.com"], }, reactStrictMode: true, webpack: (config) => { diff --git a/t3/src/pages/api/indexerWebhooks/ItemListedCanceled.ts b/t3/src/pages/api/indexerWebhooks/ItemListedCanceled.ts new file mode 100644 index 0000000..8da7876 --- /dev/null +++ b/t3/src/pages/api/indexerWebhooks/ItemListedCanceled.ts @@ -0,0 +1,56 @@ +import { prisma } from "~/server/db"; +import type { NextApiRequest, NextApiResponse } from 'next'; + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse, +) { + if(!(req.method === "POST")) { + return res.status(400).json({message: "unauthorized"}); + } + // Item Listed + const { tokenId, seller, amount, startingTime, endTime } = req.body; + + try { + await checkNftExists(tokenId, seller, amount, startingTime, endTime); + return res.status(200).json({message: "ok"}) + } catch (error) { + return res.status(500).json({message: JSON.stringify(error)}); + } +} + +const checkNftExists = async (tokenId: number, seller: string, amount: number, startingTime: number, endTime: number) => { + const item = await prisma.listedNft.findUnique({ + where: { + tokenId_startingTime: { + tokenId, startingTime, + } + } + }); + if(item) { + await prisma.listedNft.update({ + where: { + tokenId_startingTime: { + tokenId, startingTime, + } + }, + data: { + seller, + amount, + startingTime, + endTime, + isCancelled: false, + } + }); + } else { + await prisma.listedNft.create({ + data: { + tokenId, + seller, + amount, + startingTime, + endTime, + } + }); + } +} \ No newline at end of file diff --git a/t3/src/pages/api/indexerWebhooks/auctionCreated.ts b/t3/src/pages/api/indexerWebhooks/auctionCreated.ts index 3a8264c..686e278 100644 --- a/t3/src/pages/api/indexerWebhooks/auctionCreated.ts +++ b/t3/src/pages/api/indexerWebhooks/auctionCreated.ts @@ -12,14 +12,14 @@ export default async function handler( const { tokenId, seller, startingAmount, startingTime, endTime } = req.body; try { - await checkOfferExists(tokenId, seller, startingAmount, startingTime, endTime); + await checkAuctionExists(tokenId, seller, startingAmount, startingTime, endTime); return res.status(200).json({message: "ok"}); } catch (error) { return res.status(500).json({message: JSON.stringify(error)}); } } -const checkOfferExists = async (tokenId: number, seller: string, startingAmount: number, startingTime: number, endTime: number) => { +const checkAuctionExists = async (tokenId: number, seller: string, startingAmount: number, startingTime: number, endTime: number) => { const row = await prisma.auction.findUnique({ where: { tokenId_startingTime: { diff --git a/t3/src/pages/api/indexerWebhooks/offerCreated.ts b/t3/src/pages/api/indexerWebhooks/offerCreated.ts index 603b710..430bf48 100644 --- a/t3/src/pages/api/indexerWebhooks/offerCreated.ts +++ b/t3/src/pages/api/indexerWebhooks/offerCreated.ts @@ -11,6 +11,11 @@ export default async function handler( const { tokenId, buyer, amount, startingTime, endTime } = req.body; + console.log('+++++++++++++++++++') + console.log(req.body) + console.log(tokenId) + console.log('+++++++++++++++++++') + try { await checkOfferExists(tokenId, buyer, amount, startingTime, endTime); return res.status(200).json({message: "ok"}) @@ -20,6 +25,7 @@ export default async function handler( } const checkOfferExists = async (tokenId: number, buyer: string, amount: number, startingTime: number, endTime: number) => { + const row = await prisma.offer.findUnique({ where: { tokenId_buyer: { @@ -27,6 +33,7 @@ const checkOfferExists = async (tokenId: number, buyer: string, amount: number, } } }); + if(row) { await prisma.offer.update({ where: { diff --git a/t3/src/pages/explore.tsx b/t3/src/pages/explore.tsx index 68c0265..bb17d70 100644 --- a/t3/src/pages/explore.tsx +++ b/t3/src/pages/explore.tsx @@ -6,49 +6,6 @@ import { GetServerSideProps } from "next"; import { prisma } from "~/server/db"; const explore = ({ items }: { items: any }) => { - // Simular datos recibidos de la API - //const items = [ - // { - // name: "Los 90", - // description: "Iconos de los años 90", - // image: - // "https://ipfs.io/ipfs/bafybeihqg2q2lhokindipetm5c2yiknwaes423dyyi6yssa3rva5mdggfu/FUA_pLhWQAE2GyI-1024x1229.jpeg", - // price: 1, - // creator: "Bruce Willis", - // stock: 10, - // favorites: 230, - // }, - // { - // name: "Pájaro azul", - // description: "Iconos de los años 90", - // image: - // "https://ipfs.io/ipfs/bafybeibl42qqf6edhl67hfpwxax4sc6sehcs2oqhajsaqxjyfjgtlcijdi/photo_2021-10-04_16-09-14.jpg", - // price: 233, - // creator: "Fernando Alonso Díaz", - // stock: 3, - // favorites: 300, - // }, - // { - // name: "Película Netflix", - // description: "desc", - // image: - // "https://ipfs.io/ipfs/bafybeigucrxr7k5yv7bu53pohp66m55if7qvksraqwrdhx2p7pyqdv5pu4/fghertgerryhjrtyj.jpg", - // price: 32, - // creator: "Raphael", - // stock: 2, - // favorites: 310, - // }, - // { - // name: "Mr Crypto 5582", - // description: "Un Mr Crypto", - // image: - // "https://ipfs.io/ipfs/bafybeieeuo7onug6boss3hs7ryt5twcyamuktob5emwhjfeipcamzeknoe/mrCrypto5582.jpg", - // price: 5, - // creator: "Pep Guardiola", - // stock: 2, - // favorites: 310, - // }, - //]; // Simular datos recibidos de la API const [categoriesSelected, setCategoriesSelected] = useState([ diff --git a/t3/src/pages/product/[id].tsx b/t3/src/pages/product/[id].tsx index 993d37f..5b69189 100644 --- a/t3/src/pages/product/[id].tsx +++ b/t3/src/pages/product/[id].tsx @@ -9,58 +9,138 @@ import { useEffect, useState } from "react"; import { addresses } from "../../smart-contracts/constants"; -import useReadOwnerOf from "../../smart-contracts/hooks/useReadOwnerOf"; -import useIsApproved from "../../smart-contracts/hooks/useIsApproved"; -import useListItem from "../../smart-contracts/hooks/useListItemEthers"; -import useCancelList from "../../smart-contracts/hooks/useCancelListEthers"; -import useApproveItem from "../../smart-contracts/hooks/useApproveItemEthers"; -import useBuyItem from "../../smart-contracts/hooks/useBuyItem"; -import axios from "axios"; +import ReadOwnerOf from "../../smart-contracts/auxFunctions/ReadOwnerOf"; +import IsApproved from "../../smart-contracts/auxFunctions/IsApproved"; + +import CancelList from "../../smart-contracts/auxFunctions/CancelListEthers"; +import ApproveItem from "../../smart-contracts/auxFunctions/ApproveItemEthers"; +import ListItem from "../../smart-contracts/auxFunctions/ListItemEthers"; +import CreateOffer from "../../smart-contracts/auxFunctions/CreateOffer"; +import axios from "axios"; -type ListItemData = { +type ItemData = { amountList: number; durationList: number; }; -const NFTProduct = ({ nftId, tokenUri, creatorAddress, creatorFee, creatorName, sellerAddress, sellerName - , amount, isListed, isOwner, isApproved } : any) => { - // console.log('tokenUri :: ', tokenUri) +const NFTProduct = ({ nftId, userAddress, nftData, listedNftData, creatorData, sellerData, offerData, buyerData } : any) => { + + console.log('offerData', offerData) + console.log('buyerData', buyerData) - const [tokenImage, setTokenImage] = useState(""); const [showFormList, setShowFormList] = useState(false); - const [formDataList, setFormDataList] = useState({ + const [formDataList, setFormDataList] = useState({ amountList: 0, durationList: 0, }); + + const [showOfferList, setShowOfferList] = useState(false); + const [formDataOffer, setFormDataOffer] = useState({ + amountList: 0, + durationList: 0, + }); + + // logic moved from the server side props: + const [ownerOFNft, setOwnerOFNft] = useState(""); + const [isApproved, setIsApproved] = useState(false); + const [isOwner, setIsOwnerd] = useState(false); + + const [isListed, setIsListed] = useState(false); + const [hasOffer, setHasOffer] = useState(false); + + const [creatorAddress, setCreatorAddress] = useState(""); + const [creatorName, setCreatorName] = useState(""); + const [creatorImage, setCreatorImage] = useState(""); + const [creatorFee, setCreatorFee] = useState(0); + // const [tokenUri, setTokenUri] = useState(""); + const [tokenImage, setTokenImage] = useState(""); + + const [sellerAddress, setSellerAddress] = useState(""); + const [sellerName, setSellerName] = useState(""); + const [sellerImage, setSellerImage] = useState(""); + const [sellerAmount, setSellerAmount] = useState(""); - async function formatTokenUri(_tokenUri: string) { - const formattedTokenUri = `https://ipfs.io/ipfs/${_tokenUri?.substring(7,200)}`; - return formattedTokenUri - } + const [buyerAddress, setBuyerAddress] = useState(""); + const [buyerName, setBuyerName] = useState(""); + const [buyerImage, setBuyerImage] = useState(""); + const [buyerAmount, setBuyerAmount] = useState(""); - useEffect(() => { + async function loadMainInfo() { + + setOwnerOFNft(await ReadOwnerOf(nftId)) - const getTokenUri = async () => { - const _formattedTokenUri = await formatTokenUri(tokenUri) - const metadataIPFS = await axios.get(_formattedTokenUri); + const addressApproved = await IsApproved(nftId); + setIsApproved(addresses.FrommeMarketplace == addressApproved) + setIsOwnerd(ownerOFNft == userAddress) + if(nftData) { + setCreatorAddress(nftData.creator) + setCreatorFee(nftData.feeNumerator) + + + // Image + const _formattedTokenUri = await formatTokenUri(nftData.tokenUri) + const metadataIPFS = await axios.get(_formattedTokenUri) + const image = metadataIPFS.data.image const formattedImage = await formatTokenUri(image) - + setTokenImage(formattedImage) } - getTokenUri() - }, []); + if(creatorData) { + setCreatorName(creatorData.name || "NoName") + setCreatorImage(creatorData.image || "/images/test.jpg") + } + + // Is NFT listed? + if (listedNftData) { + setIsListed(true) + const amount = Number(listedNftData?.amount) + const sellerAddress = listedNftData?.seller; + + if (sellerAddress) { + if(sellerData) { + setSellerAddress(sellerAddress) + setSellerName(sellerData.name || "NoName") + setSellerImage(sellerData.image || "/images/test.jpg") + setSellerAmount(ethers.utils.formatEther(amount)) + } + } + } + // Has offers? + if (offerData) { + setHasOffer(true) + const amount = Number(offerData?.amount) + const buyerAddress = offerData?.buyer; + + if (buyerAddress) { + if(buyerData) { + setBuyerAddress(buyerAddress) + setBuyerName(buyerData.name || "NoName") + setBuyerImage(buyerData.image || "/images/test.jpg") + setBuyerAmount(ethers.utils.formatEther(amount)) + } + } + } + } + + useEffect(() => { + loadMainInfo() + }, []) + ////////////////////////////////////////// + async function formatTokenUri(_tokenUri: string) { + const formattedTokenUri = `https://ipfs.io/ipfs/${_tokenUri?.substring(7,200)}`; + return formattedTokenUri + } const handleListItem = () => { - setShowFormList(true); + setShowFormList(!showFormList); }; - const handleListItemSubmit = async (e: React.FormEvent) => { e.preventDefault(); @@ -68,37 +148,45 @@ const NFTProduct = ({ nftId, tokenUri, creatorAddress, creatorFee, creatorName, setShowFormList(false); // send data to contract - await useListItem(nftId, formDataList.amountList, formDataList.durationList) + await ListItem(nftId, formDataList.amountList, formDataList.durationList) + }; + + const handleCreateOffer = () => { + setShowOfferList(!showOfferList); - console.log('Item Listed') }; + const handleCreateOfferSubmit = async (e: React.FormEvent) => { + e.preventDefault(); - const handleCancelListSubmit = async (e: React.FormEvent) => { + setFormDataOffer(formDataOffer); + setShowOfferList(false); - await useCancelList(nftId) - console.log('List Canceled') + // send data to contract + await CreateOffer(nftId, formDataOffer.amountList, formDataOffer.durationList) }; - const handleApproveItem = async (e: React.FormEvent) => { - await useApproveItem(nftId) - console.log('Item Approved') + const handleCancelListSubmit = async (e: React.FormEvent) => { + await CancelList(nftId) }; + const handleApproveItem = async (e: React.FormEvent) => { + await ApproveItem(nftId) + }; - const handleInputChange = (e: React.ChangeEvent) => { + const handleInputChangeList = (e: React.ChangeEvent) => { setFormDataList({ ...formDataList, [e.target.name]: e.target.value }); }; - - let ethValue; - if (isListed) { - ethValue = ethers.utils.formatEther(amount); - } + const handleInputChangeOffer = (e: React.ChangeEvent) => { + setFormDataOffer({ ...formDataOffer, [e.target.name]: e.target.value }); + }; + + function shortenAddress(address: string): string { - if (address.length < 10) { - throw new Error('Invalid Ethereum address'); - } + // if (address.length < 10) { + // throw new Error('Invalid Ethereum address'); + // } const firstChars = address.slice(0, 6); const lastChars = address.slice(-4); @@ -108,16 +196,13 @@ const NFTProduct = ({ nftId, tokenUri, creatorAddress, creatorFee, creatorName, const decimalPlaces: number = 2; const creatorFeeInPerc: string = `${(creatorFee / 10000 * 100).toFixed(decimalPlaces)}%`; - function handleBuyItem() { - useBuyItem(nftId) - return 1 - } - - return (
-

Token # {nftId}

+
+

Token # {nftId} :

+

{isApproved ? "Approved" : "Pending Approval"}

+

@@ -130,55 +215,101 @@ const NFTProduct = ({ nftId, tokenUri, creatorAddress, creatorFee, creatorName,
-
-
-

Creator Address:

-

{shortenAddress(creatorAddress)}

-

Creator Fee:

-

{creatorFeeInPerc}

-
-
-

Creator

-
+ {/*
*/} + {``}

{creatorName}

+
+
+
+

Creator Address:

+

{shortenAddress(creatorAddress)}

+

Creator Fee:

+

{creatorFeeInPerc}

+
+
{isListed && (
+
+
+
+

Seller

+ {/*
*/} + {``} +

{sellerName}

+
+
+
+

Seller Address:

{shortenAddress(sellerAddress)}

Price

- {ethValue || null} + {sellerAmount || null} ETH

-
+
+ )} + {hasOffer && ( +
-

Seller

-
-

{sellerName}

+

Buyer

+ {/*
*/} + {``} +

{buyerName}

+
+
+
+

Buyer Address:

+

{shortenAddress(buyerAddress)}

+

Price

+

+ {buyerAmount || null} + ETH +

+
+
)}
{isListed == true && isOwner == false && ( )} {isListed == true && isOwner == true && ( @@ -193,7 +324,7 @@ const NFTProduct = ({ nftId, tokenUri, creatorAddress, creatorFee, creatorName, )} {isListed == false && isOwner == true && isApproved == true && ( )} {showFormList && ( @@ -204,7 +335,7 @@ const NFTProduct = ({ nftId, tokenUri, creatorAddress, creatorFee, creatorName, name="amountList" placeholder="amount in ETH" value={formDataList.amountList} - onChange={handleInputChange} + onChange={handleInputChangeList} /> + + + )} + {isOwner == false && ( + + )} + {showOfferList && ( +
+ +
@@ -240,13 +397,13 @@ const NFTProduct = ({ nftId, tokenUri, creatorAddress, creatorFee, creatorName,
{/*
*/}
- {tokenImage} + />}
Music
@@ -259,26 +416,12 @@ export default NFTProduct; export const getServerSideProps: GetServerSideProps = async (ctx) => { - const session = await getSession(ctx); - // console.log('session', session) - + const session = await getSession(ctx) const userAddress = session?.user.name - // console.log('userAddress', userAddress) // from the query data, get nftId // from nftId get everything else (nft creator, if is listed the seller, etc.) const nftId = parseInt(ctx.query.id as string); - console.log('nftId:', nftId) - - const ownerOFNft = await useReadOwnerOf(nftId); - console.log('ownerOFNft', ownerOFNft); - - const addressApproved = await useIsApproved(nftId); - const isApproved = (addresses.FrommeMarketplace == addressApproved); - console.log('isApproved', isApproved); - - const isOwner = (ownerOFNft == userAddress) - console.log('isOwner', isOwner); if (!nftId && nftId != 0) { console.log("404") @@ -295,91 +438,130 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => { tokenId: nftId } }); - // console.log('nftData :', nftData); - const creatorAddress = nftData?.creator; - const creatorFee = nftData?.feeNumerator; - const tokenUri = nftData?.tokenUri; + // console.log('nftData', nftData) - const currentTimestamp = Math.floor(Date.now() / 1000); // Get the current timestamp as a BigInt + async function formatTokenUri(_tokenUri: string) { + const formattedTokenUri = `https://ipfs.io/ipfs/${_tokenUri?.substring(7,200)}`; + return formattedTokenUri + } - const listedNftDataList = await prisma.listedNft.findMany({ - where: { - tokenId: nftId, - startingTime: { - lte: currentTimestamp, // Check if startingTime is less than or equal to current time - }, - endTime: { - gte: currentTimestamp, // Check if endTime is greater than or equal to current time - }, - } - }); - // weshould only have one listed element active (between timestamps) - const listedNftData = listedNftDataList[0] - console.log('listedNftData :', listedNftData); + if (nftData) { + // Image + const _formattedTokenUri = await formatTokenUri(nftData.tokenUri) + // console.log('_formattedTokenUri', _formattedTokenUri) + const metadataIPFS = await axios.get(_formattedTokenUri) - const creatorData = await prisma.user.findUnique({ - where: { - address: creatorAddress - } - }); - // console.log('creatorData :', creatorData); + const image = metadataIPFS.data.image + const tokenImage = await formatTokenUri(image) + // console.log('tokenImage', tokenImage) - // Is NFT listed? - if (listedNftData) { - const amount = Number(listedNftData?.amount) - const currentTime = new Date(); - const currentTimestamp = currentTime.getTime(); + const currentTimestamp = Math.floor(Date.now() / 1000); // Get the current timestamp as a BigInt + const listedNftDataList = await prisma.listedNft.findMany({ + where: { + tokenId: nftId, + startingTime: { + lte: currentTimestamp, // Check if startingTime is less than or equal to current time + }, + endTime: { + gte: currentTimestamp, // Check if endTime is greater than or equal to current time + }, + } + }); + const listedNftData = listedNftDataList[0] + // console.log('listedNftData', listedNftData) + + const creatorData = await prisma.user.findUnique({ + where: { + address: nftData.creator + } + }); + // console.log(nftId, 'creatorData', creatorData) + + // LISTED + OFFER + let listedNftDataOut + let offerDataOut + let sellerDataOut + let buyerDataOut + + // Is NFT listed? + if (listedNftData) { + + const convertedNftData = { + ...listedNftData, + amount: Number(listedNftData.amount) + }; + // console.log('convertedNftData', convertedNftData) + + const sellerAddress = convertedNftData?.seller; + const sellerData = await prisma.user.findUnique({ + where: { + address: sellerAddress || "failSellerAddress" + } + }); + + listedNftDataOut = convertedNftData + sellerDataOut = sellerData + + } else { + listedNftDataOut = null + sellerDataOut = null + } - const sellerAddress = listedNftData?.seller; - - const sellerData = await prisma.user.findUnique({ + // OFFERS + const offerDataList = await prisma.offer.findMany({ where: { - address: sellerAddress || "failSellerAddress" + tokenId: nftId, } }); - // console.log('sellerData :', sellerData); - - // If the list is still active - *100 because miliseconds to seconds - if (currentTimestamp < listedNftData.endTime * 1000) { - return { - props: { - nftId: nftId, - tokenUri: tokenUri, - creatorAddress: creatorAddress, - creatorFee: creatorFee, - creatorName: creatorData?.name, - sellerAddress: sellerAddress, - sellerName: sellerData?.name, - amount: amount, - startingTime: listedNftData?.startingTime, - endTime: listedNftData?.endTime, - isListed: true, - isOwner: isOwner, - isApproved: isApproved + const offerData = offerDataList[0] + // console.log('offerData', offerData) + + // Has offer? + if (offerData) { + + const convertedNftData = { + ...offerData, + amount: Number(offerData.amount) + }; + // console.log('convertedNftData', convertedNftData) + + const buyerAddress = convertedNftData?.buyer; + const buyerData = await prisma.user.findUnique({ + where: { + address: buyerAddress || "failBuyerAddress" + } + }); + + offerDataOut = convertedNftData + buyerDataOut = buyerData + } + + return { + props: { + nftId: nftId, + userAddress: userAddress, + nftData: nftData, + listedNftData: listedNftDataOut, + creatorData: creatorData, + sellerData: sellerDataOut, + tokenImage: tokenImage, + offerData: offerDataOut, + buyerData: buyerDataOut }, }; - } - } + } return { props: { nftId: nftId, - tokenUri: tokenUri, - creatorAddress: creatorAddress, - creatorFee: creatorFee, - creatorName: creatorData?.name, - sellerAddress: null, - sellerName: null, - amount: null, - startingTime: null, - endTime: null, - isListed: false, - isOwner: isOwner, - isApproved: isApproved + userAddress: userAddress, + nftData: null, + listedNftData: null, + creatorData: null, + sellerData: null, + tokenImage: null, + offerData: null, + buyerData: null }, - }; - -}; - - - + } +} diff --git a/t3/src/smart-contracts/hooks/useApproveItemEthers.ts b/t3/src/smart-contracts/auxFunctions/ApproveItemEthers.ts similarity index 56% rename from t3/src/smart-contracts/hooks/useApproveItemEthers.ts rename to t3/src/smart-contracts/auxFunctions/ApproveItemEthers.ts index 9fb9930..2cee9ab 100644 --- a/t3/src/smart-contracts/hooks/useApproveItemEthers.ts +++ b/t3/src/smart-contracts/auxFunctions/ApproveItemEthers.ts @@ -1,7 +1,6 @@ import { addresses, NFTFactory_abi } from "../constants"; import { ethers } from 'ethers'; -import dotenv from 'dotenv'; declare global { interface Window { @@ -9,12 +8,9 @@ declare global { } } -export default async function useApproveItem(tokenId: number) { +export default async function ApproveItem(tokenId: number) { try { - const providerUrl = process.env.NEXT_PUBLIC_URL_MUMBAI; - console.log('providerUrl', providerUrl) - const provider = new ethers.providers.Web3Provider(window.ethereum, "any"); await provider.send("eth_requestAccounts", []); const signer = provider.getSigner(); @@ -44,29 +40,6 @@ export default async function useApproveItem(tokenId: number) { callContractFunction() - //// OLD VERSION - // Create a wallet instance using a private key - // const privateKey = process.env.NEXT_PUBLIC_PRIVATE_KEY; - - // let wallet: ethers.Wallet | undefined; - // if (privateKey) { - // wallet = new ethers.Wallet(privateKey, provider); - // } - // const connectedContract = wallet ? contract.connect(wallet) : contract; - - // async function sendTransactionToContract() { - // if (!wallet) { - // console.error('Private key is missing'); - // return; - // } - - // const tx = await connectedContract.approve(addresses.FrommeMarketplace, tokenId); - // await tx.wait(); // Wait for the transaction to be mined - // console.log('Transaction mined! Nft approved'); - // } - - // sendTransactionToContract() - } catch (error) { console.error('Error reading getApproved of token:', error); throw error; diff --git a/t3/src/smart-contracts/hooks/useCancelListEthers.ts b/t3/src/smart-contracts/auxFunctions/CancelListEthers.ts similarity index 81% rename from t3/src/smart-contracts/hooks/useCancelListEthers.ts rename to t3/src/smart-contracts/auxFunctions/CancelListEthers.ts index c730e8d..ec11a73 100644 --- a/t3/src/smart-contracts/hooks/useCancelListEthers.ts +++ b/t3/src/smart-contracts/auxFunctions/CancelListEthers.ts @@ -1,12 +1,8 @@ import { addresses, FrommeMarketplace_abi } from "../constants"; import { ethers } from 'ethers'; -import dotenv from 'dotenv'; -// Load environment variables from .env file -// dotenv.config({ path: '..\..\..\.env' }); - -export default async function useCancelList(_tokenId: number) { +export default async function CancelList(_tokenId: number) { try { const provider = new ethers.providers.Web3Provider(window.ethereum, "any"); diff --git a/t3/src/smart-contracts/auxFunctions/CreateOffer.ts b/t3/src/smart-contracts/auxFunctions/CreateOffer.ts new file mode 100644 index 0000000..f408a3b --- /dev/null +++ b/t3/src/smart-contracts/auxFunctions/CreateOffer.ts @@ -0,0 +1,32 @@ + +import { addresses, FrommeMarketplace_abi } from "../constants"; +import { ethers } from 'ethers'; + +export default async function CreateOffer(_tokenId: number, _amount: number, _durationInSeconds: number) { + try { + + const provider = new ethers.providers.Web3Provider(window.ethereum, "any"); + await provider.send("eth_requestAccounts", []); + const signer = provider.getSigner(); + console.log("Account:", await signer.getAddress()); + + const contract = new ethers.Contract(addresses.FrommeMarketplace, FrommeMarketplace_abi, signer); + + // Example function to send a transaction to the contract + async function sendTransactionToContract() { + + const amountInWei = ethers.utils.parseEther(_amount.toString()); + // console.log(amountInWei) + + const tx = await contract.createOffer(_tokenId, _durationInSeconds, { value: amountInWei }); + await tx.wait(); // Wait for the transaction to be mined + console.log('Transaction mined!'); + } + + sendTransactionToContract() + + } catch (error) { + console.error('Error making offer:', error); + throw error; + } +} diff --git a/t3/src/smart-contracts/hooks/useIsApproved.ts b/t3/src/smart-contracts/auxFunctions/IsApproved.ts similarity index 85% rename from t3/src/smart-contracts/hooks/useIsApproved.ts rename to t3/src/smart-contracts/auxFunctions/IsApproved.ts index 4adc2c2..be6bcc8 100644 --- a/t3/src/smart-contracts/hooks/useIsApproved.ts +++ b/t3/src/smart-contracts/auxFunctions/IsApproved.ts @@ -1,10 +1,8 @@ import { addresses, NFTFactory_abi } from "../constants"; import { ethers } from 'ethers'; -import dotenv from 'dotenv'; - -export default async function useIsApproved(tokenId: number) { +export default async function IsApproved(tokenId: number) { try { const providerUrl = process.env.NEXT_PUBLIC_URL_MUMBAI; // Replace with the actual JSON-RPC URL diff --git a/t3/src/smart-contracts/hooks/useListItemEthers.ts b/t3/src/smart-contracts/auxFunctions/ListItemEthers.ts similarity index 81% rename from t3/src/smart-contracts/hooks/useListItemEthers.ts rename to t3/src/smart-contracts/auxFunctions/ListItemEthers.ts index 0554854..d2c306e 100644 --- a/t3/src/smart-contracts/hooks/useListItemEthers.ts +++ b/t3/src/smart-contracts/auxFunctions/ListItemEthers.ts @@ -1,12 +1,8 @@ import { addresses, FrommeMarketplace_abi } from "../constants"; import { ethers } from 'ethers'; -import dotenv from 'dotenv'; -// Load environment variables from .env file -// dotenv.config({ path: '..\..\..\.env' }); - -export default async function useListItem(_tokenId: number, _amount: number, _durationInSeconds: number) { +export default async function ListItem(_tokenId: number, _amount: number, _durationInSeconds: number) { try { const provider = new ethers.providers.Web3Provider(window.ethereum, "any"); diff --git a/t3/src/smart-contracts/hooks/useReadOwnerOf.ts b/t3/src/smart-contracts/auxFunctions/ReadOwnerOf.ts similarity index 86% rename from t3/src/smart-contracts/hooks/useReadOwnerOf.ts rename to t3/src/smart-contracts/auxFunctions/ReadOwnerOf.ts index 2a217c6..5714d5f 100644 --- a/t3/src/smart-contracts/hooks/useReadOwnerOf.ts +++ b/t3/src/smart-contracts/auxFunctions/ReadOwnerOf.ts @@ -1,10 +1,8 @@ import { addresses, NFTFactory_abi } from "../constants"; import { ethers } from 'ethers'; -import dotenv from 'dotenv'; - -export default async function useReadOwnerOf(tokenId: number) { +export default async function ReadOwnerOf(tokenId: number) { try { const providerUrl = process.env.NEXT_PUBLIC_URL_MUMBAI; // Replace with the actual JSON-RPC URL From 92fe343331d26e18e37613ace837dba5205797fb Mon Sep 17 00:00:00 2001 From: Joan Date: Fri, 14 Jul 2023 00:26:31 +0200 Subject: [PATCH 2/6] nft product --- t3/src/components/ui/NFTcard.tsx | 25 ++--- t3/src/pages/product/[id].tsx | 160 ++++++++++++++++++------------- 2 files changed, 104 insertions(+), 81 deletions(-) diff --git a/t3/src/components/ui/NFTcard.tsx b/t3/src/components/ui/NFTcard.tsx index aecf1c8..bac03d2 100644 --- a/t3/src/components/ui/NFTcard.tsx +++ b/t3/src/components/ui/NFTcard.tsx @@ -9,7 +9,7 @@ const NFTcard = ({ item }: { item: ExploreItem }) => { const [tokenId, setTokenId] = useState(); const [tokenUri, setTokenUri] = useState(); const [tokenName, setTokenName] = useState(); - const [tokenDescription, setTokenDescription] = useState(); + // const [tokenDescription, setTokenDescription] = useState(); useEffect(() => { const getIPFSMetadata = async () => { @@ -24,9 +24,11 @@ const NFTcard = ({ item }: { item: ExploreItem }) => { description: string; }>(_formattedTokenUri); - setTokenUri(metadataIPFS.data.image); + console.log('metadataIPFS :: ', metadataIPFS) + + setTokenUri(formatTokenUri(metadataIPFS.data.image)); setTokenName(metadataIPFS.data.name); - setTokenDescription(metadataIPFS.data.description); + // setTokenDescription(metadataIPFS.data.description); } catch { console.log("Invalid IPFS metadata"); } @@ -37,19 +39,10 @@ const NFTcard = ({ item }: { item: ExploreItem }) => { }, []); function formatTokenUri(_tokenUri: string) { - const formattedTokenUri = `https://ipfs.io/ipfs/${_tokenUri?.substring( - 7, - 200 - )}`; + const formattedTokenUri = `https://ipfs.io/ipfs/${_tokenUri?.substring(7,200)}`; return formattedTokenUri; } - const formattedTokenUri = `https://ipfs.io/ipfs/${tokenUri!.substring( - 7, - 200 - )}`; - const formattedTokenName = String(tokenName); - const formattedTokenDescription = String(tokenDescription); return (
{/* DIV PARA EL INFO EN HOVER */} @@ -74,15 +67,15 @@ const NFTcard = ({ item }: { item: ExploreItem }) => {
{formattedTokenName}
-

{formattedTokenName}

+

{tokenName}

{ - - // console.log('tokenUri :: ', tokenUri) +const NFTProduct = ({ nftId, userAddress, nftData, listedNftData, creatorData, sellerData, offerData, buyerData } : NFTProductProps) => { const [showFormList, setShowFormList] = useState(false); const [formDataList, setFormDataList] = useState({ @@ -161,7 +194,6 @@ const NFTProduct = ({ nftId, userAddress, nftData, listedNftData, creatorData, s setShowFormList(!showFormList); }; - const HandleListItemSubmit = async (e: React.FormEvent) => { const handleListItemSubmit = async (e: React.FormEvent) => { e.preventDefault(); @@ -217,6 +249,12 @@ const NFTProduct = ({ nftId, userAddress, nftData, listedNftData, creatorData, s const decimalPlaces: number = 2; const creatorFeeInPerc: string = `${(creatorFee / 10000 * 100).toFixed(decimalPlaces)}%`; + // console.log('creatorImage', creatorImage) + console.log('isListed', isListed) + console.log('hasOffer', hasOffer) + console.log('isOwner', isOwner) + console.log('isApproved', isApproved) + return (
@@ -239,8 +277,7 @@ const NFTProduct = ({ nftId, userAddress, nftData, listedNftData, creatorData, s
-

Creator

- {/*
*/} +

Creator

-

Creator Address:

+

Address:

{shortenAddress(creatorAddress)}

-

Creator Fee:

+

Fee:

{creatorFeeInPerc}

-
-
-
-
-

Creator

-
-

{creatorName}

-
-
-
+ {isListed && (
-
+
-

Seller

- {/*
*/} +

List

-

Seller Address:

+

Seller Address:

{shortenAddress(sellerAddress)}

-

Price

+

Price:

{sellerAmount || null} ETH @@ -305,36 +332,35 @@ const NFTProduct = ({ nftId, userAddress, nftData, listedNftData, creatorData, s

)} {hasOffer && ( -
-
-
-
-

Buyer

- {/*
*/} - {``} -

{buyerName}

-
+
+
+
+
+

Offer

+ {``} +

{buyerName}

-
-
-
-

Buyer Address:

-

{shortenAddress(buyerAddress)}

-

Price

+
+
+
+
+

Buyer Address:

+

{shortenAddress(buyerAddress)}

+

Price:

{buyerAmount || null} ETH

-
+
)}
@@ -414,7 +440,10 @@ const NFTProduct = ({ nftId, userAddress, nftData, listedNftData, creatorData, s
); -}; +} + +export default NFTProduct; + export const getServerSideProps: GetServerSideProps = async (ctx) => { @@ -426,7 +455,7 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => { const nftId = parseInt(ctx.query.id as string); if (!nftId && nftId != 0) { - console.log("404"); + console.log("404") return { redirect: { destination: "/404", @@ -437,8 +466,8 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => { const nftData = await prisma.nft.findUnique({ where: { - tokenId: nftId, - }, + tokenId: nftId + } }); // console.log('nftData', nftData) @@ -536,8 +565,13 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => { offerDataOut = convertedNftData buyerDataOut = buyerData + + } else { + offerDataOut = null + buyerDataOut = null } + return { props: { nftId: nftId, @@ -565,9 +599,5 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => { offerData: null, buyerData: null }, - }; - -}; - - - + } +} \ No newline at end of file From 16ddbe01e861ce1e00dfcaecb47ca401c7cd8863 Mon Sep 17 00:00:00 2001 From: Joan Date: Fri, 14 Jul 2023 00:43:02 +0200 Subject: [PATCH 3/6] typos --- indexer/src/index.ts | 16 ++++++++-------- indexer/src/utils/apiUtils.ts | 3 --- .../auxFunctions/ApproveItemEthers.ts | 6 +++--- .../smart-contracts/auxFunctions/IsApproved.ts | 6 +++++- .../smart-contracts/auxFunctions/ReadOwnerOf.ts | 2 +- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/indexer/src/index.ts b/indexer/src/index.ts index 8fb77f6..37ee0f9 100644 --- a/indexer/src/index.ts +++ b/indexer/src/index.ts @@ -24,8 +24,8 @@ const connect = async () => { const trackContractCallback = async () => { const lastBlocks = await prisma.tracker_State.findMany(); - // await processFactoryTrackerEvents(lastBlocks[0].lastBlockProcessed, prisma); - // await processNftMarketplaceEvents(lastBlocks[0].lastBlockProcessed, prisma); + await processFactoryTrackerEvents(lastBlocks[0].lastBlockProcessed, prisma); + await processNftMarketplaceEvents(lastBlocks[0].lastBlockProcessed, prisma); await processDeadEvents(); setTimeout(() => trackContractCallback(), 20000); // Recursividad de trackeo }; @@ -39,18 +39,18 @@ const processDeadEvents = async () => { if(!deadEvents.length) return console.log("No hay que recuperar"); // de ser asi, llamar a callApi con esos datos - // try { + try { deadEvents.forEach(async (event: Dead_events_queue) => { console.log(event.eventName) - // console.log(event) + console.log(event) const success = await callApi(event.eventName, JSON.parse(event.data), true); console.log(success) return - // if(success) await prisma.dead_events_queue.delete({where: {id: event.id}}) + if(success) await prisma.dead_events_queue.delete({where: {id: event.id}}) }); - // } catch (error) { - // console.log(error); - // } + } catch (error) { + console.log(error); + } }; setTimeout(connect, 2000); // Para que el turbo repo no pete \ No newline at end of file diff --git a/indexer/src/utils/apiUtils.ts b/indexer/src/utils/apiUtils.ts index ee9a6c5..18d15e1 100644 --- a/indexer/src/utils/apiUtils.ts +++ b/indexer/src/utils/apiUtils.ts @@ -4,9 +4,6 @@ import axios from "axios"; export const callApi = async (endpoint: string, data: any, isDead = false) => { try { console.log("endpoint:", endpoint); - console.log(`${process.env.API_ENDPOINT}${endpoint}`) - console.log("data:", data); - const x = await axios.post(`${process.env.API_ENDPOINT}${endpoint}`, data); console.log(x.data) console.log("callapi success"); diff --git a/t3/src/smart-contracts/auxFunctions/ApproveItemEthers.ts b/t3/src/smart-contracts/auxFunctions/ApproveItemEthers.ts index 2cee9ab..0ebf5cb 100644 --- a/t3/src/smart-contracts/auxFunctions/ApproveItemEthers.ts +++ b/t3/src/smart-contracts/auxFunctions/ApproveItemEthers.ts @@ -4,7 +4,7 @@ import { ethers } from 'ethers'; declare global { interface Window { - ethereum: any; + ethereum: ethers.providers.ExternalProvider & { enable: () => Promise }; } } @@ -16,7 +16,7 @@ export default async function ApproveItem(tokenId: number) { const signer = provider.getSigner(); console.log("Account:", await signer.getAddress()); - const contract = new ethers.Contract(addresses.NFTFactory, NFTFactory_abi, signer); + const contract = new ethers.Contract(addresses.NFTFactory, NFTFactory_abi, signer) as ethers.Contract & { approve: (addresses: string, tokenId: number) => Promise }; async function callContractFunction() { try { @@ -38,7 +38,7 @@ export default async function ApproveItem(tokenId: number) { } } - callContractFunction() + await callContractFunction() } catch (error) { console.error('Error reading getApproved of token:', error); diff --git a/t3/src/smart-contracts/auxFunctions/IsApproved.ts b/t3/src/smart-contracts/auxFunctions/IsApproved.ts index be6bcc8..1c53407 100644 --- a/t3/src/smart-contracts/auxFunctions/IsApproved.ts +++ b/t3/src/smart-contracts/auxFunctions/IsApproved.ts @@ -8,7 +8,11 @@ export default async function IsApproved(tokenId: number) { const providerUrl = process.env.NEXT_PUBLIC_URL_MUMBAI; // Replace with the actual JSON-RPC URL const provider = new ethers.providers.JsonRpcProvider(providerUrl); - const contract = new ethers.Contract(addresses.NFTFactory, NFTFactory_abi, provider); + const contract = new ethers.Contract( + addresses.NFTFactory, + NFTFactory_abi, + provider + ) as ethers.Contract & { getApproved: (tokenId: number) => Promise }; const addressApproved = await contract.getApproved(tokenId); diff --git a/t3/src/smart-contracts/auxFunctions/ReadOwnerOf.ts b/t3/src/smart-contracts/auxFunctions/ReadOwnerOf.ts index 5714d5f..ee65fea 100644 --- a/t3/src/smart-contracts/auxFunctions/ReadOwnerOf.ts +++ b/t3/src/smart-contracts/auxFunctions/ReadOwnerOf.ts @@ -8,7 +8,7 @@ export default async function ReadOwnerOf(tokenId: number) { const providerUrl = process.env.NEXT_PUBLIC_URL_MUMBAI; // Replace with the actual JSON-RPC URL const provider = new ethers.providers.JsonRpcProvider(providerUrl); - const contract = new ethers.Contract(addresses.NFTFactory, NFTFactory_abi, provider); + const contract = new ethers.Contract(addresses.NFTFactory, NFTFactory_abi, provider) as ethers.Contract & {ownerOf: (id: number) => Promise}; // Call the `ownerOf` function to get the owner of a specific token const owner = await contract.ownerOf(tokenId); From ac65da9da7dfbef55bf962e17059a728e75d1a92 Mon Sep 17 00:00:00 2001 From: Joan Date: Fri, 14 Jul 2023 00:47:44 +0200 Subject: [PATCH 4/6] typos 2 --- indexer/src/index.ts | 6 +- .../api/indexerWebhooks/ItemListedCanceled.ts | 56 --------------- .../api/indexerWebhooks/auctionCreated.ts | 70 +++++++++++++++++++ 3 files changed, 71 insertions(+), 61 deletions(-) delete mode 100644 t3/src/pages/api/indexerWebhooks/ItemListedCanceled.ts diff --git a/indexer/src/index.ts b/indexer/src/index.ts index 37ee0f9..9d419f1 100644 --- a/indexer/src/index.ts +++ b/indexer/src/index.ts @@ -27,7 +27,7 @@ const connect = async () => { await processFactoryTrackerEvents(lastBlocks[0].lastBlockProcessed, prisma); await processNftMarketplaceEvents(lastBlocks[0].lastBlockProcessed, prisma); await processDeadEvents(); - setTimeout(() => trackContractCallback(), 20000); // Recursividad de trackeo + setTimeout(() => trackContractCallback(), 2000); // Recursividad de trackeo }; await trackContractCallback(); }; @@ -35,17 +35,13 @@ const connect = async () => { const processDeadEvents = async () => { // checkear si hay eventos muertos const deadEvents = await prisma.dead_events_queue.findMany(); - // console.log('deadEvents', deadEvents) if(!deadEvents.length) return console.log("No hay que recuperar"); // de ser asi, llamar a callApi con esos datos try { deadEvents.forEach(async (event: Dead_events_queue) => { console.log(event.eventName) - console.log(event) const success = await callApi(event.eventName, JSON.parse(event.data), true); - console.log(success) - return if(success) await prisma.dead_events_queue.delete({where: {id: event.id}}) }); } catch (error) { diff --git a/t3/src/pages/api/indexerWebhooks/ItemListedCanceled.ts b/t3/src/pages/api/indexerWebhooks/ItemListedCanceled.ts deleted file mode 100644 index 8da7876..0000000 --- a/t3/src/pages/api/indexerWebhooks/ItemListedCanceled.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { prisma } from "~/server/db"; -import type { NextApiRequest, NextApiResponse } from 'next'; - -export default async function handler( - req: NextApiRequest, - res: NextApiResponse, -) { - if(!(req.method === "POST")) { - return res.status(400).json({message: "unauthorized"}); - } - // Item Listed - const { tokenId, seller, amount, startingTime, endTime } = req.body; - - try { - await checkNftExists(tokenId, seller, amount, startingTime, endTime); - return res.status(200).json({message: "ok"}) - } catch (error) { - return res.status(500).json({message: JSON.stringify(error)}); - } -} - -const checkNftExists = async (tokenId: number, seller: string, amount: number, startingTime: number, endTime: number) => { - const item = await prisma.listedNft.findUnique({ - where: { - tokenId_startingTime: { - tokenId, startingTime, - } - } - }); - if(item) { - await prisma.listedNft.update({ - where: { - tokenId_startingTime: { - tokenId, startingTime, - } - }, - data: { - seller, - amount, - startingTime, - endTime, - isCancelled: false, - } - }); - } else { - await prisma.listedNft.create({ - data: { - tokenId, - seller, - amount, - startingTime, - endTime, - } - }); - } -} \ No newline at end of file diff --git a/t3/src/pages/api/indexerWebhooks/auctionCreated.ts b/t3/src/pages/api/indexerWebhooks/auctionCreated.ts index e69de29..5be7610 100644 --- a/t3/src/pages/api/indexerWebhooks/auctionCreated.ts +++ b/t3/src/pages/api/indexerWebhooks/auctionCreated.ts @@ -0,0 +1,70 @@ +import { prisma } from "~/server/db"; +import type { NextApiRequest, NextApiResponse } from 'next'; + +interface EndpointParams { + tokenId: number; + seller: string; + startingAmount: number; + startingTime: number; + endTime: number; +} + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse, +) { + if(!(req.method === "POST")) { + return res.status(400).json({message: "unauthorized"}); + } + + // tokenId, seller, startingAmount, startingTime, endTime + const params = req.body as EndpointParams; + + try { + await checkOfferExists( + params.tokenId, + params.seller, + params.startingAmount, + params.startingTime, + params.endTime + ); + return res.status(200).json({message: "ok"}); + } catch (error) { + return res.status(500).json({message: JSON.stringify(error)}); + } +} + +const checkOfferExists = async (tokenId: number, seller: string, startingAmount: number, startingTime: number, endTime: number) => { + const row = await prisma.auction.findUnique({ + where: { + tokenId_startingTime: { + tokenId, startingTime, + } + } + }); + if(row) { + await prisma.auction.update({ + where: { + tokenId_startingTime: { + tokenId, startingTime, + } + }, + data: { + seller: seller, + startingTime: startingTime, + startingAmount: startingAmount, + endTime: endTime, + } + }); + } else { + await prisma.auction.create({ + data: { + tokenId: tokenId, + seller: seller, + startingTime: startingTime, + startingAmount: startingAmount, + endTime: endTime, + } + }); + } +} \ No newline at end of file From 03a068662c40271efb619467030db27c78f9b09d Mon Sep 17 00:00:00 2001 From: Joan Date: Fri, 14 Jul 2023 13:04:57 +0200 Subject: [PATCH 5/6] final comit --- t3/src/pages/product/[id].tsx | 36 +++++++------------ .../auxFunctions/CreateOffer.ts | 9 +++-- .../auxFunctions/IsApproved.ts | 2 +- .../auxFunctions/ListItemEthers.ts | 11 +++--- 4 files changed, 22 insertions(+), 36 deletions(-) diff --git a/t3/src/pages/product/[id].tsx b/t3/src/pages/product/[id].tsx index 8584a61..1d49027 100644 --- a/t3/src/pages/product/[id].tsx +++ b/t3/src/pages/product/[id].tsx @@ -133,11 +133,11 @@ const NFTProduct = ({ nftId, userAddress, nftData, listedNftData, creatorData, s // Image - const _formattedTokenUri = await formatTokenUri(nftData.tokenUri) - const metadataIPFS = await axios.get(_formattedTokenUri) + const _formattedTokenUri = formatTokenUri(nftData.tokenUri) + const metadataIPFS: MetadataIPFS = await axios.get(_formattedTokenUri) const image = metadataIPFS.data.image - const formattedImage = await formatTokenUri(image) + const formattedImage = formatTokenUri(image) setTokenImage(formattedImage) } @@ -180,12 +180,12 @@ const NFTProduct = ({ nftId, userAddress, nftData, listedNftData, creatorData, s } useEffect(() => { - loadMainInfo() + loadMainInfo().catch(console.error); }, []) ////////////////////////////////////////// - async function formatTokenUri(_tokenUri: string) { + function formatTokenUri(_tokenUri: string) { const formattedTokenUri = `https://ipfs.io/ipfs/${_tokenUri?.substring(7,200)}`; return formattedTokenUri } @@ -234,20 +234,8 @@ const NFTProduct = ({ nftId, userAddress, nftData, listedNftData, creatorData, s setFormDataOffer({ ...formDataOffer, [e.target.name]: e.target.value }); }; - - - function shortenAddress(address: string): string { - // if (address.length < 10) { - // throw new Error('Invalid Ethereum address'); - // } - - const firstChars = address.slice(0, 6); - const lastChars = address.slice(-4); - return `${firstChars}...${lastChars}`; - } - - const decimalPlaces: number = 2; - const creatorFeeInPerc: string = `${(creatorFee / 10000 * 100).toFixed(decimalPlaces)}%`; + const decimalPlaces = 2; + const creatorFeeInPerc: string = (creatorFee / 10000 * 100).toFixed(decimalPlaces) + '%'; // console.log('creatorImage', creatorImage) console.log('isListed', isListed) @@ -391,7 +379,7 @@ const NFTProduct = ({ nftId, userAddress, nftData, listedNftData, creatorData, s )} {showFormList && ( -
+ handleListItemSubmit}> { }); // console.log('nftData', nftData) - async function formatTokenUri(_tokenUri: string) { + function formatTokenUri(_tokenUri: string) { const formattedTokenUri = `https://ipfs.io/ipfs/${_tokenUri?.substring(7,200)}`; return formattedTokenUri } if (nftData) { // Image - const _formattedTokenUri = await formatTokenUri(nftData.tokenUri) + const _formattedTokenUri = formatTokenUri(nftData.tokenUri) // console.log('_formattedTokenUri', _formattedTokenUri) - const metadataIPFS = await axios.get(_formattedTokenUri) + const metadataIPFS: MetadataIPFS = await axios.get(_formattedTokenUri) const image = metadataIPFS.data.image - const tokenImage = await formatTokenUri(image) + const tokenImage = formatTokenUri(image) // console.log('tokenImage', tokenImage) const currentTimestamp = Math.floor(Date.now() / 1000); // Get the current timestamp as a BigInt diff --git a/t3/src/smart-contracts/auxFunctions/CreateOffer.ts b/t3/src/smart-contracts/auxFunctions/CreateOffer.ts index f408a3b..61a485c 100644 --- a/t3/src/smart-contracts/auxFunctions/CreateOffer.ts +++ b/t3/src/smart-contracts/auxFunctions/CreateOffer.ts @@ -10,20 +10,19 @@ export default async function CreateOffer(_tokenId: number, _amount: number, _du const signer = provider.getSigner(); console.log("Account:", await signer.getAddress()); - const contract = new ethers.Contract(addresses.FrommeMarketplace, FrommeMarketplace_abi, signer); + const contract = new ethers.Contract(addresses.FrommeMarketplace, FrommeMarketplace_abi, signer) as ethers.Contract & { createOffer: (_tokenId: number, _durationInSeconds: number, value: {value: number}) => Promise } // Example function to send a transaction to the contract async function sendTransactionToContract() { - const amountInWei = ethers.utils.parseEther(_amount.toString()); + const amountInWei = Number(ethers.utils.parseEther(_amount.toString())) // console.log(amountInWei) - const tx = await contract.createOffer(_tokenId, _durationInSeconds, { value: amountInWei }); - await tx.wait(); // Wait for the transaction to be mined + await contract.createOffer(_tokenId, _durationInSeconds, { value: amountInWei }); console.log('Transaction mined!'); } - sendTransactionToContract() + await sendTransactionToContract() } catch (error) { console.error('Error making offer:', error); diff --git a/t3/src/smart-contracts/auxFunctions/IsApproved.ts b/t3/src/smart-contracts/auxFunctions/IsApproved.ts index 1c53407..7827e94 100644 --- a/t3/src/smart-contracts/auxFunctions/IsApproved.ts +++ b/t3/src/smart-contracts/auxFunctions/IsApproved.ts @@ -12,7 +12,7 @@ export default async function IsApproved(tokenId: number) { addresses.NFTFactory, NFTFactory_abi, provider - ) as ethers.Contract & { getApproved: (tokenId: number) => Promise }; + ) as ethers.Contract & { getApproved: (tokenId: number) => Promise }; const addressApproved = await contract.getApproved(tokenId); diff --git a/t3/src/smart-contracts/auxFunctions/ListItemEthers.ts b/t3/src/smart-contracts/auxFunctions/ListItemEthers.ts index d2c306e..36fb23d 100644 --- a/t3/src/smart-contracts/auxFunctions/ListItemEthers.ts +++ b/t3/src/smart-contracts/auxFunctions/ListItemEthers.ts @@ -5,25 +5,24 @@ import { ethers } from 'ethers'; export default async function ListItem(_tokenId: number, _amount: number, _durationInSeconds: number) { try { - const provider = new ethers.providers.Web3Provider(window.ethereum, "any"); + const provider = new ethers.providers.Web3Provider(window.ethereum as ethers.providers.ExternalProvider); await provider.send("eth_requestAccounts", []); const signer = provider.getSigner(); console.log("Account:", await signer.getAddress()); - const contract = new ethers.Contract(addresses.FrommeMarketplace, FrommeMarketplace_abi, signer); + const contract = new ethers.Contract(addresses.FrommeMarketplace, FrommeMarketplace_abi, signer) as ethers.Contract & { listItem: (_tokenId: number, _amount: number, _durationInSeconds: number) => Promise } // Example function to send a transaction to the contract async function sendTransactionToContract() { - const amountInWei = ethers.utils.parseEther(_amount.toString()); + const amountInWei = Number(ethers.utils.parseEther(_amount.toString())) // console.log(amountInWei) - const tx = await contract.listItem(_tokenId, amountInWei, _durationInSeconds); - await tx.wait(); // Wait for the transaction to be mined + await contract.listItem(_tokenId, amountInWei, _durationInSeconds); console.log('Transaction mined!'); } - sendTransactionToContract() + await sendTransactionToContract() } catch (error) { console.error('Error reading owner of token:', error); From 974a29a77e3558bf79685942163961b0468a33be Mon Sep 17 00:00:00 2001 From: Joan Date: Sat, 15 Jul 2023 13:25:16 +0200 Subject: [PATCH 6/6] offer Created changes --- indexer/src/index.ts | 9 +- indexer/src/utils/apiUtils.ts | 4 +- t3/package-lock.json | 209 ++++++++++-------- t3/package.json | 2 +- t3/prisma/schema.prisma | 14 +- .../pages/api/indexerWebhooks/offerCreated.ts | 17 +- t3/src/pages/product/[id].tsx | 89 ++++++-- t3/src/utils/shortenAddress.ts | 6 +- 8 files changed, 218 insertions(+), 132 deletions(-) diff --git a/indexer/src/index.ts b/indexer/src/index.ts index 9d419f1..66a152d 100644 --- a/indexer/src/index.ts +++ b/indexer/src/index.ts @@ -24,8 +24,8 @@ const connect = async () => { const trackContractCallback = async () => { const lastBlocks = await prisma.tracker_State.findMany(); - await processFactoryTrackerEvents(lastBlocks[0].lastBlockProcessed, prisma); - await processNftMarketplaceEvents(lastBlocks[0].lastBlockProcessed, prisma); + // await processFactoryTrackerEvents(lastBlocks[0].lastBlockProcessed, prisma); + // await processNftMarketplaceEvents(lastBlocks[0].lastBlockProcessed, prisma); await processDeadEvents(); setTimeout(() => trackContractCallback(), 2000); // Recursividad de trackeo }; @@ -34,7 +34,10 @@ const connect = async () => { const processDeadEvents = async () => { // checkear si hay eventos muertos - const deadEvents = await prisma.dead_events_queue.findMany(); + const deadEventsOriginal = await prisma.dead_events_queue.findMany(); + + const deadEvents = deadEventsOriginal.slice(7,8) + console.log(deadEvents) if(!deadEvents.length) return console.log("No hay que recuperar"); // de ser asi, llamar a callApi con esos datos diff --git a/indexer/src/utils/apiUtils.ts b/indexer/src/utils/apiUtils.ts index 18d15e1..a7086e5 100644 --- a/indexer/src/utils/apiUtils.ts +++ b/indexer/src/utils/apiUtils.ts @@ -3,9 +3,9 @@ import axios from "axios"; export const callApi = async (endpoint: string, data: any, isDead = false) => { try { - console.log("endpoint:", endpoint); + console.log("endpoint:", endpoint, ' : ', `${process.env.API_ENDPOINT}${endpoint}`); const x = await axios.post(`${process.env.API_ENDPOINT}${endpoint}`, data); - console.log(x.data) + console.log('DATA :: ', x.data) console.log("callapi success"); return true } catch (error) { diff --git a/t3/package-lock.json b/t3/package-lock.json index 118acd2..6119b9d 100644 --- a/t3/package-lock.json +++ b/t3/package-lock.json @@ -24,7 +24,7 @@ "axios": "^1.4.0", "dotenv": "^16.3.1", "ethers": "^5.7.2", - "next": "^13.4.2", + "next": "^13.4.10", "next-auth": ">=4.10.2 <=4.20.1", "nft.storage": "^7.1.0", "react": "18.2.0", @@ -3519,9 +3519,9 @@ } }, "node_modules/@next/env": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.4.tgz", - "integrity": "sha512-q/y7VZj/9YpgzDe64Zi6rY1xPizx80JjlU2BTevlajtaE3w1LqweH1gGgxou2N7hdFosXHjGrI4OUvtFXXhGLg==" + "version": "13.4.10", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.10.tgz", + "integrity": "sha512-3G1yD/XKTSLdihyDSa8JEsaWOELY+OWe08o0LUYzfuHp1zHDA8SObQlzKt+v+wrkkPcnPweoLH1ImZeUa0A1NQ==" }, "node_modules/@next/eslint-plugin-next": { "version": "13.4.4", @@ -3533,9 +3533,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.4.tgz", - "integrity": "sha512-xfjgXvp4KalNUKZMHmsFxr1Ug+aGmmO6NWP0uoh4G3WFqP/mJ1xxfww0gMOeMeSq/Jyr5k7DvoZ2Pv+XOITTtw==", + "version": "13.4.10", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.10.tgz", + "integrity": "sha512-4bsdfKmmg7mgFGph0UorD1xWfZ5jZEw4kKRHYEeTK9bT1QnMbPVPlVXQRIiFPrhoDQnZUoa6duuPUJIEGLV1Jg==", "cpu": [ "arm64" ], @@ -3548,9 +3548,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.4.tgz", - "integrity": "sha512-ZY9Ti1hkIwJsxGus3nlubIkvYyB0gNOYxKrfsOrLEqD0I2iCX8D7w8v6QQZ2H+dDl6UT29oeEUdDUNGk4UEpfg==", + "version": "13.4.10", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.10.tgz", + "integrity": "sha512-ngXhUBbcZIWZWqNbQSNxQrB9T1V+wgfCzAor2olYuo/YpaL6mUYNUEgeBMhr8qwV0ARSgKaOp35lRvB7EmCRBg==", "cpu": [ "x64" ], @@ -3563,9 +3563,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.4.tgz", - "integrity": "sha512-+KZnDeMShYkpkqAvGCEDeqYTRADJXc6SY1jWXz+Uo6qWQO/Jd9CoyhTJwRSxvQA16MoYzvILkGaDqirkRNctyA==", + "version": "13.4.10", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.10.tgz", + "integrity": "sha512-SjCZZCOmHD4uyM75MVArSAmF5Y+IJSGroPRj2v9/jnBT36SYFTORN8Ag/lhw81W9EeexKY/CUg2e9mdebZOwsg==", "cpu": [ "arm64" ], @@ -3578,9 +3578,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.4.tgz", - "integrity": "sha512-evC1twrny2XDT4uOftoubZvW3EG0zs0ZxMwEtu/dDGVRO5n5pT48S8qqEIBGBUZYu/Xx4zzpOkIxx1vpWdE+9A==", + "version": "13.4.10", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.10.tgz", + "integrity": "sha512-F+VlcWijX5qteoYIOxNiBbNE8ruaWuRlcYyIRK10CugqI/BIeCDzEDyrHIHY8AWwbkTwe6GRHabMdE688Rqq4Q==", "cpu": [ "arm64" ], @@ -3593,9 +3593,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.4.tgz", - "integrity": "sha512-PX706XcCHr2FfkyhP2lpf+pX/tUvq6/ke7JYnnr0ykNdEMo+sb7cC/o91gnURh4sPYSiZJhsF2gbIqg9rciOHQ==", + "version": "13.4.10", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.10.tgz", + "integrity": "sha512-WDv1YtAV07nhfy3i1visr5p/tjiH6CeXp4wX78lzP1jI07t4PnHHG1WEDFOduXh3WT4hG6yN82EQBQHDi7hBrQ==", "cpu": [ "x64" ], @@ -3608,9 +3608,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.4.tgz", - "integrity": "sha512-TKUUx3Ftd95JlHV6XagEnqpT204Y+IsEa3awaYIjayn0MOGjgKZMZibqarK3B1FsMSPaieJf2FEAcu9z0yT5aA==", + "version": "13.4.10", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.10.tgz", + "integrity": "sha512-zFkzqc737xr6qoBgDa3AwC7jPQzGLjDlkNmt/ljvQJ/Veri5ECdHjZCUuiTUfVjshNIIpki6FuP0RaQYK9iCRg==", "cpu": [ "x64" ], @@ -3623,9 +3623,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.4.tgz", - "integrity": "sha512-FP8AadgSq4+HPtim7WBkCMGbhr5vh9FePXiWx9+YOdjwdQocwoCK5ZVC3OW8oh3TWth6iJ0AXJ/yQ1q1cwSZ3A==", + "version": "13.4.10", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.10.tgz", + "integrity": "sha512-IboRS8IWz5mWfnjAdCekkl8s0B7ijpWeDwK2O8CdgZkoCDY0ZQHBSGiJ2KViAG6+BJVfLvcP+a2fh6cdyBr9QQ==", "cpu": [ "arm64" ], @@ -3638,9 +3638,9 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.4.tgz", - "integrity": "sha512-3WekVmtuA2MCdcAOrgrI+PuFiFURtSyyrN1I3UPtS0ckR2HtLqyqmS334Eulf15g1/bdwMteePdK363X/Y9JMg==", + "version": "13.4.10", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.10.tgz", + "integrity": "sha512-bSA+4j8jY4EEiwD/M2bol4uVEu1lBlgsGdvM+mmBm/BbqofNBfaZ2qwSbwE2OwbAmzNdVJRFRXQZ0dkjopTRaQ==", "cpu": [ "ia32" ], @@ -3653,9 +3653,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.4.tgz", - "integrity": "sha512-AHRITu/CrlQ+qzoqQtEMfaTu7GHaQ6bziQln/pVWpOYC1wU+Mq6VQQFlsDtMCnDztPZtppAXdvvbNS7pcfRzlw==", + "version": "13.4.10", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.10.tgz", + "integrity": "sha512-g2+tU63yTWmcVQKDGY0MV1PjjqgZtwM4rB1oVVi/v0brdZAcrcTV+04agKzWtvWroyFz6IqtT0MoZJA7PNyLVw==", "cpu": [ "x64" ], @@ -10634,6 +10634,11 @@ "node": ">=10.13.0" } }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + }, "node_modules/globals": { "version": "13.20.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", @@ -13995,16 +14000,17 @@ "peer": true }, "node_modules/next": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/next/-/next-13.4.4.tgz", - "integrity": "sha512-C5S0ysM0Ily9McL4Jb48nOQHT1BukOWI59uC3X/xCMlYIh9rJZCv7nzG92J6e1cOBqQbKovlpgvHWFmz4eKKEA==", + "version": "13.4.10", + "resolved": "https://registry.npmjs.org/next/-/next-13.4.10.tgz", + "integrity": "sha512-4ep6aKxVTQ7rkUW2fBLhpBr/5oceCuf4KmlUpvG/aXuDTIf9mexNSpabUD6RWPspu6wiJJvozZREhXhueYO36A==", "dependencies": { - "@next/env": "13.4.4", + "@next/env": "13.4.10", "@swc/helpers": "0.5.1", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001406", "postcss": "8.4.14", "styled-jsx": "5.1.1", + "watchpack": "2.4.0", "zod": "3.21.4" }, "bin": { @@ -14014,15 +14020,15 @@ "node": ">=16.8.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "13.4.4", - "@next/swc-darwin-x64": "13.4.4", - "@next/swc-linux-arm64-gnu": "13.4.4", - "@next/swc-linux-arm64-musl": "13.4.4", - "@next/swc-linux-x64-gnu": "13.4.4", - "@next/swc-linux-x64-musl": "13.4.4", - "@next/swc-win32-arm64-msvc": "13.4.4", - "@next/swc-win32-ia32-msvc": "13.4.4", - "@next/swc-win32-x64-msvc": "13.4.4" + "@next/swc-darwin-arm64": "13.4.10", + "@next/swc-darwin-x64": "13.4.10", + "@next/swc-linux-arm64-gnu": "13.4.10", + "@next/swc-linux-arm64-musl": "13.4.10", + "@next/swc-linux-x64-gnu": "13.4.10", + "@next/swc-linux-x64-musl": "13.4.10", + "@next/swc-win32-arm64-msvc": "13.4.10", + "@next/swc-win32-ia32-msvc": "13.4.10", + "@next/swc-win32-x64-msvc": "13.4.10" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", @@ -18789,6 +18795,18 @@ "makeerror": "1.0.12" } }, + "node_modules/watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", @@ -21507,9 +21525,9 @@ "requires": {} }, "@next/env": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.4.tgz", - "integrity": "sha512-q/y7VZj/9YpgzDe64Zi6rY1xPizx80JjlU2BTevlajtaE3w1LqweH1gGgxou2N7hdFosXHjGrI4OUvtFXXhGLg==" + "version": "13.4.10", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.10.tgz", + "integrity": "sha512-3G1yD/XKTSLdihyDSa8JEsaWOELY+OWe08o0LUYzfuHp1zHDA8SObQlzKt+v+wrkkPcnPweoLH1ImZeUa0A1NQ==" }, "@next/eslint-plugin-next": { "version": "13.4.4", @@ -21521,57 +21539,57 @@ } }, "@next/swc-darwin-arm64": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.4.tgz", - "integrity": "sha512-xfjgXvp4KalNUKZMHmsFxr1Ug+aGmmO6NWP0uoh4G3WFqP/mJ1xxfww0gMOeMeSq/Jyr5k7DvoZ2Pv+XOITTtw==", + "version": "13.4.10", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.10.tgz", + "integrity": "sha512-4bsdfKmmg7mgFGph0UorD1xWfZ5jZEw4kKRHYEeTK9bT1QnMbPVPlVXQRIiFPrhoDQnZUoa6duuPUJIEGLV1Jg==", "optional": true }, "@next/swc-darwin-x64": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.4.tgz", - "integrity": "sha512-ZY9Ti1hkIwJsxGus3nlubIkvYyB0gNOYxKrfsOrLEqD0I2iCX8D7w8v6QQZ2H+dDl6UT29oeEUdDUNGk4UEpfg==", + "version": "13.4.10", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.10.tgz", + "integrity": "sha512-ngXhUBbcZIWZWqNbQSNxQrB9T1V+wgfCzAor2olYuo/YpaL6mUYNUEgeBMhr8qwV0ARSgKaOp35lRvB7EmCRBg==", "optional": true }, "@next/swc-linux-arm64-gnu": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.4.tgz", - "integrity": "sha512-+KZnDeMShYkpkqAvGCEDeqYTRADJXc6SY1jWXz+Uo6qWQO/Jd9CoyhTJwRSxvQA16MoYzvILkGaDqirkRNctyA==", + "version": "13.4.10", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.10.tgz", + "integrity": "sha512-SjCZZCOmHD4uyM75MVArSAmF5Y+IJSGroPRj2v9/jnBT36SYFTORN8Ag/lhw81W9EeexKY/CUg2e9mdebZOwsg==", "optional": true }, "@next/swc-linux-arm64-musl": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.4.tgz", - "integrity": "sha512-evC1twrny2XDT4uOftoubZvW3EG0zs0ZxMwEtu/dDGVRO5n5pT48S8qqEIBGBUZYu/Xx4zzpOkIxx1vpWdE+9A==", + "version": "13.4.10", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.10.tgz", + "integrity": "sha512-F+VlcWijX5qteoYIOxNiBbNE8ruaWuRlcYyIRK10CugqI/BIeCDzEDyrHIHY8AWwbkTwe6GRHabMdE688Rqq4Q==", "optional": true }, "@next/swc-linux-x64-gnu": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.4.tgz", - "integrity": "sha512-PX706XcCHr2FfkyhP2lpf+pX/tUvq6/ke7JYnnr0ykNdEMo+sb7cC/o91gnURh4sPYSiZJhsF2gbIqg9rciOHQ==", + "version": "13.4.10", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.10.tgz", + "integrity": "sha512-WDv1YtAV07nhfy3i1visr5p/tjiH6CeXp4wX78lzP1jI07t4PnHHG1WEDFOduXh3WT4hG6yN82EQBQHDi7hBrQ==", "optional": true }, "@next/swc-linux-x64-musl": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.4.tgz", - "integrity": "sha512-TKUUx3Ftd95JlHV6XagEnqpT204Y+IsEa3awaYIjayn0MOGjgKZMZibqarK3B1FsMSPaieJf2FEAcu9z0yT5aA==", + "version": "13.4.10", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.10.tgz", + "integrity": "sha512-zFkzqc737xr6qoBgDa3AwC7jPQzGLjDlkNmt/ljvQJ/Veri5ECdHjZCUuiTUfVjshNIIpki6FuP0RaQYK9iCRg==", "optional": true }, "@next/swc-win32-arm64-msvc": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.4.tgz", - "integrity": "sha512-FP8AadgSq4+HPtim7WBkCMGbhr5vh9FePXiWx9+YOdjwdQocwoCK5ZVC3OW8oh3TWth6iJ0AXJ/yQ1q1cwSZ3A==", + "version": "13.4.10", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.10.tgz", + "integrity": "sha512-IboRS8IWz5mWfnjAdCekkl8s0B7ijpWeDwK2O8CdgZkoCDY0ZQHBSGiJ2KViAG6+BJVfLvcP+a2fh6cdyBr9QQ==", "optional": true }, "@next/swc-win32-ia32-msvc": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.4.tgz", - "integrity": "sha512-3WekVmtuA2MCdcAOrgrI+PuFiFURtSyyrN1I3UPtS0ckR2HtLqyqmS334Eulf15g1/bdwMteePdK363X/Y9JMg==", + "version": "13.4.10", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.10.tgz", + "integrity": "sha512-bSA+4j8jY4EEiwD/M2bol4uVEu1lBlgsGdvM+mmBm/BbqofNBfaZ2qwSbwE2OwbAmzNdVJRFRXQZ0dkjopTRaQ==", "optional": true }, "@next/swc-win32-x64-msvc": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.4.tgz", - "integrity": "sha512-AHRITu/CrlQ+qzoqQtEMfaTu7GHaQ6bziQln/pVWpOYC1wU+Mq6VQQFlsDtMCnDztPZtppAXdvvbNS7pcfRzlw==", + "version": "13.4.10", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.10.tgz", + "integrity": "sha512-g2+tU63yTWmcVQKDGY0MV1PjjqgZtwM4rB1oVVi/v0brdZAcrcTV+04agKzWtvWroyFz6IqtT0MoZJA7PNyLVw==", "optional": true }, "@noble/curves": { @@ -27022,6 +27040,11 @@ "is-glob": "^4.0.3" } }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + }, "globals": { "version": "13.20.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", @@ -29659,25 +29682,26 @@ "peer": true }, "next": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/next/-/next-13.4.4.tgz", - "integrity": "sha512-C5S0ysM0Ily9McL4Jb48nOQHT1BukOWI59uC3X/xCMlYIh9rJZCv7nzG92J6e1cOBqQbKovlpgvHWFmz4eKKEA==", - "requires": { - "@next/env": "13.4.4", - "@next/swc-darwin-arm64": "13.4.4", - "@next/swc-darwin-x64": "13.4.4", - "@next/swc-linux-arm64-gnu": "13.4.4", - "@next/swc-linux-arm64-musl": "13.4.4", - "@next/swc-linux-x64-gnu": "13.4.4", - "@next/swc-linux-x64-musl": "13.4.4", - "@next/swc-win32-arm64-msvc": "13.4.4", - "@next/swc-win32-ia32-msvc": "13.4.4", - "@next/swc-win32-x64-msvc": "13.4.4", + "version": "13.4.10", + "resolved": "https://registry.npmjs.org/next/-/next-13.4.10.tgz", + "integrity": "sha512-4ep6aKxVTQ7rkUW2fBLhpBr/5oceCuf4KmlUpvG/aXuDTIf9mexNSpabUD6RWPspu6wiJJvozZREhXhueYO36A==", + "requires": { + "@next/env": "13.4.10", + "@next/swc-darwin-arm64": "13.4.10", + "@next/swc-darwin-x64": "13.4.10", + "@next/swc-linux-arm64-gnu": "13.4.10", + "@next/swc-linux-arm64-musl": "13.4.10", + "@next/swc-linux-x64-gnu": "13.4.10", + "@next/swc-linux-x64-musl": "13.4.10", + "@next/swc-win32-arm64-msvc": "13.4.10", + "@next/swc-win32-ia32-msvc": "13.4.10", + "@next/swc-win32-x64-msvc": "13.4.10", "@swc/helpers": "0.5.1", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001406", "postcss": "8.4.14", "styled-jsx": "5.1.1", + "watchpack": "2.4.0", "zod": "3.21.4" }, "dependencies": { @@ -33165,6 +33189,15 @@ "makeerror": "1.0.12" } }, + "watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, "wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", diff --git a/t3/package.json b/t3/package.json index 38cab3b..8224024 100644 --- a/t3/package.json +++ b/t3/package.json @@ -26,7 +26,7 @@ "axios": "^1.4.0", "dotenv": "^16.3.1", "ethers": "^5.7.2", - "next": "^13.4.2", + "next": "^13.4.10", "next-auth": ">=4.10.2 <=4.20.1", "nft.storage": "^7.1.0", "react": "18.2.0", diff --git a/t3/prisma/schema.prisma b/t3/prisma/schema.prisma index 72e5c03..d1194fe 100644 --- a/t3/prisma/schema.prisma +++ b/t3/prisma/schema.prisma @@ -104,11 +104,13 @@ model Auction { } model Offer { - nft Nft @relation(fields: [tokenId], references: [tokenId], onDelete: Cascade) - tokenId Int - buyer String - amount BigInt - isCancelled Boolean @default(false) + tokenId Int + buyer String + amount BigInt + startingTime Int + isCancelled Boolean @default(false) - @@unique([tokenId, buyer]) + nft Nft @relation(fields: [tokenId], references: [tokenId], onDelete: Cascade) + + @@unique([tokenId, startingTime]) } diff --git a/t3/src/pages/api/indexerWebhooks/offerCreated.ts b/t3/src/pages/api/indexerWebhooks/offerCreated.ts index f7cd148..86720cd 100644 --- a/t3/src/pages/api/indexerWebhooks/offerCreated.ts +++ b/t3/src/pages/api/indexerWebhooks/offerCreated.ts @@ -9,27 +9,29 @@ export default async function handler( return res.status(400).json({message: "unauthorized"}); } + type Body = { tokenId: number, buyer: string, amount: number, + startingTime: number, } - const { tokenId, buyer, amount } = req.body as Body; + const { tokenId, buyer, amount, startingTime } = req.body as Body; try { - await checkOfferExists(tokenId, buyer, amount); + await checkOfferExists(tokenId, buyer, amount, startingTime); return res.status(200).json({message: "ok"}) } catch (error) { return res.status(500).json({message: JSON.stringify(error)}); } } -const checkOfferExists = async (tokenId: number, buyer: string, amount: number) => { +const checkOfferExists = async (tokenId: number, buyer: string, amount: number, startingTime: number) => { const row = await prisma.offer.findUnique({ where: { - tokenId_buyer: { - tokenId, buyer, + tokenId_startingTime: { + tokenId, startingTime, } } }); @@ -37,8 +39,8 @@ const checkOfferExists = async (tokenId: number, buyer: string, amount: number) if(row) { await prisma.offer.update({ where: { - tokenId_buyer: { - tokenId, buyer, + tokenId_startingTime: { + tokenId, startingTime, } }, data: { @@ -53,6 +55,7 @@ const checkOfferExists = async (tokenId: number, buyer: string, amount: number) tokenId, buyer, amount, + startingTime, isCancelled: false, } }); diff --git a/t3/src/pages/product/[id].tsx b/t3/src/pages/product/[id].tsx index 1d49027..b93bf4b 100644 --- a/t3/src/pages/product/[id].tsx +++ b/t3/src/pages/product/[id].tsx @@ -26,11 +26,17 @@ interface MetadataIPFS { } } -type ItemData = { +type ItemDataList = { amountList: number; durationList: number; }; +type ItemDataOffer = { + amountOffer: number; + durationOffer: number; +}; + + type NFTProductProps = { nftId: number, userAddress: string, @@ -83,15 +89,15 @@ type NFTProductProps = { const NFTProduct = ({ nftId, userAddress, nftData, listedNftData, creatorData, sellerData, offerData, buyerData } : NFTProductProps) => { const [showFormList, setShowFormList] = useState(false); - const [formDataList, setFormDataList] = useState({ + const [formDataList, setFormDataList] = useState({ amountList: 0, durationList: 0, }); - const [showOfferList, setShowOfferList] = useState(false); - const [formDataOffer, setFormDataOffer] = useState({ - amountList: 0, - durationList: 0, + const [showFormOffer, setShowFormOffer] = useState(false); + const [formDataOffer, setFormDataOffer] = useState({ + amountOffer: 0, + durationOffer: 0, }); // logic moved from the server side props: @@ -125,7 +131,7 @@ const NFTProduct = ({ nftId, userAddress, nftData, listedNftData, creatorData, s const addressApproved = await IsApproved(nftId); setIsApproved(addresses.FrommeMarketplace == addressApproved) - setIsOwnerd(ownerOFNft == userAddress) + setIsOwnerd(await ReadOwnerOf(nftId) == userAddress) if(nftData) { setCreatorAddress(nftData.creator) @@ -197,25 +203,25 @@ const NFTProduct = ({ nftId, userAddress, nftData, listedNftData, creatorData, s const handleListItemSubmit = async (e: React.FormEvent) => { e.preventDefault(); - setFormDataList(formDataList); - setShowFormList(false); + console.log("List Submited", nftId, formDataList) - // send data to contract + setFormDataList(formDataList); await ListItem(nftId, formDataList.amountList, formDataList.durationList) + setShowFormList(false); }; const handleCreateOffer = () => { - setShowOfferList(!showOfferList); + setShowFormOffer(!showFormOffer); }; const handleCreateOfferSubmit = async (e: React.FormEvent) => { e.preventDefault(); - setFormDataOffer(formDataOffer); - setShowOfferList(false); + console.log("Offer Submited", nftId, formDataOffer) - // send data to contract - await CreateOffer(nftId, formDataOffer.amountList, formDataOffer.durationList) + setFormDataOffer(formDataOffer); + await CreateOffer(nftId, formDataOffer.amountOffer, formDataOffer.durationOffer) + setShowFormOffer(false); }; const handleCancelListSubmit = async (e: React.FormEvent) => { @@ -227,10 +233,12 @@ const NFTProduct = ({ nftId, userAddress, nftData, listedNftData, creatorData, s }; const handleInputChangeList = (e: React.ChangeEvent) => { + console.log("formDataList :: ", formDataList) setFormDataList({ ...formDataList, [e.target.name]: e.target.value }); }; const handleInputChangeOffer = (e: React.ChangeEvent) => { + console.log("formDataOffer :: ", formDataOffer) setFormDataOffer({ ...formDataOffer, [e.target.name]: e.target.value }); }; @@ -238,10 +246,13 @@ const NFTProduct = ({ nftId, userAddress, nftData, listedNftData, creatorData, s const creatorFeeInPerc: string = (creatorFee / 10000 * 100).toFixed(decimalPlaces) + '%'; // console.log('creatorImage', creatorImage) - console.log('isListed', isListed) - console.log('hasOffer', hasOffer) - console.log('isOwner', isOwner) - console.log('isApproved', isApproved) + // console.log('isListed', isListed) + // console.log('hasOffer', hasOffer) + // console.log('isOwner', isOwner) + // console.log('isApproved', isApproved) + + // console.log('ownerOFNft', ownerOFNft) + // console.log('userAddress', userAddress) return (
@@ -373,13 +384,15 @@ const NFTProduct = ({ nftId, userAddress, nftData, listedNftData, creatorData, s Approve Item )} + + {isListed == false && isOwner == true && isApproved == true && ( )} {showFormList && ( - handleListItemSubmit}> + - Submit + Submit List + + + )} + + {isOwner == false && ( + + )} + {showFormOffer && ( +
+ + +
)} diff --git a/t3/src/utils/shortenAddress.ts b/t3/src/utils/shortenAddress.ts index c17dd03..56819cd 100644 --- a/t3/src/utils/shortenAddress.ts +++ b/t3/src/utils/shortenAddress.ts @@ -1,7 +1,7 @@ function shortenAddress(address: string): string { - if (address.length < 10) { - throw new Error("Invalid Ethereum address"); - } + // if (address.length < 10) { + // throw new Error("Invalid Ethereum address"); + // } const firstChars = address.slice(0, 6); const lastChars = address.slice(-4);