1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3
4pub mod bam_epoch_metrics;
5pub mod bam_validators;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct StakerRewardsResponse {
10 pub rewards: Vec<StakerReward>,
11 pub total: Option<u64>,
12}
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct StakerReward {
17 pub stake_account: String,
19
20 pub stake_authority: String,
22
23 pub withdraw_authority: String,
25
26 pub epoch: u64,
28
29 pub mev_rewards: u64,
31
32 pub priority_fee_rewards: Option<u64>,
34
35 pub mev_claimed: bool,
37
38 pub priority_fee_claimed: Option<bool>,
40
41 pub vote_account: String,
43}
44
45#[derive(Debug, Clone, Serialize, Deserialize)]
47pub struct ValidatorRewardsResponse {
48 pub validators: Vec<ValidatorReward>,
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize)]
53pub struct ValidatorReward {
54 pub vote_account: String,
56
57 pub epoch: u64,
59
60 pub mev_commission_bps: u16,
62
63 pub mev_rewards: u64,
65
66 pub priority_fee_commission_bps: Option<u16>,
68
69 pub priority_fee_rewards: Option<u64>,
71
72 pub num_stakers: Option<u64>,
74
75 pub active_stake: Option<u64>,
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct ValidatorsResponse {
82 pub validators: Vec<ValidatorInfo>,
83}
84
85#[derive(Debug, Clone, Serialize, Deserialize)]
87pub struct ValidatorInfo {
88 pub vote_account: String,
90
91 pub mev_commission_bps: Option<u16>,
93
94 pub mev_rewards: Option<u64>,
96
97 pub priority_fee_commission_bps: Option<u16>,
99
100 pub priority_fee_rewards: Option<u64>,
102
103 pub running_jito: bool,
105
106 pub running_bam: Option<bool>,
108
109 pub active_stake: u64,
111}
112
113#[derive(Debug, Clone, Serialize, Deserialize)]
115pub struct ValidatorByVoteAccount {
116 pub epoch: u64,
118
119 pub mev_commission_bps: u16,
121
122 pub mev_rewards: u64,
124
125 pub priority_fee_commission_bps: u16,
127
128 pub priority_fee_rewards: u64,
130}
131
132#[derive(Debug, Clone, Serialize, Deserialize)]
134pub struct MevRewards {
135 pub epoch: u64,
137
138 pub total_network_mev_lamports: u64,
140
141 pub jito_stake_weight_lamports: u64,
143
144 pub mev_reward_per_lamport: f64,
146}
147
148#[derive(Debug, Clone, Serialize, Deserialize)]
150pub struct DailyMevRewards {
151 pub day: DateTime<Utc>,
153
154 pub count_mev_tips: u64,
156
157 pub jito_tips: f64,
159
160 pub tippers: u64,
162
163 pub validator_tips: f64,
165}
166
167#[derive(Debug, Clone, Serialize, Deserialize)]
169pub struct JitoStakeOverTime {
170 pub stake_ratio_over_time: std::collections::HashMap<String, f64>,
172}
173
174#[derive(Debug, Clone, Serialize, Deserialize)]
176pub struct MevCommissionAverageOverTime {
177 pub aggregated_mev_rewards: u64,
179
180 pub mev_rewards: Vec<TimeSeriesData<u64>>,
182
183 pub tvl: Vec<TimeSeriesData<u64>>,
185
186 pub apy: Vec<TimeSeriesData<f64>>,
188
189 pub num_validators: Vec<TimeSeriesData<u64>>,
191
192 pub supply: Vec<TimeSeriesData<f64>>,
194}
195
196#[derive(Debug, Clone, Serialize, Deserialize)]
198pub struct TimeSeriesData<T> {
199 pub data: T,
201
202 pub date: DateTime<Utc>,
204}
205
206#[derive(Debug, Clone, Serialize, Deserialize)]
208pub struct JitoSolRatio {
209 pub ratios: Vec<TimeSeriesData<f64>>,
211}
212
213#[derive(Debug, Clone, Serialize, Deserialize)]
215pub struct StakePoolStats {
216 pub aggregated_mev_rewards: u64,
218
219 pub mev_rewards: Vec<TimeSeriesData<u64>>,
221
222 pub tvl: Vec<TimeSeriesData<u64>>,
224
225 pub apy: Vec<TimeSeriesData<f64>>,
227
228 pub num_validators: Vec<TimeSeriesData<u64>>,
230
231 pub supply: Vec<TimeSeriesData<f64>>,
233}
234
235#[derive(Debug, Clone, Serialize, Deserialize)]
237pub struct BamDelegationBlacklistEntry {
238 pub vote_account: String,
240
241 pub added_epoch: u64,
243}
244
245#[derive(Debug, Clone, Serialize, Deserialize)]
251pub struct EpochRequest {
252 pub epoch: u64,
254}
255
256#[derive(Debug, Clone, Serialize, Deserialize)]
258pub struct RangeFilter {
259 pub start: DateTime<Utc>,
261
262 pub end: DateTime<Utc>,
264}
265
266#[derive(Debug, Clone, Serialize, Deserialize)]
268pub struct RangeRequest {
269 pub range_filter: RangeFilter,
271}
272
273#[derive(Debug, Clone, Serialize, Deserialize)]
275pub struct SortBy {
276 pub field: String,
278
279 pub order: String,
281}
282
283impl Default for SortBy {
284 fn default() -> Self {
285 Self {
286 field: "BlockTime".to_string(),
287 order: "Asc".to_string(),
288 }
289 }
290}
291
292#[derive(Debug, Clone, Serialize, Deserialize, Default)]
294pub struct StakePoolStatsRequest {
295 #[serde(skip_serializing_if = "Option::is_none")]
297 pub bucket_type: Option<String>,
298
299 #[serde(skip_serializing_if = "Option::is_none")]
301 pub range_filter: Option<RangeFilter>,
302
303 #[serde(skip_serializing_if = "Option::is_none")]
305 pub sort_by: Option<SortBy>,
306}
307
308impl StakePoolStatsRequest {
309 pub fn new() -> Self {
311 Self::default()
312 }
313
314 pub fn with_bucket_type(mut self, bucket_type: impl Into<String>) -> Self {
316 self.bucket_type = Some(bucket_type.into());
317 self
318 }
319
320 pub fn with_range_filter(mut self, start: DateTime<Utc>, end: DateTime<Utc>) -> Self {
322 self.range_filter = Some(RangeFilter { start, end });
323 self
324 }
325
326 pub fn with_sort_by(mut self, field: impl Into<String>, order: impl Into<String>) -> Self {
328 self.sort_by = Some(SortBy {
329 field: field.into(),
330 order: order.into(),
331 });
332 self
333 }
334
335 pub fn sort_asc(mut self) -> Self {
337 if let Some(ref mut sort) = self.sort_by {
338 sort.order = "Asc".to_string();
339 } else {
340 self.sort_by = Some(SortBy {
341 field: "BlockTime".to_string(),
342 order: "Asc".to_string(),
343 });
344 }
345 self
346 }
347
348 pub fn sort_desc(mut self) -> Self {
350 if let Some(ref mut sort) = self.sort_by {
351 sort.order = "Desc".to_string();
352 } else {
353 self.sort_by = Some(SortBy {
354 field: "BlockTime".to_string(),
355 order: "Desc".to_string(),
356 });
357 }
358 self
359 }
360}
361
362#[derive(Debug, Clone, Serialize, Deserialize)]
364pub struct ValidatorHistoryAccount {
365 pub vote_account: String,
367
368 pub history: Vec<ValidatorHistoryEntry>,
370}
371
372#[derive(Debug, Clone, Serialize, Deserialize)]
374pub struct ValidatorHistoryEntry {
375 pub epoch: u64,
377
378 pub vote_credits: Option<u32>,
380
381 pub commission: Option<u8>,
383
384 pub mev_commission_bps: Option<u16>,
386
387 pub version: Option<String>,
389
390 pub client_type: Option<String>,
392
393 pub active_stake: Option<u64>,
395
396 pub stake_rank: Option<u32>,
398
399 pub is_superminority: Option<bool>,
401
402 pub ip_address: Option<String>,
404}
405
406#[derive(Debug, Clone, Serialize, Deserialize)]
408pub struct StewardConfig {
409 pub stake_pool: String,
411
412 pub authority: String,
414
415 pub scoring_params: ScoringParams,
417}
418
419#[derive(Debug, Clone, Serialize, Deserialize)]
421pub struct ScoringParams {
422 pub min_vote_credits: u32,
424
425 pub max_commission: u8,
427
428 pub performance_weight: f64,
430
431 pub commission_weight: f64,
433
434 pub stake_concentration_limit: f64,
436}
437
438#[derive(Debug, Clone, Default)]
444pub struct QueryParams {
445 pub limit: Option<u32>,
447
448 pub offset: Option<u32>,
450
451 pub epoch: Option<u64>,
453
454 pub sort_order: Option<String>,
456}
457
458impl QueryParams {
459 pub fn with_limit(limit: u32) -> Self {
461 Self {
462 limit: Some(limit),
463 ..Default::default()
464 }
465 }
466
467 pub fn with_epoch(epoch: u64) -> Self {
469 Self {
470 epoch: Some(epoch),
471 ..Default::default()
472 }
473 }
474
475 pub fn limit(mut self, limit: u32) -> Self {
477 self.limit = Some(limit);
478 self
479 }
480
481 pub fn offset(mut self, offset: u32) -> Self {
483 self.offset = Some(offset);
484 self
485 }
486
487 pub fn epoch(mut self, epoch: u64) -> Self {
489 self.epoch = Some(epoch);
490 self
491 }
492
493 pub fn to_query_string(&self) -> String {
495 let mut params = Vec::new();
496
497 if let Some(limit) = self.limit {
498 params.push(format!("limit={}", limit));
499 }
500 if let Some(offset) = self.offset {
501 params.push(format!("offset={}", offset));
502 }
503 if let Some(epoch) = self.epoch {
504 params.push(format!("epoch={}", epoch));
505 }
506 if let Some(ref sort_order) = self.sort_order {
507 params.push(format!("sort_order={}", sort_order));
508 }
509
510 if params.is_empty() {
511 String::new()
512 } else {
513 format!("?{}", params.join("&"))
514 }
515 }
516}
517
518#[derive(Debug, Clone, Serialize, Deserialize)]
524pub struct ApiErrorResponse {
525 pub error: String,
526 pub message: Option<String>,
527 pub status_code: Option<u16>,
528}