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 vote_account: String,
91
92 pub mev_commission_bps: Option<u16>,
94
95 pub mev_rewards: Option<u64>,
97
98 pub priority_fee_commission_bps: Option<u16>,
100
101 pub priority_fee_rewards: Option<u64>,
103
104 pub running_jito: bool,
106
107 pub running_bam: Option<bool>,
109
110 pub active_stake: u64,
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize)]
116pub struct ValidatorByVoteAccount {
117 pub epoch: u64,
119
120 pub mev_commission_bps: u16,
122
123 pub mev_rewards: u64,
125
126 pub priority_fee_commission_bps: u16,
128
129 pub priority_fee_rewards: u64,
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize)]
135pub struct MevRewards {
136 pub epoch: u64,
138
139 pub total_network_mev_lamports: u64,
141
142 pub jito_stake_weight_lamports: u64,
144
145 pub mev_reward_per_lamport: f64,
147}
148
149#[derive(Debug, Clone, Serialize, Deserialize)]
151pub struct DailyMevRewards {
152 pub day: DateTime<Utc>,
154
155 pub count_mev_tips: u64,
157
158 pub jito_tips: f64,
160
161 pub tippers: u64,
163
164 pub validator_tips: f64,
166}
167
168#[derive(Debug, Clone, Serialize, Deserialize)]
170pub struct JitoStakeOverTime {
171 pub stake_ratio_over_time: std::collections::HashMap<String, f64>,
173}
174
175#[derive(Debug, Clone, Serialize, Deserialize)]
177pub struct MevCommissionAverageOverTime {
178 pub aggregated_mev_rewards: u64,
180
181 pub mev_rewards: Vec<TimeSeriesData<u64>>,
183
184 pub tvl: Vec<TimeSeriesData<u64>>,
186
187 pub apy: Vec<TimeSeriesData<f64>>,
189
190 pub num_validators: Vec<TimeSeriesData<u64>>,
192
193 pub supply: Vec<TimeSeriesData<f64>>,
195}
196
197#[derive(Debug, Clone, Serialize, Deserialize)]
199pub struct TimeSeriesData<T> {
200 pub data: T,
202
203 pub date: DateTime<Utc>,
205}
206
207#[derive(Debug, Clone, Serialize, Deserialize)]
209pub struct JitoSolRatio {
210 pub ratios: Vec<TimeSeriesData<f64>>,
212}
213
214#[derive(Debug, Clone, Serialize, Deserialize)]
216pub struct StakePoolStats {
217 pub aggregated_mev_rewards: u64,
219
220 pub mev_rewards: Vec<TimeSeriesData<u64>>,
222
223 pub tvl: Vec<TimeSeriesData<u64>>,
225
226 pub apy: Vec<TimeSeriesData<f64>>,
228
229 pub num_validators: Vec<TimeSeriesData<u64>>,
231
232 pub supply: Vec<TimeSeriesData<f64>>,
234}
235
236#[derive(Debug, Clone, Serialize, Deserialize)]
238pub struct BamDelegationBlacklistEntry {
239 pub vote_account: String,
241
242 pub added_epoch: u64,
244}
245
246#[derive(Debug, Clone, Serialize, Deserialize)]
252pub struct EpochRequest {
253 pub epoch: u64,
255}
256
257#[derive(Debug, Clone, Serialize, Deserialize)]
259pub struct RangeFilter {
260 pub start: DateTime<Utc>,
262
263 pub end: DateTime<Utc>,
265}
266
267#[derive(Debug, Clone, Serialize, Deserialize)]
269pub struct RangeRequest {
270 pub range_filter: RangeFilter,
272}
273
274#[derive(Debug, Clone, Serialize, Deserialize)]
276pub struct SortBy {
277 pub field: String,
279
280 pub order: String,
282}
283
284impl Default for SortBy {
285 fn default() -> Self {
286 Self {
287 field: "BlockTime".to_string(),
288 order: "Asc".to_string(),
289 }
290 }
291}
292
293#[derive(Debug, Clone, Serialize, Deserialize, Default)]
295pub struct StakePoolStatsRequest {
296 #[serde(skip_serializing_if = "Option::is_none")]
298 pub bucket_type: Option<String>,
299
300 #[serde(skip_serializing_if = "Option::is_none")]
302 pub range_filter: Option<RangeFilter>,
303
304 #[serde(skip_serializing_if = "Option::is_none")]
306 pub sort_by: Option<SortBy>,
307}
308
309impl StakePoolStatsRequest {
310 pub fn new() -> Self {
312 Self::default()
313 }
314
315 pub fn with_bucket_type(mut self, bucket_type: impl Into<String>) -> Self {
317 self.bucket_type = Some(bucket_type.into());
318 self
319 }
320
321 pub fn with_range_filter(mut self, start: DateTime<Utc>, end: DateTime<Utc>) -> Self {
323 self.range_filter = Some(RangeFilter { start, end });
324 self
325 }
326
327 pub fn with_sort_by(mut self, field: impl Into<String>, order: impl Into<String>) -> Self {
329 self.sort_by = Some(SortBy {
330 field: field.into(),
331 order: order.into(),
332 });
333 self
334 }
335
336 pub fn sort_asc(mut self) -> Self {
338 if let Some(ref mut sort) = self.sort_by {
339 sort.order = "Asc".to_string();
340 } else {
341 self.sort_by = Some(SortBy {
342 field: "BlockTime".to_string(),
343 order: "Asc".to_string(),
344 });
345 }
346 self
347 }
348
349 pub fn sort_desc(mut self) -> Self {
351 if let Some(ref mut sort) = self.sort_by {
352 sort.order = "Desc".to_string();
353 } else {
354 self.sort_by = Some(SortBy {
355 field: "BlockTime".to_string(),
356 order: "Desc".to_string(),
357 });
358 }
359 self
360 }
361}
362
363#[derive(Debug, Clone, Serialize, Deserialize)]
365pub struct ValidatorHistoryAccount {
366 pub vote_account: String,
368
369 pub history: Vec<ValidatorHistoryEntry>,
371}
372
373#[derive(Debug, Clone, Serialize, Deserialize)]
375pub struct ValidatorHistoryEntry {
376 pub epoch: u64,
378
379 pub vote_credits: Option<u32>,
381
382 pub commission: Option<u8>,
384
385 pub mev_commission_bps: Option<u16>,
387
388 pub version: Option<String>,
390
391 pub client_type: Option<String>,
393
394 pub active_stake: Option<u64>,
396
397 pub stake_rank: Option<u32>,
399
400 pub is_superminority: Option<bool>,
402
403 pub ip_address: Option<String>,
405}
406
407#[derive(Debug, Clone, Serialize, Deserialize)]
409pub struct StewardConfig {
410 pub stake_pool: String,
412
413 pub authority: String,
415
416 pub scoring_params: ScoringParams,
418}
419
420#[derive(Debug, Clone, Serialize, Deserialize)]
422pub struct ScoringParams {
423 pub min_vote_credits: u32,
425
426 pub max_commission: u8,
428
429 pub performance_weight: f64,
431
432 pub commission_weight: f64,
434
435 pub stake_concentration_limit: f64,
437}
438
439#[derive(Debug, Clone, Default)]
445pub struct QueryParams {
446 pub limit: Option<u32>,
448
449 pub offset: Option<u32>,
451
452 pub epoch: Option<u64>,
454
455 pub sort_order: Option<String>,
457}
458
459impl QueryParams {
460 pub fn with_limit(limit: u32) -> Self {
462 Self {
463 limit: Some(limit),
464 ..Default::default()
465 }
466 }
467
468 pub fn with_epoch(epoch: u64) -> Self {
470 Self {
471 epoch: Some(epoch),
472 ..Default::default()
473 }
474 }
475
476 pub fn limit(mut self, limit: u32) -> Self {
478 self.limit = Some(limit);
479 self
480 }
481
482 pub fn offset(mut self, offset: u32) -> Self {
484 self.offset = Some(offset);
485 self
486 }
487
488 pub fn epoch(mut self, epoch: u64) -> Self {
490 self.epoch = Some(epoch);
491 self
492 }
493
494 pub fn to_query_string(&self) -> String {
496 let mut params = Vec::new();
497
498 if let Some(limit) = self.limit {
499 params.push(format!("limit={}", limit));
500 }
501 if let Some(offset) = self.offset {
502 params.push(format!("offset={}", offset));
503 }
504 if let Some(epoch) = self.epoch {
505 params.push(format!("epoch={}", epoch));
506 }
507 if let Some(ref sort_order) = self.sort_order {
508 params.push(format!("sort_order={}", sort_order));
509 }
510
511 if params.is_empty() {
512 String::new()
513 } else {
514 format!("?{}", params.join("&"))
515 }
516 }
517}
518
519#[derive(Debug, Clone, Serialize, Deserialize)]
525pub struct ApiErrorResponse {
526 pub error: String,
527 pub message: Option<String>,
528 pub status_code: Option<u16>,
529}