use ink::codegen::ContractCallBuilder;
use ink_env::{
call::FromAccountId,
Environment,
};
use ink_primitives::{
ConstructorResult,
MessageResult,
};
use pallet_contracts::{
CodeUploadResult,
ContractExecResult,
ContractInstantiateResult,
ExecReturnValue,
InstantiateReturnValue,
};
use std::{
fmt,
fmt::Debug,
marker::PhantomData,
};
pub struct BareInstantiationResult<E: Environment, EventLog> {
pub account_id: E::AccountId,
pub events: EventLog,
}
impl<E: Environment, EventLog> BareInstantiationResult<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 BareInstantiationResult<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("events", &self.events)
.finish()
}
}
pub struct InstantiationResult<E: Environment, EventLog> {
pub account_id: E::AccountId,
pub dry_run: InstantiateDryRunResult<E>,
pub events: EventLog,
}
impl<E: Environment, EventLog> InstantiationResult<E, EventLog> {
pub fn call_builder<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()
}
}
pub struct InstantiateDryRunResult<E: Environment> {
pub contract_result: ContractInstantiateResult<E::AccountId, E::Balance, ()>,
}
impl<E: Environment> From<ContractInstantiateResult<E::AccountId, E::Balance, ()>>
for InstantiateDryRunResult<E>
{
fn from(
contract_result: ContractInstantiateResult<E::AccountId, E::Balance, ()>,
) -> Self {
Self { contract_result }
}
}
impl<E: Environment> InstantiateDryRunResult<E> {
pub fn is_err(&self) -> bool {
self.contract_result.result.is_err()
}
pub fn instantiate_return_value(&self) -> &InstantiateReturnValue<E::AccountId> {
self.contract_result
.result
.as_ref()
.unwrap_or_else(|call_err| panic!("Instantiate dry-run failed: {call_err:?}"))
}
pub fn constructor_result<V: scale::Decode>(&self) -> ConstructorResult<V> {
let data = &self.instantiate_return_value().result.data;
scale::Decode::decode(&mut data.as_ref()).unwrap_or_else(|env_err| {
panic!("Decoding dry run result to constructor return type failed: {env_err}")
})
}
pub fn debug_message(&self) -> String {
String::from_utf8_lossy(&self.contract_result.debug_message).into()
}
}
impl<E> Debug for InstantiateDryRunResult<E>
where
E: Environment,
E::AccountId: Debug,
E::Balance: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("InstantiateDryRunResult")
.field("contract_result", &self.contract_result)
.finish()
}
}