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