Skip to main content

GoldRush Streaming on Solana

Critical Rules

  1. GraphQL WebSocket URL: wss://streaming.goldrushdata.com/graphql.
  2. Chain enum: SOLANA_MAINNET (SCREAMING_SNAKE_CASE) - not solana-mainnet (that is the Foundational REST chain name).
  3. newPairs on SOLANA_MAINNET covers Raydium AMM/CLMM, Orca Whirlpool, Meteora DLMM/Dynamic, Jupiter, and PumpFun on one subscription. Filter client-side on the exchange field.
  4. PumpFun launches surface as exchange: pumpfun. Raydium graduations surface seconds later as exchange: raydium-amm with the same base_token.address.
  5. ohlcvCandlesForPair takes pool addresses (base58); ohlcvCandlesForToken takes SPL mints and aggregates across every pool carrying that token.
  6. walletTxs accepts thousands of wallet addresses per subscription on one WebSocket.
  7. No rate limits on Streaming for Solana; no per-IP subscription cap.

Common Recipes

GoalSubscriptionFilter / Args
New-pool firehose across every Solana DEXnewPairschain_name: SOLANA_MAINNET
PumpFun launches onlynewPairs → filter exchange === "pumpfun"client-side
Graduation detectionnewPairs → track (base_token.address, exchange) pairsclient-side
Live OHLCV for a specific poolohlcvCandlesForPairpair_addresses: ["<pool-pubkey>"]
Aggregated price for an SPL mintohlcvCandlesForTokentoken_addresses: ["<mint>"]
Wallet activity firehosewalletTxschain_name: SOLANA_MAINNET, wallet_addresses: [...]

GoldRush’s newPairs subscription on SOLANA_MAINNET delivers new DEX pairs as they appear.

Subscribe

GraphQL Subscription
subscription {
  newPairs(chain_name: SOLANA_MAINNET) {
    block_signed_at
    protocol
    pair_address
    base_token { contract_address contract_ticker_symbol contract_decimals }
    quote_token { contract_address contract_ticker_symbol contract_decimals }
    liquidity
  }
}
Python
import asyncio
import os
from gql import gql, Client
from gql.transport.websockets import WebsocketsTransport

WS_URL = "wss://streaming.goldrushdata.com/graphql"

SUBSCRIPTION = gql("""
subscription {
  newPairs(chain_name: SOLANA_MAINNET) {
    block_signed_at
    protocol
    pair_address
    base_token { contract_address contract_ticker_symbol contract_decimals }
    quote_token { contract_address contract_ticker_symbol contract_decimals }
    liquidity
  }
}
""")

async def main():
    transport = WebsocketsTransport(
        url=WS_URL,
        init_payload={"GOLDRUSH_API_KEY": os.environ["GOLDRUSH_API_KEY"]},
    )
    async with Client(transport=transport, fetch_schema_from_transport=False) as session:
        async for result in session.subscribe(SUBSCRIPTION):
            print(result["newPairs"])

asyncio.run(main())
Connect via WebSocket at wss://streaming.goldrushdata.com/graphql with your API key in the connection parameters. The protocol field carries the DEX protocol name. Filter client-side to scope to a particular venue.

Patterns

”New pools” tab

Stream the firehose, dedupe by pair_address, drop pools below a liquidity threshold to filter spam, and display chronologically.

Cross-DEX arbitrage discovery

The same base/quote pair can launch on multiple venues within minutes. Group new pools by base/quote token addresses to discover routes for arb.

Production considerations

  • Reconnect on close or error. Wrap the subscribe call in a function and re-invoke on error / complete with a 1-2s backoff.
  • Dedupe by pair_address. During brief reconnects you may see a recently-emitted pool twice; deduplicate on pair_address.
  • No backfill on reconnect. The subscription delivers events from the moment it opens. For historical pairs and swaps, use the warehouse swaps recipe.
  • DEX Swaps warehouse recipe - decoded swaps landed in your warehouse.
  • New DEX Pairs Stream reference - full subscription schema.


