use pyth_client::{
AccountType,
Mapping,
Product,
Price,
PriceType,
PriceStatus,
CorpAction,
cast,
MAGIC,
VERSION_2,
PROD_HDR_SIZE
};
use solana_client::{
rpc_client::RpcClient
};
use solana_program::{
pubkey::Pubkey
};
use std::{
str::FromStr
};
fn get_attr_str<'a,T>( ite: & mut T ) -> String
where T : Iterator<Item=& 'a u8>
{
let mut len = *ite.next().unwrap() as usize;
let mut val = String::with_capacity( len );
while len > 0 {
val.push( *ite.next().unwrap() as char );
len -= 1;
}
return val
}
fn get_price_type( ptype: &PriceType ) -> &'static str
{
match ptype {
PriceType::Unknown => "unknown",
PriceType::Price => "price",
}
}
fn get_status( st: &PriceStatus ) -> &'static str
{
match st {
PriceStatus::Unknown => "unknown",
PriceStatus::Trading => "trading",
PriceStatus::Halted => "halted",
PriceStatus::Auction => "auction",
}
}
fn get_corp_act( cact: &CorpAction ) -> &'static str
{
match cact {
CorpAction::NoCorpAct => "nocorpact",
}
}
fn main() {
let url = "http://api.devnet.solana.com";
let key = "BmA9Z6FjioHJPpjT39QazZyhDRUdZy2ezwx4GiDdE2u2";
let clnt = RpcClient::new( url.to_string() );
let mut akey = Pubkey::from_str( key ).unwrap();
loop {
let map_data = clnt.get_account_data( &akey ).unwrap();
let map_acct = cast::<Mapping>( &map_data );
assert_eq!( map_acct.magic, MAGIC, "not a valid pyth account" );
assert_eq!( map_acct.atype, AccountType::Mapping as u32,
"not a valid pyth mapping account" );
assert_eq!( map_acct.ver, VERSION_2,
"unexpected pyth mapping account version" );
let mut i = 0;
for prod_akey in &map_acct.products {
let prod_pkey = Pubkey::new( &prod_akey.val );
let prod_data = clnt.get_account_data( &prod_pkey ).unwrap();
let prod_acct = cast::<Product>( &prod_data );
assert_eq!( prod_acct.magic, MAGIC, "not a valid pyth account" );
assert_eq!( prod_acct.atype, AccountType::Product as u32,
"not a valid pyth product account" );
assert_eq!( prod_acct.ver, VERSION_2,
"unexpected pyth product account version" );
println!( "product_account .. {:?}", prod_pkey );
let mut psz = prod_acct.size as usize - PROD_HDR_SIZE;
let mut pit = (&prod_acct.attr[..]).iter();
while psz > 0 {
let key = get_attr_str( &mut pit );
let val = get_attr_str( &mut pit );
println!( " {:.<16} {}", key, val );
psz -= 2 + key.len() + val.len();
}
if prod_acct.px_acc.is_valid() {
let mut px_pkey = Pubkey::new( &prod_acct.px_acc.val );
loop {
let pd = clnt.get_account_data( &px_pkey ).unwrap();
let pa = cast::<Price>( &pd );
assert_eq!( pa.magic, MAGIC, "not a valid pyth account" );
assert_eq!( pa.atype, AccountType::Price as u32,
"not a valid pyth price account" );
assert_eq!( pa.ver, VERSION_2,
"unexpected pyth price account version" );
println!( " price_account .. {:?}", px_pkey );
println!( " price_type ... {}", get_price_type(&pa.ptype));
println!( " exponent ..... {}", pa.expo );
println!( " status ....... {}", get_status(&pa.agg.status));
println!( " corp_act ..... {}", get_corp_act(&pa.agg.corp_act));
println!( " price ........ {}", pa.agg.price );
println!( " conf ......... {}", pa.agg.conf );
println!( " valid_slot ... {}", pa.valid_slot );
println!( " publish_slot . {}", pa.agg.pub_slot );
println!( " twap ......... {}", pa.twap );
println!( " volatility ... {}", pa.avol );
if pa.next.is_valid() {
px_pkey = Pubkey::new( &pa.next.val );
} else {
break;
}
}
}
i += 1;
if i == map_acct.num {
break;
}
}
if !map_acct.next.is_valid() {
break;
}
akey = Pubkey::new( &map_acct.next.val );
}
}