Skip to content

Commit 7896b7d

Browse files
committed
Add marketplace page with displayed listings
1 parent 378f55d commit 7896b7d

11 files changed

+1493
-16
lines changed

abis/RMRKMarketplace.json

+1,236
Large diffs are not rendered by default.

abis/abis.ts

+2
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ import RMRKMultiResourceImpl from './RMRKMultiResourceImpl.json';
22
import RMRKMultiResourceFactory from './RMRKMultiResourceFactory.json';
33
import RMRKNestingFactory from './RMRKNestingFactory.json';
44
import RMRKNestingMultiResourceImpl from './RMRKNestingMultiResourceImpl.json';
5+
import RMRKMarketplace from './RMRKMarketplace.json';
56

67
const abis = {
78
multiResourceAbi: RMRKMultiResourceImpl.abi,
89
multiResourceFactoryAbi: RMRKMultiResourceFactory.abi,
910
nestingFactoryAbi: RMRKNestingFactory.abi,
1011
nestingImplAbi: RMRKNestingMultiResourceImpl.abi,
12+
marketplaceAbi: RMRKMarketplace.abi,
1113
};
1214

1315
export default abis;

components/nft-list.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ const NftList = (props: {
88
}) => {
99
return (
1010
<div className={styles.grid}>
11+
<h3 className="font-semibold">Your RMRK NFTs: {props.nfts?.length}</h3>
1112
<div className={styles.container}>
12-
<h3>Your RMRK NFTs: {props.nfts?.length}</h3>
1313
{props.nfts?.map((nft, index) => {
1414
return (
1515
<div key={index}>

constants.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11

22
import abis from './abis/abis';
33

4+
// MoonbaseAlpha deployments
45
export const RMRKMultiResourceFactoryContractAddress = '0x8E1214B2eD8a8581D1f35f525d82E9077C2c7513';
56
export const RMRKNestingFactoryContractAddress = '0x2a962fA5DD393507B2b1C527d2aa52EBC298f689';
7+
export const RMRKMarketplaceContractAddress = '0x4752025558E04618D6DEF4b7304F9dd7DcA49eab';
68

79
//Moonscan MR https://moonbase.moonscan.io/address/0xB77520a5D97CAF7DEBC5AF7A28C19c49F063B4A5
810
//Moonscan Nesting https://moonbase.moonscan.io/address/0xd0c004801Af669857Bf0241235b7cBC3897F5932
@@ -12,7 +14,12 @@ export const multiResourceFactoryContract = {
1214
contractInterface: abis.multiResourceFactoryAbi
1315
}
1416

15-
export const nestingFactoryContract = {
17+
export const nestingFactoryContractDetails = {
1618
addressOrName: RMRKNestingFactoryContractAddress,
1719
contractInterface: abis.nestingFactoryAbi
1820
}
21+
22+
export const marketplaceContractDetails = {
23+
addressOrName: RMRKMarketplaceContractAddress,
24+
contractInterface: abis.marketplaceAbi
25+
}

package-lock.json

+7-7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"lint": "next lint"
1010
},
1111
"dependencies": {
12-
"@rainbow-me/rainbowkit": "^0.4.6",
12+
"@rainbow-me/rainbowkit": "^0.4.8",
1313
"daisyui": "^2.22.0",
1414
"ethers": "^5.0.0",
1515
"next": "^12.2.4",

pages/index.tsx

+7
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ const Home: NextPage = () => {
4747
</div>
4848
</Link>
4949

50+
<Link href="/marketplace" >
51+
<div className={styles.card}>
52+
<h2>Marketplace Demo &rarr;</h2>
53+
<p>Buy and sell NFTs.</p>
54+
</div>
55+
</Link>
56+
5057
<Link href="/equippable" >
5158
<div className={styles.card}>
5259
<h2>Equippable NFTs Demo &rarr;</h2>

pages/marketplace.tsx

+222
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
import { ConnectButton, useAddRecentTransaction } from "@rainbow-me/rainbowkit"
2+
import type { NextPage } from "next"
3+
import Head from "next/head"
4+
import styles from "../styles/Home.module.css"
5+
import {
6+
erc721ABI,
7+
useAccount,
8+
useContract,
9+
useProvider,
10+
useSigner,
11+
} from "wagmi"
12+
import { Contract, Signer } from "ethers"
13+
import NftList from "../components/nft-list"
14+
import React, { useEffect, useState } from "react"
15+
import Image from "next/image"
16+
import Link from "next/link"
17+
import abis from "../abis/abis"
18+
import {
19+
marketplaceContractDetails,
20+
nestingFactoryContractDetails,
21+
} from "../constants"
22+
import Nft from "../components/nft"
23+
24+
interface NftData {
25+
tokenId: number
26+
owner: string
27+
tokenUri: string
28+
tokenContract: string
29+
}
30+
31+
const Marketplace: NextPage = () => {
32+
const provider = useProvider()
33+
const { data: signer, isSuccess } = useSigner()
34+
const { address, isConnected } = useAccount()
35+
const addRecentTransaction = useAddRecentTransaction()
36+
const [loading, setLoading] = useState<boolean>(true)
37+
const [priceInput, setPriceInput] = useState<number>(0)
38+
const [ownedNfts, setOwnedNfts] = useState<NftData[]>([])
39+
const [listedNfts, setListedNfts] = useState<NftData[]>([])
40+
41+
const marketplaceContract = useContract({
42+
...marketplaceContractDetails,
43+
signerOrProvider: signer,
44+
})
45+
46+
const factoryContract = useContract({
47+
...nestingFactoryContractDetails,
48+
signerOrProvider: signer,
49+
})
50+
51+
function handlePriceInput(e: React.ChangeEvent<HTMLInputElement>) {
52+
setPriceInput(Number(e.target.value))
53+
}
54+
55+
async function getListedNfts() {
56+
const nfts: NftData[] = []
57+
const totalListings = await marketplaceContract.totalListings()
58+
for (let i = 0; i < totalListings; i++) {
59+
const nft = await marketplaceContract.listings(i)
60+
const tokenContract = new Contract(nft[2], erc721ABI, provider)
61+
nfts.push({
62+
tokenId: nft[3],
63+
owner: nft[1],
64+
tokenUri: await tokenContract.tokenURI(i),
65+
tokenContract: nft[2],
66+
})
67+
}
68+
return nfts
69+
}
70+
71+
async function getOwnedNfts() {
72+
const nfts: NftData[] = []
73+
74+
if (signer instanceof Signer) {
75+
// const rmrkCollections: Contract[] = []
76+
const allRmrkCollectionDeployments =
77+
await factoryContract.getCollections()
78+
for (let i = 0; i < allRmrkCollectionDeployments.length; i++) {
79+
console.log(allRmrkCollectionDeployments[i])
80+
const collectionContract = new Contract(
81+
allRmrkCollectionDeployments[i],
82+
abis.multiResourceAbi,
83+
provider
84+
)
85+
// rmrkCollections.push(collectionContract)
86+
const nftSupply = await collectionContract.totalSupply()
87+
for (let i = 0; i < nftSupply; i++) {
88+
let isOwner = false
89+
try {
90+
isOwner =
91+
(await collectionContract.connect(signer).ownerOf(i)) == address
92+
} catch (error) {
93+
console.log(error)
94+
}
95+
if (isOwner) {
96+
nfts.push({
97+
tokenId: i,
98+
owner: await signer.getAddress(),
99+
tokenUri: await collectionContract.tokenURI(i),
100+
tokenContract: collectionContract.address,
101+
})
102+
}
103+
}
104+
}
105+
}
106+
return nfts
107+
}
108+
109+
async function sellNft() {
110+
// if (signer instanceof Signer) {
111+
// const options = {
112+
// value: nestingContract.pricePerMint(),
113+
// }
114+
// const tx = await nestingContract
115+
// .connect(signer)
116+
// .mint(await signer.getAddress(), 1, options)
117+
//
118+
// addRecentTransaction({
119+
// hash: tx.hash,
120+
// description: "Minting a new RMRK NFT",
121+
// confirmations: 1,
122+
// })
123+
// }
124+
}
125+
126+
function fetchData() {
127+
setLoading(true)
128+
getListedNfts().then((nfts) => {
129+
setListedNfts(nfts)
130+
setLoading(false)
131+
})
132+
getOwnedNfts().then((nfts) => {
133+
setOwnedNfts(nfts)
134+
setLoading(false)
135+
})
136+
}
137+
138+
useEffect(() => {
139+
console.log("Loading chain data")
140+
fetchData()
141+
}, [signer])
142+
143+
return (
144+
<div className={styles.container}>
145+
<Head>
146+
<title>RMRK Marketplace</title>
147+
<meta
148+
name="description"
149+
content="Generated by @rainbow-me/create-rainbowkit"
150+
/>
151+
</Head>
152+
153+
<main className={styles.main}>
154+
<ConnectButton />
155+
156+
<h1 className={styles.title}>RMRK Marketplace</h1>
157+
158+
<p className="mb-4">Buy or Sell NFTs on the RMRK Marketplace:</p>
159+
160+
<div className="form-control w-full max-w-xs mb-2">
161+
<label className="label">
162+
<span className="label-text">Price per NFT mint (in wei)</span>
163+
</label>
164+
<input
165+
inputMode="numeric"
166+
placeholder="Price"
167+
className="input input-bordered w-full max-w-xs my-0.5"
168+
value={priceInput}
169+
onChange={handlePriceInput}
170+
></input>
171+
</div>
172+
173+
<p className="mt-5">
174+
Your RMRK NFT Contract will be deployed on the Moonbase Alpha testnet.{" "}
175+
</p>
176+
177+
<h3 className={styles.description}>
178+
Your RMRK NFTs: {ownedNfts?.length}
179+
</h3>
180+
<div className="flex flex-wrap justify-center">
181+
{ownedNfts?.map((nft, index) => {
182+
return (
183+
<div key={index}>
184+
<Nft
185+
tokenContract={nft.tokenContract}
186+
tokenId={nft.tokenId}
187+
tokenUri={nft.tokenUri}
188+
tokenType={"contract"}
189+
/>
190+
</div>
191+
)
192+
})}
193+
</div>
194+
195+
<h3 className={styles.description}>
196+
NFTs for sale: {listedNfts?.length}
197+
</h3>
198+
<div className="flex flex-wrap justify-center">
199+
{listedNfts?.map((nft, index) => {
200+
return (
201+
<div key={index}>
202+
<Nft
203+
//TODO add collection name in the NFT card component
204+
tokenContract={nft.tokenContract}
205+
tokenId={nft.tokenId}
206+
tokenUri={nft.tokenUri}
207+
tokenType={"contract"}
208+
/>
209+
</div>
210+
)
211+
})}
212+
</div>
213+
214+
{loading && <progress className="progress mt-2 w-72"></progress>}
215+
</main>
216+
217+
<footer className={styles.footer}></footer>
218+
</div>
219+
)
220+
}
221+
222+
export default Marketplace

pages/nesting.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { ConnectButton, useAddRecentTransaction } from "@rainbow-me/rainbowkit"
22
import type { NextPage } from "next"
33
import Head from "next/head"
44
import styles from "../styles/Home.module.css"
5-
import { nestingFactoryContract } from "../constants"
5+
import { nestingFactoryContractDetails } from "../constants"
66
import { useAccount, useContract, useProvider, useSigner } from "wagmi"
77
import { Contract, Signer } from "ethers"
88
import NftList from "../components/nft-list"
@@ -28,7 +28,7 @@ const Nesting: NextPage = () => {
2828
{ tokenId: number; owner: string; tokenUri: string }[]
2929
>([])
3030
const factoryContract = useContract({
31-
...nestingFactoryContract,
31+
...nestingFactoryContractDetails,
3232
signerOrProvider: signer,
3333
})
3434

styles/Home.module.css

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
.container {
22
padding: 0 2rem;
3+
justify-content: center;
4+
display: flex;
5+
flex-wrap: wrap;
36
}
47

58
.main {

yarn.lock

+4-4
Original file line numberDiff line numberDiff line change
@@ -743,10 +743,10 @@
743743
"resolved" "https://registry.npmjs.org/@pedrouid/environment/-/environment-1.0.1.tgz"
744744
"version" "1.0.1"
745745

746-
"@rainbow-me/rainbowkit@^0.4.6":
747-
"integrity" "sha512-tb7w38u/MLJQGAsLY2sh8neSbtkqZfsLvgLOyXsC2uL3/v1d5ZL1uHUwKBVbvroCn2D+DQRElPmPAlJB6vzKtg=="
748-
"resolved" "https://registry.npmjs.org/@rainbow-me/rainbowkit/-/rainbowkit-0.4.6.tgz"
749-
"version" "0.4.6"
746+
"@rainbow-me/rainbowkit@^0.4.8":
747+
"integrity" "sha512-xtrMSgbXmNtZXiehiBHx9cOslGXAYRnTIUQPAn13XTZjwwyJiwKHw6nSlKEb6OvIFaCBeu2htRAnxMnWNzagOA=="
748+
"resolved" "https://registry.npmjs.org/@rainbow-me/rainbowkit/-/rainbowkit-0.4.8.tgz"
749+
"version" "0.4.8"
750750
dependencies:
751751
"@vanilla-extract/css" "1.7.0"
752752
"@vanilla-extract/dynamic" "2.0.2"

0 commit comments

Comments
 (0)