Skip to content

How to Build a Solana V1 Transaction With Solana Kit

Solana V1 transactions are live on mainnet with a 4,096-byte limit. Learn how to build V1 transactions, update RPC reads, and handle the new transaction configuration.

How to Build a Solana V1 Transaction With Solana Kit

On this page

Solana transaction V1 has been active on mainnet since September 15, 2026, and it changes a detail application developers can no longer safely ignore: a transaction can now be as large as 4,096 bytes instead of 1,232. The new format also moves compute and fee settings into a transaction configuration and removes address lookup tables from V1 messages. This guide shows how to build a V1 transaction, what must change in existing applications, and how to verify that your RPC and transaction-reading code handles the new format correctly. 

What changed when Solana V1 reached mainnet

The upgrade is more than a larger byte limit. Solana V1 is a new transaction format defined alongside the increase in the maximum serialized transaction size, while legacy and V0 transactions continue to work. A V1 message can use up to 4,096 bytes, giving applications considerably more room for data-heavy atomic operations, but it cannot use address lookup tables. Instead, referenced addresses are carried directly in the transaction. 

The other major difference is transaction configuration. Older transactions commonly use Compute Budget instructions to request a compute-unit limit, priority fee, heap size, or loaded-account data limit. V1 puts those values into a transactionConfig section of the message instead. That matters for both writers and readers: code that only scans Compute Budget instructions can miss V1 resource settings entirely. The official Solana V1 examples demonstrate the difference across Rust, TypeScript, Python, and Go. 

Compatibility warning: Existing legacy and V0 transactions are not being replaced. The immediate migration work is making applications capable of reading V1 transactions and updating the parts that need the larger format.

Check your SDK before building a V1 transaction

Start by checking the dependency versions rather than changing transaction code first. Solana's current upgrade guidance lists @solana/kit 8.0.0 as supporting V1 transaction creation and sending, while @solana/web3.js 3.0.0-rc.3 supports reading and sending V1 transactions. The 1.x line has a different position: version 1.99.0 supports reading V1 transactions but does not provide V1 serialization, signing, or sending. Rust's Solana crates support V1 from the 4.2.x line, and solders supports it from 0.29.0.

If your project already uses Solana Kit, this is a relatively direct extension of the transaction-building model you may already know. If you are starting a new Solana application, it is worth understanding the current Kit approach before copying older Web3.js examples. You can also review the site's existing Solana app tutorial for the broader application setup, then treat V1 support as a transaction-layer change rather than a replacement for the rest of your application architecture.

Create a V1 transaction with Solana Kit

With the current Solana Kit implementation, the transaction message is created with version 1 explicitly selected. The important part is that the version belongs to the transaction message itself, so the rest of the pipeline can continue using the same general pattern for setting the payer, blockhash, instructions, signing, and sending. Solana's official V1 example repository confirms that @solana/kit 8.0.0 supports createTransactionMessage({ version: 1 }). 

const transactionMessage = createTransactionMessage({
  version: 1,
});

const messageWithBlockhash = setTransactionMessageLifetimeUsingBlockhash(
  {
    blockhash,
    lastValidBlockHeight,
  },
  transactionMessage
);

const messageWithPayer = setTransactionMessageFeePayer(
  payerAddress,
  messageWithBlockhash
);

The exact surrounding imports and signer setup depend on how your application manages wallets, but the significant change is the version: 1 selection. From there, build the message using the current Kit transaction helpers rather than trying to force V0 assumptions into a V1 message. The official examples use the same transaction pipeline for V1 while routing V1-specific configuration into the message configuration. 

Set the V1 compute and fee configuration correctly

V1 changes the meaning of the familiar compute-budget settings. For V1, the compute-unit limit belongs in config.computeUnitLimit, while the priority fee is represented as a total number of lamports rather than a price in micro-lamports per compute unit. Loaded account data limits and heap size also move into the V1 configuration. The official examples warn that an unset compute-unit limit or loaded-account data limit resolves to zero, so code that assumes the old defaults can produce a transaction that fails.

const transactionMessage = setTransactionMessageConfig(
  {
    computeUnitLimit: 200_000,
    priorityFeeLamports: 5_000,
  },
  messageWithPayer
);

The important detail is the fee unit. In legacy and V0 transactions, priority fees are expressed as micro-lamports per compute unit through a Compute Budget instruction. V1 instead carries the priority fee as an absolute lamport amount in its configuration. That means an indexer or analytics system cannot compare the raw fields directly without normalizing them to the same unit.

Do not carry address lookup tables into a V1 message

Version 0 transactions introduced address lookup tables, which let a transaction refer to addresses stored outside the message and therefore fit more accounts into a limited serialized payload. V1 takes a different approach: address lookup tables are not supported, so the addresses referenced by the transaction have to be represented directly. This is one reason the headline jump from 1,232 to 4,096 bytes should not be interpreted as four times as much usable application space in every workload. 

The trade-off becomes particularly relevant for applications that already depend heavily on lookup tables. A transaction with relatively few accounts can gain substantial room from the larger envelope, while an account-heavy transaction can still run into Solana's account constraints. The Solana Foundation specifically describes V1 as useful for larger atomic workloads such as zero-knowledge proofs, multisignature operations, and some on-chain signature schemes rather than as an automatic performance multiplier for every transaction. 

