3 min read
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). Though on-chain programs do not have to adopt the change, many client-side applications need to be updated to prevent errors due to different transaction types.
In this guide, you will learn about the technical changes as a result of Solana's Versioned Transactions launch and how to update your client-side code to handle those changes.
What You Will Need
- Nodejs (version 16.15 or higher) installed
- Experience with Solana Web3 JSON RPC API
Client-Side Code Changes: Max Supported Transaction Version
For Solana JSON RPC requests that return a Transaction now include an optional parameter, maxSupportedTransactionVersion. This parameter tells the runtime the highest version of transactions the application should expect. At the time of this writing (10/11/2022), two values can be passed:
- legacy: older transaction format with no additional benefit
- 0: added support for Address Lookup Tables
If the request returns a versioned transaction higher than what is set in maxSupportedTransactionVersion (i.e., if a version 0 transaction is returned when legacy is selected), the runtime will return an Error.
How to Avoid Errors in Existing Applications
At present, two native Solana JSON RPC methods are impacted by this change and should include a maxSupportedTransactionVersion parameter:
- getBlock
- getTransaction
(Note: non-native methods, getParsedTransaction and getParsedBlock, also accept this parameter)
Though the maxSupportedTransactionVersion parameter is optional in both methods, the best practice will be to set maxSupportedTransactionVersion to 0 to capture all transaction types and avoid errors.
getBlock()
getBlock method calls should add { maxSupportedTransactionVersion: 0 } after the desired slot to search:
const web3 = require("@solana/web3.js");
(async () => {
const solana = new web3.Connection("https://example.solana-mainnet.quiknode.pro/0123456/");
console.log(
await solana.getBlock(
94101948,
//ADD THIS 👇
{ maxSupportedTransactionVersion: 0 })
);
})();
The returned class, VersionedBlockResponse is very similar to BlockResponse, but it has one key difference. The Transactions array will include a MessageV0 class instead of Message, allowing you to access addressTableLookups. For more detail on the MessageV0 class, check out solana-labs.github.io/.
getTransaction()
getTransaction method calls should add { maxSupportedTransactionVersion: 0 } after the desired transaction ID to search:
const web3 = require("@solana/web3.js");
(async () => {
const solana = new web3.Connection("https://example.solana-mainnet.quiknode.pro/0123456/");
console.log(
await solana.getTransaction(
"D13jTJYXoQBcRY9AfT5xRtsew7ENgCkNs6mwwwAcUCp4ZZCEM7YwZ7en4tVsoDa7Gu75Jjj2FgLXNUz8Zmgedff",
//ADD THIS 👇
{ maxSupportedTransactionVersion: 0 }
)
);
})();
Reference: edge.docs.solana.com/.../versioned-transactions
JSON Parsed Results
The Solana Foundation now recommends using JSON Parsed encoding because it includes all transaction account keys (including those from lookup tables) in the message "accountKeys" list. This makes it straightforward to resolve balance changes detailed in preBalances / postBalances and preTokenBalances / postTokenBalances. If the "json" encoding is used instead, entries in preBalances / postBalances and preTokenBalances / postTokenBalances may refer to account keys that are NOT in the "accountKeys" list and need to be resolved using "loadedAddresses" entries in the transaction metadata. (Source: Solana Foundation).
For your javascript applications, this simply means changing
- getTransaction() to getParsedTransaction() and
- getBlock() to getParsedBlock()
For cURL/CURL requests set encoding to jsonParsed:
{"encoding": "Parsed"}
Reference: docs.solana.com/...versioned-transaction-migration
Recap
If you're running existing client-side code, and you use getBlock or getTransaction, that's all you need to do! If you're using Python or cURL/CURL requests, check out our docs for code samples here.
Versioned Transactions are here to stay, and as new versions are implemented, you will need to keep up with network updates to ensure your dApp can support the latest versions. To stay up to date on the latest Solana news and information, subscribe to our newsletter or follow us on Twitter.
If you have any questions or want to discuss your project, drop us a line on Discord.
We ❤️ Feedback!
If you have any feedback or questions on this guide, let us know. We’d love to hear from you!