use crate::{
call::{
utils::{
EmptyArgumentList,
ReturnType,
Set,
Unset,
Unwrap,
},
ExecutionInput,
Selector,
},
ContractEnv,
Environment,
Error,
};
use core::marker::PhantomData;
pub mod state {
pub enum Salt {}
}
pub trait FromAccountId<T>
where
T: Environment,
{
fn from_account_id(account_id: <T as Environment>::AccountId) -> Self;
}
pub trait ConstructorReturnType<C> {
const IS_RESULT: bool = false;
type Output;
type Error: scale::Decode;
fn ok(value: C) -> Self::Output;
fn err(_err: Self::Error) -> Option<Self::Output> {
None
}
}
impl<C> ConstructorReturnType<C> for C
where
C: ContractEnv + FromAccountId<<C as ContractEnv>::Env>,
{
type Output = C;
type Error = ();
fn ok(value: C) -> Self::Output {
value
}
}
impl<C, E> ConstructorReturnType<C> for core::result::Result<C, E>
where
C: ContractEnv + FromAccountId<<C as ContractEnv>::Env>,
E: scale::Decode,
{
const IS_RESULT: bool = true;
type Output = core::result::Result<C, E>;
type Error = E;
fn ok(value: C) -> Self::Output {
Ok(value)
}
fn err(err: Self::Error) -> Option<Self::Output> {
Some(Err(err))
}
}
#[derive(Debug)]
pub struct CreateParams<E, ContractRef, Args, Salt, R>
where
E: Environment,
{
code_hash: E::Hash,
gas_limit: u64,
endowment: E::Balance,
exec_input: ExecutionInput<Args>,
salt_bytes: Salt,
_return_type: ReturnType<R>,
_phantom: PhantomData<fn() -> ContractRef>,
}
impl<E, ContractRef, Args, Salt, R> CreateParams<E, ContractRef, Args, Salt, R>
where
E: Environment,
{
#[inline]
pub fn code_hash(&self) -> &E::Hash {
&self.code_hash
}
#[inline]
pub fn gas_limit(&self) -> u64 {
self.gas_limit
}
#[inline]
pub fn endowment(&self) -> &E::Balance {
&self.endowment
}
#[inline]
pub fn exec_input(&self) -> &ExecutionInput<Args> {
&self.exec_input
}
pub fn update_selector(&mut self, selector: Selector) {
self.exec_input.update_selector(selector)
}
}
impl<E, ContractRef, Args, Salt, R> CreateParams<E, ContractRef, Args, Salt, R>
where
E: Environment,
Salt: AsRef<[u8]>,
{
#[inline]
pub fn salt_bytes(&self) -> &Salt {
&self.salt_bytes
}
}
impl<E, ContractRef, Args, Salt, R> CreateParams<E, ContractRef, Args, Salt, R>
where
E: Environment,
ContractRef: FromAccountId<E>,
Args: scale::Encode,
Salt: AsRef<[u8]>,
R: ConstructorReturnType<ContractRef>,
{
#[inline]
pub fn instantiate(&self) -> <R as ConstructorReturnType<ContractRef>>::Output {
crate::instantiate_contract(self)
.unwrap_or_else(|env_error| {
panic!("Cross-contract instantiation failed with {:?}", env_error)
})
.unwrap_or_else(|lang_error| {
panic!(
"Received a `LangError` while instantiating: {:?}",
lang_error
)
})
}
#[inline]
pub fn try_instantiate(
&self,
) -> Result<
ink_primitives::ConstructorResult<
<R as ConstructorReturnType<ContractRef>>::Output,
>,
crate::Error,
> {
crate::instantiate_contract(self)
}
}
pub struct CreateBuilder<
E,
ContractRef,
CodeHash,
GasLimit,
Endowment,
Args,
Salt,
RetType,
> where
E: Environment,
{
code_hash: CodeHash,
gas_limit: GasLimit,
endowment: Endowment,
exec_input: Args,
salt: Salt,
return_type: RetType,
_phantom: PhantomData<fn() -> (E, ContractRef)>,
}
#[allow(clippy::type_complexity)]
pub fn build_create<ContractRef>() -> CreateBuilder<
<ContractRef as ContractEnv>::Env,
ContractRef,
Unset<<<ContractRef as ContractEnv>::Env as Environment>::Hash>,
Unset<u64>,
Unset<<<ContractRef as ContractEnv>::Env as Environment>::Balance>,
Unset<ExecutionInput<EmptyArgumentList>>,
Unset<state::Salt>,
Unset<ReturnType<()>>,
>
where
ContractRef: ContractEnv,
{
CreateBuilder {
code_hash: Default::default(),
gas_limit: Default::default(),
endowment: Default::default(),
exec_input: Default::default(),
salt: Default::default(),
return_type: Default::default(),
_phantom: Default::default(),
}
}
impl<E, ContractRef, GasLimit, Endowment, Args, Salt, RetType>
CreateBuilder<
E,
ContractRef,
Unset<E::Hash>,
GasLimit,
Endowment,
Args,
Salt,
RetType,
>
where
E: Environment,
{
#[inline]
pub fn code_hash(
self,
code_hash: E::Hash,
) -> CreateBuilder<
E,
ContractRef,
Set<E::Hash>,
GasLimit,
Endowment,
Args,
Salt,
RetType,
> {
CreateBuilder {
code_hash: Set(code_hash),
gas_limit: self.gas_limit,
endowment: self.endowment,
exec_input: self.exec_input,
salt: self.salt,
return_type: self.return_type,
_phantom: Default::default(),
}
}
}
impl<E, ContractRef, CodeHash, Endowment, Args, Salt, RetType>
CreateBuilder<E, ContractRef, CodeHash, Unset<u64>, Endowment, Args, Salt, RetType>
where
E: Environment,
{
#[inline]
pub fn gas_limit(
self,
gas_limit: u64,
) -> CreateBuilder<E, ContractRef, CodeHash, Set<u64>, Endowment, Args, Salt, RetType>
{
CreateBuilder {
code_hash: self.code_hash,
gas_limit: Set(gas_limit),
endowment: self.endowment,
exec_input: self.exec_input,
salt: self.salt,
return_type: self.return_type,
_phantom: Default::default(),
}
}
}
impl<E, ContractRef, CodeHash, GasLimit, Args, Salt, RetType>
CreateBuilder<
E,
ContractRef,
CodeHash,
GasLimit,
Unset<E::Balance>,
Args,
Salt,
RetType,
>
where
E: Environment,
{
#[inline]
pub fn endowment(
self,
endowment: E::Balance,
) -> CreateBuilder<
E,
ContractRef,
CodeHash,
GasLimit,
Set<E::Balance>,
Args,
Salt,
RetType,
> {
CreateBuilder {
code_hash: self.code_hash,
gas_limit: self.gas_limit,
endowment: Set(endowment),
exec_input: self.exec_input,
salt: self.salt,
return_type: self.return_type,
_phantom: Default::default(),
}
}
}
impl<E, ContractRef, CodeHash, GasLimit, Endowment, Salt, RetType>
CreateBuilder<
E,
ContractRef,
CodeHash,
GasLimit,
Endowment,
Unset<ExecutionInput<EmptyArgumentList>>,
Salt,
RetType,
>
where
E: Environment,
{
#[inline]
pub fn exec_input<Args>(
self,
exec_input: ExecutionInput<Args>,
) -> CreateBuilder<
E,
ContractRef,
CodeHash,
GasLimit,
Endowment,
Set<ExecutionInput<Args>>,
Salt,
RetType,
> {
CreateBuilder {
code_hash: self.code_hash,
gas_limit: self.gas_limit,
endowment: self.endowment,
exec_input: Set(exec_input),
salt: self.salt,
return_type: self.return_type,
_phantom: Default::default(),
}
}
}
impl<E, ContractRef, CodeHash, GasLimit, Endowment, Args, RetType>
CreateBuilder<
E,
ContractRef,
CodeHash,
GasLimit,
Endowment,
Args,
Unset<state::Salt>,
RetType,
>
where
E: Environment,
{
#[inline]
pub fn salt_bytes<Salt>(
self,
salt: Salt,
) -> CreateBuilder<
E,
ContractRef,
CodeHash,
GasLimit,
Endowment,
Args,
Set<Salt>,
RetType,
>
where
Salt: AsRef<[u8]>,
{
CreateBuilder {
code_hash: self.code_hash,
gas_limit: self.gas_limit,
endowment: self.endowment,
exec_input: self.exec_input,
salt: Set(salt),
return_type: self.return_type,
_phantom: Default::default(),
}
}
}
impl<E, ContractRef, CodeHash, GasLimit, Endowment, Args, Salt>
CreateBuilder<
E,
ContractRef,
CodeHash,
GasLimit,
Endowment,
Args,
Salt,
Unset<ReturnType<()>>,
>
where
E: Environment,
{
#[inline]
pub fn returns<R>(
self,
) -> CreateBuilder<
E,
ContractRef,
CodeHash,
GasLimit,
Endowment,
Args,
Salt,
Set<ReturnType<R>>,
>
where
ContractRef: FromAccountId<E>,
R: ConstructorReturnType<ContractRef>,
{
CreateBuilder {
code_hash: self.code_hash,
gas_limit: self.gas_limit,
endowment: self.endowment,
exec_input: self.exec_input,
salt: self.salt,
return_type: Set(Default::default()),
_phantom: Default::default(),
}
}
}
impl<E, ContractRef, GasLimit, Args, Salt, RetType>
CreateBuilder<
E,
ContractRef,
Set<E::Hash>,
GasLimit,
Set<E::Balance>,
Set<ExecutionInput<Args>>,
Set<Salt>,
Set<ReturnType<RetType>>,
>
where
E: Environment,
GasLimit: Unwrap<Output = u64>,
{
#[inline]
pub fn params(self) -> CreateParams<E, ContractRef, Args, Salt, RetType> {
CreateParams {
code_hash: self.code_hash.value(),
gas_limit: self.gas_limit.unwrap_or_else(|| 0),
endowment: self.endowment.value(),
exec_input: self.exec_input.value(),
salt_bytes: self.salt.value(),
_return_type: Default::default(),
_phantom: Default::default(),
}
}
}
impl<E, ContractRef, GasLimit, Args, Salt, RetType>
CreateBuilder<
E,
ContractRef,
Set<E::Hash>,
GasLimit,
Set<E::Balance>,
Set<ExecutionInput<Args>>,
Set<Salt>,
Set<ReturnType<RetType>>,
>
where
E: Environment,
ContractRef: FromAccountId<E>,
GasLimit: Unwrap<Output = u64>,
Args: scale::Encode,
Salt: AsRef<[u8]>,
RetType: ConstructorReturnType<ContractRef>,
{
#[inline]
pub fn instantiate(self) -> <RetType as ConstructorReturnType<ContractRef>>::Output {
self.params().instantiate()
}
#[inline]
pub fn try_instantiate(
self,
) -> Result<
ink_primitives::ConstructorResult<
<RetType as ConstructorReturnType<ContractRef>>::Output,
>,
Error,
> {
self.params().try_instantiate()
}
}