use crate::{
call::{
utils::{
EmptyArgumentList,
ReturnType,
Set,
Unset,
Unwrap,
},
ExecutionInput,
},
Environment,
Error,
};
use core::marker::PhantomData;
#[derive(Debug)]
pub struct CallParams<E, Args, R>
where
E: Environment,
{
callee: E::AccountId,
gas_limit: u64,
transferred_value: E::Balance,
return_type: ReturnType<R>,
exec_input: ExecutionInput<Args>,
}
#[cfg(
// We do not currently support cross-contract calling in the off-chain
// environment so we do not have to provide these getters in case of
// off-chain environment compilation.
all(not(feature = "std"), target_arch = "wasm32")
)]
impl<E, Args, R> CallParams<E, Args, R>
where
E: Environment,
{
#[inline]
pub(crate) fn callee(&self) -> &E::AccountId {
&self.callee
}
#[inline]
pub(crate) fn gas_limit(&self) -> u64 {
self.gas_limit
}
#[inline]
pub(crate) fn transferred_value(&self) -> &E::Balance {
&self.transferred_value
}
#[inline]
pub(crate) fn exec_input(&self) -> &ExecutionInput<Args> {
&self.exec_input
}
}
impl<E, Args> CallParams<E, Args, ()>
where
E: Environment,
Args: scale::Encode,
{
pub fn invoke(&self) -> Result<(), crate::Error> {
crate::invoke_contract(self)
}
}
impl<E, Args, R> CallParams<E, Args, ReturnType<R>>
where
E: Environment,
Args: scale::Encode,
R: scale::Decode,
{
pub fn eval(&self) -> Result<R, crate::Error> {
crate::eval_contract(self)
}
}
#[allow(clippy::type_complexity)]
pub fn build_call<E>() -> CallBuilder<
E,
Unset<E::AccountId>,
Unset<u64>,
Unset<E::Balance>,
Unset<ExecutionInput<EmptyArgumentList>>,
Unset<ReturnType<()>>,
>
where
E: Environment,
{
CallBuilder {
env: Default::default(),
callee: Default::default(),
gas_limit: Default::default(),
transferred_value: Default::default(),
exec_input: Default::default(),
return_type: Default::default(),
}
}
pub struct CallBuilder<E, Callee, GasLimit, TransferredValue, Args, RetType>
where
E: Environment,
{
env: PhantomData<fn() -> E>,
callee: Callee,
gas_limit: GasLimit,
transferred_value: TransferredValue,
exec_input: Args,
return_type: RetType,
}
impl<E, GasLimit, TransferredValue, Args, RetType>
CallBuilder<E, Unset<E::AccountId>, GasLimit, TransferredValue, Args, RetType>
where
E: Environment,
{
#[inline]
pub fn callee(
self,
callee: E::AccountId,
) -> CallBuilder<E, Set<E::AccountId>, GasLimit, TransferredValue, Args, RetType>
{
CallBuilder {
env: Default::default(),
callee: Set(callee),
gas_limit: self.gas_limit,
transferred_value: self.transferred_value,
exec_input: self.exec_input,
return_type: self.return_type,
}
}
}
impl<E, Callee, TransferredValue, Args, RetType>
CallBuilder<E, Callee, Unset<u64>, TransferredValue, Args, RetType>
where
E: Environment,
{
#[inline]
pub fn gas_limit(
self,
gas_limit: u64,
) -> CallBuilder<E, Callee, Set<u64>, TransferredValue, Args, RetType> {
CallBuilder {
env: Default::default(),
callee: self.callee,
gas_limit: Set(gas_limit),
transferred_value: self.transferred_value,
exec_input: self.exec_input,
return_type: self.return_type,
}
}
}
impl<E, Callee, GasLimit, Args, RetType>
CallBuilder<E, Callee, GasLimit, Unset<E::Balance>, Args, RetType>
where
E: Environment,
{
#[inline]
pub fn transferred_value(
self,
transferred_value: E::Balance,
) -> CallBuilder<E, Callee, GasLimit, Set<E::Balance>, Args, RetType> {
CallBuilder {
env: Default::default(),
callee: self.callee,
gas_limit: self.gas_limit,
transferred_value: Set(transferred_value),
exec_input: self.exec_input,
return_type: self.return_type,
}
}
}
mod seal {
pub trait Sealed {}
impl Sealed for () {}
impl<T> Sealed for super::ReturnType<T> {}
}
pub trait IndicateReturnType: Default + self::seal::Sealed {}
impl IndicateReturnType for () {}
impl<T> IndicateReturnType for ReturnType<T> {}
impl<E, Callee, GasLimit, TransferredValue, Args>
CallBuilder<E, Callee, GasLimit, TransferredValue, Args, Unset<ReturnType<()>>>
where
E: Environment,
{
#[inline]
pub fn returns<R>(
self,
) -> CallBuilder<E, Callee, GasLimit, TransferredValue, Args, Set<R>>
where
R: IndicateReturnType,
{
CallBuilder {
env: Default::default(),
callee: self.callee,
gas_limit: self.gas_limit,
transferred_value: self.transferred_value,
exec_input: self.exec_input,
return_type: Set(Default::default()),
}
}
}
impl<E, Callee, GasLimit, TransferredValue, RetType>
CallBuilder<
E,
Callee,
GasLimit,
TransferredValue,
Unset<ExecutionInput<EmptyArgumentList>>,
RetType,
>
where
E: Environment,
{
pub fn exec_input<Args>(
self,
exec_input: ExecutionInput<Args>,
) -> CallBuilder<
E,
Callee,
GasLimit,
TransferredValue,
Set<ExecutionInput<Args>>,
RetType,
> {
CallBuilder {
env: Default::default(),
callee: self.callee,
gas_limit: self.gas_limit,
transferred_value: self.transferred_value,
exec_input: Set(exec_input),
return_type: self.return_type,
}
}
}
impl<E, GasLimit, TransferredValue, Args, RetType>
CallBuilder<
E,
Set<E::AccountId>,
GasLimit,
TransferredValue,
Set<ExecutionInput<Args>>,
Set<RetType>,
>
where
E: Environment,
GasLimit: Unwrap<Output = u64>,
TransferredValue: Unwrap<Output = E::Balance>,
{
pub fn params(self) -> CallParams<E, Args, RetType> {
CallParams {
callee: self.callee.value(),
gas_limit: self.gas_limit.unwrap_or_else(|| 0),
transferred_value: self
.transferred_value
.unwrap_or_else(|| E::Balance::from(0u32)),
return_type: Default::default(),
exec_input: self.exec_input.value(),
}
}
}
impl<E, GasLimit, TransferredValue, Args>
CallBuilder<
E,
Set<E::AccountId>,
GasLimit,
TransferredValue,
Set<ExecutionInput<Args>>,
Set<()>,
>
where
E: Environment,
GasLimit: Unwrap<Output = u64>,
Args: scale::Encode,
TransferredValue: Unwrap<Output = E::Balance>,
{
pub fn fire(self) -> Result<(), Error> {
self.params().invoke()
}
}
impl<E, GasLimit, TransferredValue, Args, R>
CallBuilder<
E,
Set<E::AccountId>,
GasLimit,
TransferredValue,
Set<ExecutionInput<Args>>,
Set<ReturnType<R>>,
>
where
E: Environment,
GasLimit: Unwrap<Output = u64>,
Args: scale::Encode,
R: scale::Decode,
TransferredValue: Unwrap<Output = E::Balance>,
{
pub fn fire(self) -> Result<R, Error> {
self.params().eval()
}
}