diff --git a/.env b/.env new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/.env @@ -0,0 +1 @@ + diff --git a/README.md b/README.md index b12f3e3..742da02 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,64 @@ -This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). +# Allie's Marketplace -## Getting Started +### Project Overview 📄 -First, run the development server: +Allie’s Marketplace is an NFT marketplace built on NEAR Protocol. This is a hub for Allie’s own content and where her fans can buy her NFTs. The marketplace will also offer a variety of other content, including: videos, photos, and articles from Allie. The marketplace will be open to anyone who wants to purchase Allie’s content, and all transactions will be processed on the blockchain. This will provide a secure and efficient way for Allie to sell her content and connect with her fans. -```bash -npm run dev -# or -yarn dev -``` +## Goal -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. +Our goal is to encourage web3 space adoption and utilisation by not-safe-for-work (NSFW) content producers through the development of a user-friendly and engaging NFT marketplace. -You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. +Since our software is open source, anyone can use it to create their own decentralised marketplace. For creators who struggle to make money on centralised platforms and do not have full control over their content, this will be incredibly helpful. Because the marketplaces built on this code will be decentralised, they will also be shielded from censorship. + +## Code Details + +**Technology stack:** + +- Backend: -[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`. + - Node.js + - Express.js + - MongoDB + - Supabase (For censored content storage) + - [MintbaseJS](https://github.com/Mintbase/mintbase-js) (For Authentication) -The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. +- Frontend: -## Learn More + - NextJS (ReactJS) + - [MintbaseJS](https://github.com/Mintbase/mintbase-js) (For Contract Interaction) -To learn more about Next.js, take a look at the following resources: +## How To Run Code -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. +> :warning: **Fill the .env file before run the code**: need env variables in given in .env file template -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! +### Backend -## Deploy on Vercel +First, run the backend server: + +```bash +#1 +npm install +#2 +npm run start +``` -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. +Open http://localhost:[PORT] with your browser to see the result. -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. +You can start editing the page by modifying `app.js`. The page auto-updates as you edit the file. + +### Frontend + +First, run the development server: + +```bash +#1 +npm install +#2 +npm run dev +# or +yarn dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. diff --git a/components/Buy.jsx b/components/Buy.jsx index 943fd9a..ac1e1b8 100644 --- a/components/Buy.jsx +++ b/components/Buy.jsx @@ -1,116 +1,261 @@ +/* eslint-disable @next/next/no-img-element */ +import Link from "next/link"; import { useEffect, useState } from "react"; -import { Wallet, Chain, Network } from "mintbase"; +import { useWallet } from "@mintbase-js/react"; +import { execute, buy } from "@mintbase-js/sdk"; +import { utils } from "near-api-js"; +import fetchGraphQL from "../packages/FetchGraphQL"; export const Buy = ({ meta }) => { - const [nftdata, setNFTData] = useState(); + const [nftData, setNFTData] = useState(); + const { selector } = useWallet(); - useEffect(() => { - async function fetchGraphQL(operationsDoc, operationName, variables) { - const result = await fetch( - "https://interop-testnet.hasura.app/v1/graphql", - { - method: "POST", - body: JSON.stringify({ - query: operationsDoc, - variables: variables, - operationName: operationName, - }), - } - ); - // console.log(`hi: ${await result.json()}`); - return await result; - } - const operations = (metadata_id_) => { - return ` - query checkNFT { - mb_views_active_listings( - where: {metadata_id: {_eq: "${metadata_id_}"}} - limit: 1 - ) { - token_id - nft_contract_id - title - price - description - media - market_id - } - } - `; - }; + const priceYocto = nftData?.price.toLocaleString().replace(/,/g, ""); + const priceNear = utils.format.formatNearAmount(priceYocto, 2); - const setbuydata = async () => { - setNFTData( - await (await fetchGraphQL(operations(meta), "checkNFT", {})).json() - ); - }; - setbuydata(); - }, []); - const onclkBtn = async () => { - console.log(nftdata); - const { data, error } = await new Wallet().init({ - networkName: Network.testnet, - chain: Chain.near, - apiKey: "511a3b51-2ed5-4a27-b165-a27a01eebe0a", - }); - const { wallet } = data; - const tokenId = `${nftdata.data.mb_views_active_listings[0].nft_contract_id}:${nftdata.data.mb_views_active_listings[0].token_id}`; - const price = `${nftdata.data.mb_views_active_listings[0].price.toLocaleString( - "fullwide", - { useGrouping: false } - )}`; + const handleBuyToken = async (nftContractId, tokenId, price) => { + const wallet = await selector.wallet(); - const marketAddress = nftdata.data.mb_views_active_listings[0].market_id; + await execute( + { wallet }, + buy({ + tokenId, + price, + contractAddress: nftContractId, + affiliateAccount: process.env.NEXT_PUBLIC_REFERRAL_ID, + }) + ); + }; - const buyNFT = await wallet.makeOffer(tokenId, price, { - marketAddress, - }); - console.log(`buynft: ${buyNFT}`); + const TOKEN_QUERY = (metadata_id_) => { + return ` + query checkNFT { + mb_views_active_listings( + where: {metadata_id: {_eq: "${metadata_id_}"}} + limit: 1 + order_by: {price: asc} + ) { + token_id + nft_contract_id + title + price + description + media + market_id + } + } + `; }; - const ele = nftdata ? ( -
-
-
-
- NFT image -

