Select Page

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

develop-nft-marketplace-platform

One of the biggest reasons behind blockchain technology’s growing popularity and widespread adoption across industries is its advanced use cases like NFTs. The popularity of non-fungible tokens, or NFTs, has significantly grown in the past some time, revolutionizing the buying, selling, and trading of digital assets.

NFTs are blockchain-based immutable digital asset ownership records that promise to provide true value. They show advantages in numerous forms. Industries like art, entertainment, music, game, and more have benefitted immensely from the power and potential of NFTs.

People have started relying on NFT-based digital assets for several reasons. One very important fact is that these digital assets are secured through blockchain technology which eliminates long-standing issues of copyright infringement by maintaining digital records that are impossible to delete, edit or hack.

As many have started to engage in the creation and trading of NFTs, a platform where they can be stored has become important. Thus, the demand for NFT marketplace development has increased exponentially. With the help of an NFT marketplace, one can easily list their NFT assets and allow users to acquire them without risk and the involvement of a central party.

No wonder many entrepreneurs have started to consider NFT marketplace development a great opportunity to capitalize on this new wave of technology, quickly becoming a major industry. If you are also interested in developing and launching an 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.

The architecture of an NFT marketplace

While developing an NFT marketplace, it is important to maintain consistency and build an interface that is easy to use for both new and existing users. The architectural components of an NFT marketplace must include a blockchain on which the platform will work, wallets, smart contracts and IPFS.

Blockchain integration 

Various types of blockchain networks can be utilized to build a full-functioning NFT marketplace. These include public, private, consortium and hybrid blockchain networks. The technology helps store information related to NFTs and transactions occurring on the platform.

Token minting

No matter if you allow NFTs with or without gas costs, minting NFTs is important. The process involves validating all the data gathered, creating a new block, and recording it into the blockchain.

Digital wallet

A digital wallet is an electronic wallet that helps users store digital funds. It further allows for buying and selling of NFT assets.

NFT metadata

It is the description of the NFT assets stored on the marketplace. The description may include its name, creation date and time, attributes, true owner, etc.

IPFS (Interplanetary File System)

IPFS is a data storage system used to avoid the power-consuming storage of digital assets with metadata on the blockchain.

Smart contracts

An NFT marketplace deploys smart contracts to create a unique identifier for each NFT. It employs the ERC-721 standard to create non-fungible tokens, differentiating them from fungible crypto tokens.

How does an NFT Marketplace work?

Like any other physical store, a place to store, buy and sell NFTs is also required. An NFT marketplace stores NFT assets and combine a user-friendly interface with highly powerful back-end properties that support the underlying blockchain technology.

In the working of an NFT marketplace, creators and NFT collectors play a major role. 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’s 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

Basics to consider while developing an NFT marketplace

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 on the technology stack required for developing it.

Let us look at some technology components needed for building an NFT marketplace platform.

Technology stack for building an NFT marketplace

nft tech stack

Blockchain Platforms

  • Ethereum
    Ethereum is one of the most popular platforms for NFT marketplace or non-fungible token development. Since transaction history and token metadata are publicly verifiable on Ethereum, it is easier to prove ownership history. As all Ethereum products share a common backend, NFTs become portable across products. Also, Ethereum rarely 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 NFT marketplaces 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 critical information, such as media files. The storage platform includes everything 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 a popular platform for uploading and managing 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.

Why do we need an NFT marketplace?

Big brands, tech enthusiasts, investors, and collectors are finding ways to adopt NFTs to match their pace with speedily advancing technologies, trends and opportunities in the market and expand their offerings. NFTs provide exclusive ownership rights, trading options and an online marketplace to promote extreme liquidity. On top of that, it helps establish a stronger relationship between brands and users.

