mirror of
https://github.com/payden/libwsclient
synced 2026-03-02 04:09:18 +00:00
feat : add strategy
This commit is contained in:
30
utils/api.rs
Normal file
30
utils/api.rs
Normal 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
12
utils/config_parser.rs
Normal 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
30
utils/data_sources.rs
Normal 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
11
utils/keypair.rs
Normal 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
1
utils/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod solana;
|
||||
20
utils/profit_calculator.rs
Normal file
20
utils/profit_calculator.rs
Normal 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
46
utils/solana.rs
Normal 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)
|
||||
}
|
||||
25
utils/transaction_utils.rs
Normal file
25
utils/transaction_utils.rs
Normal 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())
|
||||
}
|
||||
Reference in New Issue
Block a user