Skip to main content

7. Marketplace Setup

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!


tip

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.


  1. Open account 0x01. Make sure the Fungible Token definitions in ExampleToken.cdc from the fungible token tutorial are in this account.
  2. Deploy the ExampleToken code to account 0x01.
  3. Switch to the ExampleNFT contract (Contract 2)
  4. Make sure you have the NFT definitions in ExampleNFT.cdc from the Non-fungible token tutorial in account 0x02.
  5. Deploy the NFT code to account 0x02 by selecting it as the deploying signer.
  6. Run the transaction in Transaction 1. This is the SetupAccount1Transaction.cdc file. Use account 0x01 as the only signer to set up account 0x01's storage.
SetupAccount1Transaction.cdc

_24
// SetupAccount1Transaction.cdc
_24
_24
import ExampleToken from 0x01
_24
import ExampleNFT from 0x02
_24
_24
// This transaction sets up account 0x01 for the marketplace tutorial
_24
// by publishing a Vault reference and creating an empty NFT Collection.
_24
transaction {
_24
prepare(acct: AuthAccount) {
_24
// Create a public Receiver capability to the Vault
_24
acct.link<&ExampleToken.Vault{ExampleToken.Receiver, ExampleToken.Balance}>
_24
(/public/CadenceFungibleTokenTutorialReceiver, target: /storage/CadenceFungibleTokenTutorialVault)
_24
_24
log("Created Vault references")
_24
_24
// store an empty NFT Collection in account storage
_24
acct.save<@ExampleNFT.Collection>(<-ExampleNFT.createEmptyCollection(), to: /storage/nftTutorialCollection)
_24
_24
// publish a capability to the Collection in storage
_24
acct.link<&{ExampleNFT.NFTReceiver}>(ExampleNFT.CollectionPublicPath, target: ExampleNFT.CollectionStoragePath)
_24
_24
log("Created a new empty collection and published a reference")
_24
}
_24
}

  1. Run the transaction in Transaction 2. This is the SetupAccount2Transaction.cdc file. Use account 0x02 as the only signer to set up account 0x02's storage.
SetupAccount2Transaction.cdc

_45
// SetupAccount2Transaction.cdc
_45
_45
import ExampleToken from 0x01
_45
import ExampleNFT from 0x02
_45
_45
// This transaction adds an empty Vault to account 0x02
_45
// and mints an NFT with id=1 that is deposited into
_45
// the NFT collection on account 0x01.
_45
transaction {
_45
_45
// Private reference to this account's minter resource
_45
let minterRef: &ExampleNFT.NFTMinter
_45
_45
prepare(acct: AuthAccount) {
_45
// create a new vault instance with an initial balance of 30
_45
let vaultA <- ExampleToken.createEmptyVault()
_45
_45
// Store the vault in the account storage
_45
acct.save<@ExampleToken.Vault>(<-vaultA, to: /storage/CadenceFungibleTokenTutorialVault)
_45
_45
// Create a public Receiver capability to the Vault
_45
let ReceiverRef = acct.link<&ExampleToken.Vault{ExampleToken.Receiver, ExampleToken.Balance}>(/public/CadenceFungibleTokenTutorialReceiver, target: /storage/CadenceFungibleTokenTutorialVault)
_45
_45
log("Created a Vault and published a reference")
_45
_45
// Borrow a reference for the NFTMinter in storage
_45
self.minterRef = acct.borrow<&ExampleNFT.NFTMinter>(from: ExampleNFT.MinterStoragePath)
_45
?? panic("Could not borrow owner's NFT minter reference")
_45
}
_45
execute {
_45
// Get the recipient's public account object
_45
let recipient = getAccount(0x01)
_45
_45
// Get the Collection reference for the receiver
_45
// getting the public capability and borrowing a reference from it
_45
let receiverRef = recipient.getCapability(ExampleNFT.CollectionPublicPath)
_45
.borrow<&{ExampleNFT.NFTReceiver}>()
_45
?? panic("Could not borrow nft receiver reference")
_45
_45
// Mint an NFT and deposit it into account 0x01's collection
_45
receiverRef.deposit(token: <-self.minterRef.mintNFT())
_45
_45
log("New NFT minted for account 1")
_45
}
_45
}

  1. Run the transaction in Transaction 3. This is the SetupAccount1TransactionMinting.cdc file. Use account 0x01 as the only signer to mint fungible tokens for account 1 and 2.
SetupAccount1TransactionMinting.cdc

