diff --git a/pulse-wire/src/terminal.rs b/pulse-wire/src/terminal.rs index 2224a84..f76fd43 100644 --- a/pulse-wire/src/terminal.rs +++ b/pulse-wire/src/terminal.rs @@ -44,7 +44,6 @@ pub struct ActivePosition { pub symbol: String, pub size: f64, pub entry_price: f64, - pub mark_price: f64, pub profit: f64, } diff --git a/src/engine/engine.rs b/src/engine/engine.rs index 1bc2f1a..d186484 100644 --- a/src/engine/engine.rs +++ b/src/engine/engine.rs @@ -1,5 +1,6 @@ use std::sync::Arc; +use pulse_wire::terminal::ActivePosition; use tokio::{sync::Mutex, task::JoinHandle}; use crate::{ @@ -41,12 +42,14 @@ impl Engine { pub async fn run_broadcaster(&self) -> tokio::io::Result<()> { let mut refresh = tokio::time::interval(tokio::time::Duration::from_secs(5)); + let client = hypersdk::hypercore::mainnet(); + loop { refresh.tick().await; let watch_list = &self.config.lock().await.watchlist.symbols; - match crate::fetch::fetch_watch_list(watch_list).await { + match crate::fetch::fetch_watch_list(&client, watch_list).await { Ok(watch_list) => { if let Err(error) = self .terminal_server @@ -75,6 +78,45 @@ impl Engine { .await? } } + + let accounts = self.accounts.lock().await; + + if let Some(acc) = accounts.get_active() { + match client.clearinghouse_state(acc.address, None).await { + Ok(state) => { + self.terminal_server + .broadcast( + pulse_wire::terminal::TerminalServerMessage::PositionsUpdated( + state + .asset_positions + .into_iter() + .map(|position| ActivePosition { + symbol: position.position.coin, + size: position.position.szi.as_f64(), + entry_price: position + .position + .entry_px + .map(|px| px.as_f64()) + .unwrap_or(0.0), + profit: position.position.unrealized_pnl.as_f64(), + }) + .collect(), + ), + ) + .await?; + } + Err(e) => { + self.terminal_server + .error("orders", &format!("Unable to get open orders: {e}")) + .await?; + } + } + } else { + self.terminal_server.error( + "orders", + "Unable to get active account, make sure you have configured accounts properly", + ).await?; + } } } diff --git a/src/engine/fetch.rs b/src/engine/fetch.rs index 9f7b271..9e91a79 100644 --- a/src/engine/fetch.rs +++ b/src/engine/fetch.rs @@ -12,8 +12,11 @@ fn number(value: &Value, field: &str) -> Result { .map_err(|error| format!("could not parse asset context field {field} ({raw}): {error}")) } -pub async fn fetch_watch_list(symbols: &[String]) -> Result, String> { - let response = hypersdk::hypercore::mainnet() +pub async fn fetch_watch_list( + client: &hypersdk::hypercore::HttpClient, + symbols: &[String], +) -> Result, String> { + let response = client .meta_and_asset_ctxs(None) .await .map_err(|error| format!("Hyperliquid metaAndAssetCtxs request failed: {error}"))?; diff --git a/src/engine/store/accounts.rs b/src/engine/store/accounts.rs index 9da4af6..a2ef132 100644 --- a/src/engine/store/accounts.rs +++ b/src/engine/store/accounts.rs @@ -1,6 +1,6 @@ use std::{collections::HashMap, str::FromStr}; -use hypersdk::{U160, hypercore::PrivateKeySigner}; +use hypersdk::{Address, hypercore::PrivateKeySigner}; #[derive(Debug)] pub struct PrivateKey(pub PrivateKeySigner, pub String); @@ -40,7 +40,7 @@ impl serde::Serialize for PrivateKey { #[derive(Debug, serde::Serialize, serde::Deserialize)] pub struct Account { - pub address: U160, + pub address: Address, pub private_key: PrivateKey, } @@ -79,6 +79,10 @@ impl AccountList { toml::to_string(self) .map_err(|v| tokio::io::Error::new(std::io::ErrorKind::Other, v.to_string())) } + + pub fn get_active<'a>(&'a self) -> Option<&'a Account> { + self.accounts.get(&self.active) + } } impl Account { diff --git a/src/terminal/formatting.rs b/src/terminal/formatting.rs index 05bc89d..223c31b 100644 --- a/src/terminal/formatting.rs +++ b/src/terminal/formatting.rs @@ -101,7 +101,6 @@ impl Formatted for ActivePosition { format!("\x1b[35m{}\x1b[0m", self.symbol), format_f64(self.size), format_f64(self.entry_price), - format_f64(self.mark_price), format!( "{} {}", if self.profit.is_sign_positive() {