1#[macro_export]
2macro_rules! upgradable_api {
3 (
4 $(#[$mod_attr:meta])*
5 mod $mod_name:ident {
6 impl $api_type:ident {
7 $(
8 $(#[doc = $doc_attr:tt])*
9 $(#[ink($ink_attr:tt)])*
10 $fn_vis:vis fn $fn_name:ident(
11 & $self:ident
12 $(,)?
13 $($param:ident: $ty:ty),*
14 $(,)?
15 ) -> $fn_return:ty {
16 $( $fn_impl:tt )*
17 }
18 )*
19 }
20 $(
21 impl $api_type2:ident {
22 $(
23 $(#[doc = $doc2_attr:tt])*
24 $fn2_vis:vis fn $fn2_name:ident(
25 $(& $self2:ident)?
26 $(,)?
27 $($param2:ident: $ty2:ty),*
28 $(,)?
29 ) -> $fn2_return:ty {
30 $( $fn2_impl:tt )*
31 }
32 )*
33 }
34 )?
35 }
36 ) => {
37 pub use $mod_name::*;
38
39 #[cfg_attr(not(feature = "as-library"), ink::contract(env = PolymeshEnvironment))]
40 #[cfg(not(feature = "as-library"))]
41 mod $mod_name {
42 use super::*;
43
44 #[ink(storage)]
45 pub struct $api_type {
46 }
47
48 impl $api_type {
49 #[ink(constructor)]
50 pub fn new() -> Self {
51 panic!("Only upload this contract, don't deploy it.");
52 }
53 }
54
55 impl $api_type {
56 $(
57 $(#[doc = $doc_attr])*
58 $(#[ink($ink_attr, payable)])*
59 $fn_vis fn $fn_name(&self, $($param: $ty),*) -> $fn_return {
60 ::paste::paste! {
61 self.[<__impl_ $fn_name>]($($param),*)
62 }
63 }
64 )*
65 }
66
67 impl $api_type {
68 $(
69 ::paste::paste! {
70 fn [<__impl_ $fn_name>](&$self, $($param: $ty),*) -> $fn_return {
71 $( $fn_impl )*
72 }
73 }
74 )*
75 }
76 $(
77 impl $api_type {
78 $(
79 $(#[doc = $doc2_attr])*
80 $fn2_vis fn $fn2_name($(&$self2,)? $($param2: $ty2),*) -> $fn2_return {
81 $( $fn2_impl )*
82 }
83 )*
84 }
85 )?
86 }
87
88 #[cfg(feature = "as-library")]
89 mod $mod_name {
90 use super::*;
91
92 #[derive(Clone, Debug, Default, scale::Encode, scale::Decode)]
97 #[cfg_attr(feature = "std", derive(scale_info::TypeInfo, ink::storage::traits::StorageLayout))]
98 pub struct $api_type {
99 hash: Hash,
100 }
101
102 impl $api_type {
103 pub fn new() -> PolymeshResult<Self> {
104 Ok(Self {
105 hash: Self::get_latest_upgrade()?,
106 })
107 }
108
109 pub fn new_with_hash(hash: Hash) -> Self {
110 Self { hash }
111 }
112
113 pub fn update_code_hash(&mut self, hash: Hash) {
115 self.hash = hash;
116 }
117
118 pub fn check_for_upgrade(&mut self) -> PolymeshResult<()> {
119 self.hash = Self::get_latest_upgrade()?;
120 Ok(())
121 }
122
123 fn get_latest_upgrade() -> PolymeshResult<Hash> {
124 let extension = <<PolymeshEnvironment as ink::env::Environment>::ChainExtension as ink::ChainExtensionInstance>::instantiate();
125 Ok(extension.get_latest_api_upgrade((&API_VERSION).into())?.into())
126 }
127
128 $(
129 $crate::upgradable_api! {
130 @impl_api_func
131 $(#[doc = $doc_attr])*
132 $(#[ink($ink_attr)])*
133 $fn_vis fn $fn_name(
134 &$self,
135 $($param: $ty),*
136 ) -> $fn_return {
137 $( $fn_impl )*
138 }
139 }
140 )*
141 }
142 $(
143 impl $api_type {
144 $(
145 $(#[doc = $doc2_attr])*
146 $fn2_vis fn $fn2_name($(&$self2,)? $($param2: $ty2),*) -> $fn2_return {
147 $( $fn2_impl )*
148 }
149 )*
150 }
151 )?
152 }
153 };
154 (@impl_api_func
156 $(#[doc = $doc_attr:tt])*
157 $(#[ink($ink_attr:tt)])+
158 $fn_vis:vis fn $fn_name:ident(
159 & $self:ident
160 $(,)?
161 $($param:ident: $ty:ty),*
162 $(,)?
163 ) -> $fn_return:ty {
164 $( $fn_impl:tt )*
165 }
166 ) => {
167 $(#[doc = $doc_attr])*
168 $fn_vis fn $fn_name(&$self, $($param: $ty),*) -> $fn_return {
169 use ink::env::call::{ExecutionInput, Selector};
170 const FUNC: &'static str = stringify!{$fn_name};
171 let selector = Selector::new(::polymesh_api::ink::blake2_256(FUNC.as_bytes())[..4]
172 .try_into().unwrap());
173 ink::env::call::build_call::<ink::env::DefaultEnvironment>()
174 .delegate($self.hash)
175 .exec_input(
176 ExecutionInput::new(selector)
177 .push_arg(($($param),*)),
178 )
179 .returns::<$fn_return>()
180 .invoke()
181 }
182 };
183 (@impl_api_func
185 $(#[doc = $doc_attr:tt])*
186 $fn_vis:vis fn $fn_name:ident(
187 $(& $self:ident)?
188 $(,)?
189 $($param:ident: $ty:ty),*
190 $(,)?
191 ) -> $fn_return:ty {
192 $( $fn_impl:tt )*
193 }
194 ) => {
195 $(#[doc = $doc_attr])*
196 $fn_vis fn $fn_name($(&$self,)? $($param: $ty),*) -> $fn_return {
197 $( $fn_impl )*
198 }
199 };
200}