Thus, having a fully functional NFT marketplace that displays those digitally created NFT assets has become crucial. Here are some reasons why NFT marketplace development is considered important.

  • NFT marketplaces are backed by blockchain technology. Thus, all the transactions related to NFTs are made visible through a publicly distributed ledger. Further, a huge volume of NFT transactions can also take place instantly with no risk involved.
  • All NFT marketplaces are decentralized in nature. This means no third party is involved in any activities occurring on the platform, such as transactions, buying, selling, and trading of NFTs. So, there is no central authority overseeing such platforms.
  • Anybody can easily access NFT assets as they are instantly available in NFT marketplaces. Each NFT displayed on an NFT marketplace platform is unique in nature, with special features and digital identities.
  • Developing an NFT marketplace also increases user loyalty and encourages users from around the world to trust and participate. As NFTs are publicly accessible ownership records, they guarantee authenticity and exclusive ownership.

LeewayHertz’s Whitelabel NFT Marketplace Solution

Launch your custom NFT Marketplace

With no surprise, the surge in demand for NFT marketplaces has made us witness many trends emerging in this area. The new trends in this space are likely to unlock newer opportunities, build trust and help NFTs capture strengthen its foothold across industries.

Let us check on the latest trends with respect to NFT marketplaces.

Celebrity NFT marketplaces

Many big stars, impressed with the potential of non-fungible tokens, are launching their own unique tokenized assets. As a result, fans can now interact with their favorite celebrities more closely. Celebrity NFT marketplaces include autographs, historic moments, pictures, videos, movies, famous dialogues etc., in the form of NFTs for fans to buy and sell.

Multi-chain NFT marketplaces

Such NFT marketplaces allow NFTs to have cross-chain capabilities. Using a multi-chain NFT marketplace, one can create, buy or sell NFTs developed using various blockchain networks. Such a marketplace encourages interoperability, sustainability and less energy consumption.

NFT marketplaces selling online tickets

NFT marketplaces are also being utilized to offer NFT-based tickets for live events or virtual concerts. Such marketplaces are proving to be useful in reducing fraud cases. They also act as a long-term investment as the tickets can be sold and resold at desired prices. This is because NFT tickets can be resold at a standard price, promising a high potential to earn profit.

NFT marketplaces for displaying art

The art industry has probably benefited the most from the introduction of NFTs. Physical artworks are now represented as non-fungible tokens and are displayed on NFT marketplaces where art collectors can buy, sell or trade those digital arts. This has solved many issues like copyright infringement, centralized authorities having all the control, and no trace of ownership history.

NFT marketplaces for in-game assets

The gaming industry is rapidly adopting the concept of NFTs, and the entire gaming ecosystem is now based on NFT assets. Many blockchain-based games have also launched their own NFT marketplaces, which comprise NFT-based in-game assets, such as weapons, land, and more.

How to develop an 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 ‘https://storage.googleapis.com/flow-cli/install.ps1‘) }”

On Linux:

sh -ci “$(curl -fsSL https://storage.googleapis.com/flow-cli/install.sh)”

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.

Contracts

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) {
self.id = 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[token.id] = metadata
self.ownedNFTs[token.id] <-! 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.account.save(<-self.createEmptyCollection(),to: /storage/NFTCollection)
self.account.link<&{NFTReceiver}>(/public/NFTReceiver,target:/storage/NFTCollection)
self.account.save(<-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) {
self.receiverRef=acct.getCapability<&{PinataPartyContract.NFTReceiver}>(/public/NFTReceiver)
.borrow()
?? 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”: {
“address”: “YOUR ACCOUNT ADDRESS”,
“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”)
return
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”
config()
.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

.send([

fcl.script`

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)

setNftInfo(decoded)

};

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

.send([

fcl.script`

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)

setNftInfo(decoded)

};

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)
self.account.save(<-vault, to: /storage/MainVault)
self.account.save(<-create VaultMinter(), to: /storage/MainMinter)
self.account.link<&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”: “127.0.0.1:3569”,
“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. 

Conclusion

By following these simple steps, any business or developer can create a feature-packed, fully functional NFT marketplace where NFTs can be conveniently bought and sold.

The ever-growing popularity of NFTs has sparked the need to have more NFT marketplaces. This is to allow storing of these digital assets and further make them accessible for easy buying and selling. In a way, it can be stated that NFT marketplace development would be a major driver of the blockchain industry’s growth and success.

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.

 

Insights

How Web3 Data Storage Works

How Web3 Data Storage Works

Web3 storage gives users control over data through decentralization but retains full access to storage and communication. This article describes web3 decentralized storage solutions.

read more