How to Build an NFT Marketplace DApp with thirdweb¶
by Kevin Neilson
thirdweb is a powerful development platform that simplifies building and deploying Web3 applications on the blockchain. It provides pre-built smart contracts and tools, enabling developers to quickly launch applications that interact with NFTs, tokens, and more with less coding and configuration effort.
In this guide, we'll go step by step through the process of building an NFT marketplace DApp with thirdweb on Moonbeam. We'll deploy all of the associated contracts, including an ERC-721 NFT contract and a marketplace smart contract to Moonbase Alpha with thirdweb, and then we'll integrate them into the DApp.
For a more nuts and bolts approach to thirdweb with information about available methods, the thirdweb CLI and deployment tools, be sure to check out the thirdweb guide in the Builders section.
Clone the Template¶
thirdweb has an NFT marketplace template that is a perfect starting point for our needs. We'll only need to make minor customizations to it. Please note, thirdweb frequently updates their templates and tutorials, so ensure that you're using the latest and greatest, which may be located in another repository.
-
In your CLI run the following command:
git clone https://github.com/thirdweb-example/marketplace-template
-
Navigate to your project directory and install dependencies with your preferred package manager:
npm install
yarn
pnpm install
Next, you'll need to create a client ID for your thirdweb project and specify it in a .env
file.
Specify Client ID¶
Before you launch your dApp (locally or publicly deployed), you must have a thirdweb Client ID associated with your project. A thirdweb Client ID is synonymous with an API key. You can create a free API key by signing into your thirdweb account and navigating to Settings then click on API Keys.
Press Create API Key then take the following steps:
- Give your API key a name
- Enter the allowed domains that the API key should accept requests from. It's recommended that you allow only necessary domains, but for development purposes, you can select Allow all domains
- Press Next and confirm the prompt on the next page
Now, create a file a called .env.local
at the root level directory of your project. Add your Client ID as follows:
NEXT_PUBLIC_TW_CLIENT_ID="INSERT_CLIENT_ID"
There are no other fields that you need to specify in your .env
file at this time. If you're uncertain about formatting, you can refer to the .env.example
file included in the project.
Run the project¶
We're not finished with the project yet, but it should be at a stage where you can launch the template and see the web app load successfully in your browser.
npm run dev
yarn dev
pnpm dev
If you see a blank screen, this typically means that you've failed to properly configure your client ID.
Add Support for Moonbase Alpha¶
thirdweb offers a small number of chains from @thirdweb/chains
and does not include Moonbeam networks in that list, so you'll need to specify the network details including chain ID and RPC URL. You can create a custom chain with defineChain
as follows:
import { defineChain } from 'thirdweb';
const moonbeam = defineChain({
id: 1284,
rpc: 'https://rpc.api.moonbeam.network',
});
import { defineChain } from 'thirdweb';
const moonriver = defineChain({
id: 1285,
rpc: 'https://rpc.api.moonriver.moonbeam.network',
});
import { defineChain } from 'thirdweb';
const moonbase = defineChain({
id: 1287,
rpc: 'https://rpc.api.moonbase.moonbeam.network',
});
The NFT marketplace template includes a chains.ts
file under src/consts/chains.ts
. To add support for Moonbase Alpha to the DApp, add the following lines:
export const moonbase = defineChain({
id: 1287,
rpc: 'https://rpc.api.moonbase.moonbeam.network',
});
We don't need to add any import statements because defineChain
is already imported by default as part of the template. Feel free to add additional chains if you'd like to add support for Moonbeam, Moonriver, or other networks. The full file can be viewed below:
View chains.ts
import { defineChain } from 'thirdweb';
/**
* All chains should be exported from this file
*/
export { avalancheFuji, sepolia, polygonAmoy } from 'thirdweb/chains';
/**
* Define the Moonbase Alpha test network
*/
export const moonbase = defineChain({
id: 1287,
rpc: 'https://rpc.api.moonbase.moonbeam.network',
});
Deploy ERC-721 NFT Contract¶
Of course, we'll need to have an NFT contract to showcase as part of the marketplace. You can use an existing NFT contract, but for demo purposes we'll walk through the steps of deploying a new ERC-721 contract with thirdweb.
Head to thirdweb Explore and choose the OpenEditionERC721
NFT standard. You can also access the NFT contract directly. Press Deploy Now, then take the following steps:
- Add a name for your NFT
- Optionally add a token symbol
- Upload the image for your NFT. This will be uploaded to IPFS
- Review the royalty information. By default, this is set to the address of your currently connected wallet and the royalty is set by default to 0%
- Review the address to receive the proceeds of initial NFT sales. By default, this is set to the address of your currently connected wallet
- Select your Network as Moonbase Alpha
- Press Deploy Now
You'll be asked for three wallet confirmations - the first two are transactions and the third is a signature. The first transaction deploys the NFT contract and the second sets the NFT metadata. The signature request is simply to add the NFT contract to your dashboard on thirdweb - this is highly recommended as it makes it easy to find your previously deployed NFTs from one easily-accessible place.
Set Claim Condition¶
Before any NFTs can be minted, you'll need to configure the claim condition. If you try to mint any NFTs before setting the claim condition, the transaction will be reverted. To configure the claim condition for an open public mint, follow these steps:
- Head to the Claim Conditions page
- Select Public phase
- Optionally, choose a price to charge per mint. You can also leave this as 0 for a free mint
- Press Save Phases
Mint Some NFTs¶
For aesthetic purposes, we'd like to have some NFTs show up in the marketplace that we created. Under the Extensions, NFTs section, press Claim. Then, you can mint some NFTs by taking the following steps:
- Enter the address to receive the NFTs
- Enter the desired quantity to mint
- Press Claim NFT and confirm the transaction in your wallet
Add NFT Contract to the DApp¶
After deploying and minting your NFTs, you'll need to specify your NFT contract in src/consts/nft_contract.ts
. First, add moonbase
to the list of imports as follows:
import { moonbase, avalancheFuji, polygonAmoy, sepolia } from './chains';
Then, add your NFT contract to the array of marketplace contracts as follows:
{
address: '0x5647fb3dB4e47f25659F74b4e96902812f5bE9Fb',
chain: moonbase,
title: 'Moonbase NFT',
thumbnailUrl:
'https://258c828e8cc853bf5e0efd001055fb39.ipfscdn.io/ipfs/QmTDyLBf2LaG6mzPniPjpX3P4DTFvjAk3gtUgrAb8EVPUF/2024-05-22%2008.17.59.jpg',
type: 'ERC721',
},
To get the IPFS URL of the image of your NFT that you uploaded when creating the NFT contract, head to the Events tab of your NFT contract and locate the SharedMetadataUpdated
event. Expand the dropdown and you'll see the image URI. You can concatenate this to an IPFS CDN as shown above.
The finished file can be viewed below:
View nft-contracts.ts
import type { Chain } from 'thirdweb';
import { moonbase, avalancheFuji, polygonAmoy } from './chains';
export type NftContract = {
address: string;
chain: Chain;
type: 'ERC1155' | 'ERC721';
title?: string;
description?: string;
thumbnailUrl?: string;
slug?: string;
};
/**
* Below is a list of all NFT contracts supported by your marketplace(s).
* This is of course hard-coded for demo purposes
*
* In reality, the list should be dynamically fetched from your own data source
*/
export const NFT_CONTRACTS: NftContract[] = [
{
address: '0x6b869a0cF84147f05a447636c42b8E53De65714E',
chain: avalancheFuji,
title: 'Steakhouse: Liberatorz',
thumbnailUrl:
'https://258c828e8cc853bf5e0efd001055fb39.ipfscdn.io/ipfs/bafybeigonh3hde5suwcb3qvkh6ljtvxv7ubfmcqbwfvi3ihoi3igd27jwe/SteakhouseLogo.svg',
type: 'ERC721',
},
{
address: '0xC5A2c72c581eA4A17e17bEeF38a9597132830401',
chain: avalancheFuji,
title: 'Ugly Waifu',
thumbnailUrl:
'https://258c828e8cc853bf5e0efd001055fb39.ipfscdn.io/ipfs/bafybeidaadqapi7twzd7pjp24tu4ngsr3teubrhop7hg3jk3oj6lqysfgm/OS-LOGO.png',
slug: 'ugly-waifu',
type: 'ERC721',
},
{
address: '0x0896Db00D8987Fba2152aa7c14c4255eBC7354cE',
chain: avalancheFuji,
title: 'Unnamed Collection',
description: '',
thumbnailUrl:
'https://258c828e8cc853bf5e0efd001055fb39.ipfscdn.io/ipfs/Qmct2vS78Uwug3zVtqQognskPPRmd4wRQiaDAQWt1kRJws/0.png',
slug: 'unnamed-collection',
type: 'ERC721',
},
{
address: '0x0ACaCa3d3F64bb6e6D3564BBc891c58Bd4A4c83c',
chain: avalancheFuji,
title: 'GoroBot',
thumbnailUrl:
'https://258c828e8cc853bf5e0efd001055fb39.ipfscdn.io/ipfs/bafybeiay3ffxy3os56bvnu5cmq7gids4v6n4hf5nvvcb3gy2dzavi3ltnu/profile.jpg',
slug: 'gorobot',
type: 'ERC721',
},
{
address: '0x4b6CDEFF5885A57678261bb95250aC43aD490752',
chain: polygonAmoy,
title: 'Mata NFT',
thumbnailUrl:
'https://258c828e8cc853bf5e0efd001055fb39.ipfscdn.io/ipfs/bafybeidec7x6bptqmrxgptaedd7wfwxbsccqfogzwfsd4a7duxn4sdmnxy/0.png',
type: 'ERC721',
},
{
address: '0xd5e815241882676F772A624E3892b27Ff3a449c4',
chain: avalancheFuji,
title: 'Cats (ERC1155)',
thumbnailUrl:
'https://258c828e8cc853bf5e0efd001055fb39.ipfscdn.io/ipfs/bafybeif2nz6wbwuryijk2c4ayypocibexdeirlvmciqjyvlzz46mzoirtm/0.png',
type: 'ERC1155',
},
{
address: '0x5647fb3dB4e47f25659F74b4e96902812f5bE9Fb',
chain: moonbase,
title: 'Moonbase NFT',
thumbnailUrl:
'https://258c828e8cc853bf5e0efd001055fb39.ipfscdn.io/ipfs/QmTDyLBf2LaG6mzPniPjpX3P4DTFvjAk3gtUgrAb8EVPUF/2024-05-22%2008.17.59.jpg',
type: 'ERC721',
},
];
Deploy Marketplace Contract¶
While the template includes existing marketplace contracts for a couple of TestNets, let's deploy a similar one for Moonbase Alpha. Head to thirdweb Explore and choose the MarketplaceV3
contract. You can also access MarketplaceV3
directly. Press Deploy Now, then take the following steps:
- Add a name for the marketplace
- Select Moonbase Alpha as the network
- Press Deploy Now
You'll be asked to confirm a transaction and provide a signature. The former deploys the marketplace contract and the latter adds the contract to your dashboard on thirdweb (which is not required but highly recommend for keeping track of your contracts).
Add Marketplace Contract to the DApp¶
After deploying your marketplace contract you'll need to specify it in src/consts/marketplace_contract.ts
. To add support for the Moonbase marketplace first add moonbase
to the list of imports as follows:
import { moonbase, avalancheFuji, polygonAmoy, sepolia } from './chains';
Then, add your marketplace contract in the array of marketplace contracts as follows:
{
address: '0xA76C6E534aa651756Af8c222686fC1D3abF6952A',
chain: moonbase,
},
The finished file can be viewed below:
View marketplace-contracts.ts
import type { Chain } from 'thirdweb';
import { moonbase, avalancheFuji, polygonAmoy, sepolia } from './chains';
type MarketplaceContract = {
address: string;
chain: Chain;
};
/**
* You need a marketplace contract on each of the chains you want to support.
* Only list one marketplace contract address for each chain
*/
export const MARKETPLACE_CONTRACTS: MarketplaceContract[] = [
{
address: '0x8C1D464B385A2B7EAa80dcAAD66DD8BC0256e717',
chain: avalancheFuji,
},
{
address: '0x571B773F1e4A7C080b51C36f37e06f371C515569',
chain: polygonAmoy,
},
{
address: '0xe0eFD6fb388405b67b3E9FaFc02649c70E749f03',
chain: sepolia,
},
{
address: '0xA76C6E534aa651756Af8c222686fC1D3abF6952A',
chain: moonbase,
},
];
Wrapping Up¶
And that's it! Congratulations on making it through the tutorial. You can head to http://localhost:3000
after running the DApp locally via one of the following:
npm run dev
yarn dev
pnpm dev
On the homepage you should see your newly added NFT contract. Click on the NFT collection and you'll see something that looks like the below:
For more information on what you can do with thirdweb on Moonbeam be sure to check out the thirdweb guide in the Builders section or the thirdweb documentation site.
| Created: July 16, 2024