Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc: impl details of #[callback_unwrap] #1319

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
14 changes: 10 additions & 4 deletions examples/adder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,16 @@ impl Adder {
&self,
#[callback_unwrap] a: DoublePair,
#[callback_unwrap] b: DoublePair,
#[callback_vec] others: Vec<DoublePair>,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#[callback_vec] isn't really compatible with #[callback_unwrap] to be used in this manner, due to a feature??/bug??, because it revisits the same promise indices, already visited by callback_unwrap,
so others vector in this example contained a and b as first elements

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I don't get it. It worked before and now it does not?

) -> DoublePair {
Some(b).iter().chain(others.iter()).fold(a, |acc, el| DoublePair {
Some(b).iter().fold(a, |acc, el| DoublePair {
first: sum_pair(&acc.first, &el.first),
second: sum_pair(&acc.second, &el.second),
})
}

pub fn add_callback_vec(&self, #[callback_vec] elements: Vec<DoublePair>) -> DoublePair {
let start = DoublePair { first: Pair(0, 0), second: Pair(0, 0) };
elements.iter().fold(start, |acc, el| DoublePair {
first: sum_pair(&acc.first, &el.first),
second: sum_pair(&acc.second, &el.second),
})
Expand All @@ -55,8 +62,7 @@ mod tests {

let res = contract.view("__contract_abi").await?;

let abi_root =
serde_json::from_slice::<AbiRoot>(&zstd::decode_all(&res.result[..])?)?;
let abi_root = serde_json::from_slice::<AbiRoot>(&zstd::decode_all(&res.result[..])?)?;

assert_eq!(abi_root.schema_version, "0.4.0");
assert_eq!(abi_root.metadata.name, Some("adder".to_string()));
Expand Down
16 changes: 14 additions & 2 deletions near-sdk/src/environment/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1401,6 +1401,7 @@ pub fn promise_batch_action_delete_account(
/// assert_eq!(promise_results_count(), 0);
/// ```
/// More low-level info here: [`near_vm_runner::logic::VMLogic::promise_results_count`]
///
/// See example of usage [here](https://github.com/near/near-sdk-rs/blob/master/examples/cross-contract-calls/low-level/src/lib.rs)
pub fn promise_results_count() -> u64 {
unsafe { sys::promise_results_count() }
Expand Down Expand Up @@ -1430,8 +1431,14 @@ pub fn promise_results_count() -> u64 {
/// }
/// };
/// ```
///
/// More low-level info here: [`near_vm_runner::logic::VMLogic::promise_result`]
/// Example usages: [one](https://github.com/near/near-sdk-rs/blob/189897180649bce47aefa4e5af03664ee525508d/near-contract-standards/src/fungible_token/core_impl.rs#L178), [two](https://github.com/near/near-sdk-rs/blob/189897180649bce47aefa4e5af03664ee525508d/near-contract-standards/src/non_fungible_token/core/core_impl.rs#L433), [three](https://github.com/near/near-sdk-rs/blob/189897180649bce47aefa4e5af03664ee525508d/examples/factory-contract/low-level/src/lib.rs#L61), [four](https://github.com/near/near-sdk-rs/blob/189897180649bce47aefa4e5af03664ee525508d/examples/cross-contract-calls/low-level/src/lib.rs#L46)
///
/// Example usages:
/// - [near-contract-standards/src/fungible_token](https://github.com/near/near-sdk-rs/blob/189897180649bce47aefa4e5af03664ee525508d/near-contract-standards/src/fungible_token/core_impl.rs#L178)
/// - [near-contract-standards/src/non_fungible_token](https://github.com/near/near-sdk-rs/blob/189897180649bce47aefa4e5af03664ee525508d/near-contract-standards/src/non_fungible_token/core/core_impl.rs#L433)
/// - [examples/factory-contract/low-level](https://github.com/near/near-sdk-rs/blob/189897180649bce47aefa4e5af03664ee525508d/examples/factory-contract/low-level/src/lib.rs#L61)
/// - [examples/cross-contract-calls/low-level](https://github.com/near/near-sdk-rs/blob/189897180649bce47aefa4e5af03664ee525508d/examples/cross-contract-calls/low-level/src/lib.rs#L46)
pub fn promise_result(result_idx: u64) -> PromiseResult {
match promise_result_internal(result_idx) {
Ok(()) => {
Expand Down Expand Up @@ -1806,8 +1813,10 @@ pub fn storage_write(key: &[u8], value: &[u8]) -> bool {
/// Reads the value stored under the given key.
///
/// # Use cases
///
/// Storage functions are typically used to upgrade/migrate a contract state, preventing errors like `Cannot deserialize the contract state` after rolling out the breaking changes to the network.
/// For practical examples, see different implementations in [this repository](https://github.com/near-examples/update-migrate-rust).
///
/// For practical examples, see different implementations in [`near-examples/update-migrate-rust` repo](https://github.com/near-examples/update-migrate-rust).
///
/// # Examples
/// ```
Expand All @@ -1817,6 +1826,9 @@ pub fn storage_write(key: &[u8], value: &[u8]) -> bool {
/// storage_write(b"key", b"value");
/// assert_eq!(storage_read(b"key").unwrap(), b"value");
/// ```
///
/// Another example:
/// - [near-contract-standards/src/upgrade](https://github.com/near/near-sdk-rs/blob/746e4280a7e25b2036bd4e2f2c186cd76e1a7cde/near-contract-standards/src/upgrade/mod.rs?plain=1#L77)
pub fn storage_read(key: &[u8]) -> Option<Vec<u8>> {
match unsafe { sys::storage_read(key.len() as _, key.as_ptr() as _, ATOMIC_OP_REGISTER) } {
0 => None,
Expand Down
22 changes: 16 additions & 6 deletions near-sdk/src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,18 +89,28 @@ pub fn assert_one_yocto() {
}

/// Returns true if promise was successful.
/// Fails if called outside a callback that received 1 promise result.
/// Uses low-level [`crate::env::promise_results_count`].
///
/// Calls [`crate::env::panic_str`] **host function** if called outside a callback that received precisely 1 promise result.
///
/// Uses low-level [`crate::env::promise_results_count`] **host function**.
pub fn is_promise_success() -> bool {
require!(env::promise_results_count() == 1, "Contract expected a result on the callback");
require!(
env::promise_results_count() == 1,
"Contract expected a single result on the callback"
);
env::promise_result_internal(0).is_ok()
}

/// Returns the result of the promise if successful. Otherwise returns None.
/// Fails if called outside a callback that received 1 promise result.
/// Uses low-level [`crate::env::promise_results_count`] and [`crate::env::promise_result`].
///
/// Calls [`crate::env::panic_str`] **host function** if called outside a callback that received precisely 1 promise result.
///
/// Uses low-level [`crate::env::promise_results_count`] and [`crate::env::promise_result`] **host functions**.
pub fn promise_result_as_success() -> Option<Vec<u8>> {
require!(env::promise_results_count() == 1, "Contract expected a result on the callback");
require!(
env::promise_results_count() == 1,
"Contract expected a single result on the callback"
);
match env::promise_result(0) {
PromiseResult::Successful(result) => Some(result),
_ => None,
Expand Down