1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
use std::sync::Arc;
use crate::client::HttpCore;
use crate::error::Result;
use crate::types::*;
/// KOL wallet tracking endpoints — feed, leaderboard, coordination, profiles, alerts.
#[derive(Debug, Clone)]
pub struct Kol {
pub(crate) core: Arc<HttpCore>,
}
impl Kol {
/// Live feed of trades made by tracked KOL wallets.
pub async fn feed(&self, params: &KolFeedParams) -> Result<KolFeedResponse> {
self.core.get("/kol/feed", params).await
}
/// KOL PnL leaderboard ranked by realized profit.
pub async fn leaderboard(
&self,
params: &KolLeaderboardParams,
) -> Result<KolLeaderboardResponse> {
self.core.get("/kol/leaderboard", params).await
}
/// Full profile for a single KOL wallet.
pub async fn wallet(
&self,
wallet: &str,
params: &KolWalletParams,
) -> Result<KolWalletProfile> {
self.core.get(&format!("/kol/{}", wallet), params).await
}
/// Detect tokens where multiple KOLs are buying simultaneously.
pub async fn coordination(
&self,
params: &KolCoordinationParams,
) -> Result<KolCoordinationResponse> {
self.core.get("/kol/coordination", params).await
}
/// KOL buy/sell activity for a specific token mint.
pub async fn token(&self, mint: &str) -> Result<KolTokenActivity> {
self.core
.get(&format!("/kol/tokens/{}", mint), &())
.await
}
/// KOL affinity pairs — wallets that frequently co-trade the same tokens.
pub async fn pairs(&self, params: &KolPairsParams) -> Result<KolPairsResponse> {
self.core.get("/kol/pairs", params).await
}
/// KOL entry/exit timing profile — hold duration, exit speed, activity hours.
pub async fn timing(
&self,
wallet: &str,
params: &KolTimingParams,
) -> Result<KolTimingResponse> {
self.core
.get(&format!("/kol/{}/timing", wallet), params)
.await
}
/// Tokens with accelerating KOL buy interest.
pub async fn hot_tokens(
&self,
params: &KolHotTokensParams,
) -> Result<KolHotTokensResponse> {
self.core.get("/kol/tokens/hot", params).await
}
/// Deep per-wallet PnL breakdown — equity curve, profit factor, max drawdown.
pub async fn pnl(&self, wallet: &str, params: &KolPnlParams) -> Result<KolPnlResponse> {
self.core
.get(&format!("/kol/{}/pnl", wallet), params)
.await
}
/// Tokens ranked by KOL buy volume across multiple time windows.
pub async fn trending_tokens(
&self,
params: &KolTrendingParams,
) -> Result<KolTrendingResponse> {
self.core.get("/kol/tokens/trending", params).await
}
/// Ranked list of KOL buyers for a token, ordered by first-buy timestamp.
pub async fn token_entry_order(
&self,
mint: &str,
params: &KolEntryOrderParams,
) -> Result<KolEntryOrderResponse> {
self.core
.get(
&format!("/kol/tokens/{}/entry-order", mint),
params,
)
.await
}
/// Side-by-side comparison of 2–5 KOL wallets.
/// Tier limits: BASIC=2, PRO=4, ULTRA=5.
pub async fn compare(&self, params: &KolCompareParams) -> Result<KolCompareResponse> {
let wallets_joined = params.wallets.join(",");
self.core
.get("/kol/compare", &[("wallets", wallets_joined)])
.await
}
/// Live feed of notable KOL events — consensus clusters, fresh-launch buys, heating-up wallets.
pub async fn alerts(&self, params: &KolAlertsParams) -> Result<KolAlertsResponse> {
let mut query: Vec<(&str, String)> = Vec::new();
if let Some(window) = ¶ms.window {
query.push(("window", window.clone()));
}
if let Some(limit) = params.limit {
query.push(("limit", limit.to_string()));
}
if let Some(types) = ¶ms.types {
if !types.is_empty() {
query.push(("types", types.join(",")));
}
}
self.core.get("/kol/alerts/recent", &query).await
}
/// Recent first-KOL-touch events on tokens — every time a tracked KOL was the first
/// to buy a given mint. Filterable by scout tier (S/A/B/C from `mv_kol_scout_score`),
/// KOL winrate, token age, mint suffix, etc.
///
/// Backtest: top scouts attract ≥3 follow-on KOLs within 4h ~50% of the time vs ~14% baseline.
/// Median lead time before second KOL is 12s — for trading this signal, use the
/// `kol:first_touches` WebSocket channel rather than polling.
pub async fn first_touches(
&self,
params: &FirstTouchesParams,
) -> Result<FirstTouchesResponse> {
self.core.get("/kol/first-touches", params).await
}
}