Written by
Hunter Davis
Published on
July 24, 2023
Copy link

Solana Dev 101 — How to Transfer Solana Tokens with Typescript

Introduction

In Solana, token accounts are used to hold and manage tokens, including non-fungible tokens (NFTs). This can make transferring tokens with code a bit of a struggle for beginner developers in Solana. In this tutorial, we will learn how to transfer NFTs from one wallet to another on the Solana blockchain. We'll achieve this by creating a new Associated Token Account (ATA) for the recipient and transferring the NFT to that account.

Differences in NFT and SOL Transfers

In a Token transfer, a new Associated Token Account (ATA) needs to be created to initiate the transfer from previous owner to the new owner. This does not occur through a wallet → wallet transfer.

This is different than a regular transfer involving SOL, as the system program will handle the transfer, and a new ATA does not need to be created to house the SOL involved in the transaction.

For a brief visual representation of the process, please refer to the following:

Visual for differences in transactions.

To summarize, in a NFT/Token transfer, the asset is sent from the current ATA to a newly created ATA owned by the recipient, instead of transferring it directly to the wallet.

Prerequisites

Before proceeding with this tutorial, make sure you have the following prerequisites:

  1. Basic knowledge of TypeScript.
  2. Node.js installed on your machine.
  3. npm or yarn package manager installed.

Steps to Build

Now, let's follow the steps below to build the code:

  1. Set up the project:

           - Create a new directory for your project called “Transfer”.

            - Open a terminal and navigate to the project folder.

            - Initialize a new Node.js project using the command: npm init -y or yarn init -y.

           - Install the required dependencies by running the command:


npm install @solana/web3.js @solana/spl-token bs58

            - Create a new TypeScript file, e.g., transferNFT.ts, and open it in a code editor.

  1. Import the necessary libraries and define the transfer function in a new transferNFT.ts file:

import { Keypair, Transaction, Connection, PublicKey } from "@solana/web3.js";
import { createTransferCheckedInstruction, getAssociatedTokenAddress } from "@solana/spl-token";
import * as bs58 from "bs58";

async function transfer() {
  // Code for transferring NFTs goes here
}

transfer();

In the above code we are importing our necessary packages, as well as creating our transfer function.

     3. Establish a connection to the Solana network:


const connection = new Connection("https://rpc.helius.xyz/?api-key=");

In the above code, we are using our Helius RPC to establish a connection with the Solana blockchain.

  1. Define the fee payer's and previous owner's keypairs:

const feePayer = Keypair.fromSecretKey(bs58.decode("privateKey"));
const prevOwner = Keypair.fromSecretKey(bs58.decode("privateKey"));
  1. Specify the mint public key and recipient's wallet address. The mint public key will be the token address of the NFT you are looking to transfer:

const mintPubkey = new PublicKey("4umMdShNxbdnoV2EZjUp6h5GYYneZFLH9otBEU2K3ZYP");
const receiveAddress = new PublicKey("2xSHLfiPs3aEhzbLnYbyzWYMEaYnwSwJwAnVh5CwHWwX");
  1. Generate the associated token address (ATA) for the recipient:

const ata = await getAssociatedTokenAddress(mintPubkey, receiveAddress);

In this code, we are setting the new ATA owner to be a public key of a different address here. This does not have to be the payer of the transaction.

Make sure to set receiveAddress to the address needing the asset transferred to.

  1. Specify the source token account's and destination token account's public keys:

const tokenAccount1Pubkey = new PublicKey("CE2uTSeVbBhy2Q8qVEnp8qAJYBQkVxMC4uGzchiAn6gG");
const tokenAccount2Pubkey = new PublicKey(ata);
  1. Create a new transaction and add the transfer instruction:

const tx = new Transaction();
tx.add(
  createTransferCheckedInstruction(
    tokenAccount1Pubkey,
    mintPubkey,
    tokenAccount2Pubkey,
    prevOwner.publicKey,
    1, // Amount you are transferring. 
    0 // Decimals, since this is an NFT you can leave 0. 
  )
);

In the above code, we are:

  • Defining our previous and current token account.
  • Setting the amount to be transferred to 1 (since there is only a 1 supply of the mint address).
  • Setting the decimals to 0, since this is abiding by the non-fungible token standard. For a fungible token you can have the decimals set properly for transfer.
  1. Send the transaction to the Solana network:

const txhash = await connection.sendTransaction(tx, [feePayer, prevOwner]);
console.log(`Transaction hash: ${txhash}`);

We are now using the sendTransaction method to complete the transaction and note the fee payer, and previous owner of the asset to sign.

Full Code


import { Keypair, Transaction, Connection, PublicKey } from "@solana/web3.js";
import { createTransferCheckedInstruction, getAssociatedTokenAddress } from "@solana/spl-token";
import * as bs58 from "bs58";

async function transfer() {
  // connection to Solana. 
const connection = new Connection("https://rpc.helius.xyz/?api-key=");

// Payer of new ATA. 
const feePayer = Keypair.fromSecretKey(
  bs58.decode("privateKey")
);

// Previous owner of Token or NFT
const prevOwner = Keypair.fromSecretKey(
  bs58.decode("privateKey")
);
// Mint address of the NFT. 
const mintPubkey = new PublicKey("4umMdShNxbdnoV2EZjUp6h5GYYneZFLH9otBEU2K3ZYP");
// Recipient of the NFT. 
const receiveAdress = new PublicKey('2xSHLfiPs3aEhzbLnYbyzWYMEaYnwSwJwAnVh5CwHWwX')
// Original Token Account
const tokenAccount1Pubkey = new PublicKey("CE2uTSeVbBhy2Q8qVEnp8qAJYBQkVxMC4uGzchiAn6gG");
let ata = await getAssociatedTokenAddress(
    mintPubkey, // mint
    receiveAdress // owner
  );
// Create transfer instruction to from the previous ATA owned by old wallet, to new ATA. 
const tokenAccount2Pubkey = new PublicKey(ata);
let tx = new Transaction();
  tx.add(
    createTransferCheckedInstruction(
      tokenAccount1Pubkey, // from
      mintPubkey, // mint
      tokenAccount2Pubkey, // to
      prevOwner.publicKey, // from's owner
      1, // amount
      0 // decimals
    )
  );
  // Send Transaction here. 
  console.log(`txhash: ${await connection.sendTransaction(tx, [feePayer, prevOwner])}`);
}

transfer()

Remember to replace the placeholder values in the code with your actual values, such as RPC URL, secret keys, and public keys for the transfer.

Conclusion

Congratulations! You have successfully built the code to transfer NFTs on Solana by creating a new Associated Token Account (ATA) and transferring the NFT to the recipient's account. By following this tutorial, you learned how to establish a connection, generate ATAs, and send transactions on the Solana blockchain. You can now take the information learned here and apply to any dApp example you are creating.