pyth
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePyth Network Development Guide
Pyth Network 开发指南
Pyth Network is a decentralized oracle providing real-time price feeds for cryptocurrencies, equities, forex, and commodities. This guide covers integrating Pyth price feeds into Solana applications.
Pyth Network是一个去中心化预言机,可为加密货币、股票、外汇和大宗商品提供实时价格喂价。本指南介绍如何将Pyth价格喂价集成到Solana应用中。
Overview
概述
Pyth Network provides:
- Real-Time Price Feeds - 400ms update frequency with pull oracle model
- Confidence Intervals - Statistical uncertainty bounds for each price
- EMA Prices - Exponential moving average prices (~1 hour window)
- Multi-Asset Support - Crypto, equities, FX, commodities, indices
- On-Chain Integration - CPI for Solana programs
- Off-Chain Integration - HTTP and WebSocket APIs via Hermes
Pyth Network提供以下功能:
- 实时价格喂价 - 采用拉取式预言机模型,更新频率为400ms
- 置信区间 - 每个价格对应的统计不确定性范围
- EMA价格 - 指数移动平均价格(约1小时窗口)
- 多资产支持 - 加密货币、股票、外汇、大宗商品、指数
- 链上集成 - 适用于Solana程序的CPI
- 链下集成 - 通过Hermes提供HTTP和WebSocket API
Program IDs
程序ID
| Program | Address | Description |
|---|---|---|
| Solana Receiver | | Posts price updates to Solana |
| Price Feed | | Stores price feed data |
Deployed on: Solana Mainnet, Devnet, Eclipse Mainnet/Testnet, Sonic networks
| 程序 | 地址 | 描述 |
|---|---|---|
| Solana Receiver | | 向Solana发布价格更新 |
| Price Feed | | 存储价格喂价数据 |
部署网络:Solana主网、Devnet、Eclipse主网/测试网、Sonic网络
Popular Price Feed IDs
常用价格喂价ID
| Asset | Hex Feed ID |
|---|---|
| BTC/USD | |
| ETH/USD | |
| SOL/USD | |
| USDC/USD | |
| USDT/USD | |
| 资产 | 十六进制喂价ID |
|---|---|
| BTC/USD | |
| ETH/USD | |
| SOL/USD | |
| USDC/USD | |
| USDT/USD | |
Quick Start
快速开始
Installation
安装
bash
undefinedbash
undefinedTypeScript/JavaScript
TypeScript/JavaScript
npm install @pythnetwork/hermes-client @pythnetwork/pyth-solana-receiver
npm install @pythnetwork/hermes-client @pythnetwork/pyth-solana-receiver
Rust (add to Cargo.toml)
Rust (添加到 Cargo.toml)
pyth-solana-receiver-sdk = "0.3.0"
pyth-solana-receiver-sdk = "0.3.0"
undefinedundefinedFetch Price (Off-Chain)
链下获取价格
typescript
import { HermesClient } from "@pythnetwork/hermes-client";
const client = new HermesClient("https://hermes.pyth.network");
const priceIds = [
"0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43", // BTC/USD
];
const priceUpdates = await client.getLatestPriceUpdates(priceIds);
for (const update of priceUpdates.parsed) {
const price = update.price;
const displayPrice = Number(price.price) * Math.pow(10, price.expo);
console.log(`Price: $${displayPrice.toFixed(2)}`);
console.log(`Confidence: ±${Number(price.conf) * Math.pow(10, price.expo)}`);
}typescript
import { HermesClient } from "@pythnetwork/hermes-client";
const client = new HermesClient("https://hermes.pyth.network");
const priceIds = [
"0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43", // BTC/USD
];
const priceUpdates = await client.getLatestPriceUpdates(priceIds);
for (const update of priceUpdates.parsed) {
const price = update.price;
const displayPrice = Number(price.price) * Math.pow(10, price.expo);
console.log(`Price: $${displayPrice.toFixed(2)}`);
console.log(`Confidence: ±${Number(price.conf) * Math.pow(10, price.expo)}`);
}Use Price On-Chain (Rust/Anchor)
链上使用价格(Rust/Anchor)
rust
use anchor_lang::prelude::*;
use pyth_solana_receiver_sdk::price_update::PriceUpdateV2;
#[derive(Accounts)]
pub struct UsePrice<'info> {
pub price_update: Account<'info, PriceUpdateV2>,
}
pub fn use_price(ctx: Context<UsePrice>) -> Result<()> {
let price_update = &ctx.accounts.price_update;
let clock = Clock::get()?;
// Get price no older than 60 seconds
let price = price_update.get_price_no_older_than(
&clock,
60, // max age in seconds
)?;
msg!("Price: {} × 10^{}", price.price, price.exponent);
msg!("Confidence: ±{}", price.conf);
Ok(())
}rust
use anchor_lang::prelude::*;
use pyth_solana_receiver_sdk::price_update::PriceUpdateV2;
#[derive(Accounts)]
pub struct UsePrice<'info> {
pub price_update: Account<'info, PriceUpdateV2>,
}
pub fn use_price(ctx: Context<UsePrice>) -> Result<()> {
let price_update = &ctx.accounts.price_update;
let clock = Clock::get()?;
// 获取不早于60秒的价格
let price = price_update.get_price_no_older_than(
&clock,
60, // 最大时长(秒)
)?;
msg!("Price: {} × 10^{}", price.price, price.exponent);
msg!("Confidence: ±{}", price.conf);
Ok(())
}Core Concepts
核心概念
Price Structure
价格结构
Each Pyth price contains:
| Field | Type | Description |
|---|---|---|
| i64 | Price value in fixed-point format |
| u64 | Confidence interval (standard deviation) |
| i32 | Exponent for scaling (e.g., -8 means divide by 10^8) |
| i64 | Unix timestamp of price |
Converting to display price:
typescript
const displayPrice = price * Math.pow(10, expo);
// Example: price=19405100, expo=-2 → $194,051.00每个Pyth价格包含以下字段:
| 字段 | 类型 | 描述 |
|---|---|---|
| i64 | 定点格式的价格值 |
| u64 | 置信区间(标准差) |
| i32 | 缩放指数(例如,-8表示除以10^8) |
| i64 | 价格的Unix时间戳 |
转换为显示价格:
typescript
const displayPrice = price * Math.pow(10, expo);
// 示例: price=19405100, expo=-2 → $194,051.00Confidence Intervals
置信区间
Confidence intervals represent the uncertainty in the reported price:
typescript
// Price is $50,000 ± $50 means:
// - 68% chance true price is between $49,950 - $50,050
// - Use confidence for risk management
const price = 50000;
const confidence = 50;
// Safe lower bound (conservative)
const safeLowerBound = price - confidence;
// Safe upper bound (conservative)
const safeUpperBound = price + confidence;Best Practice: Reject prices with confidence > 2% of price:
typescript
const maxConfidenceRatio = 0.02; // 2%
const confidenceRatio = confidence / Math.abs(price);
if (confidenceRatio > maxConfidenceRatio) {
throw new Error("Price confidence too wide");
}置信区间代表报告价格的不确定性:
typescript
// 价格为$50,000 ± $50意味着:
// - 真实价格有68%的概率在$49,950 - $50,050之间
// - 可将置信区间用于风险管理
const price = 50000;
const confidence = 50;
// 安全下限(保守值)
const safeLowerBound = price - confidence;
// 安全上限(保守值)
const safeUpperBound = price + confidence;最佳实践:拒绝置信区间超过价格2%的价格数据:
typescript
const maxConfidenceRatio = 0.02; // 2%
const confidenceRatio = confidence / Math.abs(price);
if (confidenceRatio > maxConfidenceRatio) {
throw new Error("Price confidence too wide");
}EMA Prices
EMA价格
Exponential Moving Average prices smooth out short-term volatility:
- ~1 hour averaging window (5921 Solana slots)
- Weighted by inverse confidence (tight confidence = more weight)
- Good for: liquidations, collateral valuation
- Available as and
ema_priceema_conf
typescript
// Use EMA for less volatile applications
const emaPrice = priceUpdate.emaPrice;
const emaConf = priceUpdate.emaConf;指数移动平均价格可平滑短期波动:
- 约1小时平均窗口(5921个Solana插槽)
- 按置信区间的倒数加权(置信区间越窄,权重越高)
- 适用于:清算、抵押品估值
- 可通过和
ema_price获取ema_conf
typescript
// 对波动敏感度较低的应用可使用EMA
const emaPrice = priceUpdate.emaPrice;
const emaConf = priceUpdate.emaConf;Off-Chain Integration
链下集成
Hermes Client
Hermes客户端
Hermes is the recommended way to fetch Pyth prices off-chain.
Public Endpoint:
https://hermes.pyth.networkFor production, get a dedicated endpoint from a Pyth data provider.
Hermes是链下获取Pyth价格的推荐方式。
公共端点:
https://hermes.pyth.network生产环境中,请从Pyth数据提供商获取专用端点。
Fetching Latest Prices
获取最新价格
typescript
import { HermesClient } from "@pythnetwork/hermes-client";
const client = new HermesClient("https://hermes.pyth.network");
// Single price
const btcPrice = await client.getLatestPriceUpdates([
"0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43"
]);
// Multiple prices in one request
const prices = await client.getLatestPriceUpdates([
"0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43", // BTC
"0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace", // ETH
"0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d", // SOL
]);typescript
import { HermesClient } from "@pythnetwork/hermes-client";
const client = new HermesClient("https://hermes.pyth.network");
// 单个价格
const btcPrice = await client.getLatestPriceUpdates([
"0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43"
]);
// 一次请求获取多个价格
const prices = await client.getLatestPriceUpdates([
"0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43", // BTC
"0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace", // ETH
"0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d", // SOL
]);Streaming Real-Time Updates
流式实时更新
typescript
import { HermesClient } from "@pythnetwork/hermes-client";
const client = new HermesClient("https://hermes.pyth.network");
const priceIds = [
"0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43"
];
// Subscribe to real-time updates via SSE
const eventSource = await client.getPriceUpdatesStream(priceIds, {
parsed: true,
});
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log("Price update:", data);
};
eventSource.onerror = (error) => {
console.error("Stream error:", error);
eventSource.close();
};
// Close when done
// eventSource.close();typescript
import { HermesClient } from "@pythnetwork/hermes-client";
const client = new HermesClient("https://hermes.pyth.network");
const priceIds = [
"0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43"
];
// 通过SSE订阅实时更新
const eventSource = await client.getPriceUpdatesStream(priceIds, {
parsed: true,
});
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log("Price update:", data);
};
eventSource.onerror = (error) => {
console.error("Stream error:", error);
eventSource.close();
};
// 使用完毕后关闭
// eventSource.close();Posting Prices to Solana
向Solana发布价格
typescript
import { PythSolanaReceiver } from "@pythnetwork/pyth-solana-receiver";
import { HermesClient } from "@pythnetwork/hermes-client";
import { Connection, Keypair } from "@solana/web3.js";
const connection = new Connection("https://api.mainnet-beta.solana.com");
const wallet = Keypair.fromSecretKey(/* your key */);
const hermesClient = new HermesClient("https://hermes.pyth.network");
const pythReceiver = new PythSolanaReceiver({ connection, wallet });
// Fetch price update data
const priceUpdateData = await hermesClient.getLatestPriceUpdates([
"0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43"
]);
// Build transaction to post price
const transactionBuilder = pythReceiver.newTransactionBuilder();
await transactionBuilder.addPostPriceUpdates(priceUpdateData.binary.data);
// Add your program instruction that uses the price
// transactionBuilder.addInstruction(yourInstruction);
// Send transaction
const transactions = await transactionBuilder.buildVersionedTransactions({
computeUnitPriceMicroLamports: 50000,
});
for (const tx of transactions) {
const sig = await connection.sendTransaction(tx);
console.log("Transaction:", sig);
}typescript
import { PythSolanaReceiver } from "@pythnetwork/pyth-solana-receiver";
import { HermesClient } from "@pythnetwork/hermes-client";
import { Connection, Keypair } from "@solana/web3.js";
const connection = new Connection("https://api.mainnet-beta.solana.com");
const wallet = Keypair.fromSecretKey(/* 你的密钥 */);
const hermesClient = new HermesClient("https://hermes.pyth.network");
const pythReceiver = new PythSolanaReceiver({ connection, wallet });
// 获取价格更新数据
const priceUpdateData = await hermesClient.getLatestPriceUpdates([
"0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43"
]);
// 构建发布价格的交易
const transactionBuilder = pythReceiver.newTransactionBuilder();
await transactionBuilder.addPostPriceUpdates(priceUpdateData.binary.data);
// 添加使用该价格的程序指令
// transactionBuilder.addInstruction(yourInstruction);
// 发送交易
const transactions = await transactionBuilder.buildVersionedTransactions({
computeUnitPriceMicroLamports: 50000,
});
for (const tx of transactions) {
const sig = await connection.sendTransaction(tx);
console.log("Transaction:", sig);
}On-Chain Integration (Rust)
链上集成(Rust)
Setup
配置
Add to :
Cargo.tomltoml
[dependencies]
pyth-solana-receiver-sdk = "0.3.0"
anchor-lang = "0.30.1"在中添加依赖:
Cargo.tomltoml
[dependencies]
pyth-solana-receiver-sdk = "0.3.0"
anchor-lang = "0.30.1"Reading Price in Anchor Program
在Anchor程序中读取价格
rust
use anchor_lang::prelude::*;
use pyth_solana_receiver_sdk::price_update::{PriceUpdateV2, get_feed_id_from_hex};
declare_id!("YourProgramId...");
// BTC/USD price feed ID
const BTC_USD_FEED_ID: &str = "0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43";
#[program]
pub mod my_program {
use super::*;
pub fn check_price(ctx: Context<CheckPrice>) -> Result<()> {
let price_update = &ctx.accounts.price_update;
let clock = Clock::get()?;
// Verify this is the correct feed
let feed_id = get_feed_id_from_hex(BTC_USD_FEED_ID)?;
// Get price no older than 60 seconds
let price = price_update.get_price_no_older_than_with_custom_verification(
&clock,
60,
&feed_id,
ctx.accounts.price_update.to_account_info().owner,
)?;
msg!("BTC/USD Price: {} × 10^{}", price.price, price.exponent);
msg!("Confidence: ±{}", price.conf);
Ok(())
}
}
#[derive(Accounts)]
pub struct CheckPrice<'info> {
#[account(
constraint = price_update.to_account_info().owner == &pyth_solana_receiver_sdk::ID
)]
pub price_update: Account<'info, PriceUpdateV2>,
}rust
use anchor_lang::prelude::*;
use pyth_solana_receiver_sdk::price_update::{PriceUpdateV2, get_feed_id_from_hex};
declare_id!("YourProgramId...");
// BTC/USD价格喂价ID
const BTC_USD_FEED_ID: &str = "0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43";
#[program]
pub mod my_program {
use super::*;
pub fn check_price(ctx: Context<CheckPrice>) -> Result<()> {
let price_update = &ctx.accounts.price_update;
let clock = Clock::get()?;
// 验证为正确的喂价
let feed_id = get_feed_id_from_hex(BTC_USD_FEED_ID)?;
// 获取不早于60秒的价格
let price = price_update.get_price_no_older_than_with_custom_verification(
&clock,
60,
&feed_id,
ctx.accounts.price_update.to_account_info().owner,
)?;
msg!("BTC/USD Price: {} × 10^{}", price.price, price.exponent);
msg!("Confidence: ±{}", price.conf);
Ok(())
}
}
#[derive(Accounts)]
pub struct CheckPrice<'info> {
#[account(
constraint = price_update.to_account_info().owner == &pyth_solana_receiver_sdk::ID
)]
pub price_update: Account<'info, PriceUpdateV2>,
}Using Price for Calculations
使用价格进行计算
rust
pub fn swap_with_oracle(
ctx: Context<SwapWithOracle>,
amount_in: u64,
) -> Result<()> {
let price_update = &ctx.accounts.price_update;
let clock = Clock::get()?;
// Get price with staleness check
let price = price_update.get_price_no_older_than(&clock, 30)?;
// Validate confidence (max 1% of price)
let conf_ratio = (price.conf as u128 * 10000) / (price.price.unsigned_abs() as u128);
require!(conf_ratio <= 100, ErrorCode::ConfidenceTooWide);
// Convert price to usable format
// price.price is in fixed-point with price.exponent
let price_scaled = if price.exponent >= 0 {
(price.price as u128) * 10_u128.pow(price.exponent as u32)
} else {
(price.price as u128) / 10_u128.pow((-price.exponent) as u32)
};
// Calculate output amount using oracle price
let amount_out = (amount_in as u128)
.checked_mul(price_scaled)
.ok_or(ErrorCode::MathOverflow)?
/ 1_000_000; // Adjust for decimals
msg!("Swap {} -> {} using price {}", amount_in, amount_out, price_scaled);
Ok(())
}
#[error_code]
pub enum ErrorCode {
#[msg("Price confidence interval too wide")]
ConfidenceTooWide,
#[msg("Math overflow")]
MathOverflow,
}rust
pub fn swap_with_oracle(
ctx: Context<SwapWithOracle>,
amount_in: u64,
) -> Result<()> {
let price_update = &ctx.accounts.price_update;
let clock = Clock::get()?;
// 获取价格并检查时效性
let price = price_update.get_price_no_older_than(&clock, 30)?;
// 验证置信区间(最大为价格的1%)
let conf_ratio = (price.conf as u128 * 10000) / (price.price.unsigned_abs() as u128);
require!(conf_ratio <= 100, ErrorCode::ConfidenceTooWide);
// 将价格转换为可用格式
// price.price为定点格式,带有price.exponent指数
let price_scaled = if price.exponent >= 0 {
(price.price as u128) * 10_u128.pow(price.exponent as u32)
} else {
(price.price as u128) / 10_u128.pow((-price.exponent) as u32)
};
// 使用预言机价格计算输出数量
let amount_out = (amount_in as u128)
.checked_mul(price_scaled)
.ok_or(ErrorCode::MathOverflow)?
/ 1_000_000; // 调整小数位数
msg!("Swap {} -> {} using price {}", amount_in, amount_out, price_scaled);
Ok(())
}
#[error_code]
pub enum ErrorCode {
#[msg("Price confidence interval too wide")]
ConfidenceTooWide,
#[msg("Math overflow")]
MathOverflow,
}Multiple Price Feeds
多价格喂价
rust
#[derive(Accounts)]
pub struct Liquidation<'info> {
#[account(
constraint = collateral_price.to_account_info().owner == &pyth_solana_receiver_sdk::ID
)]
pub collateral_price: Account<'info, PriceUpdateV2>,
#[account(
constraint = debt_price.to_account_info().owner == &pyth_solana_receiver_sdk::ID
)]
pub debt_price: Account<'info, PriceUpdateV2>,
}
pub fn check_liquidation(ctx: Context<Liquidation>) -> Result<bool> {
let clock = Clock::get()?;
let collateral = ctx.accounts.collateral_price
.get_price_no_older_than(&clock, 60)?;
let debt = ctx.accounts.debt_price
.get_price_no_older_than(&clock, 60)?;
// Normalize to same exponent for comparison
let collateral_value = normalize_price(collateral.price, collateral.exponent);
let debt_value = normalize_price(debt.price, debt.exponent);
// Check if undercollateralized
let is_liquidatable = collateral_value < debt_value * 150 / 100; // 150% ratio
Ok(is_liquidatable)
}
fn normalize_price(price: i64, expo: i32) -> i128 {
let target_expo = -8; // Normalize to 8 decimals
let adjustment = expo - target_expo;
if adjustment >= 0 {
(price as i128) * 10_i128.pow(adjustment as u32)
} else {
(price as i128) / 10_i128.pow((-adjustment) as u32)
}
}rust
#[derive(Accounts)]
pub struct Liquidation<'info> {
#[account(
constraint = collateral_price.to_account_info().owner == &pyth_solana_receiver_sdk::ID
)]
pub collateral_price: Account<'info, PriceUpdateV2>,
#[account(
constraint = debt_price.to_account_info().owner == &pyth_solana_receiver_sdk::ID
)]
pub debt_price: Account<'info, PriceUpdateV2>,
}
pub fn check_liquidation(ctx: Context<Liquidation>) -> Result<bool> {
let clock = Clock::get()?;
let collateral = ctx.accounts.collateral_price
.get_price_no_older_than(&clock, 60)?;
let debt = ctx.accounts.debt_price
.get_price_no_older_than(&clock, 60)?;
// 归一化到相同指数以便比较
let collateral_value = normalize_price(collateral.price, collateral.exponent);
let debt_value = normalize_price(debt.price, debt.exponent);
// 检查是否抵押不足
let is_liquidatable = collateral_value < debt_value * 150 / 100; // 150%抵押率
Ok(is_liquidatable)
}
fn normalize_price(price: i64, expo: i32) -> i128 {
let target_expo = -8; // 归一化为8位小数
let adjustment = expo - target_expo;
if adjustment >= 0 {
(price as i128) * 10_i128.pow(adjustment as u32)
} else {
(price as i128) / 10_i128.pow((-adjustment) as u32)
}
}Best Practices
最佳实践
1. Always Check Staleness
1. 始终检查时效性
rust
// Don't use old prices - set appropriate max age
let max_age_seconds = 60;
let price = price_update.get_price_no_older_than(&clock, max_age_seconds)?;rust
// 不要使用旧价格 - 设置合适的最大时长
let max_age_seconds = 60;
let price = price_update.get_price_no_older_than(&clock, max_age_seconds)?;2. Validate Confidence Intervals
2. 验证置信区间
rust
// Reject prices with wide confidence (high uncertainty)
const MAX_CONF_BPS: u64 = 200; // 2%
let conf_bps = (price.conf as u128 * 10000) / (price.price.unsigned_abs() as u128);
require!(conf_bps <= MAX_CONF_BPS as u128, ErrorCode::ConfidenceTooWide);rust
// 拒绝置信区间过宽的价格(不确定性高)
const MAX_CONF_BPS: u64 = 200; // 2%
let conf_bps = (price.conf as u128 * 10000) / (price.price.unsigned_abs() as u128);
require!(conf_bps <= MAX_CONF_BPS as u128, ErrorCode::ConfidenceTooWide);3. Verify Account Ownership
3. 验证账户所有权
rust
// Always verify the price account is owned by Pyth
#[account(
constraint = price_update.to_account_info().owner == &pyth_solana_receiver_sdk::ID
)]
pub price_update: Account<'info, PriceUpdateV2>,rust
// 始终验证价格账户归Pyth所有
#[account(
constraint = price_update.to_account_info().owner == &pyth_solana_receiver_sdk::ID
)]
pub price_update: Account<'info, PriceUpdateV2>,4. Use EMA for Sensitive Operations
4. 敏感操作使用EMA
rust
// For liquidations, use EMA to avoid manipulation
let ema_price = price_update.get_ema_price_no_older_than(&clock, 60)?;rust
// 清算操作使用EMA以避免被操纵
let ema_price = price_update.get_ema_price_no_older_than(&clock, 60)?;5. Handle Price Unavailability
5. 处理价格不可用的情况
typescript
try {
const price = await client.getLatestPriceUpdates([feedId]);
// Use price
} catch (error) {
// Fallback behavior or reject transaction
console.error("Price unavailable:", error);
}typescript
try {
const price = await client.getLatestPriceUpdates([feedId]);
// 使用价格
} catch (error) {
// 执行回退逻辑或拒绝交易
console.error("Price unavailable:", error);
}6. Consider Frontrunning
6. 考虑抢先交易
- Adversaries may see price updates before your transaction
- Don't design logic that races against price updates
- Use appropriate slippage tolerances
- 攻击者可能在你的交易之前看到价格更新
- 不要设计与价格更新竞速的逻辑
- 使用合适的滑点容忍度
Price Feed Types
价格喂价类型
Fixed Price Feed Accounts
固定价格喂价账户
- Maintained continuously by Pyth
- Fixed address per feed
- Always has most recent price
- Shared by all users (potential congestion)
- 由Pyth持续维护
- 每个喂价对应固定地址
- 始终包含最新价格
- 所有用户共享(可能出现拥堵)
Ephemeral Price Update Accounts
临时价格更新账户
- Created per transaction
- Can specify shard ID for parallelization
- Rent can be recovered after use
- Better for high-throughput applications
typescript
// Use shard ID to avoid congestion
const transactionBuilder = pythReceiver.newTransactionBuilder({
shardId: Math.floor(Math.random() * 65536), // Random shard
});- 每个交易创建一个
- 可指定分片ID以实现并行处理
- 使用后可回收租金
- 更适合高吞吐量应用
typescript
// 使用分片ID避免拥堵
const transactionBuilder = pythReceiver.newTransactionBuilder({
shardId: Math.floor(Math.random() * 65536), // 随机分片
});Resources
资源
Official Documentation
官方文档
GitHub Repositories
GitHub仓库
NPM Packages
NPM包
Rust Crates
Rust Crates
Skill Structure
技能结构
pyth/
├── SKILL.md # This file
├── resources/
│ ├── program-addresses.md # All program IDs and feed IDs
│ └── api-reference.md # SDK API reference
├── examples/
│ ├── price-feeds/
│ │ ├── fetch-price.ts # Basic price fetching
│ │ └── multiple-prices.ts # Multiple price feeds
│ ├── on-chain/
│ │ ├── anchor-integration.rs # Anchor program example
│ │ └── price-validation.rs # Price validation patterns
│ └── streaming/
│ └── real-time-updates.ts # WebSocket streaming
├── templates/
│ ├── pyth-client.ts # TypeScript client template
│ └── anchor-oracle.rs # Anchor program template
└── docs/
└── troubleshooting.md # Common issues and solutionspyth/
├── SKILL.md # 本文档
├── resources/
│ ├── program-addresses.md # 所有程序ID和喂价ID
│ └── api-reference.md # SDK API参考
├── examples/
│ ├── price-feeds/
│ │ ├── fetch-price.ts # 基础价格获取示例
│ │ └── multiple-prices.ts # 多价格喂价示例
│ ├── on-chain/
│ │ ├── anchor-integration.rs # Anchor程序集成示例
│ │ └── price-validation.rs # 价格验证模式示例
│ └── streaming/
│ └── real-time-updates.ts # WebSocket流式更新示例
├── templates/
│ ├── pyth-client.ts # TypeScript客户端模板
│ └── anchor-oracle.rs # Anchor程序模板
└── docs/
└── troubleshooting.md # 常见问题与解决方案