Creating a Circulating Supply
In the previous tutorial, you looked at what a fungible token was and how you could define one in your smart contract. In this tutorial, you'll learn how to create a circulating supply belonging to the contract owner and view all the tokens, with their metadata, in the NEAR wallet.
To get started, either work off the code you wrote in the previous tutorial or switch to the 2.define-a-token
folder in our repo. If you haven't cloned the repository, refer to the Contract Architecture to start.
If you wish to see the finished code for this tutorial, you can find it in the 3.initial-supply
folder.
Introduction
Every fungible token contract on NEAR has what's known as a circulating supply. This is the number of tokens that exist on the contract and are actively available to trade.
When creating your contract, there are many different ways you could implement this to start. A few examples could be:
- Specify a starting total supply and distribute it based on a set of parameters (Benji gets 20%, Josh gets 2.5%, and the rest goes to Mike).
- Have a first come first serve pool where everybody claims up to X amount of tokens.
- Create tokens on demand resulting in a steady increase of the circulating supply overtime up to a specified cap.
The simplest approach, however, is to specify a total supply when initializing the contract. The entire circulating supply is then created and sent to the owner of the contract. The owner would then be able to transfer or sell the tokens as they wish. Once the initial supply is created, no more FTs could be minted. This means that the circulating supply will always be equal to the total supply.
Modifications to contract
In order to implement this logic, you'll need to keep track of two things in your smart contract:
- A mapping of an account to the number of tokens they own.
- The total supply of tokens.
The mapping is so that you can easily check or modify the tokens owned by any given account at anytime within your contract. You'll also need to keep track of the total supply since it's required by the standard that you have a function to query for the supply of tokens on the contract.
Setting the supply
Head over to the src/lib.rs
file and add the following code to the Contract
struct.
Loading...
You'll now want to add the functionality for depositing the tokens into the owner's account. Do this by creating a helper function that takes an amount and an account ID and performs the deposit logic for you. First create a new file src/internal.rs
such that your file structure now looks as follows.
src
├── ft_core.rs
├── internal.rs
├── lib.rs
├── metadata.rs
└── storage.rs
In the internal.rs
file, add the following code to create a function called internal_deposit
which takes an AccountId
and a NearToken
as a balance and adds the amount to the account's current supply of FTs.
Loading...
Now that the functionality for depositing FTs is in place, switch back to the src/lib.rs
file and add the internal
module:
Loading...
In addition, add the following code to the new
initialization function.
#[init]
pub fn new(
owner_id: AccountId,
total_supply: U128,
metadata: FungibleTokenMetadata,
) -> Self {
let casted_total_supply = NearToken::from_yoctonear(total_supply.0);
// Create a variable of type Self with all the fields initialized.
let mut this = Self {
// Set the total supply
total_supply: casted_total_supply,
// Storage keys are simply the prefixes used for the collections. This helps avoid data collision
accounts: LookupMap::new(StorageKey::Accounts),
metadata: LazyOption::new(
StorageKey::Metadata,
Some(&metadata),
),
};
// Set the owner's balance to the total supply.
this.internal_deposit(&owner_id, casted_total_supply);
// Return the Contract object
this
}
This will initialize the total supply to what you passed in and will call the internal_deposit
function to add the total supply to the owner's account.
Getting the supply
Now that you've created a way to set the total supply, you'll also want a way to query for it as well as the balance for a specific user. The standard dictates that you should have two methods on your smart contract for doing these operations:
ft_total_supply
ft_balance_of
Head on over to the src/ft_core.rs
file and add the following code to these functions.
Loading...
At this point, you have everything you need to create an initial supply of tokens and query for the balance of a given account. There is, however, a problem that we need to solve. How will the wallet know that the total supply was created and is owned by the contract owner? How would it even know that our contract is a fungible token contract? If you were to deploy the contract and run through the setup process, you would be able to query for the information from the contract but you wouldn't see any FTs in the owner's NEAR wallet.
Events
Have you ever wondered how the wallet knows which FTs you own and how it can display them in the balances tab? Originally, an indexer used to listen for any function calls starting with ft_
on your account. These contracts were then flagged on your account as likely FT contracts.
When you navigated to your balances tab, the wallet would then query all those contracts for the number of FTs you owned using the ft_balance_of
function you just wrote.