use ink::codegen::ContractCallBuilder;
use ink_env::{
call::FromAccountId,
Environment,
};
use ink_primitives::MessageResult;
use pallet_contracts_primitives::{
CodeUploadResult,
ContractExecResult,
ContractInstantiateResult,
ExecReturnValue,
};
use std::{
fmt::Debug,
marker::PhantomData,
};
pub struct InstantiationResult<E: Environment, EventLog> {
pub account_id: E::AccountId,
pub dry_run: ContractInstantiateResult<E::AccountId, E::Balance, ()>,
pub events: EventLog,
}
impl<E: Environment, EventLog> InstantiationResult<E, EventLog> {
pub fn call<Contract>(&self) -> <Contract as ContractCallBuilder>::Type
where
Contract: ContractCallBuilder,
Contract::Type: FromAccountId<E>,
{
<<Contract as ContractCallBuilder>::Type as FromAccountId<E>>::from_account_id(
self.account_id.clone(),
)
}
}
impl<E: Environment, EventLog> Debug for InstantiationResult<E, EventLog>
where
E::AccountId: Debug,
E::Balance: Debug,
EventLog: Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.debug_struct("InstantiationResult")
.field("account_id", &self.account_id)
.field("dry_run", &self.dry_run)
.field("events", &self.events)
.finish()
}
}
pub struct UploadResult<E: Environment, EventLog> {
pub code_hash: E::Hash,
pub dry_run: CodeUploadResult<E::Hash, E::Balance>,
pub events: EventLog,
}
impl<E: Environment, EventLog> Debug for UploadResult<E, EventLog>
where
E::Balance: Debug,
E::Hash: Debug,
EventLog: Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.debug_struct("UploadResult")
.field("code_hash", &self.code_hash)
.field("dry_run", &self.dry_run)
.field("events", &self.events)
.finish()
}
}
pub struct CallResult<E: Environment, V, EventLog> {
pub dry_run: CallDryRunResult<E, V>,
pub events: EventLog,
}
impl<E: Environment, V: scale::Decode, EventLog> CallResult<E, V, EventLog> {
pub fn message_result(&self) -> MessageResult<V> {
self.dry_run.message_result()
}
pub fn return_value(self) -> V {
self.dry_run.return_value()
}
pub fn return_data(&self) -> &[u8] {
&self.dry_run.exec_return_value().data
}
pub fn debug_message(&self) -> String {
self.dry_run.debug_message()
}
}
impl<E: Environment, V, EventLog> Debug for CallResult<E, V, EventLog>
where
E: Debug,
E::Balance: Debug,
V: Debug,
EventLog: Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.debug_struct("CallResult")
.field("dry_run", &self.dry_run)
.field("events", &self.events)
.finish()
}
}
#[derive(Debug)]
pub struct CallDryRunResult<E: Environment, V> {
pub exec_result: ContractExecResult<E::Balance, ()>,
pub _marker: PhantomData<V>,
}
impl<E: Environment, V: scale::Decode> CallDryRunResult<E, V> {
pub fn is_err(&self) -> bool {
self.exec_result.result.is_err()
}
pub fn exec_return_value(&self) -> &ExecReturnValue {
self.exec_result
.result
.as_ref()
.unwrap_or_else(|call_err| panic!("Call dry-run failed: {call_err:?}"))
}
pub fn message_result(&self) -> MessageResult<V> {
let data = &self.exec_return_value().data;
scale::Decode::decode(&mut data.as_ref()).unwrap_or_else(|env_err| {
panic!(
"Decoding dry run result to ink! message return type failed: {env_err}"
)
})
}
pub fn return_value(self) -> V {
self.message_result()
.unwrap_or_else(|lang_err| {
panic!(
"Encountered a `LangError` while decoding dry run result to ink! message: {lang_err:?}"
)
})
}
pub fn return_data(&self) -> &[u8] {
&self.exec_return_value().data
}
pub fn debug_message(&self) -> String {
String::from_utf8_lossy(&self.exec_result.debug_message).into()
}
}