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!


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 account 0x02 by selecting account 0x02 from the account selection menu.
  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.
  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.
1
// SetupAccount1Transaction.cdc
2
3
import ExampleToken from 0x01
4
import ExampleNFT from 0x02
5
6
// This transaction sets up account 0x01 for the marketplace tutorial
7
// by publishing a Vault reference and creating an empty NFT Collection.
8
transaction {
9
prepare(acct: AuthAccount) {
10
// Create a public Receiver capability to the Vault
11
acct.link<&ExampleToken.Vault{ExampleToken.Receiver, ExampleToken.Balance}>
12
(/public/CadenceFungibleTokenTutorialReceiver, target: /storage/CadenceFungibleTokenTutorialVault)
13
14
log("Created Vault references")
15
16
// store an empty NFT Collection in account storage
17
acct.save<@ExampleNFT.Collection>(<-ExampleNFT.createEmptyCollection(), to: /storage/nftTutorialCollection)
18
19
// publish a capability to the Collection in storage
20
acct.link<&{ExampleNFT.NFTReceiver}>(ExampleNFT.CollectionPublicPath, target: ExampleNFT.CollectionStoragePath)
21
22
log("Created a new empty collection and published a reference")
23
}
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.
1
// SetupAccount2Transaction.cdc
2
3
import ExampleToken from 0x01
4
import ExampleNFT from 0x02
5
6
// This transaction adds an empty Vault to account 0x02
7
// and mints an NFT with id=1 that is deposited into
8
// the NFT collection on account 0x01.
9
transaction {
10
11
// Private reference to this account's minter resource
12
let minterRef: &ExampleNFT.NFTMinter
13
14
prepare(acct: AuthAccount) {
15
// create a new vault instance with an initial balance of 30
16
let vaultA <- ExampleToken.createEmptyVault()
17
18
// Store the vault in the account storage
19
acct.save<@ExampleToken.Vault>(<-vaultA, to: /storage/CadenceFungibleTokenTutorialVault)
20
21
// Create a public Receiver capability to the Vault
22
let ReceiverRef = acct.link<&ExampleToken.Vault{ExampleToken.Receiver, ExampleToken.Balance}>(/public/CadenceFungibleTokenTutorialReceiver, target: /storage/CadenceFungibleTokenTutorialVault)
23
24
log("Created a Vault and published a reference")
25
26
// Borrow a reference for the NFTMinter in storage
27
self.minterRef = acct.borrow<&ExampleNFT.NFTMinter>(from: ExampleNFT.MinterStoragePath)
28
?? panic("Could not borrow owner's NFT minter reference")
29
}
30
execute {
31
// Get the recipient's public account object
32
let recipient = getAccount(0x01)
33
34
// Get the Collection reference for the receiver
35
// getting the public capability and borrowing a reference from it
36
let receiverRef = recipient.getCapability(ExampleNFT.CollectionPublicPath)
37
.borrow<&{ExampleNFT.NFTReceiver}>()
38
?? panic("Could not borrow nft receiver reference")
39
40
// Mint an NFT and deposit it into account 0x01's collection
41
receiverRef.deposit(token: <-self.minterRef.mintNFT())
42
43
log("New NFT minted for account 1")
44
}
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.
1
// SetupAccount1TransactionMinting.cdc
2
3
import ExampleToken from 0x01
4
import ExampleNFT from 0x02
5
6
// This transaction mints tokens for both accounts using
7
// the minter stored on account 0x01.
8
transaction {
9
10
// Public Vault Receiver References for both accounts
11
let acct1Capability: Capability<&AnyResource{ExampleToken.Receiver}>
12
let acct2Capability: Capability<&AnyResource{ExampleToken.Receiver}>
13
14
// Private minter references for this account to mint tokens
15
let minterRef: &ExampleToken.VaultMinter
16
17
prepare(acct: AuthAccount) {
18
// Get the public object for account 0x02
19
let account2 = getAccount(0x02)
20
21
// Retrieve public Vault Receiver references for both accounts
22
self.acct1Capability = acct.getCapability<&AnyResource{ExampleToken.Receiver}>(/public/CadenceFungibleTokenTutorialReceiver)
23
self.acct2Capability = account2.getCapability<&AnyResource{ExampleToken.Receiver}>(/public/CadenceFungibleTokenTutorialReceiver)
24
25
// Get the stored Minter reference for account 0x01
26
self.minterRef = acct.borrow<&ExampleToken.VaultMinter>(from: /storage/CadenceFungibleTokenTutorialMinter)
27
?? panic("Could not borrow owner's vault minter reference")
28
}
29
30
execute {
31
// Mint tokens for both accounts
32
self.minterRef.mintTokens(amount: 20.0, recipient: self.acct2Capability)
33
self.minterRef.mintTokens(amount: 10.0, recipient: self.acct1Capability)
34
35
log("Minted new fungible tokens for account 1 and 2")
36
}
37
}
  1. Run the script CheckSetupScript.cdc file in Script 1 to ensure everything is set up.
1
// CheckSetupScript.cdc
2
3
import ExampleToken from 0x01
4
import ExampleNFT from 0x02
5
6
// This script checks that the accounts are set up correctly for the marketplace tutorial.
7
//
8
// Account 0x01: Vault Balance = 40, NFT.id = 1
9
// Account 0x02: Vault Balance = 20, No NFTs
10
pub fun main() {
11
// Get the accounts' public account objects
12
let acct1 = getAccount(0x01)
13
let acct2 = getAccount(0x02)
14
15
// Get references to the account's receivers
16
// by getting their public capability
17
// and borrowing a reference from the capability
18
let acct1ReceiverRef = acct1.getCapability(/public/CadenceFungibleTokenTutorialReceiver)
19
.borrow<&ExampleToken.Vault{ExampleToken.Balance}>()
20
?? panic("Could not borrow acct1 vault reference")
21
22
let acct2ReceiverRef = acct2.getCapability(/public/CadenceFungibleTokenTutorialReceiver)
23
.borrow<&ExampleToken.Vault{ExampleToken.Balance}>()
24
?? panic("Could not borrow acct2 vault reference")
25
26
// Log the Vault balance of both accounts and ensure they are
27
// the correct numbers.
28
// Account 0x01 should have 40.
29
// Account 0x02 should have 20.
30
log("Account 1 Balance")
31
log(acct1ReceiverRef.balance)
32
log("Account 2 Balance")
33
log(acct2ReceiverRef.balance)
34
35
// verify that the balances are correct
36
if acct1ReceiverRef.balance != 40.0 || acct2ReceiverRef.balance != 20.0 {
37
panic("Wrong balances!")
38
}
39
40
// Find the public Receiver capability for their Collections
41
let acct1Capability = acct1.getCapability(ExampleNFT.CollectionPublicPath)
42
let acct2Capability = acct2.getCapability(ExampleNFT.CollectionPublicPath)
43
44
// borrow references from the capabilities
45
let nft1Ref = acct1Capability.borrow<&{ExampleNFT.NFTReceiver}>()
46
?? panic("Could not borrow acct1 nft collection reference")
47
48
let nft2Ref = acct2Capability.borrow<&{ExampleNFT.NFTReceiver}>()
49
?? panic("Could not borrow acct2 nft collection reference")
50
51
// Print both collections as arrays of IDs
52
log("Account 1 NFTs")
53
log(nft1Ref.getIDs())
54
55
log("Account 2 NFTs")
56
log(nft2Ref.getIDs())
57
58
// verify that the collections are correct
59
if nft1Ref.getIDs()[0] != 1 || nft2Ref.getIDs().length != 0 {
60
panic("Wrong Collections!")
61
}
62
}
  1. The script should not panic and you should see something like this output
1
"Account 1 Vault Balance"
2
40
3
"Account 2 Vault Balance"
4
20
5
"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.