use std::fmt;
use client_traits::EngineClient;
use common_types::ids::BlockId;
use vapabi;
use vapory_types::Address;
pub struct BoundContract<'a> {
client: &'a dyn EngineClient,
block_id: BlockId,
contract_addr: Address,
}
#[derive(Debug)]
pub enum CallError {
CallFailed(String),
DecodeFailed(vapabi::Error),
NotFullClient,
}
impl<'a> fmt::Debug for BoundContract<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("BoundContract")
.field("client", &(self.client as *const dyn EngineClient))
.field("block_id", &self.block_id)
.field("contract_addr", &self.contract_addr)
.finish()
}
}
impl<'a> BoundContract<'a> {
pub fn new(client: &dyn EngineClient, block_id: BlockId, contract_addr: Address) -> BoundContract {
BoundContract {
client,
block_id,
contract_addr,
}
}
pub fn call_const<D>(&self, call: (vapabi::Bytes, D)) -> Result<D::Output, CallError>
where
D: vapabi::FunctionOutputDecoder,
{
let (data, output_decoder) = call;
let call_return = self
.client
.as_full_client()
.ok_or(CallError::NotFullClient)?
.call_contract(self.block_id, self.contract_addr, data)
.map_err(CallError::CallFailed)?;
output_decoder
.decode(call_return.as_slice())
.map_err(CallError::DecodeFailed)
}
}