> For the complete documentation index, see [llms.txt](https://use.temporal.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://use.temporal.xyz/nozomi/transaction-v1.md).

# Transaction v1

Sending SIMD-0296 (v1) transactions through Nozomi.

Nozomi accepts the new Solana transaction format defined by [SIMD-0296](https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0296-transaction-v1.md) and serialized per [SIMD-0385](https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0385-transaction-v1-serialization.md), alongside legacy and v0 transactions. Every submission method recognises it, nothing changes in how you authenticate, tip, or choose an endpoint.

## Availability

Nozomi admits v1 transactions only while the SIMD-0296 feature gate is **active on mainnet**. Before activation every v1 submission is rejected with a specific error (see below), so you can ship v1 support ahead of time and let the network turn it on. Nozomi checks the feature gate itself; there is nothing to enable on your key.

## How Nozomi tells v1 apart

A v1 transaction starts with the byte `0x81`, followed by the signature count. Its signatures sit at the **end** of the serialized bytes rather than the front. Nozomi reads the version from the first byte, validates the envelope, and treats the transaction like any other from then on: same tip rules, same priority, same delivery.

## Encoding

Use **base64** everywhere. JSON-RPC requires `"encoding": "base64"` for every transaction, and for v1 in particular base58 is not supported beyond legacy sizes. API v2 takes the base64 body as before; Batch Send and Send Bundle take raw bytes.

## Size limits

| Method      | Maximum v1 transaction | Maximum body            |
| ----------- | ---------------------- | ----------------------- |
| JSON-RPC    | 4,096 bytes            | 96 KiB (JSON-RPC batch) |
| API v2      | 4,096 bytes            | 5,472 bytes of base64   |
| Batch Send  | 4,096 bytes per member | 65,568 bytes            |
| Send Bundle | 1,232 bytes per member | 4,936 bytes             |

v1 transactions may use the full 4,096 bytes the format allows on JSON-RPC, API v2 and Batch Send. Legacy and v0 transactions keep their 1,232-byte limit, and Send Bundle members of every version stay within 1,232 bytes. A transaction over 1,232 bytes must be base64 or raw binary; base58 cannot carry it.

## Errors

JSON-RPC returns these as `error.code` in a `200` response. API v2, Batch Send and Send Bundle return the HTTP status with a one-line body.

| Condition                               | JSON-RPC code | HTTP status | What to do                                                                |
| --------------------------------------- | ------------- | ----------- | ------------------------------------------------------------------------- |
| v1 not yet active on mainnet            | `-32006`      | `400`       | Wait for the feature gate; send legacy/v0 meanwhile.                      |
| v1 disabled on this endpoint            | `-32005`      | `400`       | Temporary operator kill switch; retry later or use another region.        |
| Unknown transaction prefix              | `-32007`      | `400`       | The first byte is neither a legacy signature count nor `0x81`.            |
| Too large                               | `-32002`      | `400`       | Over 4,096 bytes, or a legacy/v0 transaction or bundle member over 1,232. |
| Large v1 has no delivery path right now | `-32009`      | `503`       | Transient on that region; retry, or fall back to a smaller transaction.   |
| Base58 input too long                   | `-32008`      | n/a         | Switch to base64.                                                         |

Everything else behaves as for legacy transactions: `401` for a bad key, `429` for rate limits, `400` for a missing or insufficient tip.

## Building a v1 transaction in Rust

The v1 types live in the `solana-message` 4.x and `solana-transaction` 4.x crates, serialized with `wincode`. This example self-transfers one lamport and tips Nozomi, then posts through API v2.

```toml
[dependencies]
solana-message = "4.4"
solana-transaction = { version = "4.1", features = ["wincode"] }
wincode = "0.5"
solana-hash = "3"
solana-keypair = "3"
solana-pubkey = "3"
solana-signer = "3"
solana-system-interface = { version = "2", features = ["bincode"] }
solana-rpc-client = "3"
base64 = "0.22"
reqwest = { version = "0.12", features = ["blocking"] }
```

```rust
use solana_keypair::Keypair;
use solana_message::{v1, VersionedMessage};
use solana_pubkey::pubkey;
use solana_signer::Signer;
use solana_system_interface::instruction::transfer;
use solana_transaction::versioned::VersionedTransaction;

const NOZOMI_TIP: solana_pubkey::Pubkey = pubkey!("TEMPaMeCRFAS9EKF53Jd6KpHxgL47uWLcpFArU1Fanq");
const MIN_TIP_AMOUNT: u64 = 1_000_000;

fn build_v1(signer: &Keypair, blockhash: solana_hash::Hash) -> Vec<u8> {
    let ixs = vec![
        transfer(&signer.pubkey(), &signer.pubkey(), 1),
        transfer(&signer.pubkey(), &NOZOMI_TIP, MIN_TIP_AMOUNT),
    ];
    // Compute limit and priority fee move into the v1 header; no ComputeBudget instructions.
    let config = v1::TransactionConfig::empty()
        .with_compute_unit_limit(20_000)
        .with_priority_fee(0);
    let message = v1::Message::try_compile_with_config(&signer.pubkey(), &ixs, blockhash, config).unwrap();
    let tx = VersionedTransaction::try_new(VersionedMessage::V1(message), &[signer]).unwrap();
    wincode::serialize(&tx).unwrap() // first byte is 0x81
}

fn main() {
    let signer = Keypair::new();
    let rpc = solana_rpc_client::rpc_client::RpcClient::new("https://api.mainnet-beta.solana.com".to_string());
    let blockhash = rpc.get_latest_blockhash().unwrap();
    let bytes = build_v1(&signer, blockhash);

    let body = base64::Engine::encode(&base64::engine::general_purpose::STANDARD, &bytes);
    let response = reqwest::blocking::Client::new()
        .post("https://nozomi.temporal.xyz/api/sendTransaction2?c=<YOUR_API_KEY>")
        .header("content-type", "text/plain")
        .body(body)
        .send()
        .unwrap();
    assert!(response.status().is_success(), "{}", response.text().unwrap_or_default());
}
```

Points that differ from legacy transactions:

* The compute unit limit and priority fee are fields of `TransactionConfig`, not `ComputeBudget` instructions.
* Serialize with `wincode`, not `bincode`.
* The signature is the last 64 bytes of the serialized transaction, not the first.

Other SDKs will expose the same format as they add SIMD-0385 support. Nozomi only sees the bytes, so any correctly serialized v1 transaction is accepted.

## Mixing versions

A single Batch Send or Send Bundle body may mix legacy, v0 and v1 members; each is checked on its own. Nozomi never rewrites your transaction, so a v1 transaction is delivered to the leader exactly as you signed it.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://use.temporal.xyz/nozomi/transaction-v1.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
