pub struct ContractEnsemble { /* private fields */ }
Expand description

This the main type in the system that takes care of registering and executing contracts, keeping the blockchain simulation state and allowing the manipulation of particular parameters such as account funds, blocks or contract state in order to efficiently simulate testing scenarios.

Examples

use fadroma::{
    cosmwasm_std::{Deps, DepsMut, Env, MessageInfo, Response, Binary, from_binary, to_binary},
    storage::{load, save},
    ensemble::{ContractEnsemble, ContractHarness, MockEnv, EnsembleResult, AnyResult},
    serde::{Serialize, Deserialize},
    schemars::JsonSchema
};
 
const NUMBER_KEY: &[u8] = b"number";
 
struct Counter;
 
#[derive(Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
enum ExecuteMsg {
    Increment,
    Reset
}
 
impl ContractHarness for Counter {
    fn instantiate(&self, deps: DepsMut, env: Env, info: MessageInfo, _msg: Binary) -> AnyResult<Response> {
        Ok(Response::default())
    }

    fn execute(&self, deps: DepsMut, env: Env, info: MessageInfo, msg: Binary) -> AnyResult<Response> {
        match from_binary(&msg)? {
            ExecuteMsg::Increment => {
                let mut number: u64 = load(deps.storage, NUMBER_KEY)?.unwrap_or_default();
                number += 1;
 
                save(deps.storage, NUMBER_KEY, &number)?;
            },
            ExecuteMsg::Reset => save(deps.storage, NUMBER_KEY, &0u64)?
        };
  
        Ok(Response::default())
    }

    fn query(&self, deps: Deps, env: Env, _msg: Binary) -> AnyResult<Binary> {
        let number: u64 = load(deps.storage, NUMBER_KEY)?.unwrap_or_default();
        let number = to_binary(&number)?;
 
        Ok(number)
    }
}
 
let mut ensemble = ContractEnsemble::new();
let counter = ensemble.register(Box::new(Counter));
let counter = ensemble.instantiate(
    counter.id,
    &(),
    MockEnv::new("sender", "counter_address")
)
.unwrap()
.instance;
 
ensemble.execute(
    &ExecuteMsg::Increment,
    MockEnv::new("sender", counter.address.clone())
).unwrap();
 
let number: u64 = ensemble.query(&counter.address, &()).unwrap();
assert_eq!(number, 1);
 
ensemble.execute(
    &ExecuteMsg::Reset,
    MockEnv::new("sender", counter.address.clone())
).unwrap();
 
let number: u64 = ensemble.query(&counter.address, &()).unwrap();
assert_eq!(number, 0);

Implementations§

source§

impl ContractEnsemble

source

pub fn new() -> Self

Creates a new instance of the ensemble that will use “uscrt” as the native coin when the scrt feature is enabled. Otherwise, will use uatom.

source

pub fn new_with_denom(native_denom: impl Into<String>) -> Self

Creates a new instance of the ensemble that will use the provided denomination as the native coin.

source

pub fn register(&mut self, code: Box<dyn ContractHarness>) -> ContractCode

Registers a contract with the ensemble which enables it to be called by the sender or by other contracts. Corresponds to the upload step of the real chain.

Returns the code id that must be use to create an instance of it and its unique code hash.

source

pub fn block(&self) -> &Block

Returns a reference to the current block state.

source

pub fn block_mut(&mut self) -> &mut Block

Returns a mutable reference to the current block state. Can be used to manually advance the block time and height or configure the auto advancement strategy. Auto advancement occurs on successful message execution.

source

pub fn set_chain_id(&mut self, id: impl Into<String>)

Sets that chain id string i.e env.block.chain_id.

source

pub fn add_funds(&mut self, address: impl AsRef<str>, coins: Vec<Coin>)

Adds the given funds that will be associated with the provided account’s address. Can either be a contract or a mock user’s address. You need to use this method first if you want to send a contract funds when using MockEnv::sent_funds.

source

pub fn remove_funds( &mut self, address: impl AsRef<str>, coin: Coin ) -> EnsembleResult<()>

Removes the given funds from the provided account’s address. Can either be a contract or a mock user’s address. The account must already exist and have at least the given amount in order for this to be a success.

source

