Tutorials
Technical Guides
Featured Guides
Learn the Basics - Technical Guides
1 – Learn the FCL Basics
Ensure you check out the Flow App Quickstart
tutorial to learn the essentials of FCL (Flow Client Library)
2 – Add FCL to your project
FCL is available on npm
here: https://www.npmjs.com/package/@onflow/fcl
@onflow/fcl
version of at least 0.0.78-alpha.8
or higher.To install:
3 – Connect FCL to Dapper
Before a user can connect Dapper to an application, FCL must first be configured to communicate with Dapper.
There are two ways to configure FCL for Dapper.
Configuration method 1: hard-code the wallet URI
To connect a Flow-based application with Dapper, FCL must be explicitly configured for Dapper.
The environment variable values will be different between production / mainnet
and staging / testnet
environments:
For more details on access nodes, please see the Flow documentation on this subject: https://developers.flow.com/nodes/access-api#flow-access-node-endpoints
The wallet discovery endpoints we configured here tells FCL to direct user to the Dapper Wallet login/signup page.
The values for app.detail.title
and app.detail.icon
are used by Dapper for cosmetic display purposes. At the time of this writing (Dec 13, 2021), only app.detail.title
is used during the wallet connection flow. If this value is set, the user will see Connecting to <app.detail.title>...
. If not set, the user will see Connecting...
Configuration method 2: use FCL's wallet discovery page
Using this method, FCL will show a pop-up window with a list of supported wallets. Clicking on a specific wallet provider will further configure FCL with details of that wallet.
To enable Dapper Wallet on the discovery page, configure FCL in the following way:
Connect a user's Dapper wallet to the application
Once FCL is configured, a user's Dapper account can be connected by calling fcl.authenticate()
authenticate()
will open a new browser window to the specified Dapper URI. authenticate()
must be called in the same call stack as the click handler for the button
click, or the popup will be blocked by the browser (i.e. you cannot call authenticate()
asynchronous to the click handler).See https://docs.onflow.org/fcl/flow-app-quickstart/#authentication for a more in-depth example.
4 – Use FCL to interact with a Dapper user
How to request a transaction signature from a Dapper user
In order for a Cadence transaction to be executed on Flow, it must have the appropriate cryptographic signatures. On Flow, there are 3 types of signatures that must be provided: Proposer
, Payer
, and one ore more Authorizers
See this document for more details:
See the FCL documentation for guidance on how to request transaction signatures from a wallet, including Dapper:
Using FCL, follow the example of this code snippet to submit Dapper transaction through FCL.
⚠️ WARNING: Popup blocking behavior in Safari and Firefox
FCL will attempt to open a popup window to Dapper to request transaction signatures. Default browser behavior is to block the popup if there is any asynchronous action between when the user clicks the button to request the signature and when the call to fcl.send
or fcl.mutate
is made.
For example, this code will result in Safari or Firefox blocking the Dapper popup:
Please thoroughly test with Safari/Firefox any code paths that request signatures from Dapper to ensure that the popup is not blocked.
How to query Flow for account information on a Dapper user
Information about a user's Flow account can be queried using Cadence scripts. Scripts do not require authorization from the user and can be accessed from public information made available on their account.
See the FCL documentation on how to send scripts to the chain:
5 – Dapper signing transactions
Dapper signer roles
For Dapper users, the transaction signatures provided will be a mix of the user's keys and Dapper admin keys.
User-provided signatures
A Dapper user will provide a signature for theProposer
and possibly an Authorizer
. Users do not provide a Payer
signature.
An example of a transaction where the user provides both Proposer
and Authorizer
signatures is the 'initialization' transaction here.
An example of a transaction where the user only provides the Proposer
signature here.
Dapper-provided signatures
A Dapper admin account will provide a signature for the Payer
and possibly an Authorizer
.
By providing the Payer
signature, Dapper pays for transaction fees on behalf of its users.
Dapper provides the Authorizer
signature when it needs access to private resources in the Dapper Wallet admin account, such as the case when a Dapper user purchases an NFT from a marketplace. See the 'buy listing' transaction here.
Supported transactions on Dapper
Because Dapper is a custodial wallet, transactions signatures will only be provided for specific, known transaction scripts. This is to prevent transactions that are malicious or against our policies from being executed.
As part of the engagement process with marketplaces wishing to integrate with Dapper, the Dapper team will review all marketplace transaction templates to make sure they are compliant with our policies and, in the case of purchase-type transactions, will work with our payment system.
Once the transactions are reviewed and approved by the Dapper team, they will be added to an 'allow-list' on the Dapper platform, which will allow Dapper users to sign them.
6 – Initialize a user's Flow account for a marketplace
A user's Flow account, typically, needs the specific marketplace resources
and capabilities
to be created in their account in order to be able to execute the Cadence transactions that underpin the marketplace.
For a typical marketplace, two types of resources
need to be created:
- specific NFT resources to be able to store, deposit, and withdraw NFTs
- an NFT Storefront resource to be able to list NFTs for sale
NFTStorefront
resource only needs to be deployed once per Flow account, so it is unlikely that the marketplace will need to initialize this resource for the userCapabilities
are created on top of these resources that expose specific functionality to allow the marketplace to interact with the user's resources in a secure manner.
Required marketplace resources
A marketplace is responsible for writing the Cadence transactions that will check for, and create if missing, the specific NFT resources and capabilities that are required to interact with the marketplace contracts and transactions.
Whether a marketplace only allows one type of NFT (NBA Top Shot) or allows many different NFT types (VIV3), the process of checking for the specific NFT resource and creating it if it's missing, is largely the same.
NFT Storefront resource
The NFTStorefront
resource can handle any type of NFT. During the Dapper account creation process, an NFTStorefront
resource will be created in the user's Flow account, so the marketplace should not have to create this for the user. It is recommended that marketplace transactions still check for the existence of this resource.
The NFTStorefront
contract, scripts, and transactions are open source:
The Cadence transaction to add this resource and expose capabilities can be found here.
NFT resources
There are two approaches a marketplace may take when attempting to add NFT resources to a user's Flow account:
- a one-time 'initialization' transaction
- as part of a transaction that requires the NFT resource to exist, such as a 'Buy NFT' transaction
It is preferable to initialize the user's account as a one-time 'initialization' transaction to ensure can interact with all marketplace transactions (such as gifting, for example).
User initialization transaction
After a user connects their Dapper wallet to the marketplace for the first time, the marketplace can ask the user to sign a transaction that adds the correct resources and capabilities to their Flow account. By initializing the user's Flow account as part of the first-time connection experience, the user is able to receive the marketplace NFTs (again, such as receiving a gift).
An example initialization transaction(https://github.com/dapperlabs/dapper-supported-transactions/blob/master/initialize-account/initialize-account.cdc)
If a marketplace deals with multiple type of NFTs, the initialization transaction would add each NFT resource and capability one by one:
As part of a 'buy' transaction
A potential downside of the one-time 'initialization' transaction described above is the extra step a user must take before being able to fully interact with the marketplace transactions. Instead, the NFT resources can be added as part of the 'buy' transaction, if they are missing from the user's account.
A slightly modified example from the purchase-nft-direct
transaction(https://github.com/dapperlabs/dapper-supported-transactions/blob/master/purchase-nft-direct/purchase-nft-direct.cdc):
Detecting if a user's Flow account is initialized
A marketplace can determine if a user has already initialized their Flow account for the marketplace by querying their on-chain account for the required resources and capabilities.
For example, to check if a specific NFT resource and capability used by the marketplace has been added to a user's Flow account, a marketplace could run the following script, which returns a boolean
indicating whether or not the account is initialized.
7 – Initialize the Storefront account
Setting up the Storefront resource
The Flow account that will be selling direct-to-user NFTs will need to create and store a NFTStorefront.Storefront
resource, by running this transaction:
Receiving on-chain payments from Dapper users transaction
For marketplaces that will sell from a central Storefront account (e.g direct-to-user, usually used for 'drops' or other non-p2p sales), a special type of fungible token resource will need to be created on the Storefront account in order to integrate with Dapper's payment system.
To receive on-chain payments from a Dapper user, a specific fungible token resources needs to be added to the Storefront account.
A Storefront account is defined here as an account controlled by the marketplace operator, used for direct-to-consumer type sales such as NFT 'drops'.
When a Dapper user purchases an NFT listing from the Storefront, two distinct payment events happen: one off-chain, and one on-chain:
- Off-chain: a Dapper user can purchase an NFT using Dapper credits, credit cards, ACH payment, and cryptocurrencies from other chains. Dapper collects the user's payment on behalf of the Storefront.
- On-chain: after collecting the user's off-chain payment, Dapper purchases the NFT on behalf of a user, using an on-chain fungible token called
DapperUtilityCoin
(DUC). As the name implies, the Dapper Utility Coin is used strictly for utility and has no intrinsic value. Please note, DUC is intended only to be used within Dapper products.
The DUC contract is deployed here:
To receive the payment on-chain in DUC, the Storefront account must create a special resource called a Forwarder
. The Forwarder
ensures that the Storefront is properly credited for purchases made by Dapper users.
The TokenForwarding
contract, which defines the Forwarder
resource, is deployed here:
An example of the transaction to run on the Storefront account:
TokenForwarding.Forwarder
resource forwards, or routes, the DUC payment back to the Dapper admin account, such that the Storefront account never actually holds any DUC. Instead, on-chain events are emitted by the TokenForwarding
contract whenever a payment in DUC is received. These events are consumed by the Dapper platform to credit the storefront operator with Dapper credits. These credits can later be withdrawn at the storefront operator's request.8 – List an NFT for sale
Listing an NFT for sale for non-Dapper users
An NFT can be listed for sale by creating a Listing
resource in the seller's Flow account. See the following transaction that lists an ExampleNFT.NFT
for sale:
Listing an NFT for sale for Dapper users
For a Dapper user to be able to purchase an NFT, the transaction that creates the Listing
transaction needs to be different than the above example so that:
- Dapper users can pay for an NFT using off-chain payment methods, such as Dapper Balance, credit cards, ACH, wires and/or cryptocurrencies on other chains
For example:
9 – Buy an NFT from a marketplace
A Dapper user can purchase an NFT from a marketplace if the NFTStorefront.Listing
resource representing the sale was created to accept the Dapper Utility Coin (DUC) as payment. For more info, please see here.
When purchasing an NFT from a compatible marketplace, a Dapper user purchases the NFT using Dapper checkout and an off-chain payment method such as credit card, Dapper credits, ACH, or cryptocurrencies on other chains.
The payment is collected by Dapper on behalf of the marketplace (seller) and Dapper purchases the NFT on behalf of the user (buyer). On-chain, Dapper purchases the Listing
with DUC and deposits the NFT in the buyer's NFT collection. The seller receives the payment in the form of Dapper credits.
High-level 'buy NFT' flow
An example buy transaction
10 – Transaction metadata
Transactions can have metadata associated with them in order to display a user-facing description of an underlying Cadence transaction script. Dapper (will) support two types of metadata: off-chain and on-chain.
Off-chain metadata
Off-chain metadata is generic and does not take into account the specifics of a transaction, such as the arguments to it.
For example, many applications require that a user’s Flow account be properly initialized so that it can hold the application’s specific NFTs. A high-level description of such a transaction might read: “Prepare your Flow account for our awesome NFTs.” This would be displayed more prominently than the Cadence transaction script that it describes since most users do not understand Cadence.
On-chain metadata
On the other hand, on-chain metadata can be more specific than off-chain metadata because Dapper can use transaction arguments to query Flow for details about a transaction.
For example, a ‘buy NFT’ transaction will specify transaction arguments such as NFT_ID and price. Dapper can then run a Cadence script, using those argument values, to query for metadata about that particular NFT (if it exists on-chain). A hypothetical NFT might define metadata such as ‘serial number’, ‘edition name’, ‘series name’, etc. which can be queried by NFT_ID. Dapper Checkout then uses this mechanism to populate the Checkout screen with the name, serial number, price, and image of the NFT.
Another example would be listing an NFT for sale. The arguments to this transaction would be similar to the ‘buy NFT’ transaction: the NFT_ID and the price. Dapper can run an on-chain query using these arguments to display a screen to the user listing the NFT for sale with the metadata reading “Do you want to list Furry Octopus #14/100 for $99 USD?” alongside an image of the Furry Octopus. For more details on how Dapper manages assets, please see our FAQ entry titled ‘How do I provide images/assets to Dapper?’
11 – On-chain metadata
On-chain metadata is needed for Dapper checkout to ensure that the asset description and price displayed to the user matches the asset description and price on-chain.
For a more bespoke implementation, an NFT contract can define a metadata structure particular to that NFT. For example, the Genies
contract defines metadata using a hierarchy of on-chain structs
singletons that are referenced by the NFTs. This allows the metadata to be stored on-chain at minimal cost, as opposed to duplicating and storing the metadata within the NFT resource itself (storing data on-chain incurs storage costs).
In the Genies
contract, the only data stored on the NFT
itself is the serialNumber
, the mintingDate
, and a reference to the Edition
from which it was minted. The rest of the metadata for an NFT can be retrieved by querying these other structs, using the NFT.id
as the starting point.
Metadata in Dapper checkout
For transactions that are eligible for Dapper checkout, Dapper will display purchase details on the checkout UI that is pulled from on-chain NFT metadata. Using arguments to the 'buy' transaction, such as the NFTStorefront.Listing.id
, Dapper will query the chain for metadata related to the sale such as NFT name, description, imageURL (url to off-chain image of NFT), and sale price.
For example, the data Dapper references for the purchase of a Genies NFT is:
12 – Flow contract examples
Generic contracts
NFT Storefront
Non Fungible Token
Fungible Token
Specific marketplace contracts
NBA Top Shot
Genies
Kitty Items
Ballmart
Ballmart - NFT marketplace
We have the biggest balls
dapper-ballmart-git-staging-dapperlabs.vercel.app
13 – How to provide images to Dapper
NFT images can be displayed on the Dapper Checkout if they are publicly accessible via HTTP. For optimal performance, we recommend you optimize these images for 150px X 150px and host them on a CDN.
ON THIS PAGE
- Learn the Basics - Technical Guides
- 1 – Learn the FCL Basics
- 2 – Add FCL to your project
- 3 – Connect FCL to Dapper
- 4 – Use FCL to interact with a Dapper user
- 5 – Dapper signing transactions
- 6 – Initialize a user's Flow account for a marketplace
- 7 – Initialize the Storefront account
- 8 – List an NFT for sale
- 9 – Buy an NFT from a marketplace
- 10 – Transaction metadata
- 11 – On-chain metadata
- 12 – Flow contract examples
- 13 – How to provide images to Dapper