Select Page

Step-by-step Guide on How to develop an NFT Marketplace Platform

NFTs, as blockchain-based immutable ownership records of digital assets, are quite popular, particularly in the space of art and collectables. However, the potential of NFTs extends beyond digital artworks. They are used for buying digital lands in virtual worlds, publishing and licensing next-generation music ownership and accessing special sales or limited-edition products such as tickets.

Talking about the popularity of NFTs, it is interesting to know that NFT trading volume reached $10.7 billion in the third quarter of 2021, as reported by DappRadar. That’s a whopping 704% increase from the previous quarter. This trend of spending thousands of dollars on NFTs demonstrates that people believe in the future of NFT technology and, in some ways, they tie NFTs to social status.

None the less, as the community of NFT consumers is growing, NFT Marketplaces see increased traffic. Last year, the top NFT marketplaces were OpenSea, Magic Eden, Axie Infinity, and CryptoPunks. These marketplaces are in high demand in areas such as play-to-earn gaming, digital art collectables, fundraising projects, digital subscription models, etc.

No wonder many entrepreneurs consider NFT marketplace development as a great opportunity to capitalize on this new wave of technology that is quickly becoming a major industry. If you are also interested in developing and launching your NFT marketplace, here is a comprehensive guide to help you get started.

What is an NFT Marketplace?

NFT marketplace, as the name implies, is a decentralized platform where users can create, buy, sell, and store non-fungible tokens. An NFT marketplace facilities NFT minting and trading at a global scale, while blockchain as its underlying technology ensures transparency and immutable recording of the digital asset tokenization and trading process. The marketplace also takes care of NFT storage.

NFT marketplaces are gaining traction in industries such as gaming, art, social networking, and music, nearly capturing every market that deals with digital assets. With the influx of Metaverse projects, NFT marketplaces have grown into prominence and relevance even further.

With time, the features of NFT marketplaces are upgrading, and limitations like lack of NFT interoperability are getting addressed. Cross-chain bridging, niche-specific NFTs, NFT swapping, and compatibility with multiple metaverse projects are some of the advanced features of contemporary NFT marketplaces.

One important factor to consider before developing your NFT Marketplace project is the niche. However, above and beyond niche, there are numerous layers to consider like the blockchain protocol, the NFT storge, architecture designing, and others. Here, this insight covers all about NFT marketplace development.

How does an NFT Marketplace work?

Before diving deep into how an NFT marketplace is created, it is essential to understand how the NFT marketplace works from the client side. Usually, all NFT platforms share a similar workflow. Firstly, a user has to sign up on the platform and install a digital wallet to store NFTs.

Users can then create their assets by uploading items to exhibit their work. The user can also select which payment tokens they would like to accept for their art and set a fee if the platform suggests it. The next step in the workflow is to list items for sale. The user can choose a bid for a fixed price or an auction. A transaction is created when listing an item for sale to launch a personal trading smart contract for the user wallet.

The platform may need a collection moderation and NFTs will appear on the list after approval.

LeewayHertz’s Whitelabel NFT Marketplace Solution

Launch your custom NFT Marketplace

How to start NFT Marketplace Development?

Since you know how NFT marketplaces work and what types of platforms are on the market, you need to understand who you are developing your platform for and what problems it can solve.

You need to decide on a list of features and choose the technology stacks and NFT standards for your marketplace.

features of nft

Following are some of the features that can be added to the NFT marketplace:

  • Storefront
    NFT marketplace should have a storefront that offers users all the information required for an item: bids, owners, preview or price history.
  • Filters
    Using filters, it becomes easier to navigate a site, specifically if you plan to build a marketplace place for a lot of collectibles. By adding the filters feature, users can select items by payment method, listing status, category and collection.
  • Searching for items
    An NFT marketplace platform should support tagging and category management to allow users to search collectibles. Use a search bar on the site and add categories.
  • Create listings
    A user should be able to create and submit collectibles. Using this feature, a user should upload files and fill in the token information such as name, tags, description.
  • Buy and Bid
    The NFT marketplace platform should have a feature that allows users to buy and bid for NFTs listed on the platform. The bidding feature should include a bid expiration date and allow users to view details about the bids’ current status.
  • Wallet
    The NFT Marketplace Platform should have a wallet that allows users to store, send and receive non-fungible tokens. The easiest way to integrate this feature is to provide users with a connected wallet that they already use. For example, you can integrate the most popular wallets like Coinbase, Formatic or MyEtherWallet.