_37
// SetupAccount1TransactionMinting.cdc
_37
_37
import ExampleToken from 0x01
_37
import ExampleNFT from 0x02
_37
_37
// This transaction mints tokens for both accounts using
_37
// the minter stored on account 0x01.
_37
transaction {
_37
_37
// Public Vault Receiver References for both accounts
_37
let acct1Capability: Capability<&AnyResource{ExampleToken.Receiver}>
_37
let acct2Capability: Capability<&AnyResource{ExampleToken.Receiver}>
_37
_37
// Private minter references for this account to mint tokens
_37
let minterRef: &ExampleToken.VaultMinter
_37
_37
prepare(acct: AuthAccount) {
_37
// Get the public object for account 0x02
_37
let account2 = getAccount(0x02)
_37
_37
// Retrieve public Vault Receiver references for both accounts
_37
self.acct1Capability = acct.getCapability<&AnyResource{ExampleToken.Receiver}>(/public/CadenceFungibleTokenTutorialReceiver)
_37
self.acct2Capability = account2.getCapability<&AnyResource{ExampleToken.Receiver}>(/public/CadenceFungibleTokenTutorialReceiver)
_37
_37
// Get the stored Minter reference for account 0x01
_37
self.minterRef = acct.borrow<&ExampleToken.VaultMinter>(from: /storage/CadenceFungibleTokenTutorialMinter)
_37
?? panic("Could not borrow owner's vault minter reference")
_37
}
_37
_37
execute {
_37
// Mint tokens for both accounts
_37
self.minterRef.mintTokens(amount: 20.0, recipient: self.acct2Capability)
_37
self.minterRef.mintTokens(amount: 10.0, recipient: self.acct1Capability)
_37
_37
log("Minted new fungible tokens for account 1 and 2")
_37
}
_37
}

  1. Run the script CheckSetupScript.cdc file in Script 1 to ensure everything is set up.
CheckSetupScript.cdc

_62
// CheckSetupScript.cdc
_62
_62
import ExampleToken from 0x01
_62
import ExampleNFT from 0x02
_62
_62
// This script checks that the accounts are set up correctly for the marketplace tutorial.
_62
//
_62
// Account 0x01: Vault Balance = 40, NFT.id = 1
_62
// Account 0x02: Vault Balance = 20, No NFTs
_62
pub fun main() {
_62
// Get the accounts' public account objects
_62
let acct1 = getAccount(0x01)
_62
let acct2 = getAccount(0x02)
_62
_62
// Get references to the account's receivers
_62
// by getting their public capability
_62
// and borrowing a reference from the capability
_62
let acct1ReceiverRef = acct1.getCapability(/public/CadenceFungibleTokenTutorialReceiver)
_62
.borrow<&ExampleToken.Vault{ExampleToken.Balance}>()
_62
?? panic("Could not borrow acct1 vault reference")
_62
_62
let acct2ReceiverRef = acct2.getCapability(/public/CadenceFungibleTokenTutorialReceiver)
_62
.borrow<&ExampleToken.Vault{ExampleToken.Balance}>()
_62
?? panic("Could not borrow acct2 vault reference")
_62
_62
// Log the Vault balance of both accounts and ensure they are
_62
// the correct numbers.
_62
// Account 0x01 should have 40.
_62
// Account 0x02 should have 20.
_62
log("Account 1 Balance")
_62
log(acct1ReceiverRef.balance)
_62
log("Account 2 Balance")
_62
log(acct2ReceiverRef.balance)
_62
_62
// verify that the balances are correct
_62
if acct1ReceiverRef.balance != 40.0 || acct2ReceiverRef.balance != 20.0 {
_62
panic("Wrong balances!")
_62
}
_62
_62
// Find the public Receiver capability for their Collections
_62
let acct1Capability = acct1.getCapability(ExampleNFT.CollectionPublicPath)
_62
let acct2Capability = acct2.getCapability(ExampleNFT.CollectionPublicPath)
_62
_62
// borrow references from the capabilities
_62
let nft1Ref = acct1Capability.borrow<&{ExampleNFT.NFTReceiver}>()
_62
?? panic("Could not borrow acct1 nft collection reference")
_62
_62
let nft2Ref = acct2Capability.borrow<&{ExampleNFT.NFTReceiver}>()
_62
?? panic("Could not borrow acct2 nft collection reference")
_62
_62
// Print both collections as arrays of IDs
_62
log("Account 1 NFTs")
_62
log(nft1Ref.getIDs())
_62
_62
log("Account 2 NFTs")
_62
log(nft2Ref.getIDs())
_62
_62
// verify that the collections are correct
_62
if nft1Ref.getIDs()[0] != 1 || nft2Ref.getIDs().length != 0 {
_62
panic("Wrong Collections!")
_62
}
_62
}

  1. The script should not panic and you should see something like this output

_10
"Account 1 Balance"
_10
40.00000000
_10
"Account 2 Balance"
_10
20.00000000
_10
"Account 1 NFTs"
_10
[1]
_10
"Account 2 NFTs"
_10
[]


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.