Positions

This commit is contained in:
2026-07-25 01:57:27 +02:00
parent 2cbcdc7108
commit e61dd25e72
5 changed files with 54 additions and 7 deletions
+43 -1
View File
@@ -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?;
}
}
}
+5 -2
View File
@@ -12,8 +12,11 @@ fn number(value: &Value, field: &str) -> Result<f64, String> {
.map_err(|error| format!("could not parse asset context field {field} ({raw}): {error}"))
}
pub async fn fetch_watch_list(symbols: &[String]) -> Result<Vec<WatchListItem>, String> {
let response = hypersdk::hypercore::mainnet()
pub async fn fetch_watch_list(
client: &hypersdk::hypercore::HttpClient,
symbols: &[String],
) -> Result<Vec<WatchListItem>, String> {
let response = client
.meta_and_asset_ctxs(None)
.await
.map_err(|error| format!("Hyperliquid metaAndAssetCtxs request failed: {error}"))?;
+6 -2
View File
@@ -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 {
-1
View File
@@ -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() {