use anyhow::Result as AnyResult;
use cosmwasm_schema::serde::de::DeserializeOwned;
use cosmwasm_std::{
coins, to_json_binary, Addr, AnyMsg, Api, BankMsg, Binary, BlockInfo, CustomMsg, CustomQuery,
MsgResponse, Querier, Storage, SubMsgResponse,
};
use cw_multi_test::{AppResponse, BankSudo, CosmosRouter, Stargate};
use osmosis_std::types::cosmos::base::v1beta1::Coin;
use osmosis_std::types::osmosis::tokenfactory::v1beta1::{Params, QueryParamsResponse};
use lotus_tokenfactory::burn::MsgBurn;
use lotus_tokenfactory::common::EncodeMessage;
use lotus_tokenfactory::create_denom::{MsgCreateDenom, MsgCreateDenomResponse};
use lotus_tokenfactory::mint::MsgMint;
pub struct StargateMock {
pub fees: Vec<cosmwasm_std::Coin>,
}
impl StargateMock {
pub fn new(fees: Vec<cosmwasm_std::Coin>) -> Self {
Self { fees }
}
#[allow(clippy::too_many_arguments)]
fn handle_stargate_any<ExecC, QueryC>(
&self,
api: &dyn Api,
storage: &mut dyn Storage,
router: &dyn CosmosRouter<ExecC = ExecC, QueryC = QueryC>,
block: &BlockInfo,
sender: Addr,
type_url: String,
value: Binary,
) -> AnyResult<AppResponse>
where
ExecC: CustomMsg + DeserializeOwned + 'static,
QueryC: CustomQuery + DeserializeOwned + 'static,
{
#[allow(deprecated)]
match type_url.as_str() {
"/osmosis.tokenfactory.v1beta1.MsgCreateDenom" => {
let tf_msg: MsgCreateDenom = MsgCreateDenom::decode(value.into())?;
let submsg_response = SubMsgResponse {
events: vec![],
data: Some(to_json_binary(&MsgCreateDenomResponse {
new_token_denom: format!("factory/{}/{}", tf_msg.sender, tf_msg.subdenom),
})?),
msg_responses: vec![MsgResponse {
type_url,
value: to_json_binary(&MsgCreateDenomResponse {
new_token_denom: format!(
"factory/{}/{}",
tf_msg.sender, tf_msg.subdenom
),
})?,
}],
};
let burn_msg = BankMsg::Burn {
amount: self.fees.clone(),
};
router.execute(
api,
storage,
block,
Addr::unchecked(tf_msg.sender),
burn_msg.into(),
)?;
Ok(submsg_response.into())
}
"/osmosis.tokenfactory.v1beta1.MsgMint" => {
let tf_msg: MsgMint = MsgMint::decode(value.into())?;
let mint_coins = tf_msg.amount;
let bank_sudo = BankSudo::Mint {
to_address: tf_msg.mint_to_address,
amount: coins(mint_coins.amount.u128(), mint_coins.denom),
};
router.sudo(api, storage, block, bank_sudo.into())
}
"/osmosis.tokenfactory.v1beta1.MsgBurn" => {
let tf_msg: MsgBurn = MsgBurn::decode(value.into())?;
let burn_coins = tf_msg.amount;
let burn_msg = BankMsg::Burn {
amount: coins(burn_coins.amount.u128(), burn_coins.denom),
};
router.execute(
api,
storage,
block,
Addr::unchecked(tf_msg.sender),
burn_msg.into(),
)
}
_ => Err(anyhow::anyhow!(
"Unexpected exec msg {type_url} from {sender:?}",
)),
}
}
}
impl Stargate for StargateMock {
fn execute_any<ExecC, QueryC>(
&self,
api: &dyn Api,
storage: &mut dyn Storage,
router: &dyn CosmosRouter<ExecC = ExecC, QueryC = QueryC>,
block: &BlockInfo,
sender: Addr,
msg: AnyMsg,
) -> AnyResult<AppResponse>
where
ExecC: CustomMsg + DeserializeOwned + 'static,
QueryC: CustomQuery + DeserializeOwned + 'static,
{
self.handle_stargate_any(api, storage, router, block, sender, msg.type_url, msg.value)
}
fn execute_stargate<ExecC, QueryC>(
&self,
api: &dyn Api,
storage: &mut dyn Storage,
router: &dyn CosmosRouter<ExecC = ExecC, QueryC = QueryC>,
block: &BlockInfo,
sender: Addr,
type_url: String,
value: Binary,
) -> AnyResult<AppResponse>
where
ExecC: CustomMsg + DeserializeOwned + 'static,
QueryC: CustomQuery + DeserializeOwned + 'static,
{
self.handle_stargate_any(api, storage, router, block, sender, type_url, value)
}
fn query_stargate(
&self,
_api: &dyn Api,
_storage: &dyn Storage,
_querier: &dyn Querier,
_block: &BlockInfo,
path: String,
_data: Binary,
) -> AnyResult<Binary> {
let mut fees: Vec<Coin> = vec![];
for fee in self.fees.iter() {
fees.push(Coin {
denom: fee.denom.clone(),
amount: fee.amount.u128().to_string(),
});
}
match path.as_str() {
"/osmosis.tokenfactory.v1beta1.Query/Params" => {
Ok(to_json_binary(&QueryParamsResponse {
params: Some(Params {
denom_creation_fee: fees,
denom_creation_gas_consume: 0,
}),
})?)
}
_ => Err(anyhow::anyhow!("Unexpected stargate query request {path}",)),
}
}
}