For the complete documentation index optimized for AI agents, see llms.txt or llms-full.txt. A markdown version of this page is available by appending.mdto the URL or sendingAccept: text/markdown.
Filtering Feeds
For AI agents: the documentation index is at llms.txt (full corpus: llms-full.txt). A markdown source for this page is /using-stacks/filtering-feeds.md.
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 Arete 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 { useArete } from "arete-react";import { TOKEN_STACK } from "arete-stacks/token";
function TokenList() { const a4 = useArete(TOKEN_STACK); const [page, setPage] = useState(1); const pageSize = 10;
// Paginated subscription const { data: tokens } = a4.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 { Arete } from "arete-typescript";import { TOKEN_STACK } from "arete-stacks/token";
const a4 = await Arete.connect("wss://token.stack.arete.run", { stack: TOKEN_STACK,});
// Get first 10 entitiesfor await (const token of a4.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 a4.views.Token.list.use({ take: pageSize, skip: (page - 1) * pageSize})) { console.log(token.id.mint);}use a4_sdk::prelude::*;use a4_stacks::token::{TokenStack, Token};
let a4 = Arete::<TokenStack>::connect().await?;
// Get first 10 entitieslet mut stream = a4.views.token.list() .listen() .take(10);
// Get page 3 (skip 20, take 10)let page = 3;let page_size = 10;let mut stream = a4.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 } = a4.views.Token.state.use(tokenAddress);const tokenAddress = "So11111111111111111111111111111111111111112";
// One-shot queryconst token = await a4.views.Token.state.get(tokenAddress);
// Stream updatesfor await (const token of a4.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 arete::prelude::*;
#[arete(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 { useArete } from "arete-react";import { ORE_STREAM_STACK } from "arete-stacks/ore";
function LatestRounds() { const a4 = useArete(ORE_STREAM_STACK);
// Default views const { data: allRounds } = a4.views.OreRound.list.use(); const { data: round } = a4.views.OreRound.state.use(roundAddress);
// Custom view - sorted by round_id desc const { data: latestRounds } = a4.views.OreRound.latest.use();
return <div>{latestRounds?.map(r => <Round key={r.id.round_id} round={r} />)}</div>;}import { Arete } from "arete-typescript";import { ORE_STREAM_STACK } from "arete-stacks/ore";
const a4 = await Arete.connect("wss://ore.stack.arete.run", { stack: ORE_STREAM_STACK,});
// Default viewsconst allRounds = await a4.views.OreRound.list.get();const round = await a4.views.OreRound.state.get(roundAddress);
// Custom view - sorted by round_id descfor await (const round of a4.views.OreRound.latest.use()) { console.log("Round:", round.id.round_id);}use a4_sdk::prelude::*;use a4_stacks::ore::{OreStack, OreRound};
let a4 = Arete::<OreStack>::connect().await?;
// Default viewslet mut list_stream = a4.views.ore_round.list().listen();let round_address = "some-round-address";let mut state_stream = a4.views.ore_round.state().listen(round_address);
// Custom view - sorted by round_id desclet mut latest_stream = a4.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 a4.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 { useArete } from "arete-react";import { TOKEN_STACK } from "arete-stacks/token";
function HighVolumeTokens() { const a4 = useArete(TOKEN_STACK);
// Client-side filtering with where clause const { data: tokens } = a4.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 { Arete } from "arete-typescript";import { ORE_STREAM_STACK } from "arete-stacks/ore";
const a4 = await Arete.connect("wss://ore.stack.arete.run", { stack: ORE_STREAM_STACK,});
// Filter in the streaming loopfor await (const round of a4.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 a4_sdk::prelude::*;use a4_stacks::ore::{OreStack, OreRound};use futures::StreamExt;
let a4 = Arete::<OreStack>::connect().await?;
// Filter using stream adapterslet mut stream = a4.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);}