In this section of Module 4, we will focus on enhancing the previously developed token minter program by incorporating the functionality to transfer minted tokens to another account through Cross-Program Invocation (CPI). This will include steps to build, deploy, and test the updated program.
illustration
b
Upgrading SPL Token Minter Program

In this lesson, you will:

  • Adapt your spl-token-transfer program to enable token transfers.
  • Create a test file for transferring Gold Tokens.

This lesson guides you through transferring gold tokens using the same program that was employed for minting. We will introduce a transfer function in both the Solidity program and the TypeScript test files. The transferTokens function is designed to facilitate the transfer of gold tokens between Associated Token Accounts (ATAs) using Cross-Program Invocation (CPI) to the SPL Token Library.

Previously, we minted some gold tokens in our spl-token-minter program and transferred them to our ATA. Now, we aim to transfer some of these gold tokens to another account.

We're using the same project setup for this task. Let's start by adding a transfer function in the Solidity program (transfergold.sol) and the TypeScript test file (transfersol.ts).

In the transfergold.sol file, add a transferTokens function below the mintTo function:

// Transfer tokens from one token account to another via Cross-Program Invocation to Token Program
function transferTokens(
 address from, // token account to transfer from
 address to, // token account to transfer to
 uint64 amount // amount of gold to transfer
) public {
 SplToken.TokenAccountData from_data = SplToken.get_token_account_data(from);
 SplToken.transfer(from, to, from_data.owner, amount);
}

This function, transferTokens, requires three inputs:

  1. from: The sender's token account containing Gold Tokens.
  2. to: The recipient's account is linked to the Gold Token Mint.
  3. amount: The quantity of Gold Tokens to transfer.

The function retrieves the sender's token account data and then uses the SplToken.transfer function to perform the actual gold token transfer between the specified ATAs. This transfer is executed as a Cross-Program Invocation (CPI) to the SPL Token Library.

SPL Token Transfer

Here, we transfer Gold Tokens from one ATA to another using CPI.

Now, let's write a test for transferring Gold Tokens in the transfersol.ts test file. Add this test following the mint tokens to our wallet test:

// Transfer token to another wallet via CPI
it("Transfer some tokens to another wallet!", async () => {
  // Wallet's associated token account address for mint
  const tokenAccount = await getOrCreateAssociatedTokenAccount(
    connection,
    wallet.payer, // payer
    mintKeypair.publicKey, // mint
    wallet.publicKey // owner(shivam)
  );

  const receipient = anchor.web3.Keypair.generate();
  const receipientTokenAccount = await getOrCreateAssociatedTokenAccount(
    connection,
    wallet.payer, // payer
    mintKeypair.publicKey, // mint account
    receipient.publicKey // owner(justin) account
  );

  console.log("receipientTokenAccount", receipientTokenAccount);

  const tx = await program.methods
    .transferTokens(
      tokenAccount.address,
      receipientTokenAccount.address,
      new anchor.BN(54000000000)
    )
    .accounts({ dataAccount: dataAccount.publicKey })
    .remainingAccounts([
      {
        pubkey: wallet.publicKey,
        isWritable: true,
        isSigner: true,
      },
      {
        pubkey: mintKeypair.publicKey,
        isWritable: false,
        isSigner: false,
      },
      {
        pubkey: tokenAccount.address,
        isWritable: true,
        isSigner: false,
      },
      {
        pubkey: receipientTokenAccount.address,
        isWritable: true,
        isSigner: false,
      },
    ])
    .rpc();
  console.log("Your transaction signature", tx);

  const recepienttokenAmount = (
    await getAccount(connection, receipientTokenAccount.address)
  ).amount;
  console.log("recipienttokenAmount", recepienttokenAmount);
  let tokens = Number(recepienttokenAmount);

  assert.equal(tokens / LAMPORTS_PER_SOL, 54);
});

In this test:

  • We create the owner’s ATA using getOrCreateAssociatedTokenAccount.
  • Generate a new keypair for the recipient.
  • Create the recipient’s ATA using the same gold token mint.
  • Execute a transaction using the transferTokens method from the Solidity program.
  • Confirm the transfer by checking the recipient’s ATA balance.

By following these steps, we effectively enable our program to transfer Gold Tokens from one account to another.

In the next lesson, we will proceed to build, deploy, and test our upgraded program to ensure its functionality in handling token transfers within the Solana ecosystem.