The walletTxs subscription delivers transactions for the wallets you subscribe to, with decoded_details typed as a SwapTransaction or TransferTransaction union member.

Subscribe

GraphQL Subscription
subscription {
  walletTxs(
    wallet_addresses: [
      "4ZJhPQAgUseCsWhKvJLTmmRRUV74fdoTpQLNfKoekbPY"
    ]
    chain_name: SOLANA_MAINNET
  ) {
    tx_hash
    block_signed_at
    from_address
    to_address
    successful
    decoded_type
    decoded_details {
      typeString
      ... on SwapTransaction {
        amount_in
        amount_out
        token_in { contract_address contract_ticker_symbol contract_decimals }
        token_out { contract_address contract_ticker_symbol contract_decimals }
      }
      ... on TransferTransaction {
        amount
        from
        to
        quote_usd
        quote_rate_usd
        contract_metadata { contract_address contract_ticker_symbol contract_decimals }
      }
    }
  }
}
The chain enum is SOLANA_MAINNET (SCREAMING_SNAKE_CASE), not solana-mainnet. The Streaming API uses the enum; the Foundational REST API uses the kebab-case form.

Patterns

Copy-trading

Subscribe to a curated list of high-performing wallets. Filter the stream on SwapTransaction and mirror to your own execution layer.

Whale watch

Subscribe to a curated list of high-balance wallets and surface every fill and large transfer in a live tape.

Compliance / AML alerts

Subscribe to flagged addresses. Filter on TransferTransaction events and alert when amount exceeds a threshold.

Push vs pull

For long-range transfer history, use the warehouse transfers normalizer; use walletTxs here for the live tip.

Production considerations

  • Reconnect on close or error. Wrap subscribe in a function; re-invoke with 1-2s backoff on error / complete.
  • Validate addresses up front. Pre-filter with a base58 validator before passing in.
  • No gap-fill on reconnect. Events that occurred during a disconnect are not replayed. For continuity across a gap, query the warehouse transfers or swaps table over the disconnect window.
  • Wallet endpoints - REST companion for SPL token balances.
  • SPL Transfers warehouse recipe - decoded SPL transfers landed in your warehouse.
  • DEX Swaps warehouse recipe - decoded DEX swaps landed in your warehouse.
  • Wallet Activity Stream reference - full subscription schema.

GoldRush exposes two OHLCV streams on SOLANA_MAINNET:
  • ohlcvCandlesForPair - candles for a specific pool address.
  • ohlcvCandlesForToken - candles aggregated across pools carrying that SPL mint.
Both deliver candles in real time over WebSocket as new swaps land in the pool.

Stream candles for a specific pool

Best for charting one pool.
GraphQL Subscription
subscription {
  ohlcvCandlesForPair(
    chain_name: SOLANA_MAINNET
    pair_addresses: ["58oQChx4yWmvKdwLLZzBi4ChoCc2fqCUWBkwMihLYQo2"]
    interval: ONE_MINUTE
    timeframe: ONE_HOUR
  ) {
    pair_address
    timestamp
    open
    high
    low
    close
    volume_usd
  }
}
pair_addresses is an array of base58 pool addresses. You can subscribe to multiple pools on one subscription.

Stream candles for a token (across all pools)

ohlcvCandlesForToken aggregates across pools carrying that mint.
subscription {
  ohlcvCandlesForToken(
    chain_name: SOLANA_MAINNET
    token_addresses: ["EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"]
    interval: ONE_MINUTE
    timeframe: ONE_HOUR
  ) {
    timestamp
    open
    high
    low
    close
    volume_usd
  }
}

When to use pairs vs tokens

Use caseStream
Chart a single poolohlcvCandlesForPair with the pool address
Track arbitrage between two venues for the same pairohlcvCandlesForPair with both pool addresses
Get the USD price of a token aggregated across poolsohlcvCandlesForToken

Patterns

TradingView chart

Subscribe to ohlcvCandlesForPair at the user’s selected interval; push candles into TradingView’s UDF datafeed adapter. The timestamp / open / high / low / close / volume_usd fields map 1:1 to UDF.

