Marketplace has launched, further enabling blockchain developers! Learn more

How to Use Versioned Transactions on Solana

October 18, 2022

Overview

On October 10, 2022 (Epoch 358), Solana added support for new transaction version types through a concept known as "Versioned Transactions". After this change, the Solana runtime now supports two types of transactions: "legacy" (older transactions) and "0" (transactions that include Address Lookup Tables). Versioned Transactions will allow you to utilize Address Lookup Tables today and could have additional functionality in the future.

In this guide, you will create and execute a Version 0 (V0) Transaction.

If you need help with ensuring your existing client-side apps can support Versioned Transactions, check out our Guide: How to Update Your Solana Client to Handle Versioned Transactions.

What You Will Need

Set Up Your Project

Create a new project directory in your terminal with:

set up your project

Copy
mkdir solana-versioned-tx
cd solana-versioned-tx

Create a file for your app, app.ts:

set up your project

Copy
echo > app.ts

Initialize your project with the "yes" flag to use default values for your new package:

set up your project

Copy
yarn init --yes
#or
npm init --yes

Create a tsconfig.json with .json importing enabled:

set up your project

Copy
tsc -init --resolveJsonModule true

Install Solana Web3 Dependency

We will need to add the Solana Web3 library for this exercise. In your terminal, type:

set up your project

Copy
yarn add @solana/web3.js
#or
npm install @solana/web3.js

Create a Wallet and Airdrop SOL

You'll need to create a Solana File System Wallet (private key written to a guideSecret.json file) and airdrop some SOL to it. You can do this using Solana CLI or use this script we have created for you.

Make sure you save your wallet to your project directory as guideSecret.json.

Let's get started.

Set Up Your App

Import Necessary Dependencies

Open app.ts, and paste the following imports on line 1:

set up your app

Copy
import { Connection, Keypair, LAMPORTS_PER_SOL, SystemProgram, TransactionInstruction, TransactionMessage, VersionedTransaction } from '@solana/web3.js';
import secret from './guideSecret.json';

const SIGNER_WALLET = Keypair.fromSecretKey(new Uint8Array(secret));
const DESTINATION_WALLET = Keypair.generate();

In addition to the Wallet we created in the previous step, we are also importing a few essential methods and classes from the Solana Web3 library.

We have defined two wallets: SIGNER_WALLET will send SOL to our DESTINATION_WALLET.

Set Up Your QuickNode Endpoint

To build on Solana, you'll need an API endpoint to connect with the network. You're welcome to use public nodes or deploy and manage your own infrastructure; however, if you'd like 8x faster response times, you can leave the heavy lifting to us. See why over 50% of projects on Solana choose QuickNode and sign up for a free account here. We're going to use a Solana Devnet node.

Copy the HTTP Provider link:



Inside app.ts under your import statements, declare your RPC and establish your Connection to Solana:

set up your app

Copy
const QUICKNODE_RPC = 'https://example.solana-devnet.quiknode.pro/0123456/';
const SOLANA_CONNECTION = new Connection(QUICKNODE_RPC);

Your environment should look like this:



Alright, let's BUILD!

Create a Version 0 Transaction

Version 0 Transactions require us to use a new class, VersionedTransaction, which requires us to pass a VersionedMessage as a parameter. A VersionedMessage accepts either a Message or MessageV0. Though very similar, MessageV0 allows the use of Address Lookup Tables!

Let's start by creating a new transfer TransactionInstruction that sends 0.1 SOL from our SIGNER_WALLET to our DESTINATION_WALLET. Since our transaction message is going to need an array of Transaction Instructions, go ahead and wrap the instruction in an array:

create a version 0 transaction

Copy
const instructions: TransactionInstruction[] = [
    SystemProgram.transfer({
        fromPubkey: SIGNER_WALLET.publicKey,
        toPubkey: DESTINATION_WALLET.publicKey,
        lamports: 0.01 * LAMPORTS_PER_SOL,
    }),
];

Now let's build a new function, createAndSendV0Tx, that will accept our TransactionInstruction array:

create a version 0 transaction

Copy
async function createAndSendV0Tx(txInstructions: TransactionInstruction[]) {

}

Let's assemble our function. Add these 5 steps to the body of your createAndSendV0Tx function.

Step 1: Fetch the latest blockhash from the network using getLatestBlockhash:

create a version 0 transaction

Copy
    // Step 1 - Fetch Latest Blockhash
    let latestBlockhash = await SOLANA_CONNECTION.getLatestBlockhash('confirmed');
    console.log("   ✅ - Fetched latest blockhash. Last Valid Height:", latestBlockhash.lastValidBlockHeight);

Note: We pass the parameter, 'confirmed,' to make it unlikely that the hash belongs to a dropped fork.

