use crate::contract::object::ObjectMetadata;
use crate::template::Template as TransactionTemplate;
#[macro_use]
pub mod macros;
pub mod abi;
pub use abi::object;
pub mod actions;
pub mod compiler;
pub mod error;
pub use error::CompilationError;
pub mod context;
use bitcoin::util::amount::Amount;
pub use compiler::Compilable;
pub use context::Context;
pub use object::Object as Compiled;
pub type TxTmplIt = Result<
Box<dyn Iterator<Item = Result<TransactionTemplate, CompilationError>>>,
CompilationError,
>;
pub fn empty() -> TxTmplIt {
Ok(Box::new(std::iter::empty()))
}
pub trait Contract
where
Self: Sized + 'static,
Self::StatefulArguments: StatefulArgumentsTrait,
{
declare! {then}
declare! { updatable<> }
declare! {finish}
fn metadata(&self, _ctx: Context) -> Result<ObjectMetadata, CompilationError> {
Ok(Default::default())
}
fn ensure_amount(&self, _ctx: Context) -> Result<Amount, CompilationError> {
Ok(Amount::from_sat(0))
}
}
pub struct DynamicContract<'a, T, S> {
pub then: Vec<fn() -> Option<actions::ThenFuncAsFinishOrFunc<'a, S, T>>>,
pub finish_or: Vec<fn() -> Option<Box<dyn actions::CallableAsFoF<S, T>>>>,
pub finish: Vec<fn() -> Option<actions::Guard<S>>>,
pub metadata_f: Box<dyn (Fn(&S, Context) -> Result<ObjectMetadata, CompilationError>)>,
pub ensure_amount_f: Box<dyn (Fn(&S, Context) -> Result<Amount, CompilationError>)>,
pub data: S,
}
impl<T, S> AnyContract for DynamicContract<'_, T, S>
where
T: StatefulArgumentsTrait,
{
type StatefulArguments = T;
type Ref = S;
fn then_fns<'a>(
&'a self,
) -> &'a [fn() -> Option<actions::ThenFuncAsFinishOrFunc<'a, S, Self::StatefulArguments>>]
where
Self::Ref: 'a,
{
&self.then[..]
}
fn finish_or_fns<'a>(
&'a self,
) -> &'a [fn() -> Option<Box<dyn actions::CallableAsFoF<S, Self::StatefulArguments>>>] {
&self.finish_or[..]
}
fn finish_fns<'a>(&'a self) -> &'a [fn() -> Option<actions::Guard<S>>] {
&self.finish[..]
}
fn get_inner_ref<'a>(&self) -> &Self::Ref {
&self.data
}
fn metadata<'a>(&'a self, ctx: Context) -> Result<ObjectMetadata, CompilationError> {
(self.metadata_f)(self.get_inner_ref(), ctx)
}
fn ensure_amount<'a>(&'a self, ctx: Context) -> Result<Amount, CompilationError> {
(self.ensure_amount_f)(self.get_inner_ref(), ctx)
}
}
pub trait StatefulArgumentsTrait: Default {}
impl StatefulArgumentsTrait for () {}
impl<T> StatefulArgumentsTrait for Option<T> {}
pub trait AnyContract
where
Self: Sized,
{
type StatefulArguments: StatefulArgumentsTrait;
type Ref;
fn then_fns<'a>(
&'a self,
) -> &'a [fn() -> Option<
actions::ThenFuncAsFinishOrFunc<'a, Self::Ref, Self::StatefulArguments>,
>]
where
Self::Ref: 'a;
fn finish_or_fns<'a>(
&'a self,
) -> &'a [fn() -> Option<Box<dyn actions::CallableAsFoF<Self::Ref, Self::StatefulArguments>>>];
fn finish_fns<'a>(&'a self) -> &'a [fn() -> Option<actions::Guard<Self::Ref>>];
fn get_inner_ref<'a>(&'a self) -> &'a Self::Ref;
fn metadata<'a>(&'a self, ctx: Context) -> Result<ObjectMetadata, CompilationError>;
fn ensure_amount<'a>(&'a self, ctx: Context) -> Result<Amount, CompilationError>;
}
impl<C> AnyContract for C
where
C: Contract + Sized,
C::StatefulArguments: StatefulArgumentsTrait,
{
type StatefulArguments = C::StatefulArguments;
type Ref = Self;
fn then_fns<'a>(
&'a self,
) -> &'a [fn() -> Option<
actions::ThenFuncAsFinishOrFunc<'a, Self::Ref, Self::StatefulArguments>,
>]
where
Self::Ref: 'a,
{
Self::THEN_FNS
}
fn finish_or_fns<'a>(
&'a self,
) -> &'a [fn() -> Option<Box<dyn actions::CallableAsFoF<Self::Ref, Self::StatefulArguments>>>]
{
Self::FINISH_OR_FUNCS
}
fn finish_fns<'a>(&'a self) -> &'a [fn() -> Option<actions::Guard<Self::Ref>>] {
Self::FINISH_FNS
}
fn get_inner_ref<'a>(&'a self) -> &Self::Ref {
self
}
fn metadata<'a>(&'a self, ctx: Context) -> Result<ObjectMetadata, CompilationError> {
Self::Ref::metadata(self, ctx)
}
fn ensure_amount<'a>(&'a self, ctx: Context) -> Result<Amount, CompilationError> {
Self::Ref::ensure_amount(self, ctx)
}
}