# gRPC examples

> Copy-paste Yellowstone gRPC subscription code for accounts, transactions, and slots in TypeScript, Rust, Python, and grpcurl.

Working code to connect to Supanode gRPC and subscribe to streams.

## Prerequisites

- A Supanode account on a plan with gRPC (FOCUS, BUILD, GROW, or PROFESSIONAL).
- Your IPs registered in the allowlist via Telegram (gRPC uses IP allowlist authentication).
- Your gRPC endpoint - default Frankfurt: `fra.supanode.xyz:10013` for TLS or `fra.supanode.xyz:10010` for plaintext.
- Yellowstone gRPC client library for your language.

**Don't have an account yet?** Get a 48-hour free trial - contact us on Telegram: [@supanode_tgs](https://t.me/supanode_tgs).

## Test connection

Before writing code, verify your endpoint is reachable using `grpcurl`:

```bash
grpcurl fra.supanode.xyz:10013 geyser.Geyser/GetVersion
```

If you see a version number in the response, your connection works.

## Basic subscribe example

Subscribes to all successful transactions involving a specific program. The Python example generates its stubs from the Yellowstone gRPC [geyser.proto](https://github.com/rpcpool/yellowstone-grpc/blob/master/yellowstone-grpc-proto/proto/geyser.proto).

<Tabs>
  <Tab title="TypeScript">
    ```typescript
    import Client, { CommitmentLevel, SubscribeRequest } from "@triton-one/yellowstone-grpc";

    const client = new Client(
      "fra.supanode.xyz:10013",
      undefined,
      { "grpc.max_receive_message_length": 64 * 1024 * 1024 }
    );

    const stream = await client.subscribe();

    const request: SubscribeRequest = {
      commitment: CommitmentLevel.CONFIRMED,
      accounts: {},
      slots: {},
      transactions: {
        myFilter: {
          vote: false,
          failed: false,
          accountInclude: ["YOUR_PROGRAM_ID"],
          accountExclude: [],
          accountRequired: [],
        },
      },
      transactionsStatus: {},
      blocks: {},
      blocksMeta: {},
      entry: {},
      accountsDataSlice: [],
    };

    stream.write(request);

    stream.on("data", (data) => {
      if (data.transaction) {
        console.log(`Transaction: ${data.transaction.signature}`);
      }
    });
    ```
  </Tab>
  <Tab title="Rust">
    ```rust
    use yellowstone_grpc_client::{GeyserGrpcClient, ClientTlsConfig};
    use yellowstone_grpc_proto::geyser::{
        SubscribeRequest, SubscribeRequestFilterTransactions, CommitmentLevel,
    };
    use std::collections::HashMap;

    #[tokio::main]
    async fn main() -> anyhow::Result<()> {
        // TLS port :10013 (use plaintext port :10010 without tls_config instead).
        let mut client = GeyserGrpcClient::build_from_shared("https://fra.supanode.xyz:10013")?
            .tls_config(ClientTlsConfig::new().with_native_roots())?
            .connect()
            .await?;

        let mut transactions = HashMap::new();
        transactions.insert(
            "my_filter".to_string(),
            SubscribeRequestFilterTransactions {
                vote: Some(false),
                failed: Some(false),
                account_include: vec!["YOUR_PROGRAM_ID".to_string()],
                account_exclude: vec![],
                account_required: vec![],
                signature: None,
            },
        );

        let request = SubscribeRequest {
            commitment: Some(CommitmentLevel::Confirmed as i32),
            transactions,
            ..Default::default()
        };

        let (mut subscribe_tx, mut stream) = client.subscribe().await?;
        subscribe_tx.send(request).await?;

        while let Some(message) = stream.message().await? {
            println!("Received: {:?}", message);
        }

        Ok(())
    }
    ```
  </Tab>
  <Tab title="Python">
    ```python
    import grpc
    # Generate the stubs from the Yellowstone geyser.proto first, e.g.:
    #   python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. geyser.proto
    from geyser_pb2 import (
        SubscribeRequest, SubscribeRequestFilterTransactions, CommitmentLevel
    )
    from geyser_pb2_grpc import GeyserStub

    # Plaintext port is :10010. For the TLS port :10013 use grpc.secure_channel(...).
    channel = grpc.insecure_channel("fra.supanode.xyz:10010")
    stub = GeyserStub(channel)

    request = SubscribeRequest(
        commitment=CommitmentLevel.CONFIRMED,
        transactions={
            "my_filter": SubscribeRequestFilterTransactions(
                vote=False,
                failed=False,
                account_include=["YOUR_PROGRAM_ID"],
            )
        }
    )

    for response in stub.Subscribe(iter([request])):
        if response.HasField("transaction"):
            print(f"Transaction received")
    ```
  </Tab>
  <Tab title="grpcurl">
    ```bash
    grpcurl -d '{
        "commitment": "CONFIRMED",
        "transactions": {
          "my_filter": {
            "vote": false,
            "failed": false,
            "account_include": ["YOUR_PROGRAM_ID"]
          }
        }
      }' \
      fra.supanode.xyz:10013 \
      geyser.Geyser/Subscribe
    ```
  </Tab>
</Tabs>

## Production tips

1. **Reconnection with exponential backoff.** Network blips happen. Implement retry logic that starts at 1 second and backs off to 30 seconds. On `429` or `503` errors, always back off before retrying.

2. **Ping/pong for keepalive.** Yellowstone server sends ping every 15 seconds. Most client libraries handle this automatically.

3. **Use `accountsDataSlice` to reduce bandwidth.** If you only need part of an account's data, specify `accountsDataSlice: [{offset: 0, length: 40}]`.

4. **Choose commitment level wisely.** `processed` is fastest but can revert. `confirmed` is the practical default for trading. `finalized` adds ~13 seconds of latency.

5. **Handle stream restart gracefully.** When your stream restarts, you'll miss events during downtime. Design your application to recover from this.

## Where to go next

<CardGroup cols={2}>
  <Card title="Limits" icon="gauge" href="https://supanode.xyz/docs/solana/grpc/limits">Connection caps and filter limits.</Card>
  <Card title="Restrictions" icon="ban" href="https://supanode.xyz/docs/solana/grpc/restrictions">What's not supported on shared.</Card>
  <Card title="Free Trials" icon="bolt" href="https://supanode.xyz/docs/solana/pricing/free-trials">48-hour gRPC trial.</Card>
  <Card title="Yellowstone examples" icon="github" href="https://github.com/rpcpool/yellowstone-grpc/tree/master/examples">More examples on GitHub.</Card>
</CardGroup>
