# Introducing Shyft

Full-suite Solana Development Experience

> Our mission is to accelerate Solana adoption by lowering the entry barrier for developers. We do this by providing the necessary dev tools and improving the overall DevEx.

### What does Shyft offer?

* <mark style="color:yellow;">Solana RPCs</mark>
* <mark style="color:yellow;">Region specific gRPC Network</mark>
* <mark style="color:yellow;">Region specific Jupiter V6 Swap API</mark>
* <mark style="color:yellow;">Human-Readable Transaction APIs</mark>
* <mark style="color:yellow;">Callbacks ( parsed Solana webhooks)</mark>
* <mark style="color:yellow;">Defi APIs</mark>
* <mark style="color:yellow;">SuperIndexer, graphQL for Solana data</mark>
* <mark style="color:yellow;">Dedicated RPC Nodes</mark>

We also pride ourselves in providing the most extensive set of open-source community tools and code samples, which actually works. You can find them on our [<mark style="color:yellow;">Github</mark>](https://github.com/Shyft-to).

{% embed url="<https://github.com/Shyft-to>" %}


# Start Building

Unlock your super powers and just ship it!

## Step 1: Get an API key

{% embed url="<https://shyft.to/get-api-key>" %}
Get your API key from this link
{% endembed %}

## Step 2: Use Shyft Infrastructure

Multiple ways to interact with Shyft

{% embed url="<https://api.shyft.to/sol/api/explore/>" %}
Link to Swagger UI for easy API access
{% endembed %}

{% embed url="<https://documenter.getpostman.com/view/18419720/UzQvt5Kf>" %}
Fork our Postman collection
{% endembed %}

{% embed url="<https://www.npmjs.com/package/@shyft-to/js>" %}
TS SDK for easy development
{% endembed %}


# Shyft RPCs

Reliable, fast and cost-efficient

RPCs are the gateway to blockchains. They enable developers and users to interact with the Solana blockchain by making requests to the network. These requests can include querying blockchain data, submitting transactions, and more.

A standard Solana node handles this through one monolithic process: the same software doing account lookups, tracking ledger/transaction history, and streaming updates, all sharing the same resources. Under load, one gets slow, they all get slow.

Shyft takes a different approach: <mark style="color:yellow;">decouple</mark> the three things an RPC actually does, <mark style="color:yellow;">rebuild it from the ground up</mark>, and <mark style="color:yellow;">optimize</mark> each independentl&#x79;**.**

<mark style="color:$primary;">→</mark> **Account state:** Reading current on-chain data (`getProgramAccounts`, `getAccountInfo`). Instead of scanning raw state on every call like a standard node, our proprietary **Rust-based accounts engine** indexes account state separately, so reads resolve in single-digit milliseconds instead of seconds.

<mark style="color:$primary;">→</mark> **Ledger / transaction history:** Serving blocks, transactions, and signature lookups. Powered by our own transaction engine, purpose-built for this data instead of relying on the standard RPC's general-purpose query path, which is what makes `getTransactionsForAddress` possible as a single call.

<mark style="color:$primary;">→</mark> **Streaming:** Real-time updates as they happen on-chain, through RabbitStream and Yellowstone gRPC. Both are under continuous improvement, including plugin-level work, to push latency lower.

Each piece is built and scaled on its own - so a spike in one doesn't degrade the others, and each can be optimized for exactly what it does instead of being a generalist doing three jobs at once.

Shyft RPCs are built with speed and reliability in mind, plus the most cost-efficient way of accessing Solana.

To access Shyft RPCs, [<mark style="color:red;">get an API key</mark>](https://shyft.to/get-api-key) and start interacting with the fastest chain in town, Solana.

{% embed url="<https://shyft.to/get-api-key>" fullWidth="false" %}
Get your Shyft API key from this link
{% endembed %}

<mark style="color:yellow;">**Mainnet RPC**</mark> : **<https://rpc.shyft.to/?api\\_key={your\\_api\\_key}>**

<mark style="color:yellow;">**Devnet**</mark> <mark style="color:yellow;">**RPC**</mark>: **<https://devnet-rpc.shyft.to/?api\\_key={your\\_api\\_key}>**

***

### Quick Start

{% stepper %}
{% step %}

### Sign up to Shyft

Go to [<mark style="color:yellow;">Shyft Website</mark>](https://shyft.to/) and click on the [<mark style="color:yellow;">"Get API Key"</mark>](https://dashboard.shyft.to/get-api-key) Button

<figure><img src="/files/OMdDc96R64oZcAC9nsw7" alt=""><figcaption></figcaption></figure>

{% endstep %}

{% step %}

### Get your RPC URL&#x20;

Log in — your dashboard will show your RPC URL

<figure><img src="/files/n6US5xALFNgARchTpRKt" alt=""><figcaption></figcaption></figure>

{% endstep %}

{% step %}

### Make a Request

Your RPC URL will look like this:\
`https://rpc.shyft.to/?api_key={your_api_key}`

Copy the cURL request below into Postman (or your terminal) and replace the URL with your own RPC URL (or only the key part), or alternatively, use the script below with your RPC URL to make the request:

{% tabs %}
{% tab title="cURL" %}
{% code overflow="wrap" %}

```bash
curl --location 'https://rpc.shyft.to/?api_key=YOUR-API-KEY' \
--header 'Content-Type: application/json' \
--data '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getSlot"
}'
```

{% endcode %}
{% endtab %}

{% tab title="JavaScript" %}
{% code overflow="wrap" %}

```javascript
const response = await fetch('https://rpc.shyft.to/?api_key=YOUR-API-KEY', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    jsonrpc: '2.0',
    id: 1,
    method: 'getSlot'
  })
});

const data = await response.json();
console.log(data);
```

{% endcode %}
{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

***

### Key Features

#### **Accelerated getProgramAccounts**

Standard `getProgramAccounts` scans raw account state on every call - slow by design, worse under load. Shyft's accelerated version, powered by proprietary Rust-based accounts engine, sub-10ms on covered programs resolves the most <mark style="color:yellow;">common queries in under 10ms</mark>, same method, same parameters, no code changes.

<mark style="color:$primary;">→</mark> **Covers 10+ program/offset combinations** across Raydium, Meteora, Orca, Pump.fun and more.

<mark style="color:$primary;">→</mark> Falls through to standard RPC transparently if your query isn't in the accelerated set.

<mark style="color:$primary;">→</mark> New programs added on request, no downtime.

[<mark style="color:yellow;">**Full Accelerated gPA Docs →**</mark>](/solana/accelerated-getprogramaccounts)

#### **getTransactionsForAddress**

Fetching an address's transaction history normally takes two calls - `getSignaturesForAddress`, then `getTransaction` per signature - plus manual pagination and filtering on your end. `getTransactionsForAddress` <mark style="color:yellow;">collapses that into one request</mark>, with slot/status/token-account filtering handled server-side.

<mark style="color:$primary;">→</mark> Single call, signature-level or complete transaction payloads.

<mark style="color:$primary;">→</mark> Server-side filters: slot, status, token accounts.

<mark style="color:$primary;">→</mark> 2 epochs of history available.

[<mark style="color:yellow;">**Full getTransactionsForAddress Docs →**</mark>](/solana/get-transactions-for-address)

{% hint style="info" %}
Please note that transaction history is currently available upto 3-4 days.&#x20;
{% endhint %}

#### **Globally Distributed, Geo-Routed & Multi-Region Failover**

Geo DNS automatically routes every call to the nearest of our 5 regional clusters - <mark style="color:yellow;">NY, VA, Fra, Ams, Sgp</mark>. Calls route to the nearest gateway automatically. If a node lags or goes down, traffic fails over to the backup pool - no dropped requests, no manual region switching.

#### **Unlimited RPC Credits**

No credit counting, no upper limits, no overages. One flat rate, every call included - predictable bills every month, whether you're making a thousand calls or a million.

***

### Supported RPC Methods

Shyft RPC supports the full set of standard Solana JSON-RPC methods over HTTP and WebSocket, plus commitment-level controls for balancing speed and safety.

[<mark style="color:yellow;">**View all HTTP methods →**</mark>](/solana/rpc-calls/http)

[<mark style="color:yellow;">**View all WebSocket methods →**</mark>](/solana/rpc-calls/solana-websockets)

***

### Dedicated RPC Nodes

For teams with high-volume or latency-sensitive requirements, Shyft offers fault-tolerant dedicated nodes - isolated infrastructure, not shared capacity at the best pricing possible.

<mark style="color:$primary;">→</mark> Starting from $1,800/month

<mark style="color:$primary;">→</mark> <mark style="color:yellow;">Fallback mechanism included</mark> - your requests automatically route to a backup cluster if your node lags, goes down, or needs an upgrade

<mark style="color:$primary;">→</mark> Gen5 AMD CPUs, built for <mark style="color:yellow;">consistent low-latency</mark> performance

<mark style="color:$primary;">→</mark> Our proprietary <mark style="color:yellow;">Rust-based accounts engine is also supported</mark> on your dedicated node, bringing the same sub-10ms Accelerated gPA performance to your isolated infrastructure

Get in touch with us on [<mark style="color:yellow;">Discord</mark>](https://discord.com/invite/8JyZCjRPmr) or book a call with us [<mark style="color:yellow;">here</mark>](https://calendly.com/shyft-dev/lets-talk)<mark style="color:yellow;">.</mark>&#x20;

***

### Pricing

No credits, no bandwidth metering, no overage invoices. One flat rate - stream and query as much as you need, whether it's a quiet Sunday or a Pump.fun launch at 3am.

<mark style="color:$primary;">→</mark> **Unlimited RPC calls** - no per-call credits, no rate throttling on usage

<mark style="color:$primary;">→</mark> **Predictable billing** - one price, every month, regardless of volume

<mark style="color:$primary;">→</mark> **Custom/Enterprise** - for larger volume or bespoke requirements, reach out on Discord

[<mark style="color:yellow;">View full pricing →</mark>](https://shyft.to/solana-rpc-grpc-pricing)

***

### Frequently Asked Questions

<details>

<summary>Is Shyft RPC compatible with standard Solana RPC methods?</summary>

Yes. Shyft RPC supports the full set of standard Solana JSON-RPC methods over HTTP and WebSocket — it's a drop-in replacement, no SDK or code changes required.

</details>

<details>

<summary>How is Shyft RPC different from a standard Solana node?</summary>

Shyft RPC is built on custom infra from the ground up, not a standard node. This powers accelerated methods like `getProgramAccounts` — via our proprietary Rust-based accounts engine (sub-10ms on covered programs) — and `getTransactionsForAddress` (single call instead of two), plus geo-routing and staked endpoints for better transaction landing.

</details>

<details>

<summary>Do I get charged per RPC call?</summary>

Depends on your plan. On Hack, Launch, and Scale, each RPC call uses 1 credit from your plan's allotment — Launch and Scale allow overages once you exceed it, Hack does not. Build, Grow, and Accelerate are credit-less — no per-call counting, no overages, one flat rate regardless of call volume. [View pricing →](https://shyft.to/solana-rpc-grpc-pricing)

</details>

<details>

<summary>What is Accelerated getProgramAccounts?</summary>

Our proprietary Rust-based accounts engine that resolves the most common `getProgramAccounts` queries in under 10ms instead of the seconds a standard scan takes — same method, same parameters, no code changes. [Learn more →](https://docs.shyft.to/solana/accelerated-getprogramaccounts)

</details>

<details>

<summary>What does getTransactionsForAddress do?</summary>

It replaces the standard `getSignaturesForAddress` + `getTransaction` + manual pagination workflow with a single call, with server-side filtering by slot, status, and token accounts. [Learn more →](https://docs.shyft.to/solana/get-transactions-for-address)

</details>

<details>

<summary>What are staked endpoints, and why do they matter?</summary>

Staked endpoints run on infrastructure that validators prioritize under network load, giving your transactions a better chance of landing during congestion — not just faster reads. This matters most for trading bots and time-sensitive transactions.

</details>

<details>

<summary>Is Shyft RPC SWQoS-enabled?</summary>

Yes. Shyft's staked endpoints route through stake-weighted connections to validators, so your transactions get prioritized lanes instead of competing in the unstaked queue — the same mechanism as SWQoS, giving you better landing rates during network congestion without any extra configuration on your end.

</details>

<details>

<summary>How much stake does Shyft have, and does that matter?</summary>

SWQoS bandwidth isn't allocated as a flat "staked vs. not" split — validators typically reserve the majority of transaction lanes for staked connections, but within that pool, priority is proportional to the amount of stake behind the connection. So it's not just about being staked, it's about how much stake is backing the RPC you're sending through — a connection backed by more stake gets a larger share of that prioritized bandwidth, especially under congestion when everyone in the staked lane is competing for the same leader. That's the reasoning behind why Shyft's staked endpoints improve landing rates — you're not just getting past the unstaked queue, you're getting proportional priority within it.

</details>

<details>

<summary>How can I use durable nonces to improve transaction landing rates?</summary>

A durable nonce replaces the normal recent-blockhash requirement with a nonce account, so your transaction stays valid indefinitely instead of expiring after \~60-90 seconds. This is especially useful when broadcasting the same signed transaction across multiple RPC providers at once — since the transaction doesn't expire, you can fire it to Shyft and other RPCs in parallel and let whichever lands first win, without worrying about blockhash mismatches invalidating the others. It's a common pattern for time-sensitive submissions where landing matters more than which specific RPC gets credit.

</details>

<details>

<summary>Which regions does Shyft RPC run in?</summary>

Shyft RPC runs across 5 regions — NY, VA, Fra, Ams, Sgp — with Geo DNS automatically routing your calls to the nearest cluster and automatic failover if a node lags or goes down.

</details>

<details>

<summary>Does Shyft offer dedicated RPC nodes?</summary>

Yes, for teams with high-volume or latency-sensitive needs, starting from $1,800/month, with automatic failover to a backup cluster included, and the option to enable our proprietary Rust-based accounts engine for Accelerated gPA performance on your dedicated node. [Get in touch →](https://calendly.com/shyft-dev/lets-talk)

</details>

<details>

<summary>Why am I getting rate limited (429)?</summary>

Shyft applies separate rate limits for normal RPC calls, index calls, and `sendTransaction` — each has its own threshold, so hitting one doesn't mean you're capped on the others. If you're seeing 429s, check which call type is triggering it and see the full breakdown of limits per plan. View rate limits →

</details>

<details>

<summary>Why am I getting rate limited (429) even though I'm within my plan limits?</summary>

Your plan limit is a ceiling, not a guarantee against 429s — normal RPC calls, index calls, and `sendTransaction` each enforce their own separate threshold, typically on a per-second basis rather than just a total. So you can be well under your overall monthly/plan allowance and still get 429'd if one specific call type bursts past its own limit in a short window — for example, firing a batch of index calls back-to-back even though your total request count for the day is low. Check which call type is triggering the 429 and pace or batch those specifically. View rate limits →

</details>


# Solana RPC Methods

Interact with Solana nodes directly using HTTP and WebSocket-based JSON RPC methods.

#### **State Commitment Configuration Summary**

Solana nodes use a **commitment level** set by the client to decide which bank state to query during preflight checks and transaction processing. Commitment levels reflect how finalized a block is and affect how likely that state is to change.

**Available commitment levels (from most to least finalized):**

* **finalized**: Block confirmed by a supermajority and considered final (maximum lockout).
* **confirmed**: Block directly voted on by a supermajority, based on gossip and replay; supports optimistic confirmation.
* **processed**: Most recent block seen by the node; may be skipped by the cluster.

**Recommendations:**

* Use **confirmed** for processing dependent transactions (balance of speed and safety).
* Use **finalized** for maximum safety against rollback.
* **Default** is **finalized** if no commitment is specified.
* Only API methods that query bank state accept the `commitment` parameter, as indicated in the API reference.

#### **RPC Response Structure**

Many methods that take a commitment parameter return an RpcResponse JSON object comprised of two parts:

* `context` : An RpcResponseContext JSON structure including a `slot` field at which the operation was evaluated.
* `value` : The value returned by the operation itself.

#### **Parsed Responses**

Some methods support an `encoding` parameter, and can return account or instruction data in parsed JSON format if `"encoding":"jsonParsed"` is requested and the node has a parser for the owning program.&#x20;

#### **Filter Criteria Summary**

Some RPC methods allow a `filters` object to pre-filter program account data returned in the response.

**Supported filters:**

* **memcmp**: Compares a specific byte sequence at a given offset within the account data.
  * `offset` *(usize)*: Position in the data to begin comparison.
  * `bytes` *(string)*: The byte sequence to match (encoded).
  * `encoding` *(string)*: `"base58"` or `"base64"` encoding.

    > ⚠️ `base64` support is only available in **solana-core v1.14.0+**. Omit this field when querying older nodes.
* **dataSize** *(u64)*: Matches accounts with a specific data length.

These filters help reduce unnecessary data by only returning accounts that meet the specified criteria.


# HTTP Methods

Make on-demand requests to Solana nodes using standard HTTP calls—ideal for fetching account data, transactions, and blockchain state with simplicity and reliability.

### Shyft RPC docs

Learn how to use Solana RPC methods with real-world examples, code snippets, and best practices. Understand request parameters, response formats, and when to use each method for efficient blockchain development.

### Account & Balance Methods

Solana's Core RPC methods to fetch Solana account state, token info, and wallet balances.

* [getAccountInfo](/solana/rpc-calls/http/getaccountinfo) – fetch the full on-chain data and lamport balance of any account.
* [getBalance](/solana/rpc-calls/http/getbalance) – fetch the current balance of a specific account.
* [getMultipleAccounts](/solana/rpc-calls/http/getmultipleaccounts) – Fetch data for multiple accounts in a single call. (Similar to getAccountInfo but for multiple accounts)
* [getProgramAccounts](/solana/rpc-calls/http/getprogramaccounts) – Find all accounts owned by a specific on-chain program.
* [getSupply](/solana/rpc-calls/http/getsupply) – Returns information about the current total supply of SOL, including circulating and non-circulating tokens.
*

### Token Account Methods

Work with SPL tokens on Solana using these essential RPC methods.

* [getTokenAccountsByOwner](/solana/rpc-calls/http/gettokenaccountbyowner) – Fetch all SPL token accounts owned by a specific wallet address.
* [getTokenLargestAccounts](/solana/rpc-calls/http/gettokenlargestaccount) – Retrieve the largest accounts holding a given SPL token — useful for analyzing token concentration and top holders.
* [getTokenAccountsByDelegate](/solana/rpc-calls/http/gettokenaccountbydelegate) – Get all token accounts where a specific delegate is authorized to manage tokens on behalf of others.
* [getTokenAccountBalance](/solana/rpc-calls/http/gettokenaccountbalance) – Check the balance of a specific SPL token account.
* [getTokenSupply](/solana/rpc-calls/http/gettokensupply) – Returns the total supply of a given SPL token, helping track circulating and fixed supplies.
* [requestAirdrop](/solana/rpc-calls/http/requestairdrop) – Requests free SOL (lamports) to a given account.

### Transaction Methods

Core methods for sending transactions, tracking their confirmation status, and accessing historical transaction details on the Solana blockchain.

* [getTransaction](/solana/rpc-calls/http/gettransaction) —  Retrieves the complete information about a transaction using its signature.
* [getSignaturesForAddress](/solana/rpc-calls/http/getsignaturesforaddress) — Lists recent transaction signatures associated with a specific address.
* [getSignaturesStatus](/solana/rpc-calls/http/getsignaturestatuses)[es](/solana/rpc-calls/http/getsignaturestatuses) — Returns confirmation status and error information for one or more transaction signatures.
* [getTransactionCount](/solana/rpc-calls/http/gettransactioncount) — Returns the total number of transactions sent by a given account.
* [simulateTransaction](/solana/rpc-calls/http/simulatetransaction) — Simulates a transaction without broadcasting it, useful for debugging and preflight checks.
* [sendTransaction](/solana/rpc-calls/http/sendtransaction) — Submits a signed transaction to the network for processing.
* [getFeeForMessage](/solana/rpc-calls/http/getfeeformessage) — Returns the estimated transaction fee for a given compiled message, helping you simulate and plan transaction costs accurately.

### Block & Slot Methods

Explore Solana’s block structure, slot progression, leader schedules, and ledger timing for historical and real-time insights.

* [getBlock](/solana/rpc-calls/http/getblock) —  Fetch the full details of a confirmed or finalized block, including transactions.
* [getSlot](/solana/rpc-calls/http/getslot) — Returns the current slot the network is processing.
* [getBlocksWithLimit](/solana/rpc-calls/http/getblockswithlimit) — Fetches a limited number of blocks starting from a given slot.
* [getBlockTime](/solana/rpc-calls/http/getblocktime) — Provides the Unix timestamp when a block was produced.
* [getLatestBlockhash](/solana/rpc-calls/http/getlatestblockhash) — Returns the most recent finalized blockhash for sending transactions.
* [isBlockhashValid](/solana/rpc-calls/http/isblockhashvalid) — Checks whether a given blockhash is still valid for transaction processing.&#x20;
* [getSlotLeader ](/solana/rpc-calls/http/getslotleader)— Fetches the current slot’s leader (i.e., the validator responsible for producing the block).
* [getLeaderSchedule](/solana/rpc-calls/http/getleaderschedule) — Provides the full schedule of slot leaders for a given epoch.

### Network & Cluster Methods

Monitor overall network health, validator activity, epoch progress, and cluster-wide performance metrics.

* [getHealth](/solana/rpc-calls/http/gethealth) — Checks whether the connected node is healthy and fully synced with the cluster.
* [getVersion](/solana/rpc-calls/http/getversion) — Returns the Solana software version running on the connected node.
* [getIdentity](/solana/rpc-calls/http/getidentity) — Provides the public identity key of the current node.
* [getClusterNodes](/solana/rpc-calls/http/getclusternodes) — Lists all nodes in the current cluster, including their public key, gossip, TPU, and RPC addresses.
* [getEpochInfo](/solana/rpc-calls/http/getepochinfo) — Returns information about the current epoch, such as slot progress, epoch number, and leader schedule.
* [getEpochSchedule](/solana/rpc-calls/http/getepochschedule) — Provides configuration details for epochs, including slot and leader rotation rules.
* [getPerformanceSamples](/solana/rpc-calls/http/getrecentperformancesamples) — Provides recent samples of network performance, including transactions per second and average slot time.
* [getInflationGovernor](/solana/rpc-calls/http/getinflationgovernor) — Returns the current inflation configuration for the network, including the initial rate, tapering schedule, long-term rate, and allocations to the foundation.
* [getInflationRate](/solana/rpc-calls/http/getinflationrate) — Provides the current epoch’s inflation breakdown, including total inflation, validator share, foundation share, and the epoch number.
* [getInflationReward](/solana/rpc-calls/http/getinfationreward) — Returns inflation rewards (staking rewards) credited to one or more addresses for a specific epoch.
* [getStakeMinimumDelegation](/solana/rpc-calls/http/getstakeminimumdelegation) — Returns the minimum number of lamports required to create a new stake delegation.

### Utility & System Methods

Access low-level system utilities, validate blockhashes, estimate transaction fees, and retrieve protocol configuration data.

* [getGenesisHash](/solana/rpc-calls/http/getgenesishash) — Returns the hash of the genesis block for chain identity verification.
* [getFirstAvailableBlock](/solana/rpc-calls/http/getfirstavailableblock) — Returns the earliest block still available from the node’s ledger.
* [getHighestSnapshotSlot](/solana/rpc-calls/http/gethighestsnapshotslot) — Retrieves the highest snapshot slot available across the network, useful for syncing nodes.
* [minimumLedgerSlot](/solana/rpc-calls/http/getminimumledgerslot) — Returns the lowest slot that the node still retains in its ledger.
* [getMaxShredInsertSlot](/solana/rpc-calls/http/getmaxshredinsertslot) — Retrieves the highest slot for which shreds can be inserted into the blockstore.


# getAccountInfo

All the specifications for getAccountInfo RPC Method on Solana

Returns all information associated with the account of provided Pubkey

#### Parameters required for this RPC call

* The **account address** for which we are fetching the account info. This is usually provided as a string.
* **configuration object**: This contains the following methods.
  * **commitment**: The commitment describes how finalized a block is at that point in time.
  * **encoding**: The encoding format of the account data. The options can be base58, base64, base64+zstd, jsonParsed.
  * **dataSlice**: Requests a part of the account data instead of the full account data. This also has two parameters: `length: <usize>` - number of bytes to return & `offset: <usize>` - byte offset from which to start reading.
  * **minContextSlot**: The minimum slot that the request can be evaluated at.

{% tabs %}
{% tab title="cURL" %}

```bash
curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
  POST -H "Content-Type: application/json" -d ' 
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getAccountInfo",
    "params": [
      "vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg",
      {
        "commitment": "finalized",
        "encoding": "base58"
      }
    ]
  }
'
```

{% endtab %}

{% tab title="Web3.js" %}

<pre class="language-javascript"><code class="lang-javascript">import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");
<strong>const publicKey = new PublicKey("vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg");
</strong>const accountInfo = await connection.getAccountInfo(publicKey);

console.log("Account Info:", JSON.stringify(accountInfo, null, 2));
</code></pre>

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "context": { "apiVersion": "2.0.15", "slot": 341197053 },
    "value": {
      "data": [
                "F7f4N2DYrWAGMT4xa88DAkaR//wGAAAAFpkr5dnQAgCrJdwAAAAAAACAxqR+jQMAADEF7GVOCJySHmIL70rFDnnTHGrG55zYDskitMKp3eTJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "base64"
            ], // can be in the formats specified above
      "executable": false,
      "lamports": 88849814690250,
      "owner": "11111111111111111111111111111111",
      "rentEpoch": 18446744073709551615,
      "space": 0
    }
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getBalance

All the specifications for getBalance RPC Method on Solana

Returns the lamport balance of the account of provided an account address (PublicKey)

#### Parameters required for this RPC call

* The account address for which we are fetching the account info. This is usually provided as a string.
* **configuration object**: This contains the following parameters.
  * commitment: The commitment describes how finalized a block is at that point in time.
  * minContextSlot: The minimum slot that the request can be evaluated at.

{% tabs %}
{% tab title="cURL" %}

```bash
curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
  POST -H "Content-Type: application/json" -d ' 
   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getBalance",
     "params": [
       "83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri",
       {
         "commitment": "finalized"
       }
     ]
   }
 '
```

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");
const publicKey = new PublicKey("83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri");
const balance = await connection.getBalance(publicKey);

console.log("Account Balance:", JSON.stringify(balance, null, 2));
```

{% endtab %}

{% tab title="Response" %}

```json
{
    "jsonrpc": "2.0",
    "result": {
        "context": {
            "apiVersion": "2.2.16",
            "slot": 357068878
        },
        "value": 16362443 //indicates the balance of the account
    },
    "id": 2
}
```

{% endtab %}
{% endtabs %}


# getBlock

All the specifications for getBlock RPC Method on Solana

Returns identity and transaction information about a confirmed block in the ledger

#### Parameters required for this RPC call

* **T**he slot number for which the corresponding block will be returned. This is a <mark style="color:yellow;">u64 number</mark>.
* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. Only <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.
  * **encoding**: Encoding format for each returned transaction. The supported options are *json*, *jsonParsed*, <mark style="color:yellow;">base58</mark> and <mark style="color:yellow;">base64</mark>. You can know more about [Parsed responses](https://solana.com/docs/rpc#parsed-responses) more on Solana docs.
  * **transactionDetails**: Specifies the level of transaction detail to return.

    * If `accounts` are requested, transaction details only include signatures and an annotated list of accounts in each transaction.
    * Transaction metadata is limited to only: *fee, err, pre\_balances, post\_balances, pre\_token\_balances,* and *post\_token\_balances*.

    Supports the following values: <mark style="color:yellow;">full</mark>, <mark style="color:yellow;">accounts</mark>, <mark style="color:yellow;">signatures</mark> or <mark style="color:yellow;">none</mark>. Defaults to <mark style="color:yellow;">full</mark>.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getBlock",
     "params": [
       378967388,
       {
         "commitment": "finalized",
         "encoding": "json",
         "transactionDetails": "full",
         "maxSupportedTransactionVersion": 0,
         "rewards": false
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

const slot_number = 377261141;

const block = await connection.getBlock(
  slot_number,
  {
    commitment: "finalized",
    transactionDetails: "full",
    maxSupportedTransactionVersion: 0,
    rewards: false,
  },
);

console.log("block:", block);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "blockHeight": 428,
    "blockTime": null, //if present, estimated production time in unix timestamp
    "blockhash": "3Eq21vXNB5s86c62bVuUfTeaMif1N2kUqRPBmGRJhyTA",
    "parentSlot": 429, //slot index of this blocks parent
    "previousBlockhash": "mfcyqEXB3DnHXki6KjjmZck6YjmZLvpAByy2fj4nh6B", //blockhash of this block's parent
    "transactions": // Present if "full" transaction details are requested
        "meta": {
          "err": null,
          "fee": 5000,
          "innerInstructions": [],
          "logMessages": [],
          "postBalances": [499998932500, 26858640, 1, 1, 1],
          "postTokenBalances": [],
          "preBalances": [499998937500, 26858640, 1, 1, 1],
          "preTokenBalances": [],
          "rewards": null,
          "status": {
            "Ok": null
          }
        },
        "transaction": {
          "message": {
            "accountKeys": [
              "3UVYmECPPMZSCqWKfENfuoTv51fTDTWicX9xmBD2euKe",
              "AjozzgE83A3x1sHNUR64hfH7zaEBWeMaFuAN9kQgujrc",
              "SysvarS1otHashes111111111111111111111111111",
              "SysvarC1ock11111111111111111111111111111111",
              "Vote111111111111111111111111111111111111111"
            ],
            "header": {
              "numReadonlySignedAccounts": 0,
              "numReadonlyUnsignedAccounts": 3,
              "numRequiredSignatures": 1
            },
            "instructions": [
              {
                "accounts": [1, 2, 3, 0],
                "data": "37u9WtQpcm6ULa3WRQHmj49EPs4if7o9f1jSRVZpm2dvihR9C8jY4NqEwXUbLwx15HBSNcP1",
                "programIdIndex": 4
              }
            ],
            "recentBlockhash": "mfcyqEXB3DnHXki6KjjmZck6YjmZLvpAByy2fj4nh6B"
          },
          "signatures": [
            "2nBhEBYYvfaAe16UMNqRHre4YNSskvuYgx3M6E4JP1oDYvZEJHvoPzyUidNgNX5r9sTyN1J9UxtbCXy2rqYcuyuv"
          ]
        }
      }
    ]
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getBlockCommitment

All the specifications for getBlockCommitment RPC Method on Solana

Returns the commitment status for particular block

#### Parameters required for this RPC call

* The block number, which is identified by slot. This is a <mark style="color:yellow;">u64 number</mark>.
* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: Array of u64 integers logging the amount of cluster stake in lamports that has voted on the block at each depth from 0 to `MAX_LOCKOUT_HISTORY`.
  * **totalStake**: Total active stake, in lamports, of the current epoch.&#x20;

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getBlockCommitment",
     "params": [
       5
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "commitment": [
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 10, 32
    ],
    "totalStake": 42
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getBlocksWithLimit

All the specifications for getBlocksWithLimit RPC Method on Solana

Returns a list of confirmed blocks starting at the given slot

#### Parameters required for this RPC call

* The starting slot of the blocks to be returned. This is a <mark style="color:yellow;">u64 number</mark>.
* **limit**: The amount of slots to be fetched. Should not be more than 500,000 blocks higher than the start slot.
* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. Only <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getBlockCommitment",
     "params": [
       5
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "commitment": [
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 10, 32
    ],
    "totalStake": 42
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getBlockTime

All the specifications for getBlockTime RPC Method on Solana

Returns the estimated production time of a block.

#### Parameters required for this RPC call

* The Block number, identified by Slot. This is a <mark style="color:yellow;">u64 number</mark>.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getBlockTime",
     "params": [
       377268280
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let slotNumber = 377268280;
let blockTime = await connection.getBlockTime(slotNumber);

console.log("Block time:", blockTime);

```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": 1574721591, //estimated production time, as Unix timestamp
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getClusterNodes

All the specifications for getClusterNodes RPC Method on Solana

Returns information about all the nodes participating in the cluster

#### Parameters required for this RPC call

No parameters are required for this

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getClusterNodes"
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let nodes = await connection.getClusterNodes();

console.log(nodes);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": [
    {
      "featureSet": 3073396398, //unique identifier of the node's feature set
      "gossip": "10.239.6.48:8001", //Gossip network address for the node
      "pubkey": "9QzsJf7LPLj8GkXbYT3LFDKqsj2hHG7TA3xinJHu8epQ", //Node public key, as base-58 encoded string
      "rpc": "10.239.6.48:8899", //JSON RPC network address for the node, or null if the JSON RPC service is not enabled
      "shredVersion": 2405, //The shred version the node has been configured to use
      "tpu": "10.239.6.48:8856", //TPU network address for the node
      "version": "1.0.0 c375ce1f"
    }
  ],
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getEpochInfo

All the specifications for getEpochInfo RPC Method on Solana

Returns information about the current epoch

#### Parameters required for this RPC call

* **commitment**: The commitment describes how finalized a block is at that point in time.
* **minContextSlot**: The minimum slot that the request can be evaluated at.

{% tabs %}
{% tab title="cURL" %}

```bash
curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
  POST -H "Content-Type: application/json" -d ' 
   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getEpochInfo",
     "params": [
       {
         "commitment": "finalized"
       }
     ]
   }
 '
```

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");
let epochInfo = await connection.getEpochInfo();

console.log(epochInfo);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "absoluteSlot": 166598,
    "blockHeight": 166500,
    "epoch": 27,
    "slotIndex": 2790,
    "slotsInEpoch": 8192,
    "transactionCount": 22661093
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getEpochSchedule

All the specifications for getEpochSchedule RPC Method on Solana

Returns the epoch schedule information from this cluster

#### Parameters required for this RPC call

* No parameters are required

{% tabs %}
{% tab title="cURL" %}

```bash
curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
  POST -H "Content-Type: application/json" -d ' 
   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getEpochSchedule"
   }
 '
```

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");
let epochSchedule = await connection.getEpochSchedule();

console.log(epochSchedule);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "firstNormalEpoch": 8,
    "firstNormalSlot": 8160,
    "leaderScheduleSlotOffset": 8192,
    "slotsPerEpoch": 8192,
    "warmup": true
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getFeeForMessage

All the specifications for getFeeForMessage RPC Method on Solana

Get the fee the network will charge for a particular message

#### Parameters required for this RPC call

* **message**: A Base-64 encoded message, for which we are getting the fees.
* **minContextSlot**: The minimum slot that the request can be evaluated at.
* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. Only <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.
  * **encoding**: Encoding format for each returned transaction. The supported options are *json*, *jsonParsed*, <mark style="color:yellow;">base58</mark> and <mark style="color:yellow;">base64</mark>. You can know more about [Parsed responses](https://solana.com/docs/rpc#parsed-responses) more on Solana docs.

{% tabs %}
{% tab title="cURL" %}

```bash
curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
  POST -H "Content-Type: application/json" -d ' 
   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getFeeForMessage",
     "params": [
       "AQABAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQAA",
       {
         "commitment": "processed"
       }
     ]
   }
 '
```

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, Message, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");
let b64Message =
  "AQABAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQAA";
let message = Message.from(Buffer.from(b64Message, "base64"));

let fee = await connection.getFeeForMessage(message);

console.log(fee);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "context": { "slot": 5068 },
    "value": 5000
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getFirstAvailableBlock

All the specifications for getFirstAvailableBlock RPC Method on Solana

Returns the slot of the lowest confirmed block that has not been purged from the ledger

#### Parameters required for this RPC call

No parameters required

{% tabs %}
{% tab title="cURL" %}

```bash
curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
   POST -H "Content-Type: application/json" -d ' 
   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getFirstAvailableBlock"
   }
 '
```

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let firstAvailableBlock = await connection.getFirstAvailableBlock();

console.log(firstAvailableBlock);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": 250000,
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getGenesisHash

All the specifications for getGenesisHash RPC Method on Solana

Returns the genesis hash

#### Parameters required for this RPC call

No parameters required

{% tabs %}
{% tab title="cURL" %}

```bash
curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
   POST -H "Content-Type: application/json" -d ' 
   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getGenesisHash"
   }
 '
```

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let genesisHash = await connection.getGenesisHash();

console.log(genesisHash);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": "GH7ome3EiwEr7tu9JuTh2dpYWBJK3z69Xm1ZE3MEE6JC",
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getHealth

All the specifications for getHealth RPC Method on Solana

Returns the current health of the node. A healthy node is one that is within `HEALTH_CHECK_SLOT_DISTANCE` slots of the latest cluster confirmed slot.

#### Parameters required for this RPC call

No parameters required

{% tabs %}
{% tab title="cURL" %}

```bash
curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
   POST -H "Content-Type: application/json" -d ' 
   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getHealth"
   }
'
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": "ok",
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getHighestSnapshotSlot

All the specifications for getHighestSnapshotSlot RPC Method on Solana

Returns the highest slot information that the node has snapshots for. This will find the highest full snapshot slot, and the highest incremental snapshot slot *based on* the full snapshot slot, if there is one.

#### Parameters required for this RPC call

No parameters required

{% tabs %}
{% tab title="cURL" %}

```bash
curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
   POST -H "Content-Type: application/json" -d ' 
   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getHighestSnapshotSlot"
   }
 '
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "full": 100,
    "incremental": 110
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getIdentity

All the specifications for getIdentity RPC Method on Solana

Returns the identity pubkey for the current node

#### Parameters required for this RPC call

No parameters required

{% tabs %}
{% tab title="cURL" %}

```bash
curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
   POST -H "Content-Type: application/json" -d ' 
   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getIdentity"
   }
 '
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "identity": "2r1F4iWqVcb8M1DbAjQuFpebkQHY9hcVU4WuW2DJBppN"
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getInflationGovernor

All the specifications for getInflationGovernor RPC Method on Solana

Returns the current inflation governor

#### Parameters required for this RPC call

* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getInflationGovernor",
     "params": [
       {
         "commitment": "finalized"
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let commitment = "finalized";
let inflationGovener = await connection.getInflationGovernor();

console.log(inflationGovener);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "foundation": 0.05, //Percentage of total inflation allocated to the foundation
    "foundationTerm": 7, //Duration of foundation pool inflation in years
    "initial": 0.15, //Initial inflation percentage from time 0
    "taper": 0.15, //Rate per year at which inflation is lowered. (Rate reduction is derived using the target slot time in genesis config)
    "terminal": 0.015 //Terminal inflation percentage
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getInflationRate

All the specifications for getInflationRate RPC Method on Solana

Returns the specific inflation values for the current epoch.

#### Parameters required for this RPC call

No parameters required.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getInflationRate"
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let inflationRate = await connection.getInflationRate();

console.log(inflationRate);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "total": 0.149, // Total inflation
    "validator": 0.148, // Inflation allocated to validators
    "foundation": 0.001, // Inflation allocated to the foundation
    "epoch": 100 // Epoch for which these values are valid
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getInflationReward

All the specifications for getInflationReward RPC Method on Solana

Returns the inflation / staking reward for a list of addresses for an epoch

#### Parameters required for this RPC call

* An array of addresses to query, as base-58 encoded strings
* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported.
  * **epoch**: An epoch for which the reward occurs. If omitted, the previous epoch will be used
  * **minContextSlot**: The minimum slot that the request can be evaluated at. This is a number.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getInflationReward",
     "params": [
       [
         "6dmNQ5jwLeLk5REvio1JcMshcbvkYMwy26sJ8pbkvStu",
         "BGsqMegLpV6n6Ve146sSX2dTjUMj3M92HnU8BbNRMhF2"
       ],
       {
         "epoch": 800,
         "commitment": "finalized"
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let addresses = [
  new PublicKey("6dmNQ5jwLeLk5REvio1JcMshcbvkYMwy26sJ8pbkvStu"),
  new PublicKey("BGsqMegLpV6n6Ve146sSX2dTjUMj3M92HnU8BbNRMhF2"),
];

let epoch = 2;

let inflationReward = await connection.getInflationReward(addresses, epoch);

console.log(inflationReward);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": [
    {
      "epoch": 2,
      "effectiveSlot": 224,
      "amount": 2500,
      "postBalance": 499999442500
    },
    null
  ],
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getLargestAccounts

All the specifications for getLargestAccounts RPC Method on Solana

Returns the 20 largest accounts, by lamport balance (results may be cached up to two hours)

#### Parameters required for this RPC call

* An array of addresses to query, as base-58 encoded strings
* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported.
  * **filter**: Filter results by account type. The values can be <mark style="color:yellow;">circulating</mark> or <mark style="color:yellow;">nonCirculating</mark>.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getLargestAccounts",
     "params": [
       {
         "commitment": "finalized"
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let config: GetLargestAccountsConfig = {
  commitment: "finalized",
  filter: "circulating",
};

let largestAccounts = await connection.getLargestAccounts(config);

console.log(largestAccounts);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "context": { "slot": 54 },
    "value": [
      {
        "address": "99P8ZgtJYe1buSK8JXkvpLh8xPsCFuLYhz9hQFNw93WJ",
        "lamports": 999974
      },
      {
        "address": "uPwWLo16MVehpyWqsLkK3Ka8nLowWvAHbBChqv2FZeL",
        "lamports": 42
      }
    ]
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getLatestBlockhash

All the specifications for getLatestBlockhash RPC Method on Solana

Returns the latest blockhash. For older v1.8 of solana-core, please use *getRecentBlockhash*.

#### Parameters required for this RPC call

* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported.
  * **minContextSlot:** The minimum slot that the request can be evaluated at.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getLatestBlockhash",
     "params": [
       {
         "commitment": "processed"
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let commitment: Commitment = "processed";
let latestBlockhash = await connection.getLatestBlockhash(commitment);

console.log(latestBlockhash);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "context": {
      "slot": 2792
    },
    "value": {
      "blockhash": "EkSnNWid2cvwEVnVx9aBqawnmiCNiDgp3gUdkDPTKN1N", //A Hash as base-58 encoded string
      "lastValidBlockHeight": 3090 //Last block height at which the blockhash will be valid
    }
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getLeaderSchedule

All the specifications for getLeaderSchedule RPC Method on Solana

Returns the leader schedule for an epoch.

#### Parameters required for this RPC call

* Fetch the leader schedule for the epoch that corresponds to the provided slot. If unspecified, the leader schedule for the current epoch is fetched. This is an optional parameter.
* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported.
  * **identity**: Only return results for this validator identity (base-58 encoded)

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getLeaderSchedule",
     "params": [
       null,
       {
         "commitment": "processed",
         "identity": "dv2eQHeP4RFrJZ6UeiZWoc3XTtmtZCUKxxCApCDcRNV"
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let leaderSchedule = await connection.getLeaderSchedule();

console.log(leaderSchedule);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "4Qkev8aNZcqFNSRhQzwyLMFSsi94jHqE8WNVTJzTP99F": [
      0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
      21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
      39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
      57, 58, 59, 60, 61, 62, 63
    ]
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}

Returns `null` if requested epoch is not found, otherwise returns an object where:

* Keys are validator identities (as base-58 encoded strings)
* Values are arrays of leader slot indices relative to the first slot in the requested epoch


# getMaxShredInsertSlot

All the specifications for getMaxShredInsertSlot RPC Method on Solana

Get the max slot seen from after shred insert.

#### Parameters required for this RPC call

* No parameters required.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>    POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getMaxShredInsertSlot"
   }
 '
</code></pre>

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": 1234,
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getMinimumBalanceForRentExemption

All the specifications for getLatestBlockhash RPC Method on Solana

Returns minimum balance required to make account rent exempt.

#### Parameters required for this RPC call

* The Account's data length
* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getLatestBlockhash",
     "params": [
       {
         "commitment": "processed"
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let commitment: Commitment = "processed";
let latestBlockhash = await connection.getLatestBlockhash(commitment);

console.log(latestBlockhash);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "context": {
      "slot": 2792
    },
    "value": {
      "blockhash": "EkSnNWid2cvwEVnVx9aBqawnmiCNiDgp3gUdkDPTKN1N", //A Hash as base-58 encoded string
      "lastValidBlockHeight": 3090 //Last block height at which the blockhash will be valid
    }
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getMultipleAccounts

All the specifications for getMultipleAccounts RPC Method on Solana

Returns the account information for a list of Pubkeys. getAccountInfo returns for a single account, this works with an array of accounts.

#### Parameters required for this RPC call

* An array of pubkeys to query, as base-58 encoded strings. These are the addresses for the accounts which we are trying to get account information.&#x20;
* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. Commitment levels <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.
  * **encoding**: Encoding format for each returned transaction. The supported options are *json*, *jsonParsed*, <mark style="color:yellow;">base58</mark> and <mark style="color:yellow;">base64</mark>. You can know more about [Parsed responses](https://solana.com/docs/rpc#parsed-responses) more on Solana docs.
  * minContextSlot: The minimum slot that the request can be evaluated at. This is a number.
  * dataSlice: Request a slice of the account's data.
    * `length: <usize>` - number of bytes to return
    * `offset: <usize>` - byte offset from which to start reading

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getMultipleAccounts",
     "params": [
       [
         "vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg",
         "4fYNw3dojWmQ4dXtSGE9epjRGy9pFSx62YypT7avPYvA"
       ],
       {
         "encoding": "base58",
         "commitment": "finalized"
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import {
  Connection,
  PublicKey,
  clusterApiUrl,
  type GetMultipleAccountsConfig,
} from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let addresses = [
  new PublicKey("vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg"),
  new PublicKey("4fYNw3dojWmQ4dXtSGE9epjRGy9pFSx62YypT7avPYvA"),
];

let config: GetMultipleAccountsConfig = {
  commitment: "finalized",
};

let accounts = await connection.getMultipleAccountsInfo(addresses, config);

console.log(accounts);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "context": { "apiVersion": "2.0.15", "slot": 341197247 },
    "value": [
      {
        "data": ["", "base58"], //data associated with the account, in order.
        "executable": false,
        "lamports": 88849814690250,
        "owner": "11111111111111111111111111111111",
        "rentEpoch": 18446744073709551615,
        "space": 0
      },
      {
        "data": ["", "base58"],
        "executable": false,
        "lamports": 998763433,
        "owner": "2WRuhE4GJFoE23DYzp2ij6ZnuQ8p9mJeU6gDgfsjR4or",
        "rentEpoch": 18446744073709551615,
        "space": 0
      }
    ]
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getProgramAccounts

All the specifications for getProgramAccounts RPC Method on Solana

Returns all accounts owned by the provided program address.

#### Parameters required for this RPC call

* The address of the program whose accounts we are trying to fetch, as base-58 encoded string.
* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. Only <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.
  * **encoding**: Encoding format for each returned transaction. The supported options are *json*, *jsonParsed*, <mark style="color:yellow;">base58</mark> and <mark style="color:yellow;">base64</mark>. You can know more about [Parsed responses](https://solana.com/docs/rpc#parsed-responses) more on Solana docs.
  * **minContextSlot**: The minimum slot that the request can be evaluated at. This is a number.
  * **withContext**: Wrap the result in an RpcResponse JSON object.
  * **filters**: Filter results using up to 4 filter objects.
  * **dataSlice**:  Request a slice of the account's data.
    * `length: <usize>` - number of bytes to return
    * `offset: <usize>` - byte offset from which to start reading

{% hint style="info" %}
Looking for Accelerated getProgramAccounts? Find out [here](/solana/accelerated-getprogramaccounts).
{% endhint %}

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getProgramAccounts",
     "params": [
       [
         "vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg",
         "4fYNw3dojWmQ4dXtSGE9epjRGy9pFSx62YypT7avPYvA"
       ],
       {
         "encoding": "base58",
         "commitment": "finalized"
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import {
  Connection,
  PublicKey,
  clusterApiUrl,
  type GetMultipleAccountsConfig,
} from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let addresses = [
  new PublicKey("vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg"),
  new PublicKey("4fYNw3dojWmQ4dXtSGE9epjRGy9pFSx62YypT7avPYvA"),
];

let config: GetMultipleAccountsConfig = {
  commitment: "finalized",
};

let accounts = await connection.getProgramAccounts(addresses, config);

console.log(accounts);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "context": { "apiVersion": "2.0.15", "slot": 341197247 },
    "value": [
      {
        "data": ["", "base58"], //data associated with the account, in order.
        "executable": false,
        "lamports": 88849814690250,
        "owner": "11111111111111111111111111111111",
        "rentEpoch": 18446744073709551615,
        "space": 0
      },
      {
        "data": ["", "base58"],
        "executable": false,
        "lamports": 998763433,
        "owner": "2WRuhE4GJFoE23DYzp2ij6ZnuQ8p9mJeU6gDgfsjR4or",
        "rentEpoch": 18446744073709551615,
        "space": 0
      }
    ]
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getRecentPerformanceSamples

All the specifications for getRecentPerformanceSamples RPC Method on Solana

Returns a list of recent performance samples, in reverse slot order. Performance samples are taken every 60 seconds and include the number of transactions and slots that occur in a given time window.

#### Parameters required for this RPC call

* Number of samples to return (maximum 720). This is an optional parameter.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getRecentPerformanceSamples",
     "params": [
       2
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let limit = 2;

let performanceSamples = await connection.getRecentPerformanceSamples(limit);

console.log(performanceSamples);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": [
    {
      "slot": 348125,
      "numTransactions": 126,
      "numSlots": 126,
      "samplePeriodSecs": 60,
      "numNonVoteTransactions": 1
    },
    {
      "slot": 347999,
      "numTransactions": 126,
      "numSlots": 126,
      "samplePeriodSecs": 60,
      "numNonVoteTransactions": 1
    }
  ],
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getRecentPrioritizationFees

All the specifications for getRecentPrioritizationFees RPC Method on Solana

Returns a list of prioritization fees from recent blocks. Currently, a node's prioritization-fee cache stores data from up to 150 blocks.

#### Parameters required for this RPC call

* An array of Account addresses (up to a maximum of 128 addresses), as base-58 encoded strings. This is an optional parameter.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getRecentPrioritizationFees",
     "params": [
       ["CxELquR1gPP8wHe33gZ4QxqGB3sZ9RSwsJ2KshVewkFY"]
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let addresses = [new PublicKey("CxELquR1gPP8wHe33gZ4QxqGB3sZ9RSwsJ2KshVewkFY")];

let prioritizationFees = await connection.getRecentPrioritizationFees({
  lockedWritableAccounts: addresses,
});

console.log(prioritizationFees);
```

{% endtab %}

{% tab title="Response" %}
{% code overflow="wrap" %}

```json
{
  "jsonrpc": "2.0",
  "result": [
    {
      "slot": 348125,
      "prioritizationFee": 0
    },
    {
      "slot": 348126, //Slot in which the fee was observed
      "prioritizationFee": 1000 ///The per-compute-unit fee paid by at least one successfully landed transaction, specified in increments of micro-lamports
    },
    {
      "slot": 348127,
      "prioritizationFee": 500
    },
    {
      "slot": 348128,
      "prioritizationFee": 0
    },
    {
      "slot": 348129,
      "prioritizationFee": 1234
    }
  ],
  "id": 1
}
```

{% endcode %}
{% endtab %}
{% endtabs %}


# getSignaturesForAddress

All the specifications for getSignaturesForAddress RPC Method on Solana

Returns signatures for confirmed transactions that include the given address in their `accountKeys` list. Returns signatures backwards in time from the provided signature or most recent confirmed block.

#### Parameters required for this RPC call

* **address:** Account address as base-58 encoded string. This is the address for which we are fetching transaction signatures.
* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. Only <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.
  * **minContextSlot**: The minimum slot that the request can be evaluated at. This is a number.
  * **limit:** Maximum transaction signatures to return (between 1 and 1,000).
  * **before:** Start searching backwards from this transaction signature. If not provided the search starts from the top of the highest max confirmed block.
  * **until:** Search until this transaction signature, if found before limit reached

{% hint style="info" %}
`getSignaturesForAddress` + `getTransaction`, collapsed into one. Find out more about [<mark style="color:yellow;">getTransactionsForAddress</mark>](/solana/get-transactions-for-address).
{% endhint %}

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getSignaturesForAddress",
     "params": [
       "Vote111111111111111111111111111111111111111",
       {
         "commitment": "finalized",
         "limit": 1
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import {
  Connection,
  PublicKey,
  clusterApiUrl,
  type SignaturesForAddressOptions,
} from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let signaturesOptions: SignaturesForAddressOptions = {
  limit: 1,
};

let address = new PublicKey("Vote111111111111111111111111111111111111111");
let signatures = await connection.getSignaturesForAddress(
  address,
  signaturesOptions,
);

console.log(signatures);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": [
    {
      "signature": "5h6xBEauJ3PK6SWCZ1PGjBvj8vDdWG3KpwATGy1ARAXFSDwt8GFXM7W5Ncn16wmqokgpiKRLuS83KUxyZyv2sUYv",
      "slot": 114,
      "err": null,
      "memo": null,
      "blockTime": null,
      "confirmationStatus": "finalized"
    }
  ],
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getSignatureStatuses

All the specifications for getSignaturesForAddress RPC Method on Solana

Returns the statuses of a list of signatures. Each signature must be a [txid](https://solana.com/docs/references/terminology#transaction-id), the first signature of a transaction.

#### Parameters required for this RPC call

* **addresses:** An array of transaction signatures to confirm, as base-58 encoded strings (up to a maximum of 256)
* **configuration** : This contains the following parameters, all are optional fields.
  * **searchTransactionHistory**: if `true` - a Solana node will search its ledger cache for any signatures not found in the recent status cache.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getSignatureStatuses",
     "params": [
       [
         "5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW"
       ],
       {
         "searchTransactionHistory": true
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import {
  Connection,
  clusterApiUrl,
  type SignatureStatusConfig,
} from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let signatures = [
  "4cdd1oX7cfVALfr26tP52BZ6cSzrgnNGtYD7BFhm6FFeZV5sPTnRvg6NRn8yC6DbEikXcrNChBM5vVJnTgKhGhVu",
];

let config: SignatureStatusConfig = {
  searchTransactionHistory: true,
};

let signatureStatus = await connection.getSignatureStatuses(signatures, config);
console.log(signatureStatus);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "context": {
      "slot": 82
    },
    "value": [
      {
        "slot": 48,
        "confirmations": null,
        "err": null,
        "status": {
          "Ok": null
        },
        "confirmationStatus": "finalized"
      },
      null
    ]
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getSlot

All the specifications for getSlot RPC Method on Solana

Returns the slot that has reached the [given or default commitment level](https://solana.com/docs/rpc#configuring-state-commitment).

#### Parameters required for this RPC call

* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. Only <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.
  * **minContextSlot**: The minimum slot that the request can be evaluated at. This is a number.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getSlot",
     "params": [
       {
         "commitment": "finalized"
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, clusterApiUrl, type GetSlotConfig } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let config: GetSlotConfig = {
  commitment: "finalized",
};

let slot = await connection.getSlot(config);

console.log(slot);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": 1234,
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getSlotLeader

All the specifications for getSlotLeader RPC Method on Solana

Returns the current slot leader.

#### Parameters required for this RPC call

* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. Only <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.
  * **minContextSlot**: The minimum slot that the request can be evaluated at. This is a number.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>   POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getSlotLeader",
     "params": [
       {
         "commitment": "finalized"
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let slotLeader = await connection.getSlotLeader();

console.log(slotLeader);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": 1234,
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getSlotLeaders

All the specifications for getSlotLeaders RPC Method on Solana

Returns the slot leaders for a given slot range

#### Parameters required for this RPC call

* **startSlot:** Start slot, as u64 integer
* **limit**: Limit, as u64 integer (between 1 and 5,000)

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>   POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getSlotLeaders",
     "params": [
       100,
       10
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let startSlot = 378037836;
let limit = 10;

let slotLeaders = await connection.getSlotLeaders(startSlot, limit);

console.log(slotLeaders);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": [
    "ChorusmmK7i1AxXeiTtQgQZhQNiXYU84ULeaYF1EH15n",
    "ChorusmmK7i1AxXeiTtQgQZhQNiXYU84ULeaYF1EH15n",
    "ChorusmmK7i1AxXeiTtQgQZhQNiXYU84ULeaYF1EH15n",
    "ChorusmmK7i1AxXeiTtQgQZhQNiXYU84ULeaYF1EH15n",
    "Awes4Tr6TX8JDzEhCZY2QVNimT6iD1zWHzf1vNyGvpLM",
    "Awes4Tr6TX8JDzEhCZY2QVNimT6iD1zWHzf1vNyGvpLM",
    "Awes4Tr6TX8JDzEhCZY2QVNimT6iD1zWHzf1vNyGvpLM",
    "Awes4Tr6TX8JDzEhCZY2QVNimT6iD1zWHzf1vNyGvpLM",
    "DWvDTSh3qfn88UoQTEKRV2JnLt5jtJAVoiCo3ivtMwXP",
    "DWvDTSh3qfn88UoQTEKRV2JnLt5jtJAVoiCo3ivtMwXP"
  ],
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getStakeMinimumDelegation

All the specifications for getStakeMinimumDelegation RPC Method on Solana

Returns the stake minimum delegation, in lamports.

#### Parameters required for this RPC call

* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getStakeMinimumDelegation",
     "params": [
       {
         "commitment": "finalized"
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

<pre class="language-javascript"><code class="lang-javascript">import { Connection, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");
<strong>
</strong><strong>let stakeMinDelegation = await connection.getStakeMinimumDelegation();
</strong>
console.log(stakeMinDelegation);
</code></pre>

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "context": { "slot": 501 },
    "value": 1000000000
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getSupply

All the specifications for getSupply RPC Method on Solana

Returns information about the current supply.

#### Parameters required for this RPC call

* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. Commitment levels <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.
  * **excludeNonCirculatingAccountsList**: Exclude non circulating accounts list from response. This is a boolean field.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getSupply",
     "params": [
       {
         "commitment": "finalized"
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let supply = await connection.getSupply();

console.log(supply);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "context": { "slot": 1114 },
    "value": {
      "total": 1016000,
      "circulating": 16000,
      "nonCirculating": 1000000,
      "nonCirculatingAccounts": [
        "FEy8pTbP5fEoqMV1GdTz83byuA8EKByqYat1PKDgVAq5",
        "9huDUZfxoJ7wGMTffUE7vh1xePqef7gyrLJu9NApncqA",
        "3mi1GmwEE3zo2jmfDuzvjSX9ovRXsDUKHvsntpkhuLJ9",
        "BYxEJTDerkaRWBem3XgnVcdhppktBXa2HbkHPKj2Ui4Z"
      ]
    }
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getTokenAccountBalance

All the specifications for getTokenAccountBalance RPC Method on Solana

Returns the token balance of an SPL Token account.

#### Parameters required for this RPC call

* The **pubkey** of Token account to query, as base-58 encoded string.
* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. Commitment levels <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getTokenAccountBalance",
     "params": [
       "7fUAJdStEuGbc3sM84cKRL6yYaaSstyLSU4ve5oovLS7",
       {
         "commitment": "finalized"
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let tokenAddress = new PublicKey(
  "48gpnn8nsmkvkgso7462Z1nFhUrprGQ71u1YLBPzizbY",
);

let tokenBalance = await connection.getTokenAccountBalance(tokenAddress);

console.log(tokenBalance);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "context": { "slot": 1114 },
    "value": {
      "amount": "9864",
      "decimals": 2,
      "uiAmount": 98.64,
      "uiAmountString": "98.64"
    }
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getTokenAccountsByDelegate

All the specifications for getTokenAccountsByDelegate RPC Method on Solana

Returns all SPL Token accounts by approved Delegate.

#### Parameters required for this RPC call

* The **pubkey** of account delegate to query, as base-58 encoded string.
* A JSON object with one of the following fields:
  * **mint**: Pubkey of the specific token Mint to limit accounts to, as base-58 encoded string; or
  * **programId**: Pubkey of the Token program that owns the accounts, as base-58 encoded string
* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. Commitment levels <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.
  * **dataSlice**: Request a slice of the account's data.
    * `length: <usize>` - number of bytes to return
    * `offset: <usize>` - byte offset from which to start reading
  * **minContextSlot**: The minimum slot that the request can be evaluated at.
  * **encoding**: Encoding format for each returned transaction. The supported options are *json*, *jsonParsed*, <mark style="color:yellow;">base58</mark> and <mark style="color:yellow;">base64</mark>. You can know more about [Parsed responses](https://solana.com/docs/rpc#parsed-responses) more on Solana docs.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getTokenAccountBalance",
     "params": [
       "7fUAJdStEuGbc3sM84cKRL6yYaaSstyLSU4ve5oovLS7",
       {
         "commitment": "finalized"
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let tokenAddress = new PublicKey(
  "48gpnn8nsmkvkgso7462Z1nFhUrprGQ71u1YLBPzizbY",
);

let tokenBalance = await connection.getTokenAccountBalance(tokenAddress);

console.log(tokenBalance);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "context": { "slot": 1114 },
    "value": {
      "amount": "9864",
      "decimals": 2,
      "uiAmount": 98.64,
      "uiAmountString": "98.64"
    }
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getTokenAccountsByOwner

All the specifications for getTokenAccountsByOwner RPC Method on Solana

Returns all SPL Token accounts by token owner.

#### Parameters required for this RPC call

* The **pubkey** of account delegate to query, as base-58 encoded string.
* A JSON object with one of the following fields:
  * **mint**: Pubkey of the specific token Mint to limit accounts to, as base-58 encoded string; or
  * **programId**: Pubkey of the Token program that owns the accounts, as base-58 encoded string
* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. Commitment levels <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.
  * **dataSlice**: Request a slice of the account's data.
    * `length: <usize>` - number of bytes to return
    * `offset: <usize>` - byte offset from which to start reading
  * **minContextSlot**: The minimum slot that the request can be evaluated at.
  * **encoding**: Encoding format for each returned transaction. The supported options are *json*, *jsonParsed*, <mark style="color:yellow;">base58</mark> and <mark style="color:yellow;">base64</mark>. You can know more about [Parsed responses](https://solana.com/docs/rpc#parsed-responses) more on Solana docs.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getTokenAccountsByOwner",
     "params": [
       "A1TMhSGzQxMr1TboBKtgixKz1sS6REASMxPo1qsyTSJd",
       {
         "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
       },
       {
         "commitment": "finalized",
         "encoding": "jsonParsed"
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let owner = new PublicKey("4kg8oh3jdNtn7j2wcS7TrUua31AgbLzDVkBZgTAe44aF");

let tokenProgram = new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");

let tokenAccounts = await connection.getTokenAccountsByOwner(owner, {
  programId: tokenProgram,
});

console.log(tokenAccounts);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "context": { "apiVersion": "2.0.15", "slot": 341197933 },
    "value": [
      {
        "pubkey": "BGocb4GEpbTFm8UFV2VsDSaBXHELPfAXrvd4vtt8QWrA",
        "account": {
          "data": {
            "program": "spl-token",
            "parsed": {
              "info": {
                "isNative": false,
                "mint": "2cHr7QS3xfuSV8wdxo3ztuF4xbiarF6Nrgx3qpx3HzXR",
                "owner": "A1TMhSGzQxMr1TboBKtgixKz1sS6REASMxPo1qsyTSJd",
                "state": "initialized",
                "tokenAmount": {
                  "amount": "420000000000000",
                  "decimals": 6,
                  "uiAmount": 420000000.0,
                  "uiAmountString": "420000000"
                }
              },
              "type": "account"
            },
            "space": 165
          },
          "executable": false,
          "lamports": 2039280,
          "owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
          "rentEpoch": 18446744073709551615,
          "space": 165
        }
      }
    ]
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getTokenLargestAccounts

All the specifications for getTokenLargestAccounts RPC Method on Solana

Returns the 20 largest accounts of a particular SPL Token type.

#### Parameters required for this RPC call

* The **pubkey** of the token Mint to query, as base-58 encoded string
* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. Commitment levels <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.
  *

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getTokenLargestAccounts",
     "params": [
       "3wyAj7Rt1TWVPZVteFJPLa26JmLvdb1CAKEFZm3NY75E",
       {
         "commitment": "finalized"
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let mint = new PublicKey!("Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr");

let largestHolders = await connection.getTokenLargestAccounts(mint);

console.log(largestHolders);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "context": { "slot": 1114 },
    "value": [
      {
        "address": "FYjHNoFtSQ5uijKrZFyYAxvEr87hsKXkXcxkcmkBAf4r",
        "amount": "771",
        "decimals": 2,
        "uiAmount": 7.71,
        "uiAmountString": "7.71"
      },
      {
        "address": "BnsywxTcaYeNUtzrPxQUvzAWxfzZe3ZLUJ4wMMuLESnu",
        "amount": "229",
        "decimals": 2,
        "uiAmount": 2.29,
        "uiAmountString": "2.29"
      }
    ]
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getTokenSupply

All the specifications for getTokenSupply RPC Method on Solana

Returns the total supply of an SPL Token type.

#### Parameters required for this RPC call

* The **pubkey** of the token Mint to query, as base-58 encoded string
* **configuration** : This contains the following parameters, all are optional fields.

  * **commitment**: The commitment describes how finalized a block is at that point in time. Commitment levels <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>   POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getTokenSupply",
     "params": [
       "3wyAj7Rt1TWVPZVteFJPLa26JmLvdb1CAKEFZm3NY75E",
       {
         "commitment": "finalized"
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let mint = new PublicKey!("Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr");

let tokenSupply = await connection.getTokenSupply(mint);

console.log(tokenSupply);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "context": { "slot": 1114 },
    "value": {
      "amount": "100000",
      "decimals": 2,
      "uiAmount": 1000,
      "uiAmountString": "1000"
    }
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getTransaction

All the specifications for getTransaction RPC Method on Solana

Returns transaction details for a confirmed transaction

#### Parameters required for this RPC call

* The **pubkey** of account delegate to query, as base-58 encoded string.
* A JSON object with one of the following fields:
  * **mint**: Pubkey of the specific token Mint to limit accounts to, as base-58 encoded string; or
  * **programId**: Pubkey of the Token program that owns the accounts, as base-58 encoded string
* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. Commitment levels <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.
  * **dataSlice**: Request a slice of the account's data.
    * `length: <usize>` - number of bytes to return
    * `offset: <usize>` - byte offset from which to start reading
  * **maxSupportedTransactionVersion**: Currently, the only valid value for this parameter is `0`. Setting it to `0` allows you to fetch all transactions, including both Versioned and legacy transactions.
  * **encoding**: Encoding format for each returned transaction. The supported options are *json*, *jsonParsed*, <mark style="color:yellow;">base58</mark> and <mark style="color:yellow;">base64</mark>. You can know more about [Parsed responses](https://solana.com/docs/rpc#parsed-responses) more on Solana docs.

{% hint style="success" %}
`getSignaturesForAddress` + `getTransaction`, collapsed into one. Find out more about [<mark style="color:yellow;">getTransactionsForAddress</mark>](/solana/get-transactions-for-address).
{% endhint %}

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getTransaction",
     "params": [
       "5Pj5fCupXLUePYn18JkY8SrRaWFiUctuDTRwvUy2ML9yvkENLb1QMYbcBGcBXRrSVDjp7RjUwk9a3rLC6gpvtYpZ",
       {
         "commitment": "confirmed",
         "maxSupportedTransactionVersion": 0,
         "encoding": "json"
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl, type GetVersionedTransactionConfig, } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let signature =
  "5zSQuTcWsPy2cVAshBXWuJJXLwMD1GbgMpz3iq4xgwiV1s6mxYRbYb7qBiRGZd1xvDcYhQQRBKoNcnW8eKtcyZWg";

let config: GetVersionedTransactionConfig = {
  commitment: "finalized",
  maxSupportedTransactionVersion: 0,
};

let transaction = await connection.getTransaction(signature, config);

console.log(transaction);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "blockTime": 1746479684,
    "meta": {
      "computeUnitsConsumed": 150,
      "err": null,
      "fee": 5000,
      "innerInstructions": [],
      "loadedAddresses": {
        "readonly": [],
        "writable": []
      },
      "logMessages": [
        "Program 11111111111111111111111111111111 invoke [1]",
        "Program 11111111111111111111111111111111 success"
      ],
      "postBalances": [
        989995000,
        10000000,
        1
      ],
      "postTokenBalances": [],
      "preBalances": [
        1000000000,
        0,
        1
      ],
      "preTokenBalances": [],
      "rewards": [],
      "status": {
        "Ok": null
      }
    },
    "slot": 378917547,
    "transaction": {
      "message": {
        "accountKeys": [
          "7BvfixZx7Rwywf6EJFgRW6acEQ2FLSFJr4n3kLLVeEes",
          "6KtbxYovphtE3eHjPjr2sWwDfgaDwtAn2FcojDyzZWT6",
          "11111111111111111111111111111111"
        ],
        "header": {
          "numReadonlySignedAccounts": 0,
          "numReadonlyUnsignedAccounts": 1,
          "numRequiredSignatures": 1
        },
        "instructions": [
          {
            "accounts": [
              0,
              1
            ],
            "data": "3Bxs4NN8M2Yn4TLb",
            "programIdIndex": 2,
            "stackHeight": null
          }
        ],
        "recentBlockhash": "23dwTHxFhSzqohXhdni5LwpuSRpgN36YvVMCAM2VXQSf"
      },
      "signatures": [
        "5Pj5fCupXLUePYn18JkY8SrRaWFiUctuDTRwvUy2ML9yvkENLb1QMYbcBGcBXRrSVDjp7RjUwk9a3rLC6gpvtYpZ"
      ]
    },
    "version": "legacy"
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getTransactionCount

All the specifications for getTransactionCount RPC Method on Solana

Returns the current Transaction count from the ledger.

#### Parameters required for this RPC call

* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. Commitment levels <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.
  * **minContextSlot**: The minimum slot that the request can be evaluated at.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getTransactionCount",
     "params": [
       {
         "commitment": "finalized"
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl, type GetVersionedTransactionConfig, } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let txCount = await connection.getTransactionCount();

console.log(txCount);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": 268,
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getVersion

All the specifications for getVersion RPC Method on Solana

Returns the current Solana version running on the node

#### Parameters required for this RPC call

* No parameters are required for this RPC call.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getVersion"
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");
let version = await connection.getVersion();

console.log(version);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "solana-core": "1.16.7",
    "feature-set": 2891131721
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# getVoteAccounts

All the specifications for getVoteAccounts RPC Method on Solana

Returns the account info and associated stake for all the voting accounts in the current bank.

#### Parameters required for this RPC call

* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. Commitment levels <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.
  * **votePubkey**: Only return results for this validator vote address (base-58 encoded)
  * **keepUnstakedDeliquents**: Do not filter out delinquent validators with no stake
  * **delinquentSlotDistance**: Specify the number of slots behind the tip that a validator must fall to be considered delinquent. **NOTE:** For the sake of consistency between ecosystem products, *it is **not** recommended that this argument be specified.*

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getVoteAccounts",
     "params": [
       {
         "commitment": "finalized",
         "votePubkey": "i7NyKBMJCA9bLM2nsGyAGCKHECuR2L5eh4GqFciuwNT"
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl, type GetVersionedTransactionConfig, } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let version = await connection.getVoteAccounts();

console.log(version);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "current": [
      {
        "activatedStake": 38263229364446900,
        "commission": 95,
        "epochCredits": [
          [902, 1383125544, 1376213656],
          [903, 1390037304, 1383125544],
          [904, 1396949288, 1390037304],
          [905, 1403861272, 1396949288],
          [906, 1406766600, 1403861272]
        ],
        "epochVoteAccount": true,
        "lastVote": 391573587,
        "nodePubkey": "dv2eQHeP4RFrJZ6UeiZWoc3XTtmtZCUKxxCApCDcRNV",
        "rootSlot": 391573556,
        "votePubkey": "i7NyKBMJCA9bLM2nsGyAGCKHECuR2L5eh4GqFciuwNT"
      }
    ],
    "delinquent": []
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# isBlockhashValid

All the specifications for isBlockhasValid RPC Method on Solana

Returns whether a blockhash is still valid or not

#### Parameters required for this RPC call

* The blockhash of the block to evaluate, as base-58 encoded string.
* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. Commitment levels <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.
  * **minContextSlot**: The minimum slot that the request can be evaluated at.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "getVersion"
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");
let version = await connection.getVersion();

console.log(version);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "solana-core": "1.16.7",
    "feature-set": 2891131721
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# minimumLedgerSlot

All the specifications for getVersion RPC Method on Solana

Returns the current Solana version running on the node

#### Parameters required for this RPC call

* No parameters are required for this RPC call.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "minimumLedgerSlot"
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");
let minLedgerSlot = await connection.getMinimumLedgerSlot();

console.log(minLedgerSlot);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": 1234,
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# requestAirdrop

All the specifications for requestAirdrop RPC Method on Solana

Requests an airdrop of lamports to a account.

#### Parameters required for this RPC call

* The address (publicKey) of account to receive lamports, as a base-58 encoded string.
* The amount of lamports to airdrop
* **configuration** : This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. Commitment levels <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "requestAirdrop",
     "params": [
       "83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri",
       1000000000,
       {
         "commitment": "finalized"
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import {
  Connection,
  LAMPORTS_PER_SOL,
  PublicKey,
  clusterApiUrl,
} from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

let receiver = new PublicKey("4kg8oh3jdNtn7j2wcS7TrUua31AgbLzDVkBZgTAe44aF");

let airdropAmt = 1 * LAMPORTS_PER_SOL;

let sig = await connection.requestAirdrop(receiver, airdropAmt);

console.log(sig);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": "5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW",
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# sendTransaction

All the specifications for sendTransaction RPC Method on Solana

Submits a signed transaction to the cluster for processing.

This method does not alter the transaction in any way; it relays the transaction created by clients to the node as-is.

If the node's rpc service receives the transaction, this method immediately succeeds, without waiting for any confirmations. A successful response from this method does not guarantee the transaction is processed or confirmed by the cluster.

While the rpc service will reasonably retry to submit it, the transaction could be rejected if transaction's `recent_blockhash` expires before it lands.

Use [`getSignatureStatuses`](https://solana.com/docs/rpc/http/getsignaturestatuses) to ensure a transaction is processed and confirmed.

Before submitting, the following preflight checks are performed:

1. The transaction signatures are verified
2. The transaction is simulated against the bank slot specified by the preflight commitment. On failure an error will be returned. Preflight checks may be disabled if desired. It is recommended to specify the same commitment and preflight commitment to avoid confusing behavior.

The returned signature is the first signature in the transaction, which is used to identify the transaction ([transaction id](https://solana.com/docs/references/terminology#transaction-id)). This identifier can be easily extracted from the transaction data before submission.

#### Parameters required for this RPC call

* The Fully-signed Transaction, as encoded string.
* The amount of lamports to airdrop
* **configuration object**: This contains the following parameters.
  * **encoding**: Encoding used for the transaction data. Values: `base58` (*slow*, **DEPRECATED**), or `base64`.
  * **skipPreflight**: When `true`, skip the preflight transaction checks. Default: `false`.
  * **preflightCommitment**: Commitment level to use for preflight. See [Configuring State Commitment](https://solana.com/docs/rpc/index.mdx#configuring-state-commitment). Default `finalized`.
  * **maxRetries**: Maximum number of times for the RPC node to retry sending the transaction to the leader. If this parameter not provided, the RPC node will retry the transaction until it is finalized or until the blockhash expires.
  * **minContextSlot**: Set the minimum slot at which to perform preflight transaction checks.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "sendTransaction",
     "params": [
       "4hXTCkRzt9WyecNzV1XPgCDfGAZzQKNxLXgynz5QDuWWPSAZBZSHptvWRL3BjCvzUXRdKvHL2b7yGrRQcWyaqsaBCncVG7BFggS8w9snUts67BSh3EqKpXLUm5UMHfD7ZBe9GhARjbNQMLJ1QD3Spr6oMTBU6EhdB4RD8CP2xUxr2u3d6fos36PD98XS6oX8TQjLpsMwncs5DAMiD4nNnR8NBfyghGCWvCVifVwvA8B8TJxE1aiyiv2L429BCWfyzAme5sZW8rDb14NeCQHhZbtNqfXhcp2tAnaAT"
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import {
  Connection,
  LAMPORTS_PER_SOL,
  PublicKey,
  clusterApiUrl,
} from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

const base64Tx =
  "AbuRLtc5C9bZtAUT4F4Y2H5SRRUK1HwOFZOK3V4qm/78MDJt+M2de/RCCaI3iTyodDepmrkUWbss0XRHS0lk5AOAAQABAzfDSQC/GjcggrLsDpYz7jAlT+Gca846HqtFb8UQMM9cCWPIi4AX32PV8HrY7/1WgoRc3IATttceZsUMeQ1qx7UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2dTRgcJmzcoGH1R3c2WqtHah2H19KvbC1p6BxLDqfoAQICAAEMAgAAAADKmjsAAAAAAA==";

let tx = VersionedTransaction.deserialize(Buffer.from(base64Tx, "base64"));

let sig = await connection.sendTransaction(tx);

console.log(sig);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": "2id3YC2jK9G5Wo2phDx4gJVAew8DcY5NAojnVuao8rkxwPYPe8cSwE5GzhEgJA2y8fVjDEo6iR6ykBvDxrTQrtpb",
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# simulateTransaction

All the specifications for simulateTransaction RPC Method on Solana

Simulate sending a transaction.

#### Parameters required for this RPC call

* Transaction, as an encoded string.
* The amount of lamports to airdrop
* **configuration object**: This contains the following parameters. All optional.
  * **encoding**: Encoding used for the transaction data. Values: `base58` (*slow*, **DEPRECATED**), or `base64`.
  * **commitment**: Commitment level to simulate the transaction at. See [Configuring State Commitment](https://solana.com/docs/rpc/index.mdx#configuring-state-commitment). Default `finalized`.
  * **replaceRecentBlockhash**: If `true` the transaction recent blockhash will be replaced with the most recent blockhash (conflicts with `sigVerify`)
  * **sigVerify**: If `true` the transaction signatures will be verified (conflicts with `replaceRecentBlockhash`)
  * **innerInstructions**: If `true` the response will include [inner instructions](https://solana.com/docs/rpc/json-structures#inner-instructions). These inner instructions will be `jsonParsed` where possible, otherwise `json`.
  * **accounts**: If `true` the response will include [inner instructions](https://solana.com/docs/rpc/json-structures#inner-instructions). These inner instructions will be `jsonParsed` where possible, otherwise `json`.
  * **minContextSlot**: Set the minimum slot at which to perform preflight transaction checks.

{% tabs %}
{% tab title="cURL" %}

<pre class="language-bash"><code class="lang-bash">curl https://rpc.shyft.to?api_key=YOUR-API-KEY -s -X \
<strong>  POST -H "Content-Type: application/json" -d ' 
</strong>   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "simulateTransaction",
     "params": [
       "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEEjNmKiZGiOtSZ+g0//wH5kEQo3+UzictY+KlLV8hjXcs44M/Xnr+1SlZsqS6cFMQc46yj9PIsxqkycxJmXT+veJjIvefX4nhY9rY+B5qreeqTHu4mG6Xtxr5udn4MN8PnBt324e51j94YQl285GzN2rYa/E2DuQ0n/r35KNihi/zamQ6EeyeeVDvPVgUO2W3Lgt9hT+CfyqHvIa11egFPCgEDAwIBAAkDZAAAAAAAAAA=",
       {
         "commitment": "confirmed",
         "encoding": "base64",
         "replaceRecentBlockhash": true
       }
     ]
   }
 '
</code></pre>

{% endtab %}

{% tab title="Web3.js" %}

```javascript
import {
  Connection,
  VersionedTransaction,
  clusterApiUrl,
  type SimulateTransactionConfig,
} from "@solana/web3.js";

const connection = new Connection("https://rpc.shyft.to?api_key=YOUR-API-KEY", "confirmed");

const base64Tx =
  "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEEjNmKiZGiOtSZ+g0//wH5kEQo3+UzictY+KlLV8hjXcs44M/Xnr+1SlZsqS6cFMQc46yj9PIsxqkycxJmXT+veJjIvefX4nhY9rY+B5qreeqTHu4mG6Xtxr5udn4MN8PnBt324e51j94YQl285GzN2rYa/E2DuQ0n/r35KNihi/zamQ6EeyeeVDvPVgUO2W3Lgt9hT+CfyqHvIa11egFPCgEDAwIBAAkDZAAAAAAAAAA=";

let tx = VersionedTransaction.deserialize(Buffer.from(base64Tx, "base64"));

let simulateTxConfig: SimulateTransactionConfig = {
  commitment: "finalized",
  replaceRecentBlockhash: true,
  sigVerify: false,
  minContextSlot: undefined,
  innerInstructions: undefined,
  accounts: undefined,
};

let simulateResult = await connection.simulateTransaction(tx, simulateTxConfig);

console.log(simulateResult);
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "context": {
      "apiVersion": "2.3.3",
      "slot": 393226680
    },
    "value": {
      "accounts": null,
      "err": null,
      "innerInstructions": null,
      "loadedAccountsDataSize": 413,
      "logs": [
        "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [1]",
        "Program log: Instruction: Transfer",
        "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1714 of 200000 compute units",
        "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success"
      ],
      "replacementBlockhash": {
        "blockhash": "6oFLsE7kmgJx9PjR4R63VRNtpAVJ648gCTr3nq5Hihit",
        "lastValidBlockHeight": 381186895
      },
      "returnData": null,
      "unitsConsumed": 1714
    }
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# Solana Websocket Methods

Subscribe to Real-Time Solana Data via WebSocket

After connecting to the RPC PubSub websocket at `ws://<ADDRESS>/`:

* Submit subscription requests to the websocket using the methods below
* Multiple subscriptions may be active at once
* Many subscriptions take the optional [`commitment` parameter](https://solana.com/docs/rpc#configuring-state-commitment), defining how finalized a change should be to trigger a notification. For subscriptions, if commitment is unspecified, the default value is `finalized`.

#### **Subscription Methods**

These methods allow clients to subscribe to real-time updates about on-chain events through Solana’s WebSocket-based PubSub system. They're essential for building reactive applications like explorers, dashboards, bots, and monitoring tools.

* [accountSubscribe](/solana/rpc-calls/solana-websockets/accountsubscribe) – Subscribes to updates on a specific account’s data.\
  Useful for tracking balance changes or state updates in real time.
* [accountUnsubscribe](/solana/rpc-calls/solana-websockets/accountunsubscribe) – Cancels an active account subscription to stop receiving updates.
* [blockSubscribe](/solana/rpc-calls/solana-websockets/blocksubscribe) – Subscribes to notifications whenever a new block is produced.\
  Ideal for syncing block data or triggering logic based on finalized blocks.
* [blockUnsubscribe](/solana/rpc-calls/solana-websockets/blockunsubscribe) – Unsubscribes from block updates.
* [logsSubscribe](/solana/rpc-calls/solana-websockets/logssubscribe) – Subscribes to program log outputs (e.g., emitted via `msg!()` in Solana programs).\
  Helpful for debugging, tracking program activity, or triggering off-chain events.
* [logsUnsubscribe](/solana/rpc-calls/solana-websockets/logsunsubscribe) – Stops receiving program log updates.
* [programSubscribe](/solana/rpc-calls/solana-websockets/programsubscribe) – Subscribes to changes in all accounts owned by a specific program.\
  Useful for monitoring a protocol’s account activity across the network.
* [programUnsubscribe](/solana/rpc-calls/solana-websockets/programunsubscribe) – Unsubscribes from a program update stream.
* [signatureSubscribe](/solana/rpc-calls/solana-websockets/signaturesubscribe) – Subscribes to status updates for a given transaction signature.\
  Used to monitor whether a specific transaction gets confirmed or fails.
* [signatureUnsubscribe](/solana/rpc-calls/solana-websockets/signatureunsubscribe) – Stops tracking a specific transaction signature.
* [slotSubscribe](/solana/rpc-calls/solana-websockets/slotsubscribe) – Subscribes to notifications whenever a new slot is processed.\
  Useful for applications that need to stay in sync with the network clock.
* [slotUnsubscribe](/solana/rpc-calls/solana-websockets/slotunsubscribe) – Ends the slot subscription.

These real-time methods are vital for building event-driven dApps that respond to Solana state changes as they happen.


# accountSubscribe

All the specifications for accountSubscribe Websocket Method on Solana

Subscribe to an account to receive notifications when the lamports or data for a given account public key changes.

#### Parameters required for this RPC call

* the **account address (pubkey)**, as base-58 encoded string
* **configuration object**: This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. Commitment levels <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.
  * **encoding**: Encoding format for Account data

    * `base58` is slow.
    * `jsonParsed` encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data
    * If `jsonParsed` is requested but a parser cannot be found, the field falls back to binary encoding, detectable when the `data` field is type `string`.
    * Supports: `base58`      , `base64`      , `base64+zstd`      , `jsonParsed`

{% tabs %}
{% tab title="Websocket" %}

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "accountSubscribe",
  "params": [
    "CM78CPUeXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNH12",
    {
      "encoding": "jsonParsed",
      "commitment": "finalized"
    }
  ]
}
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": 23784,
  "id": 1
}
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Base58 " %}

```json
{
  "jsonrpc": "2.0",
  "method": "accountNotification",
  "params": {
    "result": {
      "context": {
        "slot": 5199307
      },
      "value": {
        "data": [
          "11116bv5nS2h3y12kD1yUKeMZvGcKLSjQgX6BeV7u1FrjeJcKfsHPXHRDEHrBesJhZyqnnq9qJeUuF7WHxiuLuL5twc38w2TXNLxnDbjmuR",
          "base58"
        ],
        "executable": false,
        "lamports": 33594,
        "owner": "11111111111111111111111111111111",
        "rentEpoch": 635,
        "space": 80
      }
    },
    "subscription": 23784
  }
}
```

{% endtab %}

{% tab title="Parsed-JSON encoding" %}

```
{
  "jsonrpc": "2.0",
  "method": "accountNotification",
  "params": {
    "result": {
      "context": {
        "slot": 5199307
      },
      "value": {
        "data": {
          "program": "nonce",
          "parsed": {
            "type": "initialized",
            "info": {
              "authority": "Bbqg1M4YVVfbhEzwA9SpC9FhsaG83YMTYoR4a8oTDLX",
              "blockhash": "LUaQTmM7WbMRiATdMMHaRGakPtCkc2GHtH57STKXs6k",
              "feeCalculator": {
                "lamportsPerSignature": 5000
              }
            }
          }
        },
        "executable": false,
        "lamports": 33594,
        "owner": "11111111111111111111111111111111",
        "rentEpoch": 635,
        "space": 80
      }
    },
    "subscription": 23784
  }
}
```

{% endtab %}
{% endtabs %}


# accountUnsubscribe

All the specifications for accountUnsubscribe Websocket Method on Solana

Unsubscribe from account change notifications

#### Parameters required for this RPC call

* The id of the account Subscription to cancel.

{% tabs %}
{% tab title="Websocket" %}

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "accountUnsubscribe",
  "params": [
    0
  ]
}
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": true,
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# blockSubscribe

All the specifications for blockSubscribe Websocket Method on Solana

Subscribe to receive notification anytime a new block is `confirmed` or `finalized`.

{% hint style="danger" %}
**Unstable Method**

This subscription is considered **unstable** and is only available if the validator was started with the&#x20;

`--rpc-pubsub-enable-block-subscription` flag. The format of this subscription may change in the future.
{% endhint %}

#### Parameters required for this RPC call

* filter criteria for the logs to receive results by account type; currently supported:
  * `all` - include all transactions in block
  * A JSON object with the following field:
    * `mentionsAccountOrProgram: <string>` - return only transactions that mention the provided public key (as base-58 encoded string). If no mentions in a given block, then no notification will be sent.
* **configuration object**: This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. Commitment levels <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.
  * **encoding**: Encoding format for Account data
    * `base58` is slow.
    * `jsonParsed` encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data
    * If `jsonParsed` is requested but a parser cannot be found, the field falls back to binary encoding, detectable when the `data` field is type `string`.
    * Supports: `base58`      , `base64`      , `base64+zstd`      , `jsonParsed`
  * **transactionDetails**: The level of transaction detail to return
    * If `accounts` are requested, transaction details only include signatures and an annotated list of accounts in each transaction.
    * Transaction metadata is limited to only: fee, err, pre\_balances, post\_balances, pre\_token\_balances, and post\_token\_balances.
  * maxSupportedTransactionVersion: Currently, the only valid value for this parameter is `0`. Setting it to `0` allows you to fetch all transactions, including both Versioned and legacy transactions.

    This parameter determines the maximum transaction version that will be returned in the response. If you request a transaction with a higher version than this value, an error will be returned. If you omit this parameter, only legacy transactions will be returned—any versioned transaction will result in an error.
  * showRewards: Whether to populate the `rewards` array. If parameter not provided, the default includes rewards. This is a boolean field.&#x20;

{% tabs %}
{% tab title="Websocket" %}

```json
{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "blockSubscribe",
  "params": [
    {
      "mentionsAccountOrProgram": "LieKvPRE8XeX3Y2xVNHjKlpAScD12lYySBVQ4HqoJ5op"
    },
    {
      "commitment": "confirmed",
      "encoding": "base64",
      "transactionDetails": "full",
      "maxSupportedTransactionVersion": 0,
      "showRewards": true
    }
  ]
}
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": 0, // id required to unsubscribe
  "id": 1
}
```

{% endtab %}
{% endtabs %}

**Notification Format:**

The notification will be an object with the following fields:

* `slot: <u64>` - The corresponding slot.
* `err: <object|null>` - Error if something went wrong publishing the notification otherwise null.
* `block: <object|null>` - A block object as seen in the [getBlock](https://solana.com/docs/rpc/http/getblock) RPC HTTP method.

{% tabs %}
{% tab title="Notification Format" %}

```json
{
  "jsonrpc": "2.0",
  "method": "blockNotification",
  "params": {
    "result": {
      "context": {
        "slot": 112301554
      },
      "value": {
        "slot": 112301554,
        "block": {
          "previousBlockhash": "GJp125YAN4ufCSUvZJVdCyWQJ7RPWMmwxoyUQySydZA",
          "blockhash": "6ojMHjctdqfB55JDpEpqfHnP96fiaHEcvzEQ2NNcxzHP",
          "parentSlot": 112301553,
          "transactions": [
            {
              "transaction": [
                "OpltwoUvWxYi1P2U8vbIdE/aPntjYo5Aa0VQ2JJyeJE2g9Vvxk8dDGgFMruYfDu8/IfUWb0REppTe7IpAuuLRgIBAAkWnj4KHRpEWWW7gvO1c0BHy06wZi2g7/DLqpEtkRsThAXIdBbhXCLvltw50ZnjDx2hzw74NVn49kmpYj2VZHQJoeJoYJqaKcvuxCi/2i4yywedcVNDWkM84Iuw+cEn9/ROCrXY4qBFI9dveEERQ1c4kdU46xjxj9Vi+QXkb2Kx45QFVkG4Y7HHsoS6WNUiw2m4ffnMNnOVdF9tJht7oeuEfDMuUEaO7l9JeUxppCvrGk3CP45saO51gkwVYEgKzhpKjCx3rgsYxNR81fY4hnUQXSbbc2Y55FkwgRBpVvQK7/+clR4Gjhd3L4y+OtPl7QF93Akg1LaU9wRMs5nvfDFlggqI9PqJl+IvVWrNRdBbPS8LIIhcwbRTkSbqlJQWxYg3Bo2CTVbw7rt1ZubuHWWp0mD/UJpLXGm2JprWTePNULzHu67sfqaWF99LwmwjTyYEkqkRt1T0Je5VzHgJs0N5jY4iIU9K3lMqvrKOIn/2zEMZ+ol2gdgjshx+sphIyhw65F3J/Dbzk04LLkK+CULmN571Y+hFlXF2ke0BIuUG6AUF+4214Cu7FXnqo3rkxEHDZAk0lRrAJ8X/Z+iwuwI5cgbd9uHXZaGT2cvhRs7reawctIXtX1s3kTqM9YV+/wCpDLAp8axcEkaQkLDKRoWxqp8XLNZSKial7Rk+ELAVVKWoWLRXRZ+OIggu0OzMExvVLE5VHqy71FNHq4gGitkiKYNFWSLIE4qGfdFLZXy/6hwS+wq9ewjikCpd//C9BcCL7Wl0iQdUslxNVCBZHnCoPYih9JXvGefOb9WWnjGy14sG9j70+RSVx6BlkFELWwFvIlWR/tHn3EhHAuL0inS2pwX7ZQTAU6gDVaoqbR2EiJ47cKoPycBNvHLoKxoY9AZaBjPl6q8SKQJSFyFd9n44opAgI6zMTjYF/8Ok4VpXEESp3QaoUyTI9sOJ6oFP6f4dwnvQelgXS+AEfAsHsKXxGAIUDQENAgMEBQAGBwgIDg8IBJCER3QXl1AVDBADCQoOAAQLERITDAjb7ugh3gOuTy==",
                "base64"
              ],
              "meta": {
                "err": null,
                "status": {
                  "Ok": null
                },
                "fee": 5000,
                "preBalances": [
                  1758510880, 2067120, 1566000, 1461600, 2039280, 2039280,
                  1900080, 1865280, 0, 3680844220, 2039280
                ],
                "postBalances": [
                  1758505880, 2067120, 1566000, 1461600, 2039280, 2039280,
                  1900080, 1865280, 0, 3680844220, 2039280
                ],
                "innerInstructions": [
                  {
                    "index": 0,
                    "instructions": [
                      {
                        "programIdIndex": 13,
                        "accounts": [1, 15, 3, 4, 2, 14],
                        "data": "21TeLgZXNbtHXVBzCaiRmH"
                      },
                      {
                        "programIdIndex": 14,
                        "accounts": [3, 4, 1],
                        "data": "6qfC8ic7Aq99"
                      },
                      {
                        "programIdIndex": 13,
                        "accounts": [1, 15, 3, 5, 2, 14],
                        "data": "21TeLgZXNbsn4QEpaSEr3q"
                      },
                      {
                        "programIdIndex": 14,
                        "accounts": [3, 5, 1],
                        "data": "6LC7BYyxhFRh"
                      }
                    ]
                  },
                  {
                    "index": 1,
                    "instructions": [
                      {
                        "programIdIndex": 14,
                        "accounts": [4, 3, 0],
                        "data": "7aUiLHFjSVdZ"
                      },
                      {
                        "programIdIndex": 19,
                        "accounts": [17, 18, 16, 9, 11, 12, 14],
                        "data": "8kvZyjATKQWYxaKR1qD53V"
                      },
                      {
                        "programIdIndex": 14,
                        "accounts": [9, 11, 18],
                        "data": "6qfC8ic7Aq99"
                      }
                    ]
                  }
                ],
                "logMessages": [
                  "Program QMNeHCGYnLVDn1icRAfQZpjPLBNkfGbSKRB83G5d8KB invoke [1]",
                  "Program QMWoBmAyJLAsA1Lh9ugMTw2gciTihncciphzdNzdZYV invoke [2]"
                ],
                "preTokenBalances": [
                  {
                    "accountIndex": 4,
                    "mint": "iouQcQBAiEXe6cKLS85zmZxUqaCqBdeHFpqKoSz615u",
                    "uiTokenAmount": {
                      "uiAmount": null,
                      "decimals": 6,
                      "amount": "0",
                      "uiAmountString": "0"
                    },
                    "owner": "LieKvPRE8XeX3Y2xVNHjKlpAScD12lYySBVQ4HqoJ5op",
                    "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
                  },
                  {
                    "accountIndex": 5,
                    "mint": "iouQcQBAiEXe6cKLS85zmZxUqaCqBdeHFpqKoSz615u",
                    "uiTokenAmount": {
                      "uiAmount": 11513.0679,
                      "decimals": 6,
                      "amount": "11513067900",
                      "uiAmountString": "11513.0679"
                    },
                    "owner": "rXhAofQCT7NN9TUqigyEAUzV1uLL4boeD8CRkNBSkYk",
                    "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
                  },
                  {
                    "accountIndex": 10,
                    "mint": "Saber2gLauYim4Mvftnrasomsv6NvAuncvMEZwcLpD1",
                    "uiTokenAmount": {
                      "uiAmount": null,
                      "decimals": 6,
                      "amount": "0",
                      "uiAmountString": "0"
                    },
                    "owner": "CL9wkGFT3SZRRNa9dgaovuRV7jrVVigBUZ6DjcgySsCU",
                    "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"
                  },
                  {
                    "accountIndex": 11,
                    "mint": "Saber2gLauYim4Mvftnrasomsv6NvAuncvMEZwcLpD1",
                    "uiTokenAmount": {
                      "uiAmount": 15138.514093,
                      "decimals": 6,
                      "amount": "15138514093",
                      "uiAmountString": "15138.514093"
                    },
                    "owner": "LieKvPRE8XeX3Y2xVNHjKlpAScD12lYySBVQ4HqoJ5op",
                    "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"
                  }
                ],
                "postTokenBalances": [
                  {
                    "accountIndex": 4,
                    "mint": "iouQcQBAiEXe6cKLS85zmZxUqaCqBdeHFpqKoSz615u",
                    "uiTokenAmount": {
                      "uiAmount": null,
                      "decimals": 6,
                      "amount": "0",
                      "uiAmountString": "0"
                    },
                    "owner": "LieKvPRE8XeX3Y2xVNHjKlpAScD12lYySBVQ4HqoJ5op",
                    "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
                  },
                  {
                    "accountIndex": 5,
                    "mint": "iouQcQBAiEXe6cKLS85zmZxUqaCqBdeHFpqKoSz615u",
                    "uiTokenAmount": {
                      "uiAmount": 11513.103028,
                      "decimals": 6,
                      "amount": "11513103028",
                      "uiAmountString": "11513.103028"
                    },
                    "owner": "rXhAofQCT7NN9TUqigyEAUzV1uLL4boeD8CRkNBSkYk",
                    "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
                  },
                  {
                    "accountIndex": 10,
                    "mint": "Saber2gLauYim4Mvftnrasomsv6NvAuncvMEZwcLpD1",
                    "uiTokenAmount": {
                      "uiAmount": null,
                      "decimals": 6,
                      "amount": "0",
                      "uiAmountString": "0"
                    },
                    "owner": "CL9wkGFT3SZRRNa9dgaovuRV7jrVVigBUZ6DjcgySsCU",
                    "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"
                  },
                  {
                    "accountIndex": 11,
                    "mint": "Saber2gLauYim4Mvftnrasomsv6NvAuncvMEZwcLpD1",
                    "uiTokenAmount": {
                      "uiAmount": 15489.767829,
                      "decimals": 6,
                      "amount": "15489767829",
                      "uiAmountString": "15489.767829"
                    },
                    "owner": "BeiHVPRE8XeX3Y2xVNrSsTpAScH94nYySBVQ4HqgN9at",
                    "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"
                  }
                ],
                "rewards": []
              }
            }
          ],
          "blockTime": 1639926816,
          "blockHeight": 101210751
        },
        "err": null
      }
    },
    "subscription": 14
  }
}
```

{% endtab %}
{% endtabs %}


# blockUnsubscribe

All the specifications for accountUnsubscribe Websocket Method on Solana

Unsubscribe from block notifications

#### Parameters required for this RPC call

* subscription id to cancel

{% tabs %}
{% tab title="Websocket" %}

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "blockUnsubscribe",
  "params": [
    0
  ]
}
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": true,
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# logsSubscribe

All the specifications for logsSubscribe Websocket Method on Solana

Subscribe to transaction logging.

#### Parameters required for this RPC call

* A filter criteria for the logs to receive results by account type. The following filters types are currently supported:

  * `all` - subscribe to all transactions except for simple vote transactions
  * `allWithVotes` - subscribe to all transactions, including simple vote transactions
  * An object with the following field:
    * `mentions: [ <string> ]` - array containing a single Pubkey (as base-58 encoded string); if present, subscribe to only transactions mentioning this address

  The `mentions` field currently [only ](https://github.com/solana-labs/solana/blob/master/rpc/src/rpc_pubsub.rs#L481)[supports one](https://github.com/solana-labs/solana/blob/master/rpc/src/rpc_pubsub.rs#L481) Pubkey string per method call. Listing additional addresses will result in an error.
* **configuration object**: This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. Commitment levels <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.

{% tabs %}
{% tab title="Websocket" %}

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "logsSubscribe",
  "params": [
    {
      "mentions": ["11111111111111111111111111111111"]
    },
    {
      "commitment": "finalized"
    }
  ]
}
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": 24040, //will be required to unsubscribe
  "id": 1
}
```

{% endtab %}
{% endtabs %}

**Notification Format:**

The notification will be an RpcResponse JSON object with value equal to:

* `signature: <string>` - The transaction signature base58 encoded.
* `err: <object|null>` - Error if transaction failed, null if transaction succeeded. [TransactionError definitions](https://github.com/solana-labs/solana/blob/c0c60386544ec9a9ec7119229f37386d9f070523/sdk/src/transaction/error.rs#L13)
* `logs: <array[string]>` - Array of log messages the transaction instructions output during execution.

{% tabs %}
{% tab title="Notification Format" %}

```json
{
  "jsonrpc": "2.0",
  "method": "logsNotification",
  "params": {
    "result": {
      "context": {
        "slot": 5208469
      },
      "value": {
        "signature": "5h6xBEauJ3PK6SWCZ1PGjBvj8vDdWG3KpwATGy1ARAXFSDwt8GFXM7W5Ncn16wmqokgpiKRLuS83KUxyZyv2sUYv",
        "err": null,
        "logs": [
          "SBF program 83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri success"
        ]
      }
    },
    "subscription": 24040
  }
}
```

{% endtab %}
{% endtabs %}


# logsUnsubscribe

All the specifications for logsUnsubscribe Websocket Method on Solana

Unsubscribe from transaction logging.

#### Parameters required for this RPC call

* subscription id to cancel

{% tabs %}
{% tab title="Websocket" %}

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "logsUnsubscribe",
  "params": [
    0
  ]
}
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": true,
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# programSubscribe

All the specifications for programSubscribe Websocket Method on Solana

Subscribe to a program to receive notifications when the lamports or data for an account owned by the given program changes.

#### Parameters required for this RPC call

* The address of the program (pubkey), as a base-58 encoded string.
* **configuration object**: This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. Commitment levels <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.
  * **filters**: Filter results using various filter objects. The resultant account must meet **ALL** filter criteria to be included in the returned results
  * **encoding**: Encoding format for Account data
    * `base58` is slow.
    * `jsonParsed` encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data
    * If `jsonParsed` is requested but a parser cannot be found, the field falls back to binary encoding, detectable when the `data` field is type `string`.
    * Supports: `base58`      , `base64`      , `base64+zstd`      , `jsonParsed`

{% tabs %}
{% tab title="Websocket" %}

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "programSubscribe",
  "params": [
    "11111111111111111111111111111111",
    {
      "encoding": "base64",
      "filters": [{ "dataSize": 80 }]
    }
  ]
}
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": 24040,
  "id": 1
}
```

{% endtab %}
{% endtabs %}

**Notification Format:**

The notification format is a single program account object as seen in the [getProgramAccounts](/solana/rpc-calls/http/getaccountinfo) RPC HTTP method.

{% tabs %}
{% tab title="base58 encoding" %}

```json
{
  "jsonrpc": "2.0",
  "method": "programNotification",
  "params": {
    "result": {
      "context": {
        "slot": 5208469
      },
      "value": {
        "pubkey": "H4vnBqifaSACnKa7acsxstsY1iV1bvJNxsCY7enrd1hq",
        "account": {
          "data": [
            "11116bv5nS2h3y12kD1yUKeMZvGcKLSjQgX6BeV7u1FrjeJcKfsHPXHRDEHrBesJhZyqnnq9qJeUuF7WHxiuLuL5twc38w2TXNLxnDbjmuR",
            "base58"
          ],
          "executable": false,
          "lamports": 33594,
          "owner": "11111111111111111111111111111111",
          "rentEpoch": 636,
          "space": 80
        }
      }
    },
    "subscription": 24040
  }
}
```

{% endtab %}

{% tab title="Parsed-JSON encoding:" %}

```json
{
  "jsonrpc": "2.0",
  "method": "programNotification",
  "params": {
    "result": {
      "context": {
        "slot": 5208469
      },
      "value": {
        "pubkey": "H4vnBqifaSACnKa7acsxstsY1iV1bvJNxsCY7enrd1hq",
        "account": {
          "data": {
            "program": "nonce",
            "parsed": {
              "type": "initialized",
              "info": {
                "authority": "Bbqg1M4YVVfbhEzwA9SpC9FhsaG83YMTYoR4a8oTDLX",
                "blockhash": "LUaQTmM7WbMRiATdMMHaRGakPtCkc2GHtH57STKXs6k",
                "feeCalculator": {
                  "lamportsPerSignature": 5000
                }
              }
            }
          },
          "executable": false,
          "lamports": 33594,
          "owner": "11111111111111111111111111111111",
          "rentEpoch": 636,
          "space": 80
        }
      }
    },
    "subscription": 24040
  }
}
```

{% endtab %}
{% endtabs %}


# programUnsubscribe

All the specifications for programUnsubscribe Websocket Method on Solana

Unsubscribe from program-owned account change notifications.

#### Parameters required for this RPC call

* id of account Subscription to cancel

{% tabs %}
{% tab title="Websocket" %}

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "programUnsubscribe",
  "params": [
    0
  ]
}
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": true,
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# rootSubscribe

All the specifications for rootSubscribe Websocket Method on Solana

Subscribe to receive notification anytime a new root is set by the validator.

#### Parameters required for this RPC call

* No parameters required.

{% tabs %}
{% tab title="Websocket" %}

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "rootSubscribe"
}
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": 0,
  "id": 1
}
```

{% endtab %}
{% endtabs %}

**Notification Format:**

The result is the latest root slot number.

{% tabs %}
{% tab title="Notification Format" %}

```json
{
  "jsonrpc": "2.0",
  "method": "rootNotification",
  "params": {
    "result": 42,
    "subscription": 0
  }
}
```

{% endtab %}
{% endtabs %}


# rootUnsubscribe

All the specifications for rootUnsubscribe Websocket Method on Solana

Unsubscribe from root notifications

#### Parameters required for this RPC call

* subscription id to cancel

{% tabs %}
{% tab title="Websocket" %}

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "rootUnsubscribe",
  "params": [
    0
  ]
}
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": true,
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# signatureSubscribe

All the specifications for signatureSubscribe Websocket Method on Solana

Subscribe to receive a notification when the transaction with the given signature reaches the specified commitment level.

{% hint style="danger" %}
This is a subscription to a single notification. It is automatically cancelled by the server once the notification, `signatureNotification`, is sent by the RPC.
{% endhint %}

#### Parameters required for this RPC call

* The transaction signature, as base-58 encoded string. The transaction signature must be the first signature from the transaction (see [transaction id](https://solana.com/docs/references/terminology#transaction-id) for more details).
* **configuration object**: This contains the following parameters, all are optional fields.
  * **commitment**: The commitment describes how finalized a block is at that point in time. Commitment levels <mark style="color:yellow;">processed</mark>, <mark style="color:yellow;">confirmed</mark> and <mark style="color:yellow;">finalized</mark> are supported, defaults to <mark style="color:yellow;">finalized</mark>.
  * **enableReceivedNotification**: Whether or not to subscribe for notifications when signatures are received by the RPC, in addition to when they are processed.

{% tabs %}
{% tab title="Websocket" %}

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "signatureSubscribe",
  "params": [
    "2EBVM6cB8vAAD93Ktr6Vd8p67XPbQzCJX47MpReuiCXJAtcjaxpvWpcg9Ege1Nr5Tk3a2GFrByT7WPBjdsTycY9b",
    {
      "commitment": "finalized",
      "enableReceivedNotification": false
    }
  ]
}
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": 0, //required to unsubscribe
  "id": 1
}
```

{% endtab %}
{% endtabs %}

**Notification Format:**

The notification will be an RpcResponse JSON object with value containing an object with:

* `slot: <u64>` - The corresponding slot.
* `value: <object|string>` - a notification value of [`RpcSignatureResult`](https://github.com/solana-labs/solana/blob/6d28fd455b07e3557fc6c0c3ddf3ba03e3fe8482/rpc-client-api/src/response.rs#L265-L268), resulting in either:
  * when `enableReceivedNotification` is `true` and the signature is received: the literal string [`"receivedSignature"`](https://github.com/solana-labs/solana/blob/6d28fd455b07e3557fc6c0c3ddf3ba03e3fe8482/rpc-client-api/src/response.rs#L286-L288), or
  * when the signature is processed: `err: <object|null>`:
    * `null` if the transaction succeeded in being processed at the specified commitment level, or
    * a [`TransactionError`](https://github.com/solana-labs/solana/blob/6d28fd455b07e3557fc6c0c3ddf3ba03e3fe8482/sdk/src/transaction/error.rs#L15-L164), if the transaction failed

**Examples Responses:**&#x20;

{% tabs %}
{% tab title="Successfully Processed Transaction" %}

```json
{
  "jsonrpc": "2.0",
  "method": "signatureNotification",
  "params": {
    "result": {
      "context": {
        "slot": 5207624
      },
      "value": {
        "err": null
      }
    },
    "subscription": 24006
  }
}
```

{% endtab %}

{% tab title="Successfully received transaction Signature" %}

```json
{
  "jsonrpc": "2.0",
  "method": "signatureNotification",
  "params": {
    "result": {
      "context": {
        "slot": 5207624
      },
      "value": "receivedSignature"
    },
    "subscription": 24006
  }
}
```

{% endtab %}
{% endtabs %}


# signatureUnsubscribe

All the specifications for signatureUnsubscribe Websocket Method on Solana

Unsubscribe from signature confirmation notification

#### Parameters required for this RPC call

* subscription id to cancel

{% tabs %}
{% tab title="Websocket" %}

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "signatureUnsubscribe",
  "params": [
    0
  ]
}
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": true,
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# slotSubscribe

All the specifications for slotSubscribe Websocket Method on Solana

Subscribe to receive notification anytime a slot is processed by the validator.

#### Parameters required for this RPC call

* No parameters required.

{% tabs %}
{% tab title="Websocket" %}

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "slotSubscribe"
}
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": 0,
  "id": 1
}
```

{% endtab %}
{% endtabs %}

**Notification Format:**

The notification will be an object with the following fields:

* `parent: <u64>` - The parent slot
* `root: <u64>` - The current root slot
* `slot: <u64>` - The newly set slot value

{% tabs %}
{% tab title="Example" %}

```json
{
  "jsonrpc": "2.0",
  "method": "slotNotification",
  "params": {
    "result": {
      "parent": 75,
      "root": 44,
      "slot": 76
    },
    "subscription": 0
  }
}
```

{% endtab %}
{% endtabs %}


# slotUnsubscribe

All the specifications for slotsUnsubscribe Websocket Method on Solana

Unsubscribe from slot-update notifications

#### Parameters required for this RPC call

* subscription id to cancel

{% tabs %}
{% tab title="Websocket" %}

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "slotsUpdatesUnsubscribe",
  "params": [
    0
  ]
}
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": true,
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# slotsUpdatesSubscribe

All the specifications for slotsUpdatesSubscribe Websocket Method on Solana

Subscribe to receive a notification from the validator on a variety of updates on every slot

{% hint style="danger" %}
This subscription is unstable. The format of this subscription may change in the future, and may not always be supported.
{% endhint %}

#### Parameters required for this RPC call

* No parameters required.

{% tabs %}
{% tab title="Websocket" %}

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "slotsUpdatesSubscribe"
}
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": 0,
  "id": 1
}
```

{% endtab %}
{% endtabs %}

**Notification Format:**

The notification will be an object with the following fields:

* `err: <string|undefined>` - The error message. Only present if the update is of type "dead".
* `parent: <u64|undefined>` - The parent slot. Only present if the update is of type "createdBank".
* `slot: <u64>` - The newly updated slot
* `stats: <object|undefined>` - The error message. Only present if the update is of type "frozen". An object with the following fields:
  * `maxTransactionsPerEntry: <u64>`,
  * `numFailedTransactions: <u64>`,
  * `numSuccessfulTransactions: <u64>`,
  * `numTransactionEntries: <u64>`,
* `timestamp: <i64>` - The Unix timestamp of the update in milliseconds
* `type: <string>` - The update type, one of:
  * "firstShredReceived"
  * "completed"
  * "createdBank"
  * "frozen"
  * "dead"
  * "optimisticConfirmation"
  * "root"

{% tabs %}
{% tab title="Example" %}

```json
{
  "jsonrpc": "2.0",
  "method": "slotsUpdatesNotification",
  "params": {
    "result": {
      "parent": 75,
      "slot": 76,
      "timestamp": 1625081266243,
      "type": "optimisticConfirmation"
    },
    "subscription": 0
  }
}
```

{% endtab %}
{% endtabs %}


# slotsUpdatesUnsubscribe

All the specifications for slotsUpdatesUnsubscribe Websocket Method on Solana

Unsubscribe from slot-update notifications

#### Parameters required for this RPC call

* subscription id to cancel

{% tabs %}
{% tab title="Websocket" %}

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "slotsUpdatesUnsubscribe",
  "params": [
    0
  ]
}
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": true,
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# voteSubscribe

All the specifications for voteSubscribe Websocket Method on Solana

Subscribe to receive notification anytime a new vote is observed in gossip. These votes are pre-consensus therefore there is no guarantee these votes will enter the ledger.

{% hint style="danger" %}
This subscription is unstable and only available if the validator was started with the&#x20;

`--rpc-pubsub-enable-vote-subscription`&#x20;

flag. The format of this subscription may change in the future.
{% endhint %}

#### Parameters required for this RPC call

* No parameters required.

{% tabs %}
{% tab title="Websocket" %}

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "voteSubscribe"
}
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": 0,
  "id": 1
}
```

{% endtab %}
{% endtabs %}

**Notification Format:**

The notification will be an object with the following fields:

* `hash: <string>` - The vote hash
* `slots: <array>` - The slots covered by the vote, as an array of u64 integers
* `timestamp: <i64|null>` - The timestamp of the vote
* `signature: <string>` - The signature of the transaction that contained this vote
* `votePubkey: <string>` - The public key of the vote account, as base-58 encoded string

{% tabs %}
{% tab title="Example" %}

```json
{
  "jsonrpc": "2.0",
  "method": "voteNotification",
  "params": {
    "result": {
      "hash": "8Rshv2oMkPu5E4opXTRyuyBeZBqQ4S477VG26wUTFxUM",
      "slots": [1, 2],
      "timestamp": null
    },
    "subscription": 0
  }
}
```

{% endtab %}
{% endtabs %}


# voteUnsubscribe

All the specifications for voteUnsubscribe Websocket Method on Solana

Unsubscribe from vote notifications

#### Parameters required for this RPC call

* subscription id to cancel

{% tabs %}
{% tab title="Websocket" %}

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "voteUnsubscribe",
  "params": [
    0
  ]
}
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": true,
  "id": 1
}
```

{% endtab %}
{% endtabs %}


# Solana RPC Limits

A reference guide to Shyft's RPC rate limits, supported methods, common errors, and how to resolve them.

Everything you need to know about [<mark style="color:yellow;">Shyft RPC</mark>](https://shyft.to/) in production — plan rate limits, method restrictions, common error codes, and troubleshooting guidance. If something isn't working, start here.

### Plan Rate Limits

Shyft enforces separate rate limits for standard RPC calls and index-heavy calls. Index calls — such as *`getProgramAccounts`, `getTokenAccountsByOwner`, `getTokenLargestAccounts`, and `getTokenAccountsByDelegate`* — are significantly more resource-intensive and are rate-limited separately from standard RPC calls.

### Unlimited RPC Plan Limits

| Feature               |    FREE   |   BUILD   |    GROW   | ACCELERATE |
| --------------------- | :-------: | :-------: | :-------: | :--------: |
| *Total Credits*       | Unlimited | Unlimited | Unlimited |  Unlimited |
| *RPC req/sec*         |     10    |    100    |    150    |     400    |
| *Index req/sec*       |     0     |     10    |     20    |     40     |
| *sendTransaction/sec* |     1     |     20    |     40    |     80     |
| *Jito simulateBundle* |     ✓     |     ✓     |     ✓     |      ✓     |
| *Staked Connections*  |     —     |     ✓     |     ✓     |      ✓     |

### Legacy RPC Plan Limits

| Feature               |   FREE  |    HACK    |    LAUNCH   |    SCALE    |
| --------------------- | :-----: | :--------: | :---------: | :---------: |
| *Total Credits*       | Default | 10 million | 100 million | 500 million |
| *RPC req/sec*         |    10   |     50     |     150     |     400     |
| *Index req/sec*       |    0    |     10     |      20     |      20     |
| *sendTransaction/sec* |    1    |     10     |      40     |      80     |
| *Jito simulateBundle* |    ✓    |      ✓     |      ✓      |      ✓      |
| *Staked Connections*  |    —    |      ✓     |      ✓      |      ✓      |

### Frequently Asked Questions

<details open>

<summary>What happens when credits run out on limited plans?</summary>

On all paid plans — Build, Grow, and Accelerate — credits are unlimited, so you will never run out. Credits only apply to legacy limited plans. If you are on HACK plan and exhaust your credits, requests stop until the next billing cycle. Calls do not stop on LAUNCH & SCALE, as these plans have overages. Overage pricing is available on select legacy plans — please check out [<mark style="color:yellow;">Shyft pricing</mark>](https://shyft.to/solana-rpc-grpc-pricing) for details.

</details>

<details>

<summary>Are other Jito RPC methods available besides <code>simulateBundle</code>?</summary>

Currently, only `simulateBundle` is supported on Shyft RPC. Other Jito-specific methods — including `sendBundle`, `getBundleStatuses`, `getInflightBundleStatuses`, and `getTipAccounts` — are not available. `simulateBundle` allows you to preview the effects of a bundle of transactions before submission, including account state changes and compute unit consumption, without executing it on-chain. If you need to send bundles, you will need to route those calls directly to the Jito Block Engine.

</details>

<details>

<summary>Why am I getting rate limited even though I am within my RPC req/sec limit?</summary>

Shyft enforces [<mark style="color:yellow;">separate rate limits</mark>](#unlimited-rpc-plan-limits) for standard RPC calls and index calls. If you are making calls like `getProgramAccounts`, `getTokenAccountsByOwner`, `getTokenLargestAccounts`, or `getTokenAccountsByDelegate`, these are counted against your index req/sec limit — which is lower than your standard RPC req/sec limit. Similarly, `sendTransaction` has its own separate limit. Check which method is triggering the 429 and compare it against the correct limit for that method type.&#x20;

</details>

<details>

<summary>Is a Solana devnet RPC endpoint available?</summary>

Yes. Shyft provides a devnet RPC endpoint at:

```
https://devnet-rpc.shyft.to/?api_key={your_api_key}
```

Use your standard Shyft API key to authenticate. Devnet is useful for testing integrations before deploying to mainnet.

</details>

<details>

<summary>Why am I getting no response or a timeout on <code>getProgramAccounts</code> calls?</summary>

`getProgramAccounts` is one of the most resource-intensive calls on Solana. Shyft enforces a 1-second timeout on gPA calls, and unfiltered gPA calls are blocked entirely. If your call is timing out, the most likely cause is an insufficiently filtered query returning too large a result set.\
We have recently released an update that brings `getProgramAccounts` <mark style="color:yellow;">response times to under 10ms</mark> for supported programs. Coverage for all major DEXes is being rolled out progressively.

</details>

<details>

<summary>How do I handle 429 rate limit errors?</summary>

You are likely hitting your [<mark style="color:yellow;">plan's rate limit</mark>](#legacy-rpc-plan-limits) for standard RPC, index, or `sendTransaction` calls — each has a separate limit. To resolve this: separate your index calls from standard RPC calls and rate-limit them independently, cache responses where possible to reduce total call volume, or upgrade to a higher plan if you are consistently hitting limits. \
If you are running a bot, many popular tools such as Metis have built-in rate limit configuration — reducing the request rate in your bot's settings is often the fastest fix.

</details>

<details>

<summary>Where do I reach out in case of any questions?</summary>

For any queries, you can reach out via the <mark style="color:yellow;">support chat</mark> on your Shyft dashboard or join the [<mark style="color:yellow;">Shyft Discord</mark>](https://discord.gg/RXBmKSdVRe). The team is happy to help with plan questions, integration issues, or anything else.

</details>


# Accelerated getProgramAccounts

Fast getProgramAccounts on Solana - Response times under 10ms

`getProgramAccounts` is one of the most expensive calls on Solana. On a standard RPC node, it scans raw *account* states on every request - slow by design, and worse under load. The root cause is structural: standard nodes have no index over account data, so every call triggers the same full scan regardless of how specific your filter is.

This is exactly what Shyft solves - Introducing **Accelerated getProgramAccounts**.

Shyft's Accelerated `getProgramAccounts` (or Accelerated gPA) <mark style="color:yellow;">resolves</mark> the most <mark style="color:yellow;">common</mark> queries in <mark style="color:yellow;">under 10ms</mark>, no code changes required.

{% hint style="success" %}
Accelerated `getProgramAccounts` is available on all paid plans. Already live on Shyft RPC across all regions. No API changes - same method, same parameters, dramatically faster responses.
{% endhint %}

### Why the standard `getProgramAccounts` is slow?

A vanilla Solana validator has no index over account data. When you call `getProgramAccounts` with a `memcmp` filter, the node walks every account owned by that program and compares bytes at the given offset - one by one, on-the-fly, every time. For large programs like Raydium or the Token Program, which own millions of accounts, this can take anywhere from hundreds of milliseconds to tens of seconds.

<figure><img src="/files/haVha0w71jgFoOJW5VUj" alt=""><figcaption><p>What happens when we call getProgramAccounts on Solana</p></figcaption></figure>

### How it works

Standard Solana RPC nodes handle everything - *block replay, vote processing, account state, and RPC* queries - in one tightly coupled stack. When a `getProgramAccounts` call comes in, it competes for resources with everything else the validator is doing, and scans raw account state on every request.

Shyft's approach is different. The accounts engine runs on entirely separate hardware, <mark style="color:yellow;">decoupled from the RPC layer</mark>. It has one job: maintain a fast, structured view of account data for the programs and offsets that matter most, and serve read requests against it.

#### The single-process architecture

The entire engine runs as a single unified process - no external database connections, no network hops between components. Three responsibilities, one process:

* **gRPC ingestion:** Streams account updates directly from the validator layer as they happen on-chain.
* **RocksDB indexing:** Writes account state into an embedded key-value store, keyed by program + offset.
* **Stateless JSON-RPC:** Serves `getProgramAccounts` reads directly from RocksDB - no external calls.

<figure><img src="/files/4TRbqgwdgEihG98vDXoe" alt=""><figcaption><p>The Shyft Accounts Engine: How It Works</p></figcaption></figure>

#### How acceleration is triggered

When a `getProgramAccounts` request arrives at the JSON-RPC layer, the engine checks two things: is this program in the accelerated set, and does the `memcmp` offset match a keyed index for that program? If both match, the result is served directly from RocksDB. If either condition is not met, the request falls through to the standard RPC path transparently - same response, just without the speed benefit.

{% hint style="info" %}
**No code changes required.** Acceleration is applied at the RPC layer automatically. Your existing `getProgramAccounts` calls work as-is - the engine intercepts matching requests before they ever touch raw ledger state.
{% endhint %}

> **On-demand Acceleration: New program + offset combinations can be added in real time**
>
> The engine currently covers a pre-defined set of programs and offsets selected based on query patterns across the Shyft network. But new indexes are not a deployment - they are created on demand. If you regularly query a program or offset not yet in the accelerated set, reach out to the Shyft team. The index is created without downtime or service interruption, and acceleration applies from that point forward.

### Accelerated programs & offsets

The following program + offset combinations are accelerated. Calls that match are served from the Shyft accounts engine.

<table><thead><tr><th width="199">Protocol</th><th width="392">Program address</th><th>Accelerated offsets</th></tr></thead><tbody><tr><td>Pump.fun AMM</td><td>pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA</td><td>43,75</td></tr><tr><td>Raydium CLMM</td><td>CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK</td><td>73, 105</td></tr><tr><td>Raydium AMM v4</td><td>675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8</td><td>400, 432</td></tr><tr><td>Raydium CPMM</td><td>CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C</td><td>168, 200</td></tr><tr><td>Meteora DLMM</td><td>LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo</td><td>88, 120</td></tr><tr><td>Meteora DAMM v2</td><td>cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG</td><td>168, 200</td></tr><tr><td>Meteora DAMM v1</td><td>Eo7WjKq67rjJQSZxS6z3YkapzY3eMj6Xy8X5EQVn5UaB</td><td>40, 72</td></tr><tr><td>Orca Whirlpool</td><td>whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc</td><td>101, 181</td></tr><tr><td>Drift</td><td>dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN</td><td>136</td></tr><tr><td>PancakeSwap CLMM</td><td>HpNfyc2Saw7RKkQd8nEL4khUcuPhQ7WwY1B2qjx8jxFq</td><td>73, 105</td></tr><tr><td>Address Lookup Table</td><td>AddressLookupTab1e1111111111111111111111111111</td><td>22</td></tr><tr><td>Solana Stake Program</td><td>Stake11111111111111111111111111111111111111</td><td>12</td></tr></tbody></table>

{% hint style="info" %}
**Need a program added?** New indexes are created on demand without downtime. Reach out to the Shyft team with the program address and the offsets you query regularly.
{% endhint %}

### How the Engine Handles Multiple Filters

Most real-world `getProgramAccounts` calls don't use a single filter. A trading bot querying Raydium CLMM pools might filter by `token_mint_a` at offset 73 *and* by `token_mint_b` at offset 107 simultaneously - narrowing the result to pools containing a specific trading pair. Here's how the engine handles it:&#x20;

**When one of your filters hits an accelerated offset:**

The engine scans your filter set, identifies the accelerated offset, and resolves that filter first - regardless of where you placed it in the array. The accelerated lookup runs against the purpose-built index and returns a narrow result set immediately. Every remaining filter is then evaluated in-memory against that already-narrow set. <mark style="color:yellow;">**Filter order**</mark>**&#x20;in your request&#x20;**<mark style="color:yellow;">**does not matter**</mark>**&#x20;- the engine&#x20;**<mark style="color:yellow;">**finds the fast path automatically**</mark>**.**

```json
{
  // example when accelerated offset is provided later
  "filters": [
    { "memcmp": { "offset": 107, "bytes": "USDC_MINT_PUBKEY" } },  
    { "memcmp": { "offset": 73,  "bytes": "WSOL_MINT_PUBKEY" } } 
    // the accelerated offset is picked first automatically  
  ]
}
```

Even though the accelerated offset `73` is second in the array, the engine resolves it first. The result is every CLMM pool where `token_mint_a` is WSOL - filtered further in-memory to those where `token_mint_b` is USDC. Two filters, one fast path.

**When none of your filters hit an accelerated offset:**

The engine falls through to the standard scan path — filters evaluated in order, full\
account set, no short-circuit. The request completes correctly, just without the speed\
benefit.&#x20;

{% hint style="info" %}
**For programs in the accelerated set,&#x20;**<mark style="color:yellow;">**including at least one filter**</mark>**&#x20;at an accelerated offset is all it takes — the engine handles the rest.**
{% endhint %}

### Quick Start

A working example for `getProgramAccounts` Pump.fun AMM at offset 43 - in cURL, JavaScript & Rust - the fastest way to see the latency difference yourself.

{% tabs %}
{% tab title="cURL" %}

```bash
curl --location 'https://rpc.shyft.to/?api_key=YOUR-API-KEY' \
--header 'Content-Type: application/json' \
--data '{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "getProgramAccounts",
    "params": [
        "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA",
        {
            "commitment": "confirmed",
            "encoding": "base64",
            "filters": [
                {
                    "memcmp": {
                        "bytes": "T4T8I/7SrQyFRxwvhoh/IzjSO8qinIinMl3nI/a4le8=",
                        "encoding": "base64",
                        "offset": 43
                    }

                }
            ]
        }
    ]
}'
```

{% endtab %}

{% tab title="JavaScript" %}
{% code overflow="wrap" %}

```javascript
const API_KEY = "YOUR_API_KEY";
const RPC_URL = `https://rpc.shyft.to/?api_key=${API_KEY}`;

const payload = {
  id: 1,
  jsonrpc: "2.0",
  method: "getProgramAccounts",
  params: [
    "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA",
    {
      commitment: "confirmed",
      encoding: "base64",
      filters: [
        {
          memcmp: {
            offset: 43, //replace with offset needed
            bytes: "T4T8I/7SrQyFRxwvhoh/IzjSO8qinIinMl3nI/a4le8=", //replace with required bytes
            encoding: "base64",
          },
        },
      ],
    },
  ],
};

async function main() {
  const start = Date.now();

  const res = await fetch(RPC_URL, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(payload),
  });

  const data = await res.json();
  const elapsed = Date.now() - start;

  if (data.error) {
    console.error("RPC error:", data.error);
    return;
  }

  console.log(`accounts found : ${data.result.length}`);
  console.log(`latency        : ${elapsed}ms`);
  console.log(`first account  :`, data.result[0]?.pubkey ?? "none");
}

main();
```

{% endcode %}
{% endtab %}

{% tab title="Rust" %}

```rust
// Cargo.toml dependencies:
// reqwest = { version = "0.12", features = ["json"] }
// tokio   = { version = "1",    features = ["full"] }
// serde   = { version = "1",    features = ["derive"] }
// serde_json = "1"

use serde_json::{json, Value};
use std::time::Instant;

const API_KEY: &str = "YOUR_API_KEY";
const RPC_URL: &str = "https://rpc.shyft.to/";

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let url = format!("{}?api_key={}", RPC_URL, API_KEY);

    let payload = json!({
        "id": 1,
        "jsonrpc": "2.0",
        "method": "getProgramAccounts",
        "params": [
            "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA",
            {
                "commitment": "confirmed",
                "encoding": "base64",
                "filters": [
                    {
                        "memcmp": {
                            "offset": 43, //replace with needed offset
                            "bytes": "T4T8I/7SrQyFRxwvhoh/IzjSO8qinIinMl3nI/a4le8=",
                            "encoding": "base64"
                        }
                    }
                ]
            }
        ]
    });

    let client = reqwest::Client::new();
    let start = Instant::now();

    let res = client
        .post(&url)
        .json(&payload)
        .send()
        .await?
        .jsonValue>()
        .await?;

    let elapsed = start.elapsed();

    if let Some(err) = res.get("error") {
        eprintln!("RPC error: {}", err);
        return Ok(());
    }

    let accounts = res["result"].as_array().map(|a| a.len()).unwrap_or(0);
    let first = &res["result"][0]["pubkey"];

    println!("accounts found : {}", accounts);
    println!("latency        : {}ms", elapsed.as_millis());
    println!("first account  : {}", first);

    Ok(())
}
```

{% endtab %}
{% endtabs %}

{% hint style="success" %}
Filter order does not matter. The engine automatically identifies the accelerated offset from whichever filters you pass and resolves it first - returning a narrow result set from the purpose-built index. Any additional filters are then applied against that already-narrow result set in memory.
{% endhint %}

### Latency results

Tests were run from the AMS region, 10 requests at 1 req/s using [Hey](https://github.com/rakyll/hey) with a persistent TCP connection. Four programs were tested, each at one of their accelerated offsets.

| Program              | Offset | Avg    | p50    | p90    |
| -------------------- | ------ | ------ | ------ | ------ |
| Raydium CLMM         | 73     | 8.7ms  | 7.8ms  | 15.2ms |
| Pump.fun AMM         | 43     | 8.3ms  | 7.9ms  | 11.7ms |
| Address Lookup Table | 22     | 10.9ms | 10.7ms | 15.4ms |
| Orca Whirlpool       | 101    | 8.2ms  | 7.8ms  | 12.4ms |

{% hint style="success" %}
**What to expect in production:** With a persistent TCP connection and repeated calls, the majority of accelerated gPA queries resolve between 10-15ms. A cold first request from a fresh TCP handshake adds approximately 5-10ms.
{% endhint %}

{% hint style="info" %}
Tests used [Hey](https://github.com/rakyll/hey), which keeps the TCP connection open after the first request - representative of real application behaviour where connections are reused.
{% endhint %}

### Frequently Asked Questions

<details>

<summary>How do I know if my request was accelerated?</summary>

You don't need to - and that's intentional. If your request matches an accelerated program + offset, it resolves faster. If it doesn't, it falls through to the standard path. The response format is identical in both cases.

</details>

<details>

<summary>What exactly is the "offset" in a memcmp filter, and how was it determined?</summary>

Every account on Solana stores its data as a raw byte buffer. The structure of that buffer - which fields live at which byte positions - is defined by the program that owns the account. This layout is typically described in the program's IDL (Interface Definition Language).

The `offset` in a `memcmp` filter tells the RPC node: "start reading at byte N in the account data buffer, and compare those bytes against my value." So `offset: 73` on Raydium CLMM means "compare starting at byte 73 of each pool account's data." Byte 73 in a CLMM pool account is where the `token_mint_a` field begins - so filtering there lets you find all pools involving a specific token.

You derive the correct offset by reading the program's IDL or inspecting its account struct definitions in the source code. For Anchor-based programs, each field has a known size and they stack sequentially - so you sum the byte sizes of all fields before the one you want. Shyft identified the most commonly queried fields across each protocol and accelerated those specific offsets.

{% hint style="info" %}
**Practical tip:** If you're using a protocol SDK (e.g. `@raydium-io/raydium-sdk` or `@orca-so/whirlpools-sdk`), the SDK usually constructs the correct `memcmp` filter for you - you don't need to calculate the offset manually.
{% endhint %}

</details>

<details>

<summary>What do you pass as the "bytes" value in the filter?</summary>

The `bytes` value is whatever you're filtering *for* at that offset - encoded as base58 (default) or base64 depending on the `encoding` you specify. It is not a fixed value; it's the specific thing you're looking up.

In most DeFi use cases, the field at an accelerated offset is a public key - a token mint address, a pool authority, or a user wallet. So `bytes` is the base58 or base64 encoded public key you're searching for.

```json
{
  "filters": [
    {
      "memcmp": {
        "offset": 73,
        "bytes": "So11111111111111111111111111111111111111112",
        "encoding": "base58"
      }
    }
  ]
}
```

{% hint style="warning" %}
**Empty results?** The most common cause is passing a base64-encoded value when encoding is set to base58, or vice versa. Double-check the `encoding` field matches how you've encoded the bytes.
{% endhint %}

</details>

<details>

<summary>What happens if I pass multiple memcmp filters at different offsets?</summary>

Filter order does not matter. The engine automatically identifies the accelerated offset from whichever filters you pass and resolves it first - returning a narrow result set from the purpose-built index. Any additional filters are then applied against that already-narrow result set in memory.

```json
{
  "filters": [
    { "memcmp": { "offset": 73,  "bytes": "TOKEN_MINT_PUBKEY" } },
    { "memcmp": { "offset": 200, "bytes": "SOME_OTHER_VALUE"  } } 
    //order doesn't matter
  ]
}
```

</details>

<details>

<summary>Is this available on all Shyft RPC plans?</summary>

Accelerated gPA is included on all paid Shyft RPC plans with no additional configuration. It is not available in the free plan.

</details>

<details>

<summary>Can I request acceleration for a program not on the list?</summary>

Yes. New indexes are not a deployment - they are created in real time on demand without downtime or service interruption. Reach out to the Shyft team with the program address and the offsets you query regularly.

</details>


# getTransactionsForAddress

A custom Solana RPC Method for Reading Historical Data With Advanced Filters And Pagination.

Fetching complete transaction data for a Solana address normally takes <mark style="color:yellow;">two steps</mark> : &#x20;

* **getSignaturesForAddress** to get signatures,&#x20;
* then a **getTransaction** call for each one \
  On top of that you have to take care of manual pagination, status filtering, and token account lookups on the client side.

<mark style="color:$primary;">**getTransactionsForAddress**</mark>**&#x20;**<mark style="color:yellow;">**collapses all of that into a single request**</mark>**, with filtering, pagination, and token account lookups handled server-side.**

{% hint style="success" %}

#### <mark style="color:$primary;">getTransactionForAddress</mark> is a custom RPC call provided by Shyft. It is not part of the standard Solana RPC interface. Currently 2 epochs of data is available.

{% endhint %}

A single call can return either signature-level information or full transaction payloads, apply slot/time/status/accounts filters before results are returned. Use pagination cursor to easily traverse historical data in either ascending or descending order.

### How It Compares to Standard Solana Methods

| Capability                   | getSignaturesForAddress + getTransaction  | getTransactionsForAddress    |
| ---------------------------- | ----------------------------------------- | ---------------------------- |
| Address history lookup       | 1 + N requests                            | 1 request                    |
| Pagination cursor            | Signature (`before`/`until`)              | Token (`paginationToken`)    |
| Server-side status filter    | ❌                                         | ✅ (`status`)                 |
| Server-side slot/time filter | ❌                                         | ✅ (`slot`, `blockTime`)      |
| Token-account fan-out        | Manual (`getTokenAccountsByOwner` + loop) | ✅ (`tokenAccounts`)          |
| Full transaction payload     | Separate `getTransaction` call per sig    | `transactionDetails: "full"` |

### Example Request

Let's look at a basic <mark style="color:$primary;">getTransactionsForAddress</mark> call to understand different options it provides.

{% tabs %}
{% tab title="cURL" %}
{% code overflow="wrap" %}

```bash
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getTransactionsForAddress",
    "params": [
        "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA",
        {
            "transactionDetails": "signatures", 
            "sortOrder": "asc",
            "limit": 1000,
            "paginationToken": null,
            "commitment": "confirmed"
            "filters": {
                "slot": {
                    "gte": 425211949 //Any slot number you want
                },
                "status": "any",
                "tokenAccounts": "none"
            }
        }
    ]
}
```

{% endcode %}
{% endtab %}

{% tab title="Response" %}
{% code overflow="wrap" %}

```json
{
    "jsonrpc": "2.0",
    "id": 1,
    "result": {
        "data": [
            {
                "signature": "4LBedoHUMeh1sDr3EqKiYcyGLT4dQQgLLEqqz76k5DSVzCtyMaXHmKGt85kEjXMkQYoiXUKnMBFpn78ziWtfzzcm",
                "slot": 425756281,
                "transactionIndex": 999,
                "err": null,
                "memo": null,
                "blockTime": 1781178051,
                "confirmationStatus": "finalized"
            },
            {
                "signature": "X6DrkpMF9pQXQJqwGRdQwz7qMJSanR22oRw8mg1DP8ukihj4pk9NS1ijpEgPCnxopCcnhXw2vrdmAxRBKzTjWp4",
                "slot": 425756281,
                "transactionIndex": 992,
                "err": null,
                "memo": null,
                "blockTime": 1781178051,
                "confirmationStatus": "finalized"
            },
            //response shortened for visibility
        ],
        "paginationToken": "425756281:979"
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

Understand what each parameter in the request stands for:

<table><thead><tr><th width="114">Option</th><th width="116">Type</th><th width="128">Default</th><th>Description</th></tr></thead><tbody><tr><td>transactionDetails</td><td>signatures | full</td><td>signatures</td><td>Controls response payload. </td></tr><tr><td>sortOrder</td><td>asc | desc</td><td>desc</td><td>Sort direction by slot and transaction position within the block.</td></tr><tr><td>limit</td><td>number</td><td>1000 (signatures) / 100 (full)</td><td>Maximum number of results per page. Hard cap is 1000 for signatures and 100 for full. Exceeding the cap returns a <code>-32602</code> error — it does not silently clamp.</td></tr><tr><td>paginationToken</td><td>string</td><td>null</td><td>Cursor returned by a previous response. Pass this value to fetch the next page. Cursors are opaque — do not construct or modify them.</td></tr><tr><td>commitment</td><td>confirmed | finalized</td><td>finalized</td><td>Commitment level for the query. Matches the semantics of <code>getSignaturesForAddress</code>.</td></tr><tr><td>minContextSlot</td><td>number</td><td>—</td><td>If provided, the node returns an error if it hasn't yet processed up to this slot. Use this when you've just sent a transaction and want to guarantee the node you're querying has advanced past that slot before returning results — otherwise you might query a slightly behind node and miss the transaction you just submitted.</td></tr><tr><td>encoding</td><td>json | jsonParsed | base58 | base64</td><td><code>json</code></td><td>Encoding for the transaction payload. Only relevant when <code>transactionDetails</code> is <code>full</code>. Matches <code>getTransaction</code> encoding behavior.</td></tr><tr><td>maxSupportedTransactionVersion</td><td>number</td><td>—</td><td>Maximum transaction version to return in the response. Requests without this field return an error if any result is a versioned transaction. Set to <code>0</code> to support all current transaction versions. Only relevant when <code>transactionDetails</code> is <code>full</code>.</td></tr><tr><td>filters</td><td>object</td><td>—</td><td>Optional filters applied server-side before results are returned. See below.</td></tr></tbody></table>

***

### Limits and error behavior

The `limit` defaults differ because the payload sizes differ significantly, a response of 1000 signature objects is still small, while 100 full transaction objects can be several megabytes depending on instruction data. Exceeding them returns an error immediately; the server does not silently clamp and return a partial result.

* "transactionDetails": "full", limit: 100
* "transactionDetails": "signatures", limit: 1000

Exceeding these limits will result in the below error:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32602,
    "message": "limit too large (max 100/1000)"
  }
}
```


# Filters

Available Filters for getTransactionsForAddress - Slot Range, Block Time, Status, Signature and Token Accounts

By default, `getTransactionsForAddress` <mark style="color:yellow;">returns</mark> all transactions for an address in <mark style="color:yellow;">reverse chronological order</mark>. <mark style="color:yellow;">Filters</mark> let you <mark style="color:yellow;">narrow</mark> that <mark style="color:yellow;">result set</mark> on the server before anything is returned - so you're not pulling down thousands of transactions and discarding most of them on the client.

Following filters are available:&#x20;

* **slot** - for slot based scans,
* **blockTime -** for time-range scans,&#x20;
* **signature -** for ledger-position bounds,&#x20;
* **status -** for filtering by execution outcome, and&#x20;
* **tokenAccounts -** for expanding or restricting coverage to SPL token accounts owned by the address. All filters are optional and can be combined in a single request.

Filters are passed as a nested `filters` object inside the options parameter. Comparison-based filters (`slot`, `blockTime`, `signature`) accept a comparison object with one or more operators (`gte`, `gt`, `lte`, `lt`, `eq`) so you can express both open-ended bounds and closed ranges.

### Available Filters

| Filter        | Type                          | Description                                                                                                                                            |
| ------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| slot          | comparison object             | Filter by slot number. Supports `gte`, `gt`, `lte`, `lt`.                                                                                              |
| blockTime     | comparison object             | Filter by Unix timestamp. Supports `gte`, `gt`, `lte`, `lt`, `eq`.                                                                                     |
| signature     | comparison object             | Filter by signature position within the ledger. Supports `gte`, `gt`, `lte`, `lt`. Rarely needed — prefer `slot` or `paginationToken` for range scans. |
| status        | any \| succeeded \| failed    | Filter by transaction outcome. `any` returns both. Corresponds to `meta.err === null` (succeeded) or non-null (failed).                                |
| tokenAccounts | none \| balanceChanged \| all | Controls token-account fan-out. See Token Account Filtering below.                                                                                     |

**Comparison object example**

```json
{
  "gte": 425214949,
  "lt":  425215949
}
```

Multiple comparison operators can be combined in a single filter to express a range.

### Slot, Block time & Signature Filtering

**Slot**

Filters by the <mark style="color:yellow;">slot number</mark> a transaction was confirmed in. Accepts `gte`, `gt`, `lte`, `lt`. Use a single operator for an open-ended bound, or combine two to express a closed range:

```json
"slot": { "gte": 425214949, "lt": 425215949}
```

**Blocktime**

Filters by the <mark style="color:yellow;">Unix timestamp</mark> of the block. Accepts `gte`, `gt`, `lte`, `lt`, and also `eq` for an exact match. Works the same way as `slot` but in wall-clock time:

```json
"blockTime": { "gte": 1780963204, "lt": 1780963600}
```

**Signature**

Filters by a <mark style="color:yellow;">transaction's position in the ledger</mark> relative to a known signature. Accepts `gte`, `gt`, `lte`, `lt` - no `eq`, since you'd just query that signature directly. Works the same way structurally as `slot` and `blockTime`:

```json
"signature": { "gt": "5wHu1qwD4E5ZPx..." }
```

***

The key difference between the three: `slot` and `signature` are ledger-native (always present, always reliable), while `blockTime` can be `null` for very old blocks. For deep historical scans, prefer `slot`.

***

### Token Account Filtering

By default, `getTransactionsForAddress` only returns transactions where the queried address appears directly in `accountKeys`. Setting `tokenAccounts` expands this to include transactions that touched token accounts owned by that address.

<table><thead><tr><th width="160">Value</th><th>Behavior</th></tr></thead><tbody><tr><td><code>none</code></td><td>Only transactions where the address appears directly in <code>accountKeys</code>. Default.</td></tr><tr><td><code>all</code></td><td>Also includes transactions that reference any token account owned by the address, regardless of whether a balance change occurred.</td></tr><tr><td><code>balanceChanged</code></td><td>Like <code>all</code>, but only for token accounts where the pre/post token balance metadata shows a change. Useful for filtering to actual transfers and swaps rather than read-only account references.</td></tr></tbody></table>

Token ownership is determined from the `meta.preTokenBalances` and `meta.postTokenBalances` fields embedded in the transaction, not from a separate on-chain lookup.

{% hint style="info" %}
When `tokenAccounts` is `all` or `balanceChanged`, the queried address may not appear in `accountKeys` at all for some results. The address is the *owner* of an account that participated — not a signer or fee payer in that transaction.
{% endhint %}

{% tabs %}
{% tab title=""signatures" mode" %}
**Signatures mode (`transactionDetails: "signatures"`)**

{% code overflow="wrap" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "data": [
      {
        "signature": "TransactionSignatureBase58",
        "slot": 250000001,
        "transactionIndex": 12,
        "err": null,
        "memo": null,
        "blockTime": 1780963600,
        "confirmationStatus": "finalized"
      }
    ],
    "paginationToken": "425214939:34"
  },
  "id": 1
}
```

{% endcode %}

**Response fields**

<table><thead><tr><th width="191">Field</th><th width="113">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>signature</code></td><td>string</td><td>Base58-encoded transaction signature.</td></tr><tr><td><code>slot</code></td><td>u64</td><td>The slot this transaction was confirmed in.</td></tr><tr><td><code>transactionIndex</code></td><td>number</td><td>The transaction's position within its block. Zero-indexed. Useful for deterministic ordering when multiple transactions share a slot.</td></tr><tr><td><code>err</code></td><td>object | null</td><td><code>null</code> if the transaction succeeded. Otherwise contains the <code>TransactionError</code> object. Mirrors the <code>err</code> field from <code>getSignaturesForAddress</code>.</td></tr><tr><td><code>memo</code></td><td>string | null</td><td>Memo program message attached to the transaction, if any.</td></tr><tr><td><code>blockTime</code></td><td>i64 | null</td><td>Estimated Unix timestamp of the block. <code>null</code> for very old blocks where this wasn't recorded.</td></tr><tr><td><code>confirmationStatus</code></td><td>string</td><td>Confirmation status: <code>processed</code>, <code>confirmed</code>, or <code>finalized</code>.</td></tr><tr><td><code>paginationToken</code></td><td>string | null</td><td>Cursor for the next page. <code>null</code> when there are no more results.</td></tr></tbody></table>
{% endtab %}

{% tab title=""full" mode" %}
**Full transaction mode (`transactionDetails: "full"`)**

```json
{
  "jsonrpc": "2.0",
  "result": {
    "data": [
      {
        "slot": 250000001,
        "transactionIndex": 12,
        "blockTime": 1700000000,
        "transaction": { ... },
        "meta": { ... }
      }
    ],
    "paginationToken": "250000001:12"
  },
  "id": 1
}
```

Each item in `data` corresponds to a single confirmed transaction. The `transaction` and `meta` fields are identical in structure to what `getTransaction` returns for the same signature and encoding. Refer to the [`getTransaction` response structure](https://solana.com/docs/rpc/http/gettransaction) for full field documentation.

{% hint style="warning" %}
**Versioned transactions:** If any result in the page is a versioned transaction (version `0` or higher), the request will fail unless `maxSupportedTransactionVersion` is set. Set it to `0` to handle all current transaction versions - this mirrors the same requirement in `getTransaction`.
{% endhint %}
{% endtab %}
{% endtabs %}

### Pagination

When a response includes a non-null `paginationToken`, there are more results. Pass the token in the next request unchanged to continue scanning from where the previous page ended.

```json
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "getTransactionsForAddress",
  "params": [
    "AddressBase58",
    {
      "limit": 100,
      "paginationToken": "425214939:34"
    }
  ]
}
```

**Understanding the token structure**

The pagination token is two numbers separated by a colon:

```
"paginationToken": "425214939:34"
```

The first number is the **slot** - the block the last returned transaction was confirmed in. The second number is the **transactionIndex** - the zero-indexed position of that transaction within that block. So `250000101:5` means the 6th transaction in slot `250000101`.

This two-part structure is more precise than a signature-based cursor. A signature alone doesn't tell you where in a block a transaction sat - two transactions in the same slot have different signatures but you can't derive their ordering from those signatures alone. The `slot:transactionIndex` pair pins the exact position in the ledger, so resumption is always deterministic.

### How to Paginate?

A single request only returns up to your `limit`. When more transactions exist, <mark style="color:yellow;">the response contains a</mark> <mark style="color:yellow;"></mark><mark style="color:yellow;">`paginationToken`</mark> <mark style="color:yellow;"></mark><mark style="color:yellow;">you can pass into the next request to continue fetching</mark>. It's a `"slot:transactionIndex"` <mark style="color:yellow;">string</mark> pointing to the last result returned.

{% tabs %}
{% tab title="JavaScript" %}
{% code overflow="wrap" %}

```javascript
async function printAllTransactions(address) {
  let paginationToken = null;
  let totalFetched = 0;

  do {
    const response = await fetch("https://rpc.shyft.to?api_key=YOUR-API-KEY", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        jsonrpc: "2.0",
        id: 1,
        method: "getTransactionsForAddress",
        params: [address, { limit: 100, paginationToken }]
      })
    });

    const { result } = await response.json();

    result.data.forEach(tx => console.log(tx));
    totalFetched += result.data.length;
    console.log(`Fetched ${totalFetched} transactions so far...`);

    paginationToken = result.paginationToken;

  } while (paginationToken !== null);

  console.log(`Done. Total transactions fetched: ${totalFetched}`);
}

printAllTransactions("AddressBase58");
```

{% endcode %}
{% endtab %}

{% tab title="Rust" %}
{% code overflow="wrap" %}

```rs
use reqwest::Client;
use serde_json::{json, Value};

#[tokio::main]
async fn main() {
    let client = Client::new();
    let address = "AddressBase58";
    let mut pagination_token: Option<String> = None;
    let mut total_fetched = 0;

    loop {
        let response = client
            .post("https://rpc.shyft.to?api_key=YOUR_KEY")
            .json(&json!({
                "jsonrpc": "2.0",
                "id": 1,
                "method": "getTransactionsForAddress",
                "params": [address, { "limit": 100, "paginationToken": pagination_token }]
            }))
            .send()
            .await
            .unwrap()
            .json::<Value>()
            .await
            .unwrap();

        let data = response["result"]["data"].as_array().unwrap();

        for tx in data {
            println!("{:#?}", tx);
        }

        total_fetched += data.len();
        println!("Fetched {} transactions so far...", total_fetched);

        pagination_token = response["result"]["paginationToken"]
            .as_str()
            .map(|s| s.to_string());

        if pagination_token.is_none() {
            break;
        }
    }

    println!("Done. Total transactions fetched: {}", total_fetched);
}
```

{% endcode %}
{% endtab %}
{% endtabs %}


# Code Examples

A few code examples related to getTransactionsForAddress on Solana

### Fetching Transactions by Order

Traverse an address's full history forwards in time — something that wasn't possible with a single `getSignaturesForAddress` call.

#### Newest first (default)

Fetches the 100 most recent transactions for an address, starting from the latest and going backwards in time. This is the default behavior — useful when you want to see what happened most recently on a wallet.

{% tabs %}
{% tab title="JavaScript" %}
{% code overflow="wrap" %}

```javascript
const response = await fetch("https://rpc.shyft.to?api_key=YOUR_API_KEY", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "getTransactionsForAddress",
    params: [
      "5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h", // base58 address to fetch transactions for
      {
        sortOrder: "desc", //sort order descending (default behavior)
        limit: 100
      }
    ]
  })
});

const { result } = await response.json();
result.data.forEach(tx => console.log(tx));
```

{% endcode %}
{% endtab %}

{% tab title="Rust" %}
{% code overflow="wrap" %}

```rust
use reqwest::Client;
use serde_json::{json, Value};

#[tokio::main]
async fn main() {
    let client = Client::new();

    let response = client
        .post("https://rpc.shyft.to?api_key=YOUR_API_KEY")
        .json(&json!({
            "jsonrpc": "2.0",
            "id": 1,
            "method": "getTransactionsForAddress",
            "params": [
                "5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h",  // base58 address to fetch transactions for
                {
                    "sortOrder": "desc", //sort order descending (default behavior)
                    "limit": 100
                }
            ]
        }))
        .send()
        .await
        .unwrap()
        .json::<Value>()
        .await
        .unwrap();

    let transactions = response["result"]["data"].as_array().unwrap();
    for tx in transactions {
        println!("{:#?}", tx);
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

#### Oldest First

Fetches transactions starting from the earliest recorded activity for the address and moves forward in time. Useful when you want to replay an address's history from the beginning - for example, reconstructing the full transaction timeline of a wallet, or fetching its first ever transaction.

{% hint style="success" %}
With sortOrder: "asc", you can fetch an **address's transactions starting from its very first - directly**, without having to paginate backwards through thousands of results first.
{% endhint %}

{% tabs %}
{% tab title="JavaScript" %}
{% code overflow="wrap" %}

```javascript
const response = await fetch("https://rpc.shyft.to?api_key=YOUR_API_KEY", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "getTransactionsForAddress",
    params: [
      "5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h", // base58 address to fetch transactions for
      {
        sortOrder: "asc", // order ascending: traverse history from the beginning
        limit: 100
      }
    ]
  })
});

const { result } = await response.json();
result.data.forEach(tx => console.log(tx));
```

{% endcode %}
{% endtab %}

{% tab title="Rust" %}
{% code overflow="wrap" %}

```rust
use reqwest::Client;
use serde_json::{json, Value};

#[tokio::main]
async fn main() {
    let client = Client::new();

    let response = client
        .post("https://rpc.shyft.to?api_key=YOUR_API_KEY")
        .json(&json!({
            "jsonrpc": "2.0",
            "id": 1,
            "method": "getTransactionsForAddress",
            "params": [
                "5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h", // base58 address to fetch transactions for
                {
                    "sortOrder": "asc", // order ascending: traverse history from the beginning
                    "limit": 100
                }
            ]
        }))
        .send()
        .await
        .unwrap()
        .json::<Value>()
        .await
        .unwrap();

    let transactions = response["result"]["data"].as_array().unwrap();
    for tx in transactions {
        println!("{:#?}", tx);
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="danger" %}
Shyft RPC retains up to <mark style="color:yellow;">3-4 days</mark> of transaction history. With `sortOrder: "asc"`, you get the oldest transaction available in that window — not necessarily the genesis transaction for the address.
{% endhint %}

### Fetch token balance changes for an owner address

The `balanceChanged` filter tells the server to find all SPL token accounts owned by the queried owner address and return only the transactions where a token balance actually changed.

{% tabs %}
{% tab title="JavaScript" %}
{% code overflow="wrap" %}

```javascript
const response = await fetch("https://rpc.shyft.to?api_key=YOUR_API_KEY", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "getTransactionsForAddress",
    params: [
      "DNfuF1L62WWyW3pNakVkyGGFzVVhj4Yr52jSmdTyeBHm", // add owner address(base58) for fetching transactions
      {
        filters: { tokenAccounts: "balanceChanged" } 
        // token account filter: include transactions that changed the balance of a token account owned by the owner address.
      }
    ]
  })
});

const { result } = await response.json();
result.data.forEach(tx => console.log(tx));
```

{% endcode %}
{% endtab %}

{% tab title="Rust" %}
{% code overflow="wrap" %}

```rs
use reqwest::Client;
use serde_json::{json, Value};

#[tokio::main]
async fn main() {
    let client = Client::new();

    let response = client
        .post("https://rpc.shyft.to?api_key=YOUR_API_KEY")
        .json(&json!({
            "jsonrpc": "2.0",
            "id": 1,
            "method": "getTransactionsForAddress",
            "params": [
                "DNfuF1L62WWyW3pNakVkyGGFzVVhj4Yr52jSmdTyeBHm", // add owner address(base58) for fetching transactions
                { "filters": { "tokenAccounts": "balanceChanged" } } // include transactions that changed the balance of a token account owned by the owner address.
            ]
        }))
        .send()
        .await
        .unwrap()
        .json::<Value>()
        .await
        .unwrap();

    let transactions = response["result"]["data"].as_array().unwrap();
    for tx in transactions {
        println!("{:#?}", tx);
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Fetch transactions within a slot range

The `slot` filter tells the server to return only transactions confirmed within the given slot range.

{% tabs %}
{% tab title="JavaScript" %}
{% code overflow="wrap" %}

```javascript
const response = await fetch("https://rpc.shyft.to?api_key=YOUR_API_KEY", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "getTransactionsForAddress",
    params: [
      "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", // base58 address for which txns will be fetched
      {
        filters: {
          slot: { gte: 332390000, lt: 332399000 } // slot range filter
        }
      }
    ]
  })
});

const { result } = await response.json();
result.data.forEach(tx => console.log(tx));
```

{% endcode %}
{% endtab %}

{% tab title="Rust" %}
{% code overflow="wrap" %}

```rs
use reqwest::Client;
use serde_json::{json, Value};

#[tokio::main]
async fn main() {
    let client = Client::new();

    let response = client
        .post("https://rpc.shyft.to?api_key=YOUR_API_KEY")
        .json(&json!({
            "jsonrpc": "2.0",
            "id": 1,
            "method": "getTransactionsForAddress",
            "params": [
                "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",  // base58 address for which txns will be fetched
                { "filters": { "slot": { "gte": 332390000, "lt": 332399000 } } } //slot range filter
            ]
        }))
        .send()
        .await
        .unwrap()
        .json::<Value>()
        .await
        .unwrap();

    let transactions = response["result"]["data"].as_array().unwrap();
    for tx in transactions {
        println!("{:#?}", tx);
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="info" %}
Since slot production speed varies slightly (validator skips, network conditions), don't rely on these estimates for precision time-based queries. If you need exact time ranges, use `blockTime` with Unix timestamps instead — it's more reliable for wall-clock scoping. Use `slot` when you already have a known reference slot from a previous query or transaction.
{% endhint %}

### Fetch successful transactions only

The `status: "succeeded"` filter tells the server to return only transactions that executed successfully - where `meta.err` is `null`. Failed transactions are excluded from the results.

{% tabs %}
{% tab title="JavaScript" %}
{% code overflow="wrap" %}

```javascript
const response = await fetch("https://rpc.shyft.to?api_key=YOUR_API_KEY", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "getTransactionsForAddress",
    params: [
      "TitanLozLMhczcwrioEguG2aAmiATAPXdYpBg3DbeKK", // base58 address for which the transactions will be fetched
      {
        filters: { status: "succeeded" }, //filtering transactions with status
        limit: 100
      }
    ]
  })
});

const { result } = await response.json();
result.data.forEach(tx => console.log(tx));
```

{% endcode %}
{% endtab %}

{% tab title="Rust" %}
{% code overflow="wrap" %}

```rust
use reqwest::Client;
use serde_json::{json, Value};

#[tokio::main]
async fn main() {
    let client = Client::new();

    let response = client
        .post("https://rpc.shyft.to?api_key=YOUR_API_KEY")
        .json(&json!({
            "jsonrpc": "2.0",
            "id": 1,
            "method": "getTransactionsForAddress",
            "params": [
                "TitanLozLMhczcwrioEguG2aAmiATAPXdYpBg3DbeKK", // base58 address for which the transactions will be fetched
                { "filters": { "status": "succeeded" }, "limit": 100 } //filtering txns with status 
            ]
        }))
        .send()
        .await
        .unwrap()
        .json::<Value>()
        .await
        .unwrap();

    let transactions = response["result"]["data"].as_array().unwrap();
    for tx in transactions {
        println!("{:#?}", tx);
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Fetch full transaction payloads

Setting `transactionDetails: "full"` returns the complete transaction payload - instructions, accounts, pre/post balances, logs, and metadata.

{% tabs %}
{% tab title="JavaScript" %}
{% code overflow="wrap" %}

```javascript
const response = await fetch("https://rpc.shyft.to?api_key=YOUR_API_KEY", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "getTransactionsForAddress",
    params: [
      "HLnpSz9h2S4hiLQ43rnSD9XkcUThA7B8hQMKmDaiTLcC", //base58 address for which txns are being fetched
      {
        transactionDetails: "full",
        encoding: "jsonParsed",
        maxSupportedTransactionVersion: 0,
        limit: 25 // maximum 100 transactions can be fetched in full mode
      }
    ]
  })
});

const { result } = await response.json();
result.data.forEach(tx => console.log(tx));
```

{% endcode %}
{% endtab %}

{% tab title="Rust" %}
{% code overflow="wrap" %}

```rs
use reqwest::Client;
use serde_json::{json, Value};

#[tokio::main]
async fn main() {
    let client = Client::new();

    let response = client
        .post("https://rpc.shyft.to?api_key=YOUR_API_KEY")
        .json(&json!({
            "jsonrpc": "2.0",
            "id": 1,
            "method": "getTransactionsForAddress",
            "params": [
                "HLnpSz9h2S4hiLQ43rnSD9XkcUThA7B8hQMKmDaiTLcC", //base58 address for which txns are being fetched
                {
                    "transactionDetails": "full",
                    "encoding": "jsonParsed",
                    "maxSupportedTransactionVersion": 0,
                    "limit": 25 // maximum 100 transactions can be fetched in full mode
                }
            ]
        }))
        .send()
        .await
        .unwrap()
        .json::<Value>()
        .await
        .unwrap();

    let transactions = response["result"]["data"].as_array().unwrap();
    for tx in transactions {
        println!("{:#?}", tx);
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

#### Common Filters for Reference

**`status`** : Filter by whether the transaction succeeded or failed on-chain. Use `succeeded` to exclude failed transactions, `failed` to inspect errors only, or `any` to return both. Maps directly to whether `meta.err` is null or not.

**`slot`** :  Scope your query to a block range. Useful when you know roughly when an event happened and want to avoid scanning the entire address history.

**`blockTime`** :  Same as `slot` but uses wall-clock Unix timestamps instead of slot numbers. Convenient when working with human-readable date ranges. Less reliable than `slot` for very old blocks where `blockTime` may be `null`.

**`tokenAccounts`** : Expand coverage to SPL token accounts owned by the queried address. Set to `balanceChanged` to include only transactions where a token balance actually changed - useful for transfer and swap history. Set to `all` to include any transaction that touched an owned token account regardless of balance change.

**`signature`** : Bound your query relative to a known transaction signature's ledger position. Rarely needed in practice - prefer `slot` for range scans and `paginationToken` for resuming pages.


# RabbitStream Overview

Stream Pre-execution Solana Transactions Directly from Turbine Shreds with gRPC Style Filters

Speed is everything on Solana. For sniping bots, MEV searchers, and high-frequency trading systems, the earliest possible transaction signal is the edge. That signal lives in <mark style="color:yellow;">shreds</mark>.

#### What are Shreds?&#x20;

When a block leader produces a block on Solana, it doesn't broadcast the full block, but breaks it into small, fixed-size packets called **shreds** — roughly 1,228 bytes each — and propagates them across the network via the **Turbine** protocol.&#x20;

Shreds are the earliest form of transaction data on Solana. They exist before any RPC node has processed anything, before any program has been executed, and before any logs have been written.

While shreds provide the <mark style="color:yellow;">earliest transaction signal</mark> on Solana, they <mark style="color:yellow;">don't</mark> carry the <mark style="color:yellow;">final execution details</mark> — like logs and confirmed results (Transaction `meta`) — still they contain enough information to power speed-critical strategies.

{% hint style="success" %}
[<mark style="color:green;">RabbitStream</mark>](https://shyft.to/solana-shreds-rabbitstream) extracts transactions directly from <mark style="color:yellow;">raw UDP shreds</mark> from multiple sources —\
independently of any RPC node — and delivers them through a Yellowstone-compatible gRPC interface. The RPC is never in the picture.
{% endhint %}

#### The Problem with Raw Shreds

While raw shreds offer unbeatable speed, working with them have their own challenges for developers:

* **Filters not available, Data Overload**: Shreds arrive as a firehose, meaning you get *every single transaction* on Solana—even the internal voting and failed ones—which creates a huge data load that's hard to handle. There is no way to isolate a  &#x20;specific program or account.
* **Complex Decoding**: The data <mark style="color:yellow;">structure</mark> of raw shreds is <mark style="color:yellow;">complex and binary-encoded</mark>, making them incompatible with standard Solana parsing libraries and requiring custom, time-consuming decoding logic.
* **Missing Transaction Context:** Since shreds are unconfirmed, they lack the full transaction metadata (meta), including program logs, inner instructions, and pre/post token balances. This limits them primarily to simple sniping strategies.
* **High Expense:** Few providers offer raw/decoded shred streams, and those that do are often priced out of reach for independent developers and smaller teams.

### Introducing RabbitStream: Shred Speed, gRPC Usability

RabbitStream is a <mark style="color:yellow;">real-time</mark> transaction stream that delivers data directly from raw UDP shreds — before transactions ever hit the RPC.

It <mark style="color:yellow;">does not run as a plugin</mark> inside a validator. Instead, it listens directly to <mark style="color:yellow;">raw UDP shreds from multiple sources</mark> as they propagate across the Solana network, performing its own shred reconstruction and validation independently. Decoded transactions are then streamed to your application through <mark style="color:yellow;">a Yellowstone-compatible gRPC interface</mark> — without touching any RPC node at any point.

It combines the delivery speed of shreds, and the usability and filtering power of Yellowstone gRPC.

<table><thead><tr><th width="235">Feature</th><th>What RabbitStream Delivers it</th></tr></thead><tbody><tr><td><strong>Independent from RPC</strong></td><td>RabbitStream is not a plugin inside an RPC node. It operates as an independent system, listening directly to raw UDP shreds on the Solana network. The RPC is never in the path.</td></tr><tr><td><strong>Multiple Shred Sources</strong></td><td>RabbitStream ingests shreds from multiple sources across the network simultaneously — maximising coverage and ensuring the earliest possible delivery.</td></tr><tr><td><strong>Yellowstone gRPC Filtering</strong></td><td>Use the <strong>exact same</strong> <code>SubscribeRequest</code> format as Yellowstone gRPC. Filter by <code>accountInclude</code>, <code>accountRequired</code>, and more—no complex decoding is required on your end.</td></tr><tr><td><strong>Compatible Transaction Structure</strong></td><td>Transactions are streamed with a structure similar to Yellowstone gRPC (minus the full meta data), making it instantly compatible with existing gRPC clients and processing logic.</td></tr><tr><td><strong>Ultra-Low Latency</strong></td><td>RabbitStream delivers transactions before the Replay stage runs — consistently arriving ahead of any RPC-based stream. </td></tr></tbody></table>

{% hint style="info" %}
To maximise coverage and reliability, RabbitStream ingests shreds from **multiple sources across the network simultaneously** — ensuring the earliest possible delivery regardless of which propagation path the shreds take.
{% endhint %}

### Allowed Filters in Rabbitstream: The Trade-Off

RabbitStream is designed for <mark style="color:yellow;">maximum speed</mark>, which means we get you the transaction data at the very start of the Solana process (Shredding).

Since RabbitStream <mark style="color:yellow;">capture the data before execution</mark> happens, certain information that is generated *later* in the pipeline is not available:

* <mark style="color:yellow;">**No Execution Metadata:**</mark> RabbitStream does not have fields that are created during the final processing stage (like logs, inner instructions, or precise error details).
* <mark style="color:yellow;">**Limited Filters:**</mark> Rabbitstream streams data from the pre-processed stage, and <mark style="color:yellow;">only transactions filters are allowed</mark>. It does **not allow** filtering by ***accounts*****,&#x20;*****blocks*****, or&#x20;*****slot number*** *directly* on the stream. This information is typically confirmed and compiled later by the RPC node.

<table><thead><tr><th>Filter type</th><th align="center">Yellowstone gRPC</th><th align="center" valign="top">RabbitStream</th></tr></thead><tbody><tr><td>transactions</td><td align="center">✅</td><td align="center" valign="top">✅</td></tr><tr><td>accounts</td><td align="center">✅</td><td align="center" valign="top">❌</td></tr><tr><td>slots</td><td align="center">✅</td><td align="center" valign="top">❌</td></tr><tr><td>blocks</td><td align="center">✅</td><td align="center" valign="top">❌</td></tr><tr><td>blocksMeta</td><td align="center">✅</td><td align="center" valign="top">❌</td></tr><tr><td>accountsDataSlice</td><td align="center">✅</td><td align="center" valign="top">❌</td></tr><tr><td>LUTs</td><td align="center">✅</td><td align="center" valign="top">✅*</td></tr></tbody></table>

{% hint style="info" %}
(\*) LUTs: 99%+ coverage vs. Yellowstone gRPCs
{% endhint %}

### Address Lookup Table (ALT) Resolution

RabbitStream resolves Address Lookup Tables (ALTs, also referred to as LUTs) at the shred stage. Filters like `accountInclude` now match against both static account keys and addresses referenced through a lookup table — no separate configuration or client changes required.

**Coverage**

Post-resolution, RabbitStream matches Yellowstone gRPC coverage on ALT-heavy programs (98.9%–99.9% in benchmarked testing), with no added latency to the shred-stage stream.

| Program                | Yellowstone gRPC | Before ALTR | After ALTR  | Match                                            |
| ---------------------- | ---------------- | ----------- | ----------- | ------------------------------------------------ |
| Meteora DLMM           | 40,427           | 5,897       | **40,369**  | 14.6% ➔ <mark style="color:yellow;">99.9%</mark> |
| pump.fun               | 131,675          | 106,349     | **131,548** | 80.8% ➔ <mark style="color:yellow;">99.9%</mark> |
| pump.fun AMM (pumpAmm) | 143,429          | 51,061      | **141,831** | 35.6% ➔ <mark style="color:yellow;">98.9%</mark> |

{% hint style="success" %}
**Note:** No action is required to enable this. If you're already subscribed with `accountInclude` filters, they now cover ALT-referenced accounts automatically.
{% endhint %}

#### Speed Advantage

We have already benchmarked RabbitStream's performance against standard Yellowstone gRPC by creating a simple Pump.fun Token Launch Detector. Our initial tests reveal a consistent <mark style="color:yellow;">speed advantage</mark> ranging from <mark style="color:yellow;">\~15ms to 100ms</mark>.

[Rabbitstream Token Detector Examples \[.ts\]](https://github.com/Shyft-to/yellowstone-grpc-vs-rabbitstream)

We feel this will be a huge unlock for a lot of devs and await **feedback** from the community.

### Frequently Asked Questions

<details>

<summary>How is RabbitStream different from Yellowstone gRPC?</summary>

Both use the same `SubscribeRequest` interface and support the same transaction filters, but they tap the validator pipeline at different stages. \
[<mark style="color:yellow;">Yellowstone gRPC</mark>](https://shyft.to/solana-yellowstone-grpc) emits transactions after the Replay stage — meaning execution has completed and you receive the full result, including logs, balance changes, and success/failure status. [<mark style="color:yellow;">RabbitStream</mark>](/solana-shredstreaming/rabbitstream-overview) taps the pipeline earlier, right after shreds are reconstructed but before any execution happens. \
You get the transaction intent much sooner, but without execution metadata.

</details>

<details>

<summary>Is RabbitStream the same as raw shred streaming?</summary>

No. Raw shreds are small binary-encoded packets, that arrive undecoded and completely <mark style="color:yellow;">unfiltered</mark> — which means your application receives every single transaction on Solana and must decode each one before it can determine whether it's even relevant.

RabbitStream removes both of those burdens. Shreds are decoded server-side, and transactions are filtered before they reach your application using the <mark style="color:yellow;">same</mark> <mark style="color:yellow;"></mark><mark style="color:yellow;">`SubscribeRequest`</mark> <mark style="color:yellow;"></mark><mark style="color:yellow;">interface as Yellowstone gRPC</mark>. You only receive the transactions you need — nothing more.

This has two practical benefits: your application ingests significantly less network traffic, and you never have to write or maintain custom shred decoding logic.

</details>

<details>

<summary>Can the same transaction appear in both RabbitStream and Yellowstone gRPC?</summary>

Yes, and this is the intended usage pattern. Subscribe to RabbitStream for earliest detection, then use Yellowstone to receive the confirmed result with full execution context. The transaction signature is the same in both streams, making it straightforward to correlate.

</details>

<details>

<summary>Can we receive failed transaction via RabbitStream?</summary>

Yes. RabbitStream delivers transactions before execution. A transaction may fail signature verification, run out of compute units, or land on a fork that is later abandoned. You must handle these cases in your application.

</details>

<details>

<summary>Do I need a separate client for RabbitStream?</summary>

No. RabbitStream uses the same SubscribeRequest format as Yellowstone gRPC, so existing Yellowstone gRPC clients work with minimal changes. The only difference is the `meta` part of the transaction (logMessages, innerInstructions etc) is not available on Transactions streamed via RabbitStream.&#x20;

</details>

<details>

<summary>How do i get access to RabbitStream?</summary>

RabbitStream is available on the **BUILD**, **GROW**, and **ACCELERATE** plans. No separate credentials are needed — authenticate using your existing gRPC token. You'll just need to point your client to the RabbitStream endpoint URL instead of the standard Yellowstone gRPC URL. Find out more about [<mark style="color:yellow;">connecting to RabbitStream</mark>](/solana-shredstreaming/how-to-stream-with-rabbitstream#access-and-authentication) here.

</details>

<details>

<summary>Where do i reach out in case of support?</summary>

If you have any queries, you can always reach out to us on [<mark style="color:yellow;">Shyft Discord</mark>](https://discord.gg/RXBmKSdVRe) or the Chat Support on your Shyft Dashboard.

</details>


# How to stream with RabbitStream

Rabbitstream Quickstart: Connecting with TypeScript and Rust

RabbitStream is designed to be a seamless, <mark style="color:yellow;">drop-in replacement</mark> for your existing Yellowstone gRPC clients, requiring only a change of endpoint URL.

{% hint style="info" %}

#### Beta-access already available for everyone with a <mark style="color:yellow;">Shyft gRPC</mark> token.

{% endhint %}

### Access and Authentication

RabbitStream requires a valid <mark style="color:yellow;">Shyft gRPC</mark> <mark style="color:yellow;">token</mark>. gRPC access is included with our *Build, Grow*, and *Accelerate* plans. Once you have your token, you can access the stream using the following regional endpoints:

| **Ams** (Amsterdam)        | `https://rabbitstream.ams.shyft.to/` |
| -------------------------- | ------------------------------------ |
| **VA** (Virginia, Ashburn) | `https://rabbitstream.va.shyft.to/`  |
| NY (New York)              | `https://rabbitstream.ny.shyft.to/`  |
| **Fra** (Frankfurt)        | `https://rabbitstream.fra.shyft.to/` |

### Connecting to RabbitStream: Client Examples

Once you have your Shyft gRPC Access Token, you can connect to Rabbitstream in the following manner:

{% tabs %}
{% tab title="TypeScript" %}

```typescript
import "dotenv/config";

import Client, {
  CommitmentLevel,
  SubscribeRequest,
  SubscribeRequestAccountsDataSlice,
} from "@triton-one/yellowstone-grpc";

const client = new Client(
  "https://rabbitstream.ams.shyft.to/",
  process.env.X_TOKEN,
  undefined
);

const req: SubscribeRequest = {
  accounts: {},
  slots: {},
  transactions: {
    pumpFun: {
      vote: false,
      failed: false,
      signature: undefined,
      accountInclude: ["6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"],
      accountExclude: [],
      accountRequired: [],
    },
  },
  transactionsStatus: {},
  entry: {},
  blocks: {},
  blocksMeta: {},
  accountsDataSlice: [] as SubscribeRequestAccountsDataSlice[],
  ping: undefined,
  commitment: CommitmentLevel.PROCESSED,
};

async function handleStream(client: Client, args: SubscribeRequest) {
  // Subscribe for events
  console.log(`Subscribing and starting stream...`);
  const stream = await client.subscribe();

  // Create `error` / `end` handler
  const streamClosed = new Promise<void>((resolve, reject) => {
    stream.on("error", (error) => {
      console.log("ERROR", error);
      reject(error);
      stream.end();
    });
    stream.on("end", () => {
      resolve();
    });
    stream.on("close", () => {
      resolve();
    });
  });

  // Handle updates
  stream.on("data", (data) => {
    console.log("Received data....");
    console.dir(data, { depth: null });
  });

  // Send subscribe request
  await new Promise<void>((resolve, reject) => {
    stream.write(args, (err: any) => {
      if (err === null || err === undefined) {
        resolve();
      } else {
        reject(err);
      }
    });
  }).catch((reason) => {
    console.error(reason);
    throw reason;
  });

  await streamClosed;
}

async function subscribeCommand(client: Client, args: SubscribeRequest) {
  while (true) {
    try {
      await handleStream(client, args);
    } catch (error) {
      console.error("Stream error, restarting in 1 second...", error);
      await new Promise((resolve) => setTimeout(resolve, 1000));
    }
  }
}

subscribeCommand(client, req);

```

{% endtab %}

{% tab title="Rust" %}

```rust
use {
    backoff::{future::retry, ExponentialBackoff},
    clap::Parser as ClapParser,
    futures::{
        future::TryFutureExt,         
        stream::StreamExt,
    },
    log::{error, info},
    std::{collections::HashMap, env, sync::Arc, time::Duration},
    tokio::sync::Mutex,
    tonic::transport::channel::ClientTlsConfig,
    yellowstone_grpc_client::{GeyserGrpcClient, Interceptor},
    yellowstone_grpc_proto::{
        geyser::SubscribeRequestFilterTransactions,
        prelude::{ CommitmentLevel, SubscribeRequest},
    },
};


type TxnFilterMap = HashMap<String, SubscribeRequestFilterTransactions>;

const PUMPFUN_AMM_PROGRAM_ID: &str = "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA";


#[derive(Debug, Clone, ClapParser)]
#[clap(author, version, about)]
struct Args {
    #[clap(short, long, help = "gRPC endpoint")]
    endpoint: String,

    #[clap(long, help = "X-Token")]
    x_token: String,
}

impl Args {
    async fn connect(&self) -> anyhow::Result<GeyserGrpcClient<impl Interceptor>> {
        GeyserGrpcClient::build_from_shared(self.endpoint.clone())?
            .x_token(Some(self.x_token.clone()))?
            .connect_timeout(Duration::from_secs(10))
            .timeout(Duration::from_secs(10))
            .tls_config(ClientTlsConfig::new().with_native_roots())?
            .max_decoding_message_size(1024 * 1024 * 1024)
            .connect()
            .await
            .map_err(Into::into)
    }

    pub fn get_txn_updates(&self) -> anyhow::Result<SubscribeRequest> {
        let mut transactions: TxnFilterMap = HashMap::new();

        transactions.insert(
            "client".to_owned(),
            SubscribeRequestFilterTransactions {
                vote: Some(false),
                failed: Some(false),
                account_include: vec![PUMPFUN_AMM_PROGRAM_ID.to_string()],
                account_exclude: vec![],
                account_required: vec![],
                signature: None,
            },
        );

        Ok(SubscribeRequest {
            accounts: HashMap::default(),
            slots: HashMap::default(),
            transactions,
            transactions_status: HashMap::default(),
            blocks: HashMap::default(),
            blocks_meta: HashMap::default(),
            entry: HashMap::default(),
            commitment: Some(CommitmentLevel::Processed as i32),
            accounts_data_slice: Vec::default(),
            ping: None,
            from_slot: None,
        })
    }
}



#[tokio::main]
async fn main() -> anyhow::Result<()> {
    env::set_var(
        env_logger::DEFAULT_FILTER_ENV,
        env::var_os(env_logger::DEFAULT_FILTER_ENV).unwrap_or_else(|| "info".into()),
    );
    env_logger::init();

    let args = Args::parse();
    let zero_attempts = Arc::new(Mutex::new(true));

    retry(ExponentialBackoff::default(), move || {
        let args = args.clone();
        let zero_attempts = Arc::clone(&zero_attempts);

        async move {
            let mut zero_attempts = zero_attempts.lock().await;
            if *zero_attempts {
                *zero_attempts = false;
            } else {
                info!("Retry to connect to the server");
            }
            drop(zero_attempts);

            let client = args.connect().await.map_err(backoff::Error::transient)?;
            info!("Connected");

            let request = args.get_txn_updates().map_err(backoff::Error::Permanent)?;

            geyser_subscribe(client, request)
                .await
                .map_err(backoff::Error::transient)?;

            Ok::<(), backoff::Error<anyhow::Error>>(())
        }
        .inspect_err(|error| error!("failed to connect: {error}"))
    })
    .await
    .map_err(Into::into)
}

async fn geyser_subscribe(
    mut client: GeyserGrpcClient<impl Interceptor>,
    request: SubscribeRequest,
) -> anyhow::Result<()> {
    let ( subscribe_tx, mut stream) = client.subscribe_with_request(Some(request)).await?;
    info!("stream opened");


    while let Some(message) = stream.next().await {
        match message {
            Ok(msg) => println!("Received Message: {:#?}", msg),
            Err(e) => error!("Failed to receive message: {e}"),
        }
    }

    info!("stream closed");
    Ok(())
}
```

{% endtab %}
{% endtabs %}

### Performance Benchmarks: The Speed Advantage

RabbitStream is ideal for applications that need <mark style="color:yellow;">low-latency transaction monitoring</mark>, such as *DeFi dashboards, arbitrage bots, or token analytics tools*. We compared the detection latency between RabbitStream and Yellowstone gRPC. All the code for this comparison tool is available on GitHub for you to try out.

<div data-full-width="false"><figure><img src="/files/JJ9arVuojS8deUWEejPR" alt=""><figcaption></figcaption></figure></div>


# RabbitStream vs. Yellowstone gRPC

Decide between Solana Shreds based RabbitStream for earliest detection or Yellowstone gRPC for full transaction conext.

### Flow of information

The difference in speed between Yellowstone gRPC and RabbitStream comes down to where in the Solana validator's data pipeline the <mark style="color:yellow;">information is extracted</mark>.

<figure><img src="/files/cxcZDA5jktVVRurHhZQI" alt="yellowstone-grpc-vs-rabbitstream-dataflow"><figcaption><p>Yellowstone gRPC vs Rabbitstream: Flow of information</p></figcaption></figure>

**Solana Validator Steps (The Pipeline)**

1. Gossip: Leader receives transactions.
2. Shredding: Leader breaks data into packets (Shreds) for network broadcast.
3. Execution: Transactions are run to determine the final outcome and generate meta (logs, fees, errors).
4. Geyser Hook: The validator makes the final, processed data available to plugins.

**Yellowstone gRPC Flow**

* **Extraction Point**: <mark style="color:yellow;">Data is extracted after it RPC processes the transaction</mark>, which is Step 4 (Geyser Hook), *after* execution.
* **Latency**: Slower than shreds as the transaction is processed to generate the inner instructions, meta, logs and all the other fields.
* **Data Completeness**: <mark style="color:yellow;">Includes full transaction</mark> `meta`, logs, and final status.
* **Best For**: Reliable indexing and analytics requiring full transaction context.

**Rabbitstream Flow**

* Extraction Point: Data is extracted from <mark style="color:yellow;">raw</mark> <mark style="color:yellow;">UDP Shreds,</mark> without the RPC being involved in any stage.&#x20;
* Latency: <mark style="color:yellow;">Ultra-Low (Fastest)</mark>. Minimal delay from the leader.
* Data Completeness: Missing all `meta` data, logs, and final execution status.
* Best For: Sniping and time-critical alerts where speed is the only priority.

### Difference between RabbitStream & Yellowstone gRPCs

<table><thead><tr><th width="195"></th><th>RabbitStream</th><th>Yellowstone gRPCs</th></tr></thead><tbody><tr><td>Extraction Point</td><td><mark style="color:yellow;">Data</mark> is <mark style="color:yellow;">extracted</mark> before it is <mark style="color:yellow;">processed by RPC</mark>, offering maximum immediacy and raw access.</td><td><mark style="color:yellow;">Earliest detection</mark> is at Processed commitment, when RPC processes and <mark style="color:yellow;">executes the transaction</mark>.</td></tr><tr><td>Latency</td><td><mark style="color:yellow;">Ultra-Low (Fastest)</mark>. Minimal delay, as data is captured at the earliest possible stage.</td><td><mark style="color:yellow;">Slower than shreds</mark> as the transaction is processed to generate the inner instructions, meta, logs, etc. High latency.</td></tr><tr><td>Data Availability</td><td><mark style="color:yellow;">Missing</mark> some <mark style="color:yellow;">meta</mark> data, logs, and final execution status upon initial capture, requiring external validation.</td><td>Includes <mark style="color:yellow;">full transaction meta</mark>, logs, and final status (executed or failed). Comprehensive data.</td></tr></tbody></table>

{% hint style="info" %}

### RabbitStream vs Yellowstone gRPC — the key architectural difference

Yellowstone gRPC is a Geyser plugin that *runs* *inside* an RPC node. It is bound to that node's execution pipeline and can only emit data after the node has fully replayed the transaction. \
RabbitStream operates <mark style="color:yellow;">entirely outside</mark> the RPC layer — listening directly to raw UDP shreds from multiple sources across the Solana network. No RPC node involved at any point.
{% endhint %}

### RabbitStream vs. Yellowstone gRPC: Benchmarks

RabbitStream's architectural advantage over Yellowstone gRPC is structural — it operates before the RPC execution pipeline entirely. The benchmarks below quantify that gap on live mainnet traffic across three regions.

**Methodology**

Both runs used [geyserbench v1.2.2](https://github.com/solstackapp/geyserbench), an open-source benchmarking tool by Solstack that connects to two endpoints simultaneously on the same live transaction stream and tags every delivery by which arrived first. No runs were excluded.

* **Tool:** geyserbench v1.2.2
* **Sample size:** 10,000 valid transactions per run
* **Runs:** 2 per region (6 total)
* **Regions tested:** Frankfurt (FRA), New York (NY), Amsterdam (AMS)
* **Test node:** Dedicated bare-metal server (AMD EPYC 9254, 384 GB RAM), co-located in the respective test region with under 1ms ping to both endpoints. Client-side network variance was not a factor in the results.

**Results Summary**

| Region          | RabbitStream Win Rate | Yellowstone P50 Behind | Yellowstone P95 Behind | Yellowstone P99 Behind |
| --------------- | --------------------- | ---------------------- | ---------------------- | ---------------------- |
| Frankfurt (FRA) | \~99.77% avg          | \~11.98ms              | \~30.36ms              | \~42.40ms              |
| New York (NY)   | \~99.94% avg          | \~7.24ms               | \~20.88ms              | \~28.55ms              |
| Amsterdam (AMS) | \~97.86% avg          | \~5.99ms               | \~20.92ms              | \~30.38ms              |

**Frankfurt (FRA) — Full Results**

<figure><img src="/files/ooftMCT9OyA6t9ItCneZ" alt="rabbitstream-vs-yellowstone-grpc-illustration-fra"><figcaption><p>RabbitStream vs Yellowstone gRPC: Benchmarks (Frankfurt)</p></figcaption></figure>

| Run   | RabbitStream Win Rate        | Yellowstone P50 Behind | Yellowstone P95 Behind | Yellowstone P99 Behind |
| ----- | ---------------------------- | ---------------------- | ---------------------- | ---------------------- |
| Run 1 | 99.68% (9,968 / 10,000 txns) | 16.12ms                | 36.72ms                | 50.48ms                |
| Run 2 | 99.87% (9,987 / 10,000 txns) | 7.84ms                 | 24.00ms                | 34.31ms                |

**New York (NY) — Full Results**

<figure><img src="/files/7zeX5HaRxCoPf0jWYc9D" alt="rabbitstream-vs-yellowstone-grpc-illustration-ny"><figcaption><p>RabbitStream vs Yellowstone gRPC: Benchmarks (New York)</p></figcaption></figure>

| Run   | RabbitStream Win Rate        | Yellowstone P50 Behind | Yellowstone P95 Behind | Yellowstone P99 Behind |
| ----- | ---------------------------- | ---------------------- | ---------------------- | ---------------------- |
| Run 1 | 99.96% (9,996 / 10,000 txns) | 6.66ms                 | 19.20ms                | 24.32ms                |
| Run 2 | 99.92% (9,992 / 10,000 txns) | 7.82ms                 | 22.55ms                | 32.78ms                |

**Amsterdam (AMS) — Full Results**

<figure><img src="/files/iBwYkscWIHMIV4hqOoxf" alt="rabbitstream-vs-yellowstone-grpc-ams-image"><figcaption><p>RabbitStream vs Yellowstone gRPC: Benchmarks (Amsterdam)</p></figcaption></figure>

| Run   | RabbitStream Win Rate        | Yellowstone P50 Behind | Yellowstone P95 Behind | Yellowstone P99 Behind |
| ----- | ---------------------------- | ---------------------- | ---------------------- | ---------------------- |
| Run 1 | 98.53% (9,853 / 10,000 txns) | 7.00ms                 | 24.54ms                | 36.34ms                |
| Run 2 | 97.20% (9,720 / 10,000 txns) | 4.97ms                 | 17.29ms                | 23.79ms                |

Amsterdam showed a slightly wider variance in win rate across runs compared to Frankfurt and New York, though RabbitStream arrived first in over 97% of transactions in both iterations. Yellowstone's P99 ranged from 23.79ms to 36.34ms across the two runs. Both feeds delivered zero backfill.

**What the numbers mean**

RabbitStream's P50 of 0.00ms across all runs is not a rounding artifact — it reflects delivery at the shred layer, before any RPC node has begun processing the transaction. Yellowstone gRPC can only emit data after the block has been fully replayed by the node. The latency gap in the tables above is that processing overhead, and it is structural rather than incidental — it will exist regardless of hardware or network conditions.

Both feeds delivered zero backfill across all runs and all regions. The shred-layer speed advantage carries no reliability trade-off.

### Response structures

While both Rabbitstream and Yellowstone gRPC use the <mark style="color:yellow;">same gRPC subscription method</mark>, the content within the streamed transaction is different. This key difference is entirely the <mark style="color:yellow;">meta</mark> field. Yellowstone gRPC delivers data *after* being processed, this having a complete `meta` field with *logs*, *fees*, and *final balances*. RabbitStream, however, delivers data captured at the high-speed Shred level (*pre-execution by the RPC*), meaning the valuable `meta` data is not available. This side-by-side comparison illustrates the trade-off between ultra-low latency and full transaction context.

<figure><img src="/files/1QFyitv66lRcIZtIWhEq" alt="Rabbitstream vs Yellowstone gRPC streamed trasnaction"><figcaption><p>Yellowstone vs Rabbitstream: Response Structures</p></figcaption></figure>

The following section denotes the detailed response structures. Please note, that the transactions received are in raw format, we have parsed them just for understanding. Also, this is a sample transaction, some parts of it may have been trimmed down for better visibilty, but the structure is the same.

{% tabs %}
{% tab title="Yellowstone Response" %}
{% code overflow="wrap" %}

```json
{
    "transaction": 
    {
      "signature": "4AEcrAwHWXwBkYpU4W9CHYnrUvMTqE9CfWTBsxyKtsn6Hsx1Dfp6rxq1MPwZuE23WZsFo73hCZZDiCAXyPH9RgyY",
      "isVote": false,
      "transaction": {
        "signatures": "4AEcrAwHWXwBkYpU4W9CHYnrUvMTqE9CfWTBsxyKtsn6Hsx1Dfp6rxq1MPwZuE23WZsFo73hCZZDiCAXyPH9RgyY",
        "message": {
          "header": {
            "numRequiredSignatures": 1,
            "numReadonlySignedAccounts": 0,
            "numReadonlyUnsignedAccounts": 8
          },
          "accountKeys": [
            "2ETSuPGkPp6Daj2gPFicaSA6c6BstWdBw1wJ18d655Ho",
            "5LoakVf9eoQf8tFArvBsX3k8EHB2eDe9nWWN2CcJwpme",
            "62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV",
            "9SoWt3pL7NFj8QBVZmQiEwtUrs8qqAnwKDdUSwSefdof",
            "9WhAmRMELSHqi3QvdYb8aFRFzzzSGJ22rt4JZcRspQNq",
            "4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf",
            "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
            "7jKWqre8igsMmy4GGYh2zJZd7KdLb52UTpnRujQvpump",
            "8Wf5TiAheLUqBrKXeYg2JtAFFMWtKdG2BSFgqUcPVwTt",
            "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1",
            "pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ",
            "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
          ],
          "recentBlockhash": "BtaXNFffjLpnhW2p489HB9cHJ79pf4SdFZyGtmndwYoB",
          "instructions": [
            {
                "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
                "accounts": [
                    "4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf",
                    "62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV",
                    "7jKWqre8igsMmy4GGYh2zJZd7KdLb52UTpnRujQvpump",
                    "87XL2uQdSGFTeXU8FNQxEJq5GQWCvaDMGUQ4dYZBTfUb",
                    "5LoakVf9eoQf8tFArvBsX3k8EHB2eDe9nWWN2CcJwpme",
                    "9SoWt3pL7NFj8QBVZmQiEwtUrs8qqAnwKDdUSwSefdof",
                    "2ETSuPGkPp6Daj2gPFicaSA6c6BstWdBw1wJ18d655Ho",
                    "11111111111111111111111111111111",
                    "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
                    "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1",
                    "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
                    "pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ"
                ],
                "data": {
                    "name": "sell",
                    "data": { 
                      "amount": 30197670084, 
                      "min_sol_output": 1253983 
                    }
                }
            } //raw data is streamed, parsed for understanding
        ],
          "versioned": false,
          "addressTableLookups": []
        }
      },
      "meta": {
        "err": "undefined",
        "fee": "5000",
        "preBalances": [
          "4486595",        "2039280",
          "24058891856602", "7749036247",
          "2039280",        "287273712",
          "1",              "453070864",
          "1505196108",     "1461600",
          "20373807",       "162706528",
          "1151476",        "5299608127"
        ],
        "postBalances": [
          "5801495",        "2039280",
          "24058891869300", "7747699639",
          "2039280",        "287277722",
          "1",              "453070864",
          "1505196108",     "1461600",
          "20373807",       "162706528",
          "1151476",        "5299608127"
        ],
        "innerInstructions": [
          {
            "index": 0,
            "instructions": [
                {
                    "outerIndex": 0,
                    "programId": "pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ",
                    "accounts": [
                        "8Wf5TiAheLUqBrKXeYg2JtAFFMWtKdG2BSFgqUcPVwTt",
                        "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"
                    ],
                    "data": "MkJmWlhTMUdRckNMWXpiU1hISnppMmJrWTN6a0w4RnJmZWo3RjdRa2d2QW1vRA==",
                    "stackHeight": 2
                },
                {
                    "outerIndex": 0,
                    "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
                    "accounts": [
                        "9SoWt3pL7NFj8QBVZmQiEwtUrs8qqAnwKDdUSwSefdof",
                        "5LoakVf9eoQf8tFArvBsX3k8EHB2eDe9nWWN2CcJwpme",
                        "2ETSuPGkPp6Daj2gPFicaSA6c6BstWdBw1wJ18d655Ho"
                    ],
                    "data": "M25QWG82RmVxbUpm",
                    "stackHeight": 2
                },
                {
                    "outerIndex": 0,
                    "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
                    "accounts": ["Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"],
                    "data": null,
                    "stackHeight": 2
                }
            ]
          }
        ],
        "innerInstructionsNone": false,
        "logMessages": [
          "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [1]",
          "Program log: Instruction: Sell",
          "Program pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ invoke [2]",
          "Program log: Instruction: GetFees",
          "Program pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ consumed 3119 of 164530 compute units",
          "Program return: pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ AAAAAAAAAABfAAAAAAAAAB4AAAAAAAAA",
          "Program pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ success",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
          "Program log: Instruction: Transfer",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4645 of 157988 compute units",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
          "Program data: vdt/007mYe5j/XMxttR+04aoGIWG+8GIbPZWlznPH2t0BMiDYYw2/yBlFAAAAAAAxODrBwcAAAAAEk4kBhCJrfsQFcid0PYx/RSGqeMU1kYMsLflKMpy1Y6vOvpoAAAAAJep0skIAAAAwrB2jKAHAwCX/a7NAQAAAMIYZEAPCQIASsL40N1cvJfjKJwZfLUGKlTz2Va5zm5RFfllZ6pcs+ZfAAAAAAAAAJoxAAAAAAAAVVmeOX+OQFCKyETMxop9AsOv45ExBC0W0nGTgluo6vkeAAAAAAAAAKoPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAHNlbGw=",
          "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [2]",
          "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 2030 of 146796 compute units",
          "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success",
          "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 56098 of 200000 compute units",
          "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success"
        ],
        "logMessagesNone": false,
        "preTokenBalances": [
          {
            "accountIndex": 1,
            "mint": "7jKWqre8igsMmy4GGYh2zJZd7KdLb52UTpnRujQvpump",
            "uiTokenAmount": {
              "uiAmount": 779780865.212414,
              "decimals": 6,
              "amount": "779780865212414",
              "uiAmountString": "779780865.212414"
            },
            "owner": "87XL2uQdSGFTeXU8FNQxEJq5GQWCvaDMGUQ4dYZBTfUb",
            "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
          },
          {
            "accountIndex": 4,
            "mint": "7jKWqre8igsMmy4GGYh2zJZd7KdLb52UTpnRujQvpump",
            "uiTokenAmount": {
              "uiAmount": 167625.704404,
              "decimals": 6,
              "amount": "167625704404",
              "uiAmountString": "167625.704404"
            },
            "owner": "2ETSuPGkPp6Daj2gPFicaSA6c6BstWdBw1wJ18d655Ho",
            "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
          }
        ],
        "postTokenBalances": [
          {
            "accountIndex": 1,
            "mint": "7jKWqre8igsMmy4GGYh2zJZd7KdLb52UTpnRujQvpump",
            "uiTokenAmount": {
              "uiAmount": 779811062.882498,
              "decimals": 6,
              "amount": "779811062882498",
              "uiAmountString": "779811062.882498"
            },
            "owner": "87XL2uQdSGFTeXU8FNQxEJq5GQWCvaDMGUQ4dYZBTfUb",
            "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
          },
          {
            "accountIndex": 4,
            "mint": "7jKWqre8igsMmy4GGYh2zJZd7KdLb52UTpnRujQvpump",
            "uiTokenAmount": {
              "uiAmount": 137428.03432,
              "decimals": 6,
              "amount": "137428034320",
              "uiAmountString": "137428.03432"
            },
            "owner": "2ETSuPGkPp6Daj2gPFicaSA6c6BstWdBw1wJ18d655Ho",
            "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
          }
        ],
        "rewards": [],
        "loadedWritableAddresses": [],
        "loadedReadonlyAddresses": [],
        "returnData": "undefined",
        "returnDataNone": true,
        "computeUnitsConsumed": "56098"
      },
      "index": "1122"
    },
    "slot": "375285929"
  }

```

{% endcode %}
{% endtab %}

{% tab title="Rabbitstream Response" %}
{% code overflow="wrap" %}

```json
{
    "transaction": 
    {
      "signature": "4AEcrAwHWXwBkYpU4W9CHYnrUvMTqE9CfWTBsxyKtsn6Hsx1Dfp6rxq1MPwZuE23WZsFo73hCZZDiCAXyPH9RgyY",
      "isVote": false,
      "transaction": {
        "signatures": "4AEcrAwHWXwBkYpU4W9CHYnrUvMTqE9CfWTBsxyKtsn6Hsx1Dfp6rxq1MPwZuE23WZsFo73hCZZDiCAXyPH9RgyY",
        "message": {
          "header": {
            "numRequiredSignatures": 1,
            "numReadonlySignedAccounts": 0,
            "numReadonlyUnsignedAccounts": 8
          },
          "accountKeys": [
            "2ETSuPGkPp6Daj2gPFicaSA6c6BstWdBw1wJ18d655Ho",
            "5LoakVf9eoQf8tFArvBsX3k8EHB2eDe9nWWN2CcJwpme",
            "62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV",
            "9SoWt3pL7NFj8QBVZmQiEwtUrs8qqAnwKDdUSwSefdof",
            "9WhAmRMELSHqi3QvdYb8aFRFzzzSGJ22rt4JZcRspQNq",
            "4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf",
            "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
            "7jKWqre8igsMmy4GGYh2zJZd7KdLb52UTpnRujQvpump",
            "8Wf5TiAheLUqBrKXeYg2JtAFFMWtKdG2BSFgqUcPVwTt",
            "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1",
            "pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ",
            "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"

          ],
          "recentBlockhash": "BtaXNFffjLpnhW2p489HB9cHJ79pf4SdFZyGtmndwYoB",
          "instructions": [
            {
                "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
                "accounts": [
                    "4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf",
                    "62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV",
                    "7jKWqre8igsMmy4GGYh2zJZd7KdLb52UTpnRujQvpump",
                    "87XL2uQdSGFTeXU8FNQxEJq5GQWCvaDMGUQ4dYZBTfUb",
                    "5LoakVf9eoQf8tFArvBsX3k8EHB2eDe9nWWN2CcJwpme",
                    "9SoWt3pL7NFj8QBVZmQiEwtUrs8qqAnwKDdUSwSefdof",
                    "2ETSuPGkPp6Daj2gPFicaSA6c6BstWdBw1wJ18d655Ho",
                    "11111111111111111111111111111111",
                    "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
                    "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1",
                    "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
                    "pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ"
                ],
                "data": {
                    "name": "sell",
                    "data": { "amount": 30197670084, "min_sol_output": 1253983 }
                } //raw data is recieved, parsed for illustration
            }
        ],
          "versioned": false,
          "addressTableLookups": []
        }
      },
      "index": "1122"
    },
    "slot": "375285929"
  } //meta missing

```

{% endcode %}
{% endtab %}

{% tab title="Raw Yellowstone Response" %}

```
{
  transaction: {
    transaction: {
      signature: Buffer(64) [Uint8Array] [
        158,   3, 197, 107, 176,  77, 142, 177,  82,  23, 183,
        241, 245,  70,  82, 254, 184,  33, 176, 101,  56,  48,
        199,   7, 160,   9, 109, 212,  71,  45,  35,  14, 177,
         78, 252, 108,  49, 208,  20, 227, 247,   4, 191, 115,
        116,   0, 241,  68, 214, 125,  89, 142, 188,   4,  35,
        148, 249,  99, 192, 254, 216,  43, 181,  11
      ],
      isVote: false,
      transaction: {
        signatures: [
          Buffer(64) [Uint8Array] [
            158,   3, 197, 107, 176,  77, 142, 177,  82,  23, 183,
            241, 245,  70,  82, 254, 184,  33, 176, 101,  56,  48,
            199,   7, 160,   9, 109, 212,  71,  45,  35,  14, 177,
             78, 252, 108,  49, 208,  20, 227, 247,   4, 191, 115,
            116,   0, 241,  68, 214, 125,  89, 142, 188,   4,  35,
            148, 249,  99, 192, 254, 216,  43, 181,  11
          ]
        ],
        message: {
          header: {
            numRequiredSignatures: 1,
            numReadonlySignedAccounts: 0,
            numReadonlyUnsignedAccounts: 8
          },
          accountKeys: [
            Buffer(32) [Uint8Array] [
               18,  78,  36,   6,  16, 137, 173, 251,
               16,  21, 200, 157, 208, 246,  49, 253,
               20, 134, 169, 227,  20, 214,  70,  12,
              176, 183, 229,  40, 202, 114, 213, 142
            ],
            Buffer(32) [Uint8Array] [
              64, 129, 116,  17, 164, 103,  64,  27,
              46,  44, 189,  68, 129, 128, 222, 153,
              22, 233, 226, 133, 191, 114, 163, 202,
               9,  51, 130, 204, 199, 189,  29,  89
            ],
            Buffer(32) [Uint8Array] [
              126, 120, 193, 229,  33, 191,  28, 182,
              255,  28,  97, 200, 139, 182, 143, 254,
               54, 219,  10, 219,  73, 171, 204, 123,
              131,  97,   4, 132, 120,  26,  98, 102
            ],
            Buffer(32) [Uint8Array] [
              0, 0, 0, 0, 0, 0, 0, 0, 0,
              0, 0, 0, 0, 0, 0, 0, 0, 0,
              0, 0, 0, 0, 0, 0, 0, 0, 0,
              0, 0, 0, 0, 0
            ], //response trimmed down
          ],
          recentBlockhash: Buffer(32) [Uint8Array] [
            161, 203, 101,  78, 235, 201, 255, 248,
             40,  64, 139, 172, 106, 113,  27, 220,
             43, 194, 119, 112, 153,   3,   1, 167,
             19,  55, 125, 218, 142, 250,  35,  34
          ],
          instructions: [
            {
              programIdIndex: 8,
              accounts: Buffer(14) [Uint8Array] [
                 7,  2, 9,  3,  1, 4,
                 0,  6, 5, 13, 11, 8,
                10, 12
              ],
              data: Buffer(24) [Uint8Array] [
                 51, 230, 133, 164, 1, 127, 131, 173,
                196, 224, 235,   7, 7,   0,   0,   0,
                 95,  34,  19,   0, 0,   0,   0,   0
              ]
            }
          ],
          versioned: false,
          addressTableLookups: []
        }
      },
      meta: {
        err: undefined,
        fee: '5000',
        preBalances: [
          '4486595',        '2039280',
          '24058891856602', '7749036247',
          '2039280',        '287273712',
          '1',              '453070864',
          '1505196108',     '1461600',
          '20373807',       '162706528',
          '1151476',        '5299608127'
        ],
        postBalances: [
          '5801495',        '2039280',
          '24058891869300', '7747699639',
          '2039280',        '287277722',
          '1',              '453070864',
          '1505196108',     '1461600',
          '20373807',       '162706528',
          '1151476',        '5299608127'
        ],
        innerInstructions: [
          {
            index: 0,
            instructions: [
              {
                programIdIndex: 12,
                accounts: Buffer(2) [Uint8Array] [ 10, 8 ],
                data: Buffer(33) [Uint8Array] [
                  231, 37, 126, 85, 207, 91, 63, 52,   1,
                  171, 11,  80, 78,  10,  0,  0,  0,   0,
                    0,  0,   0,  0,   0,  0,  0, 32, 101,
                   20,  0,   0,  0,   0,  0
                ],
                stackHeight: 2
              },
              //response trimmed
            ]
          }
        ],
        innerInstructionsNone: false,
        logMessages: [
          'Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [1]',
          'Program log: Instruction: Sell',
          'Program pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ invoke [2]',
          'Program log: Instruction: GetFees',
          'Program pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ consumed 3119 of 164530 compute units',
          'Program return: pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ AAAAAAAAAABfAAAAAAAAAB4AAAAAAAAA',
          'Program pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ success',
          'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]',
          'Program log: Instruction: Transfer',
          'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4645 of 157988 compute units',
          'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success',
          'Program data: vdt/007mYe5j/XMxttR+04aoGIWG+8GIbPZWlznPH2t0BMiDYYw2/yBlFAAAAAAAxODrBwcAAAAAEk4kBhCJrfsQFcid0PYx/RSGqeMU1kYMsLflKMpy1Y6vOvpoAAAAAJep0skIAAAAwrB2jKAHAwCX/a7NAQAAAMIYZEAPCQIASsL40N1cvJfjKJwZfLUGKlTz2Va5zm5RFfllZ6pcs+ZfAAAAAAAAAJoxAAAAAAAAVVmeOX+OQFCKyETMxop9AsOv45ExBC0W0nGTgluo6vkeAAAAAAAAAKoPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAHNlbGw=',
          'Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [2]',
          'Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 2030 of 146796 compute units',
          'Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success',
          'Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 56098 of 200000 compute units',
          'Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success'
        ],
        logMessagesNone: false,
        preTokenBalances: [
          {
            accountIndex: 1,
            mint: '7jKWqre8igsMmy4GGYh2zJZd7KdLb52UTpnRujQvpump',
            uiTokenAmount: {
              uiAmount: 779780865.212414,
              decimals: 6,
              amount: '779780865212414',
              uiAmountString: '779780865.212414'
            },
            owner: '87XL2uQdSGFTeXU8FNQxEJq5GQWCvaDMGUQ4dYZBTfUb',
            programId: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'
          },
          {
            accountIndex: 4,
            mint: '7jKWqre8igsMmy4GGYh2zJZd7KdLb52UTpnRujQvpump',
            uiTokenAmount: {
              uiAmount: 167625.704404,
              decimals: 6,
              amount: '167625704404',
              uiAmountString: '167625.704404'
            },
            owner: '2ETSuPGkPp6Daj2gPFicaSA6c6BstWdBw1wJ18d655Ho',
            programId: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'
          }
        ],
        postTokenBalances: [
          {
            accountIndex: 1,
            mint: '7jKWqre8igsMmy4GGYh2zJZd7KdLb52UTpnRujQvpump',
            uiTokenAmount: {
              uiAmount: 779811062.882498,
              decimals: 6,
              amount: '779811062882498',
              uiAmountString: '779811062.882498'
            },
            owner: '87XL2uQdSGFTeXU8FNQxEJq5GQWCvaDMGUQ4dYZBTfUb',
            programId: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'
          },
          {
            accountIndex: 4,
            mint: '7jKWqre8igsMmy4GGYh2zJZd7KdLb52UTpnRujQvpump',
            uiTokenAmount: {
              uiAmount: 137428.03432,
              decimals: 6,
              amount: '137428034320',
              uiAmountString: '137428.03432'
            },
            owner: '2ETSuPGkPp6Daj2gPFicaSA6c6BstWdBw1wJ18d655Ho',
            programId: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'
          }
        ],
        rewards: [],
        loadedWritableAddresses: [],
        loadedReadonlyAddresses: [],
        returnData: undefined,
        returnDataNone: true,
        computeUnitsConsumed: '56098'
      },
      index: '1122'
    },
    slot: '375285929'
  },

}
```

{% endtab %}

{% tab title="Raw Rabbitstream Response" %}

```
{
  transaction: {
    transaction: {
      signature: Buffer(64) [Uint8Array] [
        158,   3, 197, 107, 176,  77, 142, 177,  82,  23, 183,
        241, 245,  70,  82, 254, 184,  33, 176, 101,  56,  48,
        199,   7, 160,   9, 109, 212,  71,  45,  35,  14, 177,
         78, 252, 108,  49, 208,  20, 227, 247,   4, 191, 115,
        116,   0, 241,  68, 214, 125,  89, 142, 188,   4,  35,
        148, 249,  99, 192, 254, 216,  43, 181,  11
      ],
      isVote: false,
      transaction: {
        signatures: [
          Buffer(64) [Uint8Array] [
            158,   3, 197, 107, 176,  77, 142, 177,  82,  23, 183,
            241, 245,  70,  82, 254, 184,  33, 176, 101,  56,  48,
            199,   7, 160,   9, 109, 212,  71,  45,  35,  14, 177,
             78, 252, 108,  49, 208,  20, 227, 247,   4, 191, 115,
            116,   0, 241,  68, 214, 125,  89, 142, 188,   4,  35,
            148, 249,  99, 192, 254, 216,  43, 181,  11
          ]
        ],
        message: {
          header: {
            numRequiredSignatures: 1,
            numReadonlySignedAccounts: 0,
            numReadonlyUnsignedAccounts: 8
          },
          accountKeys: [
            Buffer(32) [Uint8Array] [
               18,  78,  36,   6,  16, 137, 173, 251,
               16,  21, 200, 157, 208, 246,  49, 253,
               20, 134, 169, 227,  20, 214,  70,  12,
              176, 183, 229,  40, 202, 114, 213, 142
            ],
            Buffer(32) [Uint8Array] [
              64, 129, 116,  17, 164, 103,  64,  27,
              46,  44, 189,  68, 129, 128, 222, 153,
              22, 233, 226, 133, 191, 114, 163, 202,
               9,  51, 130, 204, 199, 189,  29,  89
            ] //Response trimmed down
          ],
          recentBlockhash: Buffer(32) [Uint8Array] [
            161, 203, 101,  78, 235, 201, 255, 248,
             40,  64, 139, 172, 106, 113,  27, 220,
             43, 194, 119, 112, 153,   3,   1, 167,
             19,  55, 125, 218, 142, 250,  35,  34
          ],
          instructions: [
            {
              programIdIndex: 8,
              accounts: Buffer(14) [Uint8Array] [
                 7,  2, 9,  3,  1, 4,
                 0,  6, 5, 13, 11, 8,
                10, 12
              ],
              data: Buffer(24) [Uint8Array] [
                 51, 230, 133, 164, 1, 127, 131, 173,
                196, 224, 235,   7, 7,   0,   0,   0,
                 95,  34,  19,   0, 0,   0,   0,   0
              ]
            }
          ],
          versioned: false,
          addressTableLookups: []
        }
      },
      meta: undefined,
      index: '0'
    },
    slot: '375285929'
  }
}
```

{% endtab %}
{% endtabs %}


# RabbitStream vs Jito Shredstream: Benchmarks

RabbitStream transaction delivery benchmarked head-to-head against Jito ShredStream across multiple regions.

RabbitStream delivers Solana transaction data at the shred layer — the earliest point at which transaction data exists on the network. Unlike Yellowstone gRPC, which streams you data after the RPC has processed it, RabbitStream ingests raw UDP shreds directly from multiple Shred sources simultaneously. This architecture eliminates relay dependencies and RPC queue overhead, placing the data in your client's hands before any execution, log, or balance change has been recorded.

{% hint style="info" %}
A <mark style="color:yellow;">Shred</mark> is a \~1,228-byte UDP packet produced by the validator before block finalization.
{% endhint %}

This section breaks down a head-to-head performance comparison between RabbitStream and Jito ShredStream, measured across three production regions.

### Benchmark: RabbitStream vs. Jito ShredStream

#### **Methodology**

Benchmarks were conducted on live mainnet traffic across three regions, with both endpoints running side-by-side on every run.

* **Tool:** [geyserbench v1.2.2](https://github.com/solstackapp/geyserbench)
* **Sample size:** 10,000–10,011 valid transactions per run
* **Runs:** 2 per region (6 total)
* **Regions tested:** Frankfurt (FRA), New York (NY), Amsterdam (AMS)
* **Method:** Both endpoints connected simultaneously to the same live transaction stream. Every delivery tagged by which arrived first.
* **Test node:** Dedicated bare-metal server (AMD EPYC 9254, 384 GB RAM), <mark style="color:yellow;">co-located in the respective test region</mark> with under 1ms ping to both endpoints. Client-side network variance was not a factor in the results.

#### **Results Summary**

| Region          | RabbitStream Win Rate                       | Jito Win Rate | Jito P50 Behind | Jito P99 Behind |
| --------------- | ------------------------------------------- | ------------- | --------------- | --------------- |
| Frankfurt (FRA) | <mark style="color:$success;">97.77%</mark> | 2.23%         | 6.72ms          | 46.86ms         |
| New York (NY)   | <mark style="color:$success;">97.19%</mark> | 2.81%         | 5.29ms          | 81.50ms         |
| Amsterdam (AMS) | <mark style="color:$success;">92.67%</mark> | 7.33%         | 3.79ms          | 15.45ms         |

*Figures shown are from Run 1 in each region. Full per-run data below.*

RabbitStream arrived first in both regions tested. Both feeds achieved 100% delivery of valid transactions with zero backfill — the difference is not reliability, it is who gets there first.

***

**Frankfurt (FRA) — Full Results**

<figure><img src="/files/Iiq3pe0Ga9afhROuWblt" alt="rabbitstream-vs-jitoshredstream-benchmarks-frankfurt"><figcaption><p>RabbitStream vs Jito Shredstream: Benchmarks (Frankfurt)</p></figcaption></figure>

| Run   | RabbitStream Win Rate        | Jito P50 Behind | Jito P99 Behind |
| ----- | ---------------------------- | --------------- | --------------- |
| Run 1 | 97.77% (9,780 / 10,003 txns) | 6.72ms          | 46.86ms         |
| Run 2 | 97.31%                       | 4.19ms          | 25.74ms         |

Frankfurt results were consistent across both runs. The win rate gap did not meaningfully change between iterations. Jito ShredStream's P99 ranged from 25.74ms to 46.86ms.

***

**New York (NY) — Full Results**

<figure><img src="/files/rdzlDhHxORiEytw6zFOa" alt="rabbitstream-vs-jito-shreds-benchmarks"><figcaption><p>RabbitStream vs Jito Shredstream: Benchmarks (New York)</p></figcaption></figure>

| Run   | RabbitStream Win Rate        | Jito P50 Behind | Jito P99 Behind |
| ----- | ---------------------------- | --------------- | --------------- |
| Run 1 | 97.19% (9,723 / 10,004 txns) | 5.29ms          | 81.50ms         |
| Run 2 | 96.52%                       | 3.87ms          | 82.06ms         |

New York is where Jito's infrastructure is most concentrated. Despite this, RabbitStream arrived first in over 96.5% of transactions across both runs. Jito ShredStream's P99 held near 82ms in both iterations, confirming this is a structural pattern, not an outlier.

***

**Amsterdam (AMS) — Full Results**

<figure><img src="/files/pU31QPMtbgpOihlBsqF8" alt="rabbitstream-vs-jito-amsterdam"><figcaption><p>RabbitStream vs Jito Shredstream: Benchmarks (Amsterdam)</p></figcaption></figure>

| Run   | RabbitStream Win Rate        | Jito P50 Behind | Jito P95 Behind | Jito P99 Behind |
| ----- | ---------------------------- | --------------- | --------------- | --------------- |
| Run 1 | 92.67% (9,268 / 10,001 txns) | 3.79ms          | 11.57ms         | 15.45ms         |
| Run 2 | 98.62% (9,873 / 10,011 txns) | 5.04ms          | 13.21ms         | 16.73ms         |

Amsterdam showed the widest variance in win rate across runs — 92.67% in Run 1 and 98.62% in Run 2. Despite this, RabbitStream arrived first in the majority of transactions in both runs, and Jito's P99 remained capped below 17ms across both iterations. Both feeds delivered zero backfill across 10,000+ transactions per run.

### **Across All Runs**

| Region    | Run   | RabbitStream Win Rate | Jito P50 Behind | Jito P99 Behind |
| --------- | ----- | --------------------- | --------------- | --------------- |
| Frankfurt | Run 1 | 97.77%                | 6.72ms          | 46.86ms         |
| Frankfurt | Run 2 | 97.31%                | 4.19ms          | 25.74ms         |
| New York  | Run 1 | 97.19%                | 5.29ms          | 81.50ms         |
| New York  | Run 2 | 96.52%                | 3.87ms          | 82.06ms         |
| Amsterdam | Run 1 | 92.67%                | 3.79ms          | 15.45ms         |
| Amsterdam | Run 2 | 98.62%                | 5.04ms          | 16.73ms         |

***

{% hint style="warning" %}
See how Shyft RPC performs against Yellowstone gRPC in our [RabbitStream vs Yellowstone gRPC](https://docs.shyft.to/solana-shredstreaming/pages/wV8xcVXrbVHyCIznl13D#rabbitstream-vs.-yellowstone-grpc-benchmarks) benchmark.
{% endhint %}

### Why RabbitStream Arrives First

RabbitStream ingests raw UDP shreds from multiple sources simultaneously, taking whichever propagation path delivers first. There is no single relay to route through and no RPC queue to wait behind. The only server-side work before delivery is shred decoding, which adds negligible overhead.

Jito ShredStream routes shreds through Jito's Block Engine network. This gives it direct relationships with certain Solana leaders — which explains why Jito wins a small share of deliveries in each region — but introduces a single relay dependency for all other shreds. Across all four runs and both regions, Jito's share never exceeded 3% and its P99 never dropped below 25ms.


# Measuring gRPC Latency

Learn how to measure Solana Yellowstone geyser gRPC latency the right way.

Before testing **Yellowstone gRPC latency**, make sure you follow this rule of thumb:

> **Your server should be in the same region as the gRPC endpoint you are connecting to.**

For example, if you are connecting to <mark style="color:yellow;">grpc.ams.shyft.to,</mark> your server should be in Amsterdam. Same applies for all other regions. Once that’s in place, let’s address the latency question:

<mark style="color:yellow;">"Why am I getting 1s or more latency with gRPC. Isn't that slow?"</mark>

#### TLDR;

**You are not actually receiving data with \~1 s latency.**

This is a **perceived delay** caused by the lack of precision in Solana’s timestamp — as Solana stores  `blockTime`  only in **seconds**, without **milliseconds**. Because of this, when you calculate latency using `blockTime`, your result appears inflated (1s or more).

#### Why it Happen?

Developers commonly use:

<mark style="color:yellow;">**gRPC latency = transaction receive time - transaction block time**</mark>

However, it overlooks an important detail — Solana’s `blockTime` values are recorded only in **seconds**, with no millisecond precision. This means every transaction that occurs within the same second is assigned the same timestamp, even if they actually happened hundreds of milliseconds apart.\
For example, transactions happening at <mark style="color:yellow;">07:46:46.900</mark> are still recorded as <mark style="color:yellow;">07:46:46.000</mark>, making your measured latency seem much longer than it really is.

#### Example

Consider the following Solana blocks:

| Block                                           | Block Time |
| ----------------------------------------------- | ---------- |
| [319464973](https://solscan.io/block/319464973) | 07:46:46   |
| [319464974](https://solscan.io/block/319464974) | 07:46:46   |
| [319464975](https://solscan.io/block/319464975) | 07:46:47   |
| [319464976](https://solscan.io/block/319464976) | 07:46:47   |

Solana typically produces 2–3 blocks per second. In reality, those blocks are spread across the full second (e.g., 07:46:46.100, 07:46:46.500, 07:46:46.900).\
But since milliseconds are not stored, all are recorded as `07:46:46:000`.

If a transaction actually occurred at `07:46:46.900` and your client received it at `07:46:47.200`, the calculated latency would be:

**07:46:47.200 − 07:46:46.000 = 1.2 s**

The **true latency**, however, is only about **300 ms**.

#### Key points

* The gRPC stream is **not** delivering data late.
* The \~1 s gap seen in benchmarks is a **timestamp precision issue**, not a performance issue.


# Solana gRPC Docs

gRPC geyser: Low-Latency Streaming of Solana Transactions, Accounts, and Blocks

A <mark style="color:yellow;">geyser plugin</mark> on Solana allows you to push real-time updates from a Solana RPC node to an external source. <mark style="color:yellow;">**Yellowstone gRPC**</mark> is one such high-performance Solana Geyser plugin that allows you to stream real-time blockchain data via gRPC interfaces. This powerful tool enables developers to:

* **Monitor on-chain activities:** Track token mints, program interactions, and state changes.
* **Stream account states:** Efficiently retrieve account information.
* **Stream transactions:** Monitor transactions with minimal latency.
* **Indexers:** Build indexing pipelines

In short, this can be used to build applications that can respond quickly to changes on the blockchain.

{% hint style="info" %}
Looking for the fastest way to pipe blockchain events into your stack? [<mark style="color:yellow;">Shyft's Yellowstone gRPC service</mark>](https://shyft.to/solana-yellowstone-grpc) is the most robust real-time data streaming solution on Solana, built for developers who need 100% data integrity at scale.
{% endhint %}

## Resources and Replits on Shyft gRPCs

We have developed multiple sample code covering top use cases for gRPC. They run out of the box, are in multiple languages (Typescript, Rust and python) and help you get started quickly. You can explore them here

* Shyft [<mark style="color:yellow;">GitHub</mark>](https://github.com/Shyft-to/solana-defi)
* Shyft [<mark style="color:yellow;">Replit</mark>](https://replit.com/@shyft-to)
* Shyft [<mark style="color:yellow;">Blogs</mark>](https://blogs.shyft.to/)

You can also join [<mark style="color:yellow;">Shyft's discord</mark>](https://discord.gg/8JyZCjRPmr) for support and more resources.&#x20;

{% hint style="warning" %}
Unlike regular RPCs calls which are used to interact with the Solana blockchain by sending HTTP POST requests, gRPCs are only used for streaming real-time updates on Solana with minimum latency.
{% endhint %}

## Authentication

There are two ways to authenticate your server or connection when connecting to Shyft’s gRPC network:

1. **Using X-Token:**

<figure><img src="/files/6DzAt7UeZNvXofOAVkIU" alt=""><figcaption><p>x-token is available in the gRPC section of the dashboard</p></figcaption></figure>

After purchasing the gRPC service on Shyft, you can find your <mark style="color:yellow;">x-token</mark> in the gRPC section of your Shyft dashboard. This token is used to establish a gRPC connection through the Yellowstone client. The advantage of this method is that it doesn’t require IP whitelisting.

```javascript
const client = new Client(
  <YOUR-GRPC-ENDPOINT>,
  <YOUR-X-TOKEN>,
  undefined
); //initializing yellowstone client
```

2. **By Whitelisting Your IP:**

{% hint style="warning" %}
We recommend using token for authentication. Use IP whitelisting only when you cant use token authentication.
{% endhint %}

In certain scenarios, like when setting up bots, you may need to connect directly to the gRPC network via the <mark style="color:yellow;">gRPC URL without x-token</mark>. In such cases, you’ll need to <mark style="color:yellow;">whitelist</mark> your server’s IP address (the one used to receive streamed data). Once the IP is whitelisted, you can connect directly using the URL without needing an x-token. IP whitelisting can be easily managed through the gRPC section of the dashboard.

<figure><img src="/files/RnPh5sFwQSTAHdylSXcB" alt=""><figcaption><p>Whitelist your server IP to directly use without X-TOKEN</p></figcaption></figure>

{% hint style="info" %}
Please note, gRPC connections can be made from any IP address using *<mark style="color:yellow;">x-token</mark>*. Once an IP address is whitelisted, x-tokens are no longer required for connection from that IP.
{% endhint %}

## What are gRPC Subscribe Requests?&#x20;

Real-time updates in Solana’s Yellowstone gRPC plugins rely on <mark style="color:yellow;">Subscription streams</mark>. These streams let you receive updates like account changes, transactions, new blocks, or slot updates directly to your backend. To keep things focused and avoid unnecessary data, a <mark style="color:yellow;">subscription request</mark> lets you specify different kind of filters. using these filters you can specify exactly what type of updates you need.&#x20;

Subscribe requests on gRPC look somewhat like this.

```typescript
import { CommitmentLevel } from "@triton-one/yellowstone-grpc";

const req: SubscribeRequest = {
  accounts: {},
  slots: {},
  transactions: {},
  transactionsStatus: {},
  entry: {},
  blocks: {},
  blocksMeta: {},
  accountsDataSlice: [],
  ping: undefined,
  commitment: CommitmentLevel.CONFIRMED,
};
```

Most of the request parameters here are self-explanatory, working exactly with what they are named,

* <mark style="color:yellow;">`accounts`</mark>**:** You can subscribe to specific accounts (e.g., SOL-USDC OpenBook) by specifying this parameter and receive updates based on commitment levels (processed, confirmed, finalized).
* <mark style="color:yellow;">`accountDataSlice`</mark>: This field helps you to filter your gRPC stream, so that you receive only the relevant portion of streamed data. For example you are streaming accounts, for which the data size is 200bytes, but you only need 40 bytes after a certain offset. This field can help you filter those 40 bytes for every update in the stream.
* <mark style="color:yellow;">`transactions`</mark> & <mark style="color:yellow;">`transactionsStatus`</mark>: You can receive updates on all transactions or filter them based on specific criteria (vote/failed transactions, including/excluding accounts). Programs can also be monitored using this.
* <mark style="color:yellow;">`slots`</mark>, <mark style="color:yellow;">`blocks`</mark> & <mark style="color:yellow;">`blocksMeta`</mark> **:** Stay informed about new blocks and slots being produced on the blockchain.
* <mark style="color:yellow;">`commitment`</mark>: This specifies the commit level for any update, either `processed`, `confirmed` or `finalized`.

## FAQ <a href="#solana-grpc-faq" id="solana-grpc-faq"></a>

<details>

<summary>How is Solana gRPC different from Websockets?</summary>

WebSockets transmit JSON over HTTP and are easier to implement for quick integrations, while gRPC streams use Solana’s Geyser plugin system to push **real-time transactions, accounts**, and **blocks** with minimal overhead. This makes gRPC ideal for high-throughput performance applications like trading bots, market makers, and analytics platforms, whereas WebSockets are better suited for lighter, less latency-sensitive use cases.

</details>

<details>

<summary>How do I connect to a Yellowstone gRPC endpoint?</summary>

To connect to a Yellowstone gRPC endpoint, you need:

1. <mark style="color:yellow;">A gRPC endpoint URL</mark> – This is the address your client will connect to.
2. <mark style="color:yellow;">A Yellowstone-compatible gRPC client</mark> – Choose one in your preferred programming language (Rust, [Node.js](https://www.npmjs.com/package/@triton-one/yellowstone-grpc), etc.).&#x20;

For **Shyft Yellowstone gRPC**, you’ll also need an  `x-token` for authentication. The connection URL and `x-Token` are included in any gRPC-enabled Shyft plan.

Please refer to our connections and [authentication docs](#authentication) here.

</details>

<details>

<summary>What data can I stream using Solana gRPC?</summary>

With Solana gRPC, you can subscribe to:

* [**Transactions**](/solana-yellowstone-grpc/docs/transaction-streaming) – Detailed transaction data, including instructions, logs, and status.
* [**Accounts**](/solana-yellowstone-grpc/docs/account-streaming) – Live updates on account state changes.
* [**Blocks**](/solana-yellowstone-grpc/docs/streaming-blocks-and-blocksmeta) – Newly produced blocks with transaction metadata.

  These streams are ideal for bots, trading engines, real-time dashboards, and analytics platforms.

</details>

<details>

<summary>How do I parse raw Solana transaction data from Yellowstone gRPC?</summary>

Raw transaction data streamed from Solana Yellowstone gRPC is typically in a <mark style="color:yellow;">base64</mark> or binary-encoded format. To convert this into human-readable form, you can use the corresponding <mark style="color:yellow;">program’s IDL</mark> (Interface Definition Language) or a custom parser to decode the instructions, accounts, and logs.

Our developer documentation and GitHub examples cover step-by-step methods for:

* Decoding transactions using Anchor IDLs.
* Parsing data from popular Solana programs such as System Program, Token Program, and Associated Token Program.
* Extracting structured data from DEX trades, DeFi protocols, and custom programs.

Explore examples: Visit our [Docs](/solana-yellowstone-grpc/examples) and [GitHub repository](https://github.com/Shyft-to/solana-defi) for complete code samples on receiving and parsing Solana transactions via Yellowstone gRPC.

</details>

<details>

<summary>How far back can I stream slots from using gRPC?</summary>

Our service supports streaming from up to **150 slots** prior to the current head (maximum lookback depth is 150 slots).

Here is a [example for streaming from a specific slot](https://github.com/Shyft-to/solana-defi/tree/main/general-grpc-examples/Typescript/add_a_reconnect_mechanism) on Solana using gRPC.

</details>

<details>

<summary>Are there any rate limits for Solana Yellowstone gRPC streaming?</summary>

No Rate Limits. Shyft Yellowstone gRPC offers <mark style="color:yellow;">different subscription tiers</mark>, each with its own connections limits for streaming, but  <mark style="color:yellow;">no rate limits</mark> to the number of subscribe request you send. However,  certain high load programs, (such as the token program) is only allowed on Dedicated Nodes.

Check our [pricing and rate limit documentation](https://shyft.to/solana-rpc-grpc-pricing) to choose the plan that matches your Solana data streaming needs.

</details>

<details>

<summary>How are Dedicated gRPC Nodes better than Shared gRPC plans?</summary>

Solana Dedicated Nodes deliver a latency advantage of <mark style="color:yellow;">5–10ms</mark> over shared nodes, making them ideal for high-frequency trading, real-time analytics, and low-latency DeFi applications. Unlike shared nodes, they are <mark style="color:yellow;">exclusively allocated</mark> to you, with <mark style="color:yellow;">no rate limits</mark> and <mark style="color:yellow;">no access restrictions</mark> on high-load Solana addresses. Each dedicated node is <mark style="color:yellow;">load-balanced</mark> across a cluster of backup nodes, ensuring <mark style="color:yellow;">99.99%+ uptime</mark> and uninterrupted access to the Solana blockchain. [Learn More](https://shyft.to/solana-dedicated-grpc-nodes).&#x20;

</details>

<details>

<summary><strong>Why is lag building up over time with gRPC?</strong></summary>

If you notice that over time ag starts to build up, then there are two possible reasons.

* Your server is far away from the gRPC region you are connecting to. For example, if you are connecting to <mark style="color:yellow;">grpc.ams.shyft.to,</mark> your server should also be in the same region i.e Ams. We have seen cases where lag starts to build up over time if the server is far away. Its acceptable if ping < 10ms, although some users would want it to be less than 1ms.
* Another reason is that typescript sometimes is not able to keep up with gRPC speed. We suggest using <mark style="color:yellow;">Rust gRPC</mark> client for fastest processing. We have some sample codes in our [<mark style="color:red;">**Github repo**</mark>](https://github.com/Shyft-to/solana-defi) **and** [<mark style="color:red;">**Replit**</mark>](https://replit.com/@shyft-to/).
* Don't use VPNs.
* At anytime you can verify the current slot of all our regions [<mark style="color:red;">**here**</mark>](http://metrics-pool.shyft.to:3000/public-dashboards/23f6575360d9490e8fff3a82ae4f5a08?from=now-30m\&to=now\&timezone=browser)<mark style="color:red;">.</mark>

</details>

<details>

<summary>Why am I getting the following error message, “PermissionDenied, message: "Maximum connection count reached for IP address”?</summary>

This indicates you have the grpc rate limits for your plan, please checkout the details [here](https://shyft.to/solana-rpc-grpc-pricing).

</details>

<details>

<summary><strong>Why am I getting Maximum IP limit reached for token error?</strong></summary>

* This behavior is only observed on the **legacy gRPC plan**, which limits you to a single IP address. If you are on one of our newer plans — <mark style="color:$primary;">BUILD</mark>, <mark style="color:$primary;">GROW</mark>, or <mark style="color:$primary;">ACCELERATE</mark> — you can make connections from unlimited IP addresses, and this error will not occur.
* You can also get this when you change your server and the connection was not gracefully shutdown. In those cases you can clear your previous connection through this link [<mark style="color:red;">https://grpc.ams.shyft.to/clear-connections?xtoken=your-token</mark>](https://grpc.ams.shyft.to/clear-connections?xtoken=your-token)\
  Add your token in the end, grpc region doesnt matter.

</details>

<details>

<summary>How do I check if any gRPC region is lagging or not?</summary>

We have a public dashboard where you can see lag of all gRPC regions in our network. We compare it against Solana mainnet-beta. You can access it [<mark style="color:red;">**here**</mark>](http://metrics-pool.shyft.to:3000/public-dashboards/23f6575360d9490e8fff3a82ae4f5a08).

</details>


# Getting Started

Solana Yellowstone gRPC geyser - Learn how to stream Solana updates in real-time with a step-by-step guide

**Yellowstone** is a high-performance Solana validator client designed with extensibility and speed in mind. It offers powerful **gRPC support** via its **Geyser plugin**, enabling developers to subscribe to a wide range of real-time Solana events — including account changes, transaction confirmations, and slot updates — with minimal latency.

To start working with Yellowstone gRPC, you’ll need two key components:

* **gRPC Endpoint** – The <mark style="color:yellow;">endpoint</mark> where the gRPC service is exposed.
* **x-token** – An <mark style="color:yellow;">access token</mark> required to authenticate your connection.

Before establishing a connection, ensure you’ve installed the **Yellowstone gRPC package**, which provides the necessary tools and client bindings for communicating with the gRPC service.

<figure><img src="/files/ckGRZ2vP6m0OZGtj6M4g" alt=""><figcaption><p>Region specific gRPC endpoint and access token from the Shyft Dashboard</p></figcaption></figure>

Once set up, you can begin streaming real-time Solana data with precision and performance.


# Initializing the Yellowstone Client

Solana gRPC Geyser Guide - Initializing the Solana Yellowstone gRPC client

The Yellowstone client is used to <mark style="color:yellow;">connect to gRPC</mark> on Solana, sending <mark style="color:yellow;">subscribe requests</mark> and receive data from stream. The gRPC streams and RPC calls are supported through Solana's Geyser interface. To initialize a  new Yellowstone client in typescript, you need to install the following package.

```bash
npm i @triton-one/yellowstone-grpc
```

Once done, we need two parameters to initialize the client, the gRPC endpoint, and the x-token, both of which is available in the Shyft dashboard once you unlock gRPC. You can find out more about [endpoint and access token](/solana-yellowstone-grpc/docs#authentication) here.

{% tabs %}
{% tab title="TypeScript" %}

```javascript
import Client from "@triton-one/yellowstone-grpc";

const client = new Client(
  "https://grpc.ams.shyft.to", //your region specific grpc endpoint
  "YOUR-ACCESS-XTOKEN", // xtoken, which is used to authenticate
  undefined,
);
```

{% endtab %}
{% endtabs %}

{% hint style="success" %}
Please note that some gRPC connections only take in the <mark style="color:yellow;">endpoint</mark> parameter to make a connection, in those cases, <mark style="color:yellow;">IP whitelisting</mark> is required to authenticate your connection. Find out more about making a connection in our docs [here](/solana-yellowstone-grpc/docs#authentication).
{% endhint %}


# Making a gRPC connection

Solana gRPC Geyser Guide – How to Configure Your First Yellowstone gRPC Connection

Once the client has been initialized. The next step is to specify what data to stream. The Yellowstone client uses [Subscribe Requests ](/solana-yellowstone-grpc/docs#what-are-subscribe-requests)to specify the data to stream.

The `handleStream` function is used to receive the stream (`stream.on(data, func())`), and also to write  the [subscribe request](https://docs.shyft.to/solana-fast-grpc/grpc-docs#what-are-subscribe-requests) to the stream  (`stream.write()`). You can copy and paste this code on Replit to execute.

{% hint style="success" %}
The complete code for making a new gRPC connection is available on our [GitHub](https://github.com/Shyft-to/solana-defi/tree/main/general-grpc-examples/Typescript/making_a_grpc_connection), and on [Replit here](https://replit.com/@shyft-to/making-a-grpc-connection?v=1).
{% endhint %}

{% tabs %}
{% tab title="TypeScript" %}
{% code overflow="wrap" %}

```typescript

import Client, {
  CommitmentLevel,
  SubscribeRequestAccountsDataSlice,
  SubscribeRequestFilterAccounts,
  SubscribeRequestFilterBlocks,
  SubscribeRequestFilterBlocksMeta,
  SubscribeRequestFilterEntry,
  SubscribeRequestFilterSlots,
  SubscribeRequestFilterTransactions,
} from "@triton-one/yellowstone-grpc";
import { SubscribeRequestPing } from "@triton-one/yellowstone-grpc/dist/grpc/geyser";

// Interface for the subscription request structure
interface SubscribeRequest {
  accounts: { [key: string]: SubscribeRequestFilterAccounts };
  slots: { [key: string]: SubscribeRequestFilterSlots };
  transactions: { [key: string]: SubscribeRequestFilterTransactions };
  transactionsStatus: { [key: string]: SubscribeRequestFilterTransactions };
  blocks: { [key: string]: SubscribeRequestFilterBlocks };
  blocksMeta: { [key: string]: SubscribeRequestFilterBlocksMeta };
  entry: { [key: string]: SubscribeRequestFilterEntry };
  commitment?: CommitmentLevel;
  accountsDataSlice: SubscribeRequestAccountsDataSlice[];
  ping?: SubscribeRequestPing;
}

const ADDRESS_TO_STREAM_FROM = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P";

/**
 * Subscribes to the gRPC stream and handles incoming data.
 * 
 * @param client - Yellowstone gRPC client
 * @param args - The Subscription request which specifies what data to stream
 */
async function handleStream(client: Client, args: SubscribeRequest) {
  const stream = await client.subscribe();

  // Promise that resolves when the stream ends or errors out
  const streamClosed = new Promise<void>((resolve, reject) => {
    stream.on("error", (error) => {
      console.error("Stream error:", error);
      reject(error);
      stream.end();
    });

    stream.on("end", resolve);
    stream.on("close", resolve);
  });

  // Handle incoming transaction data
  stream.on("data", (data) => {
    if (data?.transaction) {
      
      console.log("Received Transaction:");
      console.log(data?.transaction);
    }
  });

  // Send the subscription request
  await new Promise<void>((resolve, reject) => {
    stream.write(args, (err: any) => {
      err ? reject(err) : resolve();
    });
  }).catch((err) => {
    console.error("Failed to send subscription request:", err);
    throw err;
  });

  // Wait for the stream to close
  await streamClosed;
}

/**
 * Entry point to start the subscription stream.
 * 
 */
async function subscribeCommand(client: Client, args: SubscribeRequest) {
  await handleStream(client, args);

}

// Instantiate Yellowstone gRPC client with env credentials
const client = new Client(
  process.env.GRPC_URL, //Your Region specific gRPC URL
  process.env.X_TOKEN, // your Access Token
  undefined
);

/**
 * Subscribe Request: The `transactions` field filters transaction streams to only include those
 * that involve the specified address in `accountInclude`.
 */
const req: SubscribeRequest = {
  accounts: {},
  slots: {},
  transactions: {
    pumpFun: {
      vote: false,
      failed: false,
      signature: undefined,
      accountInclude: [ADDRESS_TO_STREAM_FROM],
      accountExclude: [],
      accountRequired: [],
    },
  },
  transactionsStatus: {},
  blocks: {},
  blocksMeta: {},
  entry: {},
  accountsDataSlice: [],
  ping: undefined,
  commitment: CommitmentLevel.CONFIRMED,
};

// Start the subscription
subscribeCommand(client, req);
```

{% endcode %}
{% endtab %}
{% endtabs %}


# Adding a Reconnection Mechanism

Solana gRPC Geyser Guide – How to Add a Reconnection Mechanism in Production Apps

Yellowstone gRPC is a powerful, production-ready tool for real-time Solana data. But in real-world conditions, network issues or server outages can cause connection drops. Without a reconnect strategy, your app might miss critical updates from the blockchain. A <mark style="color:yellow;">reliable reconnect system</mark> ensures your app stays connected and continues receiving live data, even during temporary interruptions.

{% hint style="success" %}
The maximum lookback depth for our gRPC services is <mark style="color:$success;">**150 slots**</mark> at the moment.
{% endhint %}

You can paste this code in Replit to see it in action, or simply run the Repl [code here](https://replit.com/@shyft-to/adding-a-reconnect-mechanism-to-grpc?v=1).

{% tabs %}
{% tab title="TypeScript" %}
{% code overflow="wrap" %}

```typescript
import Client, {
  CommitmentLevel,
  SubscribeRequestAccountsDataSlice,
  SubscribeRequestFilterAccounts,
  SubscribeRequestFilterBlocks,
  SubscribeRequestFilterBlocksMeta,
  SubscribeRequestFilterEntry,
  SubscribeRequestFilterSlots,
  SubscribeRequestFilterTransactions,
} from "@triton-one/yellowstone-grpc";
import { SubscribeRequestPing } from "@triton-one/yellowstone-grpc/dist/grpc/geyser";

// Interface for the subscription request structure
interface SubscribeRequest {
  accounts: { [key: string]: SubscribeRequestFilterAccounts };
  slots: { [key: string]: SubscribeRequestFilterSlots };
  transactions: { [key: string]: SubscribeRequestFilterTransactions };
  transactionsStatus: { [key: string]: SubscribeRequestFilterTransactions };
  blocks: { [key: string]: SubscribeRequestFilterBlocks };
  blocksMeta: { [key: string]: SubscribeRequestFilterBlocksMeta };
  entry: { [key: string]: SubscribeRequestFilterEntry };
  commitment?: CommitmentLevel;
  accountsDataSlice: SubscribeRequestAccountsDataSlice[];
  ping?: SubscribeRequestPing;
}

const ADDRESS_TO_STREAM_FROM = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P";

async function handleStream(client: Client, args: SubscribeRequest) {
  const stream = await client.subscribe();

  // Promise that resolves when the stream ends or errors out
  const streamClosed = new Promise<void>((resolve, reject) => {
    stream.on("error", (error) => {
      console.error("Stream error:", error);
      reject(error);
      stream.end();
    });

    stream.on("end", resolve);
    stream.on("close", resolve);
  });

  // Handle incoming transaction data
  stream.on("data", (data) => {
    if (data?.transaction) {
      console.log("Received Transaction:");
      console.log(data?.transaction);
    }
  });

  // Send the subscription request
  await new Promise<void>((resolve, reject) => {
    stream.write(args, (err: any) => {
      err ? reject(err) : resolve();
    });
  }).catch((err) => {
    console.error("Failed to send subscription request:", err);
    throw err;
  });

  // Wait for the stream to close
  await streamClosed;
}

/**
 * The reconnection mechanism is implemented on the handle stream function
 * If any error occurs, the stream will wait for 1000ms and call 
 * the handleStream function, which in-turn will restart the stream
 */
async function subscribeCommand(client: Client, args: SubscribeRequest) {
  while (true) {
    try {
      await handleStream(client, args);
    } catch (error) {
      console.error("Stream error, retrying in 1 second...", error);
      await new Promise((resolve) => setTimeout(resolve, 1000));
      // the timeout can be changed here
    }
  }
}

// Instantiate Yellowstone gRPC client with env credentials
const client = new Client(
  process.env.GRPC_URL, //Your Region specific gRPC URL
  process.env.X_TOKEN, // your Access Token
  undefined,
);

const req: SubscribeRequest = {
  accounts: {},
  slots: {},
  transactions: {
    pumpFun: {
      vote: false,
      failed: false,
      signature: undefined,
      accountInclude: [ADDRESS_TO_STREAM_FROM],
      accountExclude: [],
      accountRequired: [],
    },
  },
  transactionsStatus: {},
  blocks: {},
  blocksMeta: {},
  entry: {},
  accountsDataSlice: [],
  ping: undefined,
  commitment: CommitmentLevel.CONFIRMED,
};

subscribeCommand(client, req);
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="success" %}
The complete code of implementing a reconnection mechanism is available on [GitHub ](https://github.com/Shyft-to/solana-defi/tree/main/general-grpc-examples/Typescript/add_a_reconnect_mechanism)and [Replit here](https://replit.com/@shyft-to/adding-a-reconnect-mechanism-to-grpc?v=1).
{% endhint %}

In the above example, if the stream is interrupted, we restart it after waiting for 1000ms. This time can be configured as per your requirement.


# Replaying Slots with Solana yellowstone gRPCs

Solana gRPC Geyser Guide – How to Stream Data from a Specific Slot on Connection or Reconnection

Reconnect mechanisms are important for production applications — we don’t want to miss any data due to temporary network issues. But sometimes, <mark style="color:yellow;">reconnecting</mark> alone <mark style="color:yellow;">isn’t enough</mark>. We also need to <mark style="color:yellow;">replay data from a specific slot</mark>, especially if a stream drops during critical updates. Yellowstone gRPC supports this via the `fromSlot` field in the subscription request. By storing the last received slot and including it in the next subscription, you can ensure your stream resumes from where it left off — without missing a single block or transaction.

{% hint style="success" %}
At any given time, the earliest available slot for replay is approximately **150 slots older than the current slot**.
{% endhint %}

The example below illustrates how you can replay from a specific slot upon disconnection. You can paste this code in Replit to see it in action, or simply run the Repl [code here](https://replit.com/@shyft-to/reconnecting-and-replaying-slots-for-yellowstone-grpc?v=1).

{% tabs %}
{% tab title="TypeScript" %}
{% code overflow="wrap" %}

```typescript
import Client, { CommitmentLevel } from "@triton-one/yellowstone-grpc";
import { SubscribeRequest } from "@triton-one/yellowstone-grpc/dist/types/grpc/geyser";
import base58 from "bs58";

const GRPC_URL = "https://grpc.ams.shyft.to"; //enter your grpc url here
const X_TOKEN = ""; //enter your grpc access token here
const MAX_RETRY_WITH_LAST_SLOT = 30;
const RETRY_DELAY_MS = 1000;
const ADDRESS_TO_STREAM_FROM = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P";

type StreamResult = {
  lastSlot?: string;
  hasRcvdMSg: boolean;
};

async function handleStream(
  client: Client,
  args: SubscribeRequest,
  lastSlot?: string,
): Promise<StreamResult> {
  const stream = await client.subscribe();
  let hasRcvdMSg = false;

  return new Promise((resolve, reject) => {
    stream.on("data", (data) => {
      const tx = data.transaction?.transaction?.transaction;
      if (tx?.signatures?.[0]) {
        const sig = base58.encode(tx.signatures[0]);
        console.log("Got tx:", sig);
        lastSlot = data.transaction.slot;
        hasRcvdMSg = true;
      }
    });

    stream.on("error", (err) => {
      stream.end();
      reject({ error: err, lastSlot, hasRcvdMSg });
    });

    const finalize = () => resolve({ lastSlot, hasRcvdMSg });
    stream.on("end", finalize);
    stream.on("close", finalize);

    stream.write(args, (err: any) => {
      if (err) reject({ error: err, lastSlot, hasRcvdMSg });
    });
  });
}

async function subscribeCommand(client: Client, args: SubscribeRequest) {
  let lastSlot: string | undefined;
  let retryCount = 0;

  while (true) {
    try {
      // checks if the stream is starting from a specific slot
      if (args.fromSlot) {
        console.log("Starting stream from slot", args.fromSlot);
      }
      // starts the stream from lastSlot if value is present
      const result = await handleStream(client, args, lastSlot);
      lastSlot = result.lastSlot;
      if (result.hasRcvdMSg) retryCount = 0;
    } catch (err: any) {
      console.error(
        `Stream error, retrying in ${RETRY_DELAY_MS / 1000} second...`,
      );
      //in case the stream is interrupted, it waits for a while before retrying
      await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY_MS));

      lastSlot = err.lastSlot;
      if (err.hasRcvdMSg) retryCount = 0;

      if (lastSlot && retryCount < MAX_RETRY_WITH_LAST_SLOT) {
        console.log(
          `#${retryCount} retrying with last slot ${lastSlot}, remaining retries ${
            MAX_RETRY_WITH_LAST_SLOT - retryCount
          }`,
        );
        // sets the fromSlot to the last slot received before the stream was interrupted, if it exists
        args.fromSlot = lastSlot;
        retryCount++;
      } else {
        //when there is no last slot available, it starts the stream from the latest slot
        console.log("Retrying from latest slot (no last slot available)");
        delete args.fromSlot;
        retryCount = 0;
        lastSlot = undefined;
      }
    }
  }
}

const client = new Client(GRPC_URL, X_TOKEN, {
  "grpc.keepalive_permit_without_calls": 1,
  "grpc.keepalive_time_ms": 10000,
  "grpc.keepalive_timeout_ms": 1000,
  "grpc.default_compression_algorithm": 2,
});

const req: SubscribeRequest = {
  accounts: {},
  slots: {},
  transactions: {
    pumpFun: {
      vote: false,
      failed: false,
      accountInclude: [ADDRESS_TO_STREAM_FROM],
      accountExclude: [],
      accountRequired: [],
    },
  },
  transactionsStatus: {},
  blocks: {},
  blocksMeta: {},
  entry: {},
  accountsDataSlice: [],
  commitment: CommitmentLevel.CONFIRMED,
};

subscribeCommand(client, req);
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="success" %}
The complete code of implementing a reconnection mechanism is available on [GitHub ](https://github.com/Shyft-to/solana-defi/tree/main/general-grpc-examples/Typescript/add_a_reconnect_mechanism)and [Replit here](https://replit.com/@shyft-to/reconnecting-and-replaying-slots-for-yellowstone-grpc#index.ts).
{% endhint %}

The above example implements a robust mechanism to **reconnect to the gRPC stream** and **replay from the last known slot** to avoid missing any data.

* **Reconnection**:\
  If the stream encounters an error (like a network drop), the stream automatically retries after waiting a short time (denoted by the`RETRY_DELAY_MS` variable). This loop ensures the stream keeps trying to reconnect without manual restart.
* **Replay from Last Slot**:\
  Before each retry, the app checks if it previously received any transaction data. If so, it stores the latest `slot` number (`lastSlot`). When reconnecting, it includes this `lastSlot` in the `fromSlot` field of the `SubscribeRequest`, telling Yellowstone gRPC to resume streaming **from that exact slot**, not from the current blockchain tip.


# Modifying your Subscribe Request

Solana gRPC Geyser Guide – How to Update Subscription Streams Without Disconnecting

Solana Yellowstone gRPCs, a reliable technology for production applications which rely on real-time data streams, However, practical applications often require dynamic adjustments. Modifying subscription requests without disconnecting the stream is crucial for several reasons:

* **Dynamic Address Tracking**: Applications often need to add or remove addresses based on incoming data.
* **Adapting to Market Changes**: Filters may need to update in response to new token listings, shifting trends, or user preferences.
* **Uninterrupted Data Flow**: Modifying subscriptions without breaking the stream helps prevent data loss and reduces latency.
* **Real-Time Responsiveness**: This flexibility is key for apps that must react quickly to live blockchain events.

You can modify you stream by sending new subscribe requests in the following manner. You can copy and paste this code on Replit and try it yourself, or can simply checkout the Repl we have created [here](https://replit.com/@shyft-to/modifying-subscribe-request-grpc?v=1).

{% tabs %}
{% tab title="TypeScript" %}
{% code overflow="wrap" %}

```typescript
import Client, {
  CommitmentLevel,
  SubscribeRequestAccountsDataSlice,
  SubscribeRequestFilterAccounts,
  SubscribeRequestFilterBlocks,
  SubscribeRequestFilterBlocksMeta,
  SubscribeRequestFilterEntry,
  SubscribeRequestFilterSlots,
  SubscribeRequestFilterTransactions,
} from "@triton-one/yellowstone-grpc";
import { SubscribeRequestPing } from "@triton-one/yellowstone-grpc/dist/grpc/geyser";

interface SubscribeRequest {
  accounts: { [key: string]: SubscribeRequestFilterAccounts };
  slots: { [key: string]: SubscribeRequestFilterSlots };
  transactions: { [key: string]: SubscribeRequestFilterTransactions };
  transactionsStatus: { [key: string]: SubscribeRequestFilterTransactions };
  blocks: { [key: string]: SubscribeRequestFilterBlocks };
  blocksMeta: { [key: string]: SubscribeRequestFilterBlocksMeta };
  entry: { [key: string]: SubscribeRequestFilterEntry };
  commitment?: CommitmentLevel;
  accountsDataSlice: SubscribeRequestAccountsDataSlice[];
  ping?: SubscribeRequestPing;
}

const subscribedWalletsA: string[] = [
  "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  "5n2WeFEQbfV65niEP63sZc3VA7EgC4gxcTzsGGuXpump",
  "4oJh9x5Cr14bfaBtUsXN1YUZbxRhuae9nrkSyWGSpump",
  "GBpE12CEBFY9C74gRBuZMTPgy2BGEJNCn4cHbEPKpump",
  "oraim8c9d1nkfuQk9EzGYEUGxqL3MHQYndRw1huVo5h",
];

const subscribedWalletsB: string[] = [
  "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
];

const subscribeRequest1: SubscribeRequest = {
  accounts: {},
  slots: {},
  transactions: {
    modifying_A: {
      vote: false,
      failed: false,
      signature: undefined,
      accountInclude: subscribedWalletsA,
      accountExclude: [],
      accountRequired: [],
    },
  },
  transactionsStatus: {},
  entry: {},
  blocks: {},
  blocksMeta: {},
  accountsDataSlice: [],
  ping: undefined,
  commitment: CommitmentLevel.PROCESSED,
};

// Subscribes to account changes for program-owned accounts of subscribedWalletsB
const subscribeRequest2: SubscribeRequest = {
  accounts: {
    modifying_B: {
      account: [],
      filters: [],
      owner: subscribedWalletsB,
    },
  },
  slots: {},
  transactions: {},
  transactionsStatus: {},
  blocks: {},
  blocksMeta: {
    block: [],
  },
  entry: {},
  accountsDataSlice: [],
  ping: undefined,
  commitment: CommitmentLevel.PROCESSED,
};

/**
 * Dynamically updates the current stream subscription with new request parameters.
 */
async function updateSubscription(stream: any, args: SubscribeRequest) {
  try {
    stream.write(args);
  } catch (error) {
    console.error("Failed to send updated subscription request:", error);
  }
}

/**
 * Handles a single streaming session.
 * Automatically switches to a second subscription request after a timeout.
 */
async function handleStream(client: Client, args: SubscribeRequest) {
  const stream = await client.subscribe();

  // Waits for the stream to close or error out
  const streamClosed = new Promise<void>((resolve, reject) => {
    stream.on("error", (error) => {
      console.error("Stream Error:", error);
      reject(error);
      stream.end();
    });
    stream.on("end", resolve);
    stream.on("close", resolve);
  });

  // Automatically switch subscription after 10 seconds
  setTimeout(async () => {
    console.log("🔁 Switching to second subscription request...");
    await updateSubscription(stream, subscribeRequest2);
  }, 10000);

  // Handle incoming data
  stream.on("data", async (data) => {
    try {
      console.log("📦 Streamed Data:", data);
      // You can add more processing logic here
    } catch (error) {
      console.error("Error processing stream data:", error);
    }
  });

  // Send initial subscription request
  await new Promise<void>((resolve, reject) => {
    stream.write(args, (err: any) => (err ? reject(err) : resolve()));
  }).catch((reason) => {
    console.error("Initial stream write failed:", reason);
    throw reason;
  });

  await streamClosed;
}

/**
 * Starts the stream and continuously attempts to reconnect on errors.
 */
async function subscribeCommand(client: Client, args: SubscribeRequest) {
  while (true) {
    try {
      await handleStream(client, args);
    } catch (error) {
      console.error("Stream error. Retrying in 1 second...", error);
      await new Promise((resolve) => setTimeout(resolve, 1000));
    }
  }
}

const client = new Client(process.env.GRPC_URL, process.env.X_TOKEN, undefined);

// Start streaming with the first subscription
subscribeCommand(client, subscribeRequest1);
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="success" %}
The complete code for updating subscribe requests is available on [GitHub](https://github.com/Shyft-to/solana-defi/tree/main/general-grpc-examples/Typescript/modifying_subscribe_request) and on [Replit here](https://replit.com/@shyft-to/modifying-subscribe-request-grpc?v=1).
{% endhint %}

The subscribe request can be updated by simply sending a new subscribe request to the stream, which is done by the `updateSubscription` method over here. In this example, the new subscribe request is sent after 10 seconds of which we start streaming, but you can call this method anytime in your code as per your requirement.


# Closing a gRPC Connection

Solana gRPC Geyser Guide – How to Properly Close Subscription Streams on Yellowstone Connections

Once the subscription stream is active, we can close it using `stream.cancel()` method.

When `stream.cancel()` is called, it triggers an `error` event with a message like "Cancelled" or error code `1`, which indicates a <mark style="color:yellow;">user-initiated shutdown</mark>. We listen for this event, identify it as intentional, and treat it as a normal closure rather than an actual error. Additionally, we listen for the `close` event to ensure the stream has fully terminated on the client side.

{% hint style="success" %}
This clean cancellation helps release server-side resources and ensures that any connection tracking (like tokens or sessions) can be properly cleaned up in middleware or proxy layers.&#x20;
{% endhint %}

You can paste this code in Replit to see it in action, or simply run the Repl [code here](https://replit.com/@shyft-to/closing-a-grpc-connection?v=1).

{% tabs %}
{% tab title="TypeScript" %}
{% code overflow="wrap" %}

```typescript
import Client, {
  CommitmentLevel,
  SubscribeRequestAccountsDataSlice,
  SubscribeRequestFilterAccounts,
  SubscribeRequestFilterBlocks,
  SubscribeRequestFilterBlocksMeta,
  SubscribeRequestFilterEntry,
  SubscribeRequestFilterSlots,
  SubscribeRequestFilterTransactions,
} from "@triton-one/yellowstone-grpc";
import bs58 from "bs58";

const PUBLIC_KEY_TO_LISTEN = "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"; //can be any address
const RUN_TIME = 5000; //decides how long to run
const GRPC_ENDPOINT = "https://grpc.ams.shyft.to"; //your gRPC endpoint
const X_TOKEN = ""; //your x-token

interface SubscribeRequest {
  accounts: { [key: string]: SubscribeRequestFilterAccounts };
  slots: { [key: string]: SubscribeRequestFilterSlots };
  transactions: { [key: string]: SubscribeRequestFilterTransactions };
  transactionsStatus: { [key: string]: SubscribeRequestFilterTransactions };
  blocks: { [key: string]: SubscribeRequestFilterBlocks };
  blocksMeta: { [key: string]: SubscribeRequestFilterBlocksMeta };
  entry: { [key: string]: SubscribeRequestFilterEntry };
  commitment?: CommitmentLevel | undefined;
  accountsDataSlice: SubscribeRequestAccountsDataSlice[];
}

const client = new Client(GRPC_ENDPOINT, X_TOKEN, undefined);

const req: SubscribeRequest = {
  accounts: {},
  slots: {},
  transactions: {
    raydiumLiquidityPoolV4: {
      vote: false,
      failed: false,
      signature: undefined,
      accountInclude: [PUBLIC_KEY_TO_LISTEN],
      accountExclude: [],
      accountRequired: [],
    },
  },
  transactionsStatus: {},
  entry: {},
  blocks: {},
  blocksMeta: {},
  accountsDataSlice: [],
  commitment: CommitmentLevel.PROCESSED,
};

async function handleStream(client: Client, args: SubscribeRequest) {
  console.log(`Subscribing and starting stream...`);
  const stream = await client.subscribe();
  console.log(`Streaming data and printing transactions...`);

  const streamClosed = new Promise<void>((resolve, reject) => {
    stream.on("error", (err: any) => {
      if (err.code === 1 || err.message.includes("Cancelled")) {
        //this indicates stream was cancelled by user.
        console.log("✅ Stream cancelled by user");
        resolve();
      } else {
        console.error("❌ Stream error:", err);
        reject(err);
      }
    });

    stream.on("close", () => {
      console.log("Stream closed.");
      resolve();
    });
  });

  stream.on("data", (data) => {
    if (data.transaction) {
      console.log(
        "Received: ",
        bs58.encode(data.transaction.transaction.signature),
      );
    }
  });

  // Subscribe
  stream.write(args);

  // Cancel after timeout
  setTimeout(() => {
    console.log("Cancelling stream...");
    try {
      stream.cancel();
      /*
       * stream.end() or stream.destroy();
       * Cancels the stream from the user end, and closes the stream.
       *
       * A "Cancelled on client" error (code 1) will be thrown once this is called,
       * which be caught in stream.on("error") function.
       * This is one of the ways to cancel the stream, and clear your connections, when using Shyft gRPCs.
       *
       * For more information on clearing connections, please check the FAQ section of gRPC docs
       * https://docs.shyft.to/solana-yellowstone-grpc/grpc-docs#solana-grpc-faq
       */
    } catch (error) {
      if (error.code !== "ERR_STREAM_PREMATURE_CLOSE") {
        console.error("Stream cancel error:", error);
      }
    }
  }, RUN_TIME);

  await streamClosed;
}

async function subscribeCommand(client: Client, args: SubscribeRequest) {
  await handleStream(client, args);
}

subscribeCommand(client, req);
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="success" %}
The complete code of closing a connection is available on [Replit here](https://replit.com/@shyft-to/closing-a-grpc-connection?v=1).
{% endhint %}

Please note that we can also use `stream.destroy()` to end and destroy the stream. When using this, the streaming does stop, but the connection is not terminated, and hence it is not useful in certain cases.


# Subscribing to Transactions

Stream Solana transaction through gRPC

A subscribe request defines the type of updates you want using filters. Filters allow you to set specific conditions—like monitoring a particular wallet, account, or transaction type—ensuring that you only receive updates relevant to your needs. We can subscribe to transactions using the <mark style="color:yellow;">transactions filter.</mark> The transactions filter has the following structure. The most important field here is the `accountInclude` **field which streams all transactions related to the account addresses specified there**. Its an array so you can specify multiple addresses in it.

```json
{
  "slots": {
    "slots": {}
  },
  "accounts": {},
  "transactions": {
    "transactionLabel": 
      {
          "vote": boolean | undefined, //optional
	  "failed": boolean | undefined, //optional
	  "signature": string | undefined, //optional
	  "accountInclude": string[], //updates streamed for these accounts
	  "accountExclude": string[], //updates for this will be excluded
          "accountRequired": string[] 
      }
  },
  "blocks": {},
  "blocksMeta": {},
  "accountsDataSlice": [],
  "commitment": CommitmentLevel.CONFIRMED //finalized or processed also available
}
```

### Subscribing to all transactions of an address

This request subscribes to all transactions of a Raydium. It can be any Solana address, a program, wallet, token etc.

{% code overflow="wrap" %}

```json
{
  "slots": {
    "slots": {}
  },
  "accounts": {},
  "transactions": {
    "raydiumPoolv4": {
      "vote": false,
      "failed": false,
      "accountInclude": [
        "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8" //You can enter any Solana address, wallet, token, program etc.
      ]
    }
  },
  "blocks": {},
  "blocksMeta": {},
  "accountsDataSlice": [],
  "commitment": CommitmentLevel.CONFIRMED
}
```

{% endcode %}

The transactions filter helps you focus on transactions from a specific Solana address. The first field in the filter (e.g., `raydiumPoolv4`in the above case) is a <mark style="color:yellow;">**client-assigned label**</mark>, allowing you to easily identify updates, especially when using multiple filters. The `vote` and `failed` fields are simple <mark style="color:yellow;">true/false options</mark>: set them to true to include vote or failed transactions, or false to exclude them. Lastly, **the** `accountInclude` **field specifies the&#x20;**<mark style="color:yellow;">**program's address**</mark>**, ensuring you only stream transactions related to that program**.

{% hint style="info" %}
For transactions, if all fields are empty, then all transactions are broadcasted. Otherwise, fields work as logical `AND`, and values in arrays as logical `OR`.
{% endhint %}

### Subscribing to all transactions of a Liquidity Pool

```json
{
  "slots": {
    "slots": {}
  },
  "accounts": {},
  "transactions": {
    "raydiumPoolv4": {
      "vote": false,
      "failed": false,
      "accountInclude": [
        "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin" //liquidity pool address
      ]
    }
  },
  "blocks": {},
  "blocksMeta": {},
  "accountsDataSlice": [],
  "commitment": CommitmentLevel.CONFIRMED
}
```

To receive transactions of a liquidity Pool, we have to specify the liquidity <mark style="color:yellow;">pool address</mark> in the `accountInclude` field.

### Subscribing to all transactions of multiple addresses

```json
{
  "slots": {
    "slots": {}
  },
  "accounts": {},
  "transactions": {
    "raydiumPoolv4": {
      "vote": false,
      "failed": false,
      "accountInclude": [
        "HgQy5bqJd3GcjqakukhfMpqAfP62nTxGiqAqh4QtTuHF",
        "8pQYy5peKKqKk34BvJBuuBAfakukTLsmT2MVSzijUgt1" //the list of wallet addresses
        //You can add more wallet addresses here
      ]
    }
  },
  "blocks": {},
  "blocksMeta": {},
  "accountsDataSlice": [],
  "commitment": CommitmentLevel.CONFIRMED
}
```

The `accountInclude` field is an <mark style="color:yellow;">array</mark> and can take <mark style="color:yellow;">multiple wallet addresses</mark>, and will subscribe to all transactions from them.

### Subscribing to all transactions of a token on Raydium

So far we were streaming all transaction of a Solana address. Now imagine, if you want all transactions of a token, but only on <mark style="color:yellow;">Raydium V4.</mark> You don't want transactions of that token on Orca or any other dex. In this case we will use a new field <mark style="color:yellow;">**accountRequired.**</mark>

```json
{
  "slots": {
    "slots": {}
  },
  "accounts": {},
  "transactions": {
    "raydiumPoolv4": {
      "vote": false,
      "failed": false,
      "accountInclude": [
        "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
      ],
      "accountRequired": ["675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"]
    }
  },
  "blocks": {},
  "blocksMeta": {},
  "accountsDataSlice": [],
  "commitment": CommitmentLevel.CONFIRMED
}
```

This  lets you add another layer of filter, now gRPC will stream you transactions of that token only if it has <mark style="color:yellow;">Raydium V4</mark> address in it.


# Streaming Transactions

Solana gRPC Geyser Examples — Ultra-Low Latency Transaction Streaming with Yellowstone gRPC

A subscribe request defines the type of updates you want using filters. Filters allow you to set specific conditions—like monitoring a particular wallet, account, or transaction type—ensuring that you only receive updates relevant to your needs. We can subscribe to transactions using the <mark style="color:yellow;">transactions filter.</mark> The transactions filter has the following structure. The most important field here is the `accountInclude` **field which streams all transactions related to the account addresses specified there**. Its an array so you can specify multiple addresses in it.

```json
{
  "slots": {
    "slots": {}
  },
  "accounts": {},
  "transactions": {
    "transactionLabel": 
      {
          "vote": boolean | undefined, //optional
	  "failed": boolean | undefined, //optional
	  "signature": string | undefined, //optional
	  "accountInclude": string[], //updates streamed for these accounts
	  "accountExclude": string[], //updates for this will be excluded
          "accountRequired": string[] 
      }
  },
  "blocks": {},
  "blocksMeta": {},
  "accountsDataSlice": [],
  "commitment": CommitmentLevel.CONFIRMED //finalized or processed also available
}
```

### Subscribing to all transactions of an address

This request subscribes to all transactions of a Raydium. It can be any Solana address, a program, wallet, token etc.

{% code overflow="wrap" %}

```json
{
  "slots": {
    "slots": {}
  },
  "accounts": {},
  "transactions": {
    "raydiumPoolv4": {
      "vote": false,
      "failed": false,
      "accountInclude": [
        "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8" //You can enter any Solana address, wallet, token, program etc.
      ]
    }
  },
  "blocks": {},
  "blocksMeta": {},
  "accountsDataSlice": [],
  "commitment": CommitmentLevel.CONFIRMED
}
```

{% endcode %}

The transactions filter helps you focus on transactions from a specific Solana address. The first field in the filter (e.g., `raydiumPoolv4`in the above case) is a <mark style="color:yellow;">**client-assigned label**</mark>, allowing you to easily identify updates, especially when using multiple filters. The `vote` and `failed` fields are simple <mark style="color:yellow;">true/false options</mark>: set them to true to include vote or failed transactions, or false to exclude them. Lastly, **the** `accountInclude` **field specifies the&#x20;**<mark style="color:yellow;">**program's address**</mark>**, ensuring you only stream transactions related to that program**.

{% hint style="info" %}
For transactions, if all fields are empty, then all transactions are broadcasted. Otherwise, fields work as logical `AND`, and values in arrays as logical `OR`.
{% endhint %}

### Subscribing to all transactions of a Liquidity Pool

```json
{
  "slots": {
    "slots": {}
  },
  "accounts": {},
  "transactions": {
    "raydiumPoolv4": {
      "vote": false,
      "failed": false,
      "accountInclude": [
        "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin" //liquidity pool address
      ]
    }
  },
  "blocks": {},
  "blocksMeta": {},
  "accountsDataSlice": [],
  "commitment": CommitmentLevel.CONFIRMED
}
```

To receive transactions of a liquidity Pool, we have to specify the liquidity <mark style="color:yellow;">pool address</mark> in the `accountInclude` field.

### Subscribing to all transactions of multiple addresses

```json
{
  "slots": {
    "slots": {}
  },
  "accounts": {},
  "transactions": {
    "raydiumPoolv4": {
      "vote": false,
      "failed": false,
      "accountInclude": [
        "HgQy5bqJd3GcjqakukhfMpqAfP62nTxGiqAqh4QtTuHF",
        "8pQYy5peKKqKk34BvJBuuBAfakukTLsmT2MVSzijUgt1" //the list of wallet addresses
        //You can add more wallet addresses here
      ]
    }
  },
  "blocks": {},
  "blocksMeta": {},
  "accountsDataSlice": [],
  "commitment": CommitmentLevel.CONFIRMED
}
```

The `accountInclude` field is an <mark style="color:yellow;">array</mark> and can take <mark style="color:yellow;">multiple wallet addresses</mark>, and will subscribe to all transactions from them.

### Subscribing to all transactions of a token on Raydium

So far we were streaming all transaction of a Solana address. Now imagine, if you want all transactions of a token, but only on <mark style="color:yellow;">Raydium V4.</mark> You don't want transactions of that token on Orca or any other dex. In this case we will use a new field <mark style="color:yellow;">**accountRequired.**</mark>

```json
{
  "slots": {
    "slots": {}
  },
  "accounts": {},
  "transactions": {
    "raydiumPoolv4": {
      "vote": false,
      "failed": false,
      "accountInclude": [
        "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
      ],
      "accountRequired": ["675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"]
    }
  },
  "blocks": {},
  "blocksMeta": {},
  "accountsDataSlice": [],
  "commitment": CommitmentLevel.CONFIRMED
}
```

This  lets you add another layer of filter, now gRPC will stream you transactions of that token only if it has <mark style="color:yellow;">Raydium V4</mark> address in it.


# All Transactions of an Address

Solana gRPC Geyser Example – How to Stream All Transactions of a Solana Address

This request subscribes to all transactions of a Raydium. It can be any Solana address, a program, wallet, token etc.

{% tabs %}
{% tab title="TypeScript" %}
{% code overflow="wrap" %}

```typescript
import Client, {
  CommitmentLevel,
  SubscribeRequestAccountsDataSlice,
  SubscribeRequestFilterAccounts,
  SubscribeRequestFilterBlocks,
  SubscribeRequestFilterBlocksMeta,
  SubscribeRequestFilterEntry,
  SubscribeRequestFilterSlots,
  SubscribeRequestFilterTransactions,
} from "@triton-one/yellowstone-grpc";
import { SubscribeRequestPing } from "@triton-one/yellowstone-grpc/dist/grpc/geyser";
import bs58 from "bs58";

// Interface for the subscription request structure
interface SubscribeRequest {
  accounts: { [key: string]: SubscribeRequestFilterAccounts };
  slots: { [key: string]: SubscribeRequestFilterSlots };
  transactions: { [key: string]: SubscribeRequestFilterTransactions };
  transactionsStatus: { [key: string]: SubscribeRequestFilterTransactions };
  blocks: { [key: string]: SubscribeRequestFilterBlocks };
  blocksMeta: { [key: string]: SubscribeRequestFilterBlocksMeta };
  entry: { [key: string]: SubscribeRequestFilterEntry };
  commitment?: CommitmentLevel;
  accountsDataSlice: SubscribeRequestAccountsDataSlice[];
  ping?: SubscribeRequestPing;
}

const ADDRESS_TO_STREAM_FROM = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P";

/**
 * Subscribes to the gRPC stream and handles incoming data.
 *
 * @param client - Yellowstone gRPC client
 * @param args - The Subscription request which specifies what data to stream
 */
async function handleStream(client: Client, args: SubscribeRequest) {
  const stream = await client.subscribe();

  // Promise that resolves when the stream ends or errors out
  const streamClosed = new Promise<void>((resolve, reject) => {
    stream.on("error", (error) => {
      console.error("Stream error:", error);
      reject(error);
      stream.end();
    });

    stream.on("end", resolve);
    stream.on("close", resolve);
  });

  // Handle incoming transaction data
  stream.on("data", (data) => {
    if (data?.transaction) {
      console.log("Received Transaction:");
      console.log(bs58.encode(data?.transaction?.transaction?.signature));
      console.log("\n");
      console.log(data?.transaction);
    }
  });

  // Send the subscription request
  await new Promise<void>((resolve, reject) => {
    stream.write(args, (err: any) => {
      err ? reject(err) : resolve();
    });
  }).catch((err) => {
    console.error("Failed to send subscription request:", err);
    throw err;
  });

  // Wait for the stream to close
  await streamClosed;
}

/**
 * Entry point to start the subscription stream.
 *
 */
async function subscribeCommand(client: Client, args: SubscribeRequest) {
  while (true) {
    try {
      await handleStream(client, args);
    } catch (error) {
      console.error("Stream error, retrying in 1 second...", error);
      await new Promise((resolve) => setTimeout(resolve, 1000));
    }
  }
}

// Instantiate Yellowstone gRPC client with env credentials
const client = new Client(
  "YOUR-GRPC-ENDPOINT", //Your Region specific gRPC URL
  "YOUR-ACCESS-TOKEN", // your Access Token
  undefined,
);

/**
 * Subscribe Request: The `transactions` field filters transaction streams to only include those
 * that involve the specified address in `accountInclude`.
 */
const req: SubscribeRequest = {
  accounts: {},
  slots: {},
  transactions: {
    pumpFun: {
      vote: false,
      failed: false,
      signature: undefined,
      accountInclude: [ADDRESS_TO_STREAM_FROM],
      accountExclude: [],
      accountRequired: [],
    },
  },
  transactionsStatus: {},
  blocks: {},
  blocksMeta: {},
  entry: {},
  accountsDataSlice: [],
  ping: undefined,
  commitment: CommitmentLevel.CONFIRMED,
};

// Start the subscription
subscribeCommand(client, req);
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="success" %}
You can copy and paste this code on Replit to see it action, or simply remix [<mark style="color:yellow;">this code</mark>](https://replit.com/@shyft-to/streaming-transactions-for-address?v=1) on Replit.
{% endhint %}

The transactions filter helps you focus on transactions from a specific Solana address. The first field in the filter (e.g., `raydiumPoolv4`in the above case) is a <mark style="color:yellow;">**client-assigned label**</mark>, allowing you to easily identify updates, especially when using multiple filters. The `vote` and `failed` fields are simple <mark style="color:yellow;">true/false options</mark>: set them to true to include vote or failed transactions, or false to exclude them. Lastly, **the** `accountInclude` **field specifies the&#x20;**<mark style="color:yellow;">**program's address**</mark>**, ensuring you only stream transactions related to that program**.

{% hint style="info" %}
For transactions, if all fields are empty, then all transactions are broadcasted. Otherwise, fields work as logical `AND`, and values in arrays as logical `OR`.
{% endhint %}


# All transactions of a Liquidity Pool

Solana gRPC Geyser Example — How to Stream All Transactions of a Liquidity Pool

A Subscribe Request These filters enable you to define precise conditions, such as monitoring a specific wallet, account, or transaction type. This subscribe request streams all transactions of a Liquidity Pool.

{% hint style="info" %}
For transactions, if all fields are empty, then all transactions are broadcasted. Otherwise, fields work as logical `AND`, and values in arrays as logical `OR`.
{% endhint %}

### Subscribing to all transactions of a Liquidity Pool

{% tabs %}
{% tab title="TypeScript" %}

```typescript
import Client, {
  CommitmentLevel,
  SubscribeRequestAccountsDataSlice,
  SubscribeRequestFilterAccounts,
  SubscribeRequestFilterBlocks,
  SubscribeRequestFilterBlocksMeta,
  SubscribeRequestFilterEntry,
  SubscribeRequestFilterSlots,
  SubscribeRequestFilterTransactions,
} from "@triton-one/yellowstone-grpc";
import { SubscribeRequestPing } from "@triton-one/yellowstone-grpc/dist/grpc/geyser";
import bs58 from "bs58";

// Interface for the subscription request structure
interface SubscribeRequest {
  accounts: { [key: string]: SubscribeRequestFilterAccounts };
  slots: { [key: string]: SubscribeRequestFilterSlots };
  transactions: { [key: string]: SubscribeRequestFilterTransactions };
  transactionsStatus: { [key: string]: SubscribeRequestFilterTransactions };
  blocks: { [key: string]: SubscribeRequestFilterBlocks };
  blocksMeta: { [key: string]: SubscribeRequestFilterBlocksMeta };
  entry: { [key: string]: SubscribeRequestFilterEntry };
  commitment?: CommitmentLevel;
  accountsDataSlice: SubscribeRequestAccountsDataSlice[];
  ping?: SubscribeRequestPing;
}

const ADDRESS_TO_STREAM_FROM = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P";

/**
 * Subscribes to the gRPC stream and handles incoming data.
 *
 * @param client - Yellowstone gRPC client
 * @param args - The Subscription request which specifies what data to stream
 */
async function handleStream(client: Client, args: SubscribeRequest) {
  const stream = await client.subscribe();

  // Promise that resolves when the stream ends or errors out
  const streamClosed = new Promise<void>((resolve, reject) => {
    stream.on("error", (error) => {
      console.error("Stream error:", error);
      reject(error);
      stream.end();
    });

    stream.on("end", resolve);
    stream.on("close", resolve);
  });

  // Handle incoming transaction data
  stream.on("data", (data) => {
    if (data?.transaction) {
      console.log("Received Transaction:");
      console.log(bs58.encode(data?.transaction?.transaction?.signature));
      console.log("\n");
      console.log(data?.transaction);
    }
  });

  // Send the subscription request
  await new Promise<void>((resolve, reject) => {
    stream.write(args, (err: any) => {
      err ? reject(err) : resolve();
    });
  }).catch((err) => {
    console.error("Failed to send subscription request:", err);
    throw err;
  });

  // Wait for the stream to close
  await streamClosed;
}

/**
 * Entry point to start the subscription stream.
 *
 */
async function subscribeCommand(client: Client, args: SubscribeRequest) {
  while (true) {
    try {
      await handleStream(client, args);
    } catch (error) {
      console.error("Stream error, retrying in 1 second...", error);
      await new Promise((resolve) => setTimeout(resolve, 1000));
    }
  }
}

// Instantiate Yellowstone gRPC client with env credentials
const client = new Client(
  "YOUR-GRPC-ENDPOINT", //Your Region specific gRPC URL
  "YOUR-ACCESS-TOKEN", // your Access Token
  undefined,
);

/**
 * Subscribe Request: The `transactions` field filters transaction streams to only include those
 * that involve the specified address in `accountInclude`.
 */
const req: SubscribeRequest = {
  accounts: {},
  slots: {},
  transactions: {
    pumpFun: {
      vote: false,
      failed: false,
      signature: undefined,
      accountInclude: [ADDRESS_TO_STREAM_FROM], //liquidity pool address
      accountExclude: [],
      accountRequired: [],
    },
  },
  transactionsStatus: {},
  blocks: {},
  blocksMeta: {},
  entry: {},
  accountsDataSlice: [],
  ping: undefined,
  commitment: CommitmentLevel.CONFIRMED,
};

// Start the subscription
subscribeCommand(client, req);
```

{% endtab %}
{% endtabs %}

{% hint style="success" %}
You can copy and paste this code on Replit to see it action, or simply remix [<mark style="color:yellow;">this code</mark>](https://replit.com/@shyft-to/streaming-transactions-for-address?v=1) on Replit.
{% endhint %}

To receive transactions of a liquidity Pool, we have to specify the liquidity <mark style="color:yellow;">pool address</mark> in the `accountInclude` field.


# All Transactions of Multiple Addresses

Solana gRPC Geyser Example – How to Track Transactions Across Multiple Wallets in Real-Time

A subscribe request defines the type of updates you want using filters. Filters allow you to set specific conditions—like monitoring a particular wallet, account, or transaction type—ensuring that you only receive updates relevant to your needs. We can subscribe to transactions using the <mark style="color:yellow;">transactions filter.</mark>

{% tabs %}
{% tab title="TypeScript" %}

```typescript
import Client, {
  CommitmentLevel,
  SubscribeRequestAccountsDataSlice,
  SubscribeRequestFilterAccounts,
  SubscribeRequestFilterBlocks,
  SubscribeRequestFilterBlocksMeta,
  SubscribeRequestFilterEntry,
  SubscribeRequestFilterSlots,
  SubscribeRequestFilterTransactions,
} from "@triton-one/yellowstone-grpc";
import { SubscribeRequestPing } from "@triton-one/yellowstone-grpc/dist/grpc/geyser";
import bs58 from "bs58";

// Interface for the subscription request structure
interface SubscribeRequest {
  accounts: { [key: string]: SubscribeRequestFilterAccounts };
  slots: { [key: string]: SubscribeRequestFilterSlots };
  transactions: { [key: string]: SubscribeRequestFilterTransactions };
  transactionsStatus: { [key: string]: SubscribeRequestFilterTransactions };
  blocks: { [key: string]: SubscribeRequestFilterBlocks };
  blocksMeta: { [key: string]: SubscribeRequestFilterBlocksMeta };
  entry: { [key: string]: SubscribeRequestFilterEntry };
  commitment?: CommitmentLevel;
  accountsDataSlice: SubscribeRequestAccountsDataSlice[];
  ping?: SubscribeRequestPing;
}

const ADDRESSES_TO_MONITOR = ["HgQy5bqJd3GcjqakukhfMpqAfP62nTxGiqAqh4QtTuHF","8pQYy5peKKqKk34BvJBuuBAfakukTLsmT2MVSzijUgt1"];

/**
 * Subscribes to the gRPC stream and handles incoming data.
 *
 * @param client - Yellowstone gRPC client
 * @param args - The Subscription request which specifies what data to stream
 */
async function handleStream(client: Client, args: SubscribeRequest) {
  const stream = await client.subscribe();

  // Promise that resolves when the stream ends or errors out
  const streamClosed = new Promise<void>((resolve, reject) => {
    stream.on("error", (error) => {
      console.error("Stream error:", error);
      reject(error);
      stream.end();
    });

    stream.on("end", resolve);
    stream.on("close", resolve);
  });

  // Handle incoming transaction data
  stream.on("data", (data) => {
    if (data?.transaction) {
      console.log("Received Transaction:");
      console.log(bs58.encode(data?.transaction?.transaction?.signature));
      console.log("\n");
      console.log(data?.transaction);
    }
  });

  // Send the subscription request
  await new Promise<void>((resolve, reject) => {
    stream.write(args, (err: any) => {
      err ? reject(err) : resolve();
    });
  }).catch((err) => {
    console.error("Failed to send subscription request:", err);
    throw err;
  });

  // Wait for the stream to close
  await streamClosed;
}

/**
 * Entry point to start the subscription stream.
 *
 */
async function subscribeCommand(client: Client, args: SubscribeRequest) {
  while (true) {
    try {
      await handleStream(client, args);
    } catch (error) {
      console.error("Stream error, retrying in 1 second...", error);
      await new Promise((resolve) => setTimeout(resolve, 1000));
    }
  }
}

// Instantiate Yellowstone gRPC client with env credentials
const client = new Client(
  "YOUR-GRPC-ENDPOINT", //Your Region specific gRPC URL
  "YOUR-ACCESS-TOKEN", // your Access Token
  undefined,
);

/**
 * Subscribe Request: The `transactions` field filters transaction streams to only include those
 * that involve the addresses in `accountInclude`.
 */
const req: SubscribeRequest = {
  accounts: {},
  slots: {},
  transactions: {
    pumpFun: {
      vote: false,
      failed: false,
      signature: undefined,
      accountInclude: ADDRESSES_TO_MONITOR, //list of wallets to be monitored
      accountExclude: [],
      accountRequired: [],
    },
  },
  transactionsStatus: {},
  blocks: {},
  blocksMeta: {},
  entry: {},
  accountsDataSlice: [],
  ping: undefined,
  commitment: CommitmentLevel.CONFIRMED,
};

// Start the subscription
subscribeCommand(client, req);

```

{% endtab %}
{% endtabs %}

The `accountInclude` field is an <mark style="color:yellow;">array</mark> and can take <mark style="color:yellow;">multiple wallet addresses</mark>, and will subscribe to all transactions from them.

{% hint style="success" %}
You can copy and paste this code on Replit to see it action, or simply remix [<mark style="color:yellow;">this code</mark>](https://replit.com/@shyft-to/streaming-transactions-for-multiple-address?v=1) on Replit.
{% endhint %}


# All Transactions of a Token

Solana gRPC Geyser Example – Subscribe to All Transactions of a Token on Solana

So far we were streaming all transaction of a Solana address. Now imagine, if you want all transactions of a token, but only on <mark style="color:yellow;">Raydium V4.</mark> You don't want transactions of that token on Orca or any other dex. In this case we will use a new field <mark style="color:yellow;">**accountRequired.**</mark>

{% tabs %}
{% tab title="TypeScript" %}

```typescript
import Client, {
  CommitmentLevel,
  SubscribeRequestAccountsDataSlice,
  SubscribeRequestFilterAccounts,
  SubscribeRequestFilterBlocks,
  SubscribeRequestFilterBlocksMeta,
  SubscribeRequestFilterEntry,
  SubscribeRequestFilterSlots,
  SubscribeRequestFilterTransactions,
} from "@triton-one/yellowstone-grpc";
import { SubscribeRequestPing } from "@triton-one/yellowstone-grpc/dist/grpc/geyser";
import bs58 from "bs58";

// Interface for the subscription request structure
interface SubscribeRequest {
  accounts: { [key: string]: SubscribeRequestFilterAccounts };
  slots: { [key: string]: SubscribeRequestFilterSlots };
  transactions: { [key: string]: SubscribeRequestFilterTransactions };
  transactionsStatus: { [key: string]: SubscribeRequestFilterTransactions };
  blocks: { [key: string]: SubscribeRequestFilterBlocks };
  blocksMeta: { [key: string]: SubscribeRequestFilterBlocksMeta };
  entry: { [key: string]: SubscribeRequestFilterEntry };
  commitment?: CommitmentLevel;
  accountsDataSlice: SubscribeRequestAccountsDataSlice[];
  ping?: SubscribeRequestPing;
}

/**
 * Subscribes to the gRPC stream and handles incoming data.
 *
 * @param client - Yellowstone gRPC client
 * @param args - The Subscription request which specifies what data to stream
 */
async function handleStream(client: Client, args: SubscribeRequest) {
  const stream = await client.subscribe();

  // Promise that resolves when the stream ends or errors out
  const streamClosed = new Promise<void>((resolve, reject) => {
    stream.on("error", (error) => {
      console.error("Stream error:", error);
      reject(error);
      stream.end();
    });

    stream.on("end", resolve);
    stream.on("close", resolve);
  });

  // Handle incoming transaction data
  stream.on("data", (data) => {
    if (data?.transaction) {
      console.log("\nReceived Transaction:");
      console.log(bs58.encode(data?.transaction?.transaction?.signature));
      console.log("\n");
      console.log(data?.transaction);
    }
  });

  // Send the subscription request
  await new Promise<void>((resolve, reject) => {
    stream.write(args, (err: any) => {
      err ? reject(err) : resolve();
    });
  }).catch((err) => {
    console.error("Failed to send subscription request:", err);
    throw err;
  });

  // Wait for the stream to close
  await streamClosed;
}

/**
 * Entry point to start the subscription stream.
 *
 */
async function subscribeCommand(client: Client, args: SubscribeRequest) {
  while (true) {
    try {
      await handleStream(client, args);
    } catch (error) {
      console.error("Stream error, retrying in 1 second...", error);
      await new Promise((resolve) => setTimeout(resolve, 1000));
    }
  }
}

// Instantiate Yellowstone gRPC client with env credentials
const client = new Client(
  "YOUR-GRPC-ENDPOINT", //Your Region specific gRPC URL
  "YOUR-ACCESS-TOKEN", // your Access Token
  undefined,
);

/**
 * Subscribe Request: The `transactions` field filters transaction streams to only include those
 * that involve the specified address in `accountInclude` and `accountRequired`.
 */
const req: SubscribeRequest = {
  accounts: {},
  slots: {},
  transactions: {
    pumpFun: {
      vote: false,
      failed: false,
      signature: undefined,
      accountInclude: [
        "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
      ],
      accountExclude: [],
      accountRequired: ["675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"],
    },
  },
  transactionsStatus: {},
  blocks: {},
  blocksMeta: {},
  entry: {},
  accountsDataSlice: [],
  ping: undefined,
  commitment: CommitmentLevel.CONFIRMED,
};

// Start the subscription
subscribeCommand(client, req);
```

{% endtab %}
{% endtabs %}

{% hint style="success" %}
You can copy and paste this code on Replit to see it action, or simply remix [<mark style="color:yellow;">this code</mark>](https://replit.com/@shyft-to/streaming-transactions-for-tokens-related-to-address?v=1) on Replit.
{% endhint %}

This  lets you add another layer of filter, now gRPC will stream you transactions of that token only if it has <mark style="color:yellow;">Raydium V4</mark> address in it.


# Subscribing to Accounts

Subscribe requests related to streaming real-time account updates

To receive account updates we use the <mark style="color:yellow;">accounts filter</mark> of the Subscribe request. The account filter has the following structure.

{% code overflow="wrap" %}

```json
{
  "slots": {},
  "accounts": {
      "accountLabel": {
        "account": string[], //account updates for these accounts 
        "owner": string[], //account updates for account with these owners
	"filters": {
	  "memcmp": {bytes and offset}  | undefined;
	  "datasize": string | undefined;
          "tokenAccountState": boolean | undefined;
        } 
  },
  "transactions": {},
  "blocks": {},
  "blocksMeta": {},
  "accountsDataSlice": [],
  "commitment": CommitmentLevel.CONFIRMED //commitment level, can be finalized or processed as well
}
```

{% endcode %}

Similar to the transactions filter, the first field under the accounts filter is the `accountLabel`, a <mark style="color:yellow;">user-defined label</mark> that helps you identify updates, especially when working with multiple filters. The `account` field specifies an array of <mark style="color:yellow;">account addresses</mark> for streaming account updates. The `owner` field streams updates for <mark style="color:yellow;">accounts owned</mark> by the specified addresses. Additionally, you can refine the data further by adding filters based on <mark style="color:yellow;">memcmp values</mark>, such as `bytes` and `dataSize`.

{% hint style="info" %}
The "key" at the start of all filters, (e.g. accountLabel, txnLabel) is a client-assigned label and can be set to any user-defined names.&#x20;
{% endhint %}

### Subscribe to account updates for a program

{% code overflow="wrap" %}

```json
{
  "slots": {},
  "accounts": {
    "pumpfun": {
      "owner": ["6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"] //account updates will be streamed for accounts with this owner
    }
  },
  "transactions": {},
  "blocks": {},
  "blocksMeta": {},
  "accountsDataSlice": [],
  "commitment": CommitmentLevel.PROCESSED
}
```

{% endcode %}

To stream all account updates for a program, use the `account` field under the accounts filter. The `owner` field should specify the <mark style="color:yellow;">program's address</mark>, as all accounts belonging to the program are owned by the program address itself.

### Subscribe to account updates of an address

{% code overflow="wrap" %}

```json
{
  "slots": {
    "slots": {}
  },
  "accounts": {
    "sol/usdc": {
      "account": ["9AnFgHoXFysVcuFFX7QztDmzuH8r5ZFvyP4sYwn1XTj9"] // pool address when streaming pool updates
    }
  },
  "transactions": {},
  "blocks": {},
  "blocksMeta": {},
  "accountsDataSlice": [],
  "commitment": CommitmentLevel.CONFIRMED
};
```

{% endcode %}

The `account` array accepts the <mark style="color:yellow;">pool address</mark> for which updates are being streamed. This is especially useful when monitoring the state of specific accounts, such as those in liquidity pools, to track changes in real time.

### Subscribe to account updates using Memory compare (memcmp)

`memcmp` filters allow you to <mark style="color:yellow;">match</mark> specific portions of <mark style="color:yellow;">binary data</mark> within accounts, helping you include only those account updates that <mark style="color:yellow;">meet specific criteria</mark>. This makes them especially useful for targeting specific states or values in program-owned accounts. For instance, you can use a `memcmp` filter to track liquidity pool balances, monitor token ownership, or identify program-specific flags. A `memcmp` filter typically specifies three key parameters: `offset`, which defines the starting byte position in the account data to compare; `bytes`, the value to match at the specified offset; and Encoding (optional), which determines how the bytes are encoded, such as base64 or base58.

```json
{
  "slots": {},
  "accounts": {
    "raydium": {
      "account": [],
      "filters": [
        {
          "memcmp": {
            "offset": LIQUIDITY_STATE_LAYOUT_V4.offsetOf('marketProgramId').toString(), 
            "base58": "srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX"
          }
        }
      ],
      "owner": ["675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"] 
    }
  },
  "transactions": {},
  "blocks": {},
  "blocksMeta": {
    "block": []
  },
  "accountsDataSlice": [],
  "commitment": CommitmentLevel.PROCESSED,
  "entry": {},
  "transactionsStatus": {}
}
```

For instance, this subscribe request streams updates for Raydium pool accounts with a `marketProgramId` equal to *<mark style="color:yellow;">serum</mark>*. The filter targets the `marketProgramId` field of the account, ensuring updates are streamed only for <mark style="color:yellow;">matching accounts</mark>.


# Streaming Accounts

Solana gRPC Geyser Examples – Stream Real-Time Account Updates on Solana

To receive account updates we use the <mark style="color:yellow;">accounts filter</mark> of the Subscribe request. The account filter has the following structure.

{% code overflow="wrap" %}

```json
{
  "slots": {},
  "accounts": {
      "accountLabel": {
        "account": string[], //account updates for these accounts 
        "owner": string[], //account updates for account with these owners
	"filters": {
	  "memcmp": {bytes and offset}  | undefined;
	  "datasize": string | undefined;
          "tokenAccountState": boolean | undefined;
        } 
  },
  "transactions": {},
  "blocks": {},
  "blocksMeta": {},
  "accountsDataSlice": [],
  "commitment": CommitmentLevel.CONFIRMED //commitment level, can be finalized or processed as well
}
```

{% endcode %}

{% hint style="info" %}
The "key" at the start of all filters, (e.g. accountLabel, txnLabel) is a client-assigned label and can be set to any user-defined names.&#x20;
{% endhint %}

Similar to the transactions filter, the first field under the accounts filter is the `accountLabel`, a <mark style="color:yellow;">user-defined label</mark> that helps you identify updates, especially when working with multiple filters. The `account` field specifies an array of <mark style="color:yellow;">account addresses</mark> for streaming account updates. The `owner` field streams updates for <mark style="color:yellow;">accounts owned</mark> by the specified addresses. Additionally, you can refine the data further by adding filters based on <mark style="color:yellow;">memcmp values</mark>, such as `bytes` and `dataSize`.


# Account Updates for a Program

Solana gRPC Geyser Example – How to Stream Program Account Updates on Solana

If an account belongs to a program, its owner is always the program's address.  To stream all account updates for a program, use the `account` field under the accounts filter. The `owner` field should specify the <mark style="color:yellow;">program's address</mark>, as all accounts belonging to the program are owned by the program address itself.

{% tabs %}
{% tab title="TypeScript" %}
{% code overflow="wrap" %}

```typescript
import Client, {
  CommitmentLevel,
  SubscribeRequestAccountsDataSlice,
  SubscribeRequestFilterAccounts,
  SubscribeRequestFilterBlocks,
  SubscribeRequestFilterBlocksMeta,
  SubscribeRequestFilterEntry,
  SubscribeRequestFilterSlots,
  SubscribeRequestFilterTransactions,
} from "@triton-one/yellowstone-grpc";
import { SubscribeRequestPing } from "@triton-one/yellowstone-grpc/dist/grpc/geyser";
import bs58 from "bs58";

const PROGRAM_ID_TO_SUB = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P";

// Interface for the subscription request structure
interface SubscribeRequest {
  accounts: { [key: string]: SubscribeRequestFilterAccounts };
  slots: { [key: string]: SubscribeRequestFilterSlots };
  transactions: { [key: string]: SubscribeRequestFilterTransactions };
  transactionsStatus: { [key: string]: SubscribeRequestFilterTransactions };
  blocks: { [key: string]: SubscribeRequestFilterBlocks };
  blocksMeta: { [key: string]: SubscribeRequestFilterBlocksMeta };
  entry: { [key: string]: SubscribeRequestFilterEntry };
  commitment?: CommitmentLevel;
  accountsDataSlice: SubscribeRequestAccountsDataSlice[];
  ping?: SubscribeRequestPing;
}

/**
 * Subscribes to the gRPC stream and handles incoming data.
 *
 * @param client - Yellowstone gRPC client
 * @param args - The Subscription request which specifies what data to stream
 */
async function handleStream(client: Client, args: SubscribeRequest) {
  const stream = await client.subscribe();

  // Promise that resolves when the stream ends or errors out
  const streamClosed = new Promise<void>((resolve, reject) => {
    stream.on("error", (error) => {
      console.error("Stream error:", error);
      reject(error);
      stream.end();
    });

    stream.on("end", resolve);
    stream.on("close", resolve);
  });

  // Handle incoming transaction data
  stream.on("data", (data) => {
    if (data?.account) {
      console.log("\nReceived Account Update for:");
      console.log(bs58.encode(data?.account?.account?.pubkey));
      console.log("\n");
      console.log(data?.account);
    }
  });

  // Send the subscription request
  await new Promise<void>((resolve, reject) => {
    stream.write(args, (err: any) => {
      err ? reject(err) : resolve();
    });
  }).catch((err) => {
    console.error("Failed to send subscription request:", err);
    throw err;
  });

  // Wait for the stream to close
  await streamClosed;
}

/**
 * Entry point to start the subscription stream.
 *
 */
async function subscribeCommand(client: Client, args: SubscribeRequest) {
  while (true) {
    try {
      await handleStream(client, args);
    } catch (error) {
      console.error("Stream error, retrying in 1 second...", error);
      await new Promise((resolve) => setTimeout(resolve, 1000));
    }
  }
}

// Instantiate Yellowstone gRPC client with env credentials
const client = new Client(
  "YOUR-GRPC-ENDPOINT", //Your Region specific gRPC URL
  "YOUR-GRPC-ACCESS-TOKEN", // your Access Token
  undefined,
);

/**
 * Subscribe Request: The `accounts` field is for streaming account updates. The `owner` field is for streaming updates for accounts owned by the specified program ID.
 */
const req: SubscribeRequest = {
  slots: {},
  accounts: {
    program_name: {
      account: [],
      filters: [],
      owner: [PROGRAM_ID_TO_SUB], //account updates will be streamed for accounts with this owner
    },
  },
  transactions: {},
  blocks: {},
  blocksMeta: {},
  accountsDataSlice: [],
  commitment: CommitmentLevel.PROCESSED, // Subscribe to processed blocks for the fastest updates
  entry: {},
  transactionsStatus: {},
};

// Start the subscription
subscribeCommand(client, req);

```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="success" %}
You can copy and paste this code on Replit to see it action, or simply remix [<mark style="color:yellow;">this code</mark>](https://replit.com/@shyft-to/streaming-account-updates-for-program?v=1) on Replit.
{% endhint %}


# Account Updates for an Address

Solana gRPC Geyser Example — How to Stream Account Updates for a Specific Address

The `account` array accepts the <mark style="color:yellow;">pool address</mark> for which updates are being streamed. This is especially useful when monitoring the state of specific accounts, such as those in liquidity pools, to track changes in real time.

{% tabs %}
{% tab title="TypeScript" %}
{% code overflow="wrap" %}

```typescript
import Client, {
  CommitmentLevel,
  SubscribeRequestAccountsDataSlice,
  SubscribeRequestFilterAccounts,
  SubscribeRequestFilterBlocks,
  SubscribeRequestFilterBlocksMeta,
  SubscribeRequestFilterEntry,
  SubscribeRequestFilterSlots,
  SubscribeRequestFilterTransactions,
} from "@triton-one/yellowstone-grpc";
import { SubscribeRequestPing } from "@triton-one/yellowstone-grpc/dist/grpc/geyser";
import bs58 from "bs58";


// Interface for the subscription request structure
interface SubscribeRequest {
  accounts: { [key: string]: SubscribeRequestFilterAccounts };
  slots: { [key: string]: SubscribeRequestFilterSlots };
  transactions: { [key: string]: SubscribeRequestFilterTransactions };
  transactionsStatus: { [key: string]: SubscribeRequestFilterTransactions };
  blocks: { [key: string]: SubscribeRequestFilterBlocks };
  blocksMeta: { [key: string]: SubscribeRequestFilterBlocksMeta };
  entry: { [key: string]: SubscribeRequestFilterEntry };
  commitment?: CommitmentLevel;
  accountsDataSlice: SubscribeRequestAccountsDataSlice[];
  ping?: SubscribeRequestPing;
}

/**
 * Subscribes to the gRPC stream and handles incoming data.
 *
 * @param client - Yellowstone gRPC client
 * @param args - The Subscription request which specifies what data to stream
 */
async function handleStream(client: Client, args: SubscribeRequest) {
  const stream = await client.subscribe();

  // Promise that resolves when the stream ends or errors out
  const streamClosed = new Promise<void>((resolve, reject) => {
    stream.on("error", (error) => {
      console.error("Stream error:", error);
      reject(error);
      stream.end();
    });

    stream.on("end", resolve);
    stream.on("close", resolve);
  });

  // Handle incoming transaction data
  stream.on("data", (data) => {
    if (data?.account) {
      console.log("\nReceived Account Update for:");
      console.log(bs58.encode(data?.account?.account?.pubkey));
      console.log("\n");
      console.log(data?.account);
    }
  });

  // Send the subscription request
  await new Promise<void>((resolve, reject) => {
    stream.write(args, (err: any) => {
      err ? reject(err) : resolve();
    });
  }).catch((err) => {
    console.error("Failed to send subscription request:", err);
    throw err;
  });

  // Wait for the stream to close
  await streamClosed;
}

/**
 * Entry point to start the subscription stream.
 *
 */
async function subscribeCommand(client: Client, args: SubscribeRequest) {
  while (true) {
    try {
      await handleStream(client, args);
    } catch (error) {
      console.error("Stream error, retrying in 1 second...", error);
      await new Promise((resolve) => setTimeout(resolve, 1000));
    }
  }
}

// Instantiate Yellowstone gRPC client with .env credentials
const client = new Client(
  "YOUR-GRPC-ENDPOINT", //Your Region specific gRPC URL
  "YOUR-GRPC-ACCESS-TOKEN", // your Access Token
  undefined,
);

/**
 * Subscribe Request: The `account` field is  for streaming account updates.
 * The `owner` field is for filtering updates based on the program ID.
 */
const req: SubscribeRequest = {
  slots: {},
  accounts: {
    sol_usdc: {
      account: ["9AnFgHoXFysVcuFFX7QztDmzuH8r5ZFvyP4sYwn1XTj9"], // pool address when streaming pool updates
      filters: [],
      owner: [],
    },
  },
  transactions: {},
  blocks: {},
  blocksMeta: {},
  accountsDataSlice: [],
  commitment: CommitmentLevel.PROCESSED, // Subscribe to processed blocks for the fastest updates
  entry: {},
  transactionsStatus: {},
};

// Start the subscription
subscribeCommand(client, req);
```

{% endcode %}
{% endtab %}
{% endtabs %}

Since an account's data can be updated many times during **its** lifecycle (for example liquidity pools), this subscription request will stream the updated data each time such an update occurs.

{% hint style="success" %}
You can copy and paste this code on Replit to see it action, or simply remix [<mark style="color:yellow;">this code</mark>](https://replit.com/@shyft-to/streaming-account-updates-for-address?v=1) on Replit.
{% endhint %}




---

[Next Page](/llms-full.txt/1)

