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
4,401 downloads per month
Used in 15 crates
(6 directly)
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(ð_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:
- Increment the version number in
Cargo.toml
. You may use a version number with a-beta.x
suffix such as0.0.1-beta.0
to create opt-in test versions. - Merge your change into
main
on github. - 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 tocrates.io
.
Dependencies
~16–25MB
~416K SLoC