pump_trades/
token_trades.rs1use 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().nth(1).unwrap_or_else(|| "ws://127.0.0.1:8080".to_string());
31 let mint = std::env::var("KEY").expect("KEY env var required (token mint address)");
32
33 let client = HyperStackClient::<PumpToken>::new(url, "PumpToken/kv")
34 .with_key(&mint);
35
36 let store = client.connect().await?;
37
38 println!("watching trades for token {}...\n", mint);
39
40 let mut updates = store.subscribe();
41 let mut trade_history: VecDeque<TradeInfo> = VecDeque::with_capacity(100);
42
43 loop {
44 tokio::select! {
45 Ok((_key, token)) = updates.recv() => {
46 if let Some(trade) = token.last_trade {
47 trade_history.push_back(trade.clone());
48 if trade_history.len() > 100 {
49 trade_history.pop_front();
50 }
51
52 println!("[{}] {} | {}... | {:.4} SOL (total: {} trades)",
53 Utc::now().format("%H:%M:%S"),
54 trade.direction,
55 &trade.wallet[..8],
56 trade.amount_sol,
57 trade_history.len());
58 }
59 }
60 _ = sleep(Duration::from_secs(60)) => {
61 println!("No trades for 60s...");
62 }
63 }
64 }
65}