关于 switchboard
switchboard 是面向 Switchboard Solana 预言机协议的集成技能,供开发者参考。内容涵盖通过 SDK 接入价格源、预言机报价、实时数据流和可验证随机数。
主要功能
- 01Solana 预言机集成指南
- 02拉取式价格源更新
- 03预言机报价集成
- 04Surge WebSocket 实时数据流
- 05VRF 随机数集成
适用场景
- 01为 Solana 程序添加价格数据
- 02使用低延迟价格流
- 03无需存储 Feed 即可读取预言机数据
- 04请求可验证的链上随机数
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ sendaifun/ skills --skill switchboard安装后在 Claude Code 中输入/switchboard确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
docs/troubleshooting.mdexamples/feeds/oracle-quote.tspull-feed.tsread-feed.tsexamples/randomness/vrf-example.tsexamples/setup/example.tsexamples/surge/streaming.tsresources/github-repos.mdprogram-ids.mdrust-reference.mdsdk-reference.mdtemplates/setup.ts详细介绍
Switchboard 预言机协议——完整集成指南
这是集成 Switchboard 的权威指南。Switchboard 是 Solana 上速度最快、最灵活、唯一无需许可的预言机协议。
什么是 Switchboard?
Switchboard 是一种无需许可的预言机协议,可让开发者以业界领先的性能将自定义数据引入链上:
- 价格馈送 - 采用拉取式机制,高效提供实时资产定价
- 预言机报价 - 亚秒级延迟,无需链上存储(成本降低 90%)
- Surge - 通过 WebSocket 进行流式传输,延迟低于 100 ms
- VRF 随机性 - 采用密码学安全的可验证随机函数
- 预测市场 - 基于市场的预测数据
关键数据
- 保障链上交易量 10 亿美元以上
- Kamino、Jito、MarginFi、Drift Protocol 均在使用
- Surge 定价模式下延迟为 2–5 ms
- 与传统预言机相比,成本降低 90%
核心原则
| 原则 | 说明 |
|---|---|
| 速度 | Surge 延迟为 2–5 ms,标准模式为 400 ms,在 DeFi 领域处于业界领先水平 |
| 成本效益 | 拉取式数据馈送无需承担持续流式传输成本 |
| 无需许可 | 无需审批即可立即部署数据馈送 |
| 安全性 | TEE(可信执行环境)可防止数据被篡改 |
集成方式
1. 预言机报价(推荐)
无需链上存储,直接将数据从预言机传输到程序:
- 亚秒级延迟
- 成本降低 90%
- 无写入锁(支持并行读取)
- 无状态设计
2. 传统数据馈送
经典的拉取式数据馈送更新:
- 维护数据馈送账户
- 执行 Cranking 操作
- 适用于简单场景
3. Surge(实时)
通过 WebSocket 流式传输,适用于高频应用:
- 延迟低于 100 ms
- 持久连接
- 非常适合交易界面
程序 ID
| 程序 | Mainnet | Devnet |
|---|---|---|
| Oracle Program | SW1TCH7qEPTdLsDHRgPuMQjbQxKdH2aBStViMFnt64f | Aio4gaXjXzJNVLtzwtNVmSqGKpANtXhybbkhtAC94ji2 |
| Quote Program | orac1eFjzWL5R3RbbdMV68K9H6TaCVVcL6LjvQQWAbz | - |
默认队列
| 网络 | 队列地址 |
|---|---|
| Mainnet | A43DyUGA7s8eXPxqEjJY6EBu1KKbNgfxF8h17VAHn13w |
| Devnet | EYiAmGSdsQTuCw413V5BzaruWuCCSDgTPtBGvLkXHbe7 |
快速开始
安装
# TypeScript SDK
npm install @switchboard-xyz/on-demand @switchboard-xyz/common
# Rust (Cargo.toml)
# switchboard-on-demand = "0.8.0"
基本设置
import { web3, AnchorProvider, Program } from "@coral-xyz/anchor";
import {
PullFeed,
CrossbarClient,
ON_DEMAND_MAINNET_PID,
ON_DEMAND_DEVNET_PID
} from "@switchboard-xyz/on-demand";
// Setup connection and provider
const connection = new web3.Connection("https://api.mainnet-beta.solana.com");
const wallet = useWallet(); // or Keypair
const provider = new AnchorProvider(connection, wallet);
// Load Switchboard program
const sbProgram = await Program.at(ON_DEMAND_MAINNET_PID, provider);
// Initialize Crossbar client for oracle communication
const crossbar = new CrossbarClient("https://crossbar.switchboard.xyz");
价格馈送
获取并更新数据馈送
import { PullFeed, asV0Tx } from "@switchboard-xyz/on-demand";
// Create feed account reference
const feedPubkey = new web3.PublicKey("YOUR_FEED_PUBKEY");
const feedAccount = new PullFeed(sbProgram, feedPubkey);
// Fetch update instruction with oracle signatures
const { pullIx, responses, numSuccess, luts } = await feedAccount.fetchUpdateIx({
crossbarClient: crossbar,
chain: "solana",
network: "mainnet", // or "devnet"
});
// Build and send transaction
const tx = await asV0Tx({
connection,
ixs: [pullIx],
signers: [payer],
computeUnitPrice: 200_000,
computeUnitLimitMultiple: 1.3,
lookupTables: luts,
});
const signature = await connection.sendTransaction(tx);
console.log("Feed updated:", signature);
读取数据馈送值
// Get current feed value
const feedData = await feedAccount.loadData();
const value = feedData.value.toNumber();
const lastUpdated = feedData.lastUpdatedSlot;
console.log(`Price: ${value}, Last Updated: ${lastUpdated}`);
预言机报价(推荐)
预言机报价提供了最高效的预言机数据使用方式:
import { OracleQuote } from "@switchboard-xyz/on-demand";
// Feed hashes (64-char hex strings)
const feedHashes = [
"0x...", // SOL/USD
"0x...", // BTC/USD
];
// Derive canonical quote account
const queueKey = new web3.PublicKey("A43DyUGA7s8eXPxqEjJY6EBu1KKbNgfxF8h17VAHn13w");
const quotePubkey = OracleQuote.getCanonicalPubkey(queueKey, feedHashes);
// Fetch quote instruction
const sigVerifyIx = await queue.fetchQuoteIx(crossbar, feedHashes, {
numSignatures: 1,
variableOverrides: {},
});
Rust 集成(预言机报价)
use anchor_lang::prelude::*;
use switchboard_on_demand::{default_queue, SwitchboardQuoteExt, SwitchboardQuote};
#[program]
pub mod my_program {
use super::*;
pub fn read_oracle_data(ctx: Context<ReadOracleData>) -> Result<()> {
let feeds = &ctx.accounts.quote_account.feeds;
let current_slot = ctx.accounts.sysvars.clock.slot;
let quote_slot = ctx.accounts.quote_account.slot;
// Check staleness
let staleness = current_slot.saturating_sub(quote_slot);
require!(staleness < 100, ErrorCode::StaleFeed);
for feed in feeds.iter() {
msg!("Feed {}: Value = {}", feed.hex_id(), feed.value());
}
Ok(())
}
}
#[derive(Accounts)]
pub struct ReadOracleData<'info> {
#[account(address = quote_account.canonical_key(&default_queue()))]
pub quote_account: Box<Account<'info, SwitchboardQuote>>,
pub sysvars: Sysvars<'info>,
}
#[derive(Accounts)]
pub struct Sysvars<'info> {
pub clock: Sysvar<'info, Clock>,
}
Surge(实时流式传输)
适用于需要实时价格更新的应用:
import { SwitchboardSurge } from "@switchboard-xyz/on-demand";
// Initialize Surge client
const surge = new SwitchboardSurge({
apiKey: "YOUR_API_KEY", // Optional
gatewayUrl: "wss://surge.switchboard.xyz",
autoReconnect: true,
maxReconnectAttempts: 5,
reconnectDelay: 1000,
});
// Subscribe to feeds
surge.subscribe(["SOL/USD", "BTC/USD"]);
// Handle events
surge.on("connected", () => {
console.log("Connected to Surge");
});
surge.on("data", (data) => {
console.log(`${data.symbol}: ${data.price}`);
});
surge.on("error", (error) => {
console.error("Surge error:", error);
});
surge.on("disconnected", () => {
console.log("Disconnected from Surge");
});
VRF 随机性
采用密码学安全的链上随机性:
TypeScript 客户端
import { RandomnessService } from "@switchboard-xyz/on-demand";
// Request randomness
const randomnessAccount = await RandomnessService.create(sbProgram, {
queue: queuePubkey,
callback: {
programId: myProgramId,
accounts: [...],
ixData: Buffer.from([...]),
},
});
// Reveal randomness (after oracle fulfillment)
const randomValue = await randomnessAccount.reveal();
console.log("Random value:", randomValue);
Rust 集成
use switchboard_on_demand::RandomnessAccountData;
pub fn consume_randomness(ctx: Context<ConsumeRandomness>) -> Result<()> {
let randomness_data = RandomnessAccountData::parse(
ctx.accounts.randomness_account.to_account_info()
)?;
// Use the random value
let random_value = randomness_data.get_value(&ctx.accounts.clock)?;
// Example: coin flip
let is_heads = random_value[0] % 2 == 0;
Ok(())
}
创建自定义数据馈送
使用数据馈送构建器界面
- 访问 ondemand.switchboard.xyz
- 点击“Create Feed”
- 配置数据源和聚合方式
- 部署到 mainnet/devnet
- 复制数据馈送哈希以进行集成
使用 TypeScript SDK
import { FeedBuilder } from "@switchboard-xyz/on-demand";
const feedConfig = new FeedBuilder()
.addJob({
tasks: [
{
httpTask: {
url: "https://api.example.com/price",
},
},
{
jsonParseTask: {
path: "$.price",
},
},
],
})
.setMinResponses(3)
.setMaxVariance(0.1);
const feedHash = await feedConfig.build();
框架对比
| 方面 | Anchor(基础) | Pinocchio(高级) |
|---|---|---|
| 学习曲线 | 适合初学者 | 仅适合高级用户 |
| 计算单元 | ~2,000 CU | ~190 CU |
| 安全模型 | 完整验证 | 信任 Cranker |
| 使用场景 | 标准 DeFi | 预言机 AMM、HFT |
最佳实践
1. 检查数据是否过时
始终验证数据馈送的新鲜度:
let staleness = current_slot.saturating_sub(feed_slot);
require!(staleness < MAX_STALENESS_SLOTS, ErrorCode::StaleFeed);
2. 多重签名
对于关键操作,请求多个预言机签名:
const { pullIx } = await feedAccount.fetchUpdateIx({
numSignatures: 3, // Increase for higher security
});
3. 错误处理
try {
const { pullIx, numSuccess } = await feedAccount.fetchUpdateIx({...});
if (numSuccess < minRequired) {
throw new Error(`Insufficient oracle responses: ${numSuccess}`);
}
} catch (error) {
if (error.message.includes("timeout")) {
// Retry with different oracles
}
throw error;
}
4. 计算预算
对于复杂操作,请提高计算预算:
import { ComputeBudgetProgram } from "@solana/web3.js";
const modifyComputeUnits = ComputeBudgetProgram.setComputeUnitLimit({
units: 400_000,
});
const tx = new Transaction()
.add(modifyComputeUnits)
.add(pullIx)
.add(yourInstruction);
资源
官方链接
- 文档:https://docs.switchboard.xyz -- 数据馈送构建器:https://ondemand.switchboard.xyz
GitHub 仓库
| 仓库 | 描述 |
|---|---|
| switchboard-sdk | Switchboard SDK 的公开镜像 |
| sb-on-demand-examples | 集成示例 |
| solana-sdk | Rust SDK |
| on-demand | TypeScript SDK |
社区
- Discord:https://discord.gg/TJAv6ZYvPC
- Twitter:@switchboardxyz
技能结构
switchboard/
├── SKILL.md # This file
├── resources/
│ ├── program-ids.md # All program addresses and queues
│ ├── sdk-reference.md # TypeScript SDK API reference
│ ├── rust-reference.md # Rust SDK reference
│ └── github-repos.md # Repository links
├── examples/
│ ├── setup/
│ │ └── example.ts # Basic setup
│ ├── feeds/
│ │ ├── pull-feed.ts # Pull feed updates
│ │ ├── oracle-quote.ts # Oracle quote integration
│ │ └── read-feed.ts # Read feed values
│ ├── randomness/
│ │ └── vrf-example.ts # VRF randomness
│ └── surge/
│ └── streaming.ts # Real-time streaming
├── templates/
│ └── setup.ts # Complete starter template
└── docs/
└── troubleshooting.md # Common issues
评论
支持 Markdown