Discovery → chart

Pair this stream with the DEX firehose: when a new pool appears in newPairs, automatically subscribe to its OHLCV. Limit to pools above a liquidity threshold to avoid spam.

Pricing service

Use ohlcvCandlesForToken on 1d candles for an aggregated USD price.
  • DEX firehose - discover new pools to subscribe to.
  • OHLCV Pairs Stream reference - full subscription schema.
  • OHLCV Tokens Stream reference - full subscription schema.


Warehouse Recipes

The swaps normalizer streams decoded Solana DEX trades into your warehouse as one unified table. See the Solana normalizers page for the full per-column schema and supported protocols.

Why warehouse delivery

Streaming and REST are great for live execution and lookups, but every retention cohort, churn model, token analytics dashboard, and tax export lives in your data warehouse - not in HTTP responses. The Pipeline API streams Solana data continuously into customer-managed destinations with no ETL on your side.

Pipeline configuration

Create a pipeline In the GoldRush Platform, navigate to Manage Pipelines and click Create Pipeline. Name it solana-swaps. Pick Solana + Swaps Choose Solana as the chain and Swaps as the data type. Configure your destination Connect ClickHouse, BigQuery, Postgres, Kafka, S3/GCS/R2, SQS, or a Webhook. ClickHouse is recommended for high-volume analytical queries over swaps.
destination:
  type: "clickhouse"
  url: "https://your-cluster.clickhouse.cloud:8443"
  user: "${CH_USER}"
  password: "${CH_PASSWORD}"
  database: "solana_swaps"
  batch_size: 5000
Optional: SQL transform Filter or reshape rows before they land. Example: keep only swaps over $100 of volume.
transforms:
  swaps: >
    SELECT *
    FROM swaps
    WHERE volume_usd >= 100
Deploy Decoded swaps begin flowing within seconds.

Schema

The swaps table is documented in full on the Solana Normalizers page. Key columns include block_slot, block_time, tx_id, signer, pool_address, base_mint, quote_mint, base_amount, quote_amount, price_usd, volume_usd, protocol_name, and CPI attribution fields (outer_program, inner_program, instruction_type).

Sample analytical queries

Top tokens by 24h volume

SELECT
  base_mint,
  SUM(volume_usd) AS volume_24h
FROM swaps
WHERE block_time >= now() - INTERVAL 1 DAY
GROUP BY base_mint
ORDER BY volume_24h DESC
LIMIT 50;

Per-protocol market share by token

SELECT
  protocol_name,
  SUM(volume_usd) AS volume_24h,
  COUNT(*) AS swap_count
FROM swaps
WHERE base_mint = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
  AND block_time >= now() - INTERVAL 1 DAY
GROUP BY protocol_name
ORDER BY volume_24h DESC;

Whale activity

SELECT
  signer,
  SUM(volume_usd) AS volume_24h,
  COUNT(*) AS swap_count
FROM swaps
WHERE block_time >= now() - INTERVAL 1 DAY
GROUP BY signer
HAVING volume_24h > 1000000
ORDER BY volume_24h DESC;

Jupiter routing through Raydium and Orca

SELECT
  tx_id,
  protocol_name,
  outer_program,
  inner_program,
  base_mint,
  quote_mint,
  volume_usd
FROM swaps
WHERE outer_program = 'JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4' -- Jupiter v6
  AND block_time >= now() - INTERVAL 1 HOUR
ORDER BY tx_id, instruction_index;

Production tips

  • ClickHouse for high-volume analytics. Solana swap volume is significant; analytical queries over millions of rows are much faster on ClickHouse than Postgres.
  • Partition by block_date. Most analytical queries are time-bounded.
  • Materialized views for per-token metrics. Build hourly / daily roll-ups in ClickHouse materialized views to keep dashboards snappy.
  • Solana Normalizers (full schema) - column-level reference for swaps and other Solana entities.
  • SPL Transfers warehouse recipe - companion table for transfer-side analytics.
  • DEX firehose (streaming) - real-time push for new pair events.

