Understand how tokens - both regular tokens and NFTs - are created, stored, and transferred on Nexis Native Chain.
@nexis-network/spl-token
Javascript library.
EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
.
With the explorer, we can see the particular details about USDC’s Token Mint
such as the current supply of tokens, the addresses of the mint and freeze
authorities, and the decimal precision of the token:
createMint
function from
@nexis-network/spl-token
.
createMint
function returns the publicKey
of the new token mint. This
function requires the following arguments:
connection
- the JSON-RPC connection to the clusterpayer
- the public key of the payer for the transactionmintAuthority
- the account that is authorized to do the actual minting of
tokens from the token mint.freezeAuthority
- an account authorized to freeze the tokens in a token
account. If freezing is not a desired attribute, the parameter can be set to
nulldecimals
- specifies the desired decimal precision of the tokencreateMint
function. However, if you were to build a
website to allow users to create a new token mint, you would need to do so with
the user’s secret key without making them expose it to the browser. In that
case, you would want to build and submit a transaction with the right
instructions.
Under the hood, the createMint
function is simply creating a transaction that
contains two instructions:
getMinimumBalanceForRentExemptMint
, the result of which is
passed into the createAccount
function. This is part of account initialization
called rent exemption.
Until recently, all accounts on Nexis Native Chain were required to do one of the following
to avoid being deallocated:
getMinimumBalanceForRentExemptMint
from the @nexis-network/spl-token
library.
However, this concept applies to all accounts and you can use the more generic
getMinimumBalanceForRentExemption
method on Connection
for other accounts
you may need to create.
spl-token
library’s createAccount
function to create the new
Token Account:
createAccount
function returns the publicKey
of the new token account.
This function requires the following arguments:
connection
- the JSON-RPC connection to the clusterpayer
- the account of the payer for the transactionmint
- the token mint that the new token account is associated withowner
- the account of the owner of the new token accountkeypair
- this is an optional parameter for specifying the new token account
address. If no keypair is provided, the createAccount
function defaults to a
derivation from the associated mint
and owner
accounts.createAccount
function is different from the
createAccount
function shown above when we looked under the hood of the
createMint
function. Previously we used the createAccount
function on
SystemProgram
to return the instruction for creating all accounts. The
createAccount
function here is a helper function in the spl-token
library
that submits a transaction with two instructions. The first creates the account
and the second initializes the account as a Token Account.
Like with creating a Token Mint, if we needed to build the transaction for
createAccount
manually we could duplicate what the function is doing under the
hood:
getMint
to retrieve the data associated with the mint
getAccountLenForMint
to calculate the space needed for the token
accountgetMinimumBalanceForRentExemption
to calculate the lamports needed for
rent exemptionSystemProgram.createAccount
and
createInitializeAccountInstruction
. Note that this createAccount
is from
@nexis-network/web3.js
and used to create a generic new account. The
createInitializeAccountInstruction
uses this new account to initialize the
new token accountpublicKey
for a specific token.
There are other ways to create token accounts (particularly for onchain
programs), but nearly all the time you want to store tokens for a user, you’ll
want it to be an Associated Token Account. Even if the user doesn’t already have
an ATA for that token, you can simply find the address and make the account for
them.
spl-token
library’s
createAssociatedTokenAccount
function.
publicKey
of the new associated token account and
requires the following arguments:
connection
- the JSON-RPC connection to the clusterpayer
- the account of the payer for the transactionmint
- the token mint that the new token account is associated withowner
- the account of the owner of the new token accountgetOrCreateAssociatedTokenAccount
to get the Token Account
associated with a given address or create it if it doesn’t exist. For example,
if you were writing code to airdrop tokens to a given user, you’d likely use
this function to ensure that the token account associated with the given user
gets created if it doesn’t already exist.
Under the hood, createAssociatedTokenAccount
is doing two things:
getAssociatedTokenAddress
to derive the associated token account
address from the mint
and owner
createAssociatedTokenAccountInstruction
spl-token
library, you can use the mintTo
function.
mintTo
function returns a TransactionSignature
that can be viewed on the
Nexis Native Chain Explorer. The mintTo
function requires the following arguments:
connection
- the JSON-RPC connection to the clusterpayer
- the account of the payer for the transactionmint
- the token mint that the new token account is associated withdestination
- the token account that tokens will be minted toauthority
- the account authorized to mint tokensamount
- the raw amount of tokens to mint outside of decimals, e.g. if
Scrooge Coin mint’s decimals property was set to 2 then to get 1 full Scrooge
Coin you would need to set this property to 100mintTo
function simply creates a transaction with the
instructions obtained from the createMintToInstruction
function.
getOrCreateAssociatedTokenAccount
when obtaining the receiver’s
associated token account to ensure their token account exists before the
transfer. If the account doesn’t exist already, this function will create it and
the payer on the transaction will be debited the lamports required for the
account creation.
Once you know the receiver’s token account address, you transfer tokens using
the spl-token
library’s transfer
function.
transfer
function returns a TransactionSignature
that can be viewed on
the Nexis Native Chain Explorer. The transfer
function requires the following arguments:
connection
- the JSON-RPC connection to the clusterpayer
- the account of the payer for the transactionsource
- the token account sending tokensdestination
- the token account receiving tokensowner
- the account of the owner of the source
token accountamount
- the number of tokens to transfertransfer
function simply creates a transaction with the
instructions obtained from the createTransferInstruction
function:
.env
file with a SECRET_KEY
setup per
Cryptography fundamentals.
create-token-mint.ts
. After loading our keypairs,
we’ll call createMint()
, setting our user
as the payer
, mintAuthority
,
and freezeAuthority
.
Think of the token mint as the factory that makes tokens. Our user
, as the
mintAuthority
is the person that runs the factory.
npx esrun create-token-mint.ts
. You should see
mpl-token-metadata
Program, version 2. This is the most
popular version of mpl-token-metadata
and saves significant complexity
compared to the newer version 3.
create-token-metadata.ts
Warning! Token names and logos are not unique. This token may have spoofed its name and logo to look like another token. Verify the token’s mint address to ensure it is correct.This warning is accurate - indeed anyone can make any token have any symbol or name they like. However for your reference, if you are making an original token that becomes very well known, Nexis Native Chain Explorer uses a whitelist based on the Unified Token List API.
create-token-account.ts
. Then use
getOrCreateAssociatedTokenAccount()
to get an associated token account based
on a wallet and our mint address, making the account if it needs to.
Remember to substitute in your token mint address below!
npx esrun create-token-mint.ts
. You should see:
user
as the mintAuthority
for the
mint
we created.
Create a function mintTokens
that uses the spl-token
function mintTo
to
mint tokens:
npx esrun mint-tokens.ts
. You should see:
spl-token
library’s transfer
function. You can
add a second account on devnet
if you like, or find a friend who has a devnet account and send them your token!
As you saw in Explorer, the tokens currently reside in an Associated Token
Account attached to our wallet. We don’t have to remember the address for our
associated token account - we can just look it up using
getOrCreateAssociatedTokenAccount()
and provide our wallet address and the
mint of the token we want to send. Likewise, we can find (or make) an ATA for
our recipient to hold this token too.
CreateMint
component. If you need a
refresher on how to send transactions to a wallet for approval, have a look
at the
Wallets lesson.Keypair
will also have to sign
the transaction. When additional signers are required in addition to the
connected wallet, use the following format:
CreateTokenAccount
component.MintToForm
component.