legacy
(see Send a legacy transaction) and v0
(transactions that can include Address Lookup Tables or LUTs).
The goal of v0
is to increase the maximum size of a transaction, and hence the number of accounts that can fit in a single atomic transaction. With LUTs, developers can now build transactions with a maximum of 256 accounts, as compared to the limit of 35 accounts in legacy transactions that do not utilize LUTs.
For a dive deep on versioned transactions, LUTs, and how the above changes affect the anatomy of a transaction, see Versioned Transactions - Anvit Mangal’s Blog.
- Building a versioned tansaction.
- Signing and sending a versioned transaction.
- Building an Address LUT.
- Extending an Address LUT.
- Signing and sending a versioned transaction using a LUT.
Build a versioned transaction
Versioned transactions are built in a very similar fashion to legacy transactions. The only difference is that developers should use theVersionedTransaction
class rather than the Transaction
class.
The following example shows how to build a simple transfer instruction. Once the transfer instruction is made, a MessageV0
formatted transaction message is constructed with the transfer instruction. Finally, a new VersionedTransaction
is created, parsing in the v0
compatible message.
createTransactionV0()
Sign and send a versioned transaction
Once a Versioned transaction is created, it can be signed and sent via Phantom using thesignAndSendTransaction
method on the provider. The call will return a Promise for an object containing the signature
. This is the same way a legacy transaction is sent via the Phantom provider.
signAndSendTransaction()
SendOptions
object as a second argument into signAndSendTransaction()
or as an options
parameter when using request
.
For a live demo of signing and sending a versioned transaction, refer to handleSignAndSendTransactionV0 in our sandbox.
Build an Address LUT
Address LUTs can be used to load accounts into table-like data structures. These structures can then be referenced to significantly increase the number of accounts that can be loaded in a single transaction. This lookup method effectively “compresses” a 32-byte address into a 1-byte index value. This “compression” enables storing up to 256 address in a single LUT for use inside any given transaction. With the@solana/web3.js
createLookupTable method, developers can construct the instruction needed to create a new LUT, as well as determine its address. Once we have the LUT instruction, we can construct a transaction, sign it, and send it to create a LUT on-chain. Address LUTs can be created with either a v0
transaction or a legacy
transaction. However, the Solana runtime can only retrieve and handle the additional addresses within a LUT while using v0
transactions.
The following is a code snippet that creates a LUT.
createAddressLookupTable()
Extend an Address LUT
Once an Address LUT is created, it can then be extended, which means that accounts can be appended to the table. Using the@solana/web3.js
library, you can create a new extend
instruction using the extendLookupTable method. Once the extend instruction is created, it can be sent in a transaction.
extendAddressLookupTable()
Sign and send a versioned transaction using a LUT
Up until now, we have:- Learned how to create a
VersionedTransaction
. - Created an Address LUT.
- Extended the Address LUT.
VersionedTransaction
using an Address LUT.
First, we need to fetch the account of the created Address LUT.
getAddressLookupTable()
Parse and read addresses
VersionedTransaction
earlier. This VersionedTransaction
can then be sent using the signAndSendTransaction()
provider function.