Skip to content

Commit

Permalink
Add price command to current feed price
Browse files Browse the repository at this point in the history
  • Loading branch information
madninja committed Jun 19, 2024
1 parent c95f7fb commit f44d984
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 9 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 22 additions & 6 deletions helium-lib/src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ lazy_static::lazy_static! {
static ref HNT_PRICE_KEY: Pubkey = Pubkey::from_str("4DdmDswskDxXGpwHrXUfn2CNUm9rt21ac79GHNTN3J33").unwrap();

static ref MOBILE_MINT: Pubkey = Pubkey::from_str("mb1eu7TzEc71KxDpsmsKoucSSuuoGLv1drys1oP2jh6").unwrap();
static ref MOBILE_PRICE_KEY: Pubkey = Pubkey::from_str("DQ4C1tzvu28cwo1roN1Wm6TW35sfJEjLh517k3ZeWevx").unwrap();

static ref IOT_MINT: Pubkey = Pubkey::from_str("iotEVVZLEywoTn1QdwNPddxPWszn3zFhEot3MfL9fns").unwrap();
static ref IOT_PRICE_KEY: Pubkey = Pubkey::from_str("8UYEn5Weq7toHwgcmctvcAxaNJo3SJxXEayM57rpoXr9").unwrap();

static ref DC_MINT: Pubkey = Pubkey::from_str("dcuc8Amr83Wz27ZkQ2K9NS6r8zRpf1J6cvArEBDZDmm").unwrap();
static ref SOL_MINT: Pubkey = solana_sdk::system_program::ID;
}
Expand Down Expand Up @@ -125,6 +129,8 @@ pub mod price {
pub enum PriceError {
#[error("price too old")]
PriceTooOld,
#[error("invalid price account: {0}")]
InvalidPriceAccount(std::io::Error),
#[error("price below 0")]
PriceBelowZero,
#[error("invalid price timestamp: {0}")]
Expand All @@ -141,13 +147,14 @@ pub mod price {
}

pub async fn get(settings: &Settings, token: Token) -> Result<Price> {
use helium_anchor_gen::anchor_lang::AccountDeserialize;
let price_key = token
.price_key()
.ok_or_else(|| DecodeError::other(format!("No pyth price key for {token}")))?;
let anchor_client = settings.mk_anchor_client(crate::keypair::Keypair::void())?;
let program = anchor_client.program(pyth_solana_receiver_sdk::ID)?;
let solana_client = settings.mk_solana_client()?;
let account = solana_client.get_account(price_key).await?;
let PriceUpdateV2 { price_message, .. } =
program.account::<PriceUpdateV2>(*price_key).await?;
PriceUpdateV2::try_deserialize(&mut account.data.as_slice())?;

if (price_message.publish_time.saturating_add(10 * 60)) < Utc::now().timestamp() {
return Err(PriceError::PriceTooOld.into());
Expand Down Expand Up @@ -222,15 +229,22 @@ impl Token {
vec![Self::Hnt, Self::Iot, Self::Mobile, Self::Dc, Self::Sol]
}

pub fn transferrable_value_parser(s: &str) -> StdResult<Self, TokenError> {
let transferrable = [Self::Iot, Self::Mobile, Self::Hnt, Self::Sol];
fn from_allowed(s: &str, allowed: &[Self]) -> StdResult<Self, TokenError> {
let result = Self::from_str(s)?;
if !transferrable.contains(&result) {
if !allowed.contains(&result) {
return Err(TokenError::InvalidToken(s.to_string()));
}
Ok(result)
}

pub fn transferrable_value_parser(s: &str) -> StdResult<Self, TokenError> {
Self::from_allowed(s, &[Self::Iot, Self::Mobile, Self::Hnt, Self::Sol])
}

pub fn pricekey_value_parser(s: &str) -> StdResult<Self, TokenError> {
Self::from_allowed(s, &[Self::Iot, Self::Mobile, Self::Hnt])
}

pub fn associated_token_adress(&self, address: &Pubkey) -> Pubkey {
match self {
Self::Sol => *address,
Expand Down Expand Up @@ -362,6 +376,8 @@ impl Token {
pub fn price_key(&self) -> Option<&Pubkey> {
match self {
Self::Hnt => Some(&HNT_PRICE_KEY),
Self::Iot => Some(&IOT_PRICE_KEY),
Self::Mobile => Some(&MOBILE_PRICE_KEY),
_ => None,
}
}
Expand Down
1 change: 1 addition & 0 deletions helium-wallet/src/cmd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub mod dc;
pub mod export;
pub mod hotspots;
pub mod info;
pub mod price;
pub mod router;
pub mod sign;
pub mod transfer;
Expand Down
19 changes: 19 additions & 0 deletions helium-wallet/src/cmd/price.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use crate::cmd::*;
use helium_lib::token;

#[derive(Clone, Debug, clap::Args)]
/// Get the current price from the pyth price feed for the given token
pub struct Cmd {
/// Token to look up
#[arg(value_parser = token::Token::pricekey_value_parser)]
token: token::Token,
}

impl Cmd {
pub async fn run(&self, opts: Opts) -> Result {
let settings = opts.try_into()?;
let price = token::price::get(&settings, self.token).await?;

print_json(&price)
}
}
6 changes: 5 additions & 1 deletion helium-wallet/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use clap::Parser;
use helium_wallet::{
cmd::{balance, create, dc, export, hotspots, info, router, sign, transfer, upgrade, Opts},
cmd::{
balance, create, dc, export, hotspots, info, price, router, sign, transfer, upgrade, Opts,
},
result::Result,
};

Expand Down Expand Up @@ -30,6 +32,7 @@ pub enum Cmd {
Create(create::Cmd),
Hotspots(Box<hotspots::Cmd>),
Dc(dc::Cmd),
Price(price::Cmd),
Transfer(transfer::Cmd),
Export(export::Cmd),
Sign(sign::Cmd),
Expand All @@ -53,6 +56,7 @@ async fn run(cli: Cli) -> Result {
Cmd::Create(cmd) => cmd.run(cli.opts).await,
Cmd::Hotspots(cmd) => cmd.run(cli.opts).await,
Cmd::Dc(cmd) => cmd.run(cli.opts).await,
Cmd::Price(cmd) => cmd.run(cli.opts).await,
Cmd::Transfer(cmd) => cmd.run(cli.opts).await,
Cmd::Export(cmd) => cmd.run(cli.opts).await,
Cmd::Sign(cmd) => cmd.run(cli.opts).await,
Expand Down

0 comments on commit f44d984

Please sign in to comment.