use crate::TokenType;
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub struct TokenConfig {
pub token: TokenType,
pub supply_cap: u64,
pub burn_rate_bps: u16,
pub decay_half_life_blocks: u64,
}
impl TokenConfig {
pub fn calculate_burn(&self, amount: u64) -> u64 {
(amount as u128 * self.burn_rate_bps as u128 / 10_000) as u64
}
pub fn apply_decay(&self, amount: u64, blocks_elapsed: u64) -> u64 {
if blocks_elapsed == 0 {
return amount;
}
let decay_factor = 2f64.powf(-(blocks_elapsed as f64 / self.decay_half_life_blocks as f64));
(amount as f64 * decay_factor) as u64
}
}
pub type TokenConfigSet = HashMap<TokenType, TokenConfig>;
pub fn token_config() -> TokenConfigSet {
let mut configs = HashMap::new();
configs.insert(
TokenType::STOMP,
TokenConfig {
token: TokenType::STOMP,
supply_cap: 1_000_000_000_000,
burn_rate_bps: 50,
decay_half_life_blocks: 1_000_000,
},
);
configs.insert(
TokenType::AUM,
TokenConfig {
token: TokenType::AUM,
supply_cap: 2_000_000_000_000,
burn_rate_bps: 0,
decay_half_life_blocks: 2_000_000,
},
);
configs.insert(
TokenType::RAVECOIN,
TokenConfig {
token: TokenType::RAVECOIN,
supply_cap: 500_000_000_000,
burn_rate_bps: 100,
decay_half_life_blocks: 500_000,
},
);
configs.insert(
TokenType::TribeChain,
TokenConfig {
token: TokenType::TribeChain,
supply_cap: 1_000_000_000_000_000,
burn_rate_bps: 0,
decay_half_life_blocks: 0,
},
);
configs.insert(
TokenType::PTtC,
TokenConfig {
token: TokenType::PTtC,
supply_cap: 21_000_000_000_000,
burn_rate_bps: 25,
decay_half_life_blocks: 500_000,
},
);
configs.insert(
TokenType::NMTC,
TokenConfig {
token: TokenType::NMTC,
supply_cap: 100_000_000_000,
burn_rate_bps: 50,
decay_half_life_blocks: 250_000,
},
);
configs.insert(
TokenType::AI3,
TokenConfig {
token: TokenType::AI3,
supply_cap: 1_000_000_000_000,
burn_rate_bps: 10,
decay_half_life_blocks: 1_000_000,
},
);
configs
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_calculate_burn() {
let config = TokenConfig {
token: TokenType::STOMP,
supply_cap: 1_000_000_000_000,
burn_rate_bps: 100, decay_half_life_blocks: 1_000_000,
};
let burn = config.calculate_burn(10_000);
assert_eq!(burn, 100);
}
#[test]
fn test_apply_decay() {
let config = TokenConfig {
token: TokenType::STOMP,
supply_cap: 1_000_000_000_000,
burn_rate_bps: 50,
decay_half_life_blocks: 1_000_000,
};
assert_eq!(config.apply_decay(1_000_000, 0), 1_000_000);
let remaining = config.apply_decay(1_000_000, 1_000_000);
assert!(remaining > 490_000 && remaining < 510_000); }
#[test]
fn test_all_tokens_have_supply_caps() {
let configs = token_config();
assert!(
configs.get(&TokenType::TribeChain).is_some(),
"TribeChain missing"
);
assert!(configs.get(&TokenType::STOMP).is_some(), "STOMP missing");
assert!(configs.get(&TokenType::AUM).is_some(), "AUM missing");
assert!(
configs.get(&TokenType::RAVECOIN).is_some(),
"RAVECOIN missing"
);
assert!(configs.get(&TokenType::PTtC).is_some(), "PTtC missing");
assert!(configs.get(&TokenType::NMTC).is_some(), "NMTC missing");
assert!(configs.get(&TokenType::AI3).is_some(), "AI3 missing");
}
#[test]
fn test_pttc_cap_value() {
let configs = token_config();
let pttc = configs.get(&TokenType::PTtC).unwrap();
assert_eq!(pttc.supply_cap, 21_000_000_000_000);
}
#[test]
fn test_nmtc_cap_value() {
let configs = token_config();
let nmtc = configs.get(&TokenType::NMTC).unwrap();
assert_eq!(nmtc.supply_cap, 100_000_000_000);
}
#[test]
fn test_ai3_cap_value() {
let configs = token_config();
let ai3 = configs.get(&TokenType::AI3).unwrap();
assert_eq!(ai3.supply_cap, 1_000_000_000_000);
}
}