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    /// Active stake
90    pub active_stake: Option<u64>,
91
92    /// Commission number
93    pub commission: Option<u8>,
94
95    /// Consensus mods score
96    pub consensus_mods_score: Option<i8>,
97
98    /// Data center concentration score
99    pub data_center_concentration_score: Option<i64>,
100
101    /// Delinquent
102    pub delinquent: Option<bool>,
103
104    /// Epoch number
105    pub epoch: Option<u64>,
106
107    /// Epoch credits
108    pub epoch_credits: Option<u64>,
109
110    /// Identity account
111    pub identity_account: Option<String>,
112
113    /// MEV Commission BPS
114    pub mev_commission_bps: Option<u16>,
115
116    /// MEV revenue lamports
117    pub mev_revenue_lamports: Option<u64>,
118
119    /// Priority fee commission bps
120    pub priority_fee_commission_bps: Option<u16>,
121
122    /// Priority fee revenue lamports
123    pub priority_fee_revenue_lamports: Option<u64>,
124
125    /// Name
126    pub name: Option<String>,
127
128    /// Published information score
129    pub published_information_score: Option<i64>,
130
131    /// Root distance score
132    pub root_distance_score: Option<i64>,
133
134    /// Whether or not running Jito client
135    pub running_jito: bool,
136
137    /// Whether or not running BAM client
138    pub running_bam: Option<bool>,
139
140    /// Software version
141    pub software_version: Option<String>,
142
143    /// Software version score
144    pub software_version_score: Option<i64>,
145
146    /// Skipped slot percent
147    pub skipped_slot_percent: Option<String>,
148
149    /// Skipped slot score
150    pub skipped_slot_score: Option<i64>,
151
152    /// Skipped slots
153    pub skipped_slots: Option<u64>,
154
155    /// Stake concentration score
156    pub stake_concentration_score: Option<i64>,
157
158    /// Stake percent
159    pub stake_percent: Option<f64>,
160
161    /// Target pool is the pool this cranker is managing
162    pub target_pool_active_lamports: Option<u64>,
163
164    /// Target pool transient lamports
165    pub target_pool_transient_lamports: Option<u64>,
166
167    /// Target pool staked
168    pub target_pool_staked: Option<bool>,
169
170    // Timestamp
171    // #[serde(with = "ts_seconds_option")]
172    // pub timestamp: Option<DateTime<Utc>>,
173    /// Vote account
174    pub vote_account: String,
175
176    /// Vote credit proportion
177    pub vote_credit_proportion: Option<f64>,
178
179    /// WWW URL
180    pub www_url: Option<String>,
181
182    /// Inflation lamports
183    pub inflation_rewards_lamports: Option<u64>,
184}
185
186/// Historical validator data
187#[derive(Debug, Clone, Serialize, Deserialize)]
188pub struct ValidatorHistory {
189    /// Epoch
190    pub epoch: u64,
191
192    /// MEV commission in basis points
193    pub mev_commission_bps: u16,
194
195    /// MEV rewards (lamports)
196    pub mev_rewards: u64,
197
198    /// Priority fee commission in basis points
199    pub priority_fee_commission_bps: Option<u16>,
200
201    /// Priority fee rewards (lamports)
202    pub priority_fee_rewards: Option<u64>,
203}
204
205/// MEV rewards network statistics
206#[derive(Debug, Clone, Serialize, Deserialize)]
207pub struct MevRewards {
208    /// Epoch number
209    pub epoch: u64,
210
211    /// Total network MEV in lamports
212    pub total_network_mev_lamports: u64,
213
214    /// Jito stake weight in lamports
215    pub jito_stake_weight_lamports: u64,
216
217    /// MEV reward per lamport staked
218    pub mev_reward_per_lamport: f64,
219}
220
221/// Daily MEV tips data
222#[derive(Debug, Clone, Serialize, Deserialize)]
223pub struct DailyMevTips {
224    /// Date of the tips
225    pub day: DateTime<Utc>,
226
227    /// Number of MEV tips
228    pub count_mev_tips: u64,
229
230    /// Jito tips amount (SOL)
231    pub jito_tips: f64,
232
233    /// Number of unique tippers
234    pub tippers: u64,
235
236    /// Validator tips amount (SOL)
237    pub validator_tips: f64,
238}
239
240/// Jito stake over time data
241#[derive(Debug, Clone, Serialize, Deserialize)]
242pub struct JitoStakeOverTime {
243    /// Map of epoch to stake ratio
244    pub stake_ratio_over_time: std::collections::HashMap<String, f64>,
245}
246
247/// MEV commission average over time
248#[derive(Debug, Clone, Serialize, Deserialize)]
249pub struct MevCommissionAverageOverTime {
250    /// Aggregated MEV rewards
251    pub aggregated_mev_rewards: u64,
252
253    /// MEV rewards time series
254    pub mev_rewards: Vec<TimeSeriesData<u64>>,
255
256    /// Total value locked time series
257    pub tvl: Vec<TimeSeriesData<u64>>,
258
259    /// APY time series
260    pub apy: Vec<TimeSeriesData<f64>>,
261
262    /// Number of validators time series
263    pub num_validators: Vec<TimeSeriesData<u64>>,
264
265    /// JitoSOL supply time series
266    pub supply: Vec<TimeSeriesData<f64>>,
267}
268
269/// Time series data point
270#[derive(Debug, Clone, Serialize, Deserialize)]
271pub struct TimeSeriesData<T> {
272    /// Data value
273    pub data: T,
274
275    /// Timestamp
276    pub date: DateTime<Utc>,
277}
278
279/// JitoSOL to SOL ratio data
280#[derive(Debug, Clone, Serialize, Deserialize)]
281pub struct JitoSolRatio {
282    /// Time series of ratio data
283    pub ratios: Vec<TimeSeriesData<f64>>,
284}
285
286/// Stake pool statistics
287#[derive(Debug, Clone, Serialize, Deserialize)]
288pub struct StakePoolStats {
289    /// Epoch
290    pub epoch: u64,
291
292    /// Total stake pool value (lamports)
293    pub total_lamports: u64,
294
295    /// JitoSOL supply
296    pub jitosol_supply: f64,
297
298    /// Current exchange ratio
299    pub exchange_ratio: f64,
300
301    /// Annual percentage yield
302    pub apy: f64,
303
304    /// Number of validators
305    pub num_validators: u64,
306
307    /// Total MEV earned
308    pub total_mev_earned: u64,
309}
310
311// ============================================================================
312// Request Types
313// ============================================================================
314
315/// Request parameters for epoch-based queries
316#[derive(Debug, Clone, Serialize, Deserialize)]
317pub struct EpochRequest {
318    /// Epoch number
319    pub epoch: u64,
320}
321
322/// Range filter for time-based queries
323#[derive(Debug, Clone, Serialize, Deserialize)]
324pub struct RangeFilter {
325    /// Start time (ISO 8601 format)
326    pub start: DateTime<Utc>,
327
328    /// End time (ISO 8601 format)
329    pub end: DateTime<Utc>,
330}
331
332/// Request with range filter
333#[derive(Debug, Clone, Serialize, Deserialize)]
334pub struct RangeRequest {
335    /// Time range filter
336    pub range_filter: RangeFilter,
337}
338
339// ============================================================================
340// StakeNet API Types (on-chain data)
341// ============================================================================
342
343/// Validator history account data
344#[derive(Debug, Clone, Serialize, Deserialize)]
345pub struct ValidatorHistoryAccount {
346    /// Validator vote account
347    pub vote_account: String,
348
349    /// Historical entries
350    pub history: Vec<ValidatorHistoryEntry>,
351}
352
353/// Single validator history entry for an epoch
354#[derive(Debug, Clone, Serialize, Deserialize)]
355pub struct ValidatorHistoryEntry {
356    /// Epoch
357    pub epoch: u64,
358
359    /// Vote credits earned
360    pub vote_credits: Option<u32>,
361
362    /// Validator commission
363    pub commission: Option<u8>,
364
365    /// MEV commission in basis points
366    pub mev_commission_bps: Option<u16>,
367
368    /// Validator version
369    pub version: Option<String>,
370
371    /// Client type
372    pub client_type: Option<String>,
373
374    /// Active stake
375    pub active_stake: Option<u64>,
376
377    /// Stake rank
378    pub stake_rank: Option<u32>,
379
380    /// Whether validator is in superminority
381    pub is_superminority: Option<bool>,
382
383    /// IP address
384    pub ip_address: Option<String>,
385}
386
387/// Steward configuration
388#[derive(Debug, Clone, Serialize, Deserialize)]
389pub struct StewardConfig {
390    /// Stake pool address
391    pub stake_pool: String,
392
393    /// Authority
394    pub authority: String,
395
396    /// Scoring parameters
397    pub scoring_params: ScoringParams,
398}
399
400/// Scoring parameters for validator selection
401#[derive(Debug, Clone, Serialize, Deserialize)]
402pub struct ScoringParams {
403    /// Minimum vote credits
404    pub min_vote_credits: u32,
405
406    /// Maximum commission
407    pub max_commission: u8,
408
409    /// Performance weight
410    pub performance_weight: f64,
411
412    /// Commission weight
413    pub commission_weight: f64,
414
415    /// Stake concentration limit
416    pub stake_concentration_limit: f64,
417}
418
419// ============================================================================
420// Common Types
421// ============================================================================
422
423/// Query parameters for paginated requests
424#[derive(Debug, Clone, Default)]
425pub struct QueryParams {
426    /// Limit number of results
427    pub limit: Option<u32>,
428
429    /// Offset for pagination
430    pub offset: Option<u32>,
431
432    /// Epoch filter
433    pub epoch: Option<u64>,
434
435    /// Sort order (asc/desc)
436    pub sort_order: Option<String>,
437}
438
439impl QueryParams {
440    /// Create new query params with limit
441    pub fn with_limit(limit: u32) -> Self {
442        Self {
443            limit: Some(limit),
444            ..Default::default()
445        }
446    }
447
448    /// Create new query params with epoch
449    pub fn with_epoch(epoch: u64) -> Self {
450        Self {
451            epoch: Some(epoch),
452            ..Default::default()
453        }
454    }
455
456    /// Set limit
457    pub fn limit(mut self, limit: u32) -> Self {
458        self.limit = Some(limit);
459        self
460    }
461
462    /// Set offset
463    pub fn offset(mut self, offset: u32) -> Self {
464        self.offset = Some(offset);
465        self
466    }
467
468    /// Set epoch
469    pub fn epoch(mut self, epoch: u64) -> Self {
470        self.epoch = Some(epoch);
471        self
472    }
473
474    /// Convert to query string
475    pub fn to_query_string(&self) -> String {
476        let mut params = Vec::new();
477
478        if let Some(limit) = self.limit {
479            params.push(format!("limit={}", limit));
480        }
481        if let Some(offset) = self.offset {
482            params.push(format!("offset={}", offset));
483        }
484        if let Some(epoch) = self.epoch {
485            params.push(format!("epoch={}", epoch));
486        }
487        if let Some(ref sort_order) = self.sort_order {
488            params.push(format!("sort_order={}", sort_order));
489        }
490
491        if params.is_empty() {
492            String::new()
493        } else {
494            format!("?{}", params.join("&"))
495        }
496    }
497}
498
499// ============================================================================
500// Error Response Types
501// ============================================================================
502
503/// API error response structure
504#[derive(Debug, Clone, Serialize, Deserialize)]
505pub struct ApiErrorResponse {
506    pub error: String,
507    pub message: Option<String>,
508    pub status_code: Option<u16>,
509}