In this 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. This page requires you to execute a series of transactions to setup your accounts to complete the Marketplace tutorial. The next page contains the main content of the tutorial.
When you are done with the tutorial, check out the NFTStorefront repo for an example of a production ready marketplace that you can use right now on testnet or mainnet!
Open the starter code for this tutorial in the Flow Playground:
https://play.onflow.org/49ec2856-1258-4675-bac3-850b4bae1929
The tutorial will be asking you to take various actions to interact with this code.
If you have already completed the Marketplace tutorial, please move on to Composable Resources: Kitty Hats.
This guide will help you quickly get the playground to the state you need to complete the Marketplace tutorial. The marketplace tutorial uses the Fungible Token and Non-Fungible token contracts to allow users to buy and sell NFTs with fungible tokens.
The state of the accounts is the same as if you had completed the Fungible Token and Non-Fungible Token tutorials in the same playground session. Having your playground in this state is necessary to follow the Composable Smart Contracts: Marketplace tutorial.
- Open account
0x01
. Make sure the Fungible Token definitions inExampleToken.cdc
from the fungible token tutorial are in this account. - Deploy the ExampleToken code to account
0x01
. - Switch to account
0x02
by selecting account0x02
from the account selection menu. - Make sure you have the NFT definitions in
ExampleNFT.cdc
from the Non-fungible token tutorial in account0x02
. - Deploy the NFT code to account
0x02
. - Run the transaction in Transaction 1. This is the
SetupAccount1Transaction.cdc
file. Use account0x01
as the only signer to set up account0x01
's storage.
1// SetupAccount1Transaction.cdc23import ExampleToken from 0x014import ExampleNFT from 0x0256// This transaction sets up account 0x01 for the marketplace tutorial7// by publishing a Vault reference and creating an empty NFT Collection.8transaction {9prepare(acct: AuthAccount) {10// Create a public Receiver capability to the Vault11acct.link<&ExampleToken.Vault{ExampleToken.Receiver, ExampleToken.Balance}>12(/public/CadenceFungibleTokenTutorialReceiver, target: /storage/CadenceFungibleTokenTutorialVault)1314log("Created Vault references")1516// store an empty NFT Collection in account storage17acct.save<@ExampleNFT.Collection>(<-ExampleNFT.createEmptyCollection(), to: /storage/nftTutorialCollection)1819// publish a capability to the Collection in storage20acct.link<&{ExampleNFT.NFTReceiver}>(ExampleNFT.CollectionPublicPath, target: ExampleNFT.CollectionStoragePath)2122log("Created a new empty collection and published a reference")23}24}
- Run the transaction in Transaction 2. This is the
SetupAccount2Transaction.cdc
file. Use account0x02
as the only signer to set up account0x02
's storage.
1// SetupAccount2Transaction.cdc23import ExampleToken from 0x014import ExampleNFT from 0x0256// This transaction adds an empty Vault to account 0x027// and mints an NFT with id=1 that is deposited into8// the NFT collection on account 0x01.9transaction {1011// Private reference to this account's minter resource12let minterRef: &ExampleNFT.NFTMinter1314prepare(acct: AuthAccount) {15// create a new vault instance with an initial balance of 3016let vaultA <- ExampleToken.createEmptyVault()1718// Store the vault in the account storage19acct.save<@ExampleToken.Vault>(<-vaultA, to: /storage/CadenceFungibleTokenTutorialVault)2021// Create a public Receiver capability to the Vault22let ReceiverRef = acct.link<&ExampleToken.Vault{ExampleToken.Receiver, ExampleToken.Balance}>(/public/CadenceFungibleTokenTutorialReceiver, target: /storage/CadenceFungibleTokenTutorialVault)2324log("Created a Vault and published a reference")2526// Borrow a reference for the NFTMinter in storage27self.minterRef = acct.borrow<&ExampleNFT.NFTMinter>(from: ExampleNFT.MinterStoragePath)28?? panic("Could not borrow owner's NFT minter reference")29}30execute {31// Get the recipient's public account object32let recipient = getAccount(0x01)3334// Get the Collection reference for the receiver35// getting the public capability and borrowing a reference from it36let receiverRef = recipient.getCapability(ExampleNFT.CollectionPublicPath)37.borrow<&{ExampleNFT.NFTReceiver}>()38?? panic("Could not borrow nft receiver reference")3940// Mint an NFT and deposit it into account 0x01's collection41receiverRef.deposit(token: <-self.minterRef.mintNFT())4243log("New NFT minted for account 1")44}45}
- Run the transaction in Transaction 3. This is the
SetupAccount1TransactionMinting.cdc
file. Use account0x01
as the only signer to mint fungible tokens for account 1 and 2.
1// SetupAccount1TransactionMinting.cdc23import ExampleToken from 0x014import ExampleNFT from 0x0256// This transaction mints tokens for both accounts using7// the minter stored on account 0x01.8transaction {910// Public Vault Receiver References for both accounts11let acct1Capability: Capability<&AnyResource{ExampleToken.Receiver}>12let acct2Capability: Capability<&AnyResource{ExampleToken.Receiver}>1314// Private minter references for this account to mint tokens15let minterRef: &ExampleToken.VaultMinter1617prepare(acct: AuthAccount) {18// Get the public object for account 0x0219let account2 = getAccount(0x02)2021// Retrieve public Vault Receiver references for both accounts22self.acct1Capability = acct.getCapability<&AnyResource{ExampleToken.Receiver}>(/public/CadenceFungibleTokenTutorialReceiver)23self.acct2Capability = account2.getCapability<&AnyResource{ExampleToken.Receiver}>(/public/CadenceFungibleTokenTutorialReceiver)2425// Get the stored Minter reference for account 0x0126self.minterRef = acct.borrow<&ExampleToken.VaultMinter>(from: /storage/CadenceFungibleTokenTutorialMinter)27?? panic("Could not borrow owner's vault minter reference")28}2930execute {31// Mint tokens for both accounts32self.minterRef.mintTokens(amount: 20.0, recipient: self.acct2Capability)33self.minterRef.mintTokens(amount: 10.0, recipient: self.acct1Capability)3435log("Minted new fungible tokens for account 1 and 2")36}37}
- Run the script
CheckSetupScript.cdc
file in Script 1 to ensure everything is set up.
1// CheckSetupScript.cdc23import ExampleToken from 0x014import ExampleNFT from 0x0256// This script checks that the accounts are set up correctly for the marketplace tutorial.7//8// Account 0x01: Vault Balance = 40, NFT.id = 19// Account 0x02: Vault Balance = 20, No NFTs10pub fun main() {11// Get the accounts' public account objects12let acct1 = getAccount(0x01)13let acct2 = getAccount(0x02)1415// Get references to the account's receivers16// by getting their public capability17// and borrowing a reference from the capability18let acct1ReceiverRef = acct1.getCapability(/public/CadenceFungibleTokenTutorialReceiver)19.borrow<&ExampleToken.Vault{ExampleToken.Balance}>()20?? panic("Could not borrow acct1 vault reference")2122let acct2ReceiverRef = acct2.getCapability(/public/CadenceFungibleTokenTutorialReceiver)23.borrow<&ExampleToken.Vault{ExampleToken.Balance}>()24?? panic("Could not borrow acct2 vault reference")2526// Log the Vault balance of both accounts and ensure they are27// the correct numbers.28// Account 0x01 should have 40.29// Account 0x02 should have 20.30log("Account 1 Balance")31log(acct1ReceiverRef.balance)32log("Account 2 Balance")33log(acct2ReceiverRef.balance)3435// verify that the balances are correct36if acct1ReceiverRef.balance != 40.0 || acct2ReceiverRef.balance != 20.0 {37panic("Wrong balances!")38}3940// Find the public Receiver capability for their Collections41let acct1Capability = acct1.getCapability(ExampleNFT.CollectionPublicPath)42let acct2Capability = acct2.getCapability(ExampleNFT.CollectionPublicPath)4344// borrow references from the capabilities45let nft1Ref = acct1Capability.borrow<&{ExampleNFT.NFTReceiver}>()46?? panic("Could not borrow acct1 nft collection reference")4748let nft2Ref = acct2Capability.borrow<&{ExampleNFT.NFTReceiver}>()49?? panic("Could not borrow acct2 nft collection reference")5051// Print both collections as arrays of IDs52log("Account 1 NFTs")53log(nft1Ref.getIDs())5455log("Account 2 NFTs")56log(nft2Ref.getIDs())5758// verify that the collections are correct59if nft1Ref.getIDs()[0] != 1 || nft2Ref.getIDs().length != 0 {60panic("Wrong Collections!")61}62}
- The script should not panic and you should see something like this output
1"Account 1 Vault Balance"2403"Account 2 Vault Balance"4205"Account 1 NFTs"6[1]7"Account 2 NFTs"8[]
With your playground now in the correct state, you're ready to continue with the next tutorial.
You do not need to open a new playground session for the marketplace tutorial. You can just continue using this one.