7. Marketplace Setup
In the Marketplace Tutorial, we're going to create a marketplace that uses both the fungible and non-fungible token (NFTs) contracts that we have learned about in previous tutorials. First, you'll execute a series of transactions to set up the accounts that you'll need to complete the marketplace tutorial. You'll build the marketplace itself in the next tutorial.
If you're farther along with your Cadence learning journey and found this page looking for a production-ready marketplace, check out the NFTStorefront repo!
Objectives
In this tutorial, you'll simply execute transactions that you've already written and validate that setup is complete. It's only necessary because the playground is not actually a blockchain, so the state is transient.
Getting Started
Your goal for this exercise is to set up the ephemeral playground into the state the blockchain would be in when you begin building a marketplace. It's also a great chance to practice some of what you've learned already. You'll need to:
- Deploy the NFT contract on account
0x06
- Deploy the fungible token contract on account
0x07
- Set up account
0x08
and0x09
to handle NFTs and tokens compatible with the simplified contracts you've built - Give fungible tokens to
0x08
- Give an NFT to
0x09
To start, you'll need to deploy some copies of the contracts you've built in the previous tutorials, and call transactions you've already built. For your convenience, they've been provided in the starter playground.
- Open the
ExampleToken
contract. This is the same contract from the fungible token tutorial. - Deploy the
ExampleToken
code to account0x06
. - Switch to the
IntermediateNFT
contract. - Deploy the NFT code to account
0x07
by selecting it as the deploying signer.
Account Setup Transactions
Next, you'll need to execute transactions to set up accounts 0x08
and 0x09
to be able to work with the contracts for the marketplace. You've already built these transactions in previous exercises.
Remember: On Flow, accounts must maintain a balance of $FLOW proportional to the amount of storage the account is using. Furthermore, placing something in the storage of an account requires that the receiving account has a capability that can accept the asset type. As a result, accounts can not accept arbitrary data (including tokens!) from random contracts without first executing a transaction to allow it.
This might seem like a burden, but it's great!! Thanks to this feature, one of the most common causes of burning assets is impossible on Flow. You can not send property to a random address - only those that know how to receive it!
NFT Setup
Open the NFT Setup
transaction.
_16import IntermediateNFT from 0x07_16_16transaction() {_16 prepare(acct: auth(SaveValue, Capabilities) &Account) {_16 // Create an empty NFT collection_16 acct.storage.save(<-IntermediateNFT.createEmptyCollection(), to: IntermediateNFT.CollectionStoragePath)_16_16 // Create a public capability for the Collection_16 let cap = acct.capabilities.storage.issue<&IntermediateNFT.Collection>(IntermediateNFT.CollectionStoragePath)_16 acct.capabilities.publish(cap, at: IntermediateNFT.CollectionPublicPath)_16 }_16_16 execute {_16 log("Empty NFT Collection Created")_16 }_16}
This transaction will:
prepare
an account reference with permissions to create and save capabilities- Call
createEmptyCollection()
from theIntermediateNFT
contract to create a collection - Create and publish public capabilities for the NFT collection
Run the transaction using 0x07
as the signer, then run it again for 0x08
.
Fungible Token Setup
Open the Fungible Token Setup
transaction.
_19import ExampleToken from 0x06_19_19transaction() {_19 prepare(acct: auth(SaveValue, Capabilities) &Account) {_19 // Create a vault and save it in account storage_19 acct.storage.save(<-ExampleToken.createEmptyVault(), to: ExampleToken.VaultStoragePath)_19_19 // Create and publish a receiver for the fungible tokens_19 let cap = acct.capabilities.storage.issue<&ExampleToken.Vault>(_19 ExampleToken.VaultStoragePath_19 )_19_19 acct.capabilities.publish(cap, at: ExampleToken.VaultPublicPath)_19 }_19_19 execute {_19 log("Vault Created")_19 }_19}
This transaction will:
- Instantiate a constant for and borrow a reference to the
ExampleToken
contract - Create and add an empty
ExampleToken
vault - Add the
Receiver
capability and publish it
Run the transaction using 0x07
as the signer, then run it again for 0x08
.
Mint NFTs
Now that you've set up both accounts to be able to receive NFTs, it's time to give account 0x08
an NFT to sell to 0x09
.
Reminder: The IntermediateNFT
contract allows anyone to freely mint NFTs. You wouldn't want this ability in production, but it is in here to streamline the tutorial.
You've already written a transaction to mint an NFT, so we've provided it here. You just need to call it.
_19import IntermediateNFT from 0x07_19_19transaction(description: String) {_19 let receiverRef: &IntermediateNFT.Collection_19_19 prepare(account: auth(BorrowValue) &Account) {_19 self.receiverRef = account.capabilities_19 .borrow<&IntermediateNFT.Collection>(IntermediateNFT.CollectionPublicPath)_19 ?? panic(IntermediateNFT.collectionNotConfiguredError(address: account.address))_19 }_19_19 execute {_19 let newNFT <- IntermediateNFT.mintNFT(description: description)_19_19 self.receiverRef.deposit(token: <-newNFT)_19_19 log("NFT Minted and deposited to minter's Collection")_19 }_19}
Mint a token with account 0x08
.
Mint Fungible Tokens
You've also set up both accounts to be able to receive non-fungible tokens from ExampleToken
.
Reminder: The ExampleToken
contract only allows the owner of the contract to mint NFTs.
You've already written a transaction to mint fungible tokens, so we've provided it here. You just need to call it.
_26import ExampleToken from 0x06_26_26transaction(recipient: Address, amount: UFix64) {_26 let mintingRef: &ExampleToken.VaultMinter_26 var receiver: Capability<&{ExampleToken.Receiver}>_26_26 prepare(signer: auth(BorrowValue) &Account) {_26 self.mintingRef = signer.storage.borrow<&ExampleToken.VaultMinter>(from: /storage/CadenceFungibleTokenTutorialMinter)_26 ?? panic(ExampleToken.vaultNotConfiguredError(address: recipient))_26_26 let recipient = getAccount(recipient)_26_26 // Consider further error handling if this fails_26 self.receiver = recipient.capabilities.get<&{ExampleToken.Receiver}>_26 (ExampleToken.VaultPublicPath)_26_26 }_26_26 execute {_26 // Mint tokens and deposit them into the recipient's Vault_26 self.mintingRef.mintTokens(amount: amount, recipient: self.receiver)_26_26 log("Tokens minted and deposited to account "_26 .concat(self.receiver.address.toString()))_26 }_26}
Call Mint Tokens
with account 0x06
to grant 40 tokens to 0x09
and 20 tokens to 0x08
Validate Setup
We've provided a script called Validate Setup
that you can use to make sure you've completed the setup correctly.
Run the Validate Setup
script and resolve any issues.
The script should not panic and you should see something like this output:
_10...64807.OwnerInfo(acct8Balance: 40.00000000, acct9Balance: 40.00000000, acct8IDs: [1], acct9IDs: [])
Conclusion
With your playground now in the correct state, you're ready to continue with the next tutorial.
Now that you have completed this tutorial, you able to:
- Set up accounts and deploy contracts required for a basic NFT marketplace on Flow.
- Configure account storage and capabilities for fungible and non-fungible tokens.
- Validate the correct setup of accounts and assets in preparation for marketplace operations.
You do not need to open a new playground session for the marketplace tutorial. You can just continue using this one.
Reference Solution
You are not saving time by skipping to the reference implementation. You'll learn much faster by doing the tutorials as presented!
Reference solutions are functional, but may not be optimal.