Skip to content

Commit 7a7e966

Browse files
committed
fix: update
1 parent fbfcd73 commit 7a7e966

File tree

10 files changed

+422
-39
lines changed

10 files changed

+422
-39
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/src/resolvers/query_resolver.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use kobe_core::{
1212
constants::{JITOSOL_VALIDATOR_LIST_MAINNET, JITOSOL_VALIDATOR_LIST_TESTNET},
1313
db_models::{
1414
bam_epoch_metric::BamEpochMetricStore,
15+
bam_validators::BamValidatorStore,
1516
mev_rewards::{StakerRewardsStore, ValidatorRewardsStore},
1617
stake_pool_stats::{StakePoolStats, StakePoolStatsStore},
1718
steward_events::StewardEventsStore,
@@ -34,6 +35,7 @@ use crate::{
3435
resolvers::error::{QueryResolverError, Result},
3536
schemas::{
3637
bam_epoch_metric::BamEpochMetricResponse,
38+
bam_validator::BamValidatorsResponse,
3739
jitosol_ratio::{JitoSolRatioRequest, JitoSolRatioResponse},
3840
mev_rewards::{
3941
MevRewards, MevRewardsRequest, StakerRewards, StakerRewardsRequest,
@@ -65,6 +67,9 @@ pub struct QueryResolver {
6567
/// BAM epoch metric store
6668
bam_epoch_metric_store: BamEpochMetricStore,
6769

70+
/// BAM validators store
71+
bam_validators_store: BamValidatorStore,
72+
6873
/// RPC Client URL
6974
rpc_client: Arc<RpcClient>,
7075
/// Solana Cluster
@@ -402,6 +407,26 @@ pub async fn get_bam_epoch_metric_wrapper(
402407
}
403408
}
404409

410+
#[cached(
411+
type = "TimedCache<String, (StatusCode, Json<BamValidatorsResponse>)>",
412+
create = "{ TimedCache::with_lifespan_and_capacity(60, 1000) }",
413+
key = "String",
414+
convert = r#"{ format!("bam-validators-{}", epoch.to_string()) }"#
415+
)]
416+
pub async fn get_bam_validators_wrapper(
417+
resolver: Extension<QueryResolver>,
418+
epoch: u64,
419+
) -> (StatusCode, Json<BamValidatorsResponse>) {
420+
if let Ok(res) = resolver.get_bam_validators(epoch).await {
421+
(StatusCode::OK, Json(res))
422+
} else {
423+
(
424+
StatusCode::INTERNAL_SERVER_ERROR,
425+
Json(BamValidatorsResponse::default()),
426+
)
427+
}
428+
}
429+
405430
#[cached(
406431
type = "TimedCache<String, Vec<PreferredWithdraw>>",
407432
create = "{ TimedCache::with_lifespan_and_capacity(10, 100) }",
@@ -473,6 +498,9 @@ impl QueryResolver {
473498
bam_epoch_metric_store: BamEpochMetricStore::new(
474499
database.collection(BamEpochMetricStore::COLLECTION),
475500
),
501+
bam_validators_store: BamValidatorStore::new(
502+
database.collection(BamValidatorStore::COLLECTION),
503+
),
476504
rpc_client: Arc::new(client),
477505
cluster,
478506
steward_config,
@@ -960,6 +988,22 @@ impl QueryResolver {
960988
Ok(BamEpochMetricResponse { bam_epoch_metric })
961989
}
962990

991+
/// Retrieves the bam validators, based on the provided epoch filter.
992+
///
993+
/// # Example
994+
///
995+
/// This endpoint can be used to fetch the bam metric for a specific epoch:
996+
///
997+
/// ```ignore
998+
/// GET /bam_validators?epoch=800
999+
/// ```
1000+
/// This request retrieves the BAM validators for epoch 800.
1001+
pub async fn get_bam_validators(&self, epoch: u64) -> Result<BamValidatorsResponse> {
1002+
let bam_validators = self.bam_validators_store.find(epoch).await?;
1003+
1004+
Ok(BamValidatorsResponse { bam_validators })
1005+
}
1006+
9631007
pub async fn get_preferred_withdraw_validator_list(
9641008
&self,
9651009
min_stake_threshold: u64,

api/src/schemas/bam_validator.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
use kobe_core::db_models::bam_validators::BamValidator;
2+
use serde::{Deserialize, Serialize};
3+
4+
#[derive(Serialize, Deserialize, Clone)]
5+
pub struct BamValidatorsRequest {
6+
pub epoch: u64,
7+
}
8+
9+
impl std::fmt::Display for BamValidatorsRequest {
10+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
11+
write!(f, "{}", self.epoch)
12+
}
13+
}
14+
15+
#[derive(Default, Serialize, Deserialize, Clone)]
16+
pub struct BamValidatorsResponse {
17+
pub bam_validators: Vec<BamValidator>,
18+
}

api/src/schemas/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod bam_epoch_metric;
2+
pub mod bam_validator;
23
pub mod jitosol_ratio;
34
pub mod mev_rewards;
45
pub mod preferred_withdraw;

bam-writer-service/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ anyhow = { workspace = true }
1313
bam-api-client = { workspace = true }
1414
clap = { workspace = true }
1515
env_logger = { workspace = true }
16+
jito-steward = { workspace = true}
1617
kobe-api = { workspace = true }
1718
kobe-core = { workspace = true }
1819
log = { workspace = true }

bam-writer-service/src/lib.rs

Lines changed: 87 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
use std::{collections::HashMap, sync::Arc};
1+
use std::{collections::HashMap, str::FromStr, sync::Arc};
22

3-
use bam_api_client::{client::BamApiClient, types::ValidatorsResponse};
4-
use kobe_core::db_models::bam_epoch_metric::{BamEpochMetric, BamEpochMetricStore};
3+
use bam_api_client::client::BamApiClient;
4+
use kobe_core::db_models::{
5+
bam_epoch_metric::{BamEpochMetric, BamEpochMetricStore},
6+
bam_validators::{BamValidator, BamValidatorStore},
7+
};
58
use mongodb::Collection;
69
use solana_client::nonblocking::rpc_client::RpcClient;
710
use solana_pubkey::Pubkey;
8-
use stakenet_sdk::utils::accounts::get_stake_pool_account;
11+
use stakenet_sdk::utils::accounts::{get_all_validator_history_accounts, get_stake_pool_account};
912

1013
use crate::bam_delegation_criteria::BamDelegationCriteria;
1114

@@ -21,8 +24,8 @@ pub struct BamWriterService {
2124
/// BAM API client
2225
bam_api_client: BamApiClient,
2326

24-
/// Kobe API base URL
25-
kobe_base_api_url: String,
27+
/// Bam validators store
28+
bam_validators_store: BamValidatorStore,
2629

2730
/// Bam epoch metric store
2831
bam_epoch_metric_store: BamEpochMetricStore,
@@ -39,12 +42,15 @@ impl BamWriterService {
3942
stake_pool: Pubkey,
4043
rpc_client: Arc<RpcClient>,
4144
bam_api_base_url: &str,
42-
kobe_api_base_url: &str,
4345
) -> anyhow::Result<Self> {
4446
// Connect to MongoDB
4547
let client = mongodb::Client::with_uri_str(mongo_connection_uri).await?;
4648
let db = client.database(mongo_db_name);
4749

50+
let bam_validators_collection: Collection<BamValidator> =
51+
db.collection(BamValidatorStore::COLLECTION);
52+
let bam_validators_store = BamValidatorStore::new(bam_validators_collection);
53+
4854
let bam_epoch_metric_collection: Collection<BamEpochMetric> =
4955
db.collection(BamEpochMetricStore::COLLECTION);
5056
let bam_epoch_metric_store = BamEpochMetricStore::new(bam_epoch_metric_collection);
@@ -58,7 +64,7 @@ impl BamWriterService {
5864
stake_pool,
5965
rpc_client,
6066
bam_api_client,
61-
kobe_base_api_url: kobe_api_base_url.to_string(),
67+
bam_validators_store,
6268
bam_epoch_metric_store,
6369
bam_delegation_criteria,
6470
})
@@ -72,42 +78,89 @@ impl BamWriterService {
7278
let jitosol_stake = get_stake_pool_account(&self.rpc_client, &self.stake_pool).await?;
7379

7480
let bam_node_validators = self.bam_api_client.get_validators().await?;
75-
let bam_validator_map: HashMap<&str, &ValidatorsResponse> = bam_node_validators
76-
.iter()
77-
.map(|v| (v.validator_pubkey.as_str(), v))
78-
.collect();
81+
// let bam_validator_map: HashMap<&str, &ValidatorsResponse> = bam_node_validators
82+
// .iter()
83+
// .map(|v| (v.validator_pubkey.as_str(), v))
84+
// .collect();
7985

8086
let vote_accounts = self.rpc_client.get_vote_accounts().await?;
87+
88+
let mut bam_validator_map = HashMap::new();
89+
for bam_node_validator in bam_node_validators {
90+
for vote_account in vote_accounts.current.iter() {
91+
if vote_account
92+
.node_pubkey
93+
.eq(&bam_node_validator.validator_pubkey)
94+
{
95+
bam_validator_map.insert(
96+
Pubkey::from_str(&vote_account.vote_pubkey).unwrap(),
97+
vote_account,
98+
);
99+
}
100+
}
101+
}
102+
103+
let validator_histories =
104+
get_all_validator_history_accounts(&self.rpc_client.clone(), jito_steward::id())
105+
.await?;
106+
107+
let start_epoch = epoch - 3;
108+
let end_epoch = epoch;
109+
let mut bam_validators: Vec<BamValidator> = Vec::new();
110+
'validator_history: for validator_history in validator_histories {
111+
if let Some(vote_account) = bam_validator_map.get(&validator_history.vote_account) {
112+
for entry in validator_history
113+
.history
114+
.epoch_range(start_epoch as u16, end_epoch as u16)
115+
{
116+
if let Some(entry) = entry {
117+
if entry.commission.ne(&0) {
118+
continue 'validator_history;
119+
}
120+
121+
if entry.mev_commission.gt(&10) {
122+
continue 'validator_history;
123+
}
124+
125+
if entry.is_superminority.eq(&0) {
126+
continue 'validator_history;
127+
}
128+
}
129+
}
130+
131+
let bam_validator = BamValidator::new(
132+
vote_account.activated_stake,
133+
epoch,
134+
&vote_account.node_pubkey,
135+
&vote_account.vote_pubkey,
136+
);
137+
bam_validators.push(bam_validator);
138+
}
139+
}
140+
141+
self.bam_validators_store
142+
.insert_many(&bam_validators)
143+
.await?;
144+
81145
let total_stake = vote_accounts
82146
.current
83147
.iter()
84148
.map(|v| v.activated_stake)
85149
.sum();
86150

87-
let validators_url = format!("{}/api/v1/validators", self.kobe_base_api_url);
88-
89-
let client = reqwest::Client::new();
90-
let validators = client
91-
.post(&validators_url)
92-
.json(&serde_json::json!({ "epoch": epoch }))
93-
.send()
94-
.await?
95-
.json::<kobe_api::schemas::validator::ValidatorsResponse>()
96-
.await?;
151+
// let validators_url = format!("{}/api/v1/validators", self.kobe_base_api_url);
97152

98-
let mut eligible_bam_validator_count = 0_u64;
99-
let mut bam_stake = 0_u64;
100-
for validator in validators.validators.iter() {
101-
if let Some(ref identity_account) = validator.identity_account {
102-
if bam_validator_map.contains_key(identity_account.as_str()) {
103-
bam_stake += validator.active_stake;
153+
// let client = reqwest::Client::new();
154+
// let validators = client
155+
// .post(&validators_url)
156+
// .json(&serde_json::json!({ "epoch": epoch }))
157+
// .send()
158+
// .await?
159+
// .json::<kobe_api::schemas::validator::ValidatorsResponse>()
160+
// .await?;
104161

105-
if let Some(true) = validator.jito_pool_eligible {
106-
eligible_bam_validator_count += 1;
107-
}
108-
}
109-
}
110-
}
162+
let eligible_bam_validator_count = bam_validators.len() as u64;
163+
let bam_stake = bam_validators.iter().map(|v| v.get_active_stake()).sum();
111164

112165
let available_bam_delegation_stake = self
113166
.bam_delegation_criteria

bam-writer-service/src/main.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,6 @@ struct Args {
3030
#[clap(long, env)]
3131
bam_api_base_url: String,
3232

33-
/// Kobe api base url
34-
#[clap(long, env)]
35-
kobe_api_base_url: String,
36-
3733
/// Stake pool address
3834
#[clap(
3935
long,
@@ -111,7 +107,6 @@ async fn main() -> anyhow::Result<()> {
111107
args.stake_pool,
112108
rpc_client.clone(),
113109
&args.bam_api_base_url,
114-
&args.kobe_api_base_url,
115110
)
116111
.await?;
117112

core/src/constants.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub const JITOSOL_VALIDATOR_LIST_MAINNET: &str = "3R3nGZpQs2aZo5FDQvd2MUQ6R7KhAP
1515
pub const JITOSOL_VALIDATOR_LIST_TESTNET: &str = "G5N6K3qW86GSkNEpywcbJk42LjEZoshzECFg1LNVjSLa";
1616
pub const DATABASE_NAME: &str = "validators";
1717
pub const VALIDATOR_COLLECTION_NAME: &str = "validators";
18+
pub const BAM_VALIDATOR_COLLECTION_NAME: &str = "bam_validators";
1819
pub const STAKE_POOL_STATS_COLLECTION_NAME: &str = "stake_pool_stats";
1920
pub const VALIDATOR_REWARDS_COLLECTION_NAME: &str = "validator_rewards";
2021
pub const STAKER_REWARDS_COLLECTION_NAME: &str = "staker_rewards";

0 commit comments

Comments
 (0)