How To Build an NFT Marketplace Instantly

How to build nft marketplace instantly no difficult coding or complex programming, develop your nfts marketplace based simple step follow easy auto instruction here.

First Step : You Should Own Catchy and Memorabe Domain Name (Exact Match Keyword is Better to Remember)

As the non-fungible tokens (NFTs) market reaches a fever pitch, it’s interesting to look back on the relatively early days of NFTs and remember the challenges that were exposed by CryptoKitties. The platform, built by the team at Dapper Labs, was the first real example of potential mass adoption and the first real strain on the Ethereum blockchain.

Since then, NFTs have taken off with platforms like Rarible , OpenSea, Foundation, and Sorare springing up. These platforms are seeing millions of dollars flow through monthly. Most of this has happened, despite the early struggles, on the Ethereum blockchain. However, the team at Dapper Labs, after their experience with CryptoKitties, set out to build a new blockchain that would be general-purpose but would also be a great fit for the NFT use case.

In doing so, their goal was to solve many of the problems they saw with NFTs on Ethereum while providing a better experience to both developers and collectors in the space. Their new blockchain, Flow, has proven itself capable of landing some big names. The NBA, UFC, and even Dr. Seuss are on Flow.

We recently wrote about creating NFTs with built-in asset support on IPFS, and we’ve talked about the responsibility problem in the NFT space and how we think IPFS can help. It’s now time to talk about how to create NFTs on Flow backed by IPFS. One of the major early applications of the Flow blockchain is NBA Top Shot. We’re going to build a very basic replica of the NFT minting process and then back the NFT metadata and assets on IPFS.

Since we love piñatas, instead of videos of NBA highlights, our NFTs are going to be focused on trade-able videos of piñatas being smashed at parties. This is a three-part tutorial:

Creating the contract and minting a token

Creating an app to view NFTs created through this contract

Creating a marketplace to transfer NFTs to others while also transferring the NFT’s underlying assets on IPFS

Let’s get started with the first tutorial.

Setting Up

We need to get the Flow CLI installed. There are some good install instructions within Flow’s documentation, but I’ll copy them here:

macOS

brew install flow-cli

