Refactor
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
use std::{collections::HashMap, path::PathBuf};
|
||||
|
||||
use anyhow::Context;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub fn get_accounts_path() -> anyhow::Result<PathBuf> {
|
||||
Ok(std::env::home_dir()
|
||||
.context("Failed to get home dir")?
|
||||
.join(".config")
|
||||
.join("sol-hunter")
|
||||
.join("accounts.json"))
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Account {
|
||||
#[serde(rename = "publicKey")]
|
||||
pub public_key: String,
|
||||
#[serde(rename = "privateKey")]
|
||||
pub private_key: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct AccountManager {
|
||||
#[serde(rename = "apiKey")]
|
||||
pub api_key: String,
|
||||
pub active: String,
|
||||
pub accounts: HashMap<String, Account>,
|
||||
}
|
||||
|
||||
impl AccountManager {
|
||||
pub async fn get() -> anyhow::Result<Self> {
|
||||
let path = get_accounts_path()?;
|
||||
|
||||
if !path.exists() {
|
||||
let default = Self::new().await?;
|
||||
|
||||
tokio::fs::create_dir_all(path.parent().unwrap()).await?;
|
||||
tokio::fs::write(&path, default.to_string()?).await?;
|
||||
|
||||
println!("Please open {path:?} and edit the data accordingly");
|
||||
|
||||
return Ok(default);
|
||||
}
|
||||
|
||||
let output = tokio::fs::read_to_string(path).await?;
|
||||
|
||||
Self::from_str(&output)
|
||||
}
|
||||
|
||||
pub async fn new() -> anyhow::Result<Self> {
|
||||
let mut accounts = HashMap::new();
|
||||
accounts.insert(
|
||||
"default".to_string(),
|
||||
Account {
|
||||
public_key: String::new(),
|
||||
private_key: String::new(),
|
||||
},
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
active: "default".to_string(),
|
||||
api_key: String::new(),
|
||||
accounts,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn from_str(s: &str) -> anyhow::Result<Self> {
|
||||
serde_json::from_str(s).context("Failed to parse accounts")
|
||||
}
|
||||
|
||||
pub fn to_string(&self) -> anyhow::Result<String> {
|
||||
serde_json::to_string(self).context("Failed to serialize accounts")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
pub mod account;
|
||||
pub mod tradelog;
|
||||
@@ -0,0 +1,70 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum ExitReason {
|
||||
TakeProfit,
|
||||
StopLoss,
|
||||
TrailingStop,
|
||||
MomentumStalled,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct TradeLog {
|
||||
pub mint: String,
|
||||
|
||||
pub opened_at: chrono::DateTime<chrono::Utc>,
|
||||
pub closed_at: Option<chrono::DateTime<chrono::Utc>>,
|
||||
pub duration_secs: Option<i64>,
|
||||
|
||||
pub entry_price_sol: f64,
|
||||
pub exit_price_sol: Option<f64>,
|
||||
|
||||
pub pnl_percent: Option<f64>,
|
||||
pub exit_reason: Option<ExitReason>,
|
||||
|
||||
pub unique_buyers: usize,
|
||||
pub net_sol_flow: f64,
|
||||
pub curve_sol: f64,
|
||||
}
|
||||
|
||||
impl TradeLog {
|
||||
pub fn new(
|
||||
mint: String,
|
||||
entry_price_sol: f64,
|
||||
unique_buyers: usize,
|
||||
net_sol_flow: f64,
|
||||
curve_sol: f64,
|
||||
) -> Self {
|
||||
Self {
|
||||
mint,
|
||||
opened_at: chrono::Utc::now(),
|
||||
closed_at: None,
|
||||
|
||||
entry_price_sol,
|
||||
exit_price_sol: None,
|
||||
|
||||
pnl_percent: None,
|
||||
duration_secs: None,
|
||||
|
||||
exit_reason: None,
|
||||
|
||||
unique_buyers,
|
||||
net_sol_flow,
|
||||
curve_sol,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn close(&mut self, exit_price_sol: f64, reason: ExitReason) {
|
||||
let now = chrono::Utc::now();
|
||||
|
||||
let pnl = ((exit_price_sol - self.entry_price_sol) / self.entry_price_sol) * 100.0;
|
||||
|
||||
self.exit_price_sol = Some(exit_price_sol);
|
||||
self.pnl_percent = Some(pnl);
|
||||
|
||||
self.closed_at = Some(now);
|
||||
self.duration_secs = Some(now.signed_duration_since(self.opened_at).num_seconds());
|
||||
|
||||
self.exit_reason = Some(reason);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user