Implemented stuff
This commit is contained in:
Generated
+1121
-10
File diff suppressed because it is too large
Load Diff
@@ -20,3 +20,4 @@ tokio-tungstenite = { version = "0.30.0", features = ["native-tls"] }
|
|||||||
log = "0.4.33"
|
log = "0.4.33"
|
||||||
env_logger = "0.11.11"
|
env_logger = "0.11.11"
|
||||||
rust_decimal = "1.42.1"
|
rust_decimal = "1.42.1"
|
||||||
|
reqwest = { version = "0.13.4", features = ["json"] }
|
||||||
|
|||||||
+39
-3
@@ -19,12 +19,42 @@ pub enum Account {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct AccountManger {
|
pub struct AccountManager {
|
||||||
pub active: String,
|
pub active: String,
|
||||||
pub accounts: HashMap<String, Account>,
|
pub accounts: HashMap<String, Account>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AccountManger {
|
impl Account {
|
||||||
|
pub async fn new() -> anyhow::Result<Self> {
|
||||||
|
let response = reqwest::Client::new()
|
||||||
|
.post("https://pumpdev.io/api/wallet/create")
|
||||||
|
.json(&serde_json::json!({}))
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.context("Failed to create PumpDev wallet")?;
|
||||||
|
|
||||||
|
if !response.status().is_success() {
|
||||||
|
let status = response.status();
|
||||||
|
let body: serde_json::Value = response.json().await.unwrap_or_default();
|
||||||
|
let message = body
|
||||||
|
.get("error")
|
||||||
|
.and_then(serde_json::Value::as_str)
|
||||||
|
.unwrap_or("Unknown error");
|
||||||
|
return Err(anyhow!(
|
||||||
|
"Failed to create PumpDev wallet ({status}): {message}"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let account: PumpDevAccount = response
|
||||||
|
.json()
|
||||||
|
.await
|
||||||
|
.context("Failed to parse PumpDev wallet")?;
|
||||||
|
|
||||||
|
Ok(Self::PumpDev(account))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AccountManager {
|
||||||
pub async fn get() -> anyhow::Result<Self> {
|
pub async fn get() -> anyhow::Result<Self> {
|
||||||
let path = get_accounts_path()?;
|
let path = get_accounts_path()?;
|
||||||
|
|
||||||
@@ -43,7 +73,13 @@ impl AccountManger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn new() -> anyhow::Result<Self> {
|
pub async fn new() -> anyhow::Result<Self> {
|
||||||
Err(anyhow!("Not implemented yet"))
|
let mut accounts = HashMap::new();
|
||||||
|
accounts.insert("default".to_string(), Account::new().await?);
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
active: "default".to_string(),
|
||||||
|
accounts,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_str(s: &str) -> anyhow::Result<Self> {
|
pub fn from_str(s: &str) -> anyhow::Result<Self> {
|
||||||
|
|||||||
+1
-4
@@ -1,7 +1,6 @@
|
|||||||
pub mod pump_fun;
|
pub mod pump_fun;
|
||||||
|
|
||||||
use rust_decimal::Decimal;
|
use rust_decimal::Decimal;
|
||||||
use tokio::sync::Mutex;
|
|
||||||
|
|
||||||
use crate::account::Account;
|
use crate::account::Account;
|
||||||
|
|
||||||
@@ -32,9 +31,7 @@ pub trait Executor {
|
|||||||
impl Account {
|
impl Account {
|
||||||
pub fn executor(self) -> impl Executor {
|
pub fn executor(self) -> impl Executor {
|
||||||
match self {
|
match self {
|
||||||
Self::PumpDev(account) => pump_fun::PumpDev {
|
Self::PumpDev(account) => pump_fun::PumpDev::new(account),
|
||||||
account: Mutex::new(account),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
|
use anyhow::{Context, anyhow};
|
||||||
|
use reqwest::Client;
|
||||||
use rust_decimal::Decimal;
|
use rust_decimal::Decimal;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
use crate::executor::Executor;
|
use crate::executor::Executor;
|
||||||
|
|
||||||
|
const TRADE_LIGHTNING_URL: &str = "https://pumpdev.io/api/trade-lightning";
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct PumpDevAccount {
|
pub struct PumpDevAccount {
|
||||||
#[serde(rename = "apiKey")]
|
#[serde(rename = "apiKey")]
|
||||||
@@ -14,8 +18,70 @@ pub struct PumpDevAccount {
|
|||||||
pub private_key: String,
|
pub private_key: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
struct TradeResponse {
|
||||||
|
signature: String,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct PumpDev {
|
pub struct PumpDev {
|
||||||
pub account: Mutex<PumpDevAccount>,
|
pub account: Mutex<PumpDevAccount>,
|
||||||
|
pub client: Client,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PumpDev {
|
||||||
|
pub fn new(account: PumpDevAccount) -> Self {
|
||||||
|
Self {
|
||||||
|
account: Mutex::new(account),
|
||||||
|
client: Client::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn trade(
|
||||||
|
&self,
|
||||||
|
action: &str,
|
||||||
|
mint: String,
|
||||||
|
amount: Decimal,
|
||||||
|
priority: Decimal,
|
||||||
|
slippage: u16,
|
||||||
|
denominated_in_sol: bool,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let account = self.account.lock().await;
|
||||||
|
|
||||||
|
let response = self
|
||||||
|
.client
|
||||||
|
.post(format!("{TRADE_LIGHTNING_URL}?api-key={}", account.api_key))
|
||||||
|
.json(&serde_json::json!({
|
||||||
|
"action": action,
|
||||||
|
"mint": mint,
|
||||||
|
"amount": amount,
|
||||||
|
"denominatedInSol": if denominated_in_sol { "true" } else { "false" },
|
||||||
|
"slippage": slippage,
|
||||||
|
"priorityFee": priority,
|
||||||
|
}))
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.context("Failed to send trade request")?;
|
||||||
|
|
||||||
|
let status = response.status();
|
||||||
|
let body = response.text().await?;
|
||||||
|
|
||||||
|
if !status.is_success() {
|
||||||
|
let error = serde_json::from_str::<serde_json::Value>(&body)
|
||||||
|
.ok()
|
||||||
|
.and_then(|value| value.get("error").cloned())
|
||||||
|
.and_then(|value| value.as_str().map(str::to_string))
|
||||||
|
.unwrap_or_else(|| body.trim().to_string());
|
||||||
|
|
||||||
|
return Err(anyhow!("Trade failed ({status}): {error}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let data: TradeResponse =
|
||||||
|
serde_json::from_str(&body).context("Failed to parse trade response")?;
|
||||||
|
|
||||||
|
log::info!("{action} executed: {}", data.signature);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Executor for PumpDev {
|
impl Executor for PumpDev {
|
||||||
@@ -26,7 +92,8 @@ impl Executor for PumpDev {
|
|||||||
priority: Decimal,
|
priority: Decimal,
|
||||||
slippage: u16,
|
slippage: u16,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
Ok(())
|
self.trade("buy", mint, amount, priority, slippage, true)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn sell(
|
async fn sell(
|
||||||
@@ -36,6 +103,7 @@ impl Executor for PumpDev {
|
|||||||
priority: Decimal,
|
priority: Decimal,
|
||||||
slippage: u16,
|
slippage: u16,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
Ok(())
|
self.trade("sell", mint, amount, priority, slippage, false)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user