Linux
sh -ci “$(curl -fsSL https://storage.googleapis.com/flow-cli/install.sh)”
Windows
iex “& { $(irm ‘https://storage.googleapis.com/flow-cli/install.ps1′) }”

We are going to be storing asset files on IPFS. To make that easier, we can use Pinata. You can sign up for a free account here and grab an API Key here. We’ll use the API in the second post of this tutorial, but we’ll use the Pinata website in this post.

We also need to have NodeJS installed and a text editor that can help with syntax highlighting of Flow smart contract code (which is written in a language called Cadence). You can install Node here. Visual Studio Code has an extension that supports Cadence.

Let’s create a directory to house our project.
mkdir pinata-party

Change into that directory and initialize a new flow project:
cd pinata-party
flow project init

Now, open the project in your favorite code editor (again, if you use Visual Studio Code, grab the Cadence extension), and let’s get to work.
You’ll see a flow.json file that we will be making use of soon. First, create a folder called cadence. Within that folder, add another folder called contracts. And finally, create a file within the contracts folder called PinataPartyContract.cdc.

Before we move forward, it’s important to point out that everything we do in regards to the Flow blockchain from this point forward will be done on the emulator. However, deploying a project to testnet or mainnet is as simple as updating configuration settings in your flow.json file. Let’s set that file up for the emulator environment now and then we can start writing our contract.Update the contracts object in flow.json to look like this:

“contracts”: {
“PinataPartyContract”: “./cadence/contracts/PinataPartyContract.cdc”
}
Then, update the deployments object in that file to look like this:
“deployments”: {
“emulator”: {
“emulator-account”: [“PinataPartyContract”]
}
}

This is telling the Flow CLI to use the emulator to deploy our contract, it’s also referencing the account (on the emulator) and the contract we will write soon. Actually…
Let’s start writing that bad boy now.

The Contract
Flow has a great tutorial on creating NFT contracts. It’s a good reference point, but as Flow points out themselves, they have not yet solved the NFT metadata problem. They would like to store metadata on chain. That’s a great idea, and they will surely come up with a logical approach to it. However, we want to mint some tokens with metadata now, AND we want media files associated with the NFT. Metadata is only one component.

We need to also point to the media that the token ultimately represents. If you’re familiar with NFTs on the Ethereum blockchain, you may know that many of the assets those tokens back are stored on traditional data stores and cloud hosting providers. This is OK except when it’s not. We’ve written in the past about the genius of content-addressable content and the downsides to storing blockchain-adjacent data on traditional cloud platforms. It all boils down to two main points:

The assets should be verifiable
It should be easy to transfer the maintenance responsibilities
IPFS takes care of both of these points. Pinata then layers in an easy way to pin that content long-term on IPFS.

This is exactly what we want for the media that backs our NFTs, right? We want to make sure that we can prove ownership (the NFT), provide data about the NFT (the NFT), and ensure that we have control over the underlying asset (IPFS) —media or otherwise—and not some replica.

With all this in mind, let’s write a contract that mints NFTs, associates metadata to the NFT, and ensures that metadata points to the underlying asset stored on IPFS. Open up the PinataPartyContract.cdc and let’s get to work.

The first step is defining our contract. We’re going to add a whole lot more to this, but we start by defining PinataPartyContract and within that, we create a resource. Resources are items stored in user accounts and accessible through access control measures. In this case, the NFT resource ultimately because the thing that is used to represent NFTs owned. NFTs have to be uniquely identifiable. The id property allows us to identify our tokens.

Next, we need to create a resource interface that we will use to define what capabilities are made available to others (i.e. people who are not the contract owner): Put this right below the NFT resource code. This NFTReceiver resource interface is saying that whoever we define as having access to the resource will be able to call the following methods:

deposit
getIDs
idExists
getMetadata

Next, we need to define our token collection interface. Think of this as the wallet that houses all a user’s NFT.
There’s a lot going on in this resource, but it should make sense soon. First, we have a variable called ownedNFTs. This one is pretty straightforward. It keeps track of all the NFTs a user owns from this contract.
Next, we have a variable called metadataObjs.

This one is a little unique because we are extending the Flow NFT contract functionality to store a mapping of metadata for each NFT. This variable maps a token id to its associated metadata, which means we need the token id before we can set it.

We then initialize our variables. This is required for variables defined in a resource within Flow.
Finally, we have all of the available functions for our NFT collection resource. Note that not all of these functions are available to the world. If you remember, we defined the functions that would be accessible to anyone earlier in our NFTReceiver resource interface.

I do want to point out the deposit function. Just as we extended the default Flow NFT contract to include the metadataObjs mapping, we are extending the default deposit function to take an additional parameter of metadata. Why are we doing this here?

We need to make sure that only the minter of the token can add that metadata to the token. To keep this private, we keep the initial addition of the metadata confined to the minting execution.We’re almost done with our contract code. So, right below the Collection resource, add this:

First, we have a function that creates an empty NFT collection when called. This is how a user who is first interacting with our contract will have a storage location created that maps to the Collection resource we defined.

After that, we create one more resource. This is an important one, because without it, we can’t mint tokens. The NFTMinter resource includes an idCount which is incremented to ensure we never have duplicate ids for our NFTs. It also has a function that actually creates our NFT.

Right below the NFTMinter resource, add the main contract initializer: This initializer function is only called when the contract is deployed. It does three things:

Creates an empty Collection for the deployer of the collection so that the owner of the contract can mint and own NFTs from that contract.

The Collection resource is published in a public location with reference to the NFTReceiver interface we created at the beginning. This is how we tell the contract that the functions defined on the NFTReceiver can be called by anyone.

The NFTMinter resource is saved in account storage for the creator of the contract. This means only the creator of the contract can mint tokens.

The full contract can be found here.
Now that we have a contract ready to go, let’s deploy it, right? Well, we should probably test it on the Flow Playground. Go there and click on the first account in the left sidebar. Replace all the code in the example contract with our contract code, then click Deploy. If all goes well, you should see a log like this in the log window at the bottom of the screen:
16:48:55 Deployment Deployed Contract To: 0x01

Now we’re ready to deploy our contract to the locally running emulator. From the command line, run this:
flow project start-emulator Now, with our emulator running and our flow.json file configured properly, we can deploy our contract. Simply run this command:
flow project deploy
I
f all went well, you should see an output like this:
Deploying 1 contracts for accounts: emulator-account
PinataPartyContract -> 0xf8d6e0586b0a20c7
We now have a contract live on the Flow emulator, but we want to mint a token. Let’s close out this blog post by taking care of that.
Minting The NFT

In the second post in this tutorial, we’ll work on making the minting process more user friendly with an app and a user interface. For the sake of getting something minted and showing how metadata will work with our NFTs on Flow, we’re going to use Cadence scripts and the command line.

Let’s create a new directory within the root of our pinata-party project, and let’s call it transactions. Once you have that folder created, create a new file within in that is called MintPinataParty.cdc.
For us to write our transaction, we need to have a file to reference in the metadata we provide to the NFT. For that, we will upload a file to IPFS via Pinata.

For the sake of this tutorial, and because our NFTs are focused on trade-able videos of piñatas being smashed at parties, we will be uploading a video of a kid hitting a piñata at a birthday party. You can upload any video file you’d like. You can really upload any asset file you’d like and associate that with your NFT, but the second post in this tutorial series will be expecting video content.

Once you have your video file ready to go, upload it here. When you’ve uploaded the file, you will be provided an IPFS hash (often referred to as a content identifier or CID). Copy this hash because we will use it in the minting process.

Now, inside your MintPinataParty.cdc file, add the following: This is a pretty simple transaction, thanks in large part to the work Flow has put in to make things easy, but let’s walk through it. First, you’ll notice the import statement at the top. If you remember, when we deployed the contract, we received an account for it.

That’s what we need to reference. So replace 0xf8d6e0586b0a20c7 with the account address from your deployment. Next we define the transaction. Everything that happens in here is related to the transaction we plan to execute.

The first thing we do in our transaction is define two reference variables, receiverRef and minterRef. In this case we are both the receiver of the NFT and the minter of the NFT. Those two variables are referencing resources we created in our Contract. If the person executing the transaction doesn’t have access to the resource, the transaction will fail.

Next, we have a prepare function. This function takes the account information of the person trying to execute the transaction and does some validations. We try to “borrow” the capabilities available on the two resources we defined NFTMinter and NFTReceiver. This is where things will fail if the person executing the transaction does not have access to those resources.

Finally, we have our execute function. This function is where we build up the metadata for our NFT, mint the NFT, then associate the metadata prior to depositing the NFT in our account. If you notice, I created a metadata variable. Within that variable, I added some info about our token.

Since our token is representing an event where a piñata is smashed at a party, and because we are trying to replicate much of what you see in NBA Top Shot, I have defined some statistics in the metadata. The velocity at which the kid swings the stick to hit the piñata, the angle of the swing, and a rating. I’m just having fun with these stats. You would enter whatever information makes sense for your token in a similar way, though.
You’ll note, I am also defining a uri property in the metadata.

This is going to point to the IPFS hash that hosts our asset file associated with the NFT. In this case, it is the actual video of the piñata being hit. You can replace the hash with the hash you received after you uploaded your file earlier.

We are prefixing the hash with ipfs:// for a couple of reasons. This is the correct reference for a file on IPFS and can be used with IPFS’s desktop client and browser extension. We can also paste it directly into the Brave browser now that they offer native support for IPFS content.

We call the mintNFT function which creates the token. We then have to call the deposit function to put it into our account. This is also where we pass in the metadata. If you remember, we defined in our deposit function a variable association that adds the metadata to the associated token id.

Finally, we simply log out the fact that the token has been minted and deposited. We’re now almost ready to send our transaction and mint the NFT. But first, we need to prepare our account. From the command line within your project’s root folder, let’s create a new private key for signing.

Run the following command:
flow keys generate
This will give you a public and a private key. ALWAYS PROTECT YOUR PRIVATE KEY
We will need the private key to sign the transaction, so we can paste that into our flow.json file. We also need to specify the signing algorithm. Here’s what your accounts object in the flow.json file should look like now:
“accounts”: {
“emulator-account”: {
“address”: “YOUR ACCOUNT ADDRESS”,
“privateKey”: “YOUR PRIVATE KEY”,
“chain”: “flow-emulator”,
“sigAlgorithm”: “ECDSA_P256”,
“hashAlgorithm”: “SHA3_256”
}
},

If you intend to store any of this project on github or any remote git repository, make sure you do not include the private key. You may want to .gitignore your entire flow.json. Even though we are only using a local emulator, it’s good practice to protect your keys.

Now that we’ve updated this, we can send our transaction. Doing so is as simple as running this command:
flow transactions send –code ./transactions/MintPinataParty.cdc –signer emulator-account We are referencing the transaction file we wrote and our signer account from the flow.json. If everything went well, you should see an output like this:

Getting information for account with address 0xf8d6e0586b0a20c7 …
Submitting transaction with ID 4a79102747a450f65b6aab06a77161af196c3f7151b2400b3b3d09ade3b69823 …
Successfully submitted transaction with ID 4a79102747a450f65b6aab06a77161af196c3f7151b2400b3b3d09ade3b69823

Now, the last thing we need to do is verify the token is in our account and fetch the metadata. Do do this, we’re going to write a very simple script and call it from the command line. From the root of your project, create a new folder called scripts. Inside of that, create a file called CheckTokenMetadata.cdc.

In that file, add the following: This script can be thought of in a similar way to read-only methods on Ethereum smart contracts are utilized. They are free and simply return data from the contract. In our script, we are importing our contract from the deployed address. We are then defining a main function (which is the required function name for a script to run). Inside this function, we’re defining three variables:
nftOwner:

This is simply the account that owns the NFT. We minted the NFT from the account that also deployed the contract, so in our example those two addresses are the same. That may not always be true depending on the design of your contracts in the future.capability: We need “borrow” the available capabilities (or functions) from the deployed contract.

Remember, these capabilities are access-controlled, so if a capability is not available to the address trying to borrow it, the script will fail. We are borrowing capabilities from the NFTReceiver resource.
receiverRef: This variable simply takes our capability and tells the script to borrow from the deployed contract.

Now, we can call functions (that are available to us). In this case, we want to make sure the address in question actually has received the NFT we minted, and then we want to see the metadata associated with the token.
Let’s run our script and see what we get. Run the following on the command line:
flow scripts execute ./scripts/CheckTokenMetadata.cdc

You should see an output something like this for the metadata output:
{“name”: “The Big Swing”, “swing_velocity”: “29”, “swing_angle”: “45”, “rating”: “5”, “uri”: “ipfs://QmRZdc3mAMXpv6Akz9Ekp1y4vDSjazTx2dCQRkxVy1yUj6”}

Congratulations! You successfully created a Flow smart contract, minted a token, and associated metadata to the token, and stored the token’s underlying digital asset on IPFS. Not too bad for part one of a tutorial.Next up, we have a tutorial on building a front-end React application that will allow you to display your NFT by fetching the metadata and resolving that metadata.

Display Your NFT Collectibles Like NBA Top Shot With Flow and IPFS

Resolve the NFT’s metadata to get the IPFS location of the NFT’s underlying digital asset (in this case a video). Quick reminder about the NFT we’re working on — we’re building NFTs that, like NBA Top Shot, back video content, but unlike Top Shot, the videos are of people smashing piñatas.

Setup
For this tutorial, you’ll need to have your Flow emulator running. If you don’t remember how to start that, take a look at the previous post or check out the Flow CLI docs. It’s important to note that the Flow emulator is an in-memory representation of the Flow blockchain. So if between the first post and this one, you shut down the emulator, you’ll need to go ahead and do the following:

Start the emulator

Deploy the project

Mint your NFT

Each of those steps is covered in detail in part one of this series. In addition, you’re going to need to have NodeJS installed on your machine. You can install it here. And as usual, you’ll need a text editor.
Setting Up React And Dependencies
I’m going to be creating my React app within the parent pinata-party directory I started in part one of these tutorials. However, if you want, you can create your React app in a completely new directory.
To create our app, run:
npx create-react-app pinata-party-frontend

When everything is done installing, you’ll have a new directory called pinata-party-frontend. Switch into that directory, and we’ll need to install some dependencies. First, per the documentation on Flow here, you’ll need to install the Flow JS SDK. In fact, for the first part of the frontend setup, we’re just going to follow the Flow documentation.

Let’s continue. Run:
npm i @onflow/fcl @onflow/types
We’re going to store some values as global variables for our application. We will make use of environment variables. In react, this means creating a .env file and setting key value pairs where the keys are prefixed with REACT_APP. If you follow the Flow documentation, you’ll be set up to be connected with their testnet. For the sake of this tutorial, we’re connecting to the Flow emulator. So, we’ll need to make some changes. In your .env file add the following:
REACT_APP_ACCESS_NODE=http://localhost:8080
REACT_APP_WALLET_DISCOVERY=https://fcl-discovery.onflow.org/testnet/authn
REACT_APP_CONTRACT_PROFILE=0xf8d6e0586b0a20c7
Replace the REACT_APP_ACCESS_NODE value with the local emulator url as indicated above. Replace the REACT_APP_CONTRACT_PROFILE value with the address you received when you deployed your project.
Now that we have that, we need to create a config file that we will use to interact with the Flow JS SDK. Create a file in the src directory called config.js. Add the following:
import {config} from “@onflow/fcl”
config()
.put(“accessNode.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”
Now, let’s wire up some authentication. You don’t need to force people to authenticate into the site if you don’t want to, but it will be important to have authentication for part three of the tutorial which enables the transferring of NFT assets.
We need to create an authentication component. In your src directory, create a file called AuthCluster.js. Inside that file, add the following:

This is simple using a login and sign up button to leverage the Flow JS SDK’s ability to connect to a wallet discovery provider. You’ll be able to sign up for an account or sign in with an existing account. It’s pretty nice!
Now, we need to get this component into our app. Let’s keep it simple for now. Replace your App.js file with the following:
import ‘./App.css’;
import AuthCluster from ‘./AuthCluster’;
function App() {
return (

);
}
export default App;
If you start the app now (npm start), you should see a page with a login and a sign up button. In fact, both of those buttons are functional. Try it out.

Ok, now that our React app is largely set up and our dependencies are installed, let’s get to building out the ability to fetch NFTs for an account and display them.
Fetching NFTs From Flow

In order to display our NFT that minted in the first post, we need to be able to communicate with the Flow blockchain. In the case of this tutorial, we need to be able to communicate with the Flow emulator. We already told our app that the emulator was running on port 8080 when we set up our .env file. But now, how do we use JavaScript to talk to Flow?

Fortunately, Flow has this functionality built into their JS SDK. If you remember, we previously wrote a script to look up an NFT based on its token id and return the token’s metadata. It looked like this:

Now, we just need to be able to convert that into a JavaScript call. Let’s create a new component that will allow us to both fetch data and eventually display the NFT data. In your src directory, create a file called TokenData.js. In that file, add the following:

In this file, we are creating a component that has a button to fetch token data. We are also creating a button to clear token data. When the fetch button is clicked, it calls a function we created called fetchTokenData. That function uses the Flow JS SDK to execute the exact same script we executed in part one of this tutorial from the command line, but in React. We take the results of the execution and we set the results to a state variable called nftInfo. If that variable exists, we render the key value pairs from the NFT metadata on screen and a button that lets us clear the data.

I’ve also added a bit of CSS to make things look less plain. If you want to add the same CSS, it’s here, and all you have to do is replace App.css with this:

Now, just add your new component to App.js below the AuthCluster component like this:
import ‘./App.css’;
import AuthCluster from ‘./AuthCluster’;
import TokenData from ‘./TokenData’;
function App() {
return (

);
}
export default App;
Check out your app now and try to fetch your token data. It should look like this:

This is pretty cool! We are looking up an NFT owned by the account we specified, then we are fetching the metadata from that token. We are displaying that metadata on screen, but we know that one value in that metadata resolves to a video file. Let’s see if we can get that rendered on screen shall we?
Getting Media From IPFS

You already signed up for a Pinata account and you added your video file to IPFS through the Pinata upload interface. That means you have been able to fetch content from IPFS already. In the Pin Explorer, when you click on a hash, you are taken to the Pinata IPFS gateway where your IPFS content is resolved and displayed to you. For the sake of this tutorial, we’re going to keep things a little more general while at the same time highlighting the beauty of IPFS.

That is to say, you don’t have to fetch your content from the Pinata gateway. Instead, we’re going to fetch it from the public Protocol Labs gateway.
Let’s dive in.

Back in your TokenData.js file, let’s add a way to display the video file we ultimately retrieve from IPFS. Update your file to look like this:

We’ve added a video element with the source pointing to the file on IPFS. You’ll notice that we had to split the uri value to get just the IPFS hash so that we could fetch the content from the IPFS gateway. Let’s talk about that URI for a moment.

The uri we created with our NFT look like ipfs://Qm…. We created it that way because the IPFS desktop client will allow you to click on and open links that look like that by default. Also, the Brave browser supports pasting in links that look like that. We think this link format will be supported more and more as we go.

However, in this case, we need the hash so that we can fetch the content from the IPFS public gateway. When we’re done, the link would look like this: https://yourdomain.tld/ipfs/QmRZdc3mAMXpv6Akz9Ekp1y4vDSjazTx2dCQRkxVy1yUj6

Now, if you try fetching the token data in our app, you should get something like this:

Our NFT is no longer a faceless token on a blockchain. It’s a real live digital asset! Your video will probably be different, but hopefully the result you see in your app is essentially the same experience.
Wrapping Up

This is a very simple app, and there is a lot you can do to make it prettier, make it more interactive, and even add more Flow elements to it. The Flow JS SDK is powerful, so I recommend reading through the docs.

We successfully added authentication to our app using Flow, we created an interface to fetch information about an NFT, and we created a way to display not just the raw metadata but the underlying digital asset. All of this is secured by both the Flow blockchain and IPFS.

We know that the NFT is owned by the person who says they own it, and we know the content displayed is valid because the hash is encoded into the NFT. In the final installment of this series, we’ll focus on creating a mini-marketplace that will allow us transfer NFTs.

This is The Final Step

Final part of the series, we’re going to finish things up by enabling the transfer of NFTs. As we’ve come to expect, Flow has some great documentation around this concept, but we are going to extend those docs and make them fit the paradigm of IPFS-hosted content. Let’s dive in!

Setting Up
Hopefully, you’ve been following along with the prior two tutorials. If so, you have all the starter code necessary to continue, and we’re going to simply add to that code. If you have not yet started the other tutorials, you’re going to be lost So definitely go back and work your way through those tutorials.
Now, go ahead and open your project. That’s all the setup we need. Congratulations!

Creating Contracts
A marketplace requires a few more things beyond what we have already built. Let’s list those things here:
Payment mechanism (i.e. fungible tokens)

Token transfer capabilities

Token supply settings
Because the Flow Emulator is an in-memory representation of the Flow blockchain, you’ll want to make sure you execute the previous tutorials before this step and make sure to keep the emulator running. Assuming you’ve done that, let’s create a fungible token contract that can be used for payments when buying NFTs.

To be clear, creating a purchasing mechanism for these fungible tokens we’re about to create is outside the scope of this tutorial. We’re simply going to mint and transfer tokens to accounts that will be purchasing NFTs.
Inside your pinata-party directory that you created in part one of this series, go into the cadence/contracts folder and create a new file called PinnieToken.cdc. This is going to be our fungible token contract. We’ll start by defining the empty contract like this:
pub contract PinnieToken {
}

Each piece of code within the main contract code will be its own Github gist, and I’ll provide the full contract code at the end. The first piece we’re going to add to this contract is the token pub variables associated with our token and a Provider resource.

Add the above code right inside the empty contract we created initially. The totalSupply and the tokenName variables are self-explanatory. We’ll set these later when we initialize our token contract.The resource interface called Provider that we created takes a little more explanation.

This resource simply defines a function that will be public, but interestingly, it will still only be callable by the account owner from whom the withdraw is being executed against. That is to say that I could not execute a withdraw request against your account.Next, we’re going to define two more public resource interfaces:

These go directly below the Provider resource interface. The Receiver interface includes a function that will be executable by anyone. This ensures that deposits into an account can be executed as long as the recipient has initialized a vault that can handle these tokens we’re creating through this contract. You’ll see the reference to a Vault coming up soon. The Balance resource will simply return a balance of our new token for any given account. Let’s now create the Vault resource we mentioned above. Add the following below the Balance resource:

The Vault resource is the main attraction here. I say this because without it, nothing can happen. If a reference to the Vault resource is not stored in an account’s storage, that account cannot receive these particular tokens. Which means that account can’t send these tokens. Which also means that account can’t buy NFTs. And darn it, we want to buy some NFTs.

Now, let’s take a look at what the Vault resource implements. You can see that our Vault resource inherits the Provider, Receiver, and Balance resource interfaces, and then it defines two functions: withdraw and deposit. If you remember, the Provider interface gave access to the withdraw function, so we’re simply defining that function here.

And the Receiver interface gave access to the deposit function, which we are defining here.
You will also note that we have a balance variable that is initialized with the Vault resource. This balance represents a given account’s balance.

Now, let’s figure out how we can make sure an account gets access to the Vault interface. Remember, without it, nothing can happen with this token we want to create. Below the Vault interface, add the following function:
pub fun createEmptyVault(): @Vault {
return <-create Vault(balance: 0.0)
}
This function, as the name implies, creates an empty Vault resource for an account. The balance, of course, is 0.
I think it’s about time to set up our minting capability. Add this below the createEmptyVault function:

The VaultMinter resource is public, but by default it is only available to the contract account owner. It is possible to make this resource available to others, but we’re not going to be focusing on that within this tutorial.
The VaultMinter resource has just one function: mintTokens.

That function requires an amount to mint and a recipient. As long as the recipient has the Vault resource stored, the newly minted tokens can be deposited into that account. When tokens are minted, the totalSupply variable has to be updated, so we add the amount minted to the previous supply to get our new supply. Ok, we’ve made it this far. There’s one thing left to do with our contract. We need to initialize it. Add this after the VaultMinter resource.

When we initialize our contract, we need to set a total supply. This could be any number you choose. For the sake of our example, we’re initializing this with a supply of 30. We are setting our tokenName to “Pinnie” because this is all about Pinata Parties after all. We are also creating a vault variable that creates a Vault resource with the initial supply and stores it in the contract creator’s account.

That’s it. That’s the contract. Here’s the full code.

Deploying and Minting Tokens
We need to update the flow.json file in our project so that we can deploy this new contract. One thing that you may have discovered in the previous tutorials is the structure of the flow.json file needs to be slightly different when you are deploying contracts compared to when you are executing transactions. Make sure your flow.json references the new contract and has the emulator-account key reference like this:

In another terminal window from within your pinata-party project directory, run flow project deploy. You’ll get the account for the deployed contract (which is the same account that the NFT contract was deployed under). Keep that somewhere because we will be making use of it soon.

Now, let’s test out our minting function. We’re going to create a transaction that allows us to mint Pinnie tokens, but first, we need to again update our flow.json. (There may be a better way to do this, but it’s what I’ve found to work when doing things on the emulator). Under the emulator-account change your json back to look something like this:
“emulator-account”: {
“address”: “f8d6e0586b0a20c7”,
“privateKey”: “e5ca2b0946358223f0555206144fe4d74e65cbd58b0933c5232ce195b9058cdd”,
“sigAlgorithm”: “ECDSA_P256”,
“hashAlgorithm”: “SHA3_256”,
“chain”: “flow-emulator”
},
The key field once again becomes the privateKey field, and then we add in our sigAlogrithm, hashAlgorithm, and chain properties. For whatever reason, this format works for sending transactions whereas the other format works for deploying contracts.

Ok, we need to do one more thing to allow our account we used to deploy the contract to mint some Pinnies. We need to create a link. This is an easy transaction that just gives access to the minting functionality. So, inside your transactions folder, add a file called LinkPinnie.cdc. In that file, add:

This transaction imports our Pinnie contract. It then creates a transaction that links the Receiver resource to the count that will ultimately be doing the minting. We would do this same thing for other accounts that need a reference to that resource.

With the transaction created, let’s go ahead and run it. In your terminal at the root of the project, run:
flow transactions send –code transactions/LinkPinnie.cdc
Now, we’re ready to move on. Let’s mint some Pinnies! To do this, we need to write a transaction. This transaction is pretty straightforward so I’m going to drop the full code snippet below:

This code should be added to a file called MintPinnie.cdc within your transactions folder. This transaction is importing our PinnieToken contract at the top, then it is creating references to two of the resources we defined in that contract. We defined a VaultMinter resource and a Receiver resource, among others.

Those two resources are being used here. The VaultMinter is, as you’d expect, being used to mint the token. The Receiver resource is being used to handle the depositing of the new tokens into an account.This is just a test to make sure we can mint tokens and deposit them into our own account. Very soon, we will create a new account, mint tokens, and deposit them into another account.

Run the transaction from the command line like this:
flow transactions send –code /transactions/MintPinnie.cdc –signer emulator-account. Remember, we deployed the contract with the emulator-account, so unless we provide a link and allow some other account to mint, the emulator-account is the one that has to do the minting. Let’s now create a script to check our Pinnie balance to make sure this all worked. Inside the scripts folder of your project, create a file called CheckPinnieBalance.cdc and add the following:

Again, we are importing the contract, we are hard-coding the account we want to check on (the emulator-account), and we are borrowing a reference to the Balance resource for the Pinnie Token. We return the balance at the end of the script so that it is printed on the command line.

When we created the contract, remember that we set an initial supply of 30 tokens. So when we ran that MintPinnie transaction, we should have minted and deposited an additional 30 tokens into the emulator-account. This means, if all went well, this balance script should show 60 tokens.
We can run the script with this command:
flow scripts execute –code scripts/CheckPinnieBalance.cdc
And the result should look something like this:
{“type”:”UFix64″,”value”:”60.00000000″}

Fantastic! We can mint tokens. Let’s make sure we can mint some and deposit them into a fresh account for someone else (really, it’s still just you, but we can pretend).
To create a new account, you’ll need to first generate a new keypair. To do this, run the following command:
flow keys generate

This will generate a private key and a public key. We need the public key to generate a new account, and we will soon use the private key to update our flow.json. So, let’s create that new account now. Run this command:
flow accounts create –key YourNewPublicKey

This will create a transaction, and the result of that transaction will include the new account address. You should have received a transaction ID as a result of creating the new account. Copy that transaction ID, and run the following command:
flow transactions status YourTransactionId
This command should result in something like this:
Status: SEALED
Events:
Event 0: flow.AccountCreated: 0x5af6470379d5e29d7ca6825b5899def6681e66f2fe61cb49113d56406e815efa
Fields:
address (Address): 01cf0e2f2f715450
Event 1: flow.AccountKeyAdded: 0x4e9368146889999ab86aafc919a31bb9f64279176f2db247b9061a3826c5e232
Fields:
address (Address): 01cf0e2f2f715450
publicKey (Unknown): f847b840c294432d731bfa29ae85d15442ddb546635efc4a40dced431eed6f35547d3897ba6d116d6d5be43b5614adeef8f468730ef61db5657fc8c4e5e03068e823823e8
The address listed is the new account address. Let’s use that to update our flow.json file.
Inside that file, under your accounts, object, let’s create a new reference to this account. Remember that private key from earlier? We’re going to need that now. Set your accounts object to look something like this:
“accounts”: {
“emulator-account”: {
“address”: “f8d6e0586b0a20c7”,
“keys”: “e5ca2b0946358223f0555206144fe4d74e65cbd58b0933c5232ce195b9058cdd”
},
“second-account”: {
“address”: “01cf0e2f2f715450”,
“keys”: “9bde7092cc0695c67f896e4375bffa0b5bf0a63ce562195a36f864ba7c3b09e3”
}
},
We now have a second account we can use to send Pinnie tokens to. Let’s see how that looks.
Sending Fungible Tokens
Our main account (the one that created the Pinnie Token) currently has 60 tokens. Let’s see if we can send some of those tokens to our second account.

If you remember from earlier, each account needs to have an empty vault in order to accept Pinnie Tokens, and it needs to have a link to the resources on the Pinnie Token contract. Let’s start by creating an empty vault. We need a new transaction for this. So, create a file in your transactions folder called CreateEmptyPinnieVault.cdc . Inside that file, add the following:

In this transaction, we are importing the Pinnie Token contract, we are calling the public function createEmptyVault, and we are using the Receiver resource on the contract to link it up with the new account.
Notice in the post section that we have a check in place. Make sure you replace NEW_ACCOUNT_ADDRESS with the account address you just created previously and prefix it with a 0x.

Let’s run the transaction now. In the root of your project, run:
flow transactions send –code transactions/CreateEmptyPinnieVault.cdc –signer second-account
Notice, we defined the signer as second-account. This is making sure that the transaction is executed by and for the correct account and not our original emulator-account. Once this is done, we can now link to the Pinnie Token resource. Run the following command:
flow transactions send –code transactions/LinkPinnie.cdc –signer second-account
All of this has been setup so that we can transfer tokens from the emulator-account to the second-account. To do this, we need—you guessed it—another transaction. Let’s write that now.
In your transactions folder, create a file called TransferPinnieToken.cdc. Inside that file, add the following:

We are importing the Pinnie Token contract, like always. We are then creating a temporary reference to the Pinnie Token vault. We do this because when dealing with fungible tokens, everything takes place inside a vault. So we will need to withdraw tokens from the emulator-account’s vault, place them into the temporary vault, then send that temporary vault to the recipient (second-account).

On line 10, you see the amount we are withdrawing and sending to the second-account is 10 tokens. That seems fair. Our friend, second-account isn’t too greedy.
Be sure to replace the value of NEW_ACCOUNT_ADDRESS with the second-account address. Prefix it with a 0x. With that done, let’s execute the transaction. Run:
flow transactions send –code transactions/TransferPinnieTokens.cdc –signer emulator-account
The signer needs to be the emulator account since the emulator account is the only one with tokens right now. After you execute the above transaction, we will now have two accounts with tokens. Let’s prove this.
Open up your CheckPinnieBalance script and replace the account address on line 3 with the address for second-account. Again, make sure you prefix the address with a 0x. Save that and then run the script like this:
flow scripts execute –code scripts/CheckPinnieBalance.cdc
You should see the following result:
{
“type”: “UFix64”,
“value”: “10.00000000”
}
And with that, you have now minted a fungible token that can be used as a currency, and you have transferred some of those tokens to another user. Now, all that’s left is allowing that second account to purchase our NFT from a marketplace.

Creating a Marketplace
We are going to simply update our React code from the second tutorial in this series to act as our marketplace. We will need to make it so that the NFT is displayed alongside a price in Pinnie Tokens. We will need a button that allows a user to purchase the NFT.
Before we can work on the frontend code, we need to create one more contract. For us to have a marketplace, we need a contract that can handle the marketplace creation and management. Let’s take care of that now.
In your cadence/contracts folder, create a new file called MarketplaceContract.cdc. The contract is larger than some of our others, so I’ll break it into a few code snippets and then reference the full contract when we’ve finished building it.
Start by adding the following to your file:

We are importing both our NFT contract and our fungible token contract as they will both work in conjunction with this marketplace contract. Inside the contract definition, we define four events: ForSale (indicates the NFT is for sale), PriceChanged (indicates a change in price for the NFT), TokenPurchased (indicates an NFT was purchased), and SaleWithdrawn (indicates an NFT was removed from the marketplace).

Below those event emitters, we have a resource interface called SalePublic. This is an interface we are going to make publicly available to anyone, not just the contract owner. Inside this interface, we are exposing three functions that we will write soon.
Next, below the SalePublic interface, we’re going to add a SaleCollection resource. This is the main focus of the contract, so unfortunately, I couldn’t easily break it into smaller pieces. This code snippet is longer than I’d like, but we’ll walk through it:

Within this resource, we are first defining a few variables. We define a mapping of tokens for sale called forSale, we define a mapping of prices for each token for sale in the prices variable, and then we define a protected variable that can only be accessed by the contract owner called ownerVault.

As usual, when we define variables on a resource, we need to initialize them. So we do that in our init function and simply initialize with empty values and the owner’s vault resource.
Next up is the meat of this resource. We are defining the functions that control all of our marketplace’s actions. Those functions are:
withdraw
listForSale
changePrice
purchase
idPrice
getIDs
destroy
If you remember, we previously had exposed only three of those functions publicly. That means, withdraw, listForSale, changePrice, and destroy are only available to the owner of the NFT being listed, which makes sense. We don’t want anyone being able to change an NFT’s price, for example.
The final part of our Marketplace contract is createSaleCollection function. This allows a collection to be added as a resource to an account. It looks like this and comes after the SaleCollection resource:
pub fun createSaleCollection(ownerVault: Capability<&AnyResource{PinnieToken.Receiver}>): @SaleCollection {
return <- create SaleCollection(vault: ownerVault)
}
Here’s the full contract for you to reference.
With that contract in place, let’s deploy it with our emulator account. From the root of your project, run:
flow project deploy
This will deploy the Marketplace contract and will allow us to use it from within our frontend application. So, let’s get to updating the frontend app.
Frontend
As I mentioned before, we’re going to use the foundation we laid in the last post to build our marketplace. So in your project, you should already have a frontend directory. Change into that directory and let’s take a look at the App.js file.
Right now, we have authentication and the ability to fetch a single NFT and display its metadata. We want to replicate this but fetch all of the tokens stored within a Marketplace contract. We also want to enable purchasing capabilities. And if you own the token, you should be able to set the token for sale and change the price of the token.
We will want to change our TokenData.js file to support all this, so open that up. Replace everything in that file with this:

We’re hard-coding some values here, so in a real app be sure to think about how you would dynamically get info like account addresses. You’ll also notice that in the checkMarketplace function we’ve wrapped everything in a try/catch. This is because the fcl.send function will throw when there are no NFTs listed for sale.
If you start your frontend app by changing into the frontend directory and running npm start, you should see in the console “NO NFTs FOR SALE”.
Let’s fix that!
For the sake of brevity, we are going to list our minted NFT for sale via the Flow CLI tool. However, you could extend this tutorial to do so from the UI. In your root pinata-party project, and inside the transactions folder, create a file called ListTokenForSale.cdc. Inside that file, add the following:

In this transaction, we are importing all three of the contracts we created. We need the the PinnieToken receiver capability since we are accepting payment in PinnieTokens. We also need to get access to the createSaleCollection function on the MarketplaceContract. Then, we need to reference the NFT we want to put up for sale. We withdraw that NFT, we list it for sale for 10.0 PinnieTokens, and we save it into the NFTSale storage path.
If you run the following command, you should successfully be able to list the NFT your minted earlier.
flow transactions execute –code transactions/ListTokenForSale.cdc
Now, go back to your React App page and refresh. In the console, you should see something like this:

This is an array of tokenIDs for the account address specified that are listed for sale. That means, we know what IDs to look up and fetch metadata for. In our simple example, there is only one token listed and it is the one and only token we created, so its tokenID is 1.
Before we add code to our React App, add the following import to the top of the TokenData.js file:
import * as t from “@onflow/types”
This allows us to pass in arguments to the scripts we send using fcl.
Ok, now we can take our array of tokenIDs and make use of some of the code we previously had to fetch token metadata. Inside the TokenData.js file and within the checkMarketplace function, add this after the decoded variable:

If you look in the console, you should now see an array of metadata associated specifically with the tokens we have for sale. The last thing we need to do before we can render anything is find out the prices for our listed tokens.
Right below the decodedMetadata variable and before the marketplaceMetadata.push(decodedMetadata) function, add the following:

We are getting the price for each NFT that has been listed, and when we receive the price back, we add it to the token metadata before pushing that metadata into the marketplaceMetadata array.
Now in your console, you should see something like this:

This is great! We can now render our listed tokens and show the price. Let’s do that now.
Under the console.log statement that shows the marketplaceMetadata array, add the following:
setTokensToSell(marketplaceMetadata)
You will need to also add the following right below the start of the TokenData main function declaration:
const TokenData = () => {
const [tokensToSell, setTokensToSell] = useState([])
}
With these things in place, you can render your marketplace. In the return statement, add the following:

If you’re using my styling, this is what I added to my App.css file:
.listing {
max-width: 30%;
padding: 50px;
margin: 2.5%;
box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23);
}
Your app should now look something like this:

The last thing we need to do is connect that Buy Now button and allow someone who is not the NFT owner to purchase the NFT.
Buying the NFT
Normally, you would need to have wallet discovery and transaction handling happen through a remote discovery node endpoint. We actually set this up in our React app in part two of this series. However, we are working with a local Flow emulator. Because of that, we need to run a local dev wallet, and then we need to update our React app’s environment variables.
Let’s get this set up. First, clone the local dev wallet. From the root of your pinata-party project run:
git clone [email protected]:onflow/fcl-dev-wallet.git
When that’s done, change into the folder:
cd fcl-dev-wallet
Now, we need to copy the sample env file and create our local env file that the dev wallet will use:
cp .env.example .env.local
Install dependencies:
npm install
Ok, when that is done, open up the .env.local file. You’ll see it references an account and a private key. Earlier, we created a new account that would be buying the NFT from the marketplace. Change the account in the .env.local file to match that new account you created. Change the private key as well and public keys as well. For the FLOW_ACCOUNT_KEY_ID environment variable, change this to 1. The emulator-account is key 0.
Now, you can run npm run dev to start the wallet server.
Back in the frontend directory of the project, find the .env file, and let’s update REACT_APP_WALLET_DISCOVERY to point to http://localhost:3000/fcl/authz. After doing so, you’ll need to restart the React app.
The next step is to wire the frontend Buy Now button to actually send a transaction to purchase the token. Open up the TokenData.js file, and let’s create a buyToken function like this:

Now, we just need to add an onClick handler for our Buy Now button. This is as simple as updating the button to look like this:
buyToken(1)} className=”btn-primary”>Buy Now
We are hard-coding the tokenID here, but you could easily fetch that from our early scripts we executed.
Now, when you go to your React app and click the Buy Now, button, you should see a screen like this:

The fcl-dev-wallet, as it says in the header is in an alpha state, so the truth is, the execution of the transaction may or may not end up working. But getting this far illustrates that your app does work and the fcl library does work.
Conclusion
This has been an especially long post in a series of long posts, but I hope they help illustrate how to combine the power of IPFS and Flow to create NFTs that are backed by verifiable identifiers.
If you have trouble with this tutorial or any of the others, I highly recommend experimenting with the Flow Playground. It’s really phenomenal.

You may also want to bypass the emulator testing and after working in the Playground start testing on Testnet. No matter what you do, I hope you’ve come away armed with more knowledge of how we can propel the NFT marketplace space forward. If you’d like to access the full source code from all these tutorials, the repository is open source and available here.

More Than 25k Share This...
Share on Reddit
Reddit
Share on Facebook
Facebook
Tweet about this on Twitter
Twitter
Share on LinkedIn
Linkedin