Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/hypertekorg/hyperstack/llms.txt

Use this file to discover all available pages before exploring further.

Subscriptions enable real-time data synchronization. Views automatically subscribe to updates when you start watching them.

Subscription Methods

Hyperstack provides three ways to subscribe to data:

use() - Simple Data Stream

Emits the full entity data after each update. Simplest API for most use cases.
// Subscribe to list view
for await (const tokens of client.views.tokens.list.use()) {
  console.log('Current tokens:', tokens);
  // tokens: Token[]
}

// Subscribe to state view
for await (const token of client.views.tokens.state.use('So11111...')) {
  console.log('Token updated:', token);
  // token: Token
}

watch() - Update Stream

Emits update events (upsert, patch, delete). Use when you need to know the type of change.
// Watch list view
for await (const update of client.views.tokens.list.watch()) {
  switch (update.type) {
    case 'upsert':
      console.log('Token added/updated:', update.data);
      break;
    case 'patch':
      console.log('Token patched:', update.key, update.data);
      break;
    case 'delete':
      console.log('Token deleted:', update.key);
      break;
  }
}

// Watch state view
for await (const update of client.views.tokens.state.watch('So11111...')) {
  console.log('Update type:', update.type);
}
Update types:
type Update<T> =
  | { type: 'upsert'; key: string; data: T }
  | { type: 'patch'; key: string; data: Partial<T> }
  | { type: 'delete'; key: string };

watchRich() - Rich Update Stream

Emits before/after states. Use when you need to compare previous and current values.
for await (const update of client.views.tokens.list.watchRich()) {
  switch (update.type) {
    case 'created':
      console.log('New token:', update.data);
      break;
    case 'updated':
      console.log('Before:', update.before);
      console.log('After:', update.after);
      console.log('Changed fields:', update.patch);
      break;
    case 'deleted':
      console.log('Deleted:', update.lastKnown);
      break;
  }
}
Rich update types:
type RichUpdate<T> =
  | { type: 'created'; key: string; data: T }
  | { type: 'updated'; key: string; before: T; after: T; patch?: unknown }
  | { type: 'deleted'; key: string; lastKnown?: T };

Subscription Options

Limiting Results

// Limit to top 10 tokens
for await (const tokens of client.views.tokens.list.use({ limit: 10 })) {
  console.log('Top 10:', tokens);
}

// Skip first 10, take next 20
for await (const tokens of client.views.tokens.list.use({ 
  skip: 10, 
  limit: 20 
})) {
  console.log('Page 2:', tokens);
}

Server-Side Filters

// Filter by custom criteria
for await (const tokens of client.views.tokens.list.use({ 
  filters: { 
    min_volume: '10000',
    verified: 'true'
  }
})) {
  console.log('Filtered tokens:', tokens);
}
Filters are sent to the server and must be supported by your stream implementation.

Watching Specific Keys

// Watch multiple specific tokens
let keys = ["So11111...", "EPjFWdd5..."];
let mut stream = hs.views.tokens().list().watch_keys(&keys);

while let Some(update) = stream.next().await {
    println!("Update to tracked token: {:?}", update);
}

Subscription Lifecycle

Automatic Management

Subscriptions are reference-counted and automatically managed:
// First subscription - sends subscribe message
const stream1 = client.views.tokens.list.use();

// Second subscription - reuses existing subscription
const stream2 = client.views.tokens.list.use();

// When both streams end, unsubscribe message is sent

Manual Control

// Get subscription registry
const registry = client.getSubscriptionRegistry();

// Check active subscriptions
const active = registry.getActiveSubscriptions();
console.log('Active:', active);

// Clear all subscriptions
registry.clear();

Connection Monitoring

// Monitor frames
client.onFrame((frame) => {
  console.log('Received frame:', frame);
});

// Monitor connection state
client.onConnectionStateChange((state, error) => {
  if (state === 'reconnecting') {
    console.log('Reconnecting...');
  } else if (state === 'connected') {
    console.log('Reconnected, subscriptions restored');
  }
});
Subscriptions are automatically restored after reconnection.

Common Patterns

Conditional Subscriptions

function TokenDetail({ mint }: { mint: string | null }) {
  // Only subscribe when mint is provided
  const token = useEntity(
    MyStack, 
    'Token/state', 
    mint ?? ''
  );

  if (!mint) return <p>Select a token</p>;
  if (!token) return <p>Loading...</p>;
  return <p>{token.name}</p>;
}

Manual Refresh

// Views don't have manual refresh in core SDK
// Disconnect and reconnect to force refresh
function RefreshButton() {
  const { getClient } = useHyperstackContext();

  const handleRefresh = async () => {
    const client = getClient(MyStack);
    if (client) {
      client.clearStore();
      await client.disconnect();
      await client.connect();
    }
  };

  return <button onClick={handleRefresh}>Refresh</button>;
}

Next Steps

Views

Learn about state and list views

Transactions

Execute blockchain transactions

Build docs developers (and LLMs) love