1
0
mirror of https://github.com/payden/libwsclient synced 2026-03-02 04:09:18 +00:00

feat : add strategy

This commit is contained in:
deniyuda348
2025-05-16 15:09:24 +09:00
parent d416fcb62c
commit 17c1e2d5e0
81 changed files with 7848 additions and 2858 deletions

30
utils/api.rs Normal file
View File

@@ -0,0 +1,30 @@
use crate::api::parsec::ParsecApi;
use crate::api::flipside::FlipsideApi;
use crate::api::thegraph::TheGraphApi;
pub async fn get_sniping_data(parsec_api: &ParsecApi, flipside_api: &FlipsideApi) -> Result<crate::models::sniping_data::SnipingData, Box<dyn std::error::Error>> {
let token_prices = parsec_api.get_token_prices().await?;
let mut sniping_data = crate::models::sniping_data::SnipingData {
token_prices,
token_volumes: HashMap::new(),
};
for token_mint in token_prices.keys() {
let token_volume = flipside_api.get_token_volume(token_mint).await?;
sniping_data.token_volumes.insert(token_mint.to_string(), token_volume);
}
Ok(sniping_data)
}
pub async fn get_copy_trade_data(thegraph_api: &TheGraphApi, trader_accounts: &[String]) -> Result<Vec<crate::models::trade::Trade>, Box<dyn std::error::Error>> {
let mut all_trades = Vec::new();
for trader_account in trader_accounts {
let trades = thegraph_api.get_trader_transactions(trader_account).await?;
all_trades.extend(trades);
}
Ok(all_trades)
}

12
utils/config_parser.rs Normal file
View File

@@ -0,0 +1,12 @@
use crate::config::Config;
use anyhow::Result;
use std::fs::File;
use std::io::Read;
pub fn parse_config(path: &str) -> Result<Config> {
let mut file = File::open(path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
let config: Config = toml::from_str(&contents)?;
Ok(config)
}

30
utils/data_sources.rs Normal file
View File

@@ -0,0 +1,30 @@
use crate::error::Result;
use reqwest::Client;
use serde::Deserialize;
use std::collections::HashMap;
#[derive(Debug, Deserialize)]
pub struct PriceData {
pub symbol: String,
pub price: f64,
}
pub async fn fetch_prices_from_coingecko(symbols: &[String]) -> Result<HashMap<String, f64>> {
let url = format!(
"https://api.coingecko.com/api/v3/simple/price?ids={}&vs_currencies=usd",
symbols.join(",")
);
let client = Client::new();
let response = client.get(&url).send().await?;
let prices: HashMap<String, HashMap<String, f64>> = response.json().await?;
let mut price_map = HashMap::new();
for (symbol, price_data) in prices {
if let Some(price) = price_data.get("usd") {
price_map.insert(symbol, *price);
}
}
Ok(price_map)
}

11
utils/keypair.rs Normal file
View File

@@ -0,0 +1,11 @@
use anyhow::Result;
use solana_sdk::signature::Keypair;
use std::fs::File;
use std::io::BufReader;
pub fn read_keypair_file(path: &str) -> Result<Keypair> {
let file = File::open(path)?;
let reader = BufReader::new(file);
let keypair = Keypair::from_bytes(&serde_json::from_reader(reader)?)?;
Ok(keypair)
}

1
utils/mod.rs Normal file
View File

@@ -0,0 +1 @@
pub mod solana;

View File

@@ -0,0 +1,20 @@
use crate::error::Result;
use crate::models::market::Market;
use crate::models::order::{Order, OrderSide};
use rust_decimal::Decimal;
pub fn calculate_profit(market: &Market, buy_order: &Order, sell_order: &Order) -> Result<f64> {
if buy_order.side != OrderSide::Bid || sell_order.side != OrderSide::Ask {
return Err(anyhow!("Invalid order sides for profit calculation"));
}
let buy_price = Decimal::from_f64(buy_order.price).ok_or_else(|| anyhow!("Invalid buy price"))?;
let sell_price = Decimal::from_f64(sell_order.price).ok_or_else(|| anyhow!("Invalid sell price"))?;
let quantity = Decimal::from_f64(buy_order.quantity).ok_or_else(|| anyhow!("Invalid quantity"))?;
let buy_value = buy_price * quantity;
let sell_value = sell_price * quantity;
let profit = sell_value - buy_value;
Ok(profit.to_f64().ok_or_else(|| anyhow!("Failed to convert profit to f64"))?)
}

46
utils/solana.rs Normal file
View File

@@ -0,0 +1,46 @@
use solana_sdk::transaction::Transaction;
use std::error::Error;
pub fn analyze_transaction(transaction: &Transaction) -> Result<crate::models::transaction_analysis::TransactionAnalysis, Box<dyn Error>> {
let mut analysis = crate::models::transaction_analysis::TransactionAnalysis::default();
analysis.signature = transaction.signatures[0].to_string();
analysis.num_instructions = transaction.message.instructions.len() as u64;
for (index, instruction) in transaction.message.instructions.iter().enumerate() {
let account_metas = &instruction.accounts;
let num_accounts = account_metas.len() as u64;
let program_id = &instruction.program_id;
analysis.instructions.push(crate::models::transaction_analysis::InstructionAnalysis {
index: index as u64,
num_accounts,
program_id: program_id.to_string(),
});
}
Ok(analysis)
}
pub fn calculate_profit(transaction: &Transaction) -> Result<f64, Box<dyn Error>> {
let mut profit = 0.0;
for (index, instruction) in transaction.message.instructions.iter().enumerate() {
let account_metas = &instruction.accounts;
if let Some(transfer_instruction) = instruction.program_id(&spl_token::ID) {
if let Ok(transfer_amount) = spl_token::instruction::unpack_amount(transfer_instruction.data) {
let from_account = &account_metas[0];
let to_account = &account_metas[1];
if from_account.is_signer {
profit -= transfer_amount as f64;
} else if to_account.is_signer {
profit += transfer_amount as f64;
}
}
}
}
Ok(profit)
}

View File

@@ -0,0 +1,25 @@
use crate::error::Result;
use solana_sdk::instruction::Instruction;
use solana_sdk::transaction::Transaction;
pub fn get_instruction_data(transaction: &Transaction, program_id: &Pubkey) -> Result<Vec<u8>> {
let instruction = transaction
.message
.instructions
.iter()
.find(|ix| ix.program_id == *program_id)
.ok_or_else(|| anyhow!("Instruction not found for program ID: {}", program_id))?;
Ok(instruction.data.clone())
}
pub fn get_instruction_accounts(transaction: &Transaction, program_id: &Pubkey) -> Result<Vec<Pubkey>> {
let instruction = transaction
.message
.instructions
.iter()
.find(|ix| ix.program_id == *program_id)
.ok_or_else(|| anyhow!("Instruction not found for program ID: {}", program_id))?;
Ok(instruction.accounts.iter().map(|account| account.pubkey).collect())
}