Getting Started with the Flow Blockchain
I recently got the opportunity to help build a Non-Fungible Token using the Flow Blockchain. This was a whole new blockchain for me! Getting up and running with a new technology is always a challenge, and I find that sometimes figuring out where to start is the hardest part. I learn by doing — getting my hands on the keyboard as soon as possible to interact with the new technology and reading the docs as I go to understand more deeply what my hands just did. So, this post follows that mindset and aims to get your hands on the keyboard to deploy a Cadence smart contract to a local emulator and interact with it as soon as possible.
Step 0: Installing Dependencies
Before we get started, let’s get our dependencies installed:
- RedSquirrelNFT example repo: Each step of this blog post has its own branch in the repository, in case you’d like to follow along step-by-step. Or, to follow along with the completed project, please refer to the
main
branch:git clone git@github.com:RedSquirrelTech/red-squirrel-nft.git
. - Flow CLI: The Flow CLI is a powerful tool that not only comes with a blockchain emulator but also allows for deploying contracts, creating account keys, and executing transactions.
- Go: This project uses Go to test the smart contract that we create, as there isn’t a testing framework for the smart contract language, Cadence, just yet.
Step 1: Scaffolding
The structure of this scaffolding is based on this blog post by Joshua Hannan, a smart contract engineer at Dapper Labs. It contains two main directories: cadence and lib:
cadence
: This directory is where the smart contract code lives, as well as scripts to interact with those contracts. You’ll note that there are two contracts already in thestandard
directory — these are standard Flow contracts that ourRedSquirrelNFT
contract will depend on.lib
: This is where we can write any code that wraps the interactions with the smart contract, using one of the Flow SDKs. This directory is also where we add tests to exercise the functionality of the smart contract.
Step 2: Creating a smart contract
Cadence, Flow’s smart contract language, is resource-oriented. In this context, a resource is a data structure that has special rules about its ownership and access, including being able to exist in only one place at a time. These rules are enforced by the language itself.
The intricate details of Cadence and writing a smart contract is out of scope for this blog post, but here we’ll walk through some of the main resources that make up our RedSquirrelNFT
smart contract. I also recommend reading Flow’s Non-Fungible Tokens tutorial which will walk you through the specifics of a basic smart contract using the Flow Playground (instead of deploying to an emulator).
NFT Resource
The NFT
resource is the fundamental object that we’ll be working with in the RedSquirrelNFT
contract. This is where we store the name, description, and link to the image that makes up the RedSquirrelNFT
. The NFT
resource implements two interfaces:
NonFungibleToken.INFT
which requires that ourNFT
resource has anid
.MetadataViews.Resolver
which requires that ourNFT
has a way to display its metadata that conforms with the metadata standard. TheMetadataViews.Resolver
interface allows us to include a “view resolver” for either anHTTPFile
, aIPFSFile
, or both — our contract exposes aIPFSFile
resolver.
Implementing both interfaces is highly recommended so that your NFT can be treated like all of the other NFTs on the Flow blockchain, which will set you up well for future compatibility in the ecosystem.
Collection Resource
The Collection
resource is essentially a wrapper around a dictionary that is made to specifically store our RedSquirrelNFTs
, while also allowing us to control what functions public users are able to access. The collection resource implements several interfaces from theNonFungibleToken
and MetadataViews
standards — these interfaces define functions that allow the owner of the collection to move their NFTs to and from the collection, and to share a reference to their collection for public visibility of the NFTs’ ids.
We also define our own interface to combine all of the public functions we’d like to expose, and include a borrowRedSquirrelNFT
function, so that public users are able to borrow a RedSquirrelNFT
reference specifically. This allows public users to access the RedSquirrelNFT
's metadata. If we only included the borrowNFT
function, the NFTs’ id
would be exposed but public users would miss out on all of that rich metadata because that isn’t included in the NonFungibleToken.INFT
interface.
NFTMinter Resource
We also include a NFTMinter
resource, which is only accessible to the owner of the RedSquirrelNFT
contract — so in this case you! The NFTMinter
resource is created and added to the contract’s account storage when the contract is initialized. This is the only way that we have allowed a minter to be created, so we can be sure that no one else will be able to get access to the minter, and create new RedSquirrelNFT
s without our consent.
Step 3: Deploying to the emulator
Before starting up the emulator, we’ll need to initialize the new Flow project. In a terminal window, from the root of the project, run flow init
. This will generate a new flow.json
file that includes configuration for connecting to the emulator network. The flow.json
file includes an emulator-account
address and private key. The address for the emulator service account is f8d6e0586b0a20c7 — this is the account that will sign all of our transactions to our emulator by default. My team decided that since this private key was used for local development, on an emulator whose state is wiped clean on each restart we felt confident checking this file into source control. But when generating private keys for testnet and mainnet, please use caution and do not check those into source control.
Next, we’ll need to include the contracts in the flow.json
file, so that they can be deployed. We add each contract name and the path to its source code in the empty contract
object:
"contracts": {
"NonFungibleToken":
"./cadence/contracts/standard/NonFungibleToken.cdc",
"MetadataViews":
"./cadence/contracts/standard/MetadataViews.cdc",
"RedSquirrelNFT": "./cadence/contracts/RedSquirrelNFT.cdc"
}
Then we’ll define the deployments specifying which network and account the contracts should be deployed to. The following is specifying that all three contracts (NonFungibleToken
, MetadataViews
and RedSquirrelNFT
) will be deployed to our emulator account, on the emulator network.
"deployments": {
"emulator": {
"emulator-account":
["NonFungibleToken", "MetadataViews", "RedSquirrelNFT"]
}
}
- In a terminal window, from the root of the project, start up the Flow emulator:
flow emulator
. - In another terminal window, deploy the contracts that we’ve configured in
flow.json
:flow deploy
.
If the deployment succeeded, you should see an output similar to this:
Deploying 3 contracts for accounts: emulator-accountNonFungibleToken -> 0xf8d6e0586b0a20c7 (721c3c7c05192b53c0e53f614d2d8b63457c5f48d19a3bbb6007a42ac3a100ff)MetadataViews -> 0xf8d6e0586b0a20c7 (4b4e5dd091f9c1a7ea6dac16012076ef6251618141b511490cffe6eeb96e007d)RedSquirrelNFT -> 0xf8d6e0586b0a20c7 (96374bf0f02c07a456a1df47481a03acb7fc9302cbf277bee580a2418ffed094)✨ All contracts deployed successfully
Step 4: Interacting with the contract
Now that we have our smart contract deployed to our emulator, it’s time to play with it! There are three ways that we’re going to interact with our contract: first, we’ll set up our emulator service account to receive RedSquirrelNFT
s, then we’ll mint a new RedSquirrelNFT
, and finally, we’ll get the metadata of the RedSquirrelNFT
we’ve just minted.
Setting up the account
Before we can mint a RedSquirrelNFT
, let’s create an empty collection in our account to hold future NFTs. We can use the Flow CLI tool to run a transaction that will create an empty collection in our emulator account’s storage. Make sure that the emulator is running, and in another terminal window run:
flow transactions send ./cadence/transactions/set_up_account.cdc
The transaction code that we’re executing from set_up_account.cdc
is written in Cadence, and has three main steps:
- Creates an empty collection.
- Saves the collection in the signing account’s storage (i.e. our emulator service account’s storage).
- Creates a publicly accessible link to the collection that’s held in storage.
Minting a new NFT
Now that we have a place to store the RedSquirrelNFT
s, let’s start minting! We again use the Flow CLI tool to send a transaction. This time we’ll need to pass in several arguments to the transaction. The transaction call will look like this:
flow transactions send ./cadence/transactions/mint.cdc <Owner Account Address> <NFT Name> <NFT Description> <NFT Ipfs CID>
And with arguments added:
flow transactions send ./cadence/transactions/mint.cdc 0xf8d6e0586b0a20c7 "Mr. Fluffy Ears" "A red squirrel with very fluffy ears enjoying an acorn." "Qmd6ENNCAJs7coQZFrHpXGZzFNiU83V2GwFcMFMYTXHMx1"
The transaction code we’re executing from mint.cdc
also has several steps:
- Gets the minter and assigns it to
self.minter
for use in theexecute
section. - Gets the recipient’s account.
- Borrows a reference to the recipient’s empty collection. We created this ability to borrow the reference to the collection in the 3rd step of the
set_up_account
transaction. - Mints the new
RedSquirrelNFT
into the recipient’s collection.
Get the NFT’s metadata
flow scripts execute ./cadence/scripts/get_red_squirrel.cdc <Owner Account Address> <RedSquirrelNFT ID>
Since we’ve only minted one NFT so far and the ids start at 0, we can use 0
as the id argument. And our emulator service account address is again used as the owner address:
flow scripts execute ./cadence/scripts/get_red_squirrel.cdc 0xf8d6e0586b0a20c7 0
Since getting metadata is a publicly available action, this code can be run as a script instead of a transaction. The get_red_squirrel.cdc
script:
- Gets the owner’s account.
- Borrows a reference to the account’s
RedSquirrelNFT
collection. - Borrows the specific NFT from that collection.
- Resolves the view of that NFT.
- Returns a custom NFT struct to include all of the data that we’d like to return from the script.
And here’s the result, edited to make the formatting a bit easier to read:
Result: s.70fee1e8869bd90e136ce629f0171aa8992f13a3b454929b631652e5266ac0aa.NFT(
redSquirrelID: 0,
resourceID: 25,
owner: 0xf8d6e0586b0a20c7,
type: "A.f8d6e0586b0a20c7.RedSquirrelNFT.NFT",
name: "Mr. Fluffy Ears",
description: "A red squirrel with very fluffy ears enjoying an acorn.",
thumbnail: "ipfs://Qmd6ENNCAJs7coQZFrHpXGZzFNiU83V2GwFcMFMYTXHMx1"
)
You’ll note that because we’ve implemented an IPFSFile
display as part of the MetadataView
interface, the thumbnail that is displayed has been formatted as an IPFS link. And to view the IPFS thumbnail in the browser visit infura-ipfs.io. Digging into how IPFS works definitely warrants its own blog post, so for now, we’ll leave it at that! 😉
Step 5: Testing
Cadence currently does not have its own testing library, and the suggestion is to use an SDK from the language of your choice to write tests that exercise key components of the smart contract. The RedSquirrelNFT repository uses the Go SDK and has those tests in a lib/go/cadence_test
directory.
These tests are focused on the main interactions we expect to have with the contract: setting up the account, minting a new NFT, getting the total supply of NFTs, and getting the metadata of a specific NFT.
To run them, navigate to the lib/go/cadence_test
directory and run: go test -v
.
Next Steps
The next step after ensuring that your smart contract works as expected on the emulator is to deploy the contract to testnet and eventually mainnet! Flow includes some helpful documentation to walk you through that process. As of April 2022, a security review of all smart contracts is required before deploying to mainnet to ensure that the ecosystem is safe and secure, but there are plans to open up unrestricted deployments in the near future.
In addition to having quite a bit of solid documentation on Flow’s website, I also found reviewing Dapper Lab’s NBA Top Shots contract and their example smart contracts very helpful as well. RedSquirrelNFT is based on ExampleNFT and the Non-Fungible Token that I worked on with my client was based on KittyItems.
Oh and don’t forget to join their discord!