1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3
4pub mod bam_epoch_metrics;
5pub mod bam_validators;
6pub mod coinbase_balance;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct StakerRewardsResponse {
11 pub rewards: Vec<StakerReward>,
12 pub total: Option<u64>,
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct StakerReward {
18 pub stake_account: String,
20
21 pub stake_authority: String,
23
24 pub withdraw_authority: String,
26
27 pub epoch: u64,
29
30 pub mev_rewards: u64,
32
33 pub priority_fee_rewards: Option<u64>,
35
36 pub mev_claimed: bool,
38
39 pub priority_fee_claimed: Option<bool>,
41
42 pub vote_account: String,
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct ValidatorRewardsResponse {
49 pub validators: Vec<ValidatorReward>,
50}
51
52#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct ValidatorReward {
55 pub vote_account: String,
57
58 pub epoch: u64,
60
61 pub mev_commission_bps: u16,
63
64 pub mev_rewards: u64,
66
67 pub priority_fee_commission_bps: Option<u16>,
69
70 pub priority_fee_rewards: Option<u64>,
72
73 pub num_stakers: Option<u64>,
75
76 pub active_stake: Option<u64>,
78}
79
80#[derive(Debug, Clone, Serialize, Deserialize)]
82pub struct ValidatorsResponse {
83 pub validators: Vec<ValidatorInfo>,
84}
85
86#[derive(Debug, Clone, Serialize, Deserialize)]
88pub struct ValidatorInfo {
89 pub identity_account: Option<String>,
91
92 pub vote_account: String,
94
95 pub mev_commission_bps: Option<u16>,
97
98 pub mev_rewards: Option<u64>,
100
101 pub priority_fee_commission_bps: Option<u16>,
103
104 pub priority_fee_rewards: Option<u64>,
106
107 pub running_jito: bool,
109
110 pub running_bam: Option<bool>,
112
113 pub bam_connection_rate: Option<f64>,
115
116 pub active_stake: u64,
118}
119
120#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct ValidatorByVoteAccount {
123 pub epoch: u64,
125
126 pub mev_commission_bps: u16,
128
129 pub mev_rewards: u64,
131
132 pub priority_fee_commission_bps: u16,
134
135 pub priority_fee_rewards: u64,
137}
138
139#[derive(Debug, Clone, Serialize, Deserialize)]
141pub struct MevRewards {
142 pub epoch: u64,
144
145 pub total_network_mev_lamports: u64,
147
148 pub jito_stake_weight_lamports: u64,
150
151 pub mev_reward_per_lamport: f64,
153}
154
155#[derive(Debug, Clone, Serialize, Deserialize)]
157pub struct DailyMevRewards {
158 pub day: DateTime<Utc>,
160
161 pub count_mev_tips: u64,
163
164 pub jito_tips: f64,
166
167 pub tippers: u64,
169
170 pub validator_tips: f64,
172}
173
174#[derive(Debug, Clone, Serialize, Deserialize)]
176pub struct JitoStakeOverTime {
177 pub stake_ratio_over_time: std::collections::HashMap<String, f64>,
179}
180
181#[derive(Debug, Clone, Serialize, Deserialize)]
183pub struct MevCommissionAverageOverTime {
184 pub aggregated_mev_rewards: u64,
186
187 pub mev_rewards: Vec<TimeSeriesData<u64>>,
189
190 pub tvl: Vec<TimeSeriesData<u64>>,
192
193 pub apy: Vec<TimeSeriesData<f64>>,
195
196 pub num_validators: Vec<TimeSeriesData<u64>>,
198
199 pub supply: Vec<TimeSeriesData<f64>>,
201}
202
203#[derive(Debug, Clone, Serialize, Deserialize)]
205pub struct TimeSeriesData<T> {
206 pub data: T,
208
209 pub date: DateTime<Utc>,
211}
212
213#[derive(Debug, Clone, Serialize, Deserialize)]
215pub struct JitoSolRatio {
216 pub ratios: Vec<TimeSeriesData<f64>>,
218}
219
220#[derive(Debug, Clone, Serialize, Deserialize)]
222pub struct StakePoolStats {
223 pub aggregated_mev_rewards: u64,
225
226 pub mev_rewards: Vec<TimeSeriesData<u64>>,
228
229 pub tvl: Vec<TimeSeriesData<u64>>,
231
232 pub apy: Vec<TimeSeriesData<f64>>,
234
235 pub num_validators: Vec<TimeSeriesData<u64>>,
237
238 pub supply: Vec<TimeSeriesData<f64>>,
240}
241
242#[derive(Debug, Clone, Serialize, Deserialize)]
244pub struct BamDelegationBlacklistEntry {
245 pub vote_account: String,
247
248 pub added_epoch: u64,
250}
251
252#[derive(Debug, Clone, Serialize, Deserialize)]
258pub struct EpochRequest {
259 pub epoch: u64,
261}
262
263#[derive(Debug, Clone, Serialize, Deserialize)]
265pub struct RangeFilter {
266 pub start: DateTime<Utc>,
268
269 pub end: DateTime<Utc>,
271}
272
273#[derive(Debug, Clone, Serialize, Deserialize)]
275pub struct RangeRequest {
276 pub range_filter: RangeFilter,
278}
279
280#[derive(Debug, Clone, Serialize, Deserialize)]
282pub struct SortBy {
283 pub field: String,
285
286 pub order: String,
288}
289
290impl Default for SortBy {
291 fn default() -> Self {
292 Self {
293 field: "BlockTime".to_string(),
294 order: "Asc".to_string(),
295 }
296 }
297}
298
299#[derive(Debug, Clone, Serialize, Deserialize, Default)]
301pub struct StakePoolStatsRequest {
302 #[serde(skip_serializing_if = "Option::is_none")]
304 pub bucket_type: Option<String>,
305
306 #[serde(skip_serializing_if = "Option::is_none")]
308 pub range_filter: Option<RangeFilter>,
309
310 #[serde(skip_serializing_if = "Option::is_none")]
312 pub sort_by: Option<SortBy>,
313}
314
315impl StakePoolStatsRequest {
316 pub fn new() -> Self {
318 Self::default()
319 }
320
321 pub fn with_bucket_type(mut self, bucket_type: impl Into<String>) -> Self {
323 self.bucket_type = Some(bucket_type.into());
324 self
325 }
326
327 pub fn with_range_filter(mut self, start: DateTime<Utc>, end: DateTime<Utc>) -> Self {
329 self.range_filter = Some(RangeFilter { start, end });
330 self
331 }
332
333 pub fn with_sort_by(mut self, field: impl Into<String>, order: impl Into<String>) -> Self {
335 self.sort_by = Some(SortBy {
336 field: field.into(),
337 order: order.into(),
338 });
339 self
340 }
341
342 pub fn sort_asc(mut self) -> Self {
344 if let Some(ref mut sort) = self.sort_by {
345 sort.order = "Asc".to_string();
346 } else {
347 self.sort_by = Some(SortBy {
348 field: "BlockTime".to_string(),
349 order: "Asc".to_string(),
350 });
351 }
352 self
353 }
354
355 pub fn sort_desc(mut self) -> Self {
357 if let Some(ref mut sort) = self.sort_by {
358 sort.order = "Desc".to_string();
359 } else {
360 self.sort_by = Some(SortBy {
361 field: "BlockTime".to_string(),
362 order: "Desc".to_string(),
363 });
364 }
365 self
366 }
367}
368
369#[derive(Debug, Clone, Serialize, Deserialize)]
371pub struct ValidatorHistoryAccount {
372 pub vote_account: String,
374
375 pub history: Vec<ValidatorHistoryEntry>,
377}
378
379#[derive(Debug, Clone, Serialize, Deserialize)]
381pub struct ValidatorHistoryEntry {
382 pub epoch: u64,
384
385 pub vote_credits: Option<u32>,
387
388 pub commission: Option<u8>,
390
391 pub mev_commission_bps: Option<u16>,
393
394 pub version: Option<String>,
396
397 pub client_type: Option<String>,
399
400 pub active_stake: Option<u64>,
402
403 pub stake_rank: Option<u32>,
405
406 pub is_superminority: Option<bool>,
408
409 pub ip_address: Option<String>,
411}
412
413#[derive(Debug, Clone, Serialize, Deserialize)]
415pub struct StewardConfig {
416 pub stake_pool: String,
418
419 pub authority: String,
421
422 pub scoring_params: ScoringParams,
424}
425
426#[derive(Debug, Clone, Serialize, Deserialize)]
428pub struct ScoringParams {
429 pub min_vote_credits: u32,
431
432 pub max_commission: u8,
434
435 pub performance_weight: f64,
437
438 pub commission_weight: f64,
440
441 pub stake_concentration_limit: f64,
443}
444
445#[derive(Debug, Clone, Default)]
451pub struct QueryParams {
452 pub limit: Option<u32>,
454
455 pub offset: Option<u32>,
457
458 pub epoch: Option<u64>,
460
461 pub sort_order: Option<String>,
463}
464
465impl QueryParams {
466 pub fn with_limit(limit: u32) -> Self {
468 Self {
469 limit: Some(limit),
470 ..Default::default()
471 }
472 }
473
474 pub fn with_epoch(epoch: u64) -> Self {
476 Self {
477 epoch: Some(epoch),
478 ..Default::default()
479 }
480 }
481
482 pub fn limit(mut self, limit: u32) -> Self {
484 self.limit = Some(limit);
485 self
486 }
487
488 pub fn offset(mut self, offset: u32) -> Self {
490 self.offset = Some(offset);
491 self
492 }
493
494 pub fn epoch(mut self, epoch: u64) -> Self {
496 self.epoch = Some(epoch);
497 self
498 }
499
500 pub fn to_query_string(&self) -> String {
502 let mut params = Vec::new();
503
504 if let Some(limit) = self.limit {
505 params.push(format!("limit={}", limit));
506 }
507 if let Some(offset) = self.offset {
508 params.push(format!("offset={}", offset));
509 }
510 if let Some(epoch) = self.epoch {
511 params.push(format!("epoch={}", epoch));
512 }
513 if let Some(ref sort_order) = self.sort_order {
514 params.push(format!("sort_order={}", sort_order));
515 }
516
517 if params.is_empty() {
518 String::new()
519 } else {
520 format!("?{}", params.join("&"))
521 }
522 }
523}
524
525#[derive(Debug, Clone, Serialize, Deserialize)]
531pub struct ApiErrorResponse {
532 pub error: String,
533 pub message: Option<String>,
534 pub status_code: Option<u16>,
535}