arrow-left

Only this pageAll pages
gitbookPowered by GitBook
1 of 22

Temporal Docs

Nozomi

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Introduction

Land transactions faster and more consistently.

Nozomi is a fully custom proprietary client written by HPC and HFT engineers designed to land transactions as fast as possible.

hashtag
Who Should Use It

Sniper Bots: Snipe tokens and mints before the competition.

Defi Apps: Create a better UX so user transactions do not stall or fail.

Traders: Land with speed and precision to capture the most opportunities.

Liquidators: Be first to a liquidation transaction.

Jito Bundle Users: Get through the block engine faster and more efficient.

Algorithmic traders: Get predictability with your bots in all market conditions.

Tipping & FAQ

hashtag
Transaction Tip

Each transaction must include a system transfer instruction to the Nozomi tip address, with a minimum tip of 0.001 SOL. Increasing the tip raises your transaction’s priority in the queue—higher tips settle faster.

These tips compensate the Jito tip and pay validators for staked connections. If Jito validates the transaction, the tip goes to the Jito validator. In that case, Nozomi forwards the entire tip to Jito.

Herearrow-up-right is a breakdown of tips by percentile.

hashtag
Nozomi Tip Addresses

Send your tip to any one of these 17 addresses. To optimize performance and avoid write CU exhaustion, use a random different address for each transaction.

hashtag
Priority Fee

Nozomi gets your transaction to the scheduler. At this point, priority fees matter. It is recommended to set CU price to at least 1,000,000 lamports, or expect subpar performance.

hashtag
Retries

Nozomi will retry transactions until confirmation or expiry. Nozomi will prioritize retries based on the amount tipped.

hashtag
Rate Limits

Each API key has an associated rate limit.

hashtag
QoS Priority

Clients with high failure rate will have a QoS penalty to their priority. For example if only 10% of your transactions successfully land, your priority will be discounted to 10%. This is based on last 30 minutes of transaction sending.

hashtag
Optimized Routing

What makes Nozomi unique is how it routes transactions through the TPU. It knows exactly when and how to send transactions.

Nozomi does not simulate transactions.

hashtag
Avoiding Front-Running

There is Front Running Protection URL that only sends through a custom whitelist of trusted validators (Helius, Coinbase, etc.) .

Set strict slippage tolerances and calculate minAmountOut to have protections against front-running.

hashtag
Customizability

Only pay the tip if you execute your desired opportunity. Since the tip is a transfer, if you detect someone captured the opportunity you wanted, you can fail your transaction to avoid paying the tip.

If you are a high tipper, please reach out for custom rate limits.

hashtag
Contact

hashtag
Open Discord Ticket to get API Key:

https://discord.gg/kvSnnF3Farrow-up-right
"TEMPaMeCRFAS9EKF53Jd6KpHxgL47uWLcpFArU1Fanq",
"noz3jAjPiHuBPqiSPkkugaJDkJscPuRhYnSpbi8UvC4",
"noz3str9KXfpKknefHji8L1mPgimezaiUyCHYMDv1GE",
"noz6uoYCDijhu1V7cutCpwxNiSovEwLdRHPwmgCGDNo",
"noz9EPNcT7WH6Sou3sr3GGjHQYVkN3DNirpbvDkv9YJ",
"nozc5yT15LazbLTFVZzoNZCwjh3yUtW86LoUyqsBu4L",
"nozFrhfnNGoyqwVuwPAW4aaGqempx4PU6g6D9CJMv7Z",
"nozievPk7HyK1Rqy1MPJwVQ7qQg2QoJGyP71oeDwbsu",
"noznbgwYnBLDHu8wcQVCEw6kDrXkPdKkydGJGNXGvL7",
"nozNVWs5N8mgzuD3qigrCG2UoKxZttxzZ85pvAQVrbP",
"nozpEGbwx4BcGp6pvEdAh1JoC2CQGZdU6HbNP1v2p6P",
"nozrhjhkCr3zXT3BiT4WCodYCUFeQvcdUkM7MqhKqge",
"nozrwQtWhEdrA6W8dkbt9gnUaMs52PdAv5byipnadq3",
"nozUacTVWub3cL4mJmGCYjKZTnE9RbdY5AP46iQgbPJ",
"nozWCyTPppJjRuw2fpzDhhWbW355fzosWSzrrMYB1Qk",
"nozWNju6dY353eMkMqURqwQEoM3SFgEKC6psLCSfUne",
"nozxNBgWohjR75vdspfxR5H9ceC7XXH99xpxhVGt3Bb"

Tip Stream

Stream Nozomi Tip Floors by Percentile

hashtag
Rest Endpoint

curl https://api.nozomi.temporal.xyz/tip_floor

hashtag
Websocket

wscat -c wss://api.nozomi.temporal.xyz/tip_stream

hashtag
Schema

[
  {
    "time": "string (ISO 8601 timestamp)",
    "landed_tips_25th_percentile": "number",
    "landed_tips_50th_percentile": "number",
    "landed_tips_75th_percentile": "number",
    "landed_tips_95th_percentile": "number",
    "landed_tips_99th_percentile": "number"
  }
]

