Renamed pulse wire to sdk

This commit is contained in:
2026-07-28 22:33:19 +02:00
parent 7968ae14af
commit 5c65b19e97
18 changed files with 39 additions and 38 deletions
+10
View File
@@ -0,0 +1,10 @@
[package]
name = "pulse-sdk"
version = "0.1.0-alpha.0"
edition = "2024"
[dependencies]
serde = { workspace = true }
hypersdk = { workspace = true }
postcard = { workspace = true }
tokio = { workspace = true }
+63
View File
@@ -0,0 +1,63 @@
use crate::units::{Direction, Symbol, USD};
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub enum MarketTrend {
Bullish,
Bearish,
Neutral,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub enum LogKind {
Info,
Warn,
Err,
Debug,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Signal {
pub symbol: String,
pub kind: Direction,
pub confidence: f32,
pub size: f64,
pub price: USD,
pub take_profit: USD,
pub stop_loss: USD,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct EventLog {
pub kind: LogKind,
pub name: String,
pub message: String,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Position {
pub symbol: Symbol,
pub size: f64,
pub entry_price: USD,
pub profit: USD,
}
impl std::fmt::Display for MarketTrend {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Bullish => write!(f, "Bullish"),
Self::Bearish => write!(f, "Bearish"),
Self::Neutral => write!(f, "Neutral"),
}
}
}
impl std::fmt::Display for LogKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Info => write!(f, "INFO"),
Self::Warn => write!(f, "WARN"),
Self::Err => write!(f, "ERR"),
Self::Debug => write!(f, "DEBUG"),
}
}
}
+25
View File
@@ -0,0 +1,25 @@
#[cfg(target_os = "macos")]
use std::path::PathBuf;
pub mod general;
pub mod plugin;
pub mod terminal;
pub mod units;
pub use hypersdk;
pub mod prelude {
pub use crate::general::*;
pub use crate::plugin::*;
pub use crate::server_path;
pub use crate::terminal::*;
pub use crate::units::*;
pub use hypersdk;
}
pub fn server_path() -> PathBuf {
PathBuf::from("/tmp/pulse-engine.sock")
}
pub fn map_postcard_err<T>(res: postcard::Result<T>) -> tokio::io::Result<T> {
res.map_err(|e| tokio::io::Error::new(std::io::ErrorKind::Other, e))
}
+100
View File
@@ -0,0 +1,100 @@
use crate::{
general::{EventLog, Signal},
terminal::MarketItem,
units::Direction,
};
use hypersdk::hypercore::{Candle, CandleInterval, Subscription};
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct StrategyManifest {
pub name: String,
pub description: String,
pub author: String,
pub version: String,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct RiskManifest {
pub name: String,
pub description: String,
pub author: String,
pub version: String,
pub max_loss: u8,
pub cooldown: CandleInterval,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub enum StrategyMessage {
Log(EventLog),
GetWatchList,
GetCandlestick {
symbol: String,
interval: CandleInterval,
count: u32,
},
Subscribe(Subscription),
Unsubscribe(Subscription),
UnsubscribeAll,
Signal(StrategySignal),
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub enum RiskMessage {
Log(EventLog),
GetWatchList,
Approve(Signal),
Reject { reason: String },
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub enum StrategyEngineMessage {
Initialize,
WatchList(Vec<MarketItem>),
Command {
command: String,
args: Vec<String>,
},
CandleUpdate {
symbol: String,
interval: CandleInterval,
candle: Candle,
},
Candlestick {
symbol: String,
interval: CandleInterval,
candles: Vec<Candle>,
},
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub enum RiskEngineMessage {
Initialize,
WatchList(Vec<MarketItem>),
Command { command: String, args: Vec<String> },
Signal(StrategySignal),
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct StrategySignal {
pub symbol: String,
pub side: Direction,
pub confidence: f32,
pub price: Option<f64>,
}
+145
View File
@@ -0,0 +1,145 @@
use crate::{
general::{EventLog, MarketTrend, Position, Signal},
plugin::{RiskManifest, StrategyManifest},
units::{Symbol, USD, Volatility},
};
use hypersdk::hypercore::CandleInterval;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub enum TerminalServerMessage {
// WatchList
WatchListUpdated(Vec<MarketItem>),
// Positions
PositionsUpdated(Vec<Position>),
// Strategy
StrategyUpdated(Strategy),
// Signals
SignalsUpdated(Vec<Signal>),
// Inspector
Inspect(InspectTarget),
// Status
StatusUpdated(Status),
// Logs
SetLogs(Vec<EventLog>),
AddLog(EventLog),
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub enum TerminalClientMessage {
ExecuteCommand(String),
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct MarketItem {
pub symbol: Symbol,
pub price: USD,
pub trend: f64,
pub volume_24h: USD,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct MarketOverview {
pub trend: MarketTrend,
pub volatility: Volatility,
pub pressure: f64,
pub alerts: Vec<Alert>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub enum AlertLevel {
High,
Medium,
Low,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Alert {
pub level: AlertLevel,
pub message: String,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Balance {
pub asset: String,
pub amount: f64,
pub value: f64,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub enum InspectTarget {
None,
Some(Vec<InspectItem>),
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub enum InspectItem {
String(String),
Symbol(String),
USD(f64),
F64(f64),
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Status {
pub feed: Mode,
pub exchange: String,
pub dex: String,
pub latency: u16,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub enum Mode {
Auto,
Manual,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub enum ItemState {
Running,
Stopped,
Error,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Strategy {
pub strategy: StrategyManifest,
pub risk: RiskManifest,
pub mode: Mode,
pub state: ItemState,
pub cooldown: CandleInterval,
}
impl std::fmt::Display for AlertLevel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::High => write!(f, "H"),
Self::Medium => write!(f, "M"),
Self::Low => write!(f, "L"),
}
}
}
impl std::fmt::Display for Mode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Auto => write!(f, "\x1b[96mAUTO\x1b[0m"),
Self::Manual => write!(f, "\x1b[97mMANUAL\x1b[0m"),
}
}
}
impl std::fmt::Display for ItemState {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Running => write!(f, "\x1b[92mRUNNING\x1b[0m"),
Self::Stopped => write!(f, "\x1b[90mSTOPPED\x1b[0m"),
Self::Error => write!(f, "\x1b[91mERROR\x1b[0m"),
}
}
}
+108
View File
@@ -0,0 +1,108 @@
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Symbol(pub String);
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)]
pub struct USD(pub f64);
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub enum Direction {
Buy,
Sell,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub enum Volatility {
Low,
Medium,
High,
}
impl std::fmt::Display for Symbol {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "\x1b[35m{}\x1b[0m", self.0)
}
}
impl std::fmt::Display for USD {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.0 > 0.0 {
write!(f, "\x1b[32m${}\x1b[0m", format_f64(self.0))
} else {
write!(f, "\x1b[31m${}\x1b[0m", format_f64(self.0))
}
}
}
pub fn format_f64(value: f64) -> String {
let abs = value.abs();
let (divisor, suffix) = if abs >= 1_000_000_000.0 {
(1_000_000_000.0, "B")
} else if abs >= 1_000_000.0 {
(1_000_000.0, "M")
} else if abs >= 1_000.0 {
(1_000.0, "K")
} else {
(1.0, "")
};
if divisor != 1.0 {
let formatted = value / divisor;
// Remove unnecessary trailing zeros
let s = format!("{:.2}", formatted)
.trim_end_matches('0')
.trim_end_matches('.')
.to_string();
return format!("{}{}", s, suffix);
}
let val = format!("{:.3}", value);
let parts: Vec<&str> = val.split('.').collect();
let int = parts[0].to_string();
let negative = int.starts_with('-');
let start = if negative { 1 } else { 0 };
let mut result = String::new();
for (i, c) in int[start..].chars().rev().enumerate() {
if i > 0 && i % 3 == 0 {
result.push(',');
}
result.push(c);
}
let mut formatted: String = result.chars().rev().collect();
if negative {
formatted.insert(0, '-');
}
if parts.len() > 1 {
formatted.push('.');
formatted.push_str(parts[1]);
}
formatted
}
impl std::fmt::Display for Direction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Buy => write!(f, "BUY"),
Self::Sell => write!(f, "SELL"),
}
}
}
impl std::fmt::Display for Volatility {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Low => write!(f, "Low"),
Self::Medium => write!(f, "Medium"),
Self::High => write!(f, "High"),
}
}
}