July 5, 2021
DappStarter makes it easy for you to generate a full-stack source code Flow blockchain application. Once you clone the auto-generated project GitHub repository and open the project in your IDE such as VSCode, you’re probably wondering how the project is organized. Here’s your answer.
In this document, I’ll lead you through the project structure and explain the purpose of key files. As a rule of thumb, if something is not described here, it is most likely something you can safely ignore.
Let’s get started with the directory structure, beginning from the root directory /packages.
This directory is where you will do almost all of your coding. It includes three things:
Before we walk through the directory structure, it’s useful to step back and understand the DappStarter architecture. Much of the orchestration of DappStarter is handled by the Rhythm Toolkit, a collection of utility scripts located in the /packages/dapplib/src subdirectory. Here’s what each script does:
Now that you have some insights into the architecture, let’s explore the project directory structure.
The /packages/dapplib/contracts contains all your smart contracts. The directory is watched and upon any change in files, the Flow emulator is restarted and all smart contracts are redeployed. In addition all test accounts are regenerated wiping out any prior state.
One important decision you will need to make is how to break up your smart contracts into files. It’s important to follow the convention established in DappStarter so the Rhythm deployment scripts work as expected:
When deploying Cadence contracts, the order in which they are deployed is significant for imported contracts. You don’t have to worry about whether or not contracts that import other contracts get deployed before/after their dependency contracts. This will be automatically handled for you.
This means if you have a contract named ExampleFungibleToken that gets imported inside ExampleNFT, you can place it in the Project directory as well. You can also create an arbitrary subdirectory structure within the Project directory. I like to use “imports,” but you can name these subdirectories anything you wish. This is shown in Figure 2.
DappStarter makes importing smart contracts extremely easy using this format:
import [EntityName] from [Source].[ContractName]
EntityName: Entity being imported
Source: Currently supported sources are “Flow,” “Decentology,” and “Project”
ContractName: Contract name
An example of this can be found in Figure 3. It isn’t necessary for a contract file to be named the same as the contract it contains, but this is a good convention to follow.
If you want to know where exactly the smart contracts are deployed you can find this information in /packages/dapplib/src/dapp-config.json. This is a configuration file that is auto-generated and managed by DappStarter.
The /packages/dapplib/interactions directory contains all your transactions and scripts. An example of a properly setup interactions directory is shown in Figure 4.
You can also create subdirectories within your transactions and scripts directories if you want a more structured layout. For example, let’s say we have transactions and scripts for both FungibleTokens and NonFungibleTokens. We can have a greater separation by adding subdirectories as shown in Figure 5.
Here’s what’s happening in the code:
You may be wondering how dapp-lib.js is actually calling these transactions/scripts. This process is shown in Figure 7.
In this article, I provided details on developing and using Flow Smart Contracts with DappStarter. I also reviewed the blockchain interaction architecture used by DappLib and covered some sample code. In Part 2, I’ll cover the DappStarter client libraries, UI Harness and provide sample code for interacting with DappLib.