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            GtBankFlagsContainer, TokenBalance, TokenBalances, TokenBalancesEntry, TokenConfig,
35            TokenFlagContainer, TokenMap, TokenMapEntry,
36        },
37    };
38    use anchor_lang::prelude::Pubkey;
39    use gmsol_utils::{
40        gt::{GtBankFlags, MAX_GT_BANK_FLAGS},
41        impl_fixed_map, impl_flags,
42        pubkey::to_bytes,
43        token_config::{
44            TokenFlag, TokenMapAccess, TokenRecord, TokensWithFeed, MAX_TREASURY_TOKEN_FLAGS,
45        },
46    };
47
48    const MAX_TOKENS: usize = 16;
49
50    impl_fixed_map!(TokenBalances, Pubkey, to_bytes, TokenBalance, MAX_TOKENS);
51    impl_fixed_map!(TokenMap, Pubkey, to_bytes, TokenConfig, MAX_TOKENS);
52
53    impl_flags!(TokenFlag, MAX_TREASURY_TOKEN_FLAGS, u8);
54    impl_flags!(GtBankFlags, MAX_GT_BANK_FLAGS, u8);
55
56    impl GtBank {
57        /// Get the number of tokens.
58        pub fn num_tokens(&self) -> usize {
59            self.balances.len()
60        }
61
62        /// Get all tokens.
63        pub fn tokens(&self) -> impl Iterator<Item = Pubkey> + '_ {
64            self.balances
65                .entries()
66                .map(|(key, _)| Pubkey::new_from_array(*key))
67        }
68
69        /// Create tokens with feed.
70        pub fn to_feeds(
71            &self,
72            map: &impl TokenMapAccess,
73            treasury_vault_config: &TreasuryVaultConfig,
74        ) -> crate::Result<TokensWithFeed> {
75            use std::collections::BTreeSet;
76
77            let tokens = self
78                .tokens()
79                .chain(treasury_vault_config.tokens())
80                .collect::<BTreeSet<_>>();
81            let records = tokens
82                .iter()
83                .map(|token| {
84                    let config = map
85                        .get(token)
86                        .ok_or_else(|| crate::Error::custom("unknown token"))?;
87                    TokenRecord::from_config(*token, config).map_err(crate::Error::custom)
88                })
89                .collect::<Result<Vec<_>, _>>()?;
90
91            TokensWithFeed::try_from_records(records).map_err(crate::Error::custom)
92        }
93    }
94
95    impl TreasuryVaultConfig {
96        /// Get the number of tokens.
97        pub fn num_tokens(&self) -> usize {
98            self.tokens.len()
99        }
100
101        /// Get all tokens.
102        pub fn tokens(&self) -> impl Iterator<Item = Pubkey> + '_ {
103            self.tokens
104                .entries()
105                .map(|(key, _)| Pubkey::new_from_array(*key))
106        }
107    }
108}