pump_trades/
token_trades.rs

1use chrono::Utc;
2use hyperstack_sdk::HyperStackClient;
3use serde::{Deserialize, Serialize};
4use std::collections::VecDeque;
5use tokio::time::{sleep, Duration};
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
8struct TradeInfo {
9    wallet: String,
10    direction: String,
11    amount_sol: f64,
12}
13
14#[derive(Serialize, Deserialize, Debug, Clone, Default)]
15struct PumpToken {
16    #[serde(skip_serializing_if = "Option::is_none")]
17    mint: Option<String>,
18    #[serde(skip_serializing_if = "Option::is_none")]
19    name: Option<String>,
20    #[serde(skip_serializing_if = "Option::is_none")]
21    symbol: Option<String>,
22    #[serde(skip_serializing_if = "Option::is_none")]
23    creator: Option<String>,
24    #[serde(skip_serializing_if = "Option::is_none")]
25    last_trade: Option<TradeInfo>,
26}
27
28#[tokio::main]
29async fn main() -> anyhow::Result<()> {
30    let url = std::env::args()
31        .nth(1)
32        .unwrap_or_else(|| "ws://127.0.0.1:8080".to_string());
33    let mint = std::env::var("KEY").expect("KEY env var required (token mint address)");
34
35    let client = HyperStackClient::<PumpToken>::new(url, "PumpToken/kv").with_key(&mint);
36
37    let store = client.connect().await?;
38
39    println!("watching trades for token {}...\n", mint);
40
41    let mut updates = store.subscribe();
42    let mut trade_history: VecDeque<TradeInfo> = VecDeque::with_capacity(100);
43
44    loop {
45        tokio::select! {
46            Ok((_key, token)) = updates.recv() => {
47                if let Some(trade) = token.last_trade {
48                    trade_history.push_back(trade.clone());
49                    if trade_history.len() > 100 {
50                        trade_history.pop_front();
51                    }
52
53                    println!("[{}] {} | {}... | {:.4} SOL (total: {} trades)",
54                        Utc::now().format("%H:%M:%S"),
55                        trade.direction,
56                        &trade.wallet[..8],
57                        trade.amount_sol,
58                        trade_history.len());
59                }
60            }
61            _ = sleep(Duration::from_secs(60)) => {
62                println!("No trades for 60s...");
63            }
64        }
65    }
66}