use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
pub mod bam_epoch_metrics;
pub mod bam_validators;
pub mod coinbase_balance;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StakerRewardsResponse {
pub rewards: Vec<StakerReward>,
pub total: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StakerReward {
pub stake_account: String,
pub stake_authority: String,
pub withdraw_authority: String,
pub epoch: u64,
pub mev_rewards: u64,
pub priority_fee_rewards: Option<u64>,
pub mev_claimed: bool,
pub priority_fee_claimed: Option<bool>,
pub vote_account: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidatorRewardsResponse {
pub validators: Vec<ValidatorReward>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidatorReward {
pub vote_account: String,
pub epoch: u64,
pub mev_commission_bps: u16,
pub mev_rewards: u64,
pub priority_fee_commission_bps: Option<u16>,
pub priority_fee_rewards: Option<u64>,
pub num_stakers: Option<u64>,
pub active_stake: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidatorsResponse {
pub validators: Vec<ValidatorInfo>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidatorInfo {
pub vote_account: String,
pub mev_commission_bps: Option<u16>,
pub mev_rewards: Option<u64>,
pub priority_fee_commission_bps: Option<u16>,
pub priority_fee_rewards: Option<u64>,
pub running_jito: bool,
pub running_bam: Option<bool>,
pub active_stake: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidatorByVoteAccount {
pub epoch: u64,
pub mev_commission_bps: u16,
pub mev_rewards: u64,
pub priority_fee_commission_bps: u16,
pub priority_fee_rewards: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MevRewards {
pub epoch: u64,
pub total_network_mev_lamports: u64,
pub jito_stake_weight_lamports: u64,
pub mev_reward_per_lamport: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DailyMevRewards {
pub day: DateTime<Utc>,
pub count_mev_tips: u64,
pub jito_tips: f64,
pub tippers: u64,
pub validator_tips: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JitoStakeOverTime {
pub stake_ratio_over_time: std::collections::HashMap<String, f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MevCommissionAverageOverTime {
pub aggregated_mev_rewards: u64,
pub mev_rewards: Vec<TimeSeriesData<u64>>,
pub tvl: Vec<TimeSeriesData<u64>>,
pub apy: Vec<TimeSeriesData<f64>>,
pub num_validators: Vec<TimeSeriesData<u64>>,
pub supply: Vec<TimeSeriesData<f64>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TimeSeriesData<T> {
pub data: T,
pub date: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JitoSolRatio {
pub ratios: Vec<TimeSeriesData<f64>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StakePoolStats {
pub aggregated_mev_rewards: u64,
pub mev_rewards: Vec<TimeSeriesData<u64>>,
pub tvl: Vec<TimeSeriesData<u64>>,
pub apy: Vec<TimeSeriesData<f64>>,
pub num_validators: Vec<TimeSeriesData<u64>>,
pub supply: Vec<TimeSeriesData<f64>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BamDelegationBlacklistEntry {
pub vote_account: String,
pub added_epoch: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EpochRequest {
pub epoch: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RangeFilter {
pub start: DateTime<Utc>,
pub end: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RangeRequest {
pub range_filter: RangeFilter,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SortBy {
pub field: String,
pub order: String,
}
impl Default for SortBy {
fn default() -> Self {
Self {
field: "BlockTime".to_string(),
order: "Asc".to_string(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct StakePoolStatsRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub bucket_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub range_filter: Option<RangeFilter>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sort_by: Option<SortBy>,
}
impl StakePoolStatsRequest {
pub fn new() -> Self {
Self::default()
}
pub fn with_bucket_type(mut self, bucket_type: impl Into<String>) -> Self {
self.bucket_type = Some(bucket_type.into());
self
}
pub fn with_range_filter(mut self, start: DateTime<Utc>, end: DateTime<Utc>) -> Self {
self.range_filter = Some(RangeFilter { start, end });
self
}
pub fn with_sort_by(mut self, field: impl Into<String>, order: impl Into<String>) -> Self {
self.sort_by = Some(SortBy {
field: field.into(),
order: order.into(),
});
self
}
pub fn sort_asc(mut self) -> Self {
if let Some(ref mut sort) = self.sort_by {
sort.order = "Asc".to_string();
} else {
self.sort_by = Some(SortBy {
field: "BlockTime".to_string(),
order: "Asc".to_string(),
});
}
self
}
pub fn sort_desc(mut self) -> Self {
if let Some(ref mut sort) = self.sort_by {
sort.order = "Desc".to_string();
} else {
self.sort_by = Some(SortBy {
field: "BlockTime".to_string(),
order: "Desc".to_string(),
});
}
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidatorHistoryAccount {
pub vote_account: String,
pub history: Vec<ValidatorHistoryEntry>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidatorHistoryEntry {
pub epoch: u64,
pub vote_credits: Option<u32>,
pub commission: Option<u8>,
pub mev_commission_bps: Option<u16>,
pub version: Option<String>,
pub client_type: Option<String>,
pub active_stake: Option<u64>,
pub stake_rank: Option<u32>,
pub is_superminority: Option<bool>,
pub ip_address: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StewardConfig {
pub stake_pool: String,
pub authority: String,
pub scoring_params: ScoringParams,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ScoringParams {
pub min_vote_credits: u32,
pub max_commission: u8,
pub performance_weight: f64,
pub commission_weight: f64,
pub stake_concentration_limit: f64,
}
#[derive(Debug, Clone, Default)]
pub struct QueryParams {
pub limit: Option<u32>,
pub offset: Option<u32>,
pub epoch: Option<u64>,
pub sort_order: Option<String>,
}
impl QueryParams {
pub fn with_limit(limit: u32) -> Self {
Self {
limit: Some(limit),
..Default::default()
}
}
pub fn with_epoch(epoch: u64) -> Self {
Self {
epoch: Some(epoch),
..Default::default()
}
}
pub fn limit(mut self, limit: u32) -> Self {
self.limit = Some(limit);
self
}
pub fn offset(mut self, offset: u32) -> Self {
self.offset = Some(offset);
self
}
pub fn epoch(mut self, epoch: u64) -> Self {
self.epoch = Some(epoch);
self
}
pub fn to_query_string(&self) -> String {
let mut params = Vec::new();
if let Some(limit) = self.limit {
params.push(format!("limit={}", limit));
}
if let Some(offset) = self.offset {
params.push(format!("offset={}", offset));
}
if let Some(epoch) = self.epoch {
params.push(format!("epoch={}", epoch));
}
if let Some(ref sort_order) = self.sort_order {
params.push(format!("sort_order={}", sort_order));
}
if params.is_empty() {
String::new()
} else {
format!("?{}", params.join("&"))
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApiErrorResponse {
pub error: String,
pub message: Option<String>,
pub status_code: Option<u16>,
}