TypeScript

Use full service RPC for fetching latest blockhash. Nozomi only supports sendTransaction.

import { Connection, PublicKey, Keypair, TransactionInstruction, SystemProgram, TransactionMessage, VersionedTransaction, TransactionSignature } from "@solana/web3.js";

const NOZOMI_ENDPOINT = "https://nozomi.temporal.xyz/?c=<YOUR_API_KEY>";
const NOZOMI_TIP = new PublicKey("TEMPaMeCRFAS9EKF53Jd6KpHxgL47uWLcpFArU1Fanq");
const MIN_TIP_AMOUNT = 1_000_000;

const SOLANA_RPC_ENDPOINT = "https://api.mainnet-beta.solana.com";

async function sendNozomiTxn(ixns: TransactionInstruction[], signer: Keypair, nozomiRpcClient: Connection, solanaRpcClient: Connection): Promise<TransactionSignature> {
    const tipIxn = SystemProgram.transfer({
        fromPubkey: signer.publicKey,
        toPubkey: NOZOMI_TIP,
        lamports: MIN_TIP_AMOUNT
    });
    ixns.push(tipIxn);

    const { blockhash } = await solanaRpcClient.getLatestBlockhash();

    const messageV0 = new TransactionMessage({
        payerKey: signer.publicKey,
        recentBlockhash: blockhash,
        instructions: ixns,
    }).compileToV0Message();

    const versionedTxn = new VersionedTransaction(messageV0);

    versionedTxn.sign([signer]);

    return await nozomiRpcClient.sendTransaction(versionedTxn);
}

function buildIxns(): TransactionInstruction[] {
    // your instruction building logic here..
    return [];
}

async function main() {
    const nozomiRpcClient = new Connection(NOZOMI_ENDPOINT);

    const solanaRpcClient = new Connection(SOLANA_RPC_ENDPOINT);

    // replace with actual keypair loading logic
    const signer = Keypair.generate();

    const ixns = buildIxns();

    const signature = await sendNozomiTxn(ixns, signer, nozomiRpcClient, solanaRpcClient);

    console.log(`Transaction sent with signature: ${signature}`);
}

main().catch(err => {
    console.error(err);
});

Batch Send

hashtag
Nozomi sendBatch Client Integration Guide

hashtag
1. What sendBatch does

POST /api/sendBatch lets you submit multiple raw Solana transactions in one request using a compact binary format (no base64).

Use this when you already have serialized tx bytes and want to reduce per-request overhead.

hashtag
2. Endpoint and auth

  • Method: POST

  • Path: /api/sendBatch

  • Required query param: c=<client_id>

Example URL:

https://YOUR_HOST/api/sendBatch?c=YOUR_CLIENT_ID

hashtag
3. Binary wire format

Body is a concatenation of entries:

[len_hi][len_lo][tx_bytes...] [len_hi][len_lo][tx_bytes...] ...

  • len_hi,len_lo: unsigned big-endian u16 length

  • len > 0

  • tx_bytes

No separators and no JSON wrapper are used.

hashtag
4. Limits and validation

  • Max entries per request: 16

  • Max tx size per entry: 1232 bytes

  • Min tx size accepted: 66 bytes

Requests violating framing, count, or parsing rules are rejected.

hashtag
5. Response behavior (important)

sendBatch is stream-processed.

That means entries are handled in order as bytes arrive. If entry N fails:

  • entries 1..N-1 may already be accepted and forwarded

  • there is no rollback

  • response is an error for the overall request

Your client should treat this endpoint as partially successful on some failures.

hashtag
6. HTTP status codes and response bodies

All responses are plain text (text/plain).

  • 200 OK + empty body Full request accepted.

  • 400 Bad Request + Bad Request\n Framing/format errors (invalid length prefixes, truncated payload, too many entries, empty batch, etc.).

hashtag
7. JavaScript reference implementation

hashtag
8. curl example

hashtag
9. Production recommendations

  1. Keep batch sizes small enough for your retry strategy (for example 2-8 txs).

  2. Track tx signatures client-side before send, so you can reconcile partial success.

  3. On non-200 responses, do not assume the whole batch failed.

hashtag
10. CORS/preflight

  • OPTIONS is supported.

  • Response headers include:

    • Access-Control-Allow-Origin: *

Recommended header: Content-Type: application/octet-stream

: raw serialized transaction bytes for that entry

Max total request body: 19,744 bytes (16 * (1232 + 2))

