solana_sdk/
rent_debits.rs

1use {
2    solana_sdk::{pubkey::Pubkey, reward_info::RewardInfo, reward_type::RewardType},
3    std::collections::HashMap,
4};
5
6#[derive(Clone, Debug, PartialEq, Eq)]
7pub struct RentDebit {
8    rent_collected: u64,
9    post_balance: u64,
10}
11
12impl RentDebit {
13    fn try_into_reward_info(self) -> Option<RewardInfo> {
14        let rent_debit = i64::try_from(self.rent_collected)
15            .ok()
16            .and_then(|r| r.checked_neg());
17        rent_debit.map(|rent_debit| RewardInfo {
18            reward_type: RewardType::Rent,
19            lamports: rent_debit,
20            post_balance: self.post_balance,
21            commission: None, // Not applicable
22        })
23    }
24}
25
26#[derive(Clone, Debug, Default, PartialEq, Eq)]
27pub struct RentDebits(HashMap<Pubkey, RentDebit>);
28impl RentDebits {
29    pub fn get_account_rent_debit(&self, address: &Pubkey) -> u64 {
30        self.0
31            .get(address)
32            .map(|r| r.rent_collected)
33            .unwrap_or_default()
34    }
35
36    // These functions/fields are only usable from a dev context (i.e. tests and benches)
37    #[cfg(feature = "dev-context-only-utils")]
38    pub fn len(&self) -> usize {
39        self.0.len()
40    }
41
42    #[cfg(feature = "dev-context-only-utils")]
43    pub fn is_empty(&self) -> bool {
44        self.0.is_empty()
45    }
46
47    pub fn insert(&mut self, address: &Pubkey, rent_collected: u64, post_balance: u64) {
48        if rent_collected != 0 {
49            self.0.insert(
50                *address,
51                RentDebit {
52                    rent_collected,
53                    post_balance,
54                },
55            );
56        }
57    }
58
59    pub fn into_unordered_rewards_iter(self) -> impl Iterator<Item = (Pubkey, RewardInfo)> {
60        self.0
61            .into_iter()
62            .filter_map(|(address, rent_debit)| Some((address, rent_debit.try_into_reward_info()?)))
63    }
64}