Skip to content

Commit 1eac0bb

Browse files
author
dj8yf0μl
committed
resolves #1306
1 parent 5bea4e2 commit 1eac0bb

File tree

1 file changed

+84
-3
lines changed

1 file changed

+84
-3
lines changed

near-sdk/src/lib.rs

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,87 @@ extern crate quickcheck;
180180
///
181181
/// * list of [**host functions**](collections#calls-to-host-functions-used-in-implementation) used for [`collections`] implementation
182182
///
183+
/// ### Implementation details and **host functions** calls used
184+
///
185+
/// If the details of [ABI](https://github.com/near/abi) generation layer are put aside, then the macro performs roughly the following:
186+
///
187+
/// #### inner workings of `#[near(contract_state)]` macro on struct/enum:
188+
///
189+
/// ```rust
190+
/// # use near_sdk::near;
191+
/// #[near(contract_state)]
192+
/// pub struct Contract { /* .. */ }
193+
/// ```
194+
///
195+
/// 1. Macro adds derived implementations of [`borsh::BorshSerialize`]/[`borsh::BorshSerialize`] for `Contract` type
196+
/// 2. Macro defines a global `CONTRACT_SOURCE_METADATA` variable, which is a string of json serialization of [`near_contract_standards::contract_metadata::ContractSourceMetadata`](https://docs.rs/near-contract-standards/latest/near_contract_standards/contract_metadata/struct.ContractSourceMetadata.html).
197+
/// 3. Macro defines `contract_source_metadata` function:
198+
/// ```rust,no_run
199+
/// #[no_mangle]
200+
/// pub extern "C" fn contract_source_metadata() { /* .. */ }
201+
/// ```
202+
/// which
203+
/// * calls [`env::setup_panic_hook`] host function
204+
/// * calls [`env::value_return`] host function with bytes of `CONTRACT_SOURCE_METADATA` from step 2.
205+
///
206+
/// #### inner workings of `#[near]` macro on impl block:
207+
///
208+
/// ```rust
209+
/// # use near_sdk::near;
210+
/// # #[near(contract_state)]
211+
/// # pub struct Contract { /* .. */ }
212+
/// #[near]
213+
/// impl Contract {
214+
/// pub fn view_method(&self) -> String { todo!("method body") }
215+
///
216+
/// pub fn mutating_method(&mut self, argument: String) { /* .. */ }
217+
/// }
218+
/// ```
219+
/// ##### for a **view** method macro defines the following function:
220+
/// ```rust,no_run
221+
/// #[no_mangle]
222+
/// pub extern "C" fn view_method() { /* .. */ }
223+
/// ```
224+
/// which
225+
///
226+
/// 1. calls [`env::setup_panic_hook`] host function
227+
/// 2. calls [`env::state_read`] host function to load `Contract` into a `state` variable
228+
/// 3. calls original `Contract::view_method(&state)` as defined in `#[near]` annotated block and saves
229+
/// the returned value into a `result` variable
230+
/// 4. calls [`serde_json::to_vec`] on obtained `result` and saves returned value to `serialized_result` variable
231+
/// * `json` format can be changed to serializing with [`borsh::to_vec`] by using [`#[result_serializer(...)]`](`near#result_serializer-annotates-methods-of-a-type-in-its-impl-block`)
232+
/// 5. if the `serialized_result` is an [`Result::Err`] error, then [`env::panic_str`] host function is called to signal result serialization error
233+
/// 6. otherwise, if the `serialized_result` is a [`Result::Ok`], then [`env::value_return`] host function is called with unwrapped `serialized_result`
234+
///
235+
/// ##### for a **mutating** method macro defines the following function:
236+
/// ```rust,no_run
237+
/// #[no_mangle]
238+
/// pub extern "C" fn mutating_method() { /* ..*/ }
239+
/// ```
240+
/// which
241+
///
242+
/// 1. calls [`env::setup_panic_hook`] host function
243+
/// 2. calls [`env::input`] host function and saves it to `input` variable
244+
/// 3. deserializes `Contract::mutating_method` arguments with [`serde_json::from_slice`] and saves it to `deserialized_input` variable
245+
/// * `json` format can be changed to deserializing with [`borsh::from_slice`] by using [`#[serializer(...)]`](`near#serializer-annotates-function-arguments`)
246+
/// 4. if the `deserialized_input` is an [`Result::Err`] error, then [`env::panic_str`] host function is called to signal input deserialization error
247+
/// 5. otherwise, if the `deserialized_input` is a [`Result::Ok`], `deserialized_input` is unwrapped and saved to `deserialized_input_success` variable
248+
/// 6. calls [`env::state_read`] host function to load `Contract` into a `state` variable
249+
/// 7. calls original `Contract::mutating_method(&mut state, deserialized_input_success.argument)` as defined in `#[near]` annotated block
250+
/// 8. calls [`env::state_write`] with `&state` as argument.
251+
///
252+
/// ##### using [cargo-expand](https://crates.io/crates/cargo-expand) to view actual macro results
253+
///
254+
/// The above is an approximate description of what macro performs.
255+
///
256+
/// Running the following in a contract's crate is a way to introspect more details of its operation:
257+
///
258+
/// ```bash,ignore
259+
/// cargo expand --lib --target wasm32-unknown-unknown
260+
/// # this has additional code generated for ABI layer
261+
/// cargo expand --lib --features near-sdk/__abi-generate
262+
/// ```
263+
///
183264
/// ## `#[near(serializers=[...])` (annotates structs/enums)
184265
///
185266
/// The attribute makes the struct or enum serializable with either json or borsh. By default, borsh is used.
@@ -233,8 +314,8 @@ extern crate quickcheck;
233314
///
234315
/// ## `#[serializer(...)]` (annotates function arguments)
235316
///
236-
/// The attribute makes the function argument serializable with either json or borsh. By default, json is used.
237-
/// Please, note that all the arguments of the function should be using the same serializer.
317+
/// The attribute makes the function argument deserializable with either json or borsh. By default, json is used.
318+
/// Please, note that all the arguments of the function should be using the same deserializer.
238319
///
239320
/// ### Basic example
240321
///
@@ -475,7 +556,7 @@ extern crate quickcheck;
475556
/// All fields(version, link) are optional and will be populated with defaults from the Cargo.toml file if not specified.
476557
/// The `standard` will be populated with `nep330` by default.
477558
///
478-
/// Any additional standards can be added and should be specified using the `standard` attribute.
559+
/// **Any additional standards can be added and should be specified using the `standard` attribute.**
479560
///
480561
/// The `contract_source_metadata()` view function will be added and can be used to retrieve the source metadata.
481562
/// Also, the source metadata will be stored as a constant, `CONTRACT_SOURCE_METADATA`, in the contract code.

0 commit comments

Comments
 (0)