> For the complete documentation index, see [llms.txt](https://docs.shyft.to/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.shyft.to/solana-yellowstone-grpc/docs/streaming-blocks-and-blocksmeta.md).

# 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": []
}
```