400 Bad Request
+
Transaction too large\n
At least one tx exceeded allowed size, or body exceeded max cap.
  • 400 Bad Request + Failed to parse transaction\n Transaction bytes failed metadata/parse checks.

  • 400 Bad Request + Malformed transaction string\n Transaction payload is malformed (for example, too small).

  • 400 Bad Request + Insufficient tip\n Tx did not satisfy configured tip policy.

  • 401 Unauthorized + Unauthorized\n Missing/invalid c client id.

  • 429 Too Many Requests + Too Many Requests\n Rate limit exceeded.

  • 405 Method Not Allowed + Used HTTP Method is not allowed. POST is required\n Non-POST usage.

  • 500 Internal Server Error + Internal Server Error\n Internal forwarding/queue failure.

  • Make retries idempotent at the tx/signature level in your system.
  • Log both HTTP status and response text; response text is meaningful for error class.

  • Access-Control-Allow-Methods: POST, GET, OPTIONS

  • Access-Control-Allow-Headers: Content-Type

  • function encodeBatch(rawTxs) {
      // rawTxs: Array<Uint8Array|Buffer> of serialized Solana tx bytes
      if (!Array.isArray(rawTxs) || rawTxs.length === 0) {
        throw new Error("batch must contain at least one transaction");
      }
      if (rawTxs.length > 16) {
        throw new Error("batch cannot exceed 16 transactions");
      }
    
      let total = 0;
      for (const tx of rawTxs) {
        if (tx.length < 66 || tx.length > 1232) {
          throw new Error(`invalid tx size: ${tx.length}`);
        }
        total += 2 + tx.length;
      }
      if (total > 19744) {
        throw new Error(`batch body too large: ${total}`);
      }
    
      const out = Buffer.allocUnsafe(total);
      let off = 0;
      for (const tx of rawTxs) {
        out.writeUInt16BE(tx.length, off);
        off += 2;
        Buffer.from(tx).copy(out, off);
        off += tx.length;
      }
      return out;
    }
    
    async function sendBatch(endpointBase, clientId, rawTxs) {
      const body = encodeBatch(rawTxs);
      const url = `${endpointBase}/api/sendBatch?c=${encodeURIComponent(clientId)}`;
    
      const res = await fetch(url, {
        method: "POST",
        headers: { "content-type": "application/octet-stream" },
        body,
      });
    
      if (!res.ok) {
        const text = await res.text();
        // Caller should handle possible partial success on some 4xx responses.
        throw new Error(`sendBatch failed: HTTP ${res.status}: ${text}`);
      }
    }
    curl -X POST \
      "https://YOUR_HOST/api/sendBatch?c=YOUR_CLIENT_ID" \
      -H "content-type: application/octet-stream" \
      --data-binary @batch.bin

    Jupiter Swap Example

    Github URL for Jupiter Swap Transactions.

    https://github.com/temporalxyz/nozomi-examples/blob/main/typescript/jup-swap-example/jup-api-v2.tsarrow-up-right

    CURL

    curl https://nozomi.temporal.xyz/api/sendTransaction2?c=<YOUR_API_KEY> \
      -X POST \
      -H "Content-Type: text/plain" \
      -d '<YOUR_BASE_64_ENCODED_TXN_BYTES>'

    JavaScript

    Use full service RPC for fetching latest blockhash. Nozomi only supports sendTransaction.

    Transaction Submission (API v2)

    Nozomi sends transactions through multiple channels to achieve best performance.

    hashtag
    sendTransaction2

    The /api/sendTransaction2 endpoint is not compatible with the Solana JSON-RPC sendTransaction method. Requests sent via the /api/sendTransaction2 endpoint from browser clients will see better performance, as this endpoint will skip the OPTIONS preflight request triggered by normal Solana JSON-RPC methods.

    The /api/sendTransaction2 endpoint does not return a transaction signature on success. A successful request will return an empty body with a 200 OK status code.

    hashtag
    Benefits

    • Eliminates CORS Preflight: Skips OPTIONS preflight requests that add 50-100ms latency

    • Faster Encoding: Base64 encoding/decoding is significantly faster than base58 operations

    • Reduced Body Size: Base64 encoding is more compact than base58 serialization used in JSON-RPC

    • Lower Bandwidth Usage: Smaller payloads reduce network transfer time and costs

    • Lower Network Overhead: Plain text payload avoids JSON parsing overhead

    hashtag
    How to Use

    Content-Type: text/plain HTTP Method: POST Body Format: "<YOUR_BASE_64_ENCODED_TXN_BYTES>"

    Just add API Key after ?c=<uuid> to get custom URL for sending.

    hashtag
    Endpoints (Regions)

    Auto Routed: https://nozomi.temporal.xyz/api/sendTransaction2?c=

    Direct HTTP:

    • PITT: http://pit1.nozomi.temporal.xyz/api/sendTransaction2?c=

    • TYO: http://tyo1.nozomi.temporal.xyz/api/sendTransaction2?c=

    • SGP: http://sgp1.nozomi.temporal.xyz/api/sendTransaction2?c=

    • EWR: http://ewr1.nozomi.temporal.xyz/api/sendTransaction2?c=

    • AMS: http://ams1.nozomi.temporal.xyz/api/sendTransaction2?c=

    • FRA: http://fra2.nozomi.temporal.xyz/api/sendTransaction2?c=

    Secure HTTPS:

    • PITT: https://pit1.nozomi.temporal.xyz/api/sendTransaction2?c=

    • TYO: https://tyo1.nozomi.temporal.xyz/api/sendTransaction2?c=

    • SGP: https://sgp1.nozomi.temporal.xyz/api/sendTransaction2?c=

    • EWR: https://ewr1.nozomi.temporal.xyz/api/sendTransaction2?c=

    • AMS: https://ams1.nozomi.temporal.xyz/api/sendTransaction2?c=

    • FRA: https://fra2.nozomi.temporal.xyz/api/sendTransaction2?c=

    Regional submission endpoints are in US East, Frankfurt, Amsterdam, Tokyo, and Singapore. All boxes are run with custom hardware modifications.

    import { Connection, PublicKey, Keypair, SystemProgram, TransactionMessage, VersionedTransaction } from "@solana/web3.js";
    
    const NOZOMI_ENDPOINT = "https://nozomi.temporal.xyz/?c=<YOUR_API_KEY>";
    const NOZOMI_TIP = new PublicKey("TEMPaMeCRFAS9EKF53Jd6KpHxgL47uWLcpFArU1Fanq");
    const MIN_TIP_AMOUNT = 1_000_000;
    
    const SOLANA_RPC_ENDPOINT = "https://api.mainnet-beta.solana.com";
    
    async function sendNozomiTxn(ixns, signer, nozomiRpcClient, solanaRpcClient) {
        const tipIxn = SystemProgram.transfer({
            fromPubkey: signer.publicKey,
            toPubkey: NOZOMI_TIP,
            lamports: MIN_TIP_AMOUNT
        });
        ixns.push(tipIxn);
    
        const { blockhash } = await solanaRpcClient.getLatestBlockhash();
    
        const messageV0 = new TransactionMessage({
            payerKey: signer.publicKey,
            recentBlockhash: blockhash,
            instructions: ixns,
        }).compileToV0Message();
    
        const versionedTxn = new VersionedTransaction(messageV0);
    
        versionedTxn.sign([signer]);
    
        return await nozomiRpcClient.sendTransaction(versionedTxn);
    }
    
    function buildIxns() {
        // your instruction building logic here..
        return [];
    }
    
    async function main() {
        const nozomiRpcClient = new Connection(NOZOMI_ENDPOINT);
    
        const solanaRpcClient = new Connection(SOLANA_RPC_ENDPOINT);
    
        // replace with actual keypair loading logic
        const signer = Keypair.generate();
    
        const ixns = buildIxns();
    
        const signature = await sendNozomiTxn(ixns, signer, nozomiRpcClient, solanaRpcClient);
    
        console.log(`Transaction sent with signature: ${signature}`);
    }
    
    main().catch(err => {
        console.error(err);
    });

    Rust

    Use full service RPC for fetching latest blockhash. Nozomi only supports sendTransaction.

    use solana_client::rpc_client::RpcClient;
    use solana_sdk::{message::Instruction, pubkey, pubkey::Pubkey, signature::Keypair, signer::Signer, transaction::Transaction};
    
    const NOZOMI_ENDPOINT: &str = "https://nozomi.temporal.xyz/?c=<YOUR_API_KEY>";
    const NOZOMI_TIP: Pubkey = pubkey!("TEMPaMeCRFAS9EKF53Jd6KpHxgL47uWLcpFArU1Fanq");
    const MIN_TIP_AMOUNT: u64 = 1_000_000;
    
    const SOLANA_RPC_ENDPOINT: &str = "https://api.mainnet-beta.solana.com";
    
    fn send_nozomi_txn(ixns: &mut Vec<Instruction>, signer: &Keypair, nozomi_rpc_client: &RpcClient, solana_rpc_client: &RpcClient) {
        let tip_ix = solana_system_interface::instruction::transfer(&signer.pubkey(), &NOZOMI_TIP, MIN_TIP_AMOUNT);
        ixns.push(tip_ix);
    
        let blockhash = solana_rpc_client.get_latest_blockhash().unwrap();
        let tx = Transaction::new_signed_with_payer(ixns, Some(&signer.pubkey()), &[signer], blockhash);
    
        nozomi_rpc_client.send_transaction(&tx).unwrap();
    }
    
    fn build_ixns() -> Vec<Instruction> {
        // your instruction building logic here..
        vec![]
    }
    
    fn main() {
        let nozomi_rpc_client = RpcClient::new(NOZOMI_ENDPOINT.to_string());
    
        let solana_rpc_client = RpcClient::new(SOLANA_RPC_ENDPOINT.to_string());
    
        let keypair = Keypair::new();
    
        let mut ixns = build_ixns();
    
        send_nozomi_txn(&mut ixns, &keypair, &nozomi_rpc_client, &solana_rpc_client);
    }

    CURL

    Please specify base64 encoding, Solana recognizes base58 as default. If you do not specify, you might get malformed transaction error

    curl https://nozomi.temporal.xyz/?c=<YOUR_API_KEY> \
      -X POST \
      -H "Content-Type: application/json" \
      -d '{
        "jsonrpc": "2.0",
        "id": 1,
        "method": "sendTransaction",
        "params": [
          "<YOUR_BASE_64_ENCODED_TXN_BYTES>",
          {
            "encoding": "base64"
          }
        ]
      }'

    Keeping Your TCP Connection Alive

    hashtag
    🔄 How Do I Keep the Connection Alive?

    To keep your TCP connection to our server alive and avoid reconnecting, you can periodically send a simple request to the /ping endpoint.


    hashtag
    Strategy

    The server supports persistent connections with a keep-alive timeout of 65 seconds. This means:

    • If your connection is idle for more than 65 seconds, it will be closed.

    • To keep it open, send any request before that timeout expires.

    • Each connection can send max 1000 requests.

    We recommend using the /ping endpoint:

    GET /ping

    This endpoint is lightweight, fast, and designed specifically to help maintain your connection.


    hashtag
    Suggested Interval

    Send a request to /ping every 60 seconds to keep the connection alive reliably.

    Example:


    hashtag
    ⚠️ Notes

    • This is not a health check — it's just a way to prevent idle disconnects

    • Avoid pinging more often than needed

    Go

    Use full service RPC for fetching latest blockhash.

    while true; do
      curl -s http://nozomi.temporal.xyz/ping > /dev/null
      sleep 60
    done
    package main
    
    import (
    	"bytes"
    	"context"
    	"encoding/base64"
    	"fmt"
    	"io"
    	"net/http"
    
    	"github.com/gagliardetto/solana-go"
    	"github.com/gagliardetto/solana-go/programs/system"
    	"github.com/gagliardetto/solana-go/rpc"
    )
    
    const (
    	NOZOMI_ENDPOINT     = "https://nozomi.temporal.xyz/api/sendTransaction2?c=<YOUR_API_KEY>"
    	NOZOMI_TIP          = "TEMPaMeCRFAS9EKF53Jd6KpHxgL47uWLcpFArU1Fanq"
    	MIN_TIP_AMOUNT      = 1_000_000
    	SOLANA_RPC_ENDPOINT = "https://api.mainnet-beta.solana.com"
    )
    
    func sendNozomiTx(
    	ctx context.Context,
    	ixns []solana.Instruction,
    	signer solana.PrivateKey,
    	nozomiEndpoint string,
    	solanaRpcClient *rpc.Client,
    ) error {
    	nozomiTipPubkey := solana.MustPublicKeyFromBase58(NOZOMI_TIP)
    	tipIxn := system.NewTransferInstruction(
    		MIN_TIP_AMOUNT,
    		signer.PublicKey(),
    		nozomiTipPubkey,
    	).Build()
    	ixns = append(ixns, tipIxn)
    
    	recentBlockhash, err := solanaRpcClient.GetLatestBlockhash(ctx, rpc.CommitmentFinalized)
    	if err != nil {
    		return fmt.Errorf("failed to get latest blockhash: %w", err)
    	}
    
    	tx, err := solana.NewTransaction(
    		ixns,
    		recentBlockhash.Value.Blockhash,
    		solana.TransactionPayer(signer.PublicKey()),
    	)
    	if err != nil {
    		return fmt.Errorf("failed to create transaction: %w", err)
    	}
    
    	_, err = tx.Sign(func(key solana.PublicKey) *solana.PrivateKey {
    		if key.Equals(signer.PublicKey()) {
    			return &signer
    		}
    		return nil
    	})
    	if err != nil {
    		return fmt.Errorf("failed to sign transaction: %w", err)
    	}
    
    	txBytes, err := tx.MarshalBinary()
    	if err != nil {
    		return fmt.Errorf("failed to marshal transaction: %w", err)
    	}
    
    	txBase64 := base64.StdEncoding.EncodeToString(txBytes)
    
    	req, err := http.NewRequestWithContext(ctx, http.MethodPost, nozomiEndpoint, bytes.NewBufferString(txBase64))
    	if err != nil {
    		return fmt.Errorf("failed to create request: %w", err)
    	}
    
    	req.Header.Set("Content-Type", "text/plain")
    
    	client := &http.Client{}
    	resp, err := client.Do(req)
    	if err != nil {
    		return fmt.Errorf("failed to send transaction: %w", err)
    	}
    	defer resp.Body.Close()
    
    	// api v2 does not return a signature, just check for success
    	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
    		body, _ := io.ReadAll(resp.Body)
    		return fmt.Errorf("transaction failed with status %d: %s", resp.StatusCode, string(body))
    	}
    
    	fmt.Println("Transaction sent successfully")
    	return nil
    }
    
    func buildIxns() []solana.Instruction {
    	// your instruction building logic here..
    	return []solana.Instruction{}
    }
    
    func main() {
    	ctx := context.Background()
    
    	solanaRpcClient := rpc.New(SOLANA_RPC_ENDPOINT)
    
    	// replace with actual keypair loading logic
    	signer := solana.NewWallet()
    
    	ixns := buildIxns()
    
    	err := sendNozomiTx(ctx, ixns, signer.PrivateKey, NOZOMI_ENDPOINT, solanaRpcClient)
    	if err != nil {
    		panic(err)
    	}
    }

    Transaction Submission (JSON-RPC)

    Nozomi sends transactions through multiple channels to achieve best performance.

    hashtag
    sendTransaction

    The Nozomi transaction submission endpoint supports the `sendTransaction` Solana JSON-RPC method. Just insert the URL where you would place a RPC URL.

    Transactions are sent through 1) Self hosted nodes 2) Staked connections and 3) Jito bundles.

    hashtag
    Auto Routed Endpoint

    https://nozomi.temporal.xyz/?c=

    hashtag
    Regioned Endpoints

    hashtag
    Direct HTTP:

    PITT:

    TYO:

    SGP:

    EWR:

    AMS:

    FRA:

    hashtag
    Secure HTTPS:

    PITT:

    TYO:

    SGP:

    EWR:

    AMS:

    FRA:

    HTTP POST Body

    Just add API Key after ?c=<uuid> to get custom URL for sending.

    Regional submission endpoints are in US East, Frankfurt, Amsterdam, Singapore and Tokyo.

    All boxes are run with custom hardware modifications.

    Please specify base64 encoding.

    http://pit1.nozomi.temporal.xyz/?c=arrow-up-right
    http://tyo1.nozomi.temporal.xyz/?c=arrow-up-right
    http://sgp1.nozomi.temporal.xyz/?c=arrow-up-right
    http://ewr1.nozomi.temporal.xyz/?c=arrow-up-right
    http://ams1.nozomi.temporal.xyz/?c=arrow-up-right
    http://fra2.nozomi.temporal.xyz/?c=arrow-up-right
    https://pit1.nozomi.temporal.xyz/?c=arrow-up-right
    http://tyo1.nozomi.temporal.xyz/?c=arrow-up-right
    http://sgp1.nozomi.temporal.xyz/?c=arrow-up-right
    https://ewr1.nozomi.temporal.xyz/?c=arrow-up-right
    https://ams1.nozomi.temporal.xyz/?c=arrow-up-right
    http://fra2.nozomi.temporal.xyz/?c=arrow-up-right
    {
        "jsonrpc": "2.0",
        "id": 1,
        "method": "sendTransaction",
        "params": [ 
            "<YOUR_BASE_64_ENCODED_TXN_BYTES>",
            { "encoding": "base64" }
        ] 
    }

    Jupiter Swap Example

    Github URL for Jupiter Swap Transactions.

    https://github.com/temporalxyz/nozomi-examples/blob/main/typescript/jup-swap-example/jup-json-rpc.tsarrow-up-right

    JavaScript

    Use full service RPC for fetching latest blockhash.

    import { Connection, PublicKey, Keypair, SystemProgram, TransactionMessage, VersionedTransaction } from "@solana/web3.js";
    
    const NOZOMI_ENDPOINT = "https://nozomi.temporal.xyz/api/sendTransaction2?c=<YOUR_API_KEY>";
    const NOZOMI_TIP = new PublicKey("TEMPaMeCRFAS9EKF53Jd6KpHxgL47uWLcpFArU1Fanq");
    const MIN_TIP_AMOUNT = 1_000_000;
    
    const SOLANA_RPC_ENDPOINT = "https://api.mainnet-beta.solana.com";
    
    async function sendNozomiTxn(ixns, signer, nozomiEndpoint, solanaRpcClient) {
        const tipIxn = SystemProgram.transfer({
            fromPubkey: signer.publicKey,
            toPubkey: NOZOMI_TIP,
            lamports: MIN_TIP_AMOUNT
        });
        ixns.push(tipIxn);
    
        const { blockhash } = await solanaRpcClient.getLatestBlockhash();
    
        const messageV0 = new TransactionMessage({
            payerKey: signer.publicKey,
            recentBlockhash: blockhash,
            instructions: ixns,
        }).compileToV0Message();
    
        const versionedTxn = new VersionedTransaction(messageV0);
        versionedTxn.sign([signer]);
    
        const txnBytes = versionedTxn.serialize();
        const txnBase64 = Buffer.from(txnBytes).toString('base64');
    
        const response = await fetch(nozomiEndpoint, {
            method: 'POST',
            headers: {
                'Content-Type': 'text/plain',
            },
            body: txnBase64
        });
    
        if (!response.ok) {
            const errorText = await response.text();
            throw new Error(`Transaction failed with status ${response.status}: ${errorText}`);
        }
    
        // api v2 does not return a signature, just check for success
        console.log('Transaction sent successfully');
    }
    
    function buildIxns() {
        // your instruction building logic here..
        return [];
    }
    
    async function main() {
        const solanaRpcClient = new Connection(SOLANA_RPC_ENDPOINT);
    
        // replace with actual keypair loading logic
        const signer = Keypair.generate();
    
        const ixns = buildIxns();
    
        await sendNozomiTxn(ixns, signer, NOZOMI_ENDPOINT, solanaRpcClient);
    }
    
    main().catch(err => {
        console.error(err);
    });

    Python

    Use full service RPC for fetching latest blockhash.

    import aiohttp
    import asyncio
    import base64
    
    from typing import List
    
    from solders.pubkey import Pubkey
    from solders.keypair import Keypair
    from solders.instruction import Instruction
    from solders.transaction import Transaction
    from solders.system_program import transfer, TransferParams
    from solders.hash import Hash
    
    from solana.rpc.async_api import AsyncClient
    
    NOZOMI_ENDPOINT = "https://nozomi.temporal.xyz/api/sendTransaction2?c=<YOUR_API_KEY>"
    NOZOMI_TIP = Pubkey.from_string("TEMPaMeCRFAS9EKF53Jd6KpHxgL47uWLcpFArU1Fanq")
    MIN_TIP_AMOUNT = 1_000_000
    
    SOLANA_RPC_ENDPOINT = "https://api.mainnet-beta.solana.com"
    
    async def send_nozomi_txn(
        ixns: List[Instruction],
        signer: Keypair,
        nozomi_endpoint: str,
        solana_rpc_client: AsyncClient
    ) -> None:
        tip_ixn = transfer(TransferParams(
            from_pubkey=signer.pubkey(),
            to_pubkey=NOZOMI_TIP,
            lamports=MIN_TIP_AMOUNT
        ))
        ixns.append(tip_ixn)
    
        blockhash_resp = await solana_rpc_client.get_latest_blockhash()
        blockhash = blockhash_resp.value.blockhash
    
        txn = Transaction.new_signed_with_payer(
            ixns,
            signer.pubkey(),
            [signer],
            blockhash
        )
    
        txn_bytes = bytes(txn)
        txn_base64 = base64.b64encode(txn_bytes).decode('utf-8')
    
        async with aiohttp.ClientSession() as session:
            async with session.post(
                nozomi_endpoint,
                headers={"Content-Type": "text/plain"},
                data=txn_base64
            ) as response:
                # api v2 does not return a signature, just check for success
                if response.status >= 200 and response.status < 300:
                    print("Transaction sent successfully")
                else:
                    error_text = await response.text()
                    raise Exception(f"Transaction failed with status {response.status}: {error_text}")
    
    def build_ixns() -> List[Instruction]:
        # your instruction building logic here..
        return []
    
    async def main():
        solana_rpc_client = AsyncClient(SOLANA_RPC_ENDPOINT)
    
        # replace with actual keypair loading logic
        signer = Keypair()
    
        ixns = build_ixns()
    
        await send_nozomi_txn(ixns, signer, NOZOMI_ENDPOINT, solana_rpc_client)
    
    if __name__ == "__main__":
        asyncio.run(main())

    Go

    Made by a wonderful community member.

    https://github.com/weeaa/tempgoralarrow-up-right

    Python

    Use full service RPC for fetching latest blockhash.. Nozomi only supports sendTransaction.

    import asyncio
    
    from typing import List
    
    from solders.pubkey import Pubkey
    from solders.keypair import Keypair
    from solders.signature import Signature
    from solders.instruction import Instruction
    from solana.transaction import Transaction
    from solders.system_program import transfer, TransferParams
    
    from solana.rpc.async_api import AsyncClient
    
    NOZOMI_ENDPOINT = "https://nozomi.temporal.xyz/?c=<YOUR_API_KEY>"
    NOZOMI_TIP = Pubkey.from_string("TEMPaMeCRFAS9EKF53Jd6KpHxgL47uWLcpFArU1Fanq")
    MIN_TIP_AMOUNT = 1_000_000
    
    SOLANA_RPC_ENDPOINT = "https://api.mainnet-beta.solana.com"
    
    async def send_nozomi_txn(ixns: List[Instruction], signer: Keypair, nozomi_rpc_client: AsyncClient, solana_rpc_client: AsyncClient) -> Signature:
        tip_ixn = transfer(TransferParams(
            from_pubkey=signer.pubkey(),
            to_pubkey=NOZOMI_TIP,
            lamports=MIN_TIP_AMOUNT
        ))
        ixns.append(tip_ixn)
    
        blockhash = (await solana_rpc_client.get_latest_blockhash()).value.blockhash
        txn = Transaction()
    
        for ixn in ixns:
            txn.add(ixn)
    
        # solanapy does not expose an encoding option via TxOpts
        return (await nozomi_rpc_client.send_transaction(txn, signer, recent_blockhash=blockhash)).value
    
    def build_ixns() -> List[Instruction]:
        # your instruction building logic here..
        return []
    
    async def main():
        nozomi_rpc_client = AsyncClient(NOZOMI_ENDPOINT)
    
        solana_rpc_client = AsyncClient(SOLANA_RPC_ENDPOINT)
    
        # replace with actual keypair loading logic
        signer = Keypair()
    
        ixns = build_ixns()
    
        signature = await send_nozomi_txn(ixns, signer, nozomi_rpc_client, solana_rpc_client)
    
        print(f"Transaction sent with signature: {signature}")
    
    if __name__ == "__main__":
        asyncio.run(main())

    TypeScript

    Use full service RPC for fetching latest blockhash.

    import { Connection, PublicKey, Keypair, TransactionInstruction, SystemProgram, TransactionMessage, VersionedTransaction } from "@solana/web3.js";
    
    const NOZOMI_ENDPOINT = "https://nozomi.temporal.xyz/api/sendTransaction2?c=<YOUR_API_KEY>";
    const NOZOMI_TIP = new PublicKey("TEMPaMeCRFAS9EKF53Jd6KpHxgL47uWLcpFArU1Fanq");
    const MIN_TIP_AMOUNT = 1_000_000;
    
    const SOLANA_RPC_ENDPOINT = "https://api.mainnet-beta.solana.com";
    
    async function sendNozomiTxn(
        ixns: TransactionInstruction[],
        signer: Keypair,
        nozomiEndpoint: string,
        solanaRpcClient: Connection
    ): Promise<void> {
        const tipIxn = SystemProgram.transfer({
            fromPubkey: signer.publicKey,
            toPubkey: NOZOMI_TIP,
            lamports: MIN_TIP_AMOUNT
        });
        ixns.push(tipIxn);
    
        const { blockhash } = await solanaRpcClient.getLatestBlockhash();
    
        const messageV0 = new TransactionMessage({
            payerKey: signer.publicKey,
            recentBlockhash: blockhash,
            instructions: ixns,
        }).compileToV0Message();
    
        const versionedTxn = new VersionedTransaction(messageV0);
        versionedTxn.sign([signer]);
    
        const txnBytes = versionedTxn.serialize();
        const txnBase64 = Buffer.from(txnBytes).toString('base64');
    
        const response = await fetch(nozomiEndpoint, {
            method: 'POST',
            headers: {
                'Content-Type': 'text/plain',
            },
            body: txnBase64
        });
    
        if (!response.ok) {
            const errorText = await response.text();
            throw new Error(`Transaction failed with status ${response.status}: ${errorText}`);
        }
    
        // api v2 does not return a signature, just check for success
        console.log('Transaction sent successfully');
    }
    
    function buildIxns(): TransactionInstruction[] {
        // your instruction building logic here..
        return [];
    }
    
    async function main() {
        const solanaRpcClient = new Connection(SOLANA_RPC_ENDPOINT);
    
        // replace with actual keypair loading logic
        const signer = Keypair.generate();
    
        const ixns = buildIxns();
    
        await sendNozomiTxn(ixns, signer, NOZOMI_ENDPOINT, solanaRpcClient);
    }
    
    main().catch(err => {
        console.error(err);
    });

    Rust

    Use full service RPC for fetching latest blockhash.

    
    use solana_client::rpc_client::RpcClient;
    use solana_sdk::{message::Instruction, pubkey, pubkey::Pubkey, signature::Keypair, signer::Signer, transaction::Transaction};
    use base64::{Engine as _, engine::general_purpose};
    
    const NOZOMI_ENDPOINT: &str = "https://nozomi.temporal.xyz/api/sendTransaction2?c=<YOUR_API_KEY>";
    const NOZOMI_TIP: Pubkey = pubkey!("TEMPaMeCRFAS9EKF53Jd6KpHxgL47uWLcpFArU1Fanq");
    const MIN_TIP_AMOUNT: u64 = 1_000_000;
    
    const SOLANA_RPC_ENDPOINT: &str = "https://api.mainnet-beta.solana.com";
    
    fn send_nozomi_txn(
        ixns: &mut Vec<Instruction>,
        signer: &Keypair,
        nozomi_endpoint: &str,
        solana_rpc_client: &RpcClient
    ) -> Result<(), Box<dyn std::error::Error>> {
        let tip_ixn = solana_system_interface::instruction::transfer(
            &signer.pubkey(),
            &NOZOMI_TIP,
            MIN_TIP_AMOUNT
        );
        ixns.push(tip_ixn);
    
        let blockhash = solana_rpc_client.get_latest_blockhash()?;
        let txn = Transaction::new_signed_with_payer(
            ixns,
            Some(&signer.pubkey()),
            &[signer],
            blockhash
        );
    
        let txn_bytes = bincode::serialize(&txn)?;
    
        let txn_base64 = general_purpose::STANDARD.encode(&txn_bytes);
    
        let client = reqwest::blocking::Client::new();
        let response = client
            .post(nozomi_endpoint)
            .header("Content-Type", "text/plain")
            .body(txn_base64)
            .send()?;
    
        // api v2 does not return a signature, just check for success
        if response.status().is_success() {
            Ok(())
        } else {
            Err(Box::new(response.error_for_status().unwrap_err()))
        }
    }
    
    fn build_ixns() -> Vec<Instruction> {
        // your instruction building logic here..
        vec![]
    }
    
    fn main() {
        let solana_rpc_client = RpcClient::new(SOLANA_RPC_ENDPOINT.to_string());
    
        // replace with actual keypair loading logic
        let signer = Keypair::new();
    
        let mut ixns = build_ixns();
    
        if send_nozomi_txn(
            &mut ixns,
            &signer,
            NOZOMI_ENDPOINT,
            &solana_rpc_client
        ).is_ok() {
            println!("Transaction sent successfully");
        }
    }