MAINNET:
Loading...
TESTNET:
Loading...
/
onflow.org
Flow Playground

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/45ae690e-c527-409c-970e-57f03df92790
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.
SetupAccount1Transaction.cdc
// SetupAccount1Transaction.cdc

import ExampleToken from 0x01
import ExampleNFT from 0x02

// This transaction sets up account 0x01 for the marketplace tutorial
// by publishing a Vault reference and creating an empty NFT Collection.
transaction {
  prepare(acct: AuthAccount) {
    // Create a public Receiver capability to the Vault
    acct.link<&ExampleToken.Vault{ExampleToken.Receiver, ExampleToken.Balance}>
             (/public/CadenceFungibleTokenTutorialReceiver, target: /storage/CadenceFungibleTokenTutorialVault)

    log("Created Vault references")

    // store an empty NFT Collection in account storage
    acct.save<@ExampleNFT.Collection>(<-ExampleNFT.createEmptyCollection(), to: /storage/nftTutorialCollection)

    // publish a capability to the Collection in storage
    acct.link<&{ExampleNFT.NFTReceiver}>(ExampleNFT.CollectionPublicPath, target: ExampleNFT.CollectionStoragePath)

    log("Created a new empty collection and published a reference")
  }
}
  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
// SetupAccount2Transaction.cdc

import ExampleToken from 0x01
import ExampleNFT from 0x02

// This transaction adds an empty Vault to account 0x02
// and mints an NFT with id=1 that is deposited into
// the NFT collection on account 0x01.
transaction {

  // Private reference to this account's minter resource
  let minterRef: &ExampleNFT.NFTMinter

  prepare(acct: AuthAccount) {
    // create a new vault instance with an initial balance of 30
    let vaultA <- ExampleToken.createEmptyVault()

    // Store the vault in the account storage
    acct.save<@ExampleToken.Vault>(<-vaultA, to: /storage/CadenceFungibleTokenTutorialVault)

    // Create a public Receiver capability to the Vault
    let ReceiverRef = acct.link<&ExampleToken.Vault{ExampleToken.Receiver, ExampleToken.Balance}>(/public/CadenceFungibleTokenTutorialReceiver, target: /storage/CadenceFungibleTokenTutorialVault)

    log("Created a Vault and published a reference")

    // Borrow a reference for the NFTMinter in storage
    self.minterRef = acct.borrow<&ExampleNFT.NFTMinter>(from: ExampleNFT.MinterStoragePath)
        ?? panic("Could not borrow owner's NFT minter reference")
  }
  execute {
    // Get the recipient's public account object
    let recipient = getAccount(0x01)

    // Get the Collection reference for the receiver
    // getting the public capability and borrowing a reference from it
    let receiverRef = recipient.getCapability(ExampleNFT.CollectionPublicPath)
                               .borrow<&{ExampleNFT.NFTReceiver}>()
                               ?? panic("Could not borrow nft receiver reference")

    // Mint an NFT and deposit it into account 0x01's collection
    receiverRef.deposit(token: <-self.minterRef.mintNFT())

    log("New NFT minted for account 1")
  }
}
  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
// SetupAccount1TransactionMinting.cdc

import ExampleToken from 0x01
import ExampleNFT from 0x02

// This transaction mints tokens for both accounts using
// the minter stored on account 0x01.
transaction {

  // Public Vault Receiver References for both accounts
  let acct1Capability: Capability<&AnyResource{ExampleToken.Receiver}>
  let acct2Capability: Capability<&AnyResource{ExampleToken.Receiver}>

  // Private minter references for this account to mint tokens
  let minterRef: &ExampleToken.VaultMinter

  prepare(acct: AuthAccount) {
    // Get the public object for account 0x02
    let account2 = getAccount(0x02)

    // Retrieve public Vault Receiver references for both accounts
    self.acct1Capability = acct.getCapability<&AnyResource{ExampleToken.Receiver}>(/public/CadenceFungibleTokenTutorialReceiver)
    self.acct2Capability = account2.getCapability<&AnyResource{ExampleToken.Receiver}>(/public/CadenceFungibleTokenTutorialReceiver)

    // Get the stored Minter reference for account 0x01
    self.minterRef = acct.borrow<&ExampleToken.VaultMinter>(from: /storage/CadenceFungibleTokenTutorialMinter)
        ?? panic("Could not borrow owner's vault minter reference")
  }

  execute {
    // Mint tokens for both accounts
    self.minterRef.mintTokens(amount: 20.0, recipient: self.acct2Capability)
    self.minterRef.mintTokens(amount: 10.0, recipient: self.acct1Capability)

    log("Minted new fungible tokens for account 1 and 2")
  }
}
  1. Run the script CheckSetupScript.cdc file in Script 1 to ensure everything is set up.
CheckSetupScript.cdc
// CheckSetupScript.cdc

import ExampleToken from 0x01
import ExampleNFT from 0x02

// This script checks that the accounts are set up correctly for the marketplace tutorial.
//
// Account 0x01: Vault Balance = 40, NFT.id = 1
// Account 0x02: Vault Balance = 20, No NFTs
pub fun main() {
    // Get the accounts' public account objects
    let acct1 = getAccount(0x01)
    let acct2 = getAccount(0x02)

    // Get references to the account's receivers
    // by getting their public capability
    // and borrowing a reference from the capability
    let acct1ReceiverRef = acct1.getCapability(/public/CadenceFungibleTokenTutorialReceiver)
                          .borrow<&ExampleToken.Vault{ExampleToken.Balance}>()
                          ?? panic("Could not borrow acct1 vault reference")

    let acct2ReceiverRef = acct2.getCapability(/public/CadenceFungibleTokenTutorialReceiver)
                          .borrow<&ExampleToken.Vault{ExampleToken.Balance}>()
                          ?? panic("Could not borrow acct2 vault reference")

    // Log the Vault balance of both accounts and ensure they are
    // the correct numbers.
    // Account 0x01 should have 40.
    // Account 0x02 should have 20.
    log("Account 1 Balance")
    log(acct1ReceiverRef.balance)
    log("Account 2 Balance")
    log(acct2ReceiverRef.balance)

    // verify that the balances are correct
    if acct1ReceiverRef.balance != 40.0 || acct2ReceiverRef.balance != 20.0 {
        panic("Wrong balances!")
    }

    // Find the public Receiver capability for their Collections
    let acct1Capability = acct1.getCapability(ExampleNFT.CollectionPublicPath)
    let acct2Capability = acct2.getCapability(ExampleNFT.CollectionPublicPath)

    // borrow references from the capabilities
    let nft1Ref = acct1Capability.borrow<&{ExampleNFT.NFTReceiver}>()
        ?? panic("Could not borrow acct1 nft collection reference")

    let nft2Ref = acct2Capability.borrow<&{ExampleNFT.NFTReceiver}>()
        ?? panic("Could not borrow acct2 nft collection reference")

    // Print both collections as arrays of IDs
    log("Account 1 NFTs")
    log(nft1Ref.getIDs())

    log("Account 2 NFTs")
    log(nft2Ref.getIDs())

    // verify that the collections are correct
    if nft1Ref.getIDs()[0] != 1 || nft2Ref.getIDs().length != 0 {
        panic("Wrong Collections!")
    }
}
  1. The script should not panic and you should see something like this output
"Account 1 Vault Balance"
40
"Account 2 Vault Balance"
20
"Account 1 NFTs"
[1]
"Account 2 NFTs"
[]

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.