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)]
234pub struct BamDelegationBlacklistEntry {
235 pub vote_account: String,
237
238 pub added_epoch: u64,
240}
241
242#[derive(Debug, Clone, Serialize, Deserialize)]
248pub struct EpochRequest {
249 pub epoch: u64,
251}
252
253#[derive(Debug, Clone, Serialize, Deserialize)]
255pub struct RangeFilter {
256 pub start: DateTime<Utc>,
258
259 pub end: DateTime<Utc>,
261}
262
263#[derive(Debug, Clone, Serialize, Deserialize)]
265pub struct RangeRequest {
266 pub range_filter: RangeFilter,
268}
269
270#[derive(Debug, Clone, Serialize, Deserialize)]
272pub struct SortBy {
273 pub field: String,
275
276 pub order: String,
278}
279
280impl Default for SortBy {
281 fn default() -> Self {
282 Self {
283 field: "BlockTime".to_string(),
284 order: "Asc".to_string(),
285 }
286 }
287}
288
289#[derive(Debug, Clone, Serialize, Deserialize, Default)]
291pub struct StakePoolStatsRequest {
292 #[serde(skip_serializing_if = "Option::is_none")]
294 pub bucket_type: Option<String>,
295
296 #[serde(skip_serializing_if = "Option::is_none")]
298 pub range_filter: Option<RangeFilter>,
299
300 #[serde(skip_serializing_if = "Option::is_none")]
302 pub sort_by: Option<SortBy>,
303}
304
305impl StakePoolStatsRequest {
306 pub fn new() -> Self {
308 Self::default()
309 }
310
311 pub fn with_bucket_type(mut self, bucket_type: impl Into<String>) -> Self {
313 self.bucket_type = Some(bucket_type.into());
314 self
315 }
316
317 pub fn with_range_filter(mut self, start: DateTime<Utc>, end: DateTime<Utc>) -> Self {
319 self.range_filter = Some(RangeFilter { start, end });
320 self
321 }
322
323 pub fn with_sort_by(mut self, field: impl Into<String>, order: impl Into<String>) -> Self {
325 self.sort_by = Some(SortBy {
326 field: field.into(),
327 order: order.into(),
328 });
329 self
330 }
331
332 pub fn sort_asc(mut self) -> Self {
334 if let Some(ref mut sort) = self.sort_by {
335 sort.order = "Asc".to_string();
336 } else {
337 self.sort_by = Some(SortBy {
338 field: "BlockTime".to_string(),
339 order: "Asc".to_string(),
340 });
341 }
342 self
343 }
344
345 pub fn sort_desc(mut self) -> Self {
347 if let Some(ref mut sort) = self.sort_by {
348 sort.order = "Desc".to_string();
349 } else {
350 self.sort_by = Some(SortBy {
351 field: "BlockTime".to_string(),
352 order: "Desc".to_string(),
353 });
354 }
355 self
356 }
357}
358
359#[derive(Debug, Clone, Serialize, Deserialize)]
361pub struct ValidatorHistoryAccount {
362 pub vote_account: String,
364
365 pub history: Vec<ValidatorHistoryEntry>,
367}
368
369#[derive(Debug, Clone, Serialize, Deserialize)]
371pub struct ValidatorHistoryEntry {
372 pub epoch: u64,
374
375 pub vote_credits: Option<u32>,
377
378 pub commission: Option<u8>,
380
381 pub mev_commission_bps: Option<u16>,
383
384 pub version: Option<String>,
386
387 pub client_type: Option<String>,
389
390 pub active_stake: Option<u64>,
392
393 pub stake_rank: Option<u32>,
395
396 pub is_superminority: Option<bool>,
398
399 pub ip_address: Option<String>,
401}
402
403#[derive(Debug, Clone, Serialize, Deserialize)]
405pub struct StewardConfig {
406 pub stake_pool: String,
408
409 pub authority: String,
411
412 pub scoring_params: ScoringParams,
414}
415
416#[derive(Debug, Clone, Serialize, Deserialize)]
418pub struct ScoringParams {
419 pub min_vote_credits: u32,
421
422 pub max_commission: u8,
424
425 pub performance_weight: f64,
427
428 pub commission_weight: f64,
430
431 pub stake_concentration_limit: f64,
433}
434
435#[derive(Debug, Clone, Default)]
441pub struct QueryParams {
442 pub limit: Option<u32>,
444
445 pub offset: Option<u32>,
447
448 pub epoch: Option<u64>,
450
451 pub sort_order: Option<String>,
453}
454
455impl QueryParams {
456 pub fn with_limit(limit: u32) -> Self {
458 Self {
459 limit: Some(limit),
460 ..Default::default()
461 }
462 }
463
464 pub fn with_epoch(epoch: u64) -> Self {
466 Self {
467 epoch: Some(epoch),
468 ..Default::default()
469 }
470 }
471
472 pub fn limit(mut self, limit: u32) -> Self {
474 self.limit = Some(limit);
475 self
476 }
477
478 pub fn offset(mut self, offset: u32) -> Self {
480 self.offset = Some(offset);
481 self
482 }
483
484 pub fn epoch(mut self, epoch: u64) -> Self {
486 self.epoch = Some(epoch);
487 self
488 }
489
490 pub fn to_query_string(&self) -> String {
492 let mut params = Vec::new();
493
494 if let Some(limit) = self.limit {
495 params.push(format!("limit={}", limit));
496 }
497 if let Some(offset) = self.offset {
498 params.push(format!("offset={}", offset));
499 }
500 if let Some(epoch) = self.epoch {
501 params.push(format!("epoch={}", epoch));
502 }
503 if let Some(ref sort_order) = self.sort_order {
504 params.push(format!("sort_order={}", sort_order));
505 }
506
507 if params.is_empty() {
508 String::new()
509 } else {
510 format!("?{}", params.join("&"))
511 }
512 }
513}
514
515#[derive(Debug, Clone, Serialize, Deserialize)]
521pub struct ApiErrorResponse {
522 pub error: String,
523 pub message: Option<String>,
524 pub status_code: Option<u16>,
525}