- {nftdata.data.mb_views_active_listings[0].title} -

-

- {nftdata.data.mb_views_active_listings[0].description} -

- - {nftdata.data.mb_views_active_listings[0].price.toLocaleString( - "fullwide", - { useGrouping: false } - ) % 18} - NEAR - -
-
- + const fetchTokenData = async () => { + const tokenData = await fetchGraphQL(TOKEN_QUERY(meta), "checkNFT", {}); + setNFTData(tokenData?.data.mb_views_active_listings[0]); + }; + + useEffect(() => { + fetchTokenData(); + }); + + const NoTokens = ( +
+
+
+
+
+

NFTs are sold.

+
+
+ Check other collections here. +
+ ); + + const TokenBuy = nftData ? ( + <> +
+
+
+
+
+

NFT Details

+
+
    +
  1. Buy this NFT to unlock the collection
  2. +
+
+
+
+
+
+
+
+
+
+
+
+
+ item-img +
+
+ +
+
+
+
+
+
+
+

Name: {nftData.title}

+ {/* */} +
+ +
+

Price :

+

+ + + {priceNear}N + +

+
+
{ + e.preventDefault(); + handleBuyToken( + nftData.nft_contract_id, + nftData.token_id, + priceYocto + ); + }} + > +
+ Buy Now{" "} +
+
+
+
+
+
+
+
+ ) : ( -

hi

+
+
+
+
+
+

Sorry! This NFT is Sold Out.

+
+
    +
  1. + Please Check Other Collections. +
  2. +
+
+
+
+
); - return ele; + return nftData ? TokenBuy : NoTokens; }; diff --git a/components/CollectionCard.jsx b/components/CollectionCard.jsx new file mode 100644 index 0000000..44a0ed1 --- /dev/null +++ b/components/CollectionCard.jsx @@ -0,0 +1,98 @@ +import Link from "next/link"; +import Image from "next/image"; +import { useState, useEffect } from "react"; +import { utils } from "near-api-js"; +import fetchGraphQL from "../packages/FetchGraphQL"; + +export const CollectionCard = ({ post }) => { + const [nftData, setNFTData] = useState(); + + const priceYocto = nftData?.price.toLocaleString().replace(/,/g, ""); + const priceNear = utils.format.formatNearAmount(priceYocto, 2); + + const TOKEN_QUERY = (metadata_id_) => { + return ` + query checkNFT { + mb_views_active_listings( + where: {metadata_id: {_eq: "${metadata_id_}"}} + limit: 1 + order_by: {price: asc} + ) { + price + } + } + `; + }; + + const fetchTokenData = async () => { + const tokenData = await fetchGraphQL( + TOKEN_QUERY(post.metadata_id), + "checkNFT", + {} + ); + setNFTData(tokenData?.data.mb_views_active_listings[0]); + }; + + useEffect(() => { + fetchTokenData(); + }); + + return ( + +
+
+ {/* */} +
+
+
    +
  • + + author-img + +
    + Allie eve knox +
    +
  • +
+
+
+ {/* */} +
+
+ nft-img +
+
+

{post.name}

+
+

+ Price:{" "} + + {priceNear <= 0 ? "Sold out" : priceNear + " N"} + +

+
+
+
+
+
+ + ); +}; diff --git a/components/Footer.jsx b/components/Footer.jsx index e302c93..f65f8d1 100644 --- a/components/Footer.jsx +++ b/components/Footer.jsx @@ -1,42 +1,192 @@ +import { useState, useEffect } from "react"; + export const Footer = () => { + const [isMobile, setIsMobile] = useState(); + + const footerStyle = () => { + let style; + if (isMobile) { + style = { + display: "flex", + width: "100%", + justifyContent: "space-between", + flexDirection: "column", + alignItems: "center" + }; + } else { + style = { + display: "flex", + width: "100%", + justifyContent: "space-between", + }; + } + + return style; + }; + + useEffect(() => { + function handleResize() { + setIsMobile(window.innerWidth < 768); + } + + window.addEventListener("resize", handleResize); + handleResize(); + return () => window.removeEventListener("resize", handleResize); + }, [setIsMobile, isMobile]); + return ( -