Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

swap token #10

Merged
merged 1 commit into from
Feb 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,294 changes: 1,093 additions & 201 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.138"
reqwest = { version = "0.12.12", features = ["json"] }
sqlx = { version = "0.8.3", features = ["sqlite", "runtime-tokio-native-tls", "runtime-tokio", "macros", "chrono"] }
solana-sdk = "2.1.12"
solana-sdk = "2.2.0"
url = "2.0"
hex = "0.4.3"
thiserror = "2.0.11"
futures = "0.3.31"
teloxide = { version = "0.13.0", features = ["macros"] }
bs58 = "0.5.1"

31 changes: 31 additions & 0 deletions jupiter-qoute-res-sample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"inputMint": "So11111111111111111111111111111111111111112",
"inAmount": "10000000000",
"outputMint": "72GbaARtT7nn6kVpXVvk5vkJWSmbsB4UWyCV9ALqSUTt",
"outAmount": "18814040356",
"otherAmountThreshold": "18437759549",
"swapMode": "ExactIn",
"slippageBps": 200,
"platformFee": null,
"priceImpactPct": "0.1253258325222518629770670564",
"routePlan": [
{
"swapInfo": {
"ammKey": "8TMu2HmdSfSmSh3koqMT7ZHzmMmnaVeW21EnBjfXodGA",
"label": "Raydium",
"inputMint": "So11111111111111111111111111111111111111112",
"outputMint": "72GbaARtT7nn6kVpXVvk5vkJWSmbsB4UWyCV9ALqSUTt",
"inAmount": "10000000000",
"outAmount": "18814040356",
"feeAmount": "25000000",
"feeMint": "So11111111111111111111111111111111111111112"
},
"percent": 100
}
],
"scoreReport": null,
"contextSlot": 319414943,
"timeTaken": 0.020167568,
"swapUsdValue": "2015.9759237640157450138817078",
"simplerRouteUsed": false
}
16 changes: 16 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,21 @@ pub struct Config {
pub liquidility_pool_wsol_pc_mint: String,
pub rug_checker_url: String,
pub rug_check_config: RugCheckConfig,
pub swap_config: SwapConfig,
pub jupiter_url: String,
}

#[derive(Debug, Clone, PartialEq)]
pub struct RugCheckConfig {
pub signal_holder_ownership: f64,
pub not_allowed_risk: Vec<String>,
pub is_skip_pump_token: bool,
}

#[derive(Debug, Clone, PartialEq)]
pub struct SwapConfig {
pub amount: String, // lamports
pub slippage_bps: String,
}

impl Config {
Expand All @@ -34,6 +43,7 @@ impl Config {
let liquidility_pool_wsol_pc_mint = std::env::var("LIQUIDILITY_POOL_WSOL_PC_MINT")
.expect("LIQUIDILITY_POOL_WSOL_PC_MINT must be set");
let rug_checker_url = std::env::var("RUG_CHECKER_URL").expect("RUG_CHECKER_URL must be set");
let jupiter_url = std::env::var("JUPITER_URL").expect("JUPITER_URL must be set");

Config {
database_url,
Expand All @@ -53,7 +63,13 @@ impl Config {
"Large Amount of LP Unlocked".to_string(),
"Copycat token".to_string(),
],
is_skip_pump_token: true,
},
swap_config: SwapConfig {
amount: "10000000000".to_string(), // 0.01 SOL = 10000000000 lamports
slippage_bps: "200".to_string(),
},
jupiter_url,
}
}
}
2 changes: 1 addition & 1 deletion src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ impl Database {
Ok(Self { pool })
}

pub async fn save_transaction(&self, record: &TokenRecord) -> Result<(), DatabaseError> {
pub async fn _save_transaction(&self, record: &TokenRecord) -> Result<(), DatabaseError> {
sqlx::query!(
r#"
INSERT INTO tokens
Expand Down
30 changes: 18 additions & 12 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ mod telegram;
mod transaction_processor;
mod websocket;

use std::time::Duration;

use crate::{
database::Database, price_monitor::PriceMonitor, telegram::TelegramNotifier,
websocket::SolanaWebsocket,
};
use futures::StreamExt;
use solana_sdk::signer::keypair::Keypair;
use tokio::time::sleep;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
Expand All @@ -38,18 +41,21 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.await?;

let mut stream = Box::pin(stream);

while let Some(message) = stream.next().await {
// Process transaction
let signer = Keypair::from_base58_string(&config.private_key);
let processor =
transaction_processor::TransactionProcessor::new(config.clone(), &websocket, &notifier);

// let notifier = notifier.clone();
if let Err(e) = processor.process_transaction(&message, &signer).await {
eprintln!("Error processing transaction: {}", e);
loop {
if let Some(message) = stream.next().await {
// Process transaction
let signer = Keypair::from_base58_string(&config.private_key);
let processor =
transaction_processor::TransactionProcessor::new(config.clone(), &websocket, &notifier);

// let notifier = notifier.clone();
if let Err(e) = processor.process_transaction(&message, &signer).await {
eprintln!("Error processing transaction: {}", e);
}
} else {
eprintln!("Socket error, retry to connect");
let wait_time = Duration::from_secs(10); // Max 32s delay
sleep(wait_time).await;
}
}

Ok(())
}
64 changes: 63 additions & 1 deletion src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use serde::{Deserialize, Serialize};
// pub updated_at: Option<DateTime<Utc>>,
// }

#[derive(sqlx::FromRow, Debug)]
#[derive(sqlx::FromRow, Debug, Serialize, Deserialize, Clone)]
pub struct TokenRecord {
pub id: i64,
pub mint_address: String,
Expand Down Expand Up @@ -192,3 +192,65 @@ pub struct RugCheckRisk {

pub level: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct QouteResponse {
pub input_mint: String,

pub in_amount: String,

pub output_mint: String,

pub out_amount: String,

pub other_amount_threshold: String,

pub swap_mode: String,

pub slippage_bps: i64,

pub platform_fee: Option<serde_json::Value>,

pub price_impact_pct: String,

pub route_plan: Vec<RoutePlan>,

pub score_report: Option<serde_json::Value>,

pub context_slot: i64,

pub time_taken: f64,

pub swap_usd_value: String,

pub simpler_route_used: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RoutePlan {
pub swap_info: SwapInfo,

pub percent: i64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SwapInfo {
pub amm_key: String,

pub label: String,

pub input_mint: String,

pub output_mint: String,

pub in_amount: String,

pub out_amount: String,

pub fee_amount: String,

pub fee_mint: String,
}
Loading