Once you identify features to be added to the platform, the next step is to consider the project’s technical implementation. To build an NFT marketplace, you should first decide the technology stack required for developing it.

Let’s look at some of the technology components needed for building an NFT marketplace platform.

Technology Stack Required for Building an NFT marketplace platform

nft tech stack

Blockchain Platforms

  • Ethereum
    Ethereum is one of the most popular platforms when it comes to NFT marketplace or non-fungible token development. Since transaction history and token metadata is publicly verifiable on Ethereum, it is easier to prove ownership history.As all Ethereum products share the common backend, NFTs become portable across products. Also, Ethereum never goes down; therefore, tokens will always be available for sale.
  • Flow
    Flow is a rapid and decentralized blockchain designed for a new generation of digital assets, apps and games. The platform is being widely used to create both the NFT marketplace and NFTs using the Cadence programming language.
  • Tezos
    Tezos is an open-source blockchain platform for applications and assets backed by a community of builders, researchers and validators. Using a pre-compiled FA2 NFT contract written in LIGO smart contract language, Tezos supports the development of NFT marketplaces and NFTs.
  • Cardano
    Cardano is a blockchain platform with technologies and tools required to provide unmatched security and sustainability to decentralized systems and applications. It also supports the development of NFTs and other digital assets. 

Storage Platforms

  • IPFS
    IPFS is a peer-to-peer hypermedia protocol designed to store media content in a decentralized way. As the media file related to NFTs cannot be stored directly on the blockchain, IPFS can store all that data.
  • Filecoin
    Filecoin is a decentralized storage network designed specifically to store the most critical information, such as media files. The storage platform includes everything that a developer will require to get started with decentralized storage for NFTs. Knowing its benefits, Truffle Suite has also launched NFT Development Template with Filecoin Box.
  • Pinata
    Pinata is also one of the popular platforms to upload and manage files on IPFS. It provides secure and verifiable files for NFTs.

NFT Standards

  • ERC-721
  • ERC-1155
  • FA2
  • dGoods
  • TRC-721

Front-end Frameworks

  • React
  • Angular
  • Vue

This article demonstrates the example of building an NFT Marketplace with Flow Blockchain and Pinata IPFS Network.

LeewayHertz’s Whitelabel NFT Marketplace Solution

Launch your custom NFT Marketplace

How to develop NFT Marketplace using IPFS and Flow?

We have shared an example of creating the contract, minting a token, building an app to view NFTs made via this contract and creating a marketplace to move NFTs to other users.

Let’s start with the creation of the contract and token minting.

Setting Up Tools 

Install Flow CLI on your system. There are different commands for installing CLI based on different operating systems.

For example, to install Flow CLI on macOS, use the command:

brew install flow-cli

On Windows:

iex “& { $(irm ‘‘) }”

On Linux:

sh -ci “$(curl -fsSL”

Asset files will be stored on IPFS. In this example, we are going to use Pinata for storing files. You can sign up for a free account and get an API key here.

It is also essential to install a NodeJS and a text editor to highlight Flow smart contract code.

The second step is to create a directory for the project using the command:

mkdir pinata-party

Initialize a new flow project and change it into that directory:

cd pinata-party

Now, open the project in your code editor and let’s start working. First, create a folder named cadence. Add another folder called contracts within that folder. Finally, create a file within the contracts folder named PinataPartyContract.cdc.

Before going forward, it is essential to point out everything we do regarding the Flow blockchain platform. Set up the file for the emulator environment and then we can start writing the contract.

We need to update the contract’s object in flow.json using the code:

“contracts”: {
“PinataPartyContract”: “./cadence/contracts/PinataPartyContract.cdc”

Update the deployments object in that file using the below code:

“deployments”: {
“emulator”: {
“emulator-account”: [“PinataPartyContract”]

It will enable the Flow CLI to use the emulator for deploying our contract. This code is also referencing the account and the contract that we are going to write soon.


We need to create contracts for minting NFT, associating metadata to the NFT and ensuring that metadata points to the underlying assets stored on IPFS.

Open the PinataPartyContract.cdc and execute the following code:

pub contract PinataPartyContract {
pub resource NFT {
pub let id: UInt64
init(initID: UInt64) { = initID

The first step is to define the contract. Let’ start by defining PinataPartyContract and create a resource within that. Resources are items saved in user accounts that are accessible via access control measures. NFTs need to be identifiable and the id property allows you to identify tokens.

Then, a resource interface is created to define what capabilities are made available to others.

pub resource interface NFTReceiver {
pub fun deposit(token: @NFT, metadata: {String : String})
pub fun getIDs(): [UInt64]
pub fun idExists(id: UInt64): Bool
pub fun getMetadata(id: UInt64) : {String : String}

Put the above code below the NFT resource code. The NFTReceiver resource interface says that the resource can call the following methods:

  • getIDs
  • idExists
  • deposit
  • getMetadata

Then, we have to define the token collection interface. Consider it as a wallet that stores NFTs of all the users.

pub resource Collection: NFTReceiver {
pub var ownedNFTs: @{UInt64: NFT}
pub var metadataObjs: {UInt64: { String : String }}
init () {
self.ownedNFTs <- {}
self.metadataObjs = {}
pub fun withdraw(withdrawID: UInt64): @NFT {
let token <- self.ownedNFTs.remove(key: withdrawID)!
return <-token
pub fun deposit(token: @NFT, metadata: {String : String}) {
self.metadataObjs[] = metadata
self.ownedNFTs[] <-! token
pub fun idExists(id: UInt64): Bool {
return self.ownedNFTs[id] != nil
pub fun getIDs(): [UInt64] {
return self.ownedNFTs.keys
pub fun updateMetadata(id: UInt64, metadata: {String: String}) {
self.metadataObjs[id] = metadata
pub fun getMetadata(id: UInt64): {String : String} {
return self.metadataObjs[id]!
destroy() {
destroy self.ownedNFTs

The variable ownedNFTs tracks all NFTs a user can own from the contactor. A variable called metadataObjs is unique as we are extending the Flow NFT contract functionality to store a mapping of metadata for every NFT.
It maps the token id to its related metadata, which means that the token id is required before we can set it. Variables are initialized to define them in a resource within Flow.

Finally, we will have all the available functions required for the NFT collection resource. The way the default NFT contract was extended to include metadataObjs mapping, we will extend the default deposit function to take an additional metadata parameter. It is done to ensure that only the token minter can add the metadata to the token. We keep the initial addition of metadata confined to the minting execution to keep it private. Add the following code below the Collection resource:

pub fun createEmptyCollection(): @Collection {
return <- create Collection()
pub resource NFTMinter {
pub var idCount: UInt64
init() {
self.idCount = 1
pub fun mintNFT(): @NFT {
var newNFT <- create NFT(initID: self.idCount)
self.idCount = self.idCount + 1 as UInt64
return <-newNFT

Firstly, we will have a function to create an empty NFT collection when called. A user who is interacting with the contract will have a storage location that maps the defined Collection resource.

We will create one more resource after that. We cannot mint tokens without it. The NFTMinter comprises an idCount that is increased every time to ensure we don’t have duplicate ids for NFTs. It also contains a function for creating NFTs.

Add the main contract initializer below the NFTMinter resource:

init() {<-self.createEmptyCollection(),to: /storage/NFTCollection)<&{NFTReceiver}>(/public/NFTReceiver,target:/storage/NFTCollection)<-create NFTMinter(), to: /storage/NFTMinter)

The initializer function is called only when deploying the contract. It performs three things:

  • Create an empty collection for the collection deployer so that the owner contract can create and own NFTs from the contract.
  • The NFTMinter resource is stored in account storage for the contract creator. It means only the contract creator can mint tokens.
  • The Collection resource is published in a public location with reference to the NFTReceiver interface created at the beginning. That is how we tell the contract that anyone can call functions defined on the NFTReceiver.

Once we have a contract ready to go, let’s deploy it. Before deploying it:

  1. Test it on the Flow Playground.
  2. Go to Flow Playground and click on the first account in the left sidebar.
  3. Replace all the code with the contract code and click Deploy.

If everything goes well, you should view a log at the bottom of the screen:

16:48:55 Deployment Deployed Contract To: 0x01

As it is now the time to deploy the contract to the locally running emulator, run the following command:

flow project start-emulator

With the emulator running and configured flow.json file, a contract can be deployed with the below command:

flow project Deploy

If everything goes well, you should view an output like this:

Deploying 1 contract for accounts: emulator-account

PinataPartyContract → 0xf8d6e0586b0a20c7

Now, we shall move to the minting of NFTs.

Minting NFTs


In this section, we will discuss the NFT minting process using an app and a user interface. For getting something minted and displaying how metadata works with NFTs on Flow, we will be using the command line and Cadence scripts.

Create a new directory within the root of our pinata-party project and call them “transactions.” Once a folder is created, create a new file within it called as MintPinataParty.cdc.

We should have a file to reference in the metadata we offer to the NFT. A file is uploaded to IPFS via Pinata. In this tutorial, NFTs are focused on tradable videos of Pinata being smashed at parties. In this demo, we will upload a kid’s video hitting a pinata at a  birthday party. You can upload any media file you want and associate it with the NFT.

Once the file is uploaded, you will be given an IPFS hash. Copy the hash as it will be used in the minting process. Now, add the following code inside MintPinataParty.cdc file.

import PinataPartyContract from 0xf8d6e0586b0a20c7
transaction {
let receiverRef: &{PinataPartyContract.NFTReceiver}
let minterRef: &PinataPartyContract.NFTMinter
prepare(acct: AuthAccount) {
?? panic(“Could not borrow receiver reference”)
self.minterRef = acct.borrow<&PinataPartyContract.NFTMinter>(from: /storage/NFTMinter)
?? panic(“could not borrow minter reference”)
execute {
let metadata : {String : String} = {
“name”: “The Big Swing”,
“swing_velocity”: “29”,
“swing_angle”: “45”,
“rating”: “5”,
“uri”: “ipfs://QmRZdc3mAMXpv6Akz9Ekp1y4vDSjazTx2dCQRkxVy1yUj6”
let newNFT <- self.minterRef.mintNFT()
self.receiverRef.deposit(token: <-newNFT, metadata: metadata)
log(“NFT Minted and deposited to Account 2’s Collection”)

Firstly, we have defined two reference variables, minterRef and receiverRef. In this scenario, we are both the receiver and minter of the NFT. These variables reference resources that are created in the contract. The transaction gets failed if the person executing it does not have access to the resource.

The above contract will mint and deposit NFTs. Now, we will send the transaction and mint the NFT. But before that, we need to prepare the account. Create a private key for signing from the command line within the project’s root folder.

Run the below command:

flow keys generate

It will provide you with public and private keys. Make sure to protect your private key.

You will need the private key for signing the transaction that needs to be pasted into our flow.json file. It is also essential to specify the signing algorithm and here is what your accounts object in the flow.json file should look like:

“accounts”: {
“emulator-account”: {
“privateKey”: “YOUR PRIVATE KEY”,
“chain”: “flow-emulator”,
“sigAlgorithm”: “ECDSA_P256”,
“hashAlgorithm”: “SHA3_256”

If you want to store any of this project on a remote git repository or Github, you should not include the private key. You may need to .gitignore the entire flow.json. Though we are only using a local emulator, it is good to keep keys protected.

The last thing that we need to do is to verify that the token is in our account and fetch the metadata. To verify it, we need to write a simple script and call it from the command line.

Create a new folder called scripts from the root of your project. Create a file called CheckTokenMetadata.cdc inside the folder. Add the following code in that file:

import PinataPartyContract from 0xf8d6e0586b0a20c7
pub fun main() : {String : String} {
let nftOwner = getAccount(0xf8d6e0586b0a20c7) // log(“NFT Owner”)
let capability = nftOwner.getCapability<&{PinataPartyContract.NFTReceiver}>(/public/NFTReceiver)
let receiverRef = capability.borrow()
?? panic(“Could not borrow the receiver reference”)
receiverRef.getMetadata(id: 1)

We are importing the contract from the deployed address in this script. We define the main function and define three variables inside it:

  • nftOwner
    This account owns the NFT.
  • capability
    Capabilities are access-controlled. If a capability is not available to the address attempting to borrow it, the script gets failed. In this example, we borrow capabilities from the NFTReceiver resource.
  • receiverRef
    The variable takes our capability and states the script to borrow from the deployed contract.

We want to ensure the address in the question has received the NFT we minted and then we want to view the metadata associated with the token.

Run the script using the following command and see what we get:

flow scripts execute ./scripts/CheckTokenMetadata.cdc

You will get an output like this:

{"name": "The Big Swing", "swing_velocity": "29", "swing_angle": "45", "rating": "5", "uri": "ipfs://QmRZdc3mAMXpv6Akz9Ekp1y4vDSjazTx2dCQRkxVy1yUj6 "}

We will then build a front-end React app that allows you to display the NFT by fetching the metadata.

Displaying NFT Collectibles

We will be building a simple React app that interacts with Flow Smart Contracts to validate and fetch NFTs owned by users. 

Setup React and Dependencies

Create React app within the parent directory pinata-party. Run the below command to create a React app:

npx create-react-app pinata-party-frontend 

When you are done with installing, you will see a new directory called pinata-party-frontend. Switch to that directory and install dependencies. For the first part of the frontend setup, run:

npm i @onflow/fcl @onflow/types

We will store some values as global variables for our app and use environment variables. In react, it means creating a .env file and setting key-value pairs where you need to prefix it with REACT_APP.

Then, create a config file that will be used to interact with the Flow JS SDK. Create a file in the src directory, config.js and add the following code:

import {config} from “@onflow/fcl”
.put(“access node.API”, process.env.REACT_APP_ACCESS_NODE)
.put(“challenge.handshake”, process.env.REACT_APP_WALLET_DISCOVERY)
.put(“0xProfile”, process.env.REACT_APP_CONTRACT_PROFILE)

This configuration file just helps the JS SDK work with the Flow blockchain (or emulator in this case). To make this file available throughout the app, open up the index.js file and add this line:

import "./config"

It is important to have an authentication feature in the app to enable the secure transferring of NFT assets. We need to have an authentication component. Create a file AuthCluster.js in your src directory. Add the following within that file:

import React, {useState, useEffect} from ‘react’

import * as fcl from “@onflow/fcl”

const AuthCluster = () => {

const [user, setUser] = useState({loggedIn: null})

useEffect(() => fcl.currentUser().subscribe(setUser), [])

if (user.loggedIn) {

return (

{user?.addr ?? “No Address”}
) } else { return (
) } } export default AuthCluster

To get this component into the app, replace the app.js file with the following:

import ‘./App.css’;

import AuthCluster from ‘./AuthCluster’;function App() {

return (

); }export default App;

After adding the above code, you will see a page with a login sign-up button on starting the app. Now, it’s time to build the ability to fetch NFTs for an account and display them.

To display NFTs that we created, it is essential to communicate with the Flow blockchain. In this tutorial, we should be able to communicate with the Flow emulator.

Let’s build a component that allows the fetching of data and displaying of NFT data. Create a file TokenData.js in your src directory and add the following code within that file:

import React, { useState } from “react”;

import * as fcl from “@onflow/fcl”;

const TokenData = () => {

const [nftInfo, setNftInfo] = useState(null)

const fetchTokenData = async () => {

const encoded = await fcl



import PinataPartyContract from 0xf8d6e0586b0a20c7

pub fun main() : {String : String} {

let nftOwner = getAccount(0xf8d6e0586b0a20c7)

let capability = nftOwner.getCapability<&{PinataPartyContract.NFTReceiver}>(/public/NFTReceiver)

let receiverRef = capability.borrow()

?? panic(“Could not borrow the receiver reference”)

return receiverRef.getMetadata(id: 1)




const decoded = await fcl.decode(encoded)



return (

{ nftInfo &&
{ Object.keys(nftInfo).map(k => { return (

{k}: {nftInfo[k]}

) }) }
); }; export default TokenData;

In this file, we are creating a component with a button to fetch token data. We have also created a button to clear token data. On clicking the fetch button, a function fetchTokenData is called. The function uses the Flow JS SDK to run the script we executed from the command line. Taking results of the execution and setting results to a state variable, nftInfo. If the variable exists, key-value pairs are rendered from the NFT metadata on screen and a button to clear the data.

Getting Media from IPFS

As we have already signed up on the Pinata account and added the video file to IPFS via the Pinata upload interface, you are navigated to the Pinata IPFS gateway where IPFS content is displayed when you click on a hash in the Pin Explorer.

In the TokenData.js file, add a way to display the video file retrieved from IPFS. Update the file to look like this:

import React, { useState } from “react”;

import * as fcl from “@onflow/fcl”;

const TokenData = () => {

const [nftInfo, setNftInfo] = useState(null)

const fetchTokenData = async () => {

const encoded = await fcl



import PinataPartyContract from 0xf8d6e0586b0a20c7

pub fun main() : {String : String} {

let nftOwner = getAccount(0xf8d6e0586b0a20c7)

let capability = nftOwner.getCapability<&{PinataPartyContract.NFTReceiver}>(/public/NFTReceiver)

let receiverRef = capability.borrow()

?? panic(“Could not borrow the receiver reference”)

return receiverRef.getMetadata(id: 1)




const decoded = await fcl.decode(encoded)



return (

{ nftInfo &&
{ Object.keys(nftInfo).map(k => { return (

{k}: {nftInfo[k]}

) }) }
); }; export default TokenData;

A video element with a source points to the file on IPFS. URI created with NFT looks like ipfs://Qm…

We made it like this because the IPFS desktop client allows clicking on and opening links.

NFT will now be a real live digital asset on the blockchain.

Now, we will enable the transfer of NFTs.

Transferring NFTs

First of all, we need to create contracts for setting up a marketplace. Contracts will be created for:

  • Payment mechanism for fungible tokens
  • Token supply settings
  • Token transfer capabilities

Let’s create a fungible token contract used for payments when purchasing NFTs.

We will create a fungible token contract by defining the empty contract:

pub contract PinnieToken {}

Token pub variables associated with token and provider resources need to be added to the contract.

pub var totalSupply: UFix64
pub var tokenName: String
pub resource interface Provider {
pub fun withdraw(amount: UFix64): @Vault {
post {
result.balance == UFix64(amount):
"Withdrawal amount must be the same as the balance of the withdrawn Vault."

Add the above contract within the empty contract.

The resource interface called Provider defines a public function, but the account owner can only call it. Then, we will define two more public resource interfaces:

pub resource interface Receiver {
pub fun deposit(from @Vault)
pub resource interface Balance {
pub var balance: UFix64

The above interfaces go directly below the Provider resource interface. The Receiver interface involves a function that anyone can execute. It ensures that deposits into an account can be performed as long as the recipient initializes a vault to handle tokens created via the contract. The Balance resource returns a balance of the new token for any provided account.

Let’s create the Vault resource and add the following code below the Balance resource:

pub resource Vault: Provider, Receiver, Balance {
pub var balance: UFix64
init(balance: UFix64) {
self.balance = balance
pub fun withdraw(amount: UFix64): @Vault {
self.balance = self.balance – amount
return <-create Vault(balance: amount)
pub fun deposit(from: @Vault) {
self.balance = self.balance + from.balance
destroy from

Add the below function under the vault interface:

pub fun createEmptyVault(): @Vault {
return <-create Vault(balance: 0.0)

As the name implies, the function creates an empty Vault resource for an account. The balance is 0.

Therefore, we now need to set up the minting capability. Add the following code below the createEmptyVault function:

pub resource VaultMinter {
pub fun mintTokens(amount: UFix64, recipient: Capability<&AnyResource{Receiver}>)
let recipientRef = recipient.borrow()
?? panic(“Could not borrow a receiver reference to the vault”)
PinnieToken.totalSupply = PinnieToken.totalSupply + UFix64(amount)
recipientRef.deposit(from: <-create Vault(balance: amount))

The VaultMinter resource is public, but it is only available to the contract account owner.

The VaultMinter resource only includes one function: mintTokens that needs an amount to mint and a recipient. The newly minted tokens can be deposited into that account as long as the recipient will have the Vault resource stored.

The totalSupply variable needs to be updated when tokens are minted. Therefore, the minted amount is added to the previous supply for getting the new supply.

Now, we need to initialize the contract and add the below code after VaultMinter resource:

init() {
self.totalSupply = 30.0
self.tokenName = “Pinnie”
let vault <- create Vault(balance: self.totalSupply)<-vault, to: /storage/MainVault)<-create VaultMinter(), to: /storage/MainMinter)<&VaultMinter>(/private/Minter, target: /storage/MainMinter)

It is essential to set a total supply when initializing the contract. In this example, we have initialized the contract with a supply of 30 and set the token name as “Pinnie.”

Deploying and Minting Tokens

Update the flow.json file in the project to deploy the new contract. Ensure that the flow.json file references the new contract and has the emulator-account key reference:

“emulators”: {
“default”: {
“port”: 3569,
“serviceAccount”: “emulator-account”
“contracts”: {
“PinataPartyContract”: “./cadence/contracts/PinataPartyContract.cdc”,
“PinnieToken”: “./cadence/contracts/PinnieToken.cdc”
“networks”: {
“emulator”: {
“host”: “”,
“chain”: “flow-emulator”
“accounts”: {
“emulator-account”: {
“address”: “f8d6e0586b0a20c7”,
“keys”: “e5ca2b0946358223f0555206144fe4d74e65cbd58b0933c5232ce195b9058cdd”
“deployments”: {
“emulator”: {
“emulator-account”: [“PinataPartyContract”, “PinnieToken”]

In another terminal window within your pinata-party project directory, run flow project deploy. Now, let’s test the minting function. We will create a transaction that allows us to create Pinnie tokens. But first, we need to update the flow.json file.

Change json under the emulator-account:

“emulator-account”: {
“address”: “f8d6e0586b0a20c7”,
“privateKey”: “e5ca2b0946358223f0555206144fe4d74e65cbd58b0933c5232ce195b9058cdd”,
"sigAlgorithm": "ECDSA_P256",
"hashAlgorithm": "SHA3_256",
"chain": "flow-emulator"

The key field becomes the privateKey field and we add properties, including sigAlgorithm, chain and hashAlgorithm.

Developing an NFT marketplace

Before working on the marketplace’s front end, we should have a contract to handle the marketplace creation and management.

In cadence/contracts folder, create a new file called MarketplaceContract.cdc.

import PinataPartyContract from 0xf8d6e0586b0a20c7
import PinnieToken from 0xf8d6e0586b0a20c7
pub contract MarketplaceContract {
pub event ForSale(id: UInt64, price: UFix64)
pub event PriceChanged(id: UInt64, newPrice: UFix64)
pub event TokenPurchased(id: UInt64, price: UFix64)
pub event SaleWithdrawn(id: UInt64)
pub resource interface SalePublic {
pub fun purchase(tokenID: UInt64, recipient: &AnyResource{PinataPartyContract.NFTReceiver}, buyTokens: @PinnieToken.Vault)
pub fun idPrice(tokenID: UInt64): UFix64?
pub fun getIDs(): [UInt64]

We need to import both the NFT contract and the fungible token contract. We have defined four events inside the contract definition:

  • ForSale: NFTs for sale
  • PriceChanged: Change in the price for NFTs
  • TokenPurchased: When NFTs are purchased
  • SaleWithdrawn: When NFTs are removed from the marketplace

We have added a resource interface called SalePublic below event emitters. The interface should be public to everyone, not only the contract owner.

We need to add a SaleCollection resource below the SalePublic interface. We have defined a few variables within this resource. For example, mapping of tokens for sale, mapping prices for each token for sale and a protected variable that is only accessible by the contract owner called ownerVault.

We need to initialize variables when defining them on a resource. It is done in the init function and is initialized with the owner’s vault resource and empty values.

Then, it is important to define functions to control the actions of an NFT Marketplace. Functions are:

  • listForSale
  • changePrice
  • withdraw
  • idPrice
  • purchase
  • destroy
  • getIDs

As mentioned above, three of these functions are available publicly, it implies that listForSale, withdraw, destroy and changePrice are only available to the NFT owners being listed. For example, changePrice is not available publicly because we don’t want anyone to change the price of NFTs. The last part of the marketplace contract is the CreateSaleCollection function.

It allows a collection to be added as a resource to the account. After writing that contract, we will deploy it with the emulator account. Run the following command from the root of your project:

flow project Deploy

It will finally deploy the marketplace contract and allow us to use it within the frontend application.

Once it is done, we need to work on the frontend and connect these contracts using the Flow CLI tool.

If you are looking to build a custom NFT marketplace, consult our NFT development experts who will help you from consulting to the marketplace platform’s development and launch. 

Webinar Details

Author’s Bio

Akash Takyar
Akash Takyar
CEO LeewayHertz
Akash Takyar is the founder and CEO at LeewayHertz. The experience of building over 100+ platforms for startups and enterprises allows Akash to rapidly architect and design solutions that are scalable and beautiful.
Akash's ability to build enterprise-grade technology solutions has attracted over 30 Fortune 500 companies, including Siemens, 3M, P&G and Hershey’s. Akash is an early adopter of new technology, a passionate technology enthusiast, and an investor in AI and IoT startups.

Start a conversation by filling the form

Once you let us know your requirement, our technical expert will schedule a call and discuss your idea in detail post sign of an NDA.

All information will be kept confidential.

 Send me the signed Non-Disclosure Agreement (NDA)


NFT APIs as a service

NFT APIs as a service

NFT APIs make working with non-fungible tokens easy. Tasks like extracting data from multiple smart contracts and integrating it into an app can be performed without manual effort.

read more