// 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. #![allow(unused)] use klever_sc::{ contract_base::ProxyObjBase, types::{BigInt, ManagedAddress}, }; use klever_sc_scenario::api::{SingleTxApi, StaticApi}; use crate::module_1::VersionModule; mod module_1 { klever_sc::imports!(); ///////////////////////////////////////////////////////////////////////////////////////////////// //////// CONTRACT TRAIT ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// pub trait VersionModule: klever_sc::contract_base::ContractBase + Sized { fn version(&self) -> BigInt; fn some_async(&self); fn callback(&self); } ///////////////////////////////////////////////////////////////////////////////////////////////// //////// AUTO-IMPLEMENTED METHODS /////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// pub trait AutoImpl: klever_sc::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 klever_sc::contract_base::UniversalContractObj where A: klever_sc::api::VMApi { } pub trait EndpointWrappers: VersionModule + klever_sc::contract_base::ContractBase { #[inline] fn call_version(&self) { klever_sc::io::call_value_init::not_payable::(); let result = self.version(); klever_sc::io::finish_multi::(&result) } fn call_some_async(&self) { self.some_async(); klever_sc::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 klever_sc::contract_base::UniversalContractObj where A: klever_sc::api::VMApi { } pub struct AbiProvider {} impl klever_sc::contract_base::ContractAbiProvider for AbiProvider { type Api = klever_sc::api::uncallable::UncallableApi; fn abi() -> klever_sc::abi::ContractAbi { klever_sc::abi::ContractAbi::default() } } pub trait ProxyTrait: klever_sc::contract_base::ProxyObjBase + Sized { fn version( &mut self, ) -> klever_sc::types::ContractCallNoPayment> { let ___address___ = self.extract_address(); klever_sc::types::ContractCallNoPayment::new(___address___, "version") } } } mod sample_adder { klever_sc::imports!(); ///////////////////////////////////////////////////////////////////////////////////////////////// //////// CONTRACT TRAIT ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// pub trait Adder: super::module_1::VersionModule + klever_sc::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()) } } ///////////////////////////////////////////////////////////////////////////////////////////////// //////// AUTO-IMPLEMENTED METHODS /////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// pub trait AutoImpl: klever_sc::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___ = klever_sc::storage::StorageKey::::new(&b"sum"[..]); klever_sc::storage_get(klever_sc::types::ManagedRef::new(&___key___)) } fn set_sum(&self, sum: &BigInt) { let mut ___key___ = klever_sc::storage::StorageKey::::new(&b"sum"[..]); klever_sc::storage_set(klever_sc::types::ManagedRef::new(&___key___), &sum); } } impl AutoImpl for klever_sc::contract_base::UniversalContractObj where A: klever_sc::api::VMApi { } pub trait EndpointWrappers: Adder + klever_sc::contract_base::ContractBase + super::module_1::EndpointWrappers { #[inline] fn call_get_sum(&self) { ::init_static(); klever_sc::io::call_value_init::not_payable::(); let () = klever_sc::io::load_endpoint_args::(()); let result = self.get_sum(); klever_sc::io::finish_multi::(&result); } #[inline] fn call_init(&self) { ::init_static(); klever_sc::io::call_value_init::not_payable::(); let (initial_value, ()) = klever_sc::io::load_endpoint_args::< Self::Api, (klever_sc::types::BigInt, ()), >(("initial_value", ())); self.init(&initial_value); } #[inline] fn call_add(&self) { ::init_static(); klever_sc::io::call_value_init::not_payable::(); let (value, ()) = klever_sc::io::load_endpoint_args::< Self::Api, (klever_sc::types::BigInt, ()), >(("value", ())); let result = self.add(value); klever_sc::io::finish_multi::(&result); } fn call(&self, fn_name: &str) -> bool { if match fn_name { "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 klever_sc::contract_base::UniversalContractObj where A: klever_sc::api::VMApi { } pub trait ProxyTrait: klever_sc::contract_base::ProxyObjBase + super::module_1::ProxyTrait { fn get_sum( &mut self, ) -> klever_sc::types::ContractCallNoPayment> { let ___address___ = self.extract_address(); klever_sc::types::ContractCallNoPayment::new(___address___, "get_sum") } fn add( &mut self, amount: &BigInt, ) -> klever_sc::types::ContractCallNoPayment { let ___address___ = self.extract_address(); let mut ___contract_call___ = klever_sc::types::ContractCallNoPayment::new(___address___, "add"); klever_sc::types::ContractCall::proxy_arg(&mut ___contract_call___, amount); ___contract_call___ } } ///////////////////////////////////////////////////////////////////////////////////////////////// //////// CONTRACT OBJECT //////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// pub struct ContractObj where A: klever_sc::api::VMApi, { _phantom: core::marker::PhantomData, } ///////////////////////////////////////////////////////////////////////////////////////////////// //////// CONTRACT OBJECT as CONTRACT BASE /////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// impl klever_sc::contract_base::ContractBase for ContractObj where A: klever_sc::api::VMApi, { type Api = A; } impl super::module_1::AutoImpl for ContractObj where A: klever_sc::api::VMApi {} impl AutoImpl for ContractObj where A: klever_sc::api::VMApi {} impl super::module_1::EndpointWrappers for ContractObj where A: klever_sc::api::VMApi {} impl EndpointWrappers for ContractObj where A: klever_sc::api::VMApi {} impl klever_sc::contract_base::CallableContract for ContractObj where A: klever_sc::api::VMApi, { fn call(&self, fn_name: &str) -> bool { EndpointWrappers::call( &klever_sc::contract_base::UniversalContractObj::::new(), fn_name, ) } } pub struct ContractBuilder; impl klever_sc::contract_base::CallableContractBuilder for ContractBuilder { fn new_contract_obj( &self, ) -> klever_sc::types::heap::Box { klever_sc::types::heap::Box::new(ContractObj:: { _phantom: core::marker::PhantomData, }) } } pub struct AbiProvider {} impl klever_sc::contract_base::ContractAbiProvider for AbiProvider { type Api = klever_sc::api::uncallable::UncallableApi; fn abi() -> klever_sc::abi::ContractAbi { klever_sc::abi::ContractAbi::default() } } pub fn contract_obj() -> ContractObj where A: klever_sc::api::VMApi, { ContractObj { _phantom: core::marker::PhantomData, } } pub struct Proxy where A: klever_sc::api::VMApi + 'static, { pub address: klever_sc::types::ManagedOption>, } impl klever_sc::contract_base::ProxyObjBase for Proxy where A: klever_sc::api::VMApi + 'static, { type Api = A; fn new_proxy_obj() -> Self { Proxy { address: klever_sc::types::ManagedOption::none(), } } fn contract(mut self, address: klever_sc::types::ManagedAddress) -> Self { self.address = klever_sc::types::ManagedOption::some(address); self } fn extract_opt_address( &mut self, ) -> klever_sc::types::ManagedOption< Self::Api, klever_sc::types::ManagedAddress, > { core::mem::replace( &mut self.address, klever_sc::types::ManagedOption::none(), ) } fn extract_address(&mut self) -> klever_sc::types::ManagedAddress { let address = core::mem::replace( &mut self.address, klever_sc::types::ManagedOption::none(), ); address.unwrap_or_sc_panic(klever_sc::err_msg::RECIPIENT_ADDRESS_NOT_SET) } } impl super::module_1::ProxyTrait for Proxy where A: klever_sc::api::VMApi {} impl ProxyTrait for Proxy where A: klever_sc::api::VMApi {} } #[test] fn contract_without_macros_basic() { use sample_adder::{Adder, EndpointWrappers, ProxyTrait}; 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 _ = klever_sc_meta::abi_json::contract_abi::(); } fn world() -> klever_sc_scenario::ScenarioWorld { let mut blockchain = klever_sc_scenario::ScenarioWorld::new(); blockchain.register_contract( "file:../../contracts/examples/adder/output/adder.wasm", sample_adder::ContractBuilder, ); blockchain } #[test] fn contract_without_macros_scenario() { world().run("../../contracts/examples/adder/scenarios/adder.scen.json"); }