The transfers normalizer streams decoded SPL token transfers on Solana into your warehouse. Each row carries source/destination account context (owner, balance pre/post, UI amount). See the Solana normalizers page for the full schema.

Pipeline configuration

Create a pipeline In the GoldRush Platform, navigate to Manage Pipelines and click Create Pipeline. Name it solana-spl-transfers. Pick Solana + Transfers Choose Solana as the chain and Transfers as the data type. Configure your destination Connect ClickHouse, BigQuery, Postgres, Kafka, S3/GCS/R2, SQS, or a Webhook.
destination:
  type: "postgres"
  url: "postgresql://your-host:5432/solana_data"
  user: "${PG_USER}"
  password: "${PG_PASSWORD}"
  batch_size: 1000
Optional: SQL transform Filter rows before they land. Example: keep only stablecoin transfers.
transforms:
  transfers: >
    SELECT *
    FROM transfers
    WHERE mint IN (
      'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',  -- USDC
      'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'   -- USDT
    )
Deploy Decoded transfers begin flowing within seconds.

Schema

The transfers table is documented in full on the Solana Normalizers page. Key columns:
  • block_slot, slot, block_time, tx_hash (signature).
  • mint, amount (raw uint64), token_decimals, is_raw_amount.
  • source_address (token account), source_owner (wallet pubkey).
  • destination_address, destination_owner.
  • Pre/post balances on both sides (*_pre_balance, *_post_balance) plus UI-amount variants.
  • transfer_index for ordering within a transaction.

Sample analytical queries

Daily stablecoin volume by mint

SELECT
  date_trunc('day', to_timestamp(block_time)) AS day,
  mint,
  SUM(amount::numeric / power(10, token_decimals)) AS volume_tokens
FROM transfers
WHERE mint IN (
  'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
  'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'
)
  AND block_time >= extract(epoch from now() - interval '30 days')
GROUP BY day, mint
ORDER BY day DESC, volume_tokens DESC;

Net flow per wallet for a token

WITH inflow AS (
  SELECT destination_owner AS wallet, mint, SUM(amount::numeric) AS in_amount
  FROM transfers
  WHERE mint = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
  GROUP BY destination_owner, mint
),
outflow AS (
  SELECT source_owner AS wallet, mint, SUM(amount::numeric) AS out_amount
  FROM transfers
  WHERE mint = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
  GROUP BY source_owner, mint
)
SELECT
  COALESCE(i.wallet, o.wallet) AS wallet,
  COALESCE(i.in_amount, 0) - COALESCE(o.out_amount, 0) AS net
FROM inflow i
FULL OUTER JOIN outflow o ON i.wallet = o.wallet AND i.mint = o.mint
ORDER BY net DESC
LIMIT 100;

Exchange deposit attribution

Maintain a table of known exchange wallets; join against destination_owner to attribute deposits.
SELECT
  ex.exchange_name,
  t.mint,
  date_trunc('day', to_timestamp(t.block_time)) AS day,
  SUM(t.amount::numeric / power(10, t.token_decimals)) AS deposits
FROM transfers t
JOIN known_exchanges ex ON t.destination_owner = ex.wallet
WHERE t.block_time >= extract(epoch from now() - interval '7 days')
GROUP BY ex.exchange_name, t.mint, day
ORDER BY day DESC, deposits DESC;

Production tips

  • source_owner and destination_owner are the wallet pubkeys, not the SPL token-account pubkeys. Index on these for wallet-centric queries.
  • amount is raw uint64. Always divide by power(10, token_decimals) (or use the *_ui balance columns) for human-readable amounts.
  • High-volume mints (USDC, USDT, WSOL). Partition by date and consider materialized views per top-N mint for fast dashboarding.
  • Solana Normalizers (full schema) - column-level reference for transfers and other Solana entities.
  • DEX Swaps warehouse recipe - companion table for DEX-trade analytics.
  • Wallet endpoints (REST) - REST lookups for the same transfer history.