Filtering Feeds
When streaming data from views, you can control what the server sends to reduce bandwidth and improve performance.
Feed Parameters
Section titled “Feed Parameters”All Hyperstack SDKs support these parameters when subscribing to feeds:
| Parameter | Type | Description |
|---|---|---|
take | number | Maximum number of entities to return |
skip | number | Number of entities to skip (for pagination) |
key | string | Entity key for state view subscriptions |
Pagination
Section titled “Pagination”Use take and skip to paginate through large datasets:
import { useHyperStack } from "hyperstack-react";import { TOKEN_STACK } from "hyperstack-stacks/token";
function TokenList() { const hs = useHyperStack(TOKEN_STACK); const [page, setPage] = useState(1); const pageSize = 10;
// Paginated subscription const { data: tokens } = hs.views.Token.list.use({ take: pageSize, skip: (page - 1) * pageSize, });
return ( <div> {tokens?.map(t => <TokenRow key={t.id.mint} token={t} />)} <button onClick={() => setPage(p => p + 1)}>Next Page</button> </div> );}import { HyperStack } from "hyperstack-typescript";import { TOKEN_STACK } from "hyperstack-stacks/token";
const hs = await HyperStack.connect("wss://token.stack.usehyperstack.com", { stack: TOKEN_STACK,});
// Get first 10 entitiesfor await (const token of hs.views.Token.list.use({ take: 10 })) { console.log(token.id.mint);}
// Get page 3 (skip 20, take 10)const page = 3;const pageSize = 10;for await (const token of hs.views.Token.list.use({ take: pageSize, skip: (page - 1) * pageSize})) { console.log(token.id.mint);}use hyperstack_sdk::prelude::*;use hyperstack_stacks::token::{TokenStack, Token};
let hs = HyperStack::<TokenStack>::connect().await?;
// Get first 10 entitieslet mut stream = hs.views.token.list() .listen() .take(10);
// Get page 3 (skip 20, take 10)let page = 3;let page_size = 10;let mut stream = hs.views.token.list() .listen() .skip((page - 1) * page_size) .take(page_size);
while let Some(token) = stream.next().await { println!("Token: {:?}", token.id.mint);}State View Keys
Section titled “State View Keys”For state views, pass the entity key to subscribe to a specific entity:
const { data: token } = hs.views.Token.state.use(tokenAddress);const tokenAddress = "So11111111111111111111111111111111111111112";
// One-shot queryconst token = await hs.views.Token.state.get(tokenAddress);
// Stream updatesfor await (const token of hs.views.Token.state.use(tokenAddress)) { console.log("Token updated:", token.id.mint);}let token_address = "So11111111111111111111111111111111111111112";
let mut stream = views.state(token_address).watch();
while let Some(update) = stream.next().await { println!("Token updated: {:?}", update.data.id.mint);}Custom Views
Section titled “Custom Views”Beyond the default state and list views, stacks can define custom views with sorting and limits applied at the server level.
Why Custom Views?
Section titled “Why Custom Views?”- Reduced bandwidth - Server applies sorting/limits before transmitting
- Consistent ordering - Sort order is defined once in your stack
- Pre-configured limits - Useful for “top N” or “latest N” views
Defining Custom Views
Section titled “Defining Custom Views”Custom views are defined using the #[view] attribute on your entity struct:
use hyperstack::prelude::*;
#[hyperstack(idl = "idl/ore.json")]pub mod ore_stream { #[entity(name = "OreRound")] #[view(name = "latest", sort_by = "id.round_id", order = "desc")] pub struct OreRound { pub id: RoundId, pub state: RoundState, // ... other fields }}View Parameters
Section titled “View Parameters”| Parameter | Type | Description |
|---|---|---|
name | string | View name (e.g., "latest") |
sort_by | string | Field path to sort by (e.g., "id.round_id") |
order | "asc" | "desc" | Sort order (default: "desc") |
take | number | Optional limit on results |
Accessing Custom Views
Section titled “Accessing Custom Views”Custom views appear alongside the default views in your SDK:
import { useHyperStack } from "hyperstack-react";import { ORE_STREAM_STACK } from "hyperstack-stacks/ore";
function LatestRounds() { const hs = useHyperStack(ORE_STREAM_STACK);
// Default views const { data: allRounds } = hs.views.OreRound.list.use(); const { data: round } = hs.views.OreRound.state.use(roundAddress);
// Custom view - sorted by round_id desc const { data: latestRounds } = hs.views.OreRound.latest.use();
return <div>{latestRounds?.map(r => <Round key={r.id.round_id} round={r} />)}</div>;}import { HyperStack } from "hyperstack-typescript";import { ORE_STREAM_STACK } from "hyperstack-stacks/ore";
const hs = await HyperStack.connect("wss://ore.stack.usehyperstack.com", { stack: ORE_STREAM_STACK,});
// Default viewsconst allRounds = await hs.views.OreRound.list.get();const round = await hs.views.OreRound.state.get(roundAddress);
// Custom view - sorted by round_id descfor await (const round of hs.views.OreRound.latest.use()) { console.log("Round:", round.id.round_id);}use hyperstack_sdk::prelude::*;use hyperstack_stacks::ore::{OreStack, OreRound};
let hs = HyperStack::<OreStack>::connect().await?;
// Default viewslet mut list_stream = hs.views.ore_round.list().listen();let round_address = "some-round-address";let mut state_stream = hs.views.ore_round.state().listen(round_address);
// Custom view - sorted by round_id desclet mut latest_stream = hs.views.ore_round.latest().listen();
while let Some(round) = latest_stream.next().await { println!("Round: {:?}", round.id.round_id);}Example: Top 10 View
Section titled “Example: Top 10 View”#[entity(name = "Token")]#[view(name = "topByVolume", sort_by = "metrics.total_volume", order = "desc", take = 10)]pub struct Token { pub id: TokenId, pub metrics: TokenMetrics,}// Get top 10 tokens by volumefor await (const token of hs.views.Token.topByVolume.use()) { console.log(token.id.mint, token.metrics.total_volume);}See Stack Definitions for complete documentation on defining entities and views.
Client-Side Filtering
Section titled “Client-Side Filtering”If you need dynamic filtering that changes at runtime, apply filters client-side after receiving data:
The React SDK provides a where clause for declarative client-side filtering:
import { useHyperStack } from "hyperstack-react";import { TOKEN_STACK } from "hyperstack-stacks/token";
function HighVolumeTokens() { const hs = useHyperStack(TOKEN_STACK);
// Client-side filtering with where clause const { data: tokens } = hs.views.Token.list.use({ where: { volume: { gte: 10000 }, price: { lte: 100 } }, limit: 20, // Client-side limit });
return <TokenList tokens={tokens} />;}Supported where operators:
| Operator | Description |
|---|---|
gte | Greater than or equal |
lte | Less than or equal |
gt | Greater than |
lt | Less than |
| (value) | Exact match |
Filter data as it streams using standard JavaScript:
import { HyperStack } from "hyperstack-typescript";import { ORE_STREAM_STACK } from "hyperstack-stacks/ore";
const hs = await HyperStack.connect("wss://ore.stack.usehyperstack.com", { stack: ORE_STREAM_STACK,});
// Filter in the streaming loopfor await (const round of hs.views.OreRound.latest.use()) { // Skip rounds below threshold if ((round.state.motherlode ?? 0) < 1_000_000_000) continue;
console.log("High-value round:", round.id.round_id);}Use iterator adapters to filter streams:
use hyperstack_sdk::prelude::*;use hyperstack_stacks::ore::{OreStack, OreRound};use futures::StreamExt;
let hs = HyperStack::<OreStack>::connect().await?;
// Filter using stream adapterslet mut stream = hs.views.ore_round.latest() .listen() .filter(|round| { let high_value = round.state.motherlode.flatten().unwrap_or(0) >= 1_000_000_000; futures::future::ready(high_value) });
while let Some(round) = stream.next().await { println!("High-value round: {:?}", round.id.round_id);}