use std::collections::HashMap;
use crate::asset::{validate_native_denom, AssetInfo};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{from_json, Addr, Api, Binary, Decimal, StdError, StdResult};
#[cw_serde]
pub struct TaxConfig<T> {
pub tax_rate: Decimal,
pub tax_recipient: T,
}
pub type TaxConfigChecked = TaxConfig<Addr>;
pub type TaxConfigUnchecked = TaxConfig<String>;
#[cw_serde]
pub struct TaxConfigs<T>(HashMap<String, TaxConfig<T>>);
pub type TaxConfigsChecked = TaxConfigs<Addr>;
pub type TaxConfigsUnchecked = TaxConfigs<String>;
impl From<TaxConfigChecked> for TaxConfigUnchecked {
fn from(value: TaxConfigChecked) -> Self {
TaxConfigUnchecked {
tax_rate: value.tax_rate,
tax_recipient: value.tax_recipient.to_string(),
}
}
}
impl From<TaxConfigsChecked> for TaxConfigsUnchecked {
fn from(value: TaxConfigsChecked) -> Self {
TaxConfigs(
value
.0
.into_iter()
.map(|(k, v)| (k, v.into()))
.collect::<HashMap<_, _>>(),
)
}
}
impl From<Vec<(&str, TaxConfigUnchecked)>> for TaxConfigsUnchecked {
fn from(value: Vec<(&str, TaxConfigUnchecked)>) -> Self {
TaxConfigs(value.into_iter().map(|(k, v)| (k.to_string(), v)).collect())
}
}
impl From<Vec<(&str, TaxConfigChecked)>> for TaxConfigsChecked {
fn from(value: Vec<(&str, TaxConfigChecked)>) -> Self {
TaxConfigs(value.into_iter().map(|(k, v)| (k.to_string(), v)).collect())
}
}
impl Default for TaxConfigChecked {
fn default() -> Self {
TaxConfigChecked {
tax_rate: Decimal::percent(5),
tax_recipient: Addr::unchecked("addr0000"),
}
}
}
impl Default for TaxConfigUnchecked {
fn default() -> Self {
TaxConfigChecked::default().into()
}
}
impl Default for TaxConfigsChecked {
fn default() -> Self {
vec![("uusd", TaxConfigChecked::default())].into()
}
}
impl Default for TaxConfigsUnchecked {
fn default() -> Self {
TaxConfigsChecked::default().into()
}
}
impl TaxConfigUnchecked {
pub fn check(self, api: &dyn Api) -> StdResult<TaxConfigChecked> {
if self.tax_rate > Decimal::percent(50) {
return Err(StdError::generic_err("Tax rate cannot be more than 50%"));
}
let tax_recipient = api.addr_validate(&self.tax_recipient)?;
Ok(TaxConfigChecked {
tax_rate: self.tax_rate,
tax_recipient,
})
}
}
impl TaxConfigsUnchecked {
pub fn new() -> Self {
TaxConfigs(HashMap::new())
}
pub fn check(
self,
api: &dyn Api,
pair_asset_infos: &[AssetInfo],
) -> StdResult<TaxConfigsChecked> {
let mut tax_configs = HashMap::new();
for (tax_denom, tax_config) in self.0.into_iter() {
validate_native_denom(&tax_denom)?;
if !pair_asset_infos.contains(&AssetInfo::native(&tax_denom)) {
return Err(StdError::generic_err(
"Tax denom must be one of the pair assets",
));
}
let tax_config = tax_config.check(api)?;
tax_configs.insert(tax_denom, tax_config);
}
Ok(TaxConfigs(tax_configs))
}
}
impl TaxConfigsChecked {
pub fn get(&self, tax_denom: &str) -> Option<&TaxConfigChecked> {
self.0.get(tax_denom)
}
}
#[cw_serde]
#[derive(Default)]
pub struct SaleTaxConfigUpdates {
pub tax_configs: Option<TaxConfigsUnchecked>,
pub tax_config_admin: Option<String>,
}
#[cw_serde]
pub struct SaleTaxInitParams {
pub tax_configs: TaxConfigs<String>,
pub tax_config_admin: String,
pub track_asset_balances: bool,
}
impl Default for SaleTaxInitParams {
fn default() -> Self {
Self {
tax_config_admin: "addr0000".to_string(),
tax_configs: TaxConfigs::default(),
track_asset_balances: false,
}
}
}
impl SaleTaxInitParams {
pub fn from_json(data: Option<Binary>) -> StdResult<Self> {
data.as_ref()
.map(from_json::<SaleTaxInitParams>)
.transpose()?
.ok_or_else(|| StdError::generic_err("Missing Init params"))
}
}
#[cw_serde]
pub struct MigrateMsg {
pub tax_configs: TaxConfigs<String>,
pub tax_config_admin: String,
}