To enable additional extensions on existing Token Accounts created via the Token
Extension program, additional space must first be reallocated to accommodate the
extra data required by these extensions. This can be done using the reallocate
instruction.
For example, this allows existing Token Accounts can be updated to enable the
MemoTransfer
and
CpiGuard
extensions.
In this guide, we'll walk through an example of using Solana Playground. Here is the final script.
Getting Started
Start by opening this Solana Playground link with the following starter code.
// Clientconsole.log("My address:", pg.wallet.publicKey.toString());const balance = await pg.connection.getBalance(pg.wallet.publicKey);console.log(`My balance: ${balance / web3.LAMPORTS_PER_SOL} SOL`);
If it is your first time using Solana Playground, you'll first need to create a Playground Wallet and fund the wallet with devnet SOL.
If you do not have a Playground wallet, you may see a type error within the
editor on all declarations of pg.wallet.publicKey
. This type error will clear
after you create a Playground wallet.
To get devnet SOL, run the solana airdrop
command in the Playground's
terminal, or visit this devnet faucet.
solana airdrop 5
Once you've created and funded the Playground wallet, click the "Run" button to run the starter code.
Add Dependencies
Let's start by setting up our script. We'll be using the @solana/web3.js
and
@solana/spl-token
libraries.
Replace the starter code with the following:
import {Connection,Transaction,clusterApiUrl,sendAndConfirmTransaction,} from "@solana/web3.js";import {ExtensionType,TOKEN_2022_PROGRAM_ID,createAccount,createMint,createReallocateInstruction,createEnableRequiredMemoTransfersInstruction,} from "@solana/spl-token";// Playground walletconst payer = pg.wallet.keypair;// Connection to devnet clusterconst connection = new Connection(clusterApiUrl("devnet"), "confirmed");// Transaction signature returned from sent transactionlet transactionSignature: string;
Create Mint and Token Account
First, we'll need to create a new Mint Account.
// Authority that can mint new tokensconst mintAuthority = pg.wallet.publicKey;// Decimals for Mint Accountconst decimals = 2;// Create Mint Accountconst mint = await createMint(connection,payer, // Payer of the transaction and initialization feesmintAuthority, // Mint Authoritynull, // Optional Freeze Authoritydecimals, // Decimals of Mintundefined, // Optional keypairundefined, // Options for confirming the transactionTOKEN_2022_PROGRAM_ID, // Token Extension Program ID);
Next, let's create a Token Account with no extensions enabled.
// Create Token Account for Playground walletconst tokenAccount = await createAccount(connection,payer, // Payer to create Token Accountmint, // Mint Account addresspayer.publicKey, // Token Account ownerundefined, // Optional keypair, default to Associated Token Accountundefined, // Confirmation optionsTOKEN_2022_PROGRAM_ID, // Token Extension Program ID);
Build Instructions
Next, let's build a transaction to enable the MemoTransfer
extensions for an
existing Token Account.
First, build the instruction to reallocate the Token Account with enough space for the specified extension. The Token Extensions Program includes a reallocate instruction that automatically calculates the space and lamports required.
// Extensions to reallocate data forconst extensions = [ExtensionType.MemoTransfer];// Instruction to reallocate Token Account dataconst reallocateInstruction = createReallocateInstruction(tokenAccount, // Token Account addresspayer.publicKey, // Payer to reallocate dataextensions, // Extensions to reallocate forpayer.publicKey, // Token Account ownerundefined, // Additional signersTOKEN_2022_PROGRAM_ID, // Token Extension Program ID);
Next, build the instruction to enable the MemoTransfer
extension for the Token
Account.
// Instruction to initialize the MemoTransfer Extensionconst enableRequiredMemoTransfersInstruction =createEnableRequiredMemoTransfersInstruction(tokenAccount, // Token Account addresspayer.publicKey, // Token Account Ownerundefined, // Additional signersTOKEN_2022_PROGRAM_ID, // Token Extension Program ID);
Send Transaction
Next, let's add the instructions to a new transaction and send it to the
network. This will update the Token Account with the MemoTransfer
extension
enabled.
// Add instructions to new transactionconst transaction = new Transaction().add(reallocateInstruction,enableRequiredMemoTransfersInstruction,);// Send TransactiontransactionSignature = await sendAndConfirmTransaction(connection,transaction,[payer],);console.log("\nReallocate:",`https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`,);
Run the script by clicking the Run
button. You can then inspect the
transaction details on SolanaFM.
Conclusion
The reallocate instruction on the Token Extensions program offers a flexible way to update existing Token Accounts with additional functionalities. This instruction is useful for token owners who may not have foreseen the need for certain extensions initially, but find themselves requiring these additional features at a later time.