From a76a20ee8cca0c64df2a0c2c092ae3eac5803c33 Mon Sep 17 00:00:00 2001 From: ZelionD Date: Mon, 25 Nov 2024 10:20:25 -0500 Subject: [PATCH] update rewards endpoint --- gov-portal-db/src/rewards_manager/mod.rs | 16 +++++- .../src/rewards_manager/rewards_cache.rs | 51 +++++++++++++------ gov-portal-db/src/server.rs | 9 +++- gov-portal-db/tests/test_rewards_manager.rs | 10 ++-- 4 files changed, 62 insertions(+), 24 deletions(-) diff --git a/gov-portal-db/src/rewards_manager/mod.rs b/gov-portal-db/src/rewards_manager/mod.rs index 90a0381..a7f8408 100644 --- a/gov-portal-db/src/rewards_manager/mod.rs +++ b/gov-portal-db/src/rewards_manager/mod.rs @@ -172,7 +172,7 @@ impl RewardsManager { .await? } - pub fn get_total_rewards( + pub fn get_available_rewards( &self, requestor: &Address, wallet: &Address, @@ -189,7 +189,19 @@ impl RewardsManager { return Err(error::Error::Unauthorized); } - Ok(self.rewards_cache.get_total_rewards(wallet)) + Ok(self.rewards_cache.get_available_rewards(wallet)) + } + + pub fn get_total_rewards(&self, requestor: &Address) -> Result { + if !self + .config + .moderators + .iter() + .any(|wallet| wallet == requestor) + { + return Err(error::Error::Unauthorized); + } + Ok(self.rewards_cache.get_total_rewards()) } /// Counts all rewards allocated by requestor within MongoDB by provided wallet EVM-like address [`Address`] diff --git a/gov-portal-db/src/rewards_manager/rewards_cache.rs b/gov-portal-db/src/rewards_manager/rewards_cache.rs index f5e5743..6450d35 100644 --- a/gov-portal-db/src/rewards_manager/rewards_cache.rs +++ b/gov-portal-db/src/rewards_manager/rewards_cache.rs @@ -10,7 +10,8 @@ use super::error; const REWARDS_BUF_LENGTH: usize = 128; pub struct RewardsCache { - total_rewards_by_wallets: Arc>>, + total_rewards: Arc>, + available_rewards_by_wallets: Arc>>, unclaimed_rewards: Arc>>>, total_rewards_tx: mpsc::UnboundedSender, } @@ -55,7 +56,9 @@ impl RewardsCache { pub fn init(rewards: Vec) -> Result { let (total_rewards_tx, mut total_rewards_rx) = mpsc::unbounded_channel(); - let mut total_rewards_by_wallet = HashMap::::with_capacity(rewards.len()); + let mut total_rewards = Reward::default(); + let mut available_rewards_by_wallet = + HashMap::::with_capacity(rewards.len()); let mut unclaimed_rewards = HashMap::>::default(); for entry in rewards { @@ -73,12 +76,17 @@ impl RewardsCache { continue; } RewardStatus::Granted => { + total_rewards.add(reward.amount, block_number); + unclaimed_rewards .entry(entry.id) .or_default() .insert(wallet, Reward::new(reward.amount, block_number)); } - RewardStatus::Claimed => {} + RewardStatus::Claimed => { + total_rewards.add(reward.amount, block_number); + continue; + } RewardStatus::Reverted => { return Err( anyhow::anyhow!("Unexpected status for reward {reward:?}").into() @@ -86,7 +94,7 @@ impl RewardsCache { } } - total_rewards_by_wallet + available_rewards_by_wallet .entry(wallet) .or_default() .add(reward.amount, block_number); @@ -95,11 +103,13 @@ impl RewardsCache { let cache = Self { total_rewards_tx, - total_rewards_by_wallets: Arc::new(RwLock::new(total_rewards_by_wallet)), + total_rewards: Arc::new(RwLock::new(total_rewards)), + available_rewards_by_wallets: Arc::new(RwLock::new(available_rewards_by_wallet)), unclaimed_rewards: Arc::new(RwLock::new(unclaimed_rewards)), }; - let total_rewards_by_wallets = cache.total_rewards_by_wallets.clone(); + let total_rewards = cache.total_rewards.clone(); + let available_rewards_by_wallets = cache.available_rewards_by_wallets.clone(); let unclaimed_rewards = cache.unclaimed_rewards.clone(); tokio::spawn(async move { @@ -110,18 +120,21 @@ impl RewardsCache { .await > 0 { - let mut total_rewards_by_wallets = total_rewards_by_wallets.write(); + let mut total_rewards = total_rewards.write(); + let mut available_rewards_by_wallets = available_rewards_by_wallets.write(); let mut unclaimed_rewards = unclaimed_rewards.write(); for rewards_delta in total_rewards_buf.drain(..) { match rewards_delta { RewardsDelta::Grant(block_number, id, wallet, amount) => { + total_rewards.add(amount, block_number); + unclaimed_rewards .entry(id) .or_default() .insert(wallet, Reward::new(amount, block_number)); - total_rewards_by_wallets + available_rewards_by_wallets .entry(wallet) .or_default() .add(amount, block_number); @@ -131,8 +144,10 @@ impl RewardsCache { entry.remove(&wallet); }); - if let Some(total_reward) = total_rewards_by_wallets.get_mut(&wallet) { - total_reward.updated_at_block = block_number; + if let Some(available_reward) = + available_rewards_by_wallets.get_mut(&wallet) + { + available_reward.sub(available_reward.amount, block_number); } } RewardsDelta::RevertBatch(block_number, id) => { @@ -141,11 +156,13 @@ impl RewardsCache { }; for (wallet, reward) in rewards_by_wallets { - if let Some(total_reward) = - total_rewards_by_wallets.get_mut(&wallet) + if let Some(available_reward) = + available_rewards_by_wallets.get_mut(&wallet) { - total_reward.sub(reward.amount, block_number); + available_reward.sub(reward.amount, block_number); } + + total_rewards.sub(reward.amount, block_number); } } } @@ -162,11 +179,15 @@ impl RewardsCache { .map_err(error::Error::from) } - pub fn get_total_rewards(&self, wallet: &Address) -> U256 { - self.total_rewards_by_wallets + pub fn get_available_rewards(&self, wallet: &Address) -> U256 { + self.available_rewards_by_wallets .read() .get(wallet) .map(|reward| reward.amount) .unwrap_or_default() } + + pub fn get_total_rewards(&self) -> U256 { + self.total_rewards.read().amount + } } diff --git a/gov-portal-db/src/server.rs b/gov-portal-db/src/server.rs index 7b7b596..9850216 100644 --- a/gov-portal-db/src/server.rs +++ b/gov-portal-db/src/server.rs @@ -123,6 +123,7 @@ pub struct RewardsResponse { pub data: Vec, pub total: u64, pub total_rewards: Option, + pub available_rewards: Option, } /// JSON-serialized request passed as POST-data to `/users` endpoint @@ -609,7 +610,8 @@ async fn rewards_route( .map(|data| RewardsResponse { data, total, - total_rewards: None, + available_rewards: None, + total_rewards: manager.get_total_rewards(&requestor).ok(), }) } }) @@ -644,7 +646,10 @@ async fn rewards_route( .map(|data| RewardsResponse { data, total, - total_rewards: manager.get_total_rewards(&requestor, &wallet).ok(), + available_rewards: manager + .get_available_rewards(&requestor, &wallet) + .ok(), + total_rewards: None, }) } }) diff --git a/gov-portal-db/tests/test_rewards_manager.rs b/gov-portal-db/tests/test_rewards_manager.rs index 119d1d6..c9da7a7 100644 --- a/gov-portal-db/tests/test_rewards_manager.rs +++ b/gov-portal-db/tests/test_rewards_manager.rs @@ -579,7 +579,7 @@ async fn test_rewards_by_wallet() -> Result<(), anyhow::Error> { assert_eq!( rewards_manager - .get_total_rewards(&Address::from_low_u64_le(1), &Address::from_low_u64_le(1)) + .get_available_rewards(&Address::from_low_u64_le(1), &Address::from_low_u64_le(1)) .unwrap(), U256::from_dec_str("31248000000000").unwrap() ); @@ -598,14 +598,14 @@ async fn test_rewards_by_wallet() -> Result<(), anyhow::Error> { assert_eq!( rewards_manager - .get_total_rewards(&Address::from_low_u64_le(1), &Address::from_low_u64_le(1)) + .get_available_rewards(&Address::from_low_u64_le(1), &Address::from_low_u64_le(1)) .unwrap(), U256::from_dec_str("31248000000000").unwrap() ); assert_eq!( rewards_manager - .get_total_rewards( + .get_available_rewards( &rewards_manager.config.moderators[0], &Address::from_low_u64_le(1) ) @@ -625,7 +625,7 @@ async fn test_rewards_by_wallet() -> Result<(), anyhow::Error> { assert_eq!( rewards_manager - .get_total_rewards(&Address::from_low_u64_le(1), &Address::from_low_u64_le(1)) + .get_available_rewards(&Address::from_low_u64_le(1), &Address::from_low_u64_le(1)) .unwrap(), U256::from_dec_str("31232000000000").unwrap() ); @@ -642,7 +642,7 @@ async fn test_rewards_by_wallet() -> Result<(), anyhow::Error> { assert_eq!( rewards_manager - .get_total_rewards( + .get_available_rewards( &rewards_manager.config.moderators[0], &Address::from_low_u64_le(1) )