1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
use odra::{
    prelude::{collections::BTreeMap, vec::Vec},
    types::{Address, Balance},
    OdraType,
};

use super::balances::BalanceStorage;

/// A module that provides aggregated data about reputation tokens.
#[odra::module]
pub struct BalanceAggregates {
    reputation_storage: BalanceStorage,
}

impl BalanceAggregates {
    /// Gets balances of all the token holders.
    pub fn all_balances(&self) -> AggregatedBalance {
        let mut balances = BTreeMap::<Address, Balance>::new();
        self.reputation_storage.holders().for_each(|address| {
            balances.insert(address, self.reputation_storage.balance_of(address));
        });

        AggregatedBalance::new(balances, self.reputation_storage.total_supply())
    }

    /// Gets balances of the given account addresses.
    pub fn partial_balances(&self, addresses: Vec<Address>) -> AggregatedBalance {
        let mut balances = BTreeMap::<Address, Balance>::new();
        let mut partial_supply = Balance::zero();
        for address in addresses {
            let balance = self.reputation_storage.balance_of(address);
            balances.insert(address, balance);
            partial_supply += balance;
        }
        AggregatedBalance {
            balances,
            total_supply: partial_supply,
        }
    }
}

/// Stores information about balances and the total supply.
#[derive(OdraType)]
pub struct AggregatedBalance {
    balances: BTreeMap<Address, Balance>,
    total_supply: Balance,
}

impl AggregatedBalance {
    pub fn new(balances: BTreeMap<Address, Balance>, total_supply: Balance) -> Self {
        Self {
            balances,
            total_supply,
        }
    }

    pub fn balances(&self) -> &BTreeMap<Address, Balance> {
        &self.balances
    }

    pub fn total_supply(&self) -> Balance {
        self.total_supply
    }
}