Step 2: Using our txInstructions parameter and the latestBlockhash, we can create a new MessageV0 by constructing a new Message and executing the .compileToV0Message() method:

create a version 0 transaction

Copy
    // Step 2 - Generate Transaction Message
    const messageV0 = new TransactionMessage({
        payerKey: SIGNER_WALLET.publicKey,
        recentBlockhash: latestBlockhash.blockhash,
        instructions: txInstructions
    }).compileToV0Message();
    console.log("   ✅ - Compiled Transaction Message");
    const transaction = new VersionedTransaction(messageV0);

We then pass our message into a new instance of VersionedTransaction. Congrats! You have created a versioned transaction!

Step 3: Sign the transaction with an array of signers. In this case, it is just our SIGNER_WALLET.

create a version 0 transaction

Copy
    // Step 3 - Sign your transaction with the required `Signers`
    transaction.sign([SIGNER_WALLET]);
    console.log("   ✅ - Transaction Signed");
NOTE: When sending a VersionedTransaction to the cluster, it must be signed BEFORE calling the sendAndConfirmTransaction method. Source: edge.docs.solana.com.

Step 4: Send the transaction to the cluster using sendTransaction, which will return a transaction signature/id:

create a version 0 transaction

Copy
    // Step 4 - Send our v0 transaction to the cluster
    const txid = await SOLANA_CONNECTION.sendTransaction(transaction, { maxRetries: 5 });
    console.log("   ✅ - Transaction sent to network");

Note: We pass the parameter, 'maxRetries,' to allow the RPC to retry sending the transaction to the leader if necessary.

Step 5: Finally, wait for the cluster to confirm the transaction has succeeded:

create a version 0 transaction

Copy
    // Step 5 - Confirm Transaction 
    const confirmation = await SOLANA_CONNECTION.confirmTransaction({
        signature: txid,
        blockhash: latestBlockhash.blockhash,
        lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
    })
    if (confirmation.value.err) { throw new Error("   ❌ - Transaction not confirmed.") }
    console.log('🎉 Transaction Succesfully Confirmed!', '\n', `https://explorer.solana.com/tx/${txid}?cluster=devnet`);

If it succeeds, we log the successful transaction's explorer URL.

Alright! We're ready to try it out!

Run Your Code

To execute our function, call createAndSendV0Tx at the bottom of the file, passing in instructions as the argument:

run your code

Copy
createAndSendV0Tx(instructions);

Our final code is available on GitHub, here.

And then, in your terminal, call:

run your code

Copy
ts-node app.ts

Do you see something like this?



Nice job! If you'd like to check your code against ours, we've provided it on GitHub, here.

Next Steps

Now that you can build and execute versioned transactions, it's time to see what V0 Transactions can do. Check out our Guide: How to Use Lookup Tables on Solana (coming soon) to learn more about Solana's new lookup table feature and how to use them.

If you're stuck, have questions, or just want to talk shop, drop us a line on Discord or Twitter!

We <3 Feedback!

If you have any feedback or questions on this guide, let us know. We’d love to hear from you.

Related articles 33

Como crear un NFT en SOLANA
Published: Dec 27, 2021
Updated: Sep 23, 2022

¡Hola querido lector! Bienvenidos a una nueva guía de Solana.Solana es una blockchain que promete mucho a la hora de intentar resolver los problemas de escalabilidad que...

Continue reading
How to Get Transaction Logs on Solana
Published: Jun 24, 2022
Updated: Oct 27, 2022

Ever need to pull all the transactions associated with a Wallet? Want to see all of the mint transactions associated with a Candy Machine? Or maybe see transaction history of an NFT? Solana's...

Continue reading
How to Transfer SPL Tokens on Solana
Published: Sep 23, 2022
Updated: Sep 23, 2022

Sending Solana Program Library (SPL) Tokens is a critical mechanism for Solana development. Whether you are airdropping whitelist tokens to your community, bulk sending NFTs to another wallet,...

Continue reading
How to Mint an NFT on Solana
Published: Aug 27, 2021
Updated: Sep 23, 2022

Updated at: April 10, 2022Welcome to another QuickNode guide on Solana - the up-and-coming blockchain that seeks to solve the scalability issues of Ethereum. We will be walking through...

Continue reading
How to Send Bulk Transactions on Solana
Published: Aug 31, 2022
Updated: Oct 3, 2022

Are you running a batch process that has many transactions? Perhaps an airdrop to your community's NFT holders or a token distribution to early users of your dApp. Solana transaction...

Continue reading
Solana Fundamentals Reference Guide
Published: Oct 27, 2022
Updated: Oct 27, 2022

The Solana blockchain is a powerful tool, delivering thousands of transactions per second with almost no-cost transaction fees. If you are new to Web3 or have developed on EVM-based...

Continue reading