Request the data you need by POSTing to /stream and you shall receive a stream of newline-separated JSON objects that package your data by block. For example

curl https://portal.sqd.dev/datasets/solana-mainnet/stream \
  -X POST \
  -d '{
    "type": "solana",
    "fromBlock": 325000000,
    "toBlock": 325000001,
    "fields": {
      "block": {"number": true},
      "instruction": {"data": true}
    },
    "instructions": [
      {"programId": [
        "MoonCVVNZFSYkqNXP6bxHLPL6QQJiMagDL3qcqUQTrG"
      ]}
    ]
  }'

outputs

{"header":{"number":325000000},"instructions":[{"data":"XJqfG9ATWCDLLmxbNnKxcQ6KRHveSXFyrM8JwmyievueP"}]}
{"header":{"number":325000001}}

Here, we requested all records on instructions executed against the MoonCVV...Trg program, with a bare minimum of fields. One such record was found for block 325000000. There were no records of such instructions being executed in block 325000001, but the block was included anyway to indicate the range boundary.

By using this general approach, you can

  • Get data on instructions, transactions, logs, balance updates and rewards.
  • Ensure that you only get the data you need by using a rich palette of filters.
  • Request data related to the data that matches your filters. In the example above we could request all transactions that contain matching instructions, or even all token balance updates caused by such transactions.

Solana data is updated in real time and includes unfinalized blocks, enabling latencies of 1-2 s. Just omit the toBlock field in the request and you’ll get the latest data.

Making your own client

Real life protocols and infra introduce a couple of complications that you need to know about to actually build a client:

  1. The endpoint may terminate the stream of blocks at any point. To resume the stream the client must update the fromBlock and the optional parentBlockHash fields of its request and send the request to the API again.

    Note that that does mean that our example theoretically could have taken two requests instead of one.

    If your request specifies a toBlock you can tell that it’s done when you get either a block with this slot number or an empty HTTP 200 response.

    If the range of your request is entirely above the range of available blocks you’ll get an HTTP 204 (No Content).

  2. Ensuring data correctness when streaming unfinalized blocks is somewhat complicated. If you don’t want to deal with that complexity and don’t mind that the newest available data is up to several hours old, use the alternative /finalized-stream endpoint; otherwise read on.

    Some of the shared code for pipes and the Squid SDK will deal with unfinalized blocks for you under the hood.

Base URL

For Solana use

https://portal.sqd.dev/datasets/solana-mainnet

Other SVM networks TBA.

Other endpoints

Request the data you need by POSTing to /stream and you shall receive a stream of newline-separated JSON objects that package your data by block. For example

curl https://portal.sqd.dev/datasets/solana-mainnet/stream \
  -X POST \
  -d '{
    "type": "solana",
    "fromBlock": 325000000,
    "toBlock": 325000001,
    "fields": {
      "block": {"number": true},
      "instruction": {"data": true}
    },
    "instructions": [
      {"programId": [
        "MoonCVVNZFSYkqNXP6bxHLPL6QQJiMagDL3qcqUQTrG"
      ]}
    ]
  }'

outputs

{"header":{"number":325000000},"instructions":[{"data":"XJqfG9ATWCDLLmxbNnKxcQ6KRHveSXFyrM8JwmyievueP"}]}
{"header":{"number":325000001}}

Here, we requested all records on instructions executed against the MoonCVV...Trg program, with a bare minimum of fields. One such record was found for block 325000000. There were no records of such instructions being executed in block 325000001, but the block was included anyway to indicate the range boundary.

By using this general approach, you can

  • Get data on instructions, transactions, logs, balance updates and rewards.
  • Ensure that you only get the data you need by using a rich palette of filters.
  • Request data related to the data that matches your filters. In the example above we could request all transactions that contain matching instructions, or even all token balance updates caused by such transactions.

Solana data is updated in real time and includes unfinalized blocks, enabling latencies of 1-2 s. Just omit the toBlock field in the request and you’ll get the latest data.

Making your own client

Real life protocols and infra introduce a couple of complications that you need to know about to actually build a client:

  1. The endpoint may terminate the stream of blocks at any point. To resume the stream the client must update the fromBlock and the optional parentBlockHash fields of its request and send the request to the API again.

    Note that that does mean that our example theoretically could have taken two requests instead of one.

    If your request specifies a toBlock you can tell that it’s done when you get either a block with this slot number or an empty HTTP 200 response.

    If the range of your request is entirely above the range of available blocks you’ll get an HTTP 204 (No Content).

  2. Ensuring data correctness when streaming unfinalized blocks is somewhat complicated. If you don’t want to deal with that complexity and don’t mind that the newest available data is up to several hours old, use the alternative /finalized-stream endpoint; otherwise read on.

    Some of the shared code for pipes and the Squid SDK will deal with unfinalized blocks for you under the hood.

Base URL

For Solana use

https://portal.sqd.dev/datasets/solana-mainnet

Other SVM networks TBA.

Other endpoints