# Streaming Blocks & BlocksMeta

## Streaming Block Updates

With gRPC, you can stream solana blocks as they are produced. However, to reduce network load, **Shyft requires&#x20;**<mark style="color:yellow;">**at least one filter**</mark>**&#x20;to be added**. Only blocks matching the filter criteria will be streamed. The <mark style="color:yellow;">blocks filter</mark> has a specific structure to define these criteria.

{% hint style="info" %}
We need atleast one filter for streaming blocks with Shyft gRPCs
{% endhint %}

{% code overflow="wrap" %}

```json
{
  "slots": {},
  "accounts": {},
  "transactions": {},
  "blocks": {
    "blockLabel": {
	"accountInclude": string[],
	"includeTransactions": boolean | undefined, //optional
	"includeAccounts": boolean | undefined, //optional
	"includeEntries": boolean | undefined //optional
     }
  },
  "blocksMeta": {
    "block": []
  },
  "accountsDataSlice": [],
  "commitment": CommitmentLevel.PROCESSED, // Subscribe to processed blocks for the fastest updates, confirmed and finalized also available
  "entry": {},
  "transactionsStatus": {}
}
```

{% endcode %}

To stream transactions or accounts involving specific accounts, you can use the `accountInclude` field to filter for those updates. `includeAccounts` and `includeTransactions` are simply *boolean* flags which work as they are named.

{% 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";

const BLOCKS_TO_INCLUDE_ADDRESS = "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"; // Replace with your address to subscribe to blocks that include this address";

// 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?.block) {
      console.log("\nReceived Block Data: ");
      console.log(data?.block);
    }
  });

  // 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 `blocks` filter will stream blocks which include those
 * that involve the specified address in `accountInclude`.
 */
const req: SubscribeRequest = {
  slots: {},
  accounts: {},
  transactions: {},
  blocks: {
    blocks: {
      accountInclude: [BLOCKS_TO_INCLUDE_ADDRESS]
    }
  },
  blocksMeta: {},
  accountsDataSlice: [],
  commitment: CommitmentLevel.PROCESSED, // Subscribe to processed blocks for the fastest updates
  entry: {},
  transactionsStatus: {},
};

// Start the subscription
subscribeCommand(client, req);

```

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

The above code, subscribes to all block updates involving the address mentioned by `BLOCKS_TO_INCLUDE_ADDRESS` field.

{% hint style="success" %}
You can copy and paste the above code on Replit to see it in action, or simply remix [<mark style="color:yellow;">this project</mark>](https://replit.com/@shyft-to/streaming-block-updates?v=1) on Replit.
{% endhint %}

## Streaming BlocksMeta

The `blocksMeta` subscription is useful when you only need updates about <mark style="color:yellow;">blocks being processed</mark>, not the full block data. The blocksMeta subscription has the following request format:

```json
{
  "slots": {},
  "accounts": {},
  "transactions": {},
  "blocks": {},
  "blocksMeta": {
    "blockmetadata": {}
  },
  "accountsDataSlice": []
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.shyft.to/solana-yellowstone-grpc/docs/streaming-blocks-and-blocksmeta.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
