1use chrono::Utc;
2use hyperstack_sdk::HyperStackClient;
3use serde::{Deserialize, Serialize};
4use tokio::time::{sleep, Duration};
5
6#[derive(Serialize, Deserialize, Debug, Clone, Default)]
7struct PumpToken {
8 #[serde(skip_serializing_if = "Option::is_none")]
9 mint: Option<String>,
10 #[serde(skip_serializing_if = "Option::is_none")]
11 name: Option<String>,
12 #[serde(skip_serializing_if = "Option::is_none")]
13 symbol: Option<String>,
14 #[serde(skip_serializing_if = "Option::is_none")]
15 creator: Option<String>,
16 #[serde(skip_serializing_if = "Option::is_none")]
17 virtual_sol_reserves: Option<u64>,
18}
19
20#[tokio::main]
21async fn main() -> anyhow::Result<()> {
22 let url = std::env::args().nth(1).unwrap_or_else(|| "ws://127.0.0.1:8080".to_string());
23
24 let client = HyperStackClient::<PumpToken>::new(url, "PumpToken/list");
25
26 let store = client.connect().await?;
27
28 println!("watching for new pump.fun token launches...\n");
29
30 let mut updates = store.subscribe();
31
32 loop {
33 tokio::select! {
34 Ok((mint, token)) = updates.recv() => {
35 if token.name.is_some() || token.symbol.is_some() {
36 println!("\n[{}] new token launch", Utc::now().format("%Y-%m-%d %H:%M:%S UTC"));
37 println!("mint: {}", mint);
38 if let Some(name) = &token.name {
39 println!("name: {}", name);
40 }
41 if let Some(symbol) = &token.symbol {
42 println!("symbol: {}", symbol);
43 }
44 if let Some(creator) = &token.creator {
45 println!("creator: {}", creator);
46 }
47 if let Some(sol) = token.virtual_sol_reserves {
48 println!("initial liquidity: {:.4} SOL", sol as f64 / 1e9);
49 }
50 }
51 }
52 _ = sleep(Duration::from_secs(60)) => {
53 println!("No new launches for 60s...");
54 }
55 }
56 }
57}