use crate::{
backend::CallFlags,
call::{
utils::{
EmptyArgumentList,
ReturnType,
Set,
Unset,
},
ExecutionInput,
},
types::Gas,
Clear,
Environment,
Error,
};
use core::marker::PhantomData;
use num_traits::Zero;
#[derive(Debug)]
pub struct CallParams<E, CallType, Args, R>
where
E: Environment,
{
call_type: CallType,
call_flags: CallFlags,
_return_type: ReturnType<R>,
exec_input: ExecutionInput<Args>,
_phantom: PhantomData<fn() -> E>,
}
impl<E, CallType, Args, R> CallParams<E, CallType, Args, R>
where
E: Environment,
{
#[inline]
pub(crate) fn call_flags(&self) -> &CallFlags {
&self.call_flags
}
#[inline]
pub(crate) fn exec_input(&self) -> &ExecutionInput<Args> {
&self.exec_input
}
}
impl<E, Args, R> CallParams<E, Call<E>, Args, R>
where
E: Environment,
{
#[inline]
pub(crate) fn callee(&self) -> &E::AccountId {
&self.call_type.callee
}
#[inline]
pub(crate) fn gas_limit(&self) -> Gas {
self.call_type.gas_limit
}
#[inline]
pub(crate) fn transferred_value(&self) -> &E::Balance {
&self.call_type.transferred_value
}
}
impl<E, Args, R> CallParams<E, DelegateCall<E>, Args, R>
where
E: Environment,
{
#[inline]
pub(crate) fn code_hash(&self) -> &E::Hash {
&self.call_type.code_hash
}
}
impl<E, Args, R> CallParams<E, Call<E>, Args, R>
where
E: Environment,
Args: scale::Encode,
R: scale::Decode,
{
pub fn invoke(&self) -> Result<R, crate::Error> {
crate::invoke_contract(self)
}
}
impl<E, Args, R> CallParams<E, DelegateCall<E>, Args, R>
where
E: Environment,
Args: scale::Encode,
R: scale::Decode,
{
pub fn invoke(&self) -> Result<R, crate::Error> {
crate::invoke_contract_delegate(self)
}
}
#[allow(clippy::type_complexity)]
pub fn build_call<E>() -> CallBuilder<
E,
Unset<Call<E>>,
Unset<ExecutionInput<EmptyArgumentList>>,
Unset<ReturnType<()>>,
>
where
E: Environment,
{
CallBuilder {
call_type: Default::default(),
call_flags: Default::default(),
exec_input: Default::default(),
return_type: Default::default(),
_phantom: Default::default(),
}
}
pub struct Call<E: Environment> {
callee: E::AccountId,
gas_limit: Gas,
transferred_value: E::Balance,
}
impl<E: Environment> Default for Call<E> {
fn default() -> Self {
Call {
callee: Default::default(),
gas_limit: Default::default(),
transferred_value: E::Balance::zero(),
}
}
}
impl<E: Environment> Call<E> {
pub fn new() -> Self {
Default::default()
}
}
impl<E> Call<E>
where
E: Environment,
{
pub fn callee(self, callee: E::AccountId) -> Self {
Call {
callee,
gas_limit: self.gas_limit,
transferred_value: self.transferred_value,
}
}
pub fn gas_limit(self, gas_limit: Gas) -> Self {
Call {
callee: self.callee,
gas_limit,
transferred_value: self.transferred_value,
}
}
pub fn transferred_value(self, transferred_value: E::Balance) -> Self {
Call {
callee: self.callee,
gas_limit: self.gas_limit,
transferred_value,
}
}
}
pub struct DelegateCall<E: Environment> {
code_hash: E::Hash,
}
impl<E: Environment> DelegateCall<E> {
pub fn new() -> Self {
Default::default()
}
}
impl<E: Environment> Default for DelegateCall<E> {
fn default() -> Self {
DelegateCall {
code_hash: E::Hash::clear(),
}
}
}
impl<E: Environment> DelegateCall<E> {
pub fn code_hash(self, code_hash: E::Hash) -> Self {
DelegateCall { code_hash }
}
}
pub struct CallBuilder<E, CallType, Args, RetType>
where
E: Environment,
{
call_type: CallType,
call_flags: CallFlags,
exec_input: Args,
return_type: RetType,
_phantom: PhantomData<fn() -> E>,
}
impl<E, CallType, Args, RetType> CallBuilder<E, Unset<CallType>, Args, RetType>
where
E: Environment,
{
#[inline]
#[must_use]
pub fn call_type<NewCallType>(
self,
call_type: NewCallType,
) -> CallBuilder<E, Set<NewCallType>, Args, RetType> {
CallBuilder {
call_type: Set(call_type),
call_flags: self.call_flags,
exec_input: self.exec_input,
return_type: self.return_type,
_phantom: Default::default(),
}
}
}
impl<E, CallType, Args, RetType> CallBuilder<E, CallType, Args, RetType>
where
E: Environment,
{
#[inline]
#[must_use]
pub fn call_flags(
self,
call_flags: CallFlags,
) -> CallBuilder<E, CallType, Args, RetType> {
CallBuilder {
call_type: self.call_type,
call_flags,
exec_input: self.exec_input,
return_type: self.return_type,
_phantom: Default::default(),
}
}
}
impl<E, CallType, Args> CallBuilder<E, CallType, Args, Unset<ReturnType<()>>>
where
E: Environment,
{
#[inline]
pub fn returns<R>(self) -> CallBuilder<E, CallType, Args, Set<ReturnType<R>>> {
CallBuilder {
call_type: self.call_type,
call_flags: self.call_flags,
exec_input: self.exec_input,
return_type: Set(Default::default()),
_phantom: Default::default(),
}
}
}
impl<E, CallType, RetType>
CallBuilder<E, CallType, Unset<ExecutionInput<EmptyArgumentList>>, RetType>
where
E: Environment,
{
pub fn exec_input<Args>(
self,
exec_input: ExecutionInput<Args>,
) -> CallBuilder<E, CallType, Set<ExecutionInput<Args>>, RetType> {
CallBuilder {
call_type: self.call_type,
call_flags: self.call_flags,
exec_input: Set(exec_input),
return_type: self.return_type,
_phantom: Default::default(),
}
}
}
impl<E, Args, RetType> CallBuilder<E, Set<Call<E>>, Args, RetType>
where
E: Environment,
{
pub fn callee(self, callee: E::AccountId) -> Self {
let call_type = self.call_type.value();
CallBuilder {
call_type: Set(Call {
callee,
gas_limit: call_type.gas_limit,
transferred_value: call_type.transferred_value,
}),
call_flags: self.call_flags,
exec_input: self.exec_input,
return_type: self.return_type,
_phantom: Default::default(),
}
}
pub fn gas_limit(self, gas_limit: Gas) -> Self {
let call_type = self.call_type.value();
CallBuilder {
call_type: Set(Call {
callee: call_type.callee,
gas_limit,
transferred_value: call_type.transferred_value,
}),
call_flags: self.call_flags,
exec_input: self.exec_input,
return_type: self.return_type,
_phantom: Default::default(),
}
}
pub fn transferred_value(self, transferred_value: E::Balance) -> Self {
let call_type = self.call_type.value();
CallBuilder {
call_type: Set(Call {
callee: call_type.callee,
gas_limit: call_type.gas_limit,
transferred_value,
}),
call_flags: self.call_flags,
exec_input: self.exec_input,
return_type: self.return_type,
_phantom: Default::default(),
}
}
}
impl<E, Args, RetType> CallBuilder<E, Set<DelegateCall<E>>, Args, RetType>
where
E: Environment,
{
pub fn code_hash(self, code_hash: E::Hash) -> Self {
CallBuilder {
call_type: Set(DelegateCall { code_hash }),
call_flags: self.call_flags,
exec_input: self.exec_input,
return_type: self.return_type,
_phantom: Default::default(),
}
}
}
impl<E, Args, RetType>
CallBuilder<E, Set<Call<E>>, Set<ExecutionInput<Args>>, Set<ReturnType<RetType>>>
where
E: Environment,
{
pub fn params(self) -> CallParams<E, Call<E>, Args, RetType> {
CallParams {
call_type: self.call_type.value(),
call_flags: self.call_flags,
_return_type: Default::default(),
exec_input: self.exec_input.value(),
_phantom: self._phantom,
}
}
}
impl<E, Args, RetType>
CallBuilder<
E,
Set<DelegateCall<E>>,
Set<ExecutionInput<Args>>,
Set<ReturnType<RetType>>,
>
where
E: Environment,
{
pub fn params(self) -> CallParams<E, DelegateCall<E>, Args, RetType> {
CallParams {
call_type: self.call_type.value(),
call_flags: self.call_flags,
_return_type: Default::default(),
exec_input: self.exec_input.value(),
_phantom: self._phantom,
}
}
}
impl<E, RetType>
CallBuilder<E, Set<Call<E>>, Unset<ExecutionInput<EmptyArgumentList>>, Unset<RetType>>
where
E: Environment,
{
pub fn params(self) -> CallParams<E, Call<E>, EmptyArgumentList, ()> {
CallParams {
call_type: self.call_type.value(),
call_flags: self.call_flags,
_return_type: Default::default(),
exec_input: Default::default(),
_phantom: self._phantom,
}
}
}
impl<E, RetType>
CallBuilder<
E,
Set<DelegateCall<E>>,
Unset<ExecutionInput<EmptyArgumentList>>,
Unset<RetType>,
>
where
E: Environment,
{
pub fn params(self) -> CallParams<E, DelegateCall<E>, EmptyArgumentList, ()> {
CallParams {
call_type: self.call_type.value(),
call_flags: self.call_flags,
_return_type: Default::default(),
exec_input: Default::default(),
_phantom: self._phantom,
}
}
}
impl<E>
CallBuilder<
E,
Set<Call<E>>,
Unset<ExecutionInput<EmptyArgumentList>>,
Unset<ReturnType<()>>,
>
where
E: Environment,
{
pub fn fire(self) -> Result<(), Error> {
self.params().invoke()
}
}
impl<E>
CallBuilder<
E,
Set<DelegateCall<E>>,
Unset<ExecutionInput<EmptyArgumentList>>,
Unset<ReturnType<()>>,
>
where
E: Environment,
{
pub fn fire(self) -> Result<(), Error> {
self.params().invoke()
}
}
impl<E, Args, R>
CallBuilder<E, Set<Call<E>>, Set<ExecutionInput<Args>>, Set<ReturnType<R>>>
where
E: Environment,
Args: scale::Encode,
R: scale::Decode,
{
pub fn fire(self) -> Result<R, Error> {
self.params().invoke()
}
}
impl<E, Args, R>
CallBuilder<E, Set<DelegateCall<E>>, Set<ExecutionInput<Args>>, Set<ReturnType<R>>>
where
E: Environment,
Args: scale::Encode,
R: scale::Decode,
{
pub fn fire(self) -> Result<R, Error> {
self.params().invoke()
}
}