Use mints with Token Extensions program from TS in web and mobile apps.
Token Extensions Program
has all of the same functions as the
Token Program
, with added extensions
Token Program
and Token Extensions Program
use
separate addresses and are not directly compatibleToken Program
unless another is specifiedToken Extensions Program
may also be referred to as it’s technical spec
name Token22
Token Extensions Program
enhances the original Token Program
by
incorporating additional features known as extensions. These extensions are
designed to address specific scenarios that previously necessitated developers
to fork and alter the Nexis Native Chain Program Library, leading to split ecosystems and
challenges in adoption. The introduction of the Token Extensions Program allows
for these scenarios to be effectively handled.
Since the Token Program
and Token Extensions Program
are different onchain
programs, they are not interoperable. For example, a token minted with
Token Extensions Program
may not be transferred with the Token Program
. As a
result, we’ll have to support both programs in any client-side applications that
need to display or otherwise support all SPL tokens. This means we’ll want to
explicitly handle mints from both the original Token Program (address:
TOKEN_PROGRAM_ID
) and the Extension Program (address:
TOKEN_2022_PROGRAM_ID
).
Fortunately, the interfaces for the two programs remain consistent, allowing the
use of spl-token
helper functions in either program by simply swapping the
program ID (the function uses the original Token Program by default if no
program ID is provided). Most of the time, end users are not concerned with the
specific token program being used. As such, implementing additional logic to
track, assemble, and merge details from both token varieties is essential to
guarantee a smooth user experience.
Lastly, “Token 22” is often used as the technical name. If you see someone refer
to the Token 22 Program, they are referring to the Token Extensions Program.
Token Program
mint, use Token Program
; to
create a mint with extensions, use the Token Extensions Program
.
Fortunately, the spl-token
package makes it simple to do this. It provides
both the TOKEN_PROGRAM_ID
and TOKEN_2022_PROGRAM_ID
constants, along with
all of its helper functions for creating and minting tokens that take a program
ID as input.
Token Program
tokens and Token Extensions Program
tokens,
you must add extra logic on the client side.
getOrCreateAssociatedTokenAccount
Extension Tokens, we can pass in
TOKEN_2022_PROGRAM_ID
for the tokenProgramId
parameter:
findProgramAddressSync
function by providing the correct seeds:
getTokenAccountsByOwner
, and then call it twice, once with
TOKEN_PROGRAM_ID
and another with TOKEN_2022_PROGRAM_ID
.
getParsedAccountInfo
will allow us to determine the
owning program:
starter
branch. This branch contains a couple of helper files
and some boilerplate code to get you started.
npm install
to install the dependencies.
print-helpers.ts
index.ts
print-helpers.ts
file contains a function called printTableData
,
which is designed to output data to the console in a structured format. This
function is capable of accepting any object as its argument, and it utilizes the
console.table
method, a feature provided by NodeJS, to display the data in
an easily readable table format.
Lastly, index.ts
contains our main script. It currently only creates a
connection and calls initializeKeypair
to generate the keypair for payer
.
solana-test-validator
. This
will run the node and also log out some keys and values. The value we need to
retrieve and use in our connection is the JSON RPC URL, which in this case is
http://127.0.0.1:8899
. We then use that in the connection to specify to use
the local RPC URL.
Connection
and the keypair path input to
initializeKeypair
.
npm run start
. You should see
the payer
public key logged out in your terminal.
Token Program
and the
Token Extensions Program
.
Create a new file called create-and-mint-token.ts
. In this file we will create
a function called createAndMintToken
. As the name suggests it will create a
mint, token account (ATA) and then mint some amount of tokens to that account.
Within this createAndMintToken
function we will be call createMint
,
getOrCreateAssociatedTokenAccount
and mintTo
. This function is designed to
be indifferent to the specific token program being used, allowing for the
creation of tokens from either the Token Program
or the
Token Extensions Program
. This capability is achieved by accepting a program
ID as a parameter, enabling the function to adapt its behavior based on the
provided ID.
Here are the arguments we’ll be passing into this function:
connection
- The connection object to usetokenProgramId
- The token program to point topayer
- The keypair paying for the transactiondecimals
- The number of decimals to include for the mintmintAmount
- The amount of tokens to mint to the payercreateMint
getMint
printTableData
getOrCreateAssociatedTokenAccount
mintTo
createAndMintToken
function looks
like:
index.ts
. We’ll want a Token Program
and Token Extensions Program
token to
test against. So we’ll use our two different program IDs:
npm run start
and see that both mints get created
and their info logged to the console.
fetch-token-info.ts
.
Within that new file, let’s create the fetchTokenInfo
function. This function
will fetch the token account provided and return a new interface we’ll create
named TokenInfoForDisplay
. This will allow us to format the returning data
nicely in our console. Again, this function will be agnostic about which token
program the account it from.
getTokenAccountsByOwner
and mapping the results into our new
TokenInfoForDisplay
interface.
To accomplish this the fetchTokenInfo
function will need the following
parameters:
connection
- The connection object to useowner
- The wallet which owns the associated token accountsprogramId
- The token program to point totype
- Either Token Program
or Token Extensions Program
; used for
console logging purposeindex.ts
, let’s add two separate
calls to this function, once for each program.
npm run start
. You should now see all of the tokens the payer wallet owns.
fetchTokenProgramFromAccount
to
fetch-token-info.ts
. This function will simply return us the programId
of
the given mint.
To accomplish this we will call the getParsedAccountInfo
function and return
the owning program from .value.owner
.
The fetchTokenProgramFromAccount
function will need the following parameters:
connection
- The connection object to usemint
- Public key of the mint accountindex.ts
:
npm run start
again. You should see the same output as before - meaning
the expected token programs were correct.
That’s it! If you get stuck at any step, you can find the complete code in
this lab’s repository’s
solution
branch.