1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct StakerRewardsResponse {
7 pub rewards: Vec<StakerReward>,
8 pub total: Option<u64>,
9}
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct StakerReward {
14 pub stake_account: String,
16
17 pub stake_authority: String,
19
20 pub withdraw_authority: String,
22
23 pub epoch: u64,
25
26 pub mev_rewards: u64,
28
29 pub priority_fee_rewards: Option<u64>,
31
32 pub mev_claimed: bool,
34
35 pub priority_fee_claimed: Option<bool>,
37
38 pub vote_account: String,
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
44pub struct ValidatorRewardsResponse {
45 pub validators: Vec<ValidatorReward>,
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct ValidatorReward {
51 pub vote_account: String,
53
54 pub epoch: u64,
56
57 pub mev_commission_bps: u16,
59
60 pub mev_rewards: u64,
62
63 pub priority_fee_commission_bps: Option<u16>,
65
66 pub priority_fee_rewards: Option<u64>,
68
69 pub num_stakers: Option<u64>,
71
72 pub active_stake: Option<u64>,
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct ValidatorsResponse {
79 pub validators: Vec<ValidatorInfo>,
80}
81
82#[derive(Debug, Clone, Serialize, Deserialize)]
84pub struct ValidatorInfo {
85 pub vote_account: String,
87
88 pub mev_commission_bps: Option<u16>,
90
91 pub mev_rewards: Option<u64>,
93
94 pub priority_fee_commission_bps: Option<u16>,
96
97 pub priority_fee_rewards: Option<u64>,
99
100 pub running_jito: bool,
102
103 pub running_bam: Option<bool>,
105
106 pub active_stake: u64,
108}
109
110#[derive(Debug, Clone, Serialize, Deserialize)]
112pub struct ValidatorByVoteAccount {
113 pub epoch: u64,
115
116 pub mev_commission_bps: u16,
118
119 pub mev_rewards: u64,
121
122 pub priority_fee_commission_bps: u16,
124
125 pub priority_fee_rewards: u64,
127}
128
129#[derive(Debug, Clone, Serialize, Deserialize)]
131pub struct MevRewards {
132 pub epoch: u64,
134
135 pub total_network_mev_lamports: u64,
137
138 pub jito_stake_weight_lamports: u64,
140
141 pub mev_reward_per_lamport: f64,
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct DailyMevRewards {
148 pub day: DateTime<Utc>,
150
151 pub count_mev_tips: u64,
153
154 pub jito_tips: f64,
156
157 pub tippers: u64,
159
160 pub validator_tips: f64,
162}
163
164#[derive(Debug, Clone, Serialize, Deserialize)]
166pub struct JitoStakeOverTime {
167 pub stake_ratio_over_time: std::collections::HashMap<String, f64>,
169}
170
171#[derive(Debug, Clone, Serialize, Deserialize)]
173pub struct MevCommissionAverageOverTime {
174 pub aggregated_mev_rewards: u64,
176
177 pub mev_rewards: Vec<TimeSeriesData<u64>>,
179
180 pub tvl: Vec<TimeSeriesData<u64>>,
182
183 pub apy: Vec<TimeSeriesData<f64>>,
185
186 pub num_validators: Vec<TimeSeriesData<u64>>,
188
189 pub supply: Vec<TimeSeriesData<f64>>,
191}
192
193#[derive(Debug, Clone, Serialize, Deserialize)]
195pub struct TimeSeriesData<T> {
196 pub data: T,
198
199 pub date: DateTime<Utc>,
201}
202
203#[derive(Debug, Clone, Serialize, Deserialize)]
205pub struct JitoSolRatio {
206 pub ratios: Vec<TimeSeriesData<f64>>,
208}
209
210#[derive(Debug, Clone, Serialize, Deserialize)]
212pub struct StakePoolStats {
213 pub aggregated_mev_rewards: u64,
215
216 pub mev_rewards: Vec<TimeSeriesData<u64>>,
218
219 pub tvl: Vec<TimeSeriesData<u64>>,
221
222 pub apy: Vec<TimeSeriesData<f64>>,
224
225 pub num_validators: Vec<TimeSeriesData<u64>>,
227
228 pub supply: Vec<TimeSeriesData<f64>>,
230}
231
232#[derive(Debug, Clone, Serialize, Deserialize)]
238pub struct EpochRequest {
239 pub epoch: u64,
241}
242
243#[derive(Debug, Clone, Serialize, Deserialize)]
245pub struct RangeFilter {
246 pub start: DateTime<Utc>,
248
249 pub end: DateTime<Utc>,
251}
252
253#[derive(Debug, Clone, Serialize, Deserialize)]
255pub struct RangeRequest {
256 pub range_filter: RangeFilter,
258}
259
260#[derive(Debug, Clone, Serialize, Deserialize)]
262pub struct SortBy {
263 pub field: String,
265
266 pub order: String,
268}
269
270impl Default for SortBy {
271 fn default() -> Self {
272 Self {
273 field: "BlockTime".to_string(),
274 order: "Asc".to_string(),
275 }
276 }
277}
278
279#[derive(Debug, Clone, Serialize, Deserialize, Default)]
281pub struct StakePoolStatsRequest {
282 #[serde(skip_serializing_if = "Option::is_none")]
284 pub bucket_type: Option<String>,
285
286 #[serde(skip_serializing_if = "Option::is_none")]
288 pub range_filter: Option<RangeFilter>,
289
290 #[serde(skip_serializing_if = "Option::is_none")]
292 pub sort_by: Option<SortBy>,
293}
294
295impl StakePoolStatsRequest {
296 pub fn new() -> Self {
298 Self::default()
299 }
300
301 pub fn with_bucket_type(mut self, bucket_type: impl Into<String>) -> Self {
303 self.bucket_type = Some(bucket_type.into());
304 self
305 }
306
307 pub fn with_range_filter(mut self, start: DateTime<Utc>, end: DateTime<Utc>) -> Self {
309 self.range_filter = Some(RangeFilter { start, end });
310 self
311 }
312
313 pub fn with_sort_by(mut self, field: impl Into<String>, order: impl Into<String>) -> Self {
315 self.sort_by = Some(SortBy {
316 field: field.into(),
317 order: order.into(),
318 });
319 self
320 }
321
322 pub fn sort_asc(mut self) -> Self {
324 if let Some(ref mut sort) = self.sort_by {
325 sort.order = "Asc".to_string();
326 } else {
327 self.sort_by = Some(SortBy {
328 field: "BlockTime".to_string(),
329 order: "Asc".to_string(),
330 });
331 }
332 self
333 }
334
335 pub fn sort_desc(mut self) -> Self {
337 if let Some(ref mut sort) = self.sort_by {
338 sort.order = "Desc".to_string();
339 } else {
340 self.sort_by = Some(SortBy {
341 field: "BlockTime".to_string(),
342 order: "Desc".to_string(),
343 });
344 }
345 self
346 }
347}
348
349#[derive(Debug, Clone, Serialize, Deserialize)]
351pub struct ValidatorHistoryAccount {
352 pub vote_account: String,
354
355 pub history: Vec<ValidatorHistoryEntry>,
357}
358
359#[derive(Debug, Clone, Serialize, Deserialize)]
361pub struct ValidatorHistoryEntry {
362 pub epoch: u64,
364
365 pub vote_credits: Option<u32>,
367
368 pub commission: Option<u8>,
370
371 pub mev_commission_bps: Option<u16>,
373
374 pub version: Option<String>,
376
377 pub client_type: Option<String>,
379
380 pub active_stake: Option<u64>,
382
383 pub stake_rank: Option<u32>,
385
386 pub is_superminority: Option<bool>,
388
389 pub ip_address: Option<String>,
391}
392
393#[derive(Debug, Clone, Serialize, Deserialize)]
395pub struct StewardConfig {
396 pub stake_pool: String,
398
399 pub authority: String,
401
402 pub scoring_params: ScoringParams,
404}
405
406#[derive(Debug, Clone, Serialize, Deserialize)]
408pub struct ScoringParams {
409 pub min_vote_credits: u32,
411
412 pub max_commission: u8,
414
415 pub performance_weight: f64,
417
418 pub commission_weight: f64,
420
421 pub stake_concentration_limit: f64,
423}
424
425#[derive(Debug, Clone, Default)]
431pub struct QueryParams {
432 pub limit: Option<u32>,
434
435 pub offset: Option<u32>,
437
438 pub epoch: Option<u64>,
440
441 pub sort_order: Option<String>,
443}
444
445impl QueryParams {
446 pub fn with_limit(limit: u32) -> Self {
448 Self {
449 limit: Some(limit),
450 ..Default::default()
451 }
452 }
453
454 pub fn with_epoch(epoch: u64) -> Self {
456 Self {
457 epoch: Some(epoch),
458 ..Default::default()
459 }
460 }
461
462 pub fn limit(mut self, limit: u32) -> Self {
464 self.limit = Some(limit);
465 self
466 }
467
468 pub fn offset(mut self, offset: u32) -> Self {
470 self.offset = Some(offset);
471 self
472 }
473
474 pub fn epoch(mut self, epoch: u64) -> Self {
476 self.epoch = Some(epoch);
477 self
478 }
479
480 pub fn to_query_string(&self) -> String {
482 let mut params = Vec::new();
483
484 if let Some(limit) = self.limit {
485 params.push(format!("limit={}", limit));
486 }
487 if let Some(offset) = self.offset {
488 params.push(format!("offset={}", offset));
489 }
490 if let Some(epoch) = self.epoch {
491 params.push(format!("epoch={}", epoch));
492 }
493 if let Some(ref sort_order) = self.sort_order {
494 params.push(format!("sort_order={}", sort_order));
495 }
496
497 if params.is_empty() {
498 String::new()
499 } else {
500 format!("?{}", params.join("&"))
501 }
502 }
503}
504
505#[derive(Debug, Clone, Serialize, Deserialize)]
511pub struct ApiErrorResponse {
512 pub error: String,
513 pub message: Option<String>,
514 pub status_code: Option<u16>,
515}