pub fn transfer_funds( &mut self, from: impl AsRef<str>, to: impl AsRef<str>, coin: Coin ) -> EnsembleResult<()>

Transfers funds from one account to another. The from address must have the sufficient amount.

source

pub fn balances( &self, address: impl AsRef<str> ) -> Option<&HashMap<String, Uint128>>

Returns a reference to all the balances associated with the given account. Returns None if the account doesn’t exist or hasn’t received any funds before.

Examples
use fadroma::{
    ensemble::ContractEnsemble,
    cosmwasm_std::coin
};
 
let mut ensemble = ContractEnsemble::new();
ensemble.add_funds("wallet", vec![coin(100, "uscrt")]);
 
let balances = ensemble.balances("wallet").unwrap();
assert_eq!(balances.get("uscrt").unwrap().u128(), 100);
 
assert!(ensemble.balances("absent").is_none());
source

pub fn balances_mut( &mut self, address: impl AsRef<str> ) -> Option<&mut HashMap<String, Uint128>>

Returns a mutable reference to all the balances associated with the given account. Returns None if the account doesn’t exist or hasn’t received any funds before.

Examples
use fadroma::{
    ensemble::ContractEnsemble,
    cosmwasm_std::{Uint128, coin}
};
 
let mut ensemble = ContractEnsemble::new();
ensemble.add_funds("wallet", vec![coin(100, "uscrt")]);
 
let balances = ensemble.balances_mut("wallet").unwrap();
let uscrt_balance = balances.get_mut("uscrt").unwrap();
*uscrt_balance -= Uint128::from(50u128);

let balances = ensemble.balances("wallet").unwrap();
assert_eq!(balances.get("uscrt").unwrap().u128(), 50);

assert!(ensemble.balances("absent").is_none());
source

pub fn delegations(&self, address: impl AsRef<str>) -> Vec<Delegation>

Returns all active delegations associated with the given address.

source

pub fn delegation( &self, delegator: impl AsRef<str>, validator: impl AsRef<str> ) -> Option<FullDelegation>

Creates a new delegation for the given address using the given validator.

source

pub fn add_validator(&mut self, validator: Validator)

Adds the validator to the validator list.

source

pub fn add_rewards(&mut self, amount: impl Into<Uint128>)

Distributes the given amount as rewards.

source

pub fn fast_forward_delegation_waits(&mut self)

Re-allow redelegating and deposit unbondings.

source

pub fn contract_storage<F>( &self, address: impl AsRef<str>, borrow: F ) -> EnsembleResult<()>where F: FnOnce(&dyn Storage),

Provides read access to the storage associated with the given contract address.

Returns Err if a contract with address wasn’t found.

source

pub fn contract_storage_mut<F>( &mut self, address: impl AsRef<str>, mutate: F ) -> EnsembleResult<()>where F: FnOnce(&mut dyn Storage) -> EnsembleResult<()>,

Provides write access to the storage associated with the given contract address.

Returns an Err if a contract with address wasn’t found. In case an error is returned from the closure, the updates to that storage are discarded.

source

pub fn instantiate<T: Serialize>( &mut self, code_id: u64, msg: &T, env: MockEnv ) -> EnsembleResult<InstantiateResponse>

Creates a new contract instance using the given code id. The code id must be obtained by calling the ContractEnsemble::register method first.

The contract will be assigned the address the was provided with the env.contract parameter.

The instance field of the response will contain this address and the code hash associated with this instance.

source

pub fn execute<T: Serialize + ?Sized>( &mut self, msg: &T, env: MockEnv ) -> EnsembleResult<ExecuteResponse>

Executes the contract with the address provided in env.contract.

source

pub fn query<T: Serialize + ?Sized, R: DeserializeOwned>( &self, address: impl AsRef<str>, msg: &T ) -> EnsembleResult<R>

Queries the contract associated with the given address and attempts to deserialize its response to the given type parameter.

source

pub fn query_raw<T: Serialize + ?Sized>( &self, address: impl AsRef<str>, msg: &T ) -> EnsembleResult<Binary>

Queries the contract associated with the given address without attempting to deserialize its response.

Trait Implementations§

source§

impl Debug for ContractEnsemble

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for Twhere V: MultiLane<T>,

§

fn vzip(self) -> V