pyth

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Pyth 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

ProgramAddressDescription
Solana Receiver
rec5EKMGg6MxZYaMdyBfgwp4d5rB9T1VQH5pJv5LtFJ
Posts price updates to Solana
Price Feed
pythWSnswVUd12oZpeFP8e9CVaEqJg25g1Vtc2biRsT
Stores price feed data
Deployed on: Solana Mainnet, Devnet, Eclipse Mainnet/Testnet, Sonic networks
程序地址描述
Solana Receiver
rec5EKMGg6MxZYaMdyBfgwp4d5rB9T1VQH5pJv5LtFJ
向Solana发布价格更新
Price Feed
pythWSnswVUd12oZpeFP8e9CVaEqJg25g1Vtc2biRsT
存储价格喂价数据
部署网络:Solana主网、Devnet、Eclipse主网/测试网、Sonic网络

Popular Price Feed IDs

常用价格喂价ID

AssetHex Feed ID
BTC/USD
0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43
ETH/USD
0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace
SOL/USD
0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d
USDC/USD
0xeaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a
USDT/USD
0x2b89b9dc8fdf9f34709a5b106b472f0f39bb6ca9ce04b0fd7f2e971688e2e53b
资产十六进制喂价ID
BTC/USD
0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43
ETH/USD
0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace
SOL/USD
0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d
USDC/USD
0xeaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a
USDT/USD
0x2b89b9dc8fdf9f34709a5b106b472f0f39bb6ca9ce04b0fd7f2e971688e2e53b

Quick Start

快速开始

Installation

安装

bash
undefined
bash
undefined

TypeScript/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"

undefined
undefined

Fetch 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:
FieldTypeDescription
price
i64Price value in fixed-point format
conf
u64Confidence interval (standard deviation)
expo
i32Exponent for scaling (e.g., -8 means divide by 10^8)
publish_time
i64Unix timestamp of price
Converting to display price:
typescript
const displayPrice = price * Math.pow(10, expo);
// Example: price=19405100, expo=-2 → $194,051.00
每个Pyth价格包含以下字段:
字段类型描述
price
i64定点格式的价格值
conf
u64置信区间(标准差)
expo
i32缩放指数(例如,-8表示除以10^8)
publish_time
i64价格的Unix时间戳
转换为显示价格:
typescript
const displayPrice = price * Math.pow(10, expo);
// 示例: price=19405100, expo=-2 → $194,051.00

Confidence 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
    ema_price
    and
    ema_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.network
For 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.toml
:
toml
[dependencies]
pyth-solana-receiver-sdk = "0.3.0"
anchor-lang = "0.30.1"
Cargo.toml
中添加依赖:
toml
[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 solutions
pyth/
├── 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            # 常见问题与解决方案