gmsol_programs/utils/
treasury.rs

1use bytemuck::Zeroable;
2
3use crate::gmsol_treasury::types::{TokenBalance, TokenBalancesEntry, TokenConfig, TokenMapEntry};
4
5impl Default for TokenBalance {
6    fn default() -> Self {
7        Zeroable::zeroed()
8    }
9}
10
11impl Default for TokenBalancesEntry {
12    fn default() -> Self {
13        Zeroable::zeroed()
14    }
15}
16
17impl Default for TokenConfig {
18    fn default() -> Self {
19        Zeroable::zeroed()
20    }
21}
22
23impl Default for TokenMapEntry {
24    fn default() -> Self {
25        Zeroable::zeroed()
26    }
27}
28
29#[cfg(feature = "gmsol-utils")]
30mod utils {
31    use crate::gmsol_treasury::{
32        accounts::{GtBank, TreasuryVaultConfig},
33        types::{
34            TokenBalance, TokenBalances, TokenBalancesEntry, TokenConfig, TokenMap, TokenMapEntry,
35        },
36    };
37    use anchor_lang::prelude::Pubkey;
38    use gmsol_utils::{
39        impl_fixed_map,
40        pubkey::to_bytes,
41        token_config::{TokenMapAccess, TokenRecord, TokensWithFeed},
42    };
43
44    const MAX_TOKENS: usize = 16;
45
46    impl_fixed_map!(TokenBalances, Pubkey, to_bytes, TokenBalance, MAX_TOKENS);
47    impl_fixed_map!(TokenMap, Pubkey, to_bytes, TokenConfig, MAX_TOKENS);
48
49    impl GtBank {
50        /// Get the number of tokens.
51        pub fn num_tokens(&self) -> usize {
52            self.balances.len()
53        }
54
55        /// Get all tokens.
56        pub fn tokens(&self) -> impl Iterator<Item = Pubkey> + '_ {
57            self.balances
58                .entries()
59                .map(|(key, _)| Pubkey::new_from_array(*key))
60        }
61
62        /// Create tokens with feed.
63        pub fn to_feeds(
64            &self,
65            map: &impl TokenMapAccess,
66            treasury_vault_config: &TreasuryVaultConfig,
67        ) -> crate::Result<TokensWithFeed> {
68            use std::collections::BTreeSet;
69
70            let tokens = self
71                .tokens()
72                .chain(treasury_vault_config.tokens())
73                .collect::<BTreeSet<_>>();
74            let records = tokens
75                .iter()
76                .map(|token| {
77                    let config = map
78                        .get(token)
79                        .ok_or_else(|| crate::Error::custom("unknown token"))?;
80                    TokenRecord::from_config(*token, config).map_err(crate::Error::custom)
81                })
82                .collect::<Result<Vec<_>, _>>()?;
83
84            TokensWithFeed::try_from_records(records).map_err(crate::Error::custom)
85        }
86    }
87
88    impl TreasuryVaultConfig {
89        /// Get the number of tokens.
90        pub fn num_tokens(&self) -> usize {
91            self.tokens.len()
92        }
93
94        /// Get all tokens.
95        pub fn tokens(&self) -> impl Iterator<Item = Pubkey> + '_ {
96            self.tokens
97                .entries()
98                .map(|(key, _)| Pubkey::new_from_array(*key))
99        }
100    }
101}