use std::cell::RefCell;
use std::rc::Rc;
use cosmwasm_std::testing::MockApi;
use cosmwasm_std::{Addr, Coin, Uint128};
use cw_multi_test::AppBuilder;
use cw_orch_core::environment::{BankQuerier, BankSetter, TxHandler};
use cw_orch_core::{
environment::{DefaultQueriers, StateInterface},
CwEnvError,
};
use cw_utils::NativeBalance;
use crate::queriers::bank::MockBankQuerier;
use crate::{Mock, MockState};
impl<S: StateInterface> Mock<S> {
pub fn set_balance(
&self,
address: impl Into<String>,
amount: Vec<cosmwasm_std::Coin>,
) -> Result<(), CwEnvError> {
self.app
.borrow_mut()
.init_modules(|router, _, storage| {
router
.bank
.init_balance(storage, &Addr::unchecked(address.into()), amount)
})
.map_err(Into::into)
}
pub fn add_balance(
&self,
address: impl Into<String>,
amount: Vec<cosmwasm_std::Coin>,
) -> Result<(), CwEnvError> {
let addr = &Addr::unchecked(address.into());
let b = self.query_all_balances(addr.clone())?;
let new_amount = NativeBalance(b) + NativeBalance(amount);
self.app
.borrow_mut()
.init_modules(|router, _, storage| {
router
.bank
.init_balance(storage, addr, new_amount.into_vec())
})
.map_err(Into::into)
}
pub fn set_balances(
&self,
balances: &[(impl Into<String> + Clone, &[cosmwasm_std::Coin])],
) -> Result<(), CwEnvError> {
self.app
.borrow_mut()
.init_modules(|router, _, storage| -> Result<(), CwEnvError> {
for (addr, coins) in balances {
router.bank.init_balance(
storage,
&Addr::unchecked(addr.clone()),
coins.to_vec(),
)?;
}
Ok(())
})
}
pub fn query_balance(
&self,
address: impl Into<String>,
denom: &str,
) -> Result<Uint128, CwEnvError> {
Ok(self
.bank_querier()
.balance(address, Some(denom.to_string()))?
.first()
.map(|c| c.amount)
.unwrap_or_default())
}
pub fn query_all_balances(
&self,
address: impl Into<String>,
) -> Result<Vec<cosmwasm_std::Coin>, CwEnvError> {
self.bank_querier().balance(address, None)
}
}
impl Mock {
pub fn new(sender: impl Into<String>) -> Self {
Mock::new_custom(sender, MockState::new())
}
pub fn new_with_chain_id(sender: impl Into<String>, chain_id: &str) -> Self {
let chain = Mock::new_custom(sender, MockState::new());
chain
.app
.borrow_mut()
.update_block(|b| b.chain_id = chain_id.to_string());
chain
}
}
impl<S: StateInterface> Mock<S> {
pub fn new_custom(sender: impl Into<String>, custom_state: S) -> Self {
let state = Rc::new(RefCell::new(custom_state));
let app = Rc::new(RefCell::new(AppBuilder::new_custom().build(|_, _, _| {})));
Self {
sender: Addr::unchecked(sender),
state,
app,
}
}
}
impl<S: StateInterface> BankSetter for Mock<S> {
type T = MockBankQuerier<MockApi>;
fn set_balance(
&mut self,
address: impl Into<String>,
amount: Vec<Coin>,
) -> Result<(), <Self as TxHandler>::Error> {
(*self).set_balance(address, amount)
}
}