diff --git a/cli/src/api_client.rs b/cli/src/api_client.rs index 1e6a680..89d8650 100644 --- a/cli/src/api_client.rs +++ b/cli/src/api_client.rs @@ -269,6 +269,57 @@ pub struct StopDeploymentResponse { pub status: DeploymentStatus, } +// ======================================================================== +// Registry DTOs +// ======================================================================== + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct RegistryStackItem { + pub name: String, + pub description: Option, + pub websocket_url: String, + pub entities: Vec, + #[serde(default)] + pub visibility: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct RegistrySchemaResponse { + pub name: String, + pub websocket_url: String, + pub description: Option, + pub schema: StackSchema, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct StackSchema { + pub stack_name: String, + pub entities: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct EntitySchema { + pub name: String, + pub primary_keys: Vec, + pub fields: Vec, + pub views: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct FieldSchema { + pub path: String, + pub rust_type: String, + pub nullable: bool, + pub section: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ViewSchema { + pub id: String, + pub mode: String, + pub pipeline: Vec, +} + impl ApiClient { pub fn new() -> Result { let base_url = @@ -455,6 +506,62 @@ impl ApiClient { Ok(specs.into_iter().find(|s| s.name == name)) } + // ======================================================================== + // Registry endpoints (public, no auth required) + // ======================================================================== + + /// List all public stacks in the registry (no auth required) + pub fn list_registry(&self) -> Result> { + let response = self + .client + .get(format!("{}/api/registry", self.base_url)) + .send() + .context("Failed to send registry list request")?; + + Self::handle_response(response) + } + + /// Get a public stack's info from the registry (no auth required) + #[allow(dead_code)] + pub fn get_registry_stack(&self, name: &str) -> Result { + let response = self + .client + .get(format!("{}/api/registry/{}", self.base_url, name)) + .send() + .context("Failed to send registry get request")?; + + Self::handle_response(response) + } + + /// Get full schema for a public stack (no auth required) + pub fn get_registry_schema(&self, name: &str) -> Result { + let response = self + .client + .get(format!("{}/api/registry/{}/schema", self.base_url, name)) + .send() + .context("Failed to send registry schema request")?; + + Self::handle_response(response) + } + + // ======================================================================== + // Authenticated schema endpoints + // ======================================================================== + + /// Get schema for user's own spec (requires auth) + pub fn get_spec_schema(&self, spec_id: i32) -> Result { + let api_key = self.require_api_key()?; + + let response = self + .client + .get(format!("{}/api/specs/{}/schema", self.base_url, spec_id)) + .bearer_auth(api_key) + .send() + .context("Failed to send spec schema request")?; + + Self::handle_response(response) + } + // ======================================================================== // Build endpoints // ======================================================================== diff --git a/cli/src/commands/explore.rs b/cli/src/commands/explore.rs new file mode 100644 index 0000000..c0a6c86 --- /dev/null +++ b/cli/src/commands/explore.rs @@ -0,0 +1,278 @@ +use anyhow::Result; +use colored::Colorize; + +use crate::api_client::{ApiClient, EntitySchema, RegistryStackItem, DEFAULT_DOMAIN_SUFFIX}; + +pub fn list(json: bool) -> Result<()> { + let client = ApiClient::new()?; + let registry_stacks = client.list_registry()?; + let user_stacks = client.list_specs().ok(); + let user_deployments = if user_stacks.is_some() { + client.list_deployments(100).ok() + } else { + None + }; + + if json { + #[derive(serde::Serialize)] + struct ExploreListOutput { + registry: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + user_stacks: Option>, + } + + #[derive(serde::Serialize)] + struct UserStackItem { + name: String, + entity_name: String, + websocket_url: String, + status: Option, + } + + let user_items = user_stacks.map(|specs| { + let deployment_map: std::collections::HashMap = user_deployments + .unwrap_or_default() + .into_iter() + .map(|d| (d.spec_id, d)) + .collect(); + + specs + .into_iter() + .map(|spec| { + let deployment = deployment_map.get(&spec.id); + UserStackItem { + name: spec.name.clone(), + entity_name: spec.entity_name.clone(), + websocket_url: spec.websocket_url(DEFAULT_DOMAIN_SUFFIX), + status: deployment.map(|d| d.status.to_string()), + } + }) + .collect() + }); + + let output = ExploreListOutput { + registry: registry_stacks, + user_stacks: user_items, + }; + + println!("{}", serde_json::to_string_pretty(&output)?); + return Ok(()); + } + + if !registry_stacks.is_empty() { + println!("\n{}", "Public Registry".bold()); + println!("{}", "-".repeat(60).dimmed()); + + for stack in ®istry_stacks { + println!( + " {} {}", + stack.name.green().bold(), + stack.websocket_url.cyan() + ); + if let Some(desc) = &stack.description { + println!(" {}", desc.dimmed()); + } + println!(" Entities: {}", stack.entities.join(", ")); + println!(); + } + } + + if let Some(specs) = user_stacks { + if !specs.is_empty() { + let deployment_map: std::collections::HashMap = user_deployments + .unwrap_or_default() + .into_iter() + .map(|d| (d.spec_id, d)) + .collect(); + + println!("{}", "Your Stacks".bold()); + println!("{}", "-".repeat(60).dimmed()); + + for spec in &specs { + let deployment = deployment_map.get(&spec.id); + let status = deployment + .map(|d| d.status.to_string()) + .unwrap_or_else(|| "-".to_string()); + + println!( + " {} {} [{}]", + spec.name.green().bold(), + spec.websocket_url(DEFAULT_DOMAIN_SUFFIX).cyan(), + status, + ); + } + println!(); + } + } + + if registry_stacks.is_empty() { + println!("{}", "No stacks found in registry.".yellow()); + } + + println!( + "{}", + "Tip: Run `hs explore ` for detailed entity info".dimmed() + ); + + Ok(()) +} + +pub fn show(name: &str, entity: Option<&str>, json: bool) -> Result<()> { + let client = ApiClient::new()?; + let schema_response = match client.get_registry_schema(name) { + Ok(schema) => schema, + Err(_) => { + let spec = client.get_spec_by_name(name)?.ok_or_else(|| { + anyhow::anyhow!( + "Stack '{}' not found. Run `hs explore` to see available stacks.", + name + ) + })?; + client.get_spec_schema(spec.id)? + } + }; + + if let Some(entity_name) = entity { + let entity_schema = schema_response + .schema + .entities + .iter() + .find(|e| e.name.eq_ignore_ascii_case(entity_name)) + .ok_or_else(|| { + anyhow::anyhow!( + "Entity '{}' not found in stack '{}'. Available entities: {}", + entity_name, + name, + schema_response + .schema + .entities + .iter() + .map(|e| e.name.as_str()) + .collect::>() + .join(", ") + ) + })?; + + if json { + println!("{}", serde_json::to_string_pretty(&entity_schema)?); + return Ok(()); + } + + print_entity_detail(entity_schema); + return Ok(()); + } + + if json { + println!("{}", serde_json::to_string_pretty(&schema_response)?); + return Ok(()); + } + + println!( + "\n{} {}", + "Stack:".bold(), + schema_response.name.green().bold() + ); + println!(" URL: {}", schema_response.websocket_url.cyan()); + if let Some(desc) = &schema_response.description { + println!(" {}", desc.dimmed()); + } + + println!("\n{}", "Entities".bold()); + println!("{}", "-".repeat(60).dimmed()); + + for entity_schema in &schema_response.schema.entities { + let view_names: Vec<&str> = entity_schema + .views + .iter() + .map(|v| v.id.split('/').next_back().unwrap_or(v.id.as_str())) + .collect(); + + println!( + " {} {} views ({})", + entity_schema.name.green().bold(), + entity_schema.views.len(), + view_names.join(", ") + ); + println!( + " Primary key: {}", + entity_schema.primary_keys.join(", ").cyan() + ); + println!(" Fields: {}", entity_schema.fields.len()); + } + + println!(); + println!( + "{}", + format!("Tip: Run `hs explore {} ` for field details", name).dimmed() + ); + + Ok(()) +} + +fn print_entity_detail(entity: &EntitySchema) { + println!("\n{} {}", "Entity:".bold(), entity.name.green().bold()); + println!(" Primary key: {}", entity.primary_keys.join(", ").cyan()); + + println!("\n{}", "Fields".bold()); + println!("{}", "-".repeat(70).dimmed()); + + let mut current_section = String::new(); + for field in &entity.fields { + if field.section != current_section { + current_section = field.section.clone(); + println!(" {} {}", "-".dimmed(), current_section.bold()); + } + + let nullable_str = if field.nullable { "?" } else { "" }; + println!( + " {:<40} {}{}", + field.path, + field.rust_type.cyan(), + nullable_str.dimmed() + ); + } + + println!("\n{}", "Views".bold()); + println!("{}", "-".repeat(70).dimmed()); + + for view in &entity.views { + let view_short = view.id.split('/').next_back().unwrap_or(view.id.as_str()); + let pipeline_str = if view.pipeline.is_empty() { + String::new() + } else { + let steps: Vec = view + .pipeline + .iter() + .map(|p| { + if let Some(sort) = p.get("Sort") { + let key = sort + .get("key") + .and_then(|k| k.get("segments")) + .and_then(|s| s.as_array()) + .map(|a| { + a.iter() + .filter_map(|v| v.as_str()) + .collect::>() + .join(".") + }) + .unwrap_or_default(); + let order = sort.get("order").and_then(|o| o.as_str()).unwrap_or("asc"); + format!("sort by {} {}", key, order) + } else { + p.to_string() + } + }) + .collect(); + format!(" ({})", steps.join(", ")) + }; + + println!( + " {:<20} {:<8}{}", + view_short.green(), + view.mode, + pipeline_str.dimmed() + ); + } + + println!(); +} diff --git a/cli/src/commands/mod.rs b/cli/src/commands/mod.rs index e7dcaf2..1041756 100644 --- a/cli/src/commands/mod.rs +++ b/cli/src/commands/mod.rs @@ -2,6 +2,7 @@ pub mod auth; pub mod build; pub mod config; pub mod create; +pub mod explore; pub mod sdk; pub mod stack; pub mod status; diff --git a/cli/src/main.rs b/cli/src/main.rs index 2c198bb..10b5e03 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -105,6 +105,15 @@ enum Commands { /// Show overview of stacks, builds, and deployments Status, + /// Discover stacks and explore their schemas + Explore { + /// Stack name to explore + name: Option, + + /// Entity name to show field details + entity: Option, + }, + /// Push local stacks to remote (alias for 'stack push') Push { /// Name of specific stack to push (pushes all if not specified) @@ -397,6 +406,7 @@ fn command_name(cmd: &Commands) -> &'static str { Commands::Init => "init", Commands::Up { .. } => "up", Commands::Status => "status", + Commands::Explore { .. } => "explore", Commands::Push { .. } => "push", Commands::Sdk(_) => "sdk", Commands::Config(_) => "config", @@ -429,6 +439,10 @@ fn run(cli: Cli) -> anyhow::Result<()> { dry_run, } => commands::up::up(&cli.config, stack_name.as_deref(), branch, preview, dry_run), Commands::Status => commands::status::status(cli.json), + Commands::Explore { name, entity } => match name { + Some(name) => commands::explore::show(&name, entity.as_deref(), cli.json), + None => commands::explore::list(cli.json), + }, Commands::Push { stack_name } => commands::stack::push(&cli.config, stack_name.as_deref()), Commands::Sdk(sdk_cmd) => match sdk_cmd { SdkCommands::Create(create_cmd) => match create_cmd { diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index 6216099..0bb78f2 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -14,7 +14,21 @@ export default defineConfig({ expressiveCode: { plugins: [ecVersionPlugin()], }, - plugins: [starlightLlmsTxt()], + plugins: [ + starlightLlmsTxt({ + projectName: "Hyperstack", + description: + "Hyperstack is a system for programmable real-time data feeds on Solana. Stream any on-chain data to your app via WebSocket. Define data shapes in a Rust DSL, deploy, and consume with typed TypeScript, React, or Rust SDKs.", + promote: [ + "using-stacks/quickstart", + "using-stacks/connect", + "agent-skills/overview", + "agent-skills/prompts", + "sdks/typescript", + "sdks/react", + ], + }), + ], title: "Hyperstack", social: [ { @@ -39,6 +53,10 @@ export default defineConfig({ label: "Get Started", autogenerate: { directory: "using-stacks" }, }, + { + label: "Build with AI", + autogenerate: { directory: "agent-skills" }, + }, { label: "Building Stacks", items: [ @@ -47,6 +65,7 @@ export default defineConfig({ { slug: "building-stacks/installation" }, { slug: "building-stacks/configuration" }, { slug: "building-stacks/your-first-stack" }, + { slug: "building-stacks/finding-idls" }, { label: "Rust DSL", items: [ diff --git a/docs/public/agent.md b/docs/public/agent.md new file mode 100644 index 0000000..66113ef --- /dev/null +++ b/docs/public/agent.md @@ -0,0 +1,72 @@ +# Hyperstack Agent Setup + +You are setting up Hyperstack, a real-time Solana data streaming platform. Follow these steps in order. + +## Step 1: Install the Hyperstack CLI + +Preferred (Cargo): +``` +cargo install hyperstack-cli +``` + +If Cargo is not available, fall back to npm: +``` +npm install -g hyperstack-cli +``` + +Verify installation: +``` +hs --version +``` + +## Step 2: Install Agent Skills + +The `npx skills` tool installs skills for 40+ coding agents including Cursor, Claude Code, OpenCode, Codex, Windsurf, VS Code Copilot, Cline, Roo Code, and many more. It auto-detects which agents are present and installs to the correct location for each. + +``` +npx skills add usehyperstack/skills +``` + +This installs context files that teach you (the agent) how to use Hyperstack's SDKs, CLI, and Rust DSL. + +If you need to target a specific agent, or want to understand the options available, see the full `npx skills` documentation: https://github.com/vercel-labs/skills + +Common options: +- `npx skills add usehyperstack/skills --all` installs all skills to all detected agents without prompts +- `npx skills add usehyperstack/skills -a claude-code` targets a specific agent +- `npx skills add usehyperstack/skills -a cursor -a opencode` targets multiple agents +- `npx skills add usehyperstack/skills -g` installs globally (available across all projects) + +## Step 3: Discover Available Data + +``` +hs explore --json +``` + +This lists all available stacks you can stream data from. For each stack, get the full schema: + +``` +hs explore --json +``` + +For field-level detail on a specific entity: + +``` +hs explore --json +``` + +## Step 4: You Are Ready + +You now have everything needed to build with Hyperstack. + +Key rules: +- ALWAYS run `hs explore --json` before writing any Hyperstack code. Never guess entity names, field paths, or types. +- Use `hs explore --json` to get exact field names, types, and view definitions. +- The primary public stack is `ore` (ORE mining data). Run `hs explore ore --json` to see its entities. +- For React apps: install `hyperstack-react` and `hyperstack-stacks` +- For TypeScript apps: install `hyperstack-typescript` and `hyperstack-stacks` +- To scaffold a new project quickly: `npx hyperstack-cli create my-app` + +Full documentation: https://docs.usehyperstack.com +Agent skills reference: https://docs.usehyperstack.com/agent-skills/overview/ +Prompt cookbook: https://docs.usehyperstack.com/agent-skills/prompts/ diff --git a/docs/src/components/CopyPrompt.astro b/docs/src/components/CopyPrompt.astro new file mode 100644 index 0000000..9154fad --- /dev/null +++ b/docs/src/components/CopyPrompt.astro @@ -0,0 +1,153 @@ +--- +/** + * CopyPrompt - A prompt box with a floating copy button + * + * Usage in MDX: + * + * Your prompt text here. Can be multi-line. + * Just write naturally without escaping. + * + */ +--- + + +
+ +
+ +
+ + + + diff --git a/docs/src/content/docs/agent-skills/explore.mdx b/docs/src/content/docs/agent-skills/explore.mdx new file mode 100644 index 0000000..407af26 --- /dev/null +++ b/docs/src/content/docs/agent-skills/explore.mdx @@ -0,0 +1,179 @@ +--- +title: Schema Discovery +sidebar: + order: 3 +description: How agents use hs explore to discover stacks and get live schema information. +--- + +The `hs explore` command is how agents (and humans) discover available stacks and introspect their schemas. Agent skills instruct the AI to run this command before writing any Hyperstack code, so it always has accurate entity names, field paths, and types. + +--- + +## Usage + +```bash +# List all available stacks +hs explore + +# Show entities and views for a stack +hs explore + +# Show fields and types for a specific entity +hs explore +``` + +Add `--json` to any command for machine-readable output (this is what agents use): + +```bash +hs explore --json +hs explore ore --json +hs explore ore OreRound --json +``` + +--- + +## Listing Stacks + +```bash +$ hs explore + +Public Registry +──────────────────────────────────────────────────────── + ore wss://ore.stack.usehyperstack.com + Entities: OreRound, OreTreasury, OreMiner + +Your Stacks +──────────────────────────────────────────────────────── + my-game wss://my-game-abc123.stack.usehyperstack.com [active] +``` + +Without authentication, you see public registry stacks only. When logged in (`hs auth login`), you also see your own stacks. + +--- + +## Exploring a Stack + +```bash +$ hs explore ore + +Stack: ore (OreStream) + URL: wss://ore.stack.usehyperstack.com + +Entities +──────────────────────────────────────────────────────── + OreRound 3 views (state, list, latest) + Primary key: id.round_id + Fields: 15 + + OreTreasury 2 views (state, list) + Primary key: id.treasury_address + Fields: 8 + + OreMiner 2 views (state, list) + Primary key: id.miner_address + Fields: 12 + +Tip: Run `hs explore ore OreRound` for field details +``` + +--- + +## Entity Fields + +```bash +$ hs explore ore OreRound + +Entity: OreRound + Primary key: id.round_id + +Fields +────────────────────────────────────────────────────────────────── + ● id + id.round_id u64 + id.round_address Pubkey? + + ● state + state.motherlode u64? + state.total_miners u64? + state.total_deployed u64? + state.expires_at i64? + + ● metrics + metrics.deploy_count u64? + metrics.checkpoint_count u64? + + ● results + results.top_miner Pubkey? + results.top_miner_reward u64? + +Views +────────────────────────────────────────────────────────────────── + state State + list List + latest List (sort by id.round_id desc) +``` + +Field types with `?` are nullable (wrapped in `Option` on the Rust side, optional in TypeScript). + +--- + +## JSON Output + +Agents use the `--json` flag to get structured output they can parse: + +```bash +$ hs explore ore OreRound --json +``` + +```json +{ + "name": "OreRound", + "primary_keys": ["id.round_id"], + "fields": [ + { "path": "id.round_id", "rust_type": "u64", "nullable": false, "section": "id" }, + { "path": "id.round_address", "rust_type": "Pubkey", "nullable": true, "section": "id" }, + { "path": "state.motherlode", "rust_type": "u64", "nullable": true, "section": "state" } + ], + "views": [ + { "id": "OreRound/state", "mode": "state", "pipeline": [] }, + { "id": "OreRound/list", "mode": "list", "pipeline": [] }, + { "id": "OreRound/latest", "mode": "list", "pipeline": [{"Sort": {"key": "id.round_id", "order": "desc"}}] } + ] +} +``` + +This is what the agent skills instruct the AI to call. The AI then uses the field paths and types to write correct SDK code. + +--- + +## How Authentication Affects Results + +| State | What you see | +| ------------- | ----------------------------------------------- | +| Not logged in | Public stacks only | +| Logged in | Public stacks + global stacks + your own stacks | + +Public stacks like `ore` are always available to everyone. Global stacks are available to all authenticated users. Your own deployed stacks are only visible when logged in. + +```bash +# Log in to see all stacks +hs auth login + +# Now explore shows everything +hs explore +``` + +--- + +## Why This Matters for Agents + +The core problem with AI coding tools is stale context. If an agent has outdated schema information, it writes code with wrong field names or missing types. + +`hs explore` solves this because: + +- It queries the live Hyperstack API, not static files +- It reflects the exact schema of the deployed stack +- The CLI version you have installed determines the API compatibility +- Agent skills tell the AI to always run it before writing code + +This means you never need to update the skill files when a stack changes. The agent gets fresh data every time. diff --git a/docs/src/content/docs/agent-skills/overview.mdx b/docs/src/content/docs/agent-skills/overview.mdx new file mode 100644 index 0000000..0f55c3d --- /dev/null +++ b/docs/src/content/docs/agent-skills/overview.mdx @@ -0,0 +1,114 @@ +--- +title: Build with AI +sidebar: + order: 1 +description: Let your AI agent set up and build with Hyperstack. One prompt, fully automated. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components"; +import CopyPrompt from "../../../components/CopyPrompt.astro"; + +The fastest way to start with Hyperstack is to let your AI agent handle everything. Paste one prompt and your agent installs the CLI, sets up skills, discovers available data, and starts building. + +--- + +## Let Your Agent Do It + +Paste this into your AI coding agent (Cursor, Claude Code, OpenCode, Windsurf, or any agent that can read URLs): + + +Read https://docs.usehyperstack.com/agent.md and follow the instructions to set up Hyperstack in this project + + +That's it. Your agent will: + +1. Install the Hyperstack CLI (prefers Cargo, falls back to npm) +2. Install agent skills so it knows the SDK patterns +3. Run `hs explore --json` to discover available data streams +4. Be ready to build + +Once setup is complete, try asking: + +- "Build a React dashboard that displays live ORE mining rounds" +- "Show me the current ORE motherlode and total miners in real-time" +- "Create a custom stack from this IDL that tracks token balances" +- "What entities does the ore stack have? Show me all fields." + +--- + +## How It Works + +The setup prompt points your agent to a plain text instruction file. The agent reads it, executes the setup commands, and learns how to use Hyperstack through the installed skills. + +Agent skills are markdown files that teach your agent the SDK syntax, CLI commands, and patterns. The skills also instruct the agent to use the `hs` CLI for live data, so type information is always accurate. + +``` +┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ +│ Agent Skills │ ──▶ │ AI Agent │ ──▶ │ Your Code │ +│ (SDK patterns │ │ (Cursor, │ │ (correct │ +│ + CLI usage) │ │ Claude, etc.) │ │ from start) │ +└─────────────────┘ └─────────┬───────┘ └─────────────────┘ + │ + hs explore --json + │ + ┌─────────▼───────┐ + │ Hyperstack API │ + │ (live schemas) │ + └─────────────────┘ +``` + +Three skills are installed: + +| Skill | What It Teaches | +| -------------------- | --------------------------------------------------------------------------------- | +| `hyperstack` | Router skill that detects your intent and points the agent to the right sub-skill | +| `hyperstack-consume` | SDK patterns for connecting to streams and building UIs (TypeScript, React, Rust) | +| `hyperstack-build` | Rust DSL syntax for building custom stacks from Solana program IDLs | + +--- + +## Prefer to Set Up Manually? + +If you'd rather run the commands yourself instead of letting the agent handle it: + + + + +```bash +# Install the CLI +cargo install hyperstack-cli +# Or: npm install -g hyperstack-cli + +# Scaffold an app +npx hyperstack-cli create my-app +cd my-app + +# Install agent skills +npx skills add usehyperstack/skills +``` + + + + +```bash +# Install the CLI +cargo install hyperstack-cli +# Or: npm install -g hyperstack-cli + +# Install agent skills in your project +npx skills add usehyperstack/skills +``` + + + + +For editor-specific file locations and manual configuration, see [Editor Setup](/agent-skills/setup/). + +--- + +## Next Steps + +- [Prompt Cookbook](/agent-skills/prompts/) - Copy-paste prompts for common tasks +- [Tutorial: ORE Dashboard](/agent-skills/tutorial-ore-dashboard/) - Build a complete app with step-by-step prompts +- [Schema Discovery](/agent-skills/explore/) - How `hs explore` provides live type information +- [Editor Setup](/agent-skills/setup/) - Manual setup for specific editors diff --git a/docs/src/content/docs/agent-skills/prompts.mdx b/docs/src/content/docs/agent-skills/prompts.mdx new file mode 100644 index 0000000..4cba07a --- /dev/null +++ b/docs/src/content/docs/agent-skills/prompts.mdx @@ -0,0 +1,103 @@ +--- +title: Prompt Cookbook +sidebar: + order: 4 +description: Copy-paste prompts for building with Hyperstack using AI coding agents. +--- + +import CopyPrompt from "../../../components/CopyPrompt.astro"; + +Curated prompts to help your AI agent build with Hyperstack. These are designed to be copied directly into your agent chat (Cursor, Claude Code, etc.) to automate discovery and implementation. + +:::note[Skills required] +These prompts assume the Hyperstack agent skills are installed. The skills teach your agent the SDK patterns, CLI commands, and when to run `hs explore` — so you don't have to spell it out in every prompt. + +Not installed yet? See [Editor Setup](/agent-skills/setup/) to get started. +::: + +--- + +## Consuming ORE (React) + +### Live ORE Mining Dashboard + + +Build a React + Vite app that shows live ORE mining data. Display: +- Current round number and motherlode amount +- Total miners and total SOL deployed +- Countdown to round expiration +- Connection status indicator + +Use Tailwind for styling. + + + +**What you should get:** A React app with `HyperstackProvider`, `useHyperstack` hook, live-updating round stats, and a connection badge. + +### ORE Round History Table + + +Build a React component that shows a table of historical ORE mining rounds. Columns: Round #, Motherlode, Total Miners, Deploy Count, Top Miner (truncated address), and whether the motherlode was hit. Sort by round descending. Add a filter for minimum motherlode amount. + + +**What you should get:** A paginated or scrollable table showing historical ORE rounds with real-time updates as new rounds complete. + +### Live ORE Grid Heatmap + + +Build a React component that visualizes the current ORE mining round as an interactive 5x5 grid heatmap. Use `OreRound.latest` to get the live round data. For each square, show the deployed SOL amount (`state.deployed_per_square_ui`) with color intensity based on the amount. Show miner counts per square (`state.count_per_square`) on hover. Include a countdown to round expiration using `state.estimated_expires_at_unix`. Highlight the winning square (`results.winning_square`) when the round completes. + + +**What you should get:** A live-updating visual grid showing where miners are deploying SOL in the current round, with real-time countdown and win detection. + +--- + +## Consuming ORE (TypeScript CLI) + +### ORE Round Monitor CLI + + +Build a TypeScript CLI tool that monitors ORE mining rounds in real-time. On each update, print: Round number, motherlode amount, total miners, total deployed, deploy count, and time until expiration. Exit cleanly on Ctrl+C. + + +**What you should get:** A terminal utility that prints a clean, live-updating summary of every ORE round. + +### ORE Treasury Tracker + + +Build a TypeScript script that tracks the ORE treasury state in real-time. Log: treasury balance, motherlode, total staked, total refined, and total unclaimed. Calculate and display the percentage of ORE that is staked vs unclaimed. + + +**What you should get:** A script for monitoring treasury health and distribution metrics. + +--- + +## Building Custom Stacks + +### Build a custom stack for [Protocol X] + + +I want to build a Hyperstack stack that tracks [describe the protocol and what data you want]. The program ID is [PROGRAM_ID]. Find the IDL and build a stack that defines entities for the account types I want to track. + + +**What you should get:** The agent finds or guides you to the IDL, then scaffolds a new Hyperstack project with entities, field mappings, and views. + +### Add a new entity to my stack + + +I have an existing Hyperstack stack and I want to add a new entity that tracks [describe account type]. The IDL is already at `idl/[program].json`. Add an entity for the [AccountName] account with appropriate sections and field mappings, following the same patterns as the existing entities. + + +**What you should get:** A new entity definition added to your `stack.rs` with correct type mappings from the IDL. + +--- + +## Exploring and Discovery + +### What data is available? + + +Run `hs explore --json` and tell me what Hyperstack stacks are available. For each stack, run `hs explore [stack-name] --json` to list the entities. Then for the most interesting entities, run `hs explore [stack-name] [Entity] --json` to show me the fields and types. Summarize what data I can stream from each stack. + + +**What you should get:** A comprehensive overview of all data you can currently access through your Hyperstack installation. diff --git a/docs/src/content/docs/agent-skills/setup.mdx b/docs/src/content/docs/agent-skills/setup.mdx new file mode 100644 index 0000000..3a3274e --- /dev/null +++ b/docs/src/content/docs/agent-skills/setup.mdx @@ -0,0 +1,218 @@ +--- +title: Editor Setup +sidebar: + order: 2 +description: Manual setup for Hyperstack agent skills in Cursor, Claude Code, VS Code, Windsurf, and other AI coding tools. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components"; +import CopyPrompt from "../../../components/CopyPrompt.astro"; + +:::tip[Let your agent handle this] +The easiest setup is to paste this into your agent and let it do everything: + + +Read https://docs.usehyperstack.com/agent.md and follow the instructions to set up Hyperstack in this project + + +See [Build with AI](/agent-skills/overview/) for details. The instructions below are for manual setup. +::: + +If you prefer to install skills yourself, the universal command is: + +```bash +npx skills add usehyperstack/skills +``` + +This auto-detects your editor and installs the skill files to the right location. For editor-specific details or manual placement, see below. + +--- + +## Supported Editors + + + + +```bash +npx skills add usehyperstack/skills --agent cursor +``` + +Skill files are created in `.agents/skills/` in your project directory: + +``` +.agents/skills/ +├── hyperstack/SKILL.md +├── hyperstack-consume/SKILL.md +└── hyperstack-build/SKILL.md +``` + +To install manually, download the SKILL.md files from the [skills repo](https://github.com/usehyperstack/skills) and place them in `.agents/skills/`. + +:::tip[Allow CLI access] +When Cursor asks to run `hs explore`, approve it. The CLI commands are safe to run. +::: + + + + +```bash +npx skills add usehyperstack/skills --agent claude-code +``` + +Skills are installed in the `.claude/skills/` directory: + +``` +.claude/skills/ +├── hyperstack/SKILL.md +├── hyperstack-consume/SKILL.md +└── hyperstack-build/SKILL.md +``` + +You can also set project-level context in `CLAUDE.md` at the project root. + + + + +```bash +npx skills add usehyperstack/skills --agent windsurf +``` + +Skills are installed in `.windsurf/skills/`: + +``` +.windsurf/skills/ +├── hyperstack/SKILL.md +├── hyperstack-consume/SKILL.md +└── hyperstack-build/SKILL.md +``` + + + + +```bash +npx skills add usehyperstack/skills --agent github-copilot +``` + +Skills are installed in `.agents/skills/`: + +``` +.agents/skills/ +├── hyperstack/SKILL.md +├── hyperstack-consume/SKILL.md +└── hyperstack-build/SKILL.md +``` + + + + +```bash +npx skills add usehyperstack/skills --agent opencode +``` + +Skills are installed in `.agents/skills/`: + +``` +.agents/skills/ +├── hyperstack/SKILL.md +├── hyperstack-consume/SKILL.md +└── hyperstack-build/SKILL.md +``` + +You can also load skills directly in OpenCode using the `/skill` command. + + + + +```bash +npx skills add usehyperstack/skills --agent cline +``` + +Skills are installed in `.cline/skills/`: + +``` +.cline/skills/ +├── hyperstack/SKILL.md +├── hyperstack-consume/SKILL.md +└── hyperstack-build/SKILL.md +``` + + + + +The `npx skills` CLI supports 35+ agents. Common options: + +| Agent | Flag | +| ---------- | -------------------- | +| Codex | `--agent codex` | +| Gemini CLI | `--agent gemini-cli` | +| Roo Code | `--agent roo` | +| Goose | `--agent goose` | +| Continue | `--agent continue` | + +Run without `--agent` to auto-detect your environment: + +```bash +npx skills add usehyperstack/skills +``` + +If your editor isn't supported, manually copy the SKILL.md files from the [skills repository](https://github.com/usehyperstack/skills) into whatever location your editor reads custom context from. + + + + +--- + +## Prerequisites + +Agent skills reference the Hyperstack CLI for live schema discovery. Make sure the CLI is installed: + + + + +```bash +cargo install hyperstack-cli +``` + + + + +```bash +npm install -g hyperstack-cli +``` + + + + +The skills tell your agent to run `hs explore --json` to discover stacks and schemas. Without the CLI installed, the agent can still use the static SDK patterns from the skills, but won't be able to discover live schema information. + +--- + +## Verifying Installation + +After installing, ask your agent a Hyperstack question. For example: + + +What stacks are available on Hyperstack? Show me the entities and fields for the ore stack. + + +The agent should: + +1. Run `hs explore --json` to list available stacks +2. Run `hs explore ore --json` to get the ore stack schema +3. Present the entity names, field paths, and types + +If the agent doesn't recognize Hyperstack commands, check that the skill files are in the correct directory for your editor. + +--- + +## Updating Skills + +Skills are version-independent. The static patterns (SDK syntax, DSL macros) change rarely, and the dynamic data (entity schemas, field types) comes from `hs explore` which always reflects your installed CLI version. + +To update skills to the latest version: + +```bash +npx skills add usehyperstack/skills +``` + +This overwrites the existing skill files with the latest versions. diff --git a/docs/src/content/docs/agent-skills/tutorial-ore-dashboard.mdx b/docs/src/content/docs/agent-skills/tutorial-ore-dashboard.mdx new file mode 100644 index 0000000..50fa6ca --- /dev/null +++ b/docs/src/content/docs/agent-skills/tutorial-ore-dashboard.mdx @@ -0,0 +1,111 @@ +--- +title: "Tutorial: ORE Dashboard" +sidebar: + order: 6 + badge: New +description: Build a live ORE mining dashboard by prompting your AI agent step by step. +--- + +import CopyPrompt from "../../../components/CopyPrompt.astro"; + +This tutorial shows you how to build a real-time ORE mining dashboard without writing any code. You will use your AI agent to discover the data, set up the project, and implement the UI. + +--- + +## Prerequisites + +- Install agent skills: `npx skills add usehyperstack/skills` +- Install Hyperstack CLI: `npm i -g hyperstack-cli` +- A code editor with an AI agent (Cursor, VS Code with Copilot, etc.) + +--- + +## Step 1: Scaffold the Project + +Start by creating the basic project structure and installing dependencies. + +**Prompt:** + + +Create a new React + Vite + TypeScript project. Install these dependencies: hyperstack-react, hyperstack-stacks, tailwindcss. Set up Tailwind with the Vite plugin. + + +--- + +## Step 2: Discover the ORE Schema + +Ask your agent to look at the available ORE data to understand what you can build. + +**Prompt:** + + +Run `hs explore ore --json` and `hs explore ore OreRound --json` to understand the ORE stack schema. Summarize the available entities, views, and fields. + + +--- + +## Step 3: Build the Main Layout + +Set up the application shell with a connection status indicator. + +**Prompt:** + + +Create the main `App.tsx` with a `HyperstackProvider` (autoConnect={true}). Create an `OreDashboard` component that will hold our mining data display. Use a dark theme with tailwind (bg-gray-900, text-white). Add a header that says "ORE Mining Dashboard" with a connection status indicator. + + +--- + +## Step 4: Add Live Round Data + +Connect to the live round view to show the current mining status. + +**Prompt:** + + +In the `OreDashboard` component, use the `useHyperstack` hook with `ORE_STREAM_STACK` from `hyperstack-stacks/ore`. Subscribe to the `OreRound.latest` view using `useOne()` to get the current round. Display: Round number (`id.round_id`), Motherlode amount (`state.motherlode`), Total miners (`state.total_miners`), Total deployed (`state.total_deployed`), and Deploy count (`metrics.deploy_count`). Format large numbers with commas. + + +--- + +## Step 5: Add Treasury Data + +Include high-level stats about the ORE treasury. + +**Prompt:** + + +Add a section that shows the ORE treasury state. Use `OreTreasury.list` view with `useOne()`. Display: Total staked, Total refined, Total unclaimed, and Treasury balance. Put these in a grid of stat cards. + + +--- + +## Step 6: Add Round History + +List previous rounds to show historical mining activity. + +**Prompt:** + + +Add a section below the stats that shows recent rounds in a table. Use `OreRound.list` view with `use()`. Show the last 10 rounds with columns: Round #, Motherlode, Miners, Deployed, Motherlode Hit (boolean as a checkmark or X). Sort by `round_id` descending in the component. + + +--- + +## Step 7: Polish the UI + +Make the dashboard look professional and responsive. + +**Prompt:** + + +Clean up the layout. Add subtle animations for when data updates like a brief highlight or pulse effect. Make the stat cards have a slightly lighter background (`bg-gray-800`). Add a footer that says "Powered by Hyperstack" with a link to `docs.usehyperstack.com`. Ensure the app is responsive on mobile devices. + + +--- + +## The Result + +Once your agent finishes the final step, you will have a fully functional, real-time dashboard. The app connects to the Hyperstack ORE stream and updates automatically as new data hits the Solana blockchain. + +You built a complex, data-heavy application in minutes without writing a single line of manual code. diff --git a/docs/src/content/docs/building-stacks/finding-idls.mdx b/docs/src/content/docs/building-stacks/finding-idls.mdx new file mode 100644 index 0000000..c8dfb44 --- /dev/null +++ b/docs/src/content/docs/building-stacks/finding-idls.mdx @@ -0,0 +1,80 @@ +--- +title: Finding IDLs +description: How to find IDL files for Solana programs when building custom Hyperstack stacks. +--- + +Hyperstack uses IDL (Interface Definition Language) files to generate type-safe bindings for your data streams. An IDL is a JSON file that describes a Solana program's accounts, instructions, and custom types. Hyperstack supports Anchor and other framework IDL formats. + +To build a custom stack, you need the IDL for the program you want to track. + +--- + +## Methods to Find IDLs + +Follow these steps in order to find the IDL for any Solana program. + +### 1. Program GitHub Repository + +Most Solana projects are open source. Search GitHub for the protocol name followed by "idl.json" or look in the project's repository. Common locations include: + +- `target/idl/program_name.json` +- `idl/program_name.json` +- The "Releases" page as an attached asset + +### 2. Anchor CLI Fetch + +If a program is built with Anchor and the developers uploaded the IDL on-chain, you can fetch it directly using the Anchor CLI: + +```bash +anchor idl fetch --provider.cluster mainnet -o idl/program.json +``` + +Replace `` with the program's on-chain address. Not every program has an IDL on-chain, so this may return an error if it's missing. + +### 3. NPM or Rust Packages + +Many protocols publish SDKs for developers. These packages often include the IDL file so the SDK can encode and decode instructions. + +- **NPM:** Check `node_modules/@protocol-name/sdk/dist/idl.json` or similar paths. +- **Crates.io:** Some Rust crates include the IDL as a resource. + +### 4. Block Explorers + +Explorers like Solscan or Solana.fm sometimes host IDLs for verified programs. Look for a "Contract" or "IDL" tab when viewing a program address. You can often download the JSON directly from these pages. + +### 5. Manual Creation + +If an IDL isn't available, you can create one manually by examining the program's source code. Tools like Kinobi or Codama can generate IDLs by parsing the Rust source. + +--- + +## Where to Put IDLs + +In a Hyperstack project, store your IDL files in an `idl/` directory at the root of your stack. This keeps your project organized and makes it easy to reference them in your code. + +```text +my-stack/ +├── idl/ +│ └── program_name.json # IDL goes here +├── src/ +│ └── stack.rs # References the IDL +├── hyperstack.toml +└── Cargo.toml +``` + +Reference the IDL in your `src/stack.rs` using the `#[hyperstack]` macro: + +```rust +#[hyperstack(idl = "idl/program_name.json")] +pub struct MyStack; +``` + +--- + +## Common IDL Locations + +| Protocol | Program ID | Source | +| -------------- | --------------------------------------------- | ---------------------------------------------- | +| ORE | `oreo7nRnU86QCen6Np3iH6q8C6c6K6c6K6c6K6c6K6c` | [GitHub](https://github.com/regolith-labs/ore) | +| System Program | `11111111111111111111111111111111` | Built-in | +| Token Program | `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA` | Built-in | diff --git a/docs/src/content/docs/cli/commands.mdx b/docs/src/content/docs/cli/commands.mdx index 610efbe..67111be 100644 --- a/docs/src/content/docs/cli/commands.mdx +++ b/docs/src/content/docs/cli/commands.mdx @@ -33,6 +33,7 @@ Complete reference for the Hyperstack CLI (`hs`). | `hs stack list` | List all stacks | | `hs stack show` | Show stack details | | `hs telemetry status` | Show telemetry status | +| `hs explore` | Discover stacks and schemas | :::note[npm vs Cargo] When installed via npm (`npm install -g hyperstack-cli`), the command is `hyperstack-cli`. When installed via Cargo (`cargo install hyperstack-cli`), the command is `hs`. Both are the same CLI. @@ -150,6 +151,47 @@ hs auth whoami --- +## Schema Discovery + +### hs explore + +Discover available stacks and explore their schemas. Works without authentication for public stacks. + +```bash +# List all available stacks +hs explore + +# Show entities and views for a stack +hs explore ore + +# Show fields and types for a specific entity +hs explore ore OreRound + +# JSON output (for agents and scripts) +hs explore --json +hs explore ore --json +hs explore ore OreRound --json +``` + +**Arguments:** + +| Argument | Description | +| ---------- | --------------------------------- | +| `[name]` | Stack name to explore | +| `[entity]` | Entity name to show field details | + +**Output varies by specificity:** + +| Command | Shows | +| ----------------------------- | --------------------------------------------- | +| `hs explore` | All available stacks with entity names | +| `hs explore ` | Stack entities, views, and field counts | +| `hs explore ` | Entity fields with types, sections, and views | + +Public stacks are visible without authentication. Log in with `hs auth login` to also see global stacks and your own deployed stacks. + +--- + ## Deployment ### hs up [stack-name] diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx index 251217c..daf296d 100644 --- a/docs/src/content/docs/index.mdx +++ b/docs/src/content/docs/index.mdx @@ -155,6 +155,31 @@ Connect to existing stacks and stream live Solana data into your app. --- +## I'm Using an AI Coding Agent + +Let your AI write the code. Agent skills teach Cursor, Claude Code, Windsurf, and other AI tools how to use Hyperstack. + + + + **One command setup** — Install skills and your agent knows all the SDK patterns and CLI commands. + + Works with Cursor, Claude Code, Windsurf, VS Code Copilot, and 30+ other agents. + + [Install skills →](/agent-skills/overview/) + + + + **Live type info** — Agents use `hs explore` to get exact entity names, field paths, and types from deployed stacks. + + Always accurate, always up to date. + + [Learn more →](/agent-skills/explore/) + + + + +--- + ## I Want to Build Stacks Create custom data pipelines that transform on-chain events into structured, streaming feeds. diff --git a/docs/src/content/docs/using-stacks/quickstart.mdx b/docs/src/content/docs/using-stacks/quickstart.mdx index d2dfa40..3812442 100644 --- a/docs/src/content/docs/using-stacks/quickstart.mdx +++ b/docs/src/content/docs/using-stacks/quickstart.mdx @@ -242,10 +242,25 @@ async fn main() -> anyhow::Result<()> { --- +## Using an AI Coding Agent? + +Install Hyperstack agent skills so your AI can write correct code without you looking up docs: + +```bash +npx skills add usehyperstack/skills +``` + +Now try asking your agent: "Show me the ORE mining round data in a table with live updates." + +See [Build with AI](/agent-skills/overview/) for the full guide and prompt cookbook. + +--- + ## Next Steps Now that you have a working app: +- [Build with AI](/agent-skills/overview/) — Let your AI agent write Hyperstack code with agent skills - [How It Works](/using-stacks/how-it-works/) — Understand Stacks, Views, and live data streaming - [React SDK](/sdks/react/) — Build a complete React app with custom stack definitions - [TypeScript SDK](/sdks/typescript/) — Use Hyperstack with Node.js, Vue, Svelte, or vanilla JS diff --git a/stacks/ore/.hyperstack/OreStream.stack.json b/stacks/ore/.hyperstack/OreStream.stack.json index c27ba3a..b54e064 100644 --- a/stacks/ore/.hyperstack/OreStream.stack.json +++ b/stacks/ore/.hyperstack/OreStream.stack.json @@ -3687,6 +3687,15 @@ } }, "resolver_hooks": [ + { + "account_type": "entropy::VarState", + "strategy": { + "PdaReverseLookup": { + "lookup_name": "default_pda_lookup", + "queue_discriminators": [] + } + } + }, { "account_type": "ore::TreasuryState", "strategy": { @@ -3706,15 +3715,6 @@ ] } } - }, - { - "account_type": "entropy::VarState", - "strategy": { - "PdaReverseLookup": { - "lookup_name": "default_pda_lookup", - "queue_discriminators": [] - } - } } ], "instruction_hooks": [ @@ -3770,14 +3770,14 @@ "pda_field": { "segments": [ "accounts", - "treasury" + "entropyVar" ], "offsets": null }, "seed_field": { "segments": [ "accounts", - "roundNext" + "round" ], "offsets": null }, @@ -3808,14 +3808,14 @@ "pda_field": { "segments": [ "accounts", - "entropyVar" + "treasury" ], "offsets": null }, "seed_field": { "segments": [ "accounts", - "round" + "roundNext" ], "offsets": null }, @@ -4556,7 +4556,7 @@ "result_type": "Option < f64 >" } ], - "content_hash": "18ee1d96ef84e2983f467e80501db45a5dfbe9fa5be2d60065aa4d535bcef88b", + "content_hash": "bb98d040a8cb94fca1a7641d664ed8245ec8c7cf266ace6c894cbfbf97dc0dea", "views": [ { "id": "OreRound/latest", @@ -5044,6 +5044,15 @@ } }, "resolver_hooks": [ + { + "account_type": "entropy::VarState", + "strategy": { + "PdaReverseLookup": { + "lookup_name": "default_pda_lookup", + "queue_discriminators": [] + } + } + }, { "account_type": "ore::TreasuryState", "strategy": { @@ -5063,15 +5072,6 @@ ] } } - }, - { - "account_type": "entropy::VarState", - "strategy": { - "PdaReverseLookup": { - "lookup_name": "default_pda_lookup", - "queue_discriminators": [] - } - } } ], "instruction_hooks": [ @@ -5127,14 +5127,14 @@ "pda_field": { "segments": [ "accounts", - "treasury" + "entropyVar" ], "offsets": null }, "seed_field": { "segments": [ "accounts", - "roundNext" + "round" ], "offsets": null }, @@ -5165,14 +5165,14 @@ "pda_field": { "segments": [ "accounts", - "entropyVar" + "treasury" ], "offsets": null }, "seed_field": { "segments": [ "accounts", - "round" + "roundNext" ], "offsets": null }, @@ -5280,7 +5280,7 @@ "result_type": "Option < f64 >" } ], - "content_hash": "6940e0c98d4f1b4ecc6592fb4b2fe825950f1205860b47de7723e81e7c921204", + "content_hash": "66301f1e812d89849a1f719de939d80b2973335b736c6c08c1d5b7773fa023ef", "views": [] }, { @@ -6604,6 +6604,15 @@ } }, "resolver_hooks": [ + { + "account_type": "entropy::VarState", + "strategy": { + "PdaReverseLookup": { + "lookup_name": "default_pda_lookup", + "queue_discriminators": [] + } + } + }, { "account_type": "ore::TreasuryState", "strategy": { @@ -6623,15 +6632,6 @@ ] } } - }, - { - "account_type": "entropy::VarState", - "strategy": { - "PdaReverseLookup": { - "lookup_name": "default_pda_lookup", - "queue_discriminators": [] - } - } } ], "instruction_hooks": [ @@ -6687,14 +6687,14 @@ "pda_field": { "segments": [ "accounts", - "treasury" + "entropyVar" ], "offsets": null }, "seed_field": { "segments": [ "accounts", - "roundNext" + "round" ], "offsets": null }, @@ -6725,14 +6725,14 @@ "pda_field": { "segments": [ "accounts", - "entropyVar" + "treasury" ], "offsets": null }, "seed_field": { "segments": [ "accounts", - "round" + "roundNext" ], "offsets": null }, @@ -6746,7 +6746,7 @@ "resolver_specs": [], "computed_fields": [], "computed_field_specs": [], - "content_hash": "cc153e8334a5d6bff0710db82de32f84037aaee14db0eeb7f443209e23f02e71", + "content_hash": "236fccaddbe4354f0fd201accb7bc597b90894a1b517d987980178b7be75a6be", "views": [] } ], @@ -8854,5 +8854,5 @@ ] } ], - "content_hash": "db794f9ed2dcceaa009c80fc34b28144867518d692494d5ead8b623c381bcc08" + "content_hash": "d54be9ac027a6a9581305854d45da529430879dd2e0dec2786f6da636a4cadda" } \ No newline at end of file diff --git a/stacks/ore/Cargo.lock b/stacks/ore/Cargo.lock index 6a80fc0..60730a9 100644 --- a/stacks/ore/Cargo.lock +++ b/stacks/ore/Cargo.lock @@ -1138,7 +1138,7 @@ dependencies = [ [[package]] name = "hyperstack" -version = "0.5.1" +version = "0.5.2" dependencies = [ "anyhow", "bs58", @@ -1161,7 +1161,7 @@ dependencies = [ [[package]] name = "hyperstack-interpreter" -version = "0.5.1" +version = "0.5.2" dependencies = [ "bs58", "dashmap", @@ -1182,7 +1182,7 @@ dependencies = [ [[package]] name = "hyperstack-macros" -version = "0.5.1" +version = "0.5.2" dependencies = [ "bs58", "hex", @@ -1196,7 +1196,7 @@ dependencies = [ [[package]] name = "hyperstack-sdk" -version = "0.5.1" +version = "0.5.2" dependencies = [ "anyhow", "flate2", @@ -1213,7 +1213,7 @@ dependencies = [ [[package]] name = "hyperstack-server" -version = "0.5.1" +version = "0.5.2" dependencies = [ "anyhow", "base64 0.22.1", diff --git a/stacks/pumpfun/Cargo.lock b/stacks/pumpfun/Cargo.lock index 53d93d1..3f7755f 100644 --- a/stacks/pumpfun/Cargo.lock +++ b/stacks/pumpfun/Cargo.lock @@ -725,21 +725,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.2" @@ -868,9 +853,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi", "wasip2", + "wasm-bindgen", ] [[package]] @@ -1103,6 +1090,7 @@ dependencies = [ "tokio", "tokio-rustls 0.26.4", "tower-service", + "webpki-roots 1.0.5", ] [[package]] @@ -1118,22 +1106,6 @@ dependencies = [ "tower-service", ] -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper 1.8.1", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - [[package]] name = "hyper-util" version = "0.1.19" @@ -1153,16 +1125,14 @@ dependencies = [ "percent-encoding", "pin-project-lite", "socket2 0.6.1", - "system-configuration", "tokio", "tower-service", "tracing", - "windows-registry", ] [[package]] name = "hyperstack" -version = "0.4.3" +version = "0.5.2" dependencies = [ "anyhow", "bs58", @@ -1185,7 +1155,7 @@ dependencies = [ [[package]] name = "hyperstack-interpreter" -version = "0.4.3" +version = "0.5.2" dependencies = [ "bs58", "dashmap", @@ -1206,7 +1176,7 @@ dependencies = [ [[package]] name = "hyperstack-macros" -version = "0.4.3" +version = "0.5.2" dependencies = [ "bs58", "hex", @@ -1220,7 +1190,7 @@ dependencies = [ [[package]] name = "hyperstack-sdk" -version = "0.4.3" +version = "0.5.2" dependencies = [ "anyhow", "flate2", @@ -1237,7 +1207,7 @@ dependencies = [ [[package]] name = "hyperstack-server" -version = "0.4.3" +version = "0.5.2" dependencies = [ "anyhow", "base64 0.22.1", @@ -1503,6 +1473,12 @@ dependencies = [ "hashbrown 0.15.5", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "matchers" version = "0.2.0" @@ -1563,23 +1539,6 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" -[[package]] -name = "native-tls" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe 0.1.6", - "openssl-sys", - "schannel", - "security-framework 2.11.1", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -1620,56 +1579,12 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" -[[package]] -name = "openssl" -version = "0.10.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" -dependencies = [ - "bitflags 2.10.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.114", -] - -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - [[package]] name = "openssl-probe" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391" -[[package]] -name = "openssl-sys" -version = "0.9.111" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "parking_lot" version = "0.11.2" @@ -1992,6 +1907,61 @@ dependencies = [ "solana-pubkey", ] +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls 0.23.36", + "socket2 0.5.10", + "thiserror 2.0.18", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +dependencies = [ + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.2", + "ring", + "rustc-hash", + "rustls 0.23.36", + "rustls-pki-types", + "slab", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2 0.5.10", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.43" @@ -2162,29 +2132,26 @@ checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64 0.22.1", "bytes", - "encoding_rs", "futures-core", - "h2 0.4.13", "http 1.4.0", "http-body 1.0.1", "http-body-util", "hyper 1.8.1", "hyper-rustls 0.27.7", - "hyper-tls", "hyper-util", "js-sys", "log", - "mime", - "native-tls", "percent-encoding", "pin-project-lite", + "quinn", + "rustls 0.23.36", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 1.0.2", "tokio", - "tokio-native-tls", + "tokio-rustls 0.26.4", "tower 0.5.3", "tower-http", "tower-service", @@ -2192,6 +2159,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots 1.0.5", ] [[package]] @@ -2208,6 +2176,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + [[package]] name = "rustix" version = "1.1.3" @@ -2255,6 +2229,7 @@ checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" dependencies = [ "log", "once_cell", + "ring", "rustls-pki-types", "rustls-webpki 0.103.9", "subtle", @@ -2267,10 +2242,10 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ - "openssl-probe 0.2.0", + "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.5.1", + "security-framework", ] [[package]] @@ -2288,6 +2263,7 @@ version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" dependencies = [ + "web-time", "zeroize", ] @@ -2360,19 +2336,6 @@ dependencies = [ "untrusted", ] -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.10.0", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - [[package]] name = "security-framework" version = "3.5.1" @@ -2825,16 +2788,6 @@ dependencies = [ "syn 2.0.114", ] -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.24.1" @@ -3378,12 +3331,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "version_check" version = "0.9.5" @@ -3483,6 +3430,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "webpki-roots" version = "0.25.4" @@ -3535,35 +3492,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-registry" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" -dependencies = [ - "windows-link", - "windows-result", - "windows-strings", -] - -[[package]] -name = "windows-result" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" -dependencies = [ - "windows-link", -] - [[package]] name = "windows-sys" version = "0.48.0"