#solana #pyth #oracle

deprecated pyth-client

pyth price oracle data structures and example usage

11 unstable releases (4 breaking)

0.5.1 May 3, 2022
0.5.0 Feb 24, 2022
0.4.0 Feb 18, 2022
0.3.0-beta.1 Dec 29, 2021
0.2.2 Jul 12, 2021

#9 in #pyth

Download history 295/week @ 2024-07-20 368/week @ 2024-07-27 330/week @ 2024-08-03 525/week @ 2024-08-10 391/week @ 2024-08-17 531/week @ 2024-08-24 478/week @ 2024-08-31 511/week @ 2024-09-07 624/week @ 2024-09-14 485/week @ 2024-09-21 381/week @ 2024-09-28 247/week @ 2024-10-05 534/week @ 2024-10-12 828/week @ 2024-10-19 1242/week @ 2024-10-26 1785/week @ 2024-11-02

4,401 downloads per month
Used in 15 crates (6 directly)

Apache-2.0

52KB
882 lines

Pyth Client

This crate has been deprecated. Please use pyth-sdk-solana instead. pyth-sdk-solana provides identical functionalities with an easier interface.

This crate provides utilities for reading price feeds from the pyth.network oracle on the Solana network. The crate includes a library for on-chain programs and an off-chain example program.

Key features of this library include:

  • Get the current price of over 50 products, including cryptocurrencies, US equities, forex and more.
  • Combine listed products to create new price feeds, e.g., for baskets of tokens or non-USD quote currencies.
  • Consume prices in on-chain Solana programs or off-chain applications.

Please see the pyth.network documentation for more information about pyth.network.

Installation

Add a dependency to your Cargo.toml:

[dependencies]
pyth-client="<version>"

If you want to use this library in your on-chain program you should use no-entrypoint feature to prevent conflict between your program and this library's program.

[dependencies]
pyth-client = {version = "<version>", features = ["no-entrypoint"]}

See pyth-client on crates.io to get the latest version of the library.

Usage

Pyth Network stores its price feeds in a collection of Solana accounts. This crate provides utilities for interpreting and manipulating the content of these accounts. Applications can obtain the content of these accounts in two different ways:

  • On-chain programs should pass these accounts to the instructions that require price feeds.
  • Off-chain programs can access these accounts using the Solana RPC client (as in the example program).

In both cases, the content of the account will be provided to the application as a binary blob (Vec<u8>). The examples below assume that the user has already obtained this account data.

Parse account data

Pyth Network has several different types of accounts:

  • Price accounts store the current price for a product
  • Product accounts store metadata about a product, such as its symbol (e.g., "BTC/USD").
  • Mapping accounts store a listing of all Pyth accounts

For more information on the different types of Pyth accounts, see the account structure documentation. The pyth.network website also lists the public keys of the accounts (e.g., BTC/USD accounts).

This library provides several load_* methods that translate the binary data in each account into an appropriate struct:

// replace with account data, either passed to on-chain program or from RPC node 
let price_account_data: Vec<u8> = ...;
let price_account: Price = load_price( &price_account_data ).unwrap();

let product_account_data: Vec<u8> = ...;
let product_account: Product = load_product( &product_account_data ).unwrap();

let mapping_account_data: Vec<u8> = ...;
let mapping_account: Mapping = load_mapping( &mapping_account_data ).unwrap();

Get the current price

Read the current price from a Price account:

let price: PriceConf = price_account.get_current_price().unwrap();
println!("price: ({} +- {}) x 10^{}", price.price, price.conf, price.expo);

The price is returned along with a confidence interval that represents the degree of uncertainty in the price. Both values are represented as fixed-point numbers, a * 10^e. The method will return None if the price is not currently available.

The status of the price feed determines if the price is available. You can get the current status using:

let price_status: PriceStatus = price_account.get_current_price_status();

Non-USD prices

Most assets in Pyth are priced in USD. Applications can combine two USD prices to price an asset in a different quote currency:

let btc_usd: Price = ...;
let eth_usd: Price = ...;
// -8 is the desired exponent for the result 
let btc_eth: PriceConf = btc_usd.get_price_in_quote(&eth_usd, -8);
println!("BTC/ETH price: ({} +- {}) x 10^{}", price.price, price.conf, price.expo);

Price a basket of assets

Applications can also compute the value of a basket of multiple assets:

let btc_usd: Price = ...;
let eth_usd: Price = ...;
// Quantity of each asset in fixed-point a * 10^e.
// This represents 0.1 BTC and .05 ETH.
// -8 is desired exponent for result
let basket_price: PriceConf = Price::price_basket(&[
    (btc_usd, 10, -2),
    (eth_usd, 5, -2)
  ], -8);
println!("0.1 BTC and 0.05 ETH are worth: ({} +- {}) x 10^{} USD",
         basket_price.price, basket_price.conf, basket_price.expo);

This function additionally propagates any uncertainty in the price into uncertainty in the value of the basket.

Off-chain example program

The example program prints the product reference data and current price information for Pyth on Solana devnet. Run the following commands to try this example program:

cargo build --examples
cargo run --example get_accounts

The output of this command is a listing of Pyth's accounts, such as:

product_account ............ 6MEwdxe4g1NeAF9u6KDG14anJpFsVEa2cvr5H6iriFZ8
  symbol.................... SRM/USD
  asset_type................ Crypto
  quote_currency............ USD
  description............... SRM/USD
  generic_symbol............ SRMUSD
  base...................... SRM
  price_account ............ 992moaMQKs32GKZ9dxi8keyM2bUmbrwBZpK4p2K6X5Vs
    price .................. 7398000000
    conf ................... 3200000
    price_type ............. price
    exponent ............... -9
    status ................. trading
    corp_act ............... nocorpact
    num_qt ................. 1
    valid_slot ............. 91340924
    publish_slot ........... 91340925
    ema_price .............. 7426390900
    ema_confidence ......... 2259870

Development

This library can be built for either your native platform or in BPF (used by Solana programs). Use cargo build / cargo test to build and test natively. Use cargo build-bpf / cargo test-bpf to build in BPF for Solana; these commands require you to have installed the Solana CLI tools.

The BPF tests will also run an instruction count program that logs the resource consumption of various library functions. This program can also be run on its own using cargo test-bpf --test instruction_count.

Releases

To release a new version of this package, perform the following steps:

  1. Increment the version number in Cargo.toml. You may use a version number with a -beta.x suffix such as 0.0.1-beta.0 to create opt-in test versions.
  2. Merge your change into main on github.
  3. Create and publish a new github release. The name of the release should be the version number, and the tag should be the version number prefixed with v. Publishing the release will trigger a github action that will automatically publish the pyth-client rust crate to crates.io.

Dependencies

~16–25MB
~416K SLoC