Update RPC reads before users send V1 transactions

Reading transactions is the migration step that is easiest to overlook. Solana's documentation says RPC requests that read transactions or blocks should pass maxSupportedTransactionVersion: 1 once the application needs to handle V1. An RPC caller that still declares version 0 as its maximum supported version can fail when a response contains a V1 transaction. For block reads, that can affect the entire response when the block contains a V1 transaction. 

const block = await connection.getBlock(slot, {
  maxSupportedTransactionVersion: 1,
});

The same principle applies to transaction reads. Do not test only the transaction your own application creates, because an indexer, explorer, analytics service, wallet backend, or monitoring process can encounter a V1 transaction created by somebody else. Mainnet activation means these transactions are now part of ordinary chain data, so read paths need to tolerate them even if your application does not create them yet. 

Read transaction configuration instead of scanning only instructions

A common V0-era pattern is to inspect Compute Budget instructions and calculate the requested compute or priority fee from them. That approach does not work for V1 because those values can live in transactionConfig. The official V1 examples explicitly warn that a pipeline which derives compute budget or priority fees only by scanning Compute Budget instructions can report zero for V1 transactions. 

if (message.transactionConfig) {
  const computeLimit = message.transactionConfig.computeUnitLimit;
  const priorityFee = message.transactionConfig.priorityFee;
}

For an indexer that supports all three transaction formats, the clean approach is to branch by transaction version and normalize the result into one internal representation. Legacy and V0 can continue using their existing instruction-based logic, while V1 reads the configuration carried by the message. This prevents dashboards, fee estimators, and analytics systems from silently showing incomplete information after V1 traffic becomes common. 

Test V1 locally before changing production traffic

The official Solana Foundation V1 examples provide a useful local test path because the repository exercises sending, decoding, block reading, and indexing against a local solana-test-validator. The example environment uses Anza CLI 4.2.1 or Surfpool 1.5+, and the local validator activates the V1 feature at genesis. This gives you a way to test transaction construction without first putting real funds or production infrastructure at risk. 

just setup-solana
just setup
just demo

If you want to keep the validator running while testing individual operations, the same project provides commands for starting the validator, running a send-and-decode example, and stopping it afterward. Its examples cover Rust, TypeScript, Python, and Go, including V1 transfers, block reads, transaction decoding, and gRPC indexing. That makes the repository particularly useful for checking how your application's transaction-reading assumptions compare with a known working implementation. 

Use a larger transaction only when the workload needs it

The 4,096-byte ceiling is useful when the application genuinely has more data or instructions that must be included atomically. The official examples demonstrate a Token-2022 confidential transfer that occupies 2,897 bytes across ten instructions, a workload that could not fit under the old 1,232-byte limit. This is a concrete example of where V1 changes what can be represented in one transaction rather than merely making an existing transaction smaller or faster. 

That distinction should shape application design. If a normal transfer or swap comfortably fits inside the older formats, moving it to V1 does not automatically provide a measurable user benefit. If your application combines several instructions, large cryptographic payloads, multisignature data, or other information that previously required splitting an operation, V1 can remove that size constraint while preserving atomic execution. Solana's own upgrade documentation describes the larger format in those terms. 

Check these four places before deploying V1 support

  • Transaction creation: confirm the SDK version can construct and serialize V1 messages, then explicitly select transaction version 1.
  • Transaction configuration: move V1 compute and priority-fee handling into the message configuration rather than assuming Compute Budget instructions will carry every value.
  • RPC reads: set maxSupportedTransactionVersion: 1 wherever your application retrieves transactions or blocks.
  • Indexing: detect V1 messages through their transaction configuration and do not rely exclusively on scanning Compute Budget instructions.

There is one more check worth making before calling the migration complete: inspect wallet support. Solana's September developer updates added support for wallets to advertise which transaction versions they understand, and the current V1 guidance lists Wallet Standard support for advertising V1 through supportedTransactionVersions. A backend may be fully capable of producing V1 while a connected wallet still cannot sign or send it, so application compatibility has to include the signing path as well as the chain and RPC layers. 

Solana V1 is therefore best treated as a new transaction format that your software must understand, not as a switch that every application should flip immediately. Existing legacy and V0 traffic remains valid, while V1 introduces more message space and a different way of carrying resource and fee information. The first practical task is to make every reader in your stack tolerate V1; the second is to adopt V1 where a real workload benefits from the larger atomic transaction. Once those two paths are tested separately, the migration becomes much easier to reason about.

H

Written by

Hamza Tariq

I’m interested in blockchain technology, cryptocurrencies, and the ideas behind decentralized applications and digital assets. I enjoy following new developments, understanding how blockchain projects work, and separating useful technology from unnecessary hype. I like explaining crypto and blockchain concepts in a straightforward way.

28 posts published

All posts by this author

0 Comments

No comments yet. Be the first to share your thoughts.

Join the conversation

Log in or create a free account to leave a comment. You can edit or delete your own comments any time.