kobe_client/
types.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3
4/// Staker rewards response from the API
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct StakerRewardsResponse {
7    pub rewards: Vec<StakerReward>,
8    pub total: Option<u64>,
9}
10
11/// Individual staker reward entry
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct StakerReward {
14    /// The public key of the stake account
15    pub stake_account: String,
16
17    /// The stake authority
18    pub stake_authority: String,
19
20    /// The withdraw authority
21    pub withdraw_authority: String,
22
23    /// Epoch when the reward was earned
24    pub epoch: u64,
25
26    /// MEV rewards in lamports
27    pub mev_rewards: u64,
28
29    /// Priority fee rewards in lamports
30    pub priority_fee_rewards: Option<u64>,
31
32    /// Whether MEV rewards have been claimed
33    pub mev_claimed: bool,
34
35    /// Whether priority fee rewards have been claimed
36    pub priority_fee_claimed: Option<bool>,
37
38    /// Validator vote account
39    pub vote_account: String,
40}
41
42/// Validator rewards response
43#[derive(Debug, Clone, Serialize, Deserialize)]
44pub struct ValidatorRewardsResponse {
45    pub validators: Vec<ValidatorReward>,
46}
47
48/// Validator reward entry
49#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct ValidatorReward {
51    /// Validator vote account public key
52    pub vote_account: String,
53
54    /// Epoch
55    pub epoch: u64,
56
57    /// MEV commission in basis points (10000 = 100%)
58    pub mev_commission_bps: u16,
59
60    /// Total MEV rewards in lamports
61    pub mev_rewards: u64,
62
63    /// Priority fee commission in basis points
64    pub priority_fee_commission_bps: Option<u16>,
65
66    /// Total priority fee rewards in lamports
67    pub priority_fee_rewards: Option<u64>,
68
69    /// Number of stakers
70    pub num_stakers: Option<u64>,
71
72    /// Total active stake
73    pub active_stake: Option<u64>,
74}
75
76// ============================================================================
77// Stake Pool API Types
78// ============================================================================
79
80/// Response for validators endpoint
81#[derive(Debug, Clone, Serialize, Deserialize)]
82pub struct ValidatorsResponse {
83    pub validators: Vec<ValidatorInfo>,
84}
85
86/// Validator information
87#[derive(Debug, Clone, Serialize, Deserialize)]
88pub struct ValidatorInfo {
89    /// Validator vote account
90    pub vote_account: String,
91
92    /// MEV commission in basis points
93    pub mev_commission_bps: u16,
94
95    /// MEV rewards for the epoch (lamports)
96    pub mev_rewards: u64,
97
98    /// Priority fee commission in basis points
99    pub priority_fee_commission_bps: Option<u16>,
100
101    /// Priority fee rewards (lamports)
102    pub priority_fee_rewards: Option<u64>,
103
104    /// Whether the validator is running Jito
105    pub running_jito: bool,
106
107    /// Active stake amount (lamports)
108    pub active_stake: u64,
109}
110
111/// Historical validator data
112#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct ValidatorHistory {
114    /// Epoch
115    pub epoch: u64,
116
117    /// MEV commission in basis points
118    pub mev_commission_bps: u16,
119
120    /// MEV rewards (lamports)
121    pub mev_rewards: u64,
122
123    /// Priority fee commission in basis points
124    pub priority_fee_commission_bps: Option<u16>,
125
126    /// Priority fee rewards (lamports)
127    pub priority_fee_rewards: Option<u64>,
128}
129
130/// MEV rewards network statistics
131#[derive(Debug, Clone, Serialize, Deserialize)]
132pub struct MevRewards {
133    /// Epoch number
134    pub epoch: u64,
135
136    /// Total network MEV in lamports
137    pub total_network_mev_lamports: u64,
138
139    /// Jito stake weight in lamports
140    pub jito_stake_weight_lamports: u64,
141
142    /// MEV reward per lamport staked
143    pub mev_reward_per_lamport: f64,
144}
145
146/// Daily MEV tips data
147#[derive(Debug, Clone, Serialize, Deserialize)]
148pub struct DailyMevTips {
149    /// Date of the tips
150    pub day: DateTime<Utc>,
151
152    /// Number of MEV tips
153    pub count_mev_tips: u64,
154
155    /// Jito tips amount (SOL)
156    pub jito_tips: f64,
157
158    /// Number of unique tippers
159    pub tippers: u64,
160
161    /// Validator tips amount (SOL)
162    pub validator_tips: f64,
163}
164
165/// Jito stake over time data
166#[derive(Debug, Clone, Serialize, Deserialize)]
167pub struct JitoStakeOverTime {
168    /// Map of epoch to stake ratio
169    pub stake_ratio_over_time: std::collections::HashMap<String, f64>,
170}
171
172/// MEV commission average over time
173#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct MevCommissionAverageOverTime {
175    /// Aggregated MEV rewards
176    pub aggregated_mev_rewards: u64,
177
178    /// MEV rewards time series
179    pub mev_rewards: Vec<TimeSeriesData<u64>>,
180
181    /// Total value locked time series
182    pub tvl: Vec<TimeSeriesData<u64>>,
183
184    /// APY time series
185    pub apy: Vec<TimeSeriesData<f64>>,
186
187    /// Number of validators time series
188    pub num_validators: Vec<TimeSeriesData<u64>>,
189
190    /// JitoSOL supply time series
191    pub supply: Vec<TimeSeriesData<f64>>,
192}
193
194/// Time series data point
195#[derive(Debug, Clone, Serialize, Deserialize)]
196pub struct TimeSeriesData<T> {
197    /// Data value
198    pub data: T,
199
200    /// Timestamp
201    pub date: DateTime<Utc>,
202}
203
204/// JitoSOL to SOL ratio data
205#[derive(Debug, Clone, Serialize, Deserialize)]
206pub struct JitoSolRatio {
207    /// Time series of ratio data
208    pub ratios: Vec<TimeSeriesData<f64>>,
209}
210
211/// Stake pool statistics
212#[derive(Debug, Clone, Serialize, Deserialize)]
213pub struct StakePoolStats {
214    /// Epoch
215    pub epoch: u64,
216
217    /// Total stake pool value (lamports)
218    pub total_lamports: u64,
219
220    /// JitoSOL supply
221    pub jitosol_supply: f64,
222
223    /// Current exchange ratio
224    pub exchange_ratio: f64,
225
226    /// Annual percentage yield
227    pub apy: f64,
228
229    /// Number of validators
230    pub num_validators: u64,
231
232    /// Total MEV earned
233    pub total_mev_earned: u64,
234}
235
236// ============================================================================
237// Request Types
238// ============================================================================
239
240/// Request parameters for epoch-based queries
241#[derive(Debug, Clone, Serialize, Deserialize)]
242pub struct EpochRequest {
243    /// Epoch number
244    pub epoch: u64,
245}
246
247/// Range filter for time-based queries
248#[derive(Debug, Clone, Serialize, Deserialize)]
249pub struct RangeFilter {
250    /// Start time (ISO 8601 format)
251    pub start: DateTime<Utc>,
252
253    /// End time (ISO 8601 format)
254    pub end: DateTime<Utc>,
255}
256
257/// Request with range filter
258#[derive(Debug, Clone, Serialize, Deserialize)]
259pub struct RangeRequest {
260    /// Time range filter
261    pub range_filter: RangeFilter,
262}
263
264// ============================================================================
265// StakeNet API Types (on-chain data)
266// ============================================================================
267
268/// Validator history account data
269#[derive(Debug, Clone, Serialize, Deserialize)]
270pub struct ValidatorHistoryAccount {
271    /// Validator vote account
272    pub vote_account: String,
273
274    /// Historical entries
275    pub history: Vec<ValidatorHistoryEntry>,
276}
277
278/// Single validator history entry for an epoch
279#[derive(Debug, Clone, Serialize, Deserialize)]
280pub struct ValidatorHistoryEntry {
281    /// Epoch
282    pub epoch: u64,
283
284    /// Vote credits earned
285    pub vote_credits: Option<u32>,
286
287    /// Validator commission
288    pub commission: Option<u8>,
289
290    /// MEV commission in basis points
291    pub mev_commission_bps: Option<u16>,
292
293    /// Validator version
294    pub version: Option<String>,
295
296    /// Client type
297    pub client_type: Option<String>,
298
299    /// Active stake
300    pub active_stake: Option<u64>,
301
302    /// Stake rank
303    pub stake_rank: Option<u32>,
304
305    /// Whether validator is in superminority
306    pub is_superminority: Option<bool>,
307
308    /// IP address
309    pub ip_address: Option<String>,
310}
311
312/// Steward configuration
313#[derive(Debug, Clone, Serialize, Deserialize)]
314pub struct StewardConfig {
315    /// Stake pool address
316    pub stake_pool: String,
317
318    /// Authority
319    pub authority: String,
320
321    /// Scoring parameters
322    pub scoring_params: ScoringParams,
323}
324
325/// Scoring parameters for validator selection
326#[derive(Debug, Clone, Serialize, Deserialize)]
327pub struct ScoringParams {
328    /// Minimum vote credits
329    pub min_vote_credits: u32,
330
331    /// Maximum commission
332    pub max_commission: u8,
333
334    /// Performance weight
335    pub performance_weight: f64,
336
337    /// Commission weight
338    pub commission_weight: f64,
339
340    /// Stake concentration limit
341    pub stake_concentration_limit: f64,
342}
343
344// ============================================================================
345// Common Types
346// ============================================================================
347
348/// Query parameters for paginated requests
349#[derive(Debug, Clone, Default)]
350pub struct QueryParams {
351    /// Limit number of results
352    pub limit: Option<u32>,
353
354    /// Offset for pagination
355    pub offset: Option<u32>,
356
357    /// Epoch filter
358    pub epoch: Option<u64>,
359
360    /// Sort order (asc/desc)
361    pub sort_order: Option<String>,
362}
363
364impl QueryParams {
365    /// Create new query params with limit
366    pub fn with_limit(limit: u32) -> Self {
367        Self {
368            limit: Some(limit),
369            ..Default::default()
370        }
371    }
372
373    /// Create new query params with epoch
374    pub fn with_epoch(epoch: u64) -> Self {
375        Self {
376            epoch: Some(epoch),
377            ..Default::default()
378        }
379    }
380
381    /// Set limit
382    pub fn limit(mut self, limit: u32) -> Self {
383        self.limit = Some(limit);
384        self
385    }
386
387    /// Set offset
388    pub fn offset(mut self, offset: u32) -> Self {
389        self.offset = Some(offset);
390        self
391    }
392
393    /// Set epoch
394    pub fn epoch(mut self, epoch: u64) -> Self {
395        self.epoch = Some(epoch);
396        self
397    }
398
399    /// Convert to query string
400    pub fn to_query_string(&self) -> String {
401        let mut params = Vec::new();
402
403        if let Some(limit) = self.limit {
404            params.push(format!("limit={}", limit));
405        }
406        if let Some(offset) = self.offset {
407            params.push(format!("offset={}", offset));
408        }
409        if let Some(epoch) = self.epoch {
410            params.push(format!("epoch={}", epoch));
411        }
412        if let Some(ref sort_order) = self.sort_order {
413            params.push(format!("sort_order={}", sort_order));
414        }
415
416        if params.is_empty() {
417            String::new()
418        } else {
419            format!("?{}", params.join("&"))
420        }
421    }
422}
423
424// ============================================================================
425// Error Response Types
426// ============================================================================
427
428/// API error response structure
429#[derive(Debug, Clone, Serialize, Deserialize)]
430pub struct ApiErrorResponse {
431    pub error: String,
432    pub message: Option<String>,
433    pub status_code: Option<u16>,
434}