use std::{collections::BTreeMap, panic::AssertUnwindSafe};
use odra_mock_vm_types::{
Address, Balance, BlockTime, BorshDeserialize, Bytes, CallArgs, MockDeserializable,
MockSerializable, PublicKey
};
use odra_types::{
address::OdraAddress,
event::{EventError, OdraEvent},
OdraError
};
use crate::{native_token::NativeTokenMetadata, EntrypointArgs, EntrypointCall};
macro_rules! delegate_to_env {
(
$(
$(#[$outer:meta])*
fn $func_name:ident($( $param_ident:ident : $param_ty:ty ),*) $( -> $ret:ty)*
)+
) => {
$(
$(#[$outer])*
pub fn $func_name( $($param_ident : $param_ty),* ) $(-> $ret)* {
crate::borrow_env().$func_name($($param_ident),*)
}
)+
}
}
delegate_to_env! {
fn register_contract(
constructor: Option<(String, &CallArgs, EntrypointCall)>,
constructors: BTreeMap<String, (EntrypointArgs, EntrypointCall)>,
entrypoints: BTreeMap<String, (EntrypointArgs, EntrypointCall)>
) -> Address
fn advance_block_time_by(milliseconds: BlockTime)
fn get_backend_name() -> String
fn set_caller(address: Address)
fn token_balance(address: Address) -> Balance
fn get_account(n: usize) -> Address
}
pub fn assert_exception<F, E>(err: E, block: F)
where
F: FnOnce(),
E: Into<OdraError>
{
let _ = std::panic::catch_unwind(AssertUnwindSafe(|| {
block();
}));
let exec_err = crate::borrow_env()
.error()
.expect("An error expected, but did not occur");
assert_eq!(exec_err, err.into());
}
pub fn one_token() -> Balance {
Balance::one()
}
pub fn call_contract<T: MockSerializable + MockDeserializable>(
address: Address,
entrypoint: &str,
args: &CallArgs,
amount: Option<Balance>
) -> T {
crate::borrow_env().call_contract(address, entrypoint, args, amount)
}
pub fn get_event<T: MockSerializable + MockDeserializable + OdraEvent>(
address: Address,
index: i32
) -> Result<T, EventError> {
let bytes = crate::borrow_env().get_event(address, index);
bytes.and_then(|bytes| {
let event_name = extract_event_name(&bytes)?;
if event_name == T::name() {
T::deser(bytes).map_err(|_| EventError::Parsing)
} else {
Err(EventError::UnexpectedType(event_name))
}
})
}
pub fn native_token_metadata() -> NativeTokenMetadata {
NativeTokenMetadata::new()
}
pub fn last_call_contract_gas_cost() -> Balance {
Balance::zero()
}
pub fn last_call_contract_gas_used() -> Balance {
Balance::zero()
}
pub fn total_gas_used(address: Address) -> Balance {
if address.is_contract() {
panic!("Contract {:?} can't burn gas.", address)
}
Balance::zero()
}
pub fn gas_report() -> Vec<(String, Balance)> {
Vec::new()
}
fn extract_event_name(mut bytes: &[u8]) -> Result<String, EventError> {
let name = BorshDeserialize::deserialize(&mut bytes).map_err(|_| EventError::Formatting)?;
Ok(name)
}
pub fn sign_message(message: &Bytes, address: &Address) -> Bytes {
let public_key = public_key(address);
let mut message = message.inner_bytes().clone();
message.extend_from_slice(public_key.inner_bytes());
Bytes::from(message)
}
pub fn public_key(address: &Address) -> PublicKey {
PublicKey(*address)
}