// The purpose of this test is to directly showcase how the various // API traits are being used, without the aid of macros. // All this code is of course always macro-generated. // // Since it is more difficult to debug macros directly, // it is helpful to keep this test as a reference for macro development // and maintenance. use elrond_wasm::{ contract_base::ProxyObjBase, types::{BigInt, ManagedAddress}, }; use crate::module_1::VersionModule; mod module_1 { elrond_wasm::imports!(); ///////////////////////////////////////////////////////////////////////////////////////////////// //////// CONTRACT TRAIT ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// pub trait VersionModule: elrond_wasm::contract_base::ContractBase + Sized { fn version(&self) -> BigInt; fn some_async(&self); fn callback(&self); } ///////////////////////////////////////////////////////////////////////////////////////////////// //////// AUTO-IMPLEMENTED METHODS /////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// pub trait AutoImpl: elrond_wasm::contract_base::ContractBase {} impl VersionModule for C where C: AutoImpl, { fn version(&self) -> BigInt { BigInt::from(100) } fn some_async(&self) { panic!("wooo") } fn callback(&self) {} } impl AutoImpl for elrond_wasm::contract_base::UniversalContractObj where A: elrond_wasm::api::VMApi { } pub trait EndpointWrappers: VersionModule + elrond_wasm::contract_base::ContractBase { #[inline] fn call_version(&self) { elrond_wasm::api::CallValueApiImpl::check_not_payable(&Self::Api::call_value_api_impl()); let result = self.version(); elrond_wasm::io::finish_multi::(&result) } fn call_some_async(&self) { self.some_async(); elrond_wasm::io::finish_multi::(&()) } fn call(&self, fn_name: &str) -> bool { if match fn_name { "callBack" => { self.callback(); return true; }, "version" => { self.call_version(); true }, _other => false, } { return true; } false } } impl EndpointWrappers for elrond_wasm::contract_base::UniversalContractObj where A: elrond_wasm::api::VMApi { } pub struct AbiProvider {} impl elrond_wasm::contract_base::ContractAbiProvider for AbiProvider { type Api = elrond_wasm::api::uncallable::UncallableApi; fn abi() -> elrond_wasm::abi::ContractAbi { elrond_wasm::abi::ContractAbi::default() } } pub trait ProxyTrait: elrond_wasm::contract_base::ProxyObjBase + Sized { fn version( &mut self, ) -> elrond_wasm::types::ContractCallNoPayment> { let ___address___ = self.extract_address(); elrond_wasm::types::ContractCallNoPayment::new(___address___, "version") } } } mod sample_adder { elrond_wasm::imports!(); ///////////////////////////////////////////////////////////////////////////////////////////////// //////// CONTRACT TRAIT ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// pub trait Adder: super::module_1::VersionModule + elrond_wasm::contract_base::ContractBase + Sized { fn init(&self, initial_value: &BigInt) { self.set_sum(initial_value); } fn add(&self, value: BigInt) -> SCResult<()> { let mut sum = self.get_sum(); sum.add_assign(value); self.set_sum(&sum); Ok(()) } fn get_sum(&self) -> BigInt; fn set_sum(&self, sum: &BigInt); fn add_version(&self) -> SCResult<()> { self.add(self.version()) } fn callback(&self); fn callbacks(&self) -> self::CallbackProxyObj; } ///////////////////////////////////////////////////////////////////////////////////////////////// //////// AUTO-IMPLEMENTED METHODS /////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// pub trait AutoImpl: elrond_wasm::contract_base::ContractBase {} // impl super::module_1::AutoImpl for C where C: AutoImpl {} impl Adder for C where C: AutoImpl + super::module_1::AutoImpl, { fn get_sum(&self) -> BigInt { let mut ___key___ = elrond_wasm::storage::StorageKey::::new(&b"sum"[..]); elrond_wasm::storage_get(elrond_wasm::types::ManagedRef::new(&___key___)) } fn set_sum(&self, sum: &BigInt) { let mut ___key___ = elrond_wasm::storage::StorageKey::::new(&b"sum"[..]); elrond_wasm::storage_set(elrond_wasm::types::ManagedRef::new(&___key___), &sum); } fn callback(&self) {} fn callbacks(&self) -> self::CallbackProxyObj { as elrond_wasm::contract_base::CallbackProxyObjBase>::new_cb_proxy_obj() } } impl AutoImpl for elrond_wasm::contract_base::UniversalContractObj where A: elrond_wasm::api::VMApi { } pub trait EndpointWrappers: Adder + elrond_wasm::contract_base::ContractBase + super::module_1::EndpointWrappers { #[inline] fn call_get_sum(&self) { ::init_static(); elrond_wasm::api::CallValueApiImpl::check_not_payable(&Self::Api::call_value_api_impl()); let () = elrond_wasm::io::load_endpoint_args::(()); let result = self.get_sum(); elrond_wasm::io::finish_multi::(&result); } #[inline] fn call_init(&self) { ::init_static(); elrond_wasm::api::CallValueApiImpl::check_not_payable(&Self::Api::call_value_api_impl()); let (initial_value, ()) = elrond_wasm::io::load_endpoint_args::< Self::Api, (elrond_wasm::types::BigInt, ()), >(("initial_value", ())); self.init(&initial_value); } #[inline] fn call_add(&self) { ::init_static(); elrond_wasm::api::CallValueApiImpl::check_not_payable(&Self::Api::call_value_api_impl()); let (value, ()) = elrond_wasm::io::load_endpoint_args::< Self::Api, (elrond_wasm::types::BigInt, ()), >(("value", ())); let result = self.add(value); elrond_wasm::io::finish_multi::(&result); } fn call(&self, fn_name: &str) -> bool { if match fn_name { "callBack" => { Adder::callback(self); return true; }, "getSum" => { self.call_get_sum(); true }, "init" => { self.call_init(); true }, "add" => { self.call_add(); true }, _other => false, } { return true; } if super::module_1::EndpointWrappers::call(self, fn_name) { return true; } false } } impl EndpointWrappers for elrond_wasm::contract_base::UniversalContractObj where A: elrond_wasm::api::VMApi { } pub trait ProxyTrait: elrond_wasm::contract_base::ProxyObjBase + super::module_1::ProxyTrait { fn get_sum( &mut self, ) -> elrond_wasm::types::ContractCallNoPayment> { let ___address___ = self.extract_address(); elrond_wasm::types::ContractCallNoPayment::new(___address___, "get_sum") } fn add( &mut self, amount: &BigInt, ) -> elrond_wasm::types::ContractCallNoPayment { let ___address___ = self.extract_address(); let mut ___contract_call___ = elrond_wasm::types::ContractCallNoPayment::new(___address___, "add"); elrond_wasm::types::ContractCall::proxy_arg(&mut ___contract_call___, amount); ___contract_call___ } } ///////////////////////////////////////////////////////////////////////////////////////////////// //////// CONTRACT OBJECT //////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// pub struct ContractObj where A: elrond_wasm::api::VMApi, { _phantom: core::marker::PhantomData, } ///////////////////////////////////////////////////////////////////////////////////////////////// //////// CONTRACT OBJECT as CONTRACT BASE /////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// impl elrond_wasm::contract_base::ContractBase for ContractObj where A: elrond_wasm::api::VMApi, { type Api = A; } impl super::module_1::AutoImpl for ContractObj where A: elrond_wasm::api::VMApi {} impl AutoImpl for ContractObj where A: elrond_wasm::api::VMApi {} impl super::module_1::EndpointWrappers for ContractObj where A: elrond_wasm::api::VMApi {} impl EndpointWrappers for ContractObj where A: elrond_wasm::api::VMApi {} impl elrond_wasm::contract_base::CallableContract for ContractObj where A: elrond_wasm::api::VMApi, { fn call(&self, fn_name: &str) -> bool { EndpointWrappers::call( &elrond_wasm::contract_base::UniversalContractObj::::new(), fn_name, ) } } pub struct ContractBuilder; impl elrond_wasm::contract_base::CallableContractBuilder for ContractBuilder { fn new_contract_obj( &self, ) -> elrond_wasm::types::heap::Box { elrond_wasm::types::heap::Box::new(ContractObj:: { _phantom: core::marker::PhantomData, }) } } pub struct AbiProvider {} impl elrond_wasm::contract_base::ContractAbiProvider for AbiProvider { type Api = elrond_wasm::api::uncallable::UncallableApi; fn abi() -> elrond_wasm::abi::ContractAbi { elrond_wasm::abi::ContractAbi::default() } } pub fn contract_obj() -> ContractObj where A: elrond_wasm::api::VMApi, { ContractObj { _phantom: core::marker::PhantomData, } } pub struct Proxy where A: elrond_wasm::api::VMApi + 'static, { pub address: elrond_wasm::types::ManagedOption>, } impl elrond_wasm::contract_base::ProxyObjBase for Proxy where A: elrond_wasm::api::VMApi + 'static, { type Api = A; fn new_proxy_obj() -> Self { Proxy { address: elrond_wasm::types::ManagedOption::none(), } } fn contract(mut self, address: elrond_wasm::types::ManagedAddress) -> Self { self.address = elrond_wasm::types::ManagedOption::some(address); self } fn extract_opt_address( &mut self, ) -> elrond_wasm::types::ManagedOption< Self::Api, elrond_wasm::types::ManagedAddress, > { core::mem::replace(&mut self.address, elrond_wasm::types::ManagedOption::none()) } fn extract_address(&mut self) -> elrond_wasm::types::ManagedAddress { let address = core::mem::replace(&mut self.address, elrond_wasm::types::ManagedOption::none()); address.unwrap_or_sc_panic(elrond_wasm::err_msg::RECIPIENT_ADDRESS_NOT_SET) } } impl super::module_1::ProxyTrait for Proxy where A: elrond_wasm::api::VMApi {} impl ProxyTrait for Proxy where A: elrond_wasm::api::VMApi {} pub struct CallbackProxyObj where A: elrond_wasm::api::VMApi + 'static, { _phantom: core::marker::PhantomData, } impl elrond_wasm::contract_base::CallbackProxyObjBase for CallbackProxyObj where A: elrond_wasm::api::VMApi + 'static, { type Api = A; fn new_cb_proxy_obj() -> Self { CallbackProxyObj { _phantom: core::marker::PhantomData, } } } pub trait CallbackProxy: elrond_wasm::contract_base::CallbackProxyObjBase + Sized { fn my_callback(self, caller: &Address) -> elrond_wasm::types::CallbackClosure { let mut ___callback_call___ = elrond_wasm::types::new_callback_call::("my_callback"); ___callback_call___.push_endpoint_arg(caller); ___callback_call___ } } impl self::CallbackProxy for CallbackProxyObj where A: elrond_wasm::api::VMApi + 'static {} } #[test] fn test_add() { use elrond_wasm_debug::DebugApi; use sample_adder::{Adder, EndpointWrappers, ProxyTrait}; let _ = DebugApi::dummy(); let adder = sample_adder::contract_obj::(); adder.init(&BigInt::from(5)); assert_eq!(BigInt::from(5), adder.get_sum()); let _ = adder.add(BigInt::from(7)); assert_eq!(BigInt::from(12), adder.get_sum()); let _ = adder.add(BigInt::from(-1)); assert_eq!(BigInt::from(11), adder.get_sum()); assert_eq!(BigInt::from(100), adder.version()); let _ = adder.add_version(); assert_eq!(BigInt::from(111), adder.get_sum()); assert!(!adder.call("invalid_endpoint")); assert!(adder.call("version")); let mut own_proxy = sample_adder::Proxy::::new_proxy_obj().contract(ManagedAddress::zero()); let _ = own_proxy.get_sum(); let _ = elrond_wasm_debug::abi_json::contract_abi::(); } fn world() -> elrond_wasm_debug::BlockchainMock { let mut blockchain = elrond_wasm_debug::BlockchainMock::new(); blockchain.register_contract( "file:../contracts/examples/adder/output/adder.wasm", sample_adder::ContractBuilder, ); blockchain } #[test] fn test_mandos() { elrond_wasm_debug::mandos_rs( "../contracts/examples/adder/mandos/adder.scen.json", world(), ); }