From b8e2d9774486b0c7c25e306f268b1a1cf18bd107 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Fri, 14 Oct 2022 09:42:25 +0300 Subject: [PATCH 01/68] base ownable example --- Cargo.toml | 2 +- examples/ownable_base/Cargo.toml | 23 +++++++ examples/ownable_base/build.sh | 3 + examples/ownable_base/src/lib.rs | 101 +++++++++++++++++++++++++++++++ 4 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 examples/ownable_base/Cargo.toml create mode 100755 examples/ownable_base/build.sh create mode 100644 examples/ownable_base/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index da1d968..20f104a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = [ "near-plugins", "near-plugins-derive" ] -exclude = ["target"] +exclude = ["target", "examples"] [workspace.metadata.workspaces] version = "0.15.0" diff --git a/examples/ownable_base/Cargo.toml b/examples/ownable_base/Cargo.toml new file mode 100644 index 0000000..4bae40a --- /dev/null +++ b/examples/ownable_base/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "ownable_base" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +near-sdk = "4.0.0" +near-plugins = { path = "../../near-plugins" } +near-plugins-derive = { path = "../../near-plugins-derive" } +borsh = "0.9.3" + +[dev-dependencies] +near-primitives = "0.14.0" +workspaces = "0.6" +tokio = { version = "1.1", features = ["rt", "macros"] } +serde_json = "1.0.74" + + diff --git a/examples/ownable_base/build.sh b/examples/ownable_base/build.sh new file mode 100755 index 0000000..651e364 --- /dev/null +++ b/examples/ownable_base/build.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +/bin/bash -c "rustup target add wasm32-unknown-unknown; cargo build --target wasm32-unknown-unknown --release" diff --git a/examples/ownable_base/src/lib.rs b/examples/ownable_base/src/lib.rs new file mode 100644 index 0000000..19728bf --- /dev/null +++ b/examples/ownable_base/src/lib.rs @@ -0,0 +1,101 @@ +use near_plugins::Ownable; +use near_sdk::near_bindgen; +use near_plugins_derive::only; +use borsh::{BorshSerialize, BorshDeserialize}; + +#[near_bindgen] +#[derive(Ownable, Default, BorshSerialize, BorshDeserialize)] +struct Counter { + counter: u64, +} + +#[near_bindgen] +impl Counter { + /// Specify the owner of the contract in the constructor + #[init] + pub fn new() -> Self { + let mut contract = Self { counter: 0 }; + contract.owner_set(Some(near_sdk::env::predecessor_account_id())); + contract + } + + /// Only owner account, or the contract itself can call this method. + #[only(self, owner)] + pub fn protected(&mut self) { + self.counter += 1; + } + + /// *Only* owner account can call this method. + #[only(owner)] + pub fn protected_owner(&mut self) { + self.counter += 1; + } + + /// *Only* self account can call this method. This can be used even if the contract is not Ownable. + #[only(self)] + pub fn protected_self(&mut self) { + self.counter += 1; + } + + /// Everyone can call this method + pub fn unprotected(&mut self) { + self.counter += 1; + } + + pub fn get_counter(&self) -> u64 { + self.counter + } +} + + +#[cfg(test)] +mod tests { + use workspaces::{Account, Contract}; + use tokio::runtime::Runtime; + use serde_json::json; + use near_sdk::AccountId; + use borsh::BorshDeserialize; + + const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/ownable_base.wasm"; + + fn get_contract() -> (Account, Contract) { + let rt = Runtime::new().unwrap(); + let worker = rt.block_on(workspaces::sandbox()).unwrap(); + + let owner = worker.root_account().unwrap(); + + let wasm = std::fs::read(WASM_FILEPATH).unwrap(); + let contract = rt.block_on(owner.deploy(&wasm)).unwrap().unwrap(); + + (owner, contract) + } + + #[test] + fn base_scenario() { + let (owner, contract) = get_contract(); + let rt = Runtime::new().unwrap(); + + rt.block_on( + contract.call("new") + .max_gas() + .transact() + ); + + + let current_owner: Option:: = serde_json::from_slice( + &rt.block_on( + contract.view("owner_get", + json!({}).to_string().into_bytes()) + ).unwrap().result).unwrap(); + + assert_eq!(current_owner.unwrap().as_str(), owner.id().as_str()); + + let counter: u64 = serde_json::from_slice( + &rt.block_on( + contract.view("get_counter", + json!({}).to_string().into_bytes()) + ).unwrap().result).unwrap(); + + assert_eq!(counter, 0); + } +} From 85b979c828e0dd2b66eecc9f3869196db8847e16 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Fri, 14 Oct 2022 11:49:14 +0300 Subject: [PATCH 02/68] function for view and call --- examples/ownable_base/src/lib.rs | 37 +++++++++++++++++++------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/examples/ownable_base/src/lib.rs b/examples/ownable_base/src/lib.rs index 19728bf..7350be9 100644 --- a/examples/ownable_base/src/lib.rs +++ b/examples/ownable_base/src/lib.rs @@ -70,31 +70,38 @@ mod tests { (owner, contract) } - #[test] - fn base_scenario() { - let (owner, contract) = get_contract(); + fn view(contract: &Contract, method_name: &str) -> Vec { let rt = Runtime::new().unwrap(); rt.block_on( - contract.call("new") - .max_gas() - .transact() - ); + contract.view(method_name, + json!({}).to_string().into_bytes()) + ).unwrap().result + } + + fn call(contract: &Contract, method_name: &str) { + let rt = Runtime::new().unwrap(); + + rt.block_on( + contract.call(method_name) + .max_gas() + .transact() + ); + } + + #[test] + fn base_scenario() { + let (owner, contract) = get_contract(); + call(&contract,"new"); let current_owner: Option:: = serde_json::from_slice( - &rt.block_on( - contract.view("owner_get", - json!({}).to_string().into_bytes()) - ).unwrap().result).unwrap(); + &view(&contract, "owner_get")).unwrap(); assert_eq!(current_owner.unwrap().as_str(), owner.id().as_str()); let counter: u64 = serde_json::from_slice( - &rt.block_on( - contract.view("get_counter", - json!({}).to_string().into_bytes()) - ).unwrap().result).unwrap(); + &view(&contract, "get_counter")).unwrap(); assert_eq!(counter, 0); } From b59bad5ff22509c3d02eb40262a91d02bc4e0a6e Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Fri, 14 Oct 2022 13:37:44 +0300 Subject: [PATCH 03/68] view macros --- examples/ownable_base/src/lib.rs | 74 +++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 10 deletions(-) diff --git a/examples/ownable_base/src/lib.rs b/examples/ownable_base/src/lib.rs index 7350be9..952119b 100644 --- a/examples/ownable_base/src/lib.rs +++ b/examples/ownable_base/src/lib.rs @@ -53,8 +53,7 @@ mod tests { use workspaces::{Account, Contract}; use tokio::runtime::Runtime; use serde_json::json; - use near_sdk::AccountId; - use borsh::BorshDeserialize; + use near_sdk::{AccountId, ONE_NEAR}; const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/ownable_base.wasm"; @@ -79,30 +78,85 @@ mod tests { ).unwrap().result } - fn call(contract: &Contract, method_name: &str) { + fn call(contract: &Contract, method_name: &str) -> bool { let rt = Runtime::new().unwrap(); rt.block_on( contract.call(method_name) .max_gas() .transact() - ); + ).unwrap().is_success() + } + + fn call_arg(contract: &Contract, method_name: &str, args: &serde_json::Value) -> bool { + let rt = Runtime::new().unwrap(); + + rt.block_on( + contract.call(method_name) + .args_json(args) + .max_gas() + .transact() + ).unwrap().is_success() + } + + fn call_by(account: &Account, contract: &Contract, method_name: &str) -> bool { + let rt = Runtime::new().unwrap(); + + rt.block_on( + account.call(contract.id(),method_name) + .max_gas() + .transact() + ).unwrap().is_success() + } + + fn get_subaccount(account: &Account, new_account_name: &str) -> Account { + let rt = Runtime::new().unwrap(); + + rt.block_on(account.create_subaccount(new_account_name) + .initial_balance(ONE_NEAR) + .transact()).unwrap().unwrap() + } + + macro_rules! view { + ($contract:ident, $method_name:literal) => { + serde_json::from_slice(&view(&$contract, $method_name)).unwrap() + } } #[test] fn base_scenario() { - let (owner, contract) = get_contract(); + let (contract_holder, contract) = get_contract(); - call(&contract,"new"); + assert!(call(&contract,"new")); - let current_owner: Option:: = serde_json::from_slice( - &view(&contract, "owner_get")).unwrap(); + let current_owner: Option:: = view!(contract, "owner_get"); + assert_eq!(current_owner.unwrap().as_str(), contract_holder.id().as_str()); - assert_eq!(current_owner.unwrap().as_str(), owner.id().as_str()); + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 0); + + assert!(call(&contract, "protected")); + assert!(call(&contract, "protected_owner")); + assert!(call(&contract, "protected_self")); + assert!(call(&contract, "unprotected")); + + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 4); + + let next_owner = get_subaccount(&contract_holder, "next_owner"); + assert!(!call_by(&next_owner, &contract, "protected")); + assert!(!call_by(&next_owner, &contract, "protected_owner")); + assert!(!call_by(&next_owner, &contract, "protected_self")); + assert!(call_by(&next_owner, &contract, "unprotected")); let counter: u64 = serde_json::from_slice( &view(&contract, "get_counter")).unwrap(); + assert_eq!(counter, 5); - assert_eq!(counter, 0); + assert!(call_arg(&contract, "owner_set", &json!({"owner": next_owner.id()}))); + + let current_owner: Option:: = view!(contract, "owner_get"); + assert_ne!(current_owner.clone().unwrap().as_str(), contract_holder.id().as_str()); + assert_eq!(current_owner.unwrap().as_str(), next_owner.id().as_str()); } } From 8932a4606f537b720d66ce1701f83b3fc1b283e3 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Fri, 14 Oct 2022 15:15:55 +0300 Subject: [PATCH 04/68] tests for ownable --- examples/ownable_base/src/lib.rs | 63 ++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/examples/ownable_base/src/lib.rs b/examples/ownable_base/src/lib.rs index 952119b..c9b07f7 100644 --- a/examples/ownable_base/src/lib.rs +++ b/examples/ownable_base/src/lib.rs @@ -52,8 +52,9 @@ impl Counter { mod tests { use workspaces::{Account, Contract}; use tokio::runtime::Runtime; - use serde_json::json; + use serde_json::{json, Value}; use near_sdk::{AccountId, ONE_NEAR}; + use workspaces::result::{ExecutionResult, ExecutionSuccess, ValueOrReceiptId}; const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/ownable_base.wasm"; @@ -149,8 +150,7 @@ mod tests { assert!(!call_by(&next_owner, &contract, "protected_self")); assert!(call_by(&next_owner, &contract, "unprotected")); - let counter: u64 = serde_json::from_slice( - &view(&contract, "get_counter")).unwrap(); + let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 5); assert!(call_arg(&contract, "owner_set", &json!({"owner": next_owner.id()}))); @@ -158,5 +158,62 @@ mod tests { let current_owner: Option:: = view!(contract, "owner_get"); assert_ne!(current_owner.clone().unwrap().as_str(), contract_holder.id().as_str()); assert_eq!(current_owner.unwrap().as_str(), next_owner.id().as_str()); + + assert!(call_by(&next_owner, &contract, "protected")); + assert!(call_by(&next_owner, &contract, "protected_owner")); + assert!(!call_by(&next_owner, &contract, "protected_self")); + assert!(call_by(&next_owner, &contract, "unprotected")); + + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 8); + + assert!(call(&contract, "protected")); + assert!(!call(&contract, "protected_owner")); + assert!(call(&contract, "protected_self")); + assert!(call(&contract, "unprotected")); + + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 11); + } + + #[test] + fn null_owner() { + let (contract_holder, contract) = get_contract(); + let rt = Runtime::new().unwrap(); + + assert!(call(&contract,"new")); + + assert!(call_arg(&contract, "owner_set", &json!({"owner": Option::::None}))); + + let current_owner: Option:: = view!(contract, "owner_get"); + assert_eq!(current_owner, None); + + assert!(call(&contract, "protected")); + assert!(!call(&contract, "protected_owner")); + assert!(call(&contract, "protected_self")); + assert!(call(&contract, "unprotected")); + + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 3); + + assert!(call_arg(&contract, "owner_set", &json!({"owner": contract.id().as_str()}))); + assert!(call(&contract, "protected")); + assert!(call(&contract, "protected_owner")); + assert!(call(&contract, "protected_self")); + assert!(call(&contract, "unprotected")); + + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 7); + } + + #[test] + fn check_owner_storage_key() { + let (contract_holder, contract) = get_contract(); + let rt = Runtime::new().unwrap(); + + assert!(call(&contract,"new")); + + let owner_storage_key: Vec = view!(contract, "owner_storage_key"); + assert_eq!(owner_storage_key, "__OWNER__".as_bytes().to_vec()); } } From 0af6958d36f166d1a2c61fb321a944a1fd9be338 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Fri, 14 Oct 2022 16:08:51 +0300 Subject: [PATCH 05/68] example change owner_storage_key --- .../ownable_change_storage_key/Cargo.toml | 23 ++++ examples/ownable_change_storage_key/build.sh | 3 + .../ownable_change_storage_key/src/lib.rs | 109 ++++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 examples/ownable_change_storage_key/Cargo.toml create mode 100755 examples/ownable_change_storage_key/build.sh create mode 100644 examples/ownable_change_storage_key/src/lib.rs diff --git a/examples/ownable_change_storage_key/Cargo.toml b/examples/ownable_change_storage_key/Cargo.toml new file mode 100644 index 0000000..2860fce --- /dev/null +++ b/examples/ownable_change_storage_key/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "ownable_change_storage_key" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +near-sdk = "4.0.0" +near-plugins = { path = "../../near-plugins" } +near-plugins-derive = { path = "../../near-plugins-derive" } +borsh = "0.9.3" + +[dev-dependencies] +near-primitives = "0.14.0" +workspaces = "0.6" +tokio = { version = "1.1", features = ["rt", "macros"] } +serde_json = "1.0.74" + + diff --git a/examples/ownable_change_storage_key/build.sh b/examples/ownable_change_storage_key/build.sh new file mode 100755 index 0000000..651e364 --- /dev/null +++ b/examples/ownable_change_storage_key/build.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +/bin/bash -c "rustup target add wasm32-unknown-unknown; cargo build --target wasm32-unknown-unknown --release" diff --git a/examples/ownable_change_storage_key/src/lib.rs b/examples/ownable_change_storage_key/src/lib.rs new file mode 100644 index 0000000..8360ce2 --- /dev/null +++ b/examples/ownable_change_storage_key/src/lib.rs @@ -0,0 +1,109 @@ +use near_plugins::Ownable; +use near_sdk::near_bindgen; +use near_plugins_derive::only; +use borsh::{BorshSerialize, BorshDeserialize}; + +#[near_bindgen] +#[derive(Ownable, Default, BorshSerialize, BorshDeserialize)] +#[ownable(owner_storage_key="new_storage_key")] +struct Counter { + counter: u64, +} + +#[near_bindgen] +impl Counter { + /// Specify the owner of the contract in the constructor + #[init] + pub fn new() -> Self { + let mut contract = Self { counter: 0 }; + contract.owner_set(Some(near_sdk::env::predecessor_account_id())); + contract + } + + /// Only owner account, or the contract itself can call this method. + #[only(self, owner)] + pub fn protected(&mut self) { + self.counter += 1; + } + + /// *Only* owner account can call this method. + #[only(owner)] + pub fn protected_owner(&mut self) { + self.counter += 1; + } + + /// *Only* self account can call this method. This can be used even if the contract is not Ownable. + #[only(self)] + pub fn protected_self(&mut self) { + self.counter += 1; + } + + /// Everyone can call this method + pub fn unprotected(&mut self) { + self.counter += 1; + } + + pub fn get_counter(&self) -> u64 { + self.counter + } +} + + +#[cfg(test)] +mod tests { + use workspaces::{Account, Contract}; + use tokio::runtime::Runtime; + use serde_json::{json, Value}; + use near_sdk::{AccountId, ONE_NEAR}; + use workspaces::result::{ExecutionResult, ExecutionSuccess, ValueOrReceiptId}; + + const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/ownable_change_storage_key.wasm"; + + fn get_contract() -> (Account, Contract) { + let rt = Runtime::new().unwrap(); + let worker = rt.block_on(workspaces::sandbox()).unwrap(); + + let owner = worker.root_account().unwrap(); + + let wasm = std::fs::read(WASM_FILEPATH).unwrap(); + let contract = rt.block_on(owner.deploy(&wasm)).unwrap().unwrap(); + + (owner, contract) + } + + fn view(contract: &Contract, method_name: &str) -> Vec { + let rt = Runtime::new().unwrap(); + + rt.block_on( + contract.view(method_name, + json!({}).to_string().into_bytes()) + ).unwrap().result + } + + fn call(contract: &Contract, method_name: &str) -> bool { + let rt = Runtime::new().unwrap(); + + rt.block_on( + contract.call(method_name) + .max_gas() + .transact() + ).unwrap().is_success() + } + + macro_rules! view { + ($contract:ident, $method_name:literal) => { + serde_json::from_slice(&view(&$contract, $method_name)).unwrap() + } + } + + #[test] + fn check_owner_storage_key() { + let (contract_holder, contract) = get_contract(); + let rt = Runtime::new().unwrap(); + + assert!(call(&contract,"new")); + + let owner_storage_key: Vec = view!(contract, "owner_storage_key"); + assert_eq!(owner_storage_key, "new_storage_key".as_bytes().to_vec()); + } +} From 2a0d8a6f5b5716eed6e93162961a1b874b85d490 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Fri, 14 Oct 2022 19:01:27 +0300 Subject: [PATCH 06/68] cross contract example --- examples/ownable_cross_call/Cargo.toml | 23 ++++ examples/ownable_cross_call/build.sh | 3 + examples/ownable_cross_call/src/lib.rs | 181 +++++++++++++++++++++++++ 3 files changed, 207 insertions(+) create mode 100644 examples/ownable_cross_call/Cargo.toml create mode 100755 examples/ownable_cross_call/build.sh create mode 100644 examples/ownable_cross_call/src/lib.rs diff --git a/examples/ownable_cross_call/Cargo.toml b/examples/ownable_cross_call/Cargo.toml new file mode 100644 index 0000000..411d7fc --- /dev/null +++ b/examples/ownable_cross_call/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "ownable_cross_call" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +near-sdk = "4.0.0" +near-plugins = { path = "../../near-plugins" } +near-plugins-derive = { path = "../../near-plugins-derive" } +borsh = "0.9.3" + +[dev-dependencies] +near-primitives = "0.14.0" +workspaces = "0.6" +tokio = { version = "1.1", features = ["rt", "macros"] } +serde_json = "1.0.74" + + diff --git a/examples/ownable_cross_call/build.sh b/examples/ownable_cross_call/build.sh new file mode 100755 index 0000000..651e364 --- /dev/null +++ b/examples/ownable_cross_call/build.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +/bin/bash -c "rustup target add wasm32-unknown-unknown; cargo build --target wasm32-unknown-unknown --release" diff --git a/examples/ownable_cross_call/src/lib.rs b/examples/ownable_cross_call/src/lib.rs new file mode 100644 index 0000000..6cd0f3c --- /dev/null +++ b/examples/ownable_cross_call/src/lib.rs @@ -0,0 +1,181 @@ +use near_plugins::Ownable; +use near_sdk::{env, near_bindgen}; +use near_sdk::ext_contract; +use near_plugins_derive::only; +use borsh::{BorshSerialize, BorshDeserialize}; + +#[ext_contract(ext_counter)] +pub trait ExtCounter { + fn protected_self(&mut self); + fn protected_owner(&mut self); +} + +#[near_bindgen] +#[derive(Ownable, Default, BorshSerialize, BorshDeserialize)] +struct Counter { + counter: u64, +} + +#[near_bindgen] +impl Counter { + /// Specify the owner of the contract in the constructor + #[init] + pub fn new() -> Self { + let mut contract = Self { counter: 0 }; + contract.owner_set(Some(near_sdk::env::predecessor_account_id())); + contract + } + + /// Only owner account, or the contract itself can call this method. + #[only(self, owner)] + pub fn protected(&mut self) { + self.counter += 1; + } + + /// *Only* owner account can call this method. + #[only(owner)] + pub fn protected_owner(&mut self) { + self.counter += 1; + } + + /// *Only* self account can call this method. This can be used even if the contract is not Ownable. + #[only(self)] + pub fn protected_self(&mut self) { + self.counter += 1; + } + + /// Everyone can call this method + pub fn unprotected(&mut self) { + self.counter += 1; + } + + #[only(owner)] + pub fn cross_call_owner_self(&mut self) { + ext_counter::ext(env::current_account_id()).protected_self(); + } + + #[only(self)] + pub fn cross_call_self_owner(&mut self) { + ext_counter::ext(env::current_account_id()).protected_owner(); + } + + #[only(owner)] + pub fn cross_call_owner_owner(&mut self) { + ext_counter::ext(env::current_account_id()).protected_owner(); + } + + #[only(self)] + pub fn cross_call_self_self(&mut self) { + ext_counter::ext(env::current_account_id()).protected_self(); + } + + pub fn get_counter(&self) -> u64 { + self.counter + } +} + + +#[cfg(test)] +mod tests { + use workspaces::{Account, Contract}; + use tokio::runtime::Runtime; + use serde_json::{json, Value}; + use near_sdk::{AccountId, ONE_NEAR}; + use workspaces::result::{ExecutionResult, ExecutionSuccess, ValueOrReceiptId}; + + const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/ownable_cross_call.wasm"; + + fn get_contract() -> (Account, Contract) { + let rt = Runtime::new().unwrap(); + let worker = rt.block_on(workspaces::sandbox()).unwrap(); + + let owner = worker.root_account().unwrap(); + + let wasm = std::fs::read(WASM_FILEPATH).unwrap(); + let contract = rt.block_on(owner.deploy(&wasm)).unwrap().unwrap(); + + (owner, contract) + } + + fn view(contract: &Contract, method_name: &str) -> Vec { + let rt = Runtime::new().unwrap(); + + rt.block_on( + contract.view(method_name, + json!({}).to_string().into_bytes()) + ).unwrap().result + } + + fn call(contract: &Contract, method_name: &str) -> bool { + let rt = Runtime::new().unwrap(); + + rt.block_on( + contract.call(method_name) + .max_gas() + .transact() + ).unwrap().is_success() + } + + fn call_arg(contract: &Contract, method_name: &str, args: &serde_json::Value) -> bool { + let rt = Runtime::new().unwrap(); + + rt.block_on( + contract.call(method_name) + .args_json(args) + .max_gas() + .transact() + ).unwrap().is_success() + } + + fn call_by(account: &Account, contract: &Contract, method_name: &str) -> bool { + let rt = Runtime::new().unwrap(); + + rt.block_on( + account.call(contract.id(),method_name) + .max_gas() + .transact() + ).unwrap().is_success() + } + + fn get_subaccount(account: &Account, new_account_name: &str) -> Account { + let rt = Runtime::new().unwrap(); + + rt.block_on(account.create_subaccount(new_account_name) + .initial_balance(ONE_NEAR) + .transact()).unwrap().unwrap() + } + + macro_rules! view { + ($contract:ident, $method_name:literal) => { + serde_json::from_slice(&view(&$contract, $method_name)).unwrap() + } + } + + #[test] + fn base_scenario() { + let (contract_holder, contract) = get_contract(); + + assert!(call(&contract,"new")); + let next_owner = get_subaccount(&contract_holder, "next_owner"); + assert!(call_arg(&contract, "owner_set", &json!({"owner": next_owner.id()}))); + let current_owner: Option:: = view!(contract, "owner_get"); + assert_ne!(current_owner.clone().unwrap().as_str(), contract_holder.id().as_str()); + assert_eq!(current_owner.unwrap().as_str(), next_owner.id().as_str()); + + assert!(call_by(&next_owner, &contract, "cross_call_owner_self")); + assert!(call_by(&next_owner, &contract, "cross_call_owner_owner")); + assert!(!call_by(&next_owner, &contract, "cross_call_self_self")); + assert!(!call_by(&next_owner, &contract, "cross_call_self_owner")); + + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 1); + + assert!(!call(&contract, "cross_call_owner_self")); + assert!(!call(&contract, "cross_call_owner_owner")); + assert!(call(&contract, "cross_call_self_self")); + assert!(call(&contract, "cross_call_self_owner")); + + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 2); + } +} From d36c09bd0557539db5d25ecb14a6ee5de5739ad1 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Sat, 15 Oct 2022 13:43:51 +0300 Subject: [PATCH 07/68] separate add extra code to function --- near-plugins-derive/src/access_controllable.rs | 1 + near-plugins-derive/src/ownable.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/near-plugins-derive/src/access_controllable.rs b/near-plugins-derive/src/access_controllable.rs index 0722817..d3ef1e7 100644 --- a/near-plugins-derive/src/access_controllable.rs +++ b/near-plugins-derive/src/access_controllable.rs @@ -7,6 +7,7 @@ use proc_macro2::Span; use quote::quote; use syn::parse::Parser; use syn::{parse_macro_input, AttributeArgs, ItemFn, ItemStruct}; +use crate::utils; #[derive(Debug, FromMeta)] pub struct MacroArgs { diff --git a/near-plugins-derive/src/ownable.rs b/near-plugins-derive/src/ownable.rs index 08abcde..0c48f23 100644 --- a/near-plugins-derive/src/ownable.rs +++ b/near-plugins-derive/src/ownable.rs @@ -4,6 +4,7 @@ use darling::FromDeriveInput; use proc_macro::{self, TokenStream}; use quote::quote; use syn::{parse, parse_macro_input, DeriveInput, ItemFn}; +use crate::utils; #[derive(FromDeriveInput, Default)] #[darling(default, attributes(ownable), forward_attrs(allow, doc, cfg))] From fd7b3ae340a37784a1b5503c2449cd304a6fecf1 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Sat, 15 Oct 2022 18:28:02 +0300 Subject: [PATCH 08/68] example for pausable --- examples/pausable_base/Cargo.toml | 23 ++++ examples/pausable_base/build.sh | 3 + examples/pausable_base/src/lib.rs | 197 ++++++++++++++++++++++++++++++ 3 files changed, 223 insertions(+) create mode 100644 examples/pausable_base/Cargo.toml create mode 100755 examples/pausable_base/build.sh create mode 100644 examples/pausable_base/src/lib.rs diff --git a/examples/pausable_base/Cargo.toml b/examples/pausable_base/Cargo.toml new file mode 100644 index 0000000..0c67a81 --- /dev/null +++ b/examples/pausable_base/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "pausable_base" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +near-sdk = "4.0.0" +near-plugins = { path = "../../near-plugins" } +near-plugins-derive = { path = "../../near-plugins-derive" } +borsh = "0.9.3" + +[dev-dependencies] +near-primitives = "0.14.0" +workspaces = "0.6" +tokio = { version = "1.1", features = ["rt", "macros"] } +serde_json = "1.0.74" + + diff --git a/examples/pausable_base/build.sh b/examples/pausable_base/build.sh new file mode 100755 index 0000000..651e364 --- /dev/null +++ b/examples/pausable_base/build.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +/bin/bash -c "rustup target add wasm32-unknown-unknown; cargo build --target wasm32-unknown-unknown --release" diff --git a/examples/pausable_base/src/lib.rs b/examples/pausable_base/src/lib.rs new file mode 100644 index 0000000..829ec4d --- /dev/null +++ b/examples/pausable_base/src/lib.rs @@ -0,0 +1,197 @@ +use near_plugins::Ownable; +use near_plugins::Pausable; +use near_sdk::near_bindgen; +use near_plugins_derive::only; +use near_plugins_derive::{pause, if_paused}; +use borsh::{BorshSerialize, BorshDeserialize}; + +#[near_bindgen] +#[derive(Ownable, Pausable, Default, BorshSerialize, BorshDeserialize)] +struct Counter { + counter: u64, +} + +#[near_bindgen] +impl Counter { + /// Specify the owner of the contract in the constructor + #[init] + pub fn new() -> Self { + let mut contract = Self { counter: 0 }; + contract.owner_set(Some(near_sdk::env::predecessor_account_id())); + contract + } + + /// Function can be paused using feature name "increase_1" or "ALL" like: + /// `contract.pa_pause_feature("increase_1")` or `contract.pa_pause_feature("ALL")` + /// + /// If the function is paused, all calls to it will fail. Even calls started from owner or self. + #[pause] + pub fn increase_1(&mut self) { + self.counter += 1; + } + + /// Similar to `#[pause]` but use an explicit name for the feature. In this case the feature to be paused + /// is named "Increase by two". Note that trying to pause it using "increase_2" will not have any effect. + /// + /// This can be used to pause a subset of the methods at once without requiring to use "ALL". + #[pause(name = "Increase by two")] + pub fn increase_2(&mut self) { + self.counter += 2; + } + + /// Similar to `#[pause]` but owner or self can still call this method. Any subset of {self, owner} can be specified. + #[pause(except(owner, self))] + pub fn increase_4(&mut self) { + self.counter += 4; + } + + /// This method can only be called when "increase_1" is paused. Use this macro to create escape hatches when some + /// features are paused. Note that if "ALL" is specified the "increase_1" is considered to be paused. + #[if_paused(name = "increase_1")] + pub fn decrease_1(&mut self) { + self.counter -= 1; + } + + /// Custom use of pause features. Only allow increasing the counter using `careful_increase` if it is below 10. + pub fn careful_increase(&mut self) { + if self.counter >= 10 { + assert!( + !self.pa_is_paused("INCREASE_BIG".to_string()), + "Method paused for large values of counter" + ); + } + + self.counter += 1; + } + + pub fn get_counter(&self) -> u64 { + self.counter + } +} + +#[cfg(test)] +mod tests { + use workspaces::{Account, Contract}; + use tokio::runtime::Runtime; + use serde_json::{json, Value}; + use near_sdk::{AccountId, ONE_NEAR}; + use workspaces::result::{ExecutionResult, ExecutionSuccess, ValueOrReceiptId}; + + const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/pausable_base.wasm"; + + fn get_contract() -> (Account, Contract) { + let rt = Runtime::new().unwrap(); + let worker = rt.block_on(workspaces::sandbox()).unwrap(); + + let owner = worker.root_account().unwrap(); + + let wasm = std::fs::read(WASM_FILEPATH).unwrap(); + let contract = rt.block_on(owner.deploy(&wasm)).unwrap().unwrap(); + + (owner, contract) + } + + fn view(contract: &Contract, method_name: &str) -> Vec { + let rt = Runtime::new().unwrap(); + + rt.block_on( + contract.view(method_name, + json!({}).to_string().into_bytes()) + ).unwrap().result + } + + fn call(contract: &Contract, method_name: &str) -> bool { + let rt = Runtime::new().unwrap(); + + rt.block_on( + contract.call(method_name) + .max_gas() + .transact() + ).unwrap().is_success() + } + + fn call_arg(contract: &Contract, method_name: &str, args: &serde_json::Value) -> bool { + let rt = Runtime::new().unwrap(); + + rt.block_on( + contract.call(method_name) + .args_json(args) + .max_gas() + .transact() + ).unwrap().is_success() + } + + fn call_by(account: &Account, contract: &Contract, method_name: &str) -> bool { + let rt = Runtime::new().unwrap(); + + rt.block_on( + account.call(contract.id(),method_name) + .max_gas() + .transact() + ).unwrap().is_success() + } + + fn call_by_with_arg(account: &Account, contract: &Contract, method_name: &str, args: &serde_json::Value) -> bool { + let rt = Runtime::new().unwrap(); + + rt.block_on( + account.call(contract.id(), method_name) + .args_json(args) + .max_gas() + .transact() + ).unwrap().is_success() + } + + fn get_subaccount(account: &Account, new_account_name: &str) -> Account { + let rt = Runtime::new().unwrap(); + + rt.block_on(account.create_subaccount(new_account_name) + .initial_balance(ONE_NEAR) + .transact()).unwrap().unwrap() + } + + macro_rules! view { + ($contract:ident, $method_name:literal) => { + serde_json::from_slice(&view(&$contract, $method_name)).unwrap() + } + } + + #[test] + fn base_scenario() { + let (contract_holder, contract) = get_contract(); + + assert!(call(&contract,"new")); + + let next_owner = get_subaccount(&contract_holder, "next_owner"); + assert!(call_arg(&contract, "owner_set", &json!({"owner": next_owner.id()}))); + let current_owner: Option:: = view!(contract, "owner_get"); + assert_eq!(current_owner.unwrap().as_str(), next_owner.id().as_str()); + + let alice = get_subaccount(&contract_holder, "alice"); + + assert!(call_by(&alice, &contract, "increase_1")); + + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 1); + + assert!(!call_by_with_arg(&alice, &contract, "pa_pause_feature", &json!({"key": "increase_1"}))); + assert!(call_by_with_arg(&next_owner, &contract, "pa_pause_feature", &json!({"key": "increase_1"}))); + + assert!(!call_by(&alice, &contract, "increase_1")); + + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 1); + + assert!(!call_by(&next_owner, &contract, "increase_1")); + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 1); + + assert!(!call_by_with_arg(&contract_holder, &contract, "pa_unpause_feature", &json!({"key": "increase_1"}))); + assert!(call_by_with_arg(&next_owner, &contract, "pa_unpause_feature", &json!({"key": "increase_1"}))); + + assert!(call_by(&alice, &contract, "increase_1")); + + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 2); + } +} From a9e2ea0f9ff81e6e5546c7f850d08011874ad19c Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Sun, 16 Oct 2022 14:15:24 +0300 Subject: [PATCH 09/68] example for upgradable base second --- examples/upgradable_base/Cargo.toml | 23 ++++ examples/upgradable_base/build.sh | 3 + examples/upgradable_base/src/lib.rs | 121 +++++++++++++++++++++ examples/upgradable_base_second/Cargo.toml | 23 ++++ examples/upgradable_base_second/build.sh | 3 + examples/upgradable_base_second/src/lib.rs | 27 +++++ 6 files changed, 200 insertions(+) create mode 100644 examples/upgradable_base/Cargo.toml create mode 100755 examples/upgradable_base/build.sh create mode 100644 examples/upgradable_base/src/lib.rs create mode 100644 examples/upgradable_base_second/Cargo.toml create mode 100755 examples/upgradable_base_second/build.sh create mode 100644 examples/upgradable_base_second/src/lib.rs diff --git a/examples/upgradable_base/Cargo.toml b/examples/upgradable_base/Cargo.toml new file mode 100644 index 0000000..f780046 --- /dev/null +++ b/examples/upgradable_base/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "upgradable_base" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +near-sdk = "4.0.0" +near-plugins = { path = "../../near-plugins" } +near-plugins-derive = { path = "../../near-plugins-derive" } +borsh = "0.9.3" + +[dev-dependencies] +near-primitives = { version = "0.14.0" } +workspaces = "0.6" +tokio = { version = "1.1", features = ["rt", "macros"] } +serde_json = "1.0.74" + + diff --git a/examples/upgradable_base/build.sh b/examples/upgradable_base/build.sh new file mode 100755 index 0000000..651e364 --- /dev/null +++ b/examples/upgradable_base/build.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +/bin/bash -c "rustup target add wasm32-unknown-unknown; cargo build --target wasm32-unknown-unknown --release" diff --git a/examples/upgradable_base/src/lib.rs b/examples/upgradable_base/src/lib.rs new file mode 100644 index 0000000..d6bf423 --- /dev/null +++ b/examples/upgradable_base/src/lib.rs @@ -0,0 +1,121 @@ +use near_plugins::{Ownable, Upgradable}; +use near_sdk::near_bindgen; +use borsh::{BorshSerialize, BorshDeserialize}; + +#[near_bindgen] +#[derive(Ownable, Upgradable, Default, BorshSerialize, BorshDeserialize)] +struct Counter1 { + counter: u64, +} + +#[near_bindgen] +impl Counter1 { + /// Specify the owner of the contract in the constructor + #[init] + pub fn new() -> Self { + let mut contract = Self { counter: 0 }; + contract.owner_set(Some(near_sdk::env::predecessor_account_id())); + contract + } + + pub fn inc1(&mut self) { + self.counter += 1; + } + + pub fn get_counter(&self) -> u64 { + self.counter + } +} + + +#[cfg(test)] +mod tests { + use workspaces::{Account, Contract}; + use tokio::runtime::Runtime; + use serde_json::{json, Value}; + use near_sdk::{AccountId, ONE_NEAR}; + use workspaces::result::{ExecutionResult, ExecutionSuccess, ValueOrReceiptId}; + + const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/upgradable_base.wasm"; + const WASM_FILEPATH_SECOND: &str = "../upgradable_base_second/target/wasm32-unknown-unknown/release/upgradable_base_second.wasm"; + + fn get_contract() -> (Account, Contract) { + let rt = Runtime::new().unwrap(); + let worker = rt.block_on(workspaces::testnet()).unwrap(); + + let owner = rt.block_on(worker.dev_create_account()).unwrap(); + + let wasm = std::fs::read(WASM_FILEPATH).unwrap(); + let contract = rt.block_on(owner.deploy(&wasm)).unwrap().unwrap(); + + (owner, contract) + } + + fn view(contract: &Contract, method_name: &str) -> Vec { + let rt = Runtime::new().unwrap(); + + rt.block_on( + contract.view(method_name, + json!({}).to_string().into_bytes()) + ).unwrap().result + } + + fn call(contract: &Contract, method_name: &str) -> bool { + let rt = Runtime::new().unwrap(); + + rt.block_on( + contract.call(method_name) + .max_gas() + .transact() + ).unwrap().is_success() + } + + fn call_arg(contract: &Contract, method_name: &str, args: Vec) -> bool { + let rt = Runtime::new().unwrap(); + + rt.block_on( + contract.call(method_name) + .args_borsh(args) + .max_gas() + .transact() + ).unwrap().is_success() + } + + macro_rules! view { + ($contract:ident, $method_name:literal) => { + serde_json::from_slice(&view(&$contract, $method_name)).unwrap() + } + } + + //https://docs.near.org/sdk/rust/promises/deploy-contract + #[test] + fn base_scenario() { + let (contract_holder, contract) = get_contract(); + assert!(call(&contract,"new")); + + assert!(call(&contract, "inc1")); + + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 1); + + assert!(!call(&contract, "inc2")); + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 1); + + let wasm = std::fs::read(WASM_FILEPATH_SECOND).unwrap(); + + assert!(call_arg(&contract, "up_stage_code", wasm)); + assert!(call(&contract, "up_deploy_code")); + + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 1); + + assert!(!call(&contract, "inc1")); + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 1); + + assert!(call(&contract, "inc2")); + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 3); + } +} diff --git a/examples/upgradable_base_second/Cargo.toml b/examples/upgradable_base_second/Cargo.toml new file mode 100644 index 0000000..6c18b4d --- /dev/null +++ b/examples/upgradable_base_second/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "upgradable_base_second" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +near-sdk = "4.0.0" +near-plugins = { path = "../../near-plugins" } +near-plugins-derive = { path = "../../near-plugins-derive" } +borsh = "0.9.3" + +[dev-dependencies] +near-primitives = "0.14.0" +workspaces = "0.6" +tokio = { version = "1.1", features = ["rt", "macros"] } +serde_json = "1.0.74" + + diff --git a/examples/upgradable_base_second/build.sh b/examples/upgradable_base_second/build.sh new file mode 100755 index 0000000..651e364 --- /dev/null +++ b/examples/upgradable_base_second/build.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +/bin/bash -c "rustup target add wasm32-unknown-unknown; cargo build --target wasm32-unknown-unknown --release" diff --git a/examples/upgradable_base_second/src/lib.rs b/examples/upgradable_base_second/src/lib.rs new file mode 100644 index 0000000..6439f24 --- /dev/null +++ b/examples/upgradable_base_second/src/lib.rs @@ -0,0 +1,27 @@ +use near_plugins::{Ownable, Upgradable}; +use near_sdk::near_bindgen; +use borsh::{BorshSerialize, BorshDeserialize}; + +#[near_bindgen] +#[derive(Ownable, Upgradable, Default, BorshSerialize, BorshDeserialize)] +struct Counter2 { + counter: u64, +} + +#[near_bindgen] +impl Counter2 { + #[init] + pub fn new() -> Self { + let mut contract = Self { counter: 0 }; + contract.owner_set(Some(near_sdk::env::predecessor_account_id())); + contract + } + + pub fn inc2(&mut self) { + self.counter += 2; + } + + pub fn get_counter(&self) -> u64 { + self.counter + } +} \ No newline at end of file From 28cc57d0d45b61859b07c11156594bfa75853d2d Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Mon, 17 Oct 2022 07:31:55 +0300 Subject: [PATCH 10/68] example for full access key fallback base --- .../full_access_key_fallback_base/Cargo.toml | 23 +++ .../full_access_key_fallback_base/build.sh | 3 + .../full_access_key_fallback_base/src/lib.rs | 164 ++++++++++++++++++ 3 files changed, 190 insertions(+) create mode 100644 examples/full_access_key_fallback_base/Cargo.toml create mode 100755 examples/full_access_key_fallback_base/build.sh create mode 100644 examples/full_access_key_fallback_base/src/lib.rs diff --git a/examples/full_access_key_fallback_base/Cargo.toml b/examples/full_access_key_fallback_base/Cargo.toml new file mode 100644 index 0000000..77ca378 --- /dev/null +++ b/examples/full_access_key_fallback_base/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "full_access_key_fallback_base" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +near-sdk = "4.0.0" +near-plugins = { path = "../../near-plugins" } +near-plugins-derive = { path = "../../near-plugins-derive" } +borsh = "0.9.3" + +[dev-dependencies] +near-primitives = "0.14.0" +workspaces = "0.6" +tokio = { version = "1.1", features = ["rt", "macros"] } +serde_json = "1.0.74" + + diff --git a/examples/full_access_key_fallback_base/build.sh b/examples/full_access_key_fallback_base/build.sh new file mode 100755 index 0000000..651e364 --- /dev/null +++ b/examples/full_access_key_fallback_base/build.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +/bin/bash -c "rustup target add wasm32-unknown-unknown; cargo build --target wasm32-unknown-unknown --release" diff --git a/examples/full_access_key_fallback_base/src/lib.rs b/examples/full_access_key_fallback_base/src/lib.rs new file mode 100644 index 0000000..84bea44 --- /dev/null +++ b/examples/full_access_key_fallback_base/src/lib.rs @@ -0,0 +1,164 @@ +use near_plugins::{Ownable, FullAccessKeyFallback}; +use near_sdk::near_bindgen; +use near_plugins_derive::only; +use borsh::{BorshSerialize, BorshDeserialize}; + +#[near_bindgen] +#[derive(Ownable, FullAccessKeyFallback, Default, BorshSerialize, BorshDeserialize)] +struct Counter { + counter: u64, +} + +#[near_bindgen] +impl Counter { + /// Specify the owner of the contract in the constructor + #[init] + pub fn new() -> Self { + let mut contract = Self { counter: 0 }; + contract.owner_set(Some(near_sdk::env::predecessor_account_id())); + contract + } + + /// *Only* self account can call this method. This can be used even if the contract is not Ownable. + #[only(self)] + pub fn protected_self(&mut self) { + self.counter += 1; + } + + pub fn get_counter(&self) -> u64 { + self.counter + } +} + + +#[cfg(test)] +mod tests { + use workspaces::{Account, Contract}; + use tokio::runtime::Runtime; + use serde_json::{json, Value}; + use near_sdk::{AccountId, ONE_NEAR}; + use workspaces::result::{ExecutionResult, ExecutionSuccess, ValueOrReceiptId}; + + const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/full_access_key_fallback_base.wasm"; + + fn get_contract() -> (Account, Contract) { + let rt = Runtime::new().unwrap(); + let worker = rt.block_on(workspaces::testnet()).unwrap(); + + let wasm = std::fs::read(WASM_FILEPATH).unwrap(); + let contract: Contract = rt.block_on(worker.dev_deploy(&wasm)).unwrap(); + + let owner = contract.as_account(); + + (owner.clone(), contract) + } + + fn view(contract: &Contract, method_name: &str) -> Vec { + let rt = Runtime::new().unwrap(); + + rt.block_on( + contract.view(method_name, + json!({}).to_string().into_bytes()) + ).unwrap().result + } + + fn call(contract: &Contract, method_name: &str) -> bool { + let rt = Runtime::new().unwrap(); + + rt.block_on( + contract.call(method_name) + .max_gas() + .transact() + ).unwrap().is_success() + } + + fn call_arg(contract: &Contract, method_name: &str, args: &serde_json::Value) -> bool { + let rt = Runtime::new().unwrap(); + + rt.block_on( + contract.call(method_name) + .args_json(args) + .max_gas() + .transact() + ).unwrap().is_success() + } + + fn call_by(account: &Account, contract: &Contract, method_name: &str) -> bool { + let rt = Runtime::new().unwrap(); + + rt.block_on( + account.call(contract.id(),method_name) + .max_gas() + .transact() + ).unwrap().is_success() + } + + fn call_by_with_arg(account: &Account, contract: &Contract, method_name: &str, args: &serde_json::Value) -> bool { + let rt = Runtime::new().unwrap(); + + rt.block_on( + account.call(contract.id(), method_name) + .args_json(args) + .max_gas() + .transact() + ).unwrap().is_success() + } + + fn get_subaccount(account: &Account, new_account_name: &str) -> Account { + let rt = Runtime::new().unwrap(); + + rt.block_on(account.create_subaccount(new_account_name) + .initial_balance(ONE_NEAR) + .transact()).unwrap().unwrap() + } + + macro_rules! view { + ($contract:ident, $method_name:literal) => { + serde_json::from_slice(&view(&$contract, $method_name)).unwrap() + } + } + + #[test] + fn base_scenario() { + let (mut contract_holder, contract) = get_contract(); + + assert!(call(&contract,"new")); + + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 0); + + let next_owner = get_subaccount(&contract_holder, "next_owner"); + assert!(call_arg(&contract, "owner_set", &json!({"owner": next_owner.id()}))); + let current_owner: Option:: = view!(contract, "owner_get"); + assert_eq!(current_owner.unwrap().as_str(), next_owner.id().as_str()); + + assert!(call_by(&contract_holder, &contract, "protected_self")); + + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 1); + + contract_holder.set_secret_key(next_owner.secret_key().clone()); + + assert!(call_by_with_arg(&next_owner, &contract, "attach_full_access_key", &json!({"public_key": next_owner.secret_key().public_key()}))); + + assert!(call(&contract, "protected_self")); + + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 2); + } + + #[test] + #[should_panic(expected = "AccessKeyNotFound")] + fn base_panic_on_wrong_key() { + let (mut contract_holder, contract) = get_contract(); + + assert!(call(&contract,"new")); + let next_owner = get_subaccount(&contract_holder, "next_owner"); + assert!(call_arg(&contract, "owner_set", &json!({"owner": next_owner.id()}))); + + assert!(call_by(&contract_holder, &contract, "protected_self")); + contract_holder.set_secret_key(next_owner.secret_key().clone()); + + call_by(&contract_holder, &contract, "protected_self"); + } +} From 30045d11740e1c7dae62564e075d3e05e2b5fa22 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Mon, 17 Oct 2022 09:32:07 +0300 Subject: [PATCH 11/68] axample for access_controle_role --- examples/access_control_role_base/Cargo.toml | 15 +++++++++++ examples/access_control_role_base/src/lib.rs | 27 ++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 examples/access_control_role_base/Cargo.toml create mode 100644 examples/access_control_role_base/src/lib.rs diff --git a/examples/access_control_role_base/Cargo.toml b/examples/access_control_role_base/Cargo.toml new file mode 100644 index 0000000..e000231 --- /dev/null +++ b/examples/access_control_role_base/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "access_control_role_base" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +near-plugins = { path = "../../near-plugins" } +near-plugins-derive = { path = "../../near-plugins-derive" } +bitflags = "1.3.2" +borsh = "*" diff --git a/examples/access_control_role_base/src/lib.rs b/examples/access_control_role_base/src/lib.rs new file mode 100644 index 0000000..2b97c4e --- /dev/null +++ b/examples/access_control_role_base/src/lib.rs @@ -0,0 +1,27 @@ +use near_plugins::AccessControlRole; +use borsh::{BorshDeserialize, BorshSerialize}; + +#[derive(AccessControlRole, Clone, Copy)] +pub enum Positions { + LevelA, + LevelB, + LevelC +} + +#[cfg(test)] +mod tests { + use near_plugins::AccessControlRole; + use crate::Positions; + + #[test] + fn base_scenario() { + let role: Positions = Positions::LevelA; + + assert_eq!(Positions::acl_super_admin_permission(), 1); + assert_eq!(role.acl_permission(), 1 << 1); + assert_eq!(role.acl_admin_permission(), 1 << 2); + + //https://docs.rs/bitflags/latest/bitflags/ + assert_eq!(crate::RoleFlags::LEVELA.bits, role.acl_permission() as u128); + } +} From 32f14a0afaffbed5b5d2449402e0e447e3310006 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Mon, 17 Oct 2022 13:51:42 +0300 Subject: [PATCH 12/68] example for access_controllable_base --- examples/access_controllable_base/Cargo.toml | 24 +++ examples/access_controllable_base/build.sh | 3 + examples/access_controllable_base/src/lib.rs | 174 +++++++++++++++++++ 3 files changed, 201 insertions(+) create mode 100644 examples/access_controllable_base/Cargo.toml create mode 100755 examples/access_controllable_base/build.sh create mode 100644 examples/access_controllable_base/src/lib.rs diff --git a/examples/access_controllable_base/Cargo.toml b/examples/access_controllable_base/Cargo.toml new file mode 100644 index 0000000..6e288b2 --- /dev/null +++ b/examples/access_controllable_base/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "access_controllable_base" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +near-sdk = "4.0.0" +near-plugins = { path = "../../near-plugins" } +near-plugins-derive = { path = "../../near-plugins-derive" } +borsh = "0.9.3" +bitflags = "*" + +[dev-dependencies] +near-primitives = "0.14.0" +workspaces = "0.6" +tokio = { version = "1.1", features = ["rt", "macros"] } +serde_json = "1.0.74" + + diff --git a/examples/access_controllable_base/build.sh b/examples/access_controllable_base/build.sh new file mode 100755 index 0000000..651e364 --- /dev/null +++ b/examples/access_controllable_base/build.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +/bin/bash -c "rustup target add wasm32-unknown-unknown; cargo build --target wasm32-unknown-unknown --release" diff --git a/examples/access_controllable_base/src/lib.rs b/examples/access_controllable_base/src/lib.rs new file mode 100644 index 0000000..7a8dca5 --- /dev/null +++ b/examples/access_controllable_base/src/lib.rs @@ -0,0 +1,174 @@ +use near_plugins::AccessControllable; +use near_plugins::AccessControlRole; +use near_plugins_derive::access_control; +use near_plugins_derive::access_control_any; +use near_sdk::near_bindgen; +use borsh::{BorshSerialize, BorshDeserialize}; +use near_plugins::events::AsEvent; +use near_sdk::env; + +#[derive(AccessControlRole, Clone, Copy)] +pub enum Positions { + LevelA, + LevelB, + LevelC +} + +#[near_bindgen] +#[access_control(role_type="Positions")] +#[derive(Default, BorshSerialize, BorshDeserialize)] +struct Counter { + counter: u64, +} + +#[near_bindgen] +impl Counter { + #[init] + pub fn new() -> Self { + let mut contract: Counter = Self{ + counter: 0, + __acl: __Acl::default(), + }; + + contract.__acl.init_super_admin(&near_sdk::env::predecessor_account_id()); + + contract + } + + pub fn unprotected(&mut self) { + self.counter += 1; + } + + #[access_control_any(roles(Positions::LevelA))] + pub fn level_a_incr(&mut self) { + self.counter += 1; + } + + pub fn get_counter(&self) -> u64 { + self.counter + } +} + + +#[cfg(test)] +mod tests { + use workspaces::{Account, Contract}; + use tokio::runtime::Runtime; + use serde_json::{json, Value}; + use near_sdk::{AccountId, ONE_NEAR}; + use crate::Positions; + use workspaces::result::{ExecutionResult, ExecutionSuccess, ValueOrReceiptId}; + + const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/access_controllable_base.wasm"; + + fn get_contract() -> (Account, Contract) { + let rt = Runtime::new().unwrap(); + let worker = rt.block_on(workspaces::sandbox()).unwrap(); + + let owner = worker.root_account().unwrap(); + + let wasm = std::fs::read(WASM_FILEPATH).unwrap(); + let contract = rt.block_on(owner.deploy(&wasm)).unwrap().unwrap(); + + (owner, contract) + } + + fn view(contract: &Contract, method_name: &str) -> Vec { + let rt = Runtime::new().unwrap(); + + rt.block_on( + contract.view(method_name, + json!({}).to_string().into_bytes()) + ).unwrap().result + } + + fn view_args(contract: &Contract, method_name: &str, args: &serde_json::Value) -> Vec { + let rt = Runtime::new().unwrap(); + + rt.block_on( + contract.view(method_name, + args.to_string().into_bytes()) + ).unwrap().result + } + + fn call(contract: &Contract, method_name: &str) -> bool { + let rt = Runtime::new().unwrap(); + + rt.block_on( + contract.call(method_name) + .max_gas() + .transact() + ).unwrap().is_success() + } + + fn call_arg(contract: &Contract, method_name: &str, args: &serde_json::Value) -> bool { + let rt = Runtime::new().unwrap(); + + rt.block_on( + contract.call(method_name) + .args_json(args) + .max_gas() + .transact() + ).unwrap().is_success() + } + + fn call_by(account: &Account, contract: &Contract, method_name: &str) -> bool { + let rt = Runtime::new().unwrap(); + + rt.block_on( + account.call(contract.id(),method_name) + .max_gas() + .transact() + ).unwrap().is_success() + } + + fn get_subaccount(account: &Account, new_account_name: &str) -> Account { + let rt = Runtime::new().unwrap(); + + rt.block_on(account.create_subaccount(new_account_name) + .initial_balance(ONE_NEAR) + .transact()).unwrap().unwrap() + } + + macro_rules! view { + ($contract:ident, $method_name:literal) => { + serde_json::from_slice(&view(&$contract, $method_name)).unwrap() + }; + ($contract:ident, $method_name:literal, $args:expr) => { + serde_json::from_slice(&view_args(&$contract, $method_name, $args)).unwrap() + }; + } + + #[test] + fn base_scenario() { + let (contract_holder, contract) = get_contract(); + assert!(call(&contract,"new")); + + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 0); + + assert!(call(&contract, "unprotected")); + + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 1); + + let alice = get_subaccount(&contract_holder, "alice"); + + let is_super_admin: bool = view!(contract, "acl_is_super_admin", &json!({"account_id": alice.id()})); + assert!(!is_super_admin); + + assert!(!call_by(&alice, &contract, "level_a_incr")); + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 1); + + assert!(call_arg(&contract, "acl_grant_role", &json!({"role": String::from(Positions::LevelA), "account_id": alice.id()}))); + + let alice_has_role: bool = view!(contract, "acl_has_role", &json!({"role": String::from(Positions::LevelA), "account_id": alice.id()})); + assert!(alice_has_role); + + assert!(call_by(&alice, &contract, "level_a_incr")); + + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 2); + } +} From 0f8e193ecf0a41a8d8769c178dbf66e978857576 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Mon, 17 Oct 2022 14:19:37 +0300 Subject: [PATCH 13/68] check that admin cann't call functions --- examples/access_controllable_base/src/lib.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/examples/access_controllable_base/src/lib.rs b/examples/access_controllable_base/src/lib.rs index 7a8dca5..cdce009 100644 --- a/examples/access_controllable_base/src/lib.rs +++ b/examples/access_controllable_base/src/lib.rs @@ -170,5 +170,17 @@ mod tests { let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 2); + + + let bob = get_subaccount(&contract_holder, "bob"); + assert!(call_arg(&contract, "acl_add_admin", &json!({"role": String::from(Positions::LevelA), "account_id": bob.id()}))); + + let bob_is_admin: bool = view!(contract, "acl_is_admin", &json!({"role": String::from(Positions::LevelA), "account_id": bob.id()})); + assert!(bob_is_admin); + + assert!(!call_by(&bob, &contract, "level_a_incr")); + + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 2); } } From 62546b7a3e2407937a12dc1d37762fffc7b799c5 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Mon, 17 Oct 2022 15:12:14 +0300 Subject: [PATCH 14/68] crate to roles function --- examples/access_controllable_base/src/lib.rs | 22 ++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/examples/access_controllable_base/src/lib.rs b/examples/access_controllable_base/src/lib.rs index cdce009..5eee29d 100644 --- a/examples/access_controllable_base/src/lib.rs +++ b/examples/access_controllable_base/src/lib.rs @@ -44,6 +44,11 @@ impl Counter { self.counter += 1; } + #[access_control_any(roles(Positions::LevelA, Positions::LevelB))] + pub fn level_ab_incr(&mut self) { + self.counter += 1; + } + pub fn get_counter(&self) -> u64 { self.counter } @@ -182,5 +187,22 @@ mod tests { let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 2); + + assert!(call_by(&alice, &contract, "level_ab_incr")); + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 3); + + assert!(!call_by(&bob, &contract, "level_ab_incr")); + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 3); + + assert!(call_arg(&contract, "acl_grant_role", &json!({"role": String::from(Positions::LevelB), "account_id": bob.id()}))); + assert!(call_by(&bob, &contract, "level_ab_incr")); + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 4); + + assert!(!call_by(&bob, &contract, "level_a_incr")); + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, 4); } } From e26e1ddde1964c85dec30d16d0f6c3c76871e066 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Tue, 18 Oct 2022 10:17:38 +0300 Subject: [PATCH 15/68] separate near-pluginf-test-utils --- examples/access_controllable_base/Cargo.toml | 2 +- examples/access_controllable_base/src/lib.rs | 87 +------------ .../full_access_key_fallback_base/Cargo.toml | 3 +- .../full_access_key_fallback_base/src/lib.rs | 89 +------------- examples/near-plugins-test-utils/Cargo.toml | 17 +++ examples/near-plugins-test-utils/src/lib.rs | 114 ++++++++++++++++++ examples/ownable_base/Cargo.toml | 1 + examples/ownable_base/src/lib.rs | 84 +------------ .../ownable_change_storage_key/Cargo.toml | 2 +- .../ownable_change_storage_key/src/lib.rs | 47 +------- examples/ownable_cross_call/Cargo.toml | 2 +- examples/ownable_cross_call/src/lib.rs | 76 +----------- examples/pausable_base/Cargo.toml | 1 + examples/pausable_base/src/lib.rs | 88 +------------- examples/upgradable_base/Cargo.toml | 2 +- examples/upgradable_base/src/lib.rs | 35 +----- 16 files changed, 166 insertions(+), 484 deletions(-) create mode 100644 examples/near-plugins-test-utils/Cargo.toml create mode 100644 examples/near-plugins-test-utils/src/lib.rs diff --git a/examples/access_controllable_base/Cargo.toml b/examples/access_controllable_base/Cargo.toml index 6e288b2..e1b5030 100644 --- a/examples/access_controllable_base/Cargo.toml +++ b/examples/access_controllable_base/Cargo.toml @@ -20,5 +20,5 @@ near-primitives = "0.14.0" workspaces = "0.6" tokio = { version = "1.1", features = ["rt", "macros"] } serde_json = "1.0.74" - +near-plugins-test-utils = { path = "../near-plugins-test-utils" } diff --git a/examples/access_controllable_base/src/lib.rs b/examples/access_controllable_base/src/lib.rs index 5eee29d..69341ea 100644 --- a/examples/access_controllable_base/src/lib.rs +++ b/examples/access_controllable_base/src/lib.rs @@ -57,96 +57,15 @@ impl Counter { #[cfg(test)] mod tests { - use workspaces::{Account, Contract}; - use tokio::runtime::Runtime; - use serde_json::{json, Value}; - use near_sdk::{AccountId, ONE_NEAR}; + use serde_json::json; use crate::Positions; - use workspaces::result::{ExecutionResult, ExecutionSuccess, ValueOrReceiptId}; + use near_plugins_test_utils::*; const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/access_controllable_base.wasm"; - fn get_contract() -> (Account, Contract) { - let rt = Runtime::new().unwrap(); - let worker = rt.block_on(workspaces::sandbox()).unwrap(); - - let owner = worker.root_account().unwrap(); - - let wasm = std::fs::read(WASM_FILEPATH).unwrap(); - let contract = rt.block_on(owner.deploy(&wasm)).unwrap().unwrap(); - - (owner, contract) - } - - fn view(contract: &Contract, method_name: &str) -> Vec { - let rt = Runtime::new().unwrap(); - - rt.block_on( - contract.view(method_name, - json!({}).to_string().into_bytes()) - ).unwrap().result - } - - fn view_args(contract: &Contract, method_name: &str, args: &serde_json::Value) -> Vec { - let rt = Runtime::new().unwrap(); - - rt.block_on( - contract.view(method_name, - args.to_string().into_bytes()) - ).unwrap().result - } - - fn call(contract: &Contract, method_name: &str) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on( - contract.call(method_name) - .max_gas() - .transact() - ).unwrap().is_success() - } - - fn call_arg(contract: &Contract, method_name: &str, args: &serde_json::Value) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on( - contract.call(method_name) - .args_json(args) - .max_gas() - .transact() - ).unwrap().is_success() - } - - fn call_by(account: &Account, contract: &Contract, method_name: &str) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on( - account.call(contract.id(),method_name) - .max_gas() - .transact() - ).unwrap().is_success() - } - - fn get_subaccount(account: &Account, new_account_name: &str) -> Account { - let rt = Runtime::new().unwrap(); - - rt.block_on(account.create_subaccount(new_account_name) - .initial_balance(ONE_NEAR) - .transact()).unwrap().unwrap() - } - - macro_rules! view { - ($contract:ident, $method_name:literal) => { - serde_json::from_slice(&view(&$contract, $method_name)).unwrap() - }; - ($contract:ident, $method_name:literal, $args:expr) => { - serde_json::from_slice(&view_args(&$contract, $method_name, $args)).unwrap() - }; - } - #[test] fn base_scenario() { - let (contract_holder, contract) = get_contract(); + let (contract_holder, contract) = get_contract(WASM_FILEPATH); assert!(call(&contract,"new")); let counter: u64 = view!(contract, "get_counter"); diff --git a/examples/full_access_key_fallback_base/Cargo.toml b/examples/full_access_key_fallback_base/Cargo.toml index 77ca378..2f4a21e 100644 --- a/examples/full_access_key_fallback_base/Cargo.toml +++ b/examples/full_access_key_fallback_base/Cargo.toml @@ -19,5 +19,4 @@ near-primitives = "0.14.0" workspaces = "0.6" tokio = { version = "1.1", features = ["rt", "macros"] } serde_json = "1.0.74" - - +near-plugins-test-utils = { path = "../near-plugins-test-utils" } diff --git a/examples/full_access_key_fallback_base/src/lib.rs b/examples/full_access_key_fallback_base/src/lib.rs index 84bea44..a0bc32a 100644 --- a/examples/full_access_key_fallback_base/src/lib.rs +++ b/examples/full_access_key_fallback_base/src/lib.rs @@ -33,94 +33,15 @@ impl Counter { #[cfg(test)] mod tests { - use workspaces::{Account, Contract}; - use tokio::runtime::Runtime; - use serde_json::{json, Value}; - use near_sdk::{AccountId, ONE_NEAR}; - use workspaces::result::{ExecutionResult, ExecutionSuccess, ValueOrReceiptId}; + use serde_json::json; + use near_sdk::AccountId; + use near_plugins_test_utils::*; const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/full_access_key_fallback_base.wasm"; - fn get_contract() -> (Account, Contract) { - let rt = Runtime::new().unwrap(); - let worker = rt.block_on(workspaces::testnet()).unwrap(); - - let wasm = std::fs::read(WASM_FILEPATH).unwrap(); - let contract: Contract = rt.block_on(worker.dev_deploy(&wasm)).unwrap(); - - let owner = contract.as_account(); - - (owner.clone(), contract) - } - - fn view(contract: &Contract, method_name: &str) -> Vec { - let rt = Runtime::new().unwrap(); - - rt.block_on( - contract.view(method_name, - json!({}).to_string().into_bytes()) - ).unwrap().result - } - - fn call(contract: &Contract, method_name: &str) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on( - contract.call(method_name) - .max_gas() - .transact() - ).unwrap().is_success() - } - - fn call_arg(contract: &Contract, method_name: &str, args: &serde_json::Value) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on( - contract.call(method_name) - .args_json(args) - .max_gas() - .transact() - ).unwrap().is_success() - } - - fn call_by(account: &Account, contract: &Contract, method_name: &str) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on( - account.call(contract.id(),method_name) - .max_gas() - .transact() - ).unwrap().is_success() - } - - fn call_by_with_arg(account: &Account, contract: &Contract, method_name: &str, args: &serde_json::Value) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on( - account.call(contract.id(), method_name) - .args_json(args) - .max_gas() - .transact() - ).unwrap().is_success() - } - - fn get_subaccount(account: &Account, new_account_name: &str) -> Account { - let rt = Runtime::new().unwrap(); - - rt.block_on(account.create_subaccount(new_account_name) - .initial_balance(ONE_NEAR) - .transact()).unwrap().unwrap() - } - - macro_rules! view { - ($contract:ident, $method_name:literal) => { - serde_json::from_slice(&view(&$contract, $method_name)).unwrap() - } - } - #[test] fn base_scenario() { - let (mut contract_holder, contract) = get_contract(); + let (mut contract_holder, contract) = get_contract_testnet(WASM_FILEPATH); assert!(call(&contract,"new")); @@ -150,7 +71,7 @@ mod tests { #[test] #[should_panic(expected = "AccessKeyNotFound")] fn base_panic_on_wrong_key() { - let (mut contract_holder, contract) = get_contract(); + let (mut contract_holder, contract) = get_contract_testnet(WASM_FILEPATH); assert!(call(&contract,"new")); let next_owner = get_subaccount(&contract_holder, "next_owner"); diff --git a/examples/near-plugins-test-utils/Cargo.toml b/examples/near-plugins-test-utils/Cargo.toml new file mode 100644 index 0000000..5baf7ac --- /dev/null +++ b/examples/near-plugins-test-utils/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "near-plugins-test-utils" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +near-sdk = "4.0.0" +borsh = "0.9.3" +near-primitives = "0.14.0" +workspaces = "0.6" +tokio = { version = "1.1", features = ["rt", "macros"] } +serde_json = "1.0.74" \ No newline at end of file diff --git a/examples/near-plugins-test-utils/src/lib.rs b/examples/near-plugins-test-utils/src/lib.rs new file mode 100644 index 0000000..a14ac8c --- /dev/null +++ b/examples/near-plugins-test-utils/src/lib.rs @@ -0,0 +1,114 @@ +use near_sdk::ONE_NEAR; +use serde_json::json; +use tokio::runtime::Runtime; +use workspaces::{Account, Contract}; + +pub fn get_contract(wasm_path: &str) -> (Account, Contract) { + let rt = Runtime::new().unwrap(); + let worker = rt.block_on(workspaces::sandbox()).unwrap(); + + let owner = worker.root_account().unwrap(); + + let wasm = std::fs::read(wasm_path).unwrap(); + let contract = rt.block_on(owner.deploy(&wasm)).unwrap().unwrap(); + + (owner, contract) +} + +pub fn view(contract: &Contract, method_name: &str) -> Vec { + let rt = Runtime::new().unwrap(); + + rt.block_on(contract.view(method_name, json!({}).to_string().into_bytes())) + .unwrap() + .result +} + +pub fn view_args(contract: &Contract, method_name: &str, args: &serde_json::Value) -> Vec { + let rt = Runtime::new().unwrap(); + + rt.block_on( + contract.view(method_name, + args.to_string().into_bytes()) + ).unwrap().result +} + +pub fn call(contract: &Contract, method_name: &str) -> bool { + let rt = Runtime::new().unwrap(); + + rt.block_on(contract.call(method_name).max_gas().transact()) + .unwrap() + .is_success() +} + +pub fn call_arg(contract: &Contract, method_name: &str, args: &serde_json::Value) -> bool { + let rt = Runtime::new().unwrap(); + + rt.block_on( + contract + .call(method_name) + .args_json(args) + .max_gas() + .transact(), + ) + .unwrap() + .is_success() +} + +pub fn call_by(account: &Account, contract: &Contract, method_name: &str) -> bool { + let rt = Runtime::new().unwrap(); + + rt.block_on( + account + .call(contract.id(), method_name) + .max_gas() + .transact(), + ) + .unwrap() + .is_success() +} + +pub fn call_by_with_arg(account: &Account, contract: &Contract, method_name: &str, args: &serde_json::Value) -> bool { + let rt = Runtime::new().unwrap(); + + rt.block_on( + account.call(contract.id(), method_name) + .args_json(args) + .max_gas() + .transact() + ).unwrap().is_success() +} + +pub fn get_subaccount(account: &Account, new_account_name: &str) -> Account { + let rt = Runtime::new().unwrap(); + + rt.block_on( + account + .create_subaccount(new_account_name) + .initial_balance(ONE_NEAR) + .transact(), + ) + .unwrap() + .unwrap() +} + +pub fn get_contract_testnet(wasm_file: &str) -> (Account, Contract) { + let rt = Runtime::new().unwrap(); + let worker = rt.block_on(workspaces::testnet()).unwrap(); + + let wasm = std::fs::read(wasm_file).unwrap(); + let contract: Contract = rt.block_on(worker.dev_deploy(&wasm)).unwrap(); + + let owner = contract.as_account(); + + (owner.clone(), contract) +} + +#[macro_export] +macro_rules! view { + ($contract:ident, $method_name:literal) => { + serde_json::from_slice(&view(&$contract, $method_name)).unwrap() + }; + ($contract:ident, $method_name:literal, $args:expr) => { + serde_json::from_slice(&view_args(&$contract, $method_name, $args)).unwrap() + }; +} diff --git a/examples/ownable_base/Cargo.toml b/examples/ownable_base/Cargo.toml index 4bae40a..93735a1 100644 --- a/examples/ownable_base/Cargo.toml +++ b/examples/ownable_base/Cargo.toml @@ -19,5 +19,6 @@ near-primitives = "0.14.0" workspaces = "0.6" tokio = { version = "1.1", features = ["rt", "macros"] } serde_json = "1.0.74" +near-plugins-test-utils = { path = "../near-plugins-test-utils" } diff --git a/examples/ownable_base/src/lib.rs b/examples/ownable_base/src/lib.rs index c9b07f7..0b884d8 100644 --- a/examples/ownable_base/src/lib.rs +++ b/examples/ownable_base/src/lib.rs @@ -50,83 +50,15 @@ impl Counter { #[cfg(test)] mod tests { - use workspaces::{Account, Contract}; - use tokio::runtime::Runtime; - use serde_json::{json, Value}; - use near_sdk::{AccountId, ONE_NEAR}; - use workspaces::result::{ExecutionResult, ExecutionSuccess, ValueOrReceiptId}; + use serde_json::json; + use near_sdk::AccountId; + use near_plugins_test_utils::*; const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/ownable_base.wasm"; - fn get_contract() -> (Account, Contract) { - let rt = Runtime::new().unwrap(); - let worker = rt.block_on(workspaces::sandbox()).unwrap(); - - let owner = worker.root_account().unwrap(); - - let wasm = std::fs::read(WASM_FILEPATH).unwrap(); - let contract = rt.block_on(owner.deploy(&wasm)).unwrap().unwrap(); - - (owner, contract) - } - - fn view(contract: &Contract, method_name: &str) -> Vec { - let rt = Runtime::new().unwrap(); - - rt.block_on( - contract.view(method_name, - json!({}).to_string().into_bytes()) - ).unwrap().result - } - - fn call(contract: &Contract, method_name: &str) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on( - contract.call(method_name) - .max_gas() - .transact() - ).unwrap().is_success() - } - - fn call_arg(contract: &Contract, method_name: &str, args: &serde_json::Value) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on( - contract.call(method_name) - .args_json(args) - .max_gas() - .transact() - ).unwrap().is_success() - } - - fn call_by(account: &Account, contract: &Contract, method_name: &str) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on( - account.call(contract.id(),method_name) - .max_gas() - .transact() - ).unwrap().is_success() - } - - fn get_subaccount(account: &Account, new_account_name: &str) -> Account { - let rt = Runtime::new().unwrap(); - - rt.block_on(account.create_subaccount(new_account_name) - .initial_balance(ONE_NEAR) - .transact()).unwrap().unwrap() - } - - macro_rules! view { - ($contract:ident, $method_name:literal) => { - serde_json::from_slice(&view(&$contract, $method_name)).unwrap() - } - } - #[test] fn base_scenario() { - let (contract_holder, contract) = get_contract(); + let (contract_holder, contract) = get_contract(WASM_FILEPATH); assert!(call(&contract,"new")); @@ -178,9 +110,7 @@ mod tests { #[test] fn null_owner() { - let (contract_holder, contract) = get_contract(); - let rt = Runtime::new().unwrap(); - + let (_, contract) = get_contract(WASM_FILEPATH); assert!(call(&contract,"new")); assert!(call_arg(&contract, "owner_set", &json!({"owner": Option::::None}))); @@ -208,9 +138,7 @@ mod tests { #[test] fn check_owner_storage_key() { - let (contract_holder, contract) = get_contract(); - let rt = Runtime::new().unwrap(); - + let (_, contract) = get_contract(WASM_FILEPATH); assert!(call(&contract,"new")); let owner_storage_key: Vec = view!(contract, "owner_storage_key"); diff --git a/examples/ownable_change_storage_key/Cargo.toml b/examples/ownable_change_storage_key/Cargo.toml index 2860fce..a444172 100644 --- a/examples/ownable_change_storage_key/Cargo.toml +++ b/examples/ownable_change_storage_key/Cargo.toml @@ -19,5 +19,5 @@ near-primitives = "0.14.0" workspaces = "0.6" tokio = { version = "1.1", features = ["rt", "macros"] } serde_json = "1.0.74" - +near-plugins-test-utils = { path = "../near-plugins-test-utils" } diff --git a/examples/ownable_change_storage_key/src/lib.rs b/examples/ownable_change_storage_key/src/lib.rs index 8360ce2..1089e98 100644 --- a/examples/ownable_change_storage_key/src/lib.rs +++ b/examples/ownable_change_storage_key/src/lib.rs @@ -51,56 +51,13 @@ impl Counter { #[cfg(test)] mod tests { - use workspaces::{Account, Contract}; - use tokio::runtime::Runtime; - use serde_json::{json, Value}; - use near_sdk::{AccountId, ONE_NEAR}; - use workspaces::result::{ExecutionResult, ExecutionSuccess, ValueOrReceiptId}; + use near_plugins_test_utils::*; const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/ownable_change_storage_key.wasm"; - fn get_contract() -> (Account, Contract) { - let rt = Runtime::new().unwrap(); - let worker = rt.block_on(workspaces::sandbox()).unwrap(); - - let owner = worker.root_account().unwrap(); - - let wasm = std::fs::read(WASM_FILEPATH).unwrap(); - let contract = rt.block_on(owner.deploy(&wasm)).unwrap().unwrap(); - - (owner, contract) - } - - fn view(contract: &Contract, method_name: &str) -> Vec { - let rt = Runtime::new().unwrap(); - - rt.block_on( - contract.view(method_name, - json!({}).to_string().into_bytes()) - ).unwrap().result - } - - fn call(contract: &Contract, method_name: &str) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on( - contract.call(method_name) - .max_gas() - .transact() - ).unwrap().is_success() - } - - macro_rules! view { - ($contract:ident, $method_name:literal) => { - serde_json::from_slice(&view(&$contract, $method_name)).unwrap() - } - } - #[test] fn check_owner_storage_key() { - let (contract_holder, contract) = get_contract(); - let rt = Runtime::new().unwrap(); - + let (_, contract) = get_contract(WASM_FILEPATH); assert!(call(&contract,"new")); let owner_storage_key: Vec = view!(contract, "owner_storage_key"); diff --git a/examples/ownable_cross_call/Cargo.toml b/examples/ownable_cross_call/Cargo.toml index 411d7fc..e7a99a7 100644 --- a/examples/ownable_cross_call/Cargo.toml +++ b/examples/ownable_cross_call/Cargo.toml @@ -19,5 +19,5 @@ near-primitives = "0.14.0" workspaces = "0.6" tokio = { version = "1.1", features = ["rt", "macros"] } serde_json = "1.0.74" - +near-plugins-test-utils = { path = "../near-plugins-test-utils" } diff --git a/examples/ownable_cross_call/src/lib.rs b/examples/ownable_cross_call/src/lib.rs index 6cd0f3c..1ebeac6 100644 --- a/examples/ownable_cross_call/src/lib.rs +++ b/examples/ownable_cross_call/src/lib.rs @@ -77,83 +77,15 @@ impl Counter { #[cfg(test)] mod tests { - use workspaces::{Account, Contract}; - use tokio::runtime::Runtime; - use serde_json::{json, Value}; - use near_sdk::{AccountId, ONE_NEAR}; - use workspaces::result::{ExecutionResult, ExecutionSuccess, ValueOrReceiptId}; + use serde_json::json; + use near_sdk::AccountId; + use near_plugins_test_utils::*; const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/ownable_cross_call.wasm"; - fn get_contract() -> (Account, Contract) { - let rt = Runtime::new().unwrap(); - let worker = rt.block_on(workspaces::sandbox()).unwrap(); - - let owner = worker.root_account().unwrap(); - - let wasm = std::fs::read(WASM_FILEPATH).unwrap(); - let contract = rt.block_on(owner.deploy(&wasm)).unwrap().unwrap(); - - (owner, contract) - } - - fn view(contract: &Contract, method_name: &str) -> Vec { - let rt = Runtime::new().unwrap(); - - rt.block_on( - contract.view(method_name, - json!({}).to_string().into_bytes()) - ).unwrap().result - } - - fn call(contract: &Contract, method_name: &str) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on( - contract.call(method_name) - .max_gas() - .transact() - ).unwrap().is_success() - } - - fn call_arg(contract: &Contract, method_name: &str, args: &serde_json::Value) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on( - contract.call(method_name) - .args_json(args) - .max_gas() - .transact() - ).unwrap().is_success() - } - - fn call_by(account: &Account, contract: &Contract, method_name: &str) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on( - account.call(contract.id(),method_name) - .max_gas() - .transact() - ).unwrap().is_success() - } - - fn get_subaccount(account: &Account, new_account_name: &str) -> Account { - let rt = Runtime::new().unwrap(); - - rt.block_on(account.create_subaccount(new_account_name) - .initial_balance(ONE_NEAR) - .transact()).unwrap().unwrap() - } - - macro_rules! view { - ($contract:ident, $method_name:literal) => { - serde_json::from_slice(&view(&$contract, $method_name)).unwrap() - } - } - #[test] fn base_scenario() { - let (contract_holder, contract) = get_contract(); + let (contract_holder, contract) = get_contract(WASM_FILEPATH); assert!(call(&contract,"new")); let next_owner = get_subaccount(&contract_holder, "next_owner"); diff --git a/examples/pausable_base/Cargo.toml b/examples/pausable_base/Cargo.toml index 0c67a81..62641f3 100644 --- a/examples/pausable_base/Cargo.toml +++ b/examples/pausable_base/Cargo.toml @@ -19,5 +19,6 @@ near-primitives = "0.14.0" workspaces = "0.6" tokio = { version = "1.1", features = ["rt", "macros"] } serde_json = "1.0.74" +near-plugins-test-utils = { path = "../near-plugins-test-utils" } diff --git a/examples/pausable_base/src/lib.rs b/examples/pausable_base/src/lib.rs index 829ec4d..65099a5 100644 --- a/examples/pausable_base/src/lib.rs +++ b/examples/pausable_base/src/lib.rs @@ -1,7 +1,6 @@ use near_plugins::Ownable; use near_plugins::Pausable; use near_sdk::near_bindgen; -use near_plugins_derive::only; use near_plugins_derive::{pause, if_paused}; use borsh::{BorshSerialize, BorshDeserialize}; @@ -71,94 +70,15 @@ impl Counter { #[cfg(test)] mod tests { - use workspaces::{Account, Contract}; - use tokio::runtime::Runtime; - use serde_json::{json, Value}; - use near_sdk::{AccountId, ONE_NEAR}; - use workspaces::result::{ExecutionResult, ExecutionSuccess, ValueOrReceiptId}; + use serde_json::json; + use near_sdk::AccountId; + use near_plugins_test_utils::*; const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/pausable_base.wasm"; - fn get_contract() -> (Account, Contract) { - let rt = Runtime::new().unwrap(); - let worker = rt.block_on(workspaces::sandbox()).unwrap(); - - let owner = worker.root_account().unwrap(); - - let wasm = std::fs::read(WASM_FILEPATH).unwrap(); - let contract = rt.block_on(owner.deploy(&wasm)).unwrap().unwrap(); - - (owner, contract) - } - - fn view(contract: &Contract, method_name: &str) -> Vec { - let rt = Runtime::new().unwrap(); - - rt.block_on( - contract.view(method_name, - json!({}).to_string().into_bytes()) - ).unwrap().result - } - - fn call(contract: &Contract, method_name: &str) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on( - contract.call(method_name) - .max_gas() - .transact() - ).unwrap().is_success() - } - - fn call_arg(contract: &Contract, method_name: &str, args: &serde_json::Value) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on( - contract.call(method_name) - .args_json(args) - .max_gas() - .transact() - ).unwrap().is_success() - } - - fn call_by(account: &Account, contract: &Contract, method_name: &str) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on( - account.call(contract.id(),method_name) - .max_gas() - .transact() - ).unwrap().is_success() - } - - fn call_by_with_arg(account: &Account, contract: &Contract, method_name: &str, args: &serde_json::Value) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on( - account.call(contract.id(), method_name) - .args_json(args) - .max_gas() - .transact() - ).unwrap().is_success() - } - - fn get_subaccount(account: &Account, new_account_name: &str) -> Account { - let rt = Runtime::new().unwrap(); - - rt.block_on(account.create_subaccount(new_account_name) - .initial_balance(ONE_NEAR) - .transact()).unwrap().unwrap() - } - - macro_rules! view { - ($contract:ident, $method_name:literal) => { - serde_json::from_slice(&view(&$contract, $method_name)).unwrap() - } - } - #[test] fn base_scenario() { - let (contract_holder, contract) = get_contract(); + let (contract_holder, contract) = get_contract(WASM_FILEPATH); assert!(call(&contract,"new")); diff --git a/examples/upgradable_base/Cargo.toml b/examples/upgradable_base/Cargo.toml index f780046..da4880f 100644 --- a/examples/upgradable_base/Cargo.toml +++ b/examples/upgradable_base/Cargo.toml @@ -19,5 +19,5 @@ near-primitives = { version = "0.14.0" } workspaces = "0.6" tokio = { version = "1.1", features = ["rt", "macros"] } serde_json = "1.0.74" - +near-plugins-test-utils = { path = "../near-plugins-test-utils" } diff --git a/examples/upgradable_base/src/lib.rs b/examples/upgradable_base/src/lib.rs index d6bf423..694663c 100644 --- a/examples/upgradable_base/src/lib.rs +++ b/examples/upgradable_base/src/lib.rs @@ -32,9 +32,7 @@ impl Counter1 { mod tests { use workspaces::{Account, Contract}; use tokio::runtime::Runtime; - use serde_json::{json, Value}; - use near_sdk::{AccountId, ONE_NEAR}; - use workspaces::result::{ExecutionResult, ExecutionSuccess, ValueOrReceiptId}; + use near_plugins_test_utils::*; const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/upgradable_base.wasm"; const WASM_FILEPATH_SECOND: &str = "../upgradable_base_second/target/wasm32-unknown-unknown/release/upgradable_base_second.wasm"; @@ -51,26 +49,7 @@ mod tests { (owner, contract) } - fn view(contract: &Contract, method_name: &str) -> Vec { - let rt = Runtime::new().unwrap(); - - rt.block_on( - contract.view(method_name, - json!({}).to_string().into_bytes()) - ).unwrap().result - } - - fn call(contract: &Contract, method_name: &str) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on( - contract.call(method_name) - .max_gas() - .transact() - ).unwrap().is_success() - } - - fn call_arg(contract: &Contract, method_name: &str, args: Vec) -> bool { + fn call_borsh_arg(contract: &Contract, method_name: &str, args: Vec) -> bool { let rt = Runtime::new().unwrap(); rt.block_on( @@ -81,16 +60,10 @@ mod tests { ).unwrap().is_success() } - macro_rules! view { - ($contract:ident, $method_name:literal) => { - serde_json::from_slice(&view(&$contract, $method_name)).unwrap() - } - } - //https://docs.near.org/sdk/rust/promises/deploy-contract #[test] fn base_scenario() { - let (contract_holder, contract) = get_contract(); + let (_, contract) = get_contract(); assert!(call(&contract,"new")); assert!(call(&contract, "inc1")); @@ -104,7 +77,7 @@ mod tests { let wasm = std::fs::read(WASM_FILEPATH_SECOND).unwrap(); - assert!(call_arg(&contract, "up_stage_code", wasm)); + assert!(call_borsh_arg(&contract, "up_stage_code", wasm)); assert!(call(&contract, "up_deploy_code")); let counter: u64 = view!(contract, "get_counter"); From 911fd5c707324a7dec4b94f9448dfe07d633260b Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Tue, 18 Oct 2022 11:07:50 +0300 Subject: [PATCH 16/68] remove view function duplication --- examples/near-plugins-test-utils/src/lib.rs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/examples/near-plugins-test-utils/src/lib.rs b/examples/near-plugins-test-utils/src/lib.rs index a14ac8c..044a8c5 100644 --- a/examples/near-plugins-test-utils/src/lib.rs +++ b/examples/near-plugins-test-utils/src/lib.rs @@ -1,5 +1,4 @@ use near_sdk::ONE_NEAR; -use serde_json::json; use tokio::runtime::Runtime; use workspaces::{Account, Contract}; @@ -15,15 +14,7 @@ pub fn get_contract(wasm_path: &str) -> (Account, Contract) { (owner, contract) } -pub fn view(contract: &Contract, method_name: &str) -> Vec { - let rt = Runtime::new().unwrap(); - - rt.block_on(contract.view(method_name, json!({}).to_string().into_bytes())) - .unwrap() - .result -} - -pub fn view_args(contract: &Contract, method_name: &str, args: &serde_json::Value) -> Vec { +pub fn view(contract: &Contract, method_name: &str, args: &serde_json::Value) -> Vec { let rt = Runtime::new().unwrap(); rt.block_on( @@ -106,9 +97,9 @@ pub fn get_contract_testnet(wasm_file: &str) -> (Account, Contract) { #[macro_export] macro_rules! view { ($contract:ident, $method_name:literal) => { - serde_json::from_slice(&view(&$contract, $method_name)).unwrap() + serde_json::from_slice(&view(&$contract, $method_name, &json!({}))).unwrap() }; ($contract:ident, $method_name:literal, $args:expr) => { - serde_json::from_slice(&view_args(&$contract, $method_name, $args)).unwrap() + serde_json::from_slice(&view(&$contract, $method_name, $args)).unwrap() }; } From 6ee28cb8fba2dd2b6c898cdb7cc90a0ee544880b Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Tue, 18 Oct 2022 12:51:04 +0300 Subject: [PATCH 17/68] mecros for call --- examples/access_controllable_base/src/lib.rs | 24 ++++---- .../full_access_key_fallback_base/src/lib.rs | 18 +++--- examples/near-plugins-test-utils/src/lib.rs | 37 +++++------- examples/ownable_base/src/lib.rs | 58 +++++++++---------- .../ownable_change_storage_key/src/lib.rs | 3 +- examples/ownable_cross_call/src/lib.rs | 20 +++---- examples/pausable_base/src/lib.rs | 20 +++---- examples/upgradable_base/src/lib.rs | 13 +++-- 8 files changed, 95 insertions(+), 98 deletions(-) diff --git a/examples/access_controllable_base/src/lib.rs b/examples/access_controllable_base/src/lib.rs index 69341ea..e05b3f0 100644 --- a/examples/access_controllable_base/src/lib.rs +++ b/examples/access_controllable_base/src/lib.rs @@ -66,12 +66,12 @@ mod tests { #[test] fn base_scenario() { let (contract_holder, contract) = get_contract(WASM_FILEPATH); - assert!(call(&contract,"new")); + assert!(call!(contract,"new")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 0); - assert!(call(&contract, "unprotected")); + assert!(call!(contract, "unprotected")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 1); @@ -81,46 +81,46 @@ mod tests { let is_super_admin: bool = view!(contract, "acl_is_super_admin", &json!({"account_id": alice.id()})); assert!(!is_super_admin); - assert!(!call_by(&alice, &contract, "level_a_incr")); + assert!(!call!(&alice, contract, "level_a_incr")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 1); - assert!(call_arg(&contract, "acl_grant_role", &json!({"role": String::from(Positions::LevelA), "account_id": alice.id()}))); + assert!(call!(contract, "acl_grant_role", &json!({"role": String::from(Positions::LevelA), "account_id": alice.id()}))); let alice_has_role: bool = view!(contract, "acl_has_role", &json!({"role": String::from(Positions::LevelA), "account_id": alice.id()})); assert!(alice_has_role); - assert!(call_by(&alice, &contract, "level_a_incr")); + assert!(call!(&alice, contract, "level_a_incr")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 2); let bob = get_subaccount(&contract_holder, "bob"); - assert!(call_arg(&contract, "acl_add_admin", &json!({"role": String::from(Positions::LevelA), "account_id": bob.id()}))); + assert!(call!(contract, "acl_add_admin", &json!({"role": String::from(Positions::LevelA), "account_id": bob.id()}))); let bob_is_admin: bool = view!(contract, "acl_is_admin", &json!({"role": String::from(Positions::LevelA), "account_id": bob.id()})); assert!(bob_is_admin); - assert!(!call_by(&bob, &contract, "level_a_incr")); + assert!(!call!(&bob, contract, "level_a_incr")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 2); - assert!(call_by(&alice, &contract, "level_ab_incr")); + assert!(call!(&alice, contract, "level_ab_incr")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 3); - assert!(!call_by(&bob, &contract, "level_ab_incr")); + assert!(!call!(&bob, contract, "level_ab_incr")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 3); - assert!(call_arg(&contract, "acl_grant_role", &json!({"role": String::from(Positions::LevelB), "account_id": bob.id()}))); - assert!(call_by(&bob, &contract, "level_ab_incr")); + assert!(call!(contract, "acl_grant_role", &json!({"role": String::from(Positions::LevelB), "account_id": bob.id()}))); + assert!(call!(&bob, contract, "level_ab_incr")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 4); - assert!(!call_by(&bob, &contract, "level_a_incr")); + assert!(!call!(&bob, contract, "level_a_incr")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 4); } diff --git a/examples/full_access_key_fallback_base/src/lib.rs b/examples/full_access_key_fallback_base/src/lib.rs index a0bc32a..a5da48a 100644 --- a/examples/full_access_key_fallback_base/src/lib.rs +++ b/examples/full_access_key_fallback_base/src/lib.rs @@ -43,26 +43,26 @@ mod tests { fn base_scenario() { let (mut contract_holder, contract) = get_contract_testnet(WASM_FILEPATH); - assert!(call(&contract,"new")); + assert!(call!(contract,"new")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 0); let next_owner = get_subaccount(&contract_holder, "next_owner"); - assert!(call_arg(&contract, "owner_set", &json!({"owner": next_owner.id()}))); + assert!(call!(contract, "owner_set", &json!({"owner": next_owner.id()}))); let current_owner: Option:: = view!(contract, "owner_get"); assert_eq!(current_owner.unwrap().as_str(), next_owner.id().as_str()); - assert!(call_by(&contract_holder, &contract, "protected_self")); + assert!(call!(&contract_holder, contract, "protected_self")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 1); contract_holder.set_secret_key(next_owner.secret_key().clone()); - assert!(call_by_with_arg(&next_owner, &contract, "attach_full_access_key", &json!({"public_key": next_owner.secret_key().public_key()}))); + assert!(call!(&next_owner, contract, "attach_full_access_key", &json!({"public_key": next_owner.secret_key().public_key()}))); - assert!(call(&contract, "protected_self")); + assert!(call!(contract, "protected_self")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 2); @@ -73,13 +73,13 @@ mod tests { fn base_panic_on_wrong_key() { let (mut contract_holder, contract) = get_contract_testnet(WASM_FILEPATH); - assert!(call(&contract,"new")); + assert!(call!(contract, "new")); let next_owner = get_subaccount(&contract_holder, "next_owner"); - assert!(call_arg(&contract, "owner_set", &json!({"owner": next_owner.id()}))); + assert!(call!(contract, "owner_set", &json!({"owner": next_owner.id()}))); - assert!(call_by(&contract_holder, &contract, "protected_self")); + assert!(call!(&contract_holder, contract, "protected_self")); contract_holder.set_secret_key(next_owner.secret_key().clone()); - call_by(&contract_holder, &contract, "protected_self"); + call!(&contract_holder, contract, "protected_self"); } } diff --git a/examples/near-plugins-test-utils/src/lib.rs b/examples/near-plugins-test-utils/src/lib.rs index 044a8c5..4039f2e 100644 --- a/examples/near-plugins-test-utils/src/lib.rs +++ b/examples/near-plugins-test-utils/src/lib.rs @@ -23,14 +23,6 @@ pub fn view(contract: &Contract, method_name: &str, args: &serde_json::Value) -> ).unwrap().result } -pub fn call(contract: &Contract, method_name: &str) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on(contract.call(method_name).max_gas().transact()) - .unwrap() - .is_success() -} - pub fn call_arg(contract: &Contract, method_name: &str, args: &serde_json::Value) -> bool { let rt = Runtime::new().unwrap(); @@ -45,19 +37,6 @@ pub fn call_arg(contract: &Contract, method_name: &str, args: &serde_json::Value .is_success() } -pub fn call_by(account: &Account, contract: &Contract, method_name: &str) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on( - account - .call(contract.id(), method_name) - .max_gas() - .transact(), - ) - .unwrap() - .is_success() -} - pub fn call_by_with_arg(account: &Account, contract: &Contract, method_name: &str, args: &serde_json::Value) -> bool { let rt = Runtime::new().unwrap(); @@ -103,3 +82,19 @@ macro_rules! view { serde_json::from_slice(&view(&$contract, $method_name, $args)).unwrap() }; } + +#[macro_export] +macro_rules! call { + ($contract:ident, $method_name:literal) => { + call_arg(&$contract, $method_name, &json!({})) + }; + ($contract:ident, $method_name:literal, $args:expr) => { + call_arg(&$contract, $method_name, $args) + }; + ($account:expr, $contract:ident, $method_name:literal) => { + call_by_with_arg($account, &$contract, $method_name, &json!({})) + }; + ($account:expr, $contract:ident, $method_name:literal, $args:expr) => { + call_by_with_arg($account, &$contract, $method_name, $args) + }; +} diff --git a/examples/ownable_base/src/lib.rs b/examples/ownable_base/src/lib.rs index 0b884d8..0a7b720 100644 --- a/examples/ownable_base/src/lib.rs +++ b/examples/ownable_base/src/lib.rs @@ -60,7 +60,7 @@ mod tests { fn base_scenario() { let (contract_holder, contract) = get_contract(WASM_FILEPATH); - assert!(call(&contract,"new")); + assert!(call!(contract, "new")); let current_owner: Option:: = view!(contract, "owner_get"); assert_eq!(current_owner.unwrap().as_str(), contract_holder.id().as_str()); @@ -68,19 +68,19 @@ mod tests { let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 0); - assert!(call(&contract, "protected")); - assert!(call(&contract, "protected_owner")); - assert!(call(&contract, "protected_self")); - assert!(call(&contract, "unprotected")); + assert!(call!(contract, "protected")); + assert!(call!(contract, "protected_owner")); + assert!(call!(contract, "protected_self")); + assert!(call!(contract, "unprotected")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 4); let next_owner = get_subaccount(&contract_holder, "next_owner"); - assert!(!call_by(&next_owner, &contract, "protected")); - assert!(!call_by(&next_owner, &contract, "protected_owner")); - assert!(!call_by(&next_owner, &contract, "protected_self")); - assert!(call_by(&next_owner, &contract, "unprotected")); + assert!(!call!(&next_owner, contract, "protected")); + assert!(!call!(&next_owner, contract, "protected_owner")); + assert!(!call!(&next_owner, contract, "protected_self")); + assert!(call!(&next_owner, contract, "unprotected")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 5); @@ -91,18 +91,18 @@ mod tests { assert_ne!(current_owner.clone().unwrap().as_str(), contract_holder.id().as_str()); assert_eq!(current_owner.unwrap().as_str(), next_owner.id().as_str()); - assert!(call_by(&next_owner, &contract, "protected")); - assert!(call_by(&next_owner, &contract, "protected_owner")); - assert!(!call_by(&next_owner, &contract, "protected_self")); - assert!(call_by(&next_owner, &contract, "unprotected")); + assert!(call!(&next_owner, contract, "protected")); + assert!(call!(&next_owner, contract, "protected_owner")); + assert!(!call!(&next_owner, contract, "protected_self")); + assert!(call!(&next_owner, contract, "unprotected")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 8); - assert!(call(&contract, "protected")); - assert!(!call(&contract, "protected_owner")); - assert!(call(&contract, "protected_self")); - assert!(call(&contract, "unprotected")); + assert!(call!(contract, "protected")); + assert!(!call!(contract, "protected_owner")); + assert!(call!(contract, "protected_self")); + assert!(call!(contract, "unprotected")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 11); @@ -111,26 +111,26 @@ mod tests { #[test] fn null_owner() { let (_, contract) = get_contract(WASM_FILEPATH); - assert!(call(&contract,"new")); + assert!(call!(contract,"new")); - assert!(call_arg(&contract, "owner_set", &json!({"owner": Option::::None}))); + assert!(call!(contract, "owner_set", &json!({"owner": Option::::None}))); let current_owner: Option:: = view!(contract, "owner_get"); assert_eq!(current_owner, None); - assert!(call(&contract, "protected")); - assert!(!call(&contract, "protected_owner")); - assert!(call(&contract, "protected_self")); - assert!(call(&contract, "unprotected")); + assert!(call!(contract, "protected")); + assert!(!call!(contract, "protected_owner")); + assert!(call!(contract, "protected_self")); + assert!(call!(contract, "unprotected")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 3); - assert!(call_arg(&contract, "owner_set", &json!({"owner": contract.id().as_str()}))); - assert!(call(&contract, "protected")); - assert!(call(&contract, "protected_owner")); - assert!(call(&contract, "protected_self")); - assert!(call(&contract, "unprotected")); + assert!(call!(contract, "owner_set", &json!({"owner": contract.id().as_str()}))); + assert!(call!(contract, "protected")); + assert!(call!(contract, "protected_owner")); + assert!(call!(contract, "protected_self")); + assert!(call!(contract, "unprotected")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 7); @@ -139,7 +139,7 @@ mod tests { #[test] fn check_owner_storage_key() { let (_, contract) = get_contract(WASM_FILEPATH); - assert!(call(&contract,"new")); + assert!(call!(contract,"new")); let owner_storage_key: Vec = view!(contract, "owner_storage_key"); assert_eq!(owner_storage_key, "__OWNER__".as_bytes().to_vec()); diff --git a/examples/ownable_change_storage_key/src/lib.rs b/examples/ownable_change_storage_key/src/lib.rs index 1089e98..414d940 100644 --- a/examples/ownable_change_storage_key/src/lib.rs +++ b/examples/ownable_change_storage_key/src/lib.rs @@ -51,6 +51,7 @@ impl Counter { #[cfg(test)] mod tests { + use serde_json::json; use near_plugins_test_utils::*; const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/ownable_change_storage_key.wasm"; @@ -58,7 +59,7 @@ mod tests { #[test] fn check_owner_storage_key() { let (_, contract) = get_contract(WASM_FILEPATH); - assert!(call(&contract,"new")); + assert!(call!(contract,"new")); let owner_storage_key: Vec = view!(contract, "owner_storage_key"); assert_eq!(owner_storage_key, "new_storage_key".as_bytes().to_vec()); diff --git a/examples/ownable_cross_call/src/lib.rs b/examples/ownable_cross_call/src/lib.rs index 1ebeac6..fc78e77 100644 --- a/examples/ownable_cross_call/src/lib.rs +++ b/examples/ownable_cross_call/src/lib.rs @@ -87,25 +87,25 @@ mod tests { fn base_scenario() { let (contract_holder, contract) = get_contract(WASM_FILEPATH); - assert!(call(&contract,"new")); + assert!(call!(contract,"new")); let next_owner = get_subaccount(&contract_holder, "next_owner"); - assert!(call_arg(&contract, "owner_set", &json!({"owner": next_owner.id()}))); + assert!(call!(contract, "owner_set", &json!({"owner": next_owner.id()}))); let current_owner: Option:: = view!(contract, "owner_get"); assert_ne!(current_owner.clone().unwrap().as_str(), contract_holder.id().as_str()); assert_eq!(current_owner.unwrap().as_str(), next_owner.id().as_str()); - assert!(call_by(&next_owner, &contract, "cross_call_owner_self")); - assert!(call_by(&next_owner, &contract, "cross_call_owner_owner")); - assert!(!call_by(&next_owner, &contract, "cross_call_self_self")); - assert!(!call_by(&next_owner, &contract, "cross_call_self_owner")); + assert!(call!(&next_owner, contract, "cross_call_owner_self")); + assert!(call!(&next_owner, contract, "cross_call_owner_owner")); + assert!(!call!(&next_owner, contract, "cross_call_self_self")); + assert!(!call!(&next_owner, contract, "cross_call_self_owner")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 1); - assert!(!call(&contract, "cross_call_owner_self")); - assert!(!call(&contract, "cross_call_owner_owner")); - assert!(call(&contract, "cross_call_self_self")); - assert!(call(&contract, "cross_call_self_owner")); + assert!(!call!(contract, "cross_call_owner_self")); + assert!(!call!(contract, "cross_call_owner_owner")); + assert!(call!(contract, "cross_call_self_self")); + assert!(call!(contract, "cross_call_self_owner")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 2); diff --git a/examples/pausable_base/src/lib.rs b/examples/pausable_base/src/lib.rs index 65099a5..b443249 100644 --- a/examples/pausable_base/src/lib.rs +++ b/examples/pausable_base/src/lib.rs @@ -80,36 +80,36 @@ mod tests { fn base_scenario() { let (contract_holder, contract) = get_contract(WASM_FILEPATH); - assert!(call(&contract,"new")); + assert!(call!(contract,"new")); let next_owner = get_subaccount(&contract_holder, "next_owner"); - assert!(call_arg(&contract, "owner_set", &json!({"owner": next_owner.id()}))); + assert!(call!(contract, "owner_set", &json!({"owner": next_owner.id()}))); let current_owner: Option:: = view!(contract, "owner_get"); assert_eq!(current_owner.unwrap().as_str(), next_owner.id().as_str()); let alice = get_subaccount(&contract_holder, "alice"); - assert!(call_by(&alice, &contract, "increase_1")); + assert!(call!(&alice, contract, "increase_1")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 1); - assert!(!call_by_with_arg(&alice, &contract, "pa_pause_feature", &json!({"key": "increase_1"}))); - assert!(call_by_with_arg(&next_owner, &contract, "pa_pause_feature", &json!({"key": "increase_1"}))); + assert!(!call!(&alice, contract, "pa_pause_feature", &json!({"key": "increase_1"}))); + assert!(call!(&next_owner, contract, "pa_pause_feature", &json!({"key": "increase_1"}))); - assert!(!call_by(&alice, &contract, "increase_1")); + assert!(!call!(&alice, contract, "increase_1")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 1); - assert!(!call_by(&next_owner, &contract, "increase_1")); + assert!(!call!(&next_owner, contract, "increase_1")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 1); - assert!(!call_by_with_arg(&contract_holder, &contract, "pa_unpause_feature", &json!({"key": "increase_1"}))); - assert!(call_by_with_arg(&next_owner, &contract, "pa_unpause_feature", &json!({"key": "increase_1"}))); + assert!(!call!(&contract_holder, contract, "pa_unpause_feature", &json!({"key": "increase_1"}))); + assert!(call!(&next_owner, contract, "pa_unpause_feature", &json!({"key": "increase_1"}))); - assert!(call_by(&alice, &contract, "increase_1")); + assert!(call!(&alice, contract, "increase_1")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 2); diff --git a/examples/upgradable_base/src/lib.rs b/examples/upgradable_base/src/lib.rs index 694663c..9b4c9cc 100644 --- a/examples/upgradable_base/src/lib.rs +++ b/examples/upgradable_base/src/lib.rs @@ -30,6 +30,7 @@ impl Counter1 { #[cfg(test)] mod tests { + use serde_json::json; use workspaces::{Account, Contract}; use tokio::runtime::Runtime; use near_plugins_test_utils::*; @@ -64,30 +65,30 @@ mod tests { #[test] fn base_scenario() { let (_, contract) = get_contract(); - assert!(call(&contract,"new")); + assert!(call!(contract,"new")); - assert!(call(&contract, "inc1")); + assert!(call!(contract, "inc1")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 1); - assert!(!call(&contract, "inc2")); + assert!(!call!(contract, "inc2")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 1); let wasm = std::fs::read(WASM_FILEPATH_SECOND).unwrap(); assert!(call_borsh_arg(&contract, "up_stage_code", wasm)); - assert!(call(&contract, "up_deploy_code")); + assert!(call!(contract, "up_deploy_code")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 1); - assert!(!call(&contract, "inc1")); + assert!(!call!(contract, "inc1")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 1); - assert!(call(&contract, "inc2")); + assert!(call!(contract, "inc2")); let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, 3); } From 5aa1af7ba7f0dd21ab0d9db9a57772455a9a430b Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Tue, 18 Oct 2022 13:54:18 +0300 Subject: [PATCH 18/68] separate check counter function --- examples/access_controllable_base/src/lib.rs | 28 ++++++------------- .../full_access_key_fallback_base/src/lib.rs | 9 ++---- examples/near-plugins-test-utils/src/lib.rs | 8 +++++- examples/ownable_base/src/lib.rs | 21 +++++--------- examples/ownable_cross_call/src/lib.rs | 6 ++-- examples/pausable_base/src/lib.rs | 14 +++------- examples/upgradable_base/src/lib.rs | 17 ++++------- 7 files changed, 37 insertions(+), 66 deletions(-) diff --git a/examples/access_controllable_base/src/lib.rs b/examples/access_controllable_base/src/lib.rs index e05b3f0..8609d78 100644 --- a/examples/access_controllable_base/src/lib.rs +++ b/examples/access_controllable_base/src/lib.rs @@ -68,13 +68,11 @@ mod tests { let (contract_holder, contract) = get_contract(WASM_FILEPATH); assert!(call!(contract,"new")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 0); + check_counter(&contract, 0); assert!(call!(contract, "unprotected")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 1); + check_counter(&contract, 1); let alice = get_subaccount(&contract_holder, "alice"); @@ -82,8 +80,7 @@ mod tests { assert!(!is_super_admin); assert!(!call!(&alice, contract, "level_a_incr")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 1); + check_counter(&contract, 1); assert!(call!(contract, "acl_grant_role", &json!({"role": String::from(Positions::LevelA), "account_id": alice.id()}))); @@ -92,9 +89,7 @@ mod tests { assert!(call!(&alice, contract, "level_a_incr")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 2); - + check_counter(&contract, 2); let bob = get_subaccount(&contract_holder, "bob"); assert!(call!(contract, "acl_add_admin", &json!({"role": String::from(Positions::LevelA), "account_id": bob.id()}))); @@ -104,24 +99,19 @@ mod tests { assert!(!call!(&bob, contract, "level_a_incr")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 2); + check_counter(&contract, 2); assert!(call!(&alice, contract, "level_ab_incr")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 3); + check_counter(&contract, 3); assert!(!call!(&bob, contract, "level_ab_incr")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 3); + check_counter(&contract, 3); assert!(call!(contract, "acl_grant_role", &json!({"role": String::from(Positions::LevelB), "account_id": bob.id()}))); assert!(call!(&bob, contract, "level_ab_incr")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 4); + check_counter(&contract, 4); assert!(!call!(&bob, contract, "level_a_incr")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 4); + check_counter(&contract, 4); } } diff --git a/examples/full_access_key_fallback_base/src/lib.rs b/examples/full_access_key_fallback_base/src/lib.rs index a5da48a..254c160 100644 --- a/examples/full_access_key_fallback_base/src/lib.rs +++ b/examples/full_access_key_fallback_base/src/lib.rs @@ -45,8 +45,7 @@ mod tests { assert!(call!(contract,"new")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 0); + check_counter(&contract, 0); let next_owner = get_subaccount(&contract_holder, "next_owner"); assert!(call!(contract, "owner_set", &json!({"owner": next_owner.id()}))); @@ -55,8 +54,7 @@ mod tests { assert!(call!(&contract_holder, contract, "protected_self")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 1); + check_counter(&contract, 1); contract_holder.set_secret_key(next_owner.secret_key().clone()); @@ -64,8 +62,7 @@ mod tests { assert!(call!(contract, "protected_self")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 2); + check_counter(&contract, 2); } #[test] diff --git a/examples/near-plugins-test-utils/src/lib.rs b/examples/near-plugins-test-utils/src/lib.rs index 4039f2e..65957d1 100644 --- a/examples/near-plugins-test-utils/src/lib.rs +++ b/examples/near-plugins-test-utils/src/lib.rs @@ -1,3 +1,4 @@ +use serde_json::json; use near_sdk::ONE_NEAR; use tokio::runtime::Runtime; use workspaces::{Account, Contract}; @@ -79,7 +80,7 @@ macro_rules! view { serde_json::from_slice(&view(&$contract, $method_name, &json!({}))).unwrap() }; ($contract:ident, $method_name:literal, $args:expr) => { - serde_json::from_slice(&view(&$contract, $method_name, $args)).unwrap() + serde_json::from_slice(&view(&$contract, $method_name, $args)).unwrap() }; } @@ -98,3 +99,8 @@ macro_rules! call { call_by_with_arg($account, &$contract, $method_name, $args) }; } + +pub fn check_counter(contract: &Contract, expect_counter: u64) { + let counter: u64 = view!(contract, "get_counter"); + assert_eq!(counter, expect_counter); +} \ No newline at end of file diff --git a/examples/ownable_base/src/lib.rs b/examples/ownable_base/src/lib.rs index 0a7b720..1b95a20 100644 --- a/examples/ownable_base/src/lib.rs +++ b/examples/ownable_base/src/lib.rs @@ -65,16 +65,14 @@ mod tests { let current_owner: Option:: = view!(contract, "owner_get"); assert_eq!(current_owner.unwrap().as_str(), contract_holder.id().as_str()); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 0); + check_counter(&contract, 0); assert!(call!(contract, "protected")); assert!(call!(contract, "protected_owner")); assert!(call!(contract, "protected_self")); assert!(call!(contract, "unprotected")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 4); + check_counter(&contract, 4); let next_owner = get_subaccount(&contract_holder, "next_owner"); assert!(!call!(&next_owner, contract, "protected")); @@ -82,8 +80,7 @@ mod tests { assert!(!call!(&next_owner, contract, "protected_self")); assert!(call!(&next_owner, contract, "unprotected")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 5); + check_counter(&contract, 5); assert!(call_arg(&contract, "owner_set", &json!({"owner": next_owner.id()}))); @@ -96,16 +93,14 @@ mod tests { assert!(!call!(&next_owner, contract, "protected_self")); assert!(call!(&next_owner, contract, "unprotected")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 8); + check_counter(&contract, 8); assert!(call!(contract, "protected")); assert!(!call!(contract, "protected_owner")); assert!(call!(contract, "protected_self")); assert!(call!(contract, "unprotected")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 11); + check_counter(&contract, 11); } #[test] @@ -123,8 +118,7 @@ mod tests { assert!(call!(contract, "protected_self")); assert!(call!(contract, "unprotected")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 3); + check_counter(&contract, 3); assert!(call!(contract, "owner_set", &json!({"owner": contract.id().as_str()}))); assert!(call!(contract, "protected")); @@ -132,8 +126,7 @@ mod tests { assert!(call!(contract, "protected_self")); assert!(call!(contract, "unprotected")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 7); + check_counter(&contract, 7); } #[test] diff --git a/examples/ownable_cross_call/src/lib.rs b/examples/ownable_cross_call/src/lib.rs index fc78e77..8ee43c3 100644 --- a/examples/ownable_cross_call/src/lib.rs +++ b/examples/ownable_cross_call/src/lib.rs @@ -99,15 +99,13 @@ mod tests { assert!(!call!(&next_owner, contract, "cross_call_self_self")); assert!(!call!(&next_owner, contract, "cross_call_self_owner")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 1); + check_counter(&contract, 1); assert!(!call!(contract, "cross_call_owner_self")); assert!(!call!(contract, "cross_call_owner_owner")); assert!(call!(contract, "cross_call_self_self")); assert!(call!(contract, "cross_call_self_owner")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 2); + check_counter(&contract, 2); } } diff --git a/examples/pausable_base/src/lib.rs b/examples/pausable_base/src/lib.rs index b443249..4ab7687 100644 --- a/examples/pausable_base/src/lib.rs +++ b/examples/pausable_base/src/lib.rs @@ -90,28 +90,22 @@ mod tests { let alice = get_subaccount(&contract_holder, "alice"); assert!(call!(&alice, contract, "increase_1")); - - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 1); + check_counter(&contract, 1); assert!(!call!(&alice, contract, "pa_pause_feature", &json!({"key": "increase_1"}))); assert!(call!(&next_owner, contract, "pa_pause_feature", &json!({"key": "increase_1"}))); assert!(!call!(&alice, contract, "increase_1")); - - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 1); + check_counter(&contract, 1); assert!(!call!(&next_owner, contract, "increase_1")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 1); + check_counter(&contract, 1); assert!(!call!(&contract_holder, contract, "pa_unpause_feature", &json!({"key": "increase_1"}))); assert!(call!(&next_owner, contract, "pa_unpause_feature", &json!({"key": "increase_1"}))); assert!(call!(&alice, contract, "increase_1")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 2); + check_counter(&contract, 2); } } diff --git a/examples/upgradable_base/src/lib.rs b/examples/upgradable_base/src/lib.rs index 9b4c9cc..dae0ca9 100644 --- a/examples/upgradable_base/src/lib.rs +++ b/examples/upgradable_base/src/lib.rs @@ -68,28 +68,21 @@ mod tests { assert!(call!(contract,"new")); assert!(call!(contract, "inc1")); - - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 1); + check_counter(&contract, 1); assert!(!call!(contract, "inc2")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 1); + check_counter(&contract, 1); let wasm = std::fs::read(WASM_FILEPATH_SECOND).unwrap(); assert!(call_borsh_arg(&contract, "up_stage_code", wasm)); assert!(call!(contract, "up_deploy_code")); - - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 1); + check_counter(&contract, 1); assert!(!call!(contract, "inc1")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 1); + check_counter(&contract, 1); assert!(call!(contract, "inc2")); - let counter: u64 = view!(contract, "get_counter"); - assert_eq!(counter, 3); + check_counter(&contract, 3); } } From 8ce8a8e552ec9247a398d89d652952559bbe3273 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Tue, 18 Oct 2022 15:29:54 +0300 Subject: [PATCH 19/68] README for ownable_base --- examples/ownable_base/README.md | 54 ++++++++++++++++++++++++ examples/ownable_base/src/lib.rs | 71 ++++++++++++++++---------------- 2 files changed, 90 insertions(+), 35 deletions(-) create mode 100644 examples/ownable_base/README.md diff --git a/examples/ownable_base/README.md b/examples/ownable_base/README.md new file mode 100644 index 0000000..d0fabba --- /dev/null +++ b/examples/ownable_base/README.md @@ -0,0 +1,54 @@ +# Example using Ownable plugin + +Basic access control mechanism that allows only an authorized account id to call certain methods. Note this account id can belong either to a regular user, or it could be a contract (a DAO for example). + +```Rust +#[near_bindgen] +#[derive(Ownable, Default, BorshSerialize, BorshDeserialize)] +struct Counter { + counter: u64, +} + +#[near_bindgen] +impl Counter { + /// Specify the owner of the contract in the constructor + #[init] + pub fn new() -> Self { + let mut contract = Self { counter: 0 }; + contract.owner_set(Some(near_sdk::env::predecessor_account_id())); + contract + } + + /// Only owner account, or the contract itself can call this method. + #[only(self, owner)] + pub fn protected(&mut self) { + self.counter += 1; + } + + /// *Only* owner account can call this method. + #[only(owner)] + pub fn protected_owner(&mut self) { + self.counter += 1; + } + + /// *Only* self account can call this method. This can be used even if the contract is not Ownable. + #[only(self)] + pub fn protected_self(&mut self) { + self.counter += 1; + } + + /// Everyone can call this method + pub fn unprotected(&mut self) { + self.counter += 1; + } + + /// View method returns the value of the counter. Everyone can call it + pub fn get_counter(&self) -> u64 { + self.counter + } +} +``` + +## Preparation steps for demonstration + +## Test running instruction diff --git a/examples/ownable_base/src/lib.rs b/examples/ownable_base/src/lib.rs index 1b95a20..d40fd3b 100644 --- a/examples/ownable_base/src/lib.rs +++ b/examples/ownable_base/src/lib.rs @@ -6,45 +6,46 @@ use borsh::{BorshSerialize, BorshDeserialize}; #[near_bindgen] #[derive(Ownable, Default, BorshSerialize, BorshDeserialize)] struct Counter { - counter: u64, + counter: u64, } #[near_bindgen] impl Counter { - /// Specify the owner of the contract in the constructor - #[init] - pub fn new() -> Self { - let mut contract = Self { counter: 0 }; - contract.owner_set(Some(near_sdk::env::predecessor_account_id())); - contract - } - - /// Only owner account, or the contract itself can call this method. - #[only(self, owner)] - pub fn protected(&mut self) { - self.counter += 1; - } - - /// *Only* owner account can call this method. - #[only(owner)] - pub fn protected_owner(&mut self) { - self.counter += 1; - } - - /// *Only* self account can call this method. This can be used even if the contract is not Ownable. - #[only(self)] - pub fn protected_self(&mut self) { - self.counter += 1; - } - - /// Everyone can call this method - pub fn unprotected(&mut self) { - self.counter += 1; - } - - pub fn get_counter(&self) -> u64 { - self.counter - } + /// Specify the owner of the contract in the constructor + #[init] + pub fn new() -> Self { + let mut contract = Self { counter: 0 }; + contract.owner_set(Some(near_sdk::env::predecessor_account_id())); + contract + } + + /// Only owner account, or the contract itself can call this method. + #[only(self, owner)] + pub fn protected(&mut self) { + self.counter += 1; + } + + /// *Only* owner account can call this method. + #[only(owner)] + pub fn protected_owner(&mut self) { + self.counter += 1; + } + + /// *Only* self account can call this method. This can be used even if the contract is not Ownable. + #[only(self)] + pub fn protected_self(&mut self) { + self.counter += 1; + } + + /// Everyone can call this method + pub fn unprotected(&mut self) { + self.counter += 1; + } + + /// View method returns the value of the counter. Everyone can call it + pub fn get_counter(&self) -> u64 { + self.counter + } } From b3d45c1e210bb366ccafd70110d1daed1033c670 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Tue, 18 Oct 2022 16:04:02 +0300 Subject: [PATCH 20/68] update build.sh --- examples/access_controllable_base/build.sh | 2 +- examples/full_access_key_fallback_base/build.sh | 2 +- examples/ownable_base/build.sh | 2 +- examples/ownable_change_storage_key/build.sh | 2 +- examples/ownable_cross_call/build.sh | 2 +- examples/pausable_base/build.sh | 2 +- examples/upgradable_base/build.sh | 2 +- examples/upgradable_base_second/build.sh | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/access_controllable_base/build.sh b/examples/access_controllable_base/build.sh index 651e364..5fb19d6 100755 --- a/examples/access_controllable_base/build.sh +++ b/examples/access_controllable_base/build.sh @@ -1,3 +1,3 @@ #!/usr/bin/env bash -/bin/bash -c "rustup target add wasm32-unknown-unknown; cargo build --target wasm32-unknown-unknown --release" +RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release \ No newline at end of file diff --git a/examples/full_access_key_fallback_base/build.sh b/examples/full_access_key_fallback_base/build.sh index 651e364..5fb19d6 100755 --- a/examples/full_access_key_fallback_base/build.sh +++ b/examples/full_access_key_fallback_base/build.sh @@ -1,3 +1,3 @@ #!/usr/bin/env bash -/bin/bash -c "rustup target add wasm32-unknown-unknown; cargo build --target wasm32-unknown-unknown --release" +RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release \ No newline at end of file diff --git a/examples/ownable_base/build.sh b/examples/ownable_base/build.sh index 651e364..5fb19d6 100755 --- a/examples/ownable_base/build.sh +++ b/examples/ownable_base/build.sh @@ -1,3 +1,3 @@ #!/usr/bin/env bash -/bin/bash -c "rustup target add wasm32-unknown-unknown; cargo build --target wasm32-unknown-unknown --release" +RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release \ No newline at end of file diff --git a/examples/ownable_change_storage_key/build.sh b/examples/ownable_change_storage_key/build.sh index 651e364..5fb19d6 100755 --- a/examples/ownable_change_storage_key/build.sh +++ b/examples/ownable_change_storage_key/build.sh @@ -1,3 +1,3 @@ #!/usr/bin/env bash -/bin/bash -c "rustup target add wasm32-unknown-unknown; cargo build --target wasm32-unknown-unknown --release" +RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release \ No newline at end of file diff --git a/examples/ownable_cross_call/build.sh b/examples/ownable_cross_call/build.sh index 651e364..5fb19d6 100755 --- a/examples/ownable_cross_call/build.sh +++ b/examples/ownable_cross_call/build.sh @@ -1,3 +1,3 @@ #!/usr/bin/env bash -/bin/bash -c "rustup target add wasm32-unknown-unknown; cargo build --target wasm32-unknown-unknown --release" +RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release \ No newline at end of file diff --git a/examples/pausable_base/build.sh b/examples/pausable_base/build.sh index 651e364..5fb19d6 100755 --- a/examples/pausable_base/build.sh +++ b/examples/pausable_base/build.sh @@ -1,3 +1,3 @@ #!/usr/bin/env bash -/bin/bash -c "rustup target add wasm32-unknown-unknown; cargo build --target wasm32-unknown-unknown --release" +RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release \ No newline at end of file diff --git a/examples/upgradable_base/build.sh b/examples/upgradable_base/build.sh index 651e364..5fb19d6 100755 --- a/examples/upgradable_base/build.sh +++ b/examples/upgradable_base/build.sh @@ -1,3 +1,3 @@ #!/usr/bin/env bash -/bin/bash -c "rustup target add wasm32-unknown-unknown; cargo build --target wasm32-unknown-unknown --release" +RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release \ No newline at end of file diff --git a/examples/upgradable_base_second/build.sh b/examples/upgradable_base_second/build.sh index 651e364..5fb19d6 100755 --- a/examples/upgradable_base_second/build.sh +++ b/examples/upgradable_base_second/build.sh @@ -1,3 +1,3 @@ #!/usr/bin/env bash -/bin/bash -c "rustup target add wasm32-unknown-unknown; cargo build --target wasm32-unknown-unknown --release" +RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release \ No newline at end of file From ce9ef6b686810492d5a7d2c016692c64237f10e3 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Tue, 18 Oct 2022 17:46:03 +0300 Subject: [PATCH 21/68] preparing step for ownable contract --- examples/ownable_base/README.md | 44 +++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/examples/ownable_base/README.md b/examples/ownable_base/README.md index d0fabba..5917a02 100644 --- a/examples/ownable_base/README.md +++ b/examples/ownable_base/README.md @@ -49,6 +49,46 @@ impl Counter { } ``` -## Preparation steps for demonstration +## Example of using contract with ownable plugin +In that document we are providing some example of using contract with ownable plugin. You also can explore the usage examples in the tests in `./src/lib.rs`. For running a tests please take a look to the **Test running instruction** section. -## Test running instruction +### Preparation steps for demonstration +1. **Creating an account on testnet** + + For demonstration, we should create a few accounts on NEAR testnet. Let's say we will create two accounts on NEAR testnet: (1) ..testnet, (2) ..testnet. You should pick some unique names for accounts. + + The instruction of creating an accounts on NEAR testnet: https://docs.near.org/tools/near-cli#near-create-account + + ```shell + $ near create-account ..testnet --masterAccount --initialBalance 10 + $ near create-account ..testnet --masterAccount --initialBalance 10 + ``` + +2. **Compile Contract to wasm file** + For compiling the contract just run the `build.sh` script. The target file with compiled contract will be `./target/wasm32-unknown-unknown/release/ownable_base.wasm` + + ```shell + $ ./build.sh + ``` + +3. **Deploy and init a contract** + ```shell + $ near deploy --accountId ..testnet --wasmFile ./target/wasm32-unknown-unknown/release/ownable_base.wasm --initFunction new --initArgs '{}' + ``` + + + +### Test running instruction +Tests in `src/lib.rs` contain examples of interaction with a contract. + +For running test: +1. Generate `wasm` file by running `build.sh` script. The target file will be `target/wasm32-unknown-unknown/release/ownable_base.wasm` +2. Run tests `cargo test` + +```shell +$ ./build.sh +$ cargo test +``` + +For tests, we use `workspaces` library and `sandbox` environment for details you can explorer `../near-plugins-test-utils` crate +contract_account. \ No newline at end of file From 947fe110fdcb39077be063bc4d86d6cc26143c81 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Tue, 18 Oct 2022 20:01:07 +0300 Subject: [PATCH 22/68] docs for ownable example --- examples/ownable_base/README.md | 102 ++++++++++++++++++++++++++++++-- 1 file changed, 98 insertions(+), 4 deletions(-) diff --git a/examples/ownable_base/README.md b/examples/ownable_base/README.md index 5917a02..bf32352 100644 --- a/examples/ownable_base/README.md +++ b/examples/ownable_base/README.md @@ -3,6 +3,11 @@ Basic access control mechanism that allows only an authorized account id to call certain methods. Note this account id can belong either to a regular user, or it could be a contract (a DAO for example). ```Rust +use near_plugins::Ownable; +use near_sdk::near_bindgen; +use near_plugins_derive::only; +use borsh::{BorshSerialize, BorshDeserialize}; + #[near_bindgen] #[derive(Ownable, Default, BorshSerialize, BorshDeserialize)] struct Counter { @@ -55,15 +60,17 @@ In that document we are providing some example of using contract with ownable pl ### Preparation steps for demonstration 1. **Creating an account on testnet** - For demonstration, we should create a few accounts on NEAR testnet. Let's say we will create two accounts on NEAR testnet: (1) ..testnet, (2) ..testnet. You should pick some unique names for accounts. + For demonstration, we should create a few accounts on NEAR testnet. Let's say we will create two accounts on NEAR testnet: (1) ..testnet, (2) ..testnet. You should pick some unique names for accounts. The instruction of creating an accounts on NEAR testnet: https://docs.near.org/tools/near-cli#near-create-account ```shell - $ near create-account ..testnet --masterAccount --initialBalance 10 - $ near create-account ..testnet --masterAccount --initialBalance 10 + $ near create-account ..testnet --masterAccount --initialBalance 10 + $ near create-account ..testnet --masterAccount --initialBalance 10 ``` + In the next section we will refer to the `..testnet` as `` and to the `..testnet` as `` for simplicity. + 2. **Compile Contract to wasm file** For compiling the contract just run the `build.sh` script. The target file with compiled contract will be `./target/wasm32-unknown-unknown/release/ownable_base.wasm` @@ -73,10 +80,97 @@ In that document we are providing some example of using contract with ownable pl 3. **Deploy and init a contract** ```shell - $ near deploy --accountId ..testnet --wasmFile ./target/wasm32-unknown-unknown/release/ownable_base.wasm --initFunction new --initArgs '{}' + $ near deploy --accountId --wasmFile ./target/wasm32-unknown-unknown/release/ownable_base.wasm --initFunction new --initArgs '{}' ``` +### Contract with owner plugin usage +#### Self is owner +After initialization the `` is the owner of this contract. So this account both the `self` and the `owner` of the contract and can call of the contract method. + +```shell +$ near call protected '{}' --accountId +$ near call protected_owner '{}' --accountId +$ near call protected_self '{}' --accountId +$ near call unprotected '{}' --accountId +``` + +We can check that we succeeded in calling all this function by calling `get_counter` view method and check that counter is 4. + +```shell +$ near view get_counter '{}' +View call: .get_counter({}) +4 +``` + +#### Limitation for another accounts +Currently, the `` doesn't connected to the contract. So, we can check that we can only succeed in calling `unprotected` method and will fail on calling all other protected methods. + +```shell +$ near call protected '{}' --accountId +$ near call protected_owner '{}' --accountId +$ near call protected_self '{}' --accountId +$ near view get_counter '{}' +View call: .get_counter({}) +4 +$ near call unprotected '{}' --accountId +$ near view get_counter '{}' +View call: .get_counter({}) +5 +``` + +#### Change the contract owner +Let's change the contract owner from `` to the ``. Only the current owner of the contract can change the owner. + +We can check the owner of the contract by callint `owner_get` view method. +```shell +$ near view owner_get '{}' +View call: .owner_get({}) +'' +``` + +In this case the owner is ``. And we can change the contract owner by running `owner_set`. +```shell +$ near call owner_set '{"owner": }' --accountId +``` + +And we can chack the contract owner one more time for making sure, that it is changed. +```shell +$ near view owner_get '{}' +View call: .owner_get({}) +'' +``` +#### Self is not a contract owner anymore +So, now `` is not an owner of out contract anymore. So, the `` can run the `unprotected`, `proteced_self`, `protected` and can't use the methods `protected_owner`. + +```shell +$ near call protected '{}' --accountId +$ near call unprotected '{}' --accountId +$ near call protected_self '{}' --accountId +$ near view get_counter '{}' +View call: .get_counter({}) +8 +$ near call protected_owner '{}' --accountId +$ near view get_counter '{}' +View call: .get_counter({}) +8 +``` + +#### Owner run the functions +And the owner of the contract(``) can use the functions `protected`, `protected_owner` and `unprotected` and can not run the `protected_self` method. + +```shell +$ near call protected '{}' --accountId +$ near call unprotected '{}' --accountId +$ near call protected_owner '{}' --accountId +$ near view get_counter '{}' +View call: .get_counter({}) +11 +$ near call protected_self '{}' --accountId +$ near view get_counter '{}' +View call: .get_counter({}) +11 +``` ### Test running instruction Tests in `src/lib.rs` contain examples of interaction with a contract. From e1a0ec5ee8f568bf84a632a311081c8a6913ed0b Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Wed, 19 Oct 2022 08:57:50 +0300 Subject: [PATCH 23/68] description of NULL ownership --- examples/ownable_base/README.md | 63 +++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 7 deletions(-) diff --git a/examples/ownable_base/README.md b/examples/ownable_base/README.md index bf32352..0e6ef21 100644 --- a/examples/ownable_base/README.md +++ b/examples/ownable_base/README.md @@ -53,6 +53,8 @@ impl Counter { } } ``` +## The contract methods description + ## Example of using contract with ownable plugin In that document we are providing some example of using contract with ownable plugin. You also can explore the usage examples in the tests in `./src/lib.rs`. For running a tests please take a look to the **Test running instruction** section. @@ -83,8 +85,8 @@ In that document we are providing some example of using contract with ownable pl $ near deploy --accountId --wasmFile ./target/wasm32-unknown-unknown/release/ownable_base.wasm --initFunction new --initArgs '{}' ``` -### Contract with owner plugin usage -#### Self is owner +### Contract with owner plugin usage examples +#### When self is owner we can call all methods After initialization the `` is the owner of this contract. So this account both the `self` and the `owner` of the contract and can call of the contract method. ```shell @@ -102,7 +104,7 @@ View call: .get_counter({}) 4 ``` -#### Limitation for another accounts +#### The stranger accounts can use only unprotected functions Currently, the `` doesn't connected to the contract. So, we can check that we can only succeed in calling `unprotected` method and will fail on calling all other protected methods. ```shell @@ -118,7 +120,7 @@ View call: .get_counter({}) 5 ``` -#### Change the contract owner +#### Check and Change the contract owner Let's change the contract owner from `` to the ``. Only the current owner of the contract can change the owner. We can check the owner of the contract by callint `owner_get` view method. @@ -140,7 +142,7 @@ View call: .owner_get({}) '' ``` -#### Self is not a contract owner anymore +#### When self is not owner it can't run the only(owner) functions So, now `` is not an owner of out contract anymore. So, the `` can run the `unprotected`, `proteced_self`, `protected` and can't use the methods `protected_owner`. ```shell @@ -156,7 +158,7 @@ View call: .get_counter({}) 8 ``` -#### Owner run the functions +#### Owner can't run the only(self) functions And the owner of the contract(``) can use the functions `protected`, `protected_owner` and `unprotected` and can not run the `protected_self` method. ```shell @@ -171,8 +173,55 @@ $ near view get_counter '{}' View call: .get_counter({}) 11 ``` +#### Only owner can change the contract ownership +When the contract have an owner only the owner can change the ownership. All other account, include self, cann't. + +```shell +$ near view owner_get '{}' +View call: .owner_get({}) +'' +$ near call owner_set '{"owner": }' --accountId +$ near view owner_get '{}' +View call: .owner_get({}) +'' + +``` + +#### Removing the owner of contract +We can remove the owner of the contract by set owner Null +```shell +$ near call owner_set '{"owner": null}' --accountId +$ near view owner_get '{}' +View call: .owner_get({}) +null +``` + +#### The self cann't run the only(owner) function if contract doesn't have an owner +When contract doesn't have an owner no one can use only(owner) functions include self. + +```shell +$ near view get_counter '{}' +View call: .get_counter({}) +11 +$ near call protected_owner '{}' --accountId +$ near view get_counter '{}' +View call: .get_counter({}) +11 +``` + +#### When the contract doesn't have owner the self can setup a new one +When the contract doesn't have the owner, the self can setup a new owner. +```shell +$ near view owner_get '{}' +View call: .owner_get({}) +null +$ near call owner_set '{"owner": }' --accountId +$ near view owner_get '{}' +View call: .owner_get({}) +'' +``` -### Test running instruction +### Tests running instruction Tests in `src/lib.rs` contain examples of interaction with a contract. For running test: From e9c3e8bb01662799ba59259feaffda86c3425cff Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Wed, 19 Oct 2022 10:06:53 +0300 Subject: [PATCH 24/68] add description of the contract methods --- examples/ownable_base/README.md | 45 +++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/examples/ownable_base/README.md b/examples/ownable_base/README.md index 0e6ef21..9f5ae50 100644 --- a/examples/ownable_base/README.md +++ b/examples/ownable_base/README.md @@ -55,6 +55,51 @@ impl Counter { ``` ## The contract methods description +### owner_set +`owner_set` - the method which sets the new owner of the contract. Only the current owner of the contract can set a new one. +If the contract doesn't have any owner the self can set one. + +```shell +$ near call owner_set '{"owner": }' --accountId +``` + +### owner_get +`owner_get` - the _view_ method which returns the current contract owner + +```shell +$ near view owner_get '{}' +View call: .owner_get({}) +'' +``` + +### owner_storage_key +`owner_storage_key` - the _view_ method which returns the key for storage the owner account id. +The `__OWNER__` by default. Can be changed by using the `ownable` attribute. See example `ownable_change_storage_key`. + +```shell +$ near view owner_storage_key +View call: .owner_storage_key() +[ + 95, 95, 79, 87, 78, + 69, 82, 95, 95 +] +$ python3 +>>> print(' '.join(str(b) for b in bytes("__OWNER__", 'utf8'))) +95 95 79 87 78 69 82 95 95 +``` + +### owner_is +`owner_is` - the methods checks if the caller is the owner of the contract +```shell +$ near call owner_is --accountId +Scheduling a call: .testnet.owner_is() +Doing account.functionCall() +Transaction Id +To see the transaction in the transaction explorer, please open this url in your browser +https://explorer.testnet.near.org/transactions/ +true +``` + ## Example of using contract with ownable plugin In that document we are providing some example of using contract with ownable plugin. You also can explore the usage examples in the tests in `./src/lib.rs`. For running a tests please take a look to the **Test running instruction** section. From 5ea7375ed258d95988bd4d5a4d84a11a33e17700 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Wed, 19 Oct 2022 11:21:24 +0300 Subject: [PATCH 25/68] create a README for access controll plugin --- examples/access_controllable_base/README.md | 69 ++++++++++++++++++++ examples/access_controllable_base/src/lib.rs | 23 ++++--- examples/ownable_base/README.md | 2 +- 3 files changed, 85 insertions(+), 9 deletions(-) create mode 100644 examples/access_controllable_base/README.md diff --git a/examples/access_controllable_base/README.md b/examples/access_controllable_base/README.md new file mode 100644 index 0000000..dbf05f5 --- /dev/null +++ b/examples/access_controllable_base/README.md @@ -0,0 +1,69 @@ +# Example of using Access Control plugin + +An access control mechanism that allows you to specify which groups of users can have access to certain functions. + +```rust +use near_plugins::AccessControllable; +use near_plugins::AccessControlRole; +use near_plugins_derive::access_control; +use near_plugins_derive::access_control_any; +use near_sdk::near_bindgen; +use borsh::{BorshSerialize, BorshDeserialize}; +use near_plugins::events::AsEvent; +use near_sdk::env; + +/// All types of access groups +#[derive(AccessControlRole, Clone, Copy)] +pub enum UsersGroups { + GroupA, + GroupB, +} + +#[near_bindgen] +#[access_control(role_type="UsersGroups")] +#[derive(Default, BorshSerialize, BorshDeserialize)] +struct Counter { + counter: u64, +} + +#[near_bindgen] +impl Counter { + /// In the constructor we set up a super admin, + /// which can control the member lists of all user groups + #[init] + pub fn new() -> Self { + let mut contract: Counter = Self{ + counter: 0, + __acl: __Acl::default(), + }; + + contract.__acl.init_super_admin(&near_sdk::env::predecessor_account_id()); + + contract + } + + /// unprotected function, every one can call this function + pub fn unprotected(&mut self) { + self.counter += 1; + } + + /// only the users from GroupA can call this method + #[access_control_any(roles(UsersGroups::GroupA))] + pub fn level_a_incr(&mut self) { + self.counter += 1; + } + + /// only the users from GroupA or GroupB can call this method + #[access_control_any(roles(UsersGroups::GroupA, UsersGroups::GroupB))] + pub fn level_ab_incr(&mut self) { + self.counter += 1; + } + + + /// view method for get current counter value, every one can use it + pub fn get_counter(&self) -> u64 { + self.counter + } +} +``` + diff --git a/examples/access_controllable_base/src/lib.rs b/examples/access_controllable_base/src/lib.rs index 8609d78..85a6ca6 100644 --- a/examples/access_controllable_base/src/lib.rs +++ b/examples/access_controllable_base/src/lib.rs @@ -7,15 +7,15 @@ use borsh::{BorshSerialize, BorshDeserialize}; use near_plugins::events::AsEvent; use near_sdk::env; +/// All types of access groups #[derive(AccessControlRole, Clone, Copy)] -pub enum Positions { - LevelA, - LevelB, - LevelC +pub enum UsersGroups { + GroupA, + GroupB, } #[near_bindgen] -#[access_control(role_type="Positions")] +#[access_control(role_type="UsersGroups")] #[derive(Default, BorshSerialize, BorshDeserialize)] struct Counter { counter: u64, @@ -23,6 +23,8 @@ struct Counter { #[near_bindgen] impl Counter { + /// In the constructor we set up a super admin, + /// which can control the member lists of all user groups #[init] pub fn new() -> Self { let mut contract: Counter = Self{ @@ -35,20 +37,25 @@ impl Counter { contract } + /// unprotected function, every one can call this function pub fn unprotected(&mut self) { self.counter += 1; } - #[access_control_any(roles(Positions::LevelA))] + /// only the users from GroupA can call this method + #[access_control_any(roles(UsersGroups::GroupA))] pub fn level_a_incr(&mut self) { self.counter += 1; } - #[access_control_any(roles(Positions::LevelA, Positions::LevelB))] + /// only the users from GroupA or GroupB can call this method + #[access_control_any(roles(UsersGroups::GroupA, UsersGroups::GroupB))] pub fn level_ab_incr(&mut self) { self.counter += 1; } + + /// view method for get current counter value, every one can use it pub fn get_counter(&self) -> u64 { self.counter } @@ -58,7 +65,7 @@ impl Counter { #[cfg(test)] mod tests { use serde_json::json; - use crate::Positions; + use crate::UsersGroups; use near_plugins_test_utils::*; const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/access_controllable_base.wasm"; diff --git a/examples/ownable_base/README.md b/examples/ownable_base/README.md index 9f5ae50..8e41d1c 100644 --- a/examples/ownable_base/README.md +++ b/examples/ownable_base/README.md @@ -1,4 +1,4 @@ -# Example using Ownable plugin +# Example of using Ownable plugin Basic access control mechanism that allows only an authorized account id to call certain methods. Note this account id can belong either to a regular user, or it could be a contract (a DAO for example). From de38224e6e5445808e45d634e40571202bb7bfdb Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Wed, 19 Oct 2022 13:53:07 +0300 Subject: [PATCH 26/68] the contract method descriptions --- examples/access_controllable_base/README.md | 103 ++++++++++++++++++++ examples/ownable_base/README.md | 4 +- 2 files changed, 105 insertions(+), 2 deletions(-) diff --git a/examples/access_controllable_base/README.md b/examples/access_controllable_base/README.md index dbf05f5..2906fee 100644 --- a/examples/access_controllable_base/README.md +++ b/examples/access_controllable_base/README.md @@ -67,3 +67,106 @@ impl Counter { } ``` +## The contract methods description +### acl_storage_prefix + +### acl_is_super_admin +`acl_is_super_admin` is a _view_ method which checks that account have a super admin rights. +Super admin can control the members list of each group and control the admins list for each group. + +```shell +$ near view acl_is_super_admin '{"account_id": "" }' +View call: .acl_is_super_admin({"account_id": ""}) +true +``` + +### acl_add_admin +`acl_add_admin` - add a new admin for a specific group. +Admins right doesn't aloud to run group specific functions, but group admins can control the group member list. +This method can be run by the admin of specific group or by the super admin. + +```shell +$ near call acl_add_admin '{"role": "GroupA", "account_id": ""}' --accountId +``` + +### acl_is_admin +`acl_is_admin` is a _view_ method which checks if the account have an admin right for specified group. For super admin it will return true. + +```shell +$ near view acl_is_admin '{"role": "GroupA", "account_id": }' +View call: .acl_is_admin({"role": "GroupA", "account_id": }) +true +``` + +### acl_revoke_admin +`acl_revoke_admin` - remove the group admin right for specific account. Can be executed by admin of this group or by super admin. + +```shell +$ near call acl_revoke_admin '{"role": "GroupA", "account_id": }' --accountId +``` + +### acl_renounce_admin +`acl_renounce_admin` - remove the group admin right for called account. + +```shell +$ near call acl_renounce_admin '{"role": "GroupA"}' --accountId +``` + +After calling that method Alice will not have the admin right for GroupA anymore. + +### acl_revoke_role + +### acl_renounce_role + +### acl_grant_role + +### acl_has_role + +### acl_has_any_role + +### acl_get_admins + +### acl_get_grantees + +## Example of using contract with access control plugin +In that document we are providing some example of using contract with access control plugin. You also can explore the usage examples in the tests in `./src/lib.rs`. For running a tests please take a look to the **Test running instruction** section. + +### Preparation steps for demonstration +1. **Creating an account on testnet** + For demonstration let's create 3 accounts: ``, ``, `` + ```shell + $ near create-account ..testnet --masterAccount .testnet --initialBalance 10 + $ near create-account ..testnet --masterAccount .testnet --initialBalance 10 + $ near create-account ..testnet --masterAccount .testnet --initialBalance 10 + ``` + + In the next section we will refer to the `..testnet` as ``, + to the `..testnet` as ``, and to the `..testnet` as `` for simplicity. + +2. **Compile Contract to wasm file** + For compiling the contract just run the `build.sh` script. The target file with compiled contract will be `./target/wasm32-unknown-unknown/release/access_controllable_base.wasm` + + ```shell + $ ./build.sh + ``` + +3. **Deploy and init a contract** + ```shell + $ near deploy --accountId --wasmFile ./target/wasm32-unknown-unknown/release/access_controllable_base.wasm --initFunction new --initArgs '{}' + ``` + + +### Tests running instruction +Tests in `src/lib.rs` contain examples of interaction with a contract. + +For running test: +1. Generate `wasm` file by running `build.sh` script. The target file will be `target/wasm32-unknown-unknown/release/access_controllable_base.wasm` +2. Run tests `cargo test` + +```shell +$ ./build.sh +$ cargo test +``` + +For tests, we use `workspaces` library and `sandbox` environment for details you can explorer `../near-plugins-test-utils` crate +contract_account. \ No newline at end of file diff --git a/examples/ownable_base/README.md b/examples/ownable_base/README.md index 8e41d1c..2539b50 100644 --- a/examples/ownable_base/README.md +++ b/examples/ownable_base/README.md @@ -112,8 +112,8 @@ In that document we are providing some example of using contract with ownable pl The instruction of creating an accounts on NEAR testnet: https://docs.near.org/tools/near-cli#near-create-account ```shell - $ near create-account ..testnet --masterAccount --initialBalance 10 - $ near create-account ..testnet --masterAccount --initialBalance 10 + $ near create-account ..testnet --masterAccount .testnet --initialBalance 10 + $ near create-account ..testnet --masterAccount .testnet --initialBalance 10 ``` In the next section we will refer to the `..testnet` as `` and to the `..testnet` as `` for simplicity. From 822cb726984ef07f4b837a15853e1d93ca03bc1d Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Wed, 19 Oct 2022 14:24:52 +0300 Subject: [PATCH 27/68] the contract method descriptions 2 --- examples/access_controllable_base/README.md | 37 +++++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/examples/access_controllable_base/README.md b/examples/access_controllable_base/README.md index 2906fee..5ac196d 100644 --- a/examples/access_controllable_base/README.md +++ b/examples/access_controllable_base/README.md @@ -93,8 +93,8 @@ $ near call acl_add_admin '{"role": "GroupA", "account_id": " `acl_is_admin` is a _view_ method which checks if the account have an admin right for specified group. For super admin it will return true. ```shell -$ near view acl_is_admin '{"role": "GroupA", "account_id": }' -View call: .acl_is_admin({"role": "GroupA", "account_id": }) +$ near view acl_is_admin '{"role": "GroupA", "account_id": ""}' +View call: .acl_is_admin({"role": "GroupA", "account_id": ""}) true ``` @@ -102,7 +102,7 @@ true `acl_revoke_admin` - remove the group admin right for specific account. Can be executed by admin of this group or by super admin. ```shell -$ near call acl_revoke_admin '{"role": "GroupA", "account_id": }' --accountId +$ near call acl_revoke_admin '{"role": "GroupA", "account_id": ""}' --accountId ``` ### acl_renounce_admin @@ -115,17 +115,48 @@ $ near call acl_renounce_admin '{"role": "GroupA"}' --account After calling that method Alice will not have the admin right for GroupA anymore. ### acl_revoke_role +`acl_revoke_role` - remove the specified account from the list of the group member. +Only the group admin or super admin can execute this function. + +```shell +$ near call acl_revoke_role '{"role": "GroupA", "account_id": ""}' --accountId +``` ### acl_renounce_role +`acl_renounce_role` - remove the caller account from the member list of the group. Can be called by anyone. + +```shell +$ near call acl_renounce_role '{"role": "GroupA"}' --accountId +``` ### acl_grant_role +`acl_grant_role` - add the account to the group member list. Can be executed only by the group admin or by super admin. + +```shell +$ near call acl_grant_role '{"role": "GroupA", "account_id": ""}' --accountId +``` ### acl_has_role +`acl_has_role` - a _view_ method for check if the account is a member of specified group. + +```shell +$ near view acl_has_role '{"role": "GroupA", "account_id": ""}' +View call: .acl_has_role({"role": "GroupA", "account_id": ""}) +true +``` ### acl_has_any_role +`acl_has_any_role` - a _view_ method to check if an account a member of at least one of specified groups. + +```shell +$ near view acl_has_any_role '{"roles": ["GroupA", "GroupB"], "account_id": ""}' +View call: .acl_has_any_role({"roles": ["GroupA", "GroupB"], "account_id": ""}) +true +``` ### acl_get_admins + ### acl_get_grantees ## Example of using contract with access control plugin From a2ac89ac48d77a57565c5c26f323f96e3bbf6218 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Wed, 19 Oct 2022 15:03:15 +0300 Subject: [PATCH 28/68] the contract method descriptions 3 --- examples/access_controllable_base/README.md | 36 ++++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/examples/access_controllable_base/README.md b/examples/access_controllable_base/README.md index 5ac196d..f9fdb94 100644 --- a/examples/access_controllable_base/README.md +++ b/examples/access_controllable_base/README.md @@ -69,9 +69,24 @@ impl Counter { ## The contract methods description ### acl_storage_prefix +`acl_storage_prefix` - a method which show the common prefix of keys for storage the members and the admins of groups. +`__acl` by default. + +```shell +$ near call acl_storage_prefix --accountId acl.olga24912_3.testnet +Scheduling a call: .acl_storage_prefix() +Doing account.functionCall() +Transaction Id +To see the transaction in the transaction explorer, please open this url in your browser +https://explorer.testnet.near.org/transactions/ +[ 95, 95, 97, 99, 108 ] +$ python3 +>>> print(' '.join(str(b) for b in bytes("__acl", 'utf8'))) +95 95 97 99 108 +``` ### acl_is_super_admin -`acl_is_super_admin` is a _view_ method which checks that account have a super admin rights. +`acl_is_super_admin` - a _view_ method which checks that account have a super admin rights. Super admin can control the members list of each group and control the admins list for each group. ```shell @@ -155,14 +170,26 @@ true ``` ### acl_get_admins +`acl_get_admins` - a _view_ method which shows some group admins. It will skip first `skip` admins and return maximum `limit` number of admins. +```shell +$ near view acl_get_admins '{"role": "GroupA", "skip": 0, "limit": 2}' +View call: .acl_get_admins({"role": "GroupA", "skip": 0, "limit": 2}) +[ '' ] +``` ### acl_get_grantees +`acl_get_grantess` - a _view_ method which shows some members of the group. It will skip first `skip` members and return maximum `limit` number of members. + +```shell +$ near view acl_get_grantess '{"role": "GroupA", "skip": 0, "limit": 2}' +View call: .acl_get_grantess({"role": "GroupA", "skip": 0, "limit": 2}) +[ '' ] +``` -## Example of using contract with access control plugin +## Preparation steps for demonstration In that document we are providing some example of using contract with access control plugin. You also can explore the usage examples in the tests in `./src/lib.rs`. For running a tests please take a look to the **Test running instruction** section. -### Preparation steps for demonstration 1. **Creating an account on testnet** For demonstration let's create 3 accounts: ``, ``, `` ```shell @@ -186,8 +213,9 @@ In that document we are providing some example of using contract with access con $ near deploy --accountId --wasmFile ./target/wasm32-unknown-unknown/release/access_controllable_base.wasm --initFunction new --initArgs '{}' ``` +## Example of using the contract with access control plugin -### Tests running instruction +## Tests running instruction Tests in `src/lib.rs` contain examples of interaction with a contract. For running test: From ac401f8893fb3e557b3feb2efca58777e5b169b4 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Wed, 19 Oct 2022 16:00:26 +0300 Subject: [PATCH 29/68] simple examples for access control --- examples/access_controllable_base/README.md | 39 +++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/examples/access_controllable_base/README.md b/examples/access_controllable_base/README.md index f9fdb94..87ff722 100644 --- a/examples/access_controllable_base/README.md +++ b/examples/access_controllable_base/README.md @@ -214,6 +214,45 @@ In that document we are providing some example of using contract with access con ``` ## Example of using the contract with access control plugin +### Calling the access control methods +For using the method `level_a_incr` you should be a memeber of the GroupA. Alice not a member of any group, so she cann't use this method. + +```shell +$ near call level_a_incr --accountId +$ near view get_counter +0 +``` + +Let's make the Alice the member of the GroupA. +```shell +$ near call acl_grant_role '{"role": "GroupA", "account_id": ""}' --accountId +``` + +Now Alice the member of GroupA and call the level_a_incr method +```shell +$ near call level_a_incr --accountId +$ near view get_counter +1 +``` + +As well as `level_ab_incr` which aloud for both GroupA and GroupB members. +```shell +$ near call level_ab_incr --accountId +$ near view get_counter +2 +``` + +### Admin of the group not a member of the group +Note the admin of the group may not be a member of this group. For example, the `` is a super admin, but he +cann't execute the `level_a_incr` method. + +```shell +$ near view get_counter +2 +$ near call level_a_incr --accountId +$ near view get_counter +2 +``` ## Tests running instruction Tests in `src/lib.rs` contain examples of interaction with a contract. From 7c68c98ab3cfc64bd75589122f7bbe1240939295 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Wed, 19 Oct 2022 16:04:23 +0300 Subject: [PATCH 30/68] fix tests --- examples/access_controllable_base/src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/access_controllable_base/src/lib.rs b/examples/access_controllable_base/src/lib.rs index 85a6ca6..c01419b 100644 --- a/examples/access_controllable_base/src/lib.rs +++ b/examples/access_controllable_base/src/lib.rs @@ -89,9 +89,9 @@ mod tests { assert!(!call!(&alice, contract, "level_a_incr")); check_counter(&contract, 1); - assert!(call!(contract, "acl_grant_role", &json!({"role": String::from(Positions::LevelA), "account_id": alice.id()}))); + assert!(call!(contract, "acl_grant_role", &json!({"role": String::from(UsersGroups::GroupA), "account_id": alice.id()}))); - let alice_has_role: bool = view!(contract, "acl_has_role", &json!({"role": String::from(Positions::LevelA), "account_id": alice.id()})); + let alice_has_role: bool = view!(contract, "acl_has_role", &json!({"role": String::from(UsersGroups::GroupA), "account_id": alice.id()})); assert!(alice_has_role); assert!(call!(&alice, contract, "level_a_incr")); @@ -99,9 +99,9 @@ mod tests { check_counter(&contract, 2); let bob = get_subaccount(&contract_holder, "bob"); - assert!(call!(contract, "acl_add_admin", &json!({"role": String::from(Positions::LevelA), "account_id": bob.id()}))); + assert!(call!(contract, "acl_add_admin", &json!({"role": String::from(UsersGroups::GroupA), "account_id": bob.id()}))); - let bob_is_admin: bool = view!(contract, "acl_is_admin", &json!({"role": String::from(Positions::LevelA), "account_id": bob.id()})); + let bob_is_admin: bool = view!(contract, "acl_is_admin", &json!({"role": String::from(UsersGroups::GroupA), "account_id": bob.id()})); assert!(bob_is_admin); assert!(!call!(&bob, contract, "level_a_incr")); @@ -114,7 +114,7 @@ mod tests { assert!(!call!(&bob, contract, "level_ab_incr")); check_counter(&contract, 3); - assert!(call!(contract, "acl_grant_role", &json!({"role": String::from(Positions::LevelB), "account_id": bob.id()}))); + assert!(call!(contract, "acl_grant_role", &json!({"role": String::from(UsersGroups::GroupB), "account_id": bob.id()}))); assert!(call!(&bob, contract, "level_ab_incr")); check_counter(&contract, 4); From 4f8d1735129f2e139641e127ae7cc035dc9eee58 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Wed, 19 Oct 2022 16:27:11 +0300 Subject: [PATCH 31/68] README for upgradable base --- examples/upgradable_base/README.md | 71 ++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 examples/upgradable_base/README.md diff --git a/examples/upgradable_base/README.md b/examples/upgradable_base/README.md new file mode 100644 index 0000000..2c619ef --- /dev/null +++ b/examples/upgradable_base/README.md @@ -0,0 +1,71 @@ +# Example of using Upgradable plugin + +Allows a contract to be upgraded by owner without having a Full Access Key. + +Contract example using Upgradable plugin. Note that it requires the contract to be Ownable. + +```rust +use near_plugins::{Ownable, Upgradable}; +use near_sdk::near_bindgen; +use borsh::{BorshSerialize, BorshDeserialize}; + +#[near_bindgen] +#[derive(Ownable, Upgradable, Default, BorshSerialize, BorshDeserialize)] +struct Counter1 { + counter: u64, +} + +#[near_bindgen] +impl Counter1 { + /// Specify the owner of the contract in the constructor + #[init] + pub fn new() -> Self { + let mut contract = Self { counter: 0 }; + contract.owner_set(Some(near_sdk::env::predecessor_account_id())); + contract + } + + pub fn inc1(&mut self) { + self.counter += 1; + } + + pub fn get_counter(&self) -> u64 { + self.counter + } +} +``` + +The second example contract for upgrading you can find in the `../upgradable_base_second/` folder. + +The second contract: +```rust +use near_plugins::{Ownable, Upgradable}; +use near_sdk::near_bindgen; +use borsh::{BorshSerialize, BorshDeserialize}; + +#[near_bindgen] +#[derive(Ownable, Upgradable, Default, BorshSerialize, BorshDeserialize)] +struct Counter2 { + counter: u64, +} + +#[near_bindgen] +impl Counter2 { + #[init] + pub fn new() -> Self { + let mut contract = Self { counter: 0 }; + contract.owner_set(Some(near_sdk::env::predecessor_account_id())); + contract + } + + pub fn inc2(&mut self) { + self.counter += 2; + } + + pub fn get_counter(&self) -> u64 { + self.counter + } +} +``` + +To upgrade the contract first call up_stage_code passing the binary as first argument serialized as borsh. Then call up_deploy_code. This functions must be called from the owner. \ No newline at end of file From 356979c647a328e965c15d51edba9990e9b12cb0 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Wed, 19 Oct 2022 16:37:37 +0300 Subject: [PATCH 32/68] README for pausable --- examples/pausable_base/README.md | 76 ++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 examples/pausable_base/README.md diff --git a/examples/pausable_base/README.md b/examples/pausable_base/README.md new file mode 100644 index 0000000..2ea4a83 --- /dev/null +++ b/examples/pausable_base/README.md @@ -0,0 +1,76 @@ +# Example of using Pausable plugin +Allow contracts to implement an emergency stop mechanism that can be triggered by an authorized account. Pauses can be used granularly to only limit certain features. + +Contract example using Pausable plugin. Note that it requires the contract to be Ownable. + +```rust +use near_plugins::Ownable; +use near_plugins::Pausable; +use near_sdk::near_bindgen; +use near_plugins_derive::{pause, if_paused}; +use borsh::{BorshSerialize, BorshDeserialize}; + +#[near_bindgen] +#[derive(Ownable, Pausable, Default, BorshSerialize, BorshDeserialize)] +struct Counter { + counter: u64, +} + +#[near_bindgen] +impl Counter { + /// Specify the owner of the contract in the constructor + #[init] + pub fn new() -> Self { + let mut contract = Self { counter: 0 }; + contract.owner_set(Some(near_sdk::env::predecessor_account_id())); + contract + } + + /// Function can be paused using feature name "increase_1" or "ALL" like: + /// `contract.pa_pause_feature("increase_1")` or `contract.pa_pause_feature("ALL")` + /// + /// If the function is paused, all calls to it will fail. Even calls started from owner or self. + #[pause] + pub fn increase_1(&mut self) { + self.counter += 1; + } + + /// Similar to `#[pause]` but use an explicit name for the feature. In this case the feature to be paused + /// is named "Increase by two". Note that trying to pause it using "increase_2" will not have any effect. + /// + /// This can be used to pause a subset of the methods at once without requiring to use "ALL". + #[pause(name = "Increase by two")] + pub fn increase_2(&mut self) { + self.counter += 2; + } + + /// Similar to `#[pause]` but owner or self can still call this method. Any subset of {self, owner} can be specified. + #[pause(except(owner, self))] + pub fn increase_4(&mut self) { + self.counter += 4; + } + + /// This method can only be called when "increase_1" is paused. Use this macro to create escape hatches when some + /// features are paused. Note that if "ALL" is specified the "increase_1" is considered to be paused. + #[if_paused(name = "increase_1")] + pub fn decrease_1(&mut self) { + self.counter -= 1; + } + + /// Custom use of pause features. Only allow increasing the counter using `careful_increase` if it is below 10. + pub fn careful_increase(&mut self) { + if self.counter >= 10 { + assert!( + !self.pa_is_paused("INCREASE_BIG".to_string()), + "Method paused for large values of counter" + ); + } + + self.counter += 1; + } + + pub fn get_counter(&self) -> u64 { + self.counter + } +} +``` \ No newline at end of file From b095d72fb65b1dfe556c87524ec9c53d7e09e5bf Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Wed, 19 Oct 2022 16:46:07 +0300 Subject: [PATCH 33/68] full access key fallback README --- .../full_access_key_fallback_base/README.md | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 examples/full_access_key_fallback_base/README.md diff --git a/examples/full_access_key_fallback_base/README.md b/examples/full_access_key_fallback_base/README.md new file mode 100644 index 0000000..4b59f52 --- /dev/null +++ b/examples/full_access_key_fallback_base/README.md @@ -0,0 +1,39 @@ +# Example of using Full Access Key Fallback plugin + +Allows an authorized account to attach a Full Access Key to the contract. + +Contract example using Full Access Key Fallback plugin. Note that it requires the contract to be Ownable. + +```rust +use near_plugins::{Ownable, FullAccessKeyFallback}; +use near_sdk::near_bindgen; +use near_plugins_derive::only; +use borsh::{BorshSerialize, BorshDeserialize}; + +#[near_bindgen] +#[derive(Ownable, FullAccessKeyFallback, Default, BorshSerialize, BorshDeserialize)] +struct Counter { + counter: u64, +} + +#[near_bindgen] +impl Counter { + /// Specify the owner of the contract in the constructor + #[init] + pub fn new() -> Self { + let mut contract = Self { counter: 0 }; + contract.owner_set(Some(near_sdk::env::predecessor_account_id())); + contract + } + + /// *Only* self account can call this method. This can be used even if the contract is not Ownable. + #[only(self)] + pub fn protected_self(&mut self) { + self.counter += 1; + } + + pub fn get_counter(&self) -> u64 { + self.counter + } +} +``` \ No newline at end of file From aed85f85ebfc9d6a9e5252561bb6fbd9db0c3f43 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Wed, 19 Oct 2022 17:03:57 +0300 Subject: [PATCH 34/68] add metods list for plugins --- examples/full_access_key_fallback_base/README.md | 5 ++++- examples/pausable_base/README.md | 13 ++++++++++++- examples/upgradable_base/README.md | 13 ++++++++++++- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/examples/full_access_key_fallback_base/README.md b/examples/full_access_key_fallback_base/README.md index 4b59f52..40bb045 100644 --- a/examples/full_access_key_fallback_base/README.md +++ b/examples/full_access_key_fallback_base/README.md @@ -36,4 +36,7 @@ impl Counter { self.counter } } -``` \ No newline at end of file +``` + +## The contract methods description +### attach_full_access_key diff --git a/examples/pausable_base/README.md b/examples/pausable_base/README.md index 2ea4a83..9caf84c 100644 --- a/examples/pausable_base/README.md +++ b/examples/pausable_base/README.md @@ -73,4 +73,15 @@ impl Counter { self.counter } } -``` \ No newline at end of file +``` + +## The contract methods description +### pa_storage_key + +### pa_is_paused + +### pa_all_paused + +### pa_pause_feature + +### pa_unpause_feature \ No newline at end of file diff --git a/examples/upgradable_base/README.md b/examples/upgradable_base/README.md index 2c619ef..65dcbee 100644 --- a/examples/upgradable_base/README.md +++ b/examples/upgradable_base/README.md @@ -68,4 +68,15 @@ impl Counter2 { } ``` -To upgrade the contract first call up_stage_code passing the binary as first argument serialized as borsh. Then call up_deploy_code. This functions must be called from the owner. \ No newline at end of file +To upgrade the contract first call up_stage_code passing the binary as first argument serialized as borsh. Then call up_deploy_code. This functions must be called from the owner. + +## The contract methods description +### up_storage_key + +### up_stage_code + +### up_staged_code + +### up_staged_code_hash + +### up_deploy_code From cd304df4144f7b9c848f047eba84a90f2c78078c Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Thu, 20 Oct 2022 09:43:01 +0300 Subject: [PATCH 35/68] info about pausable storage key --- examples/pausable_base/README.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/examples/pausable_base/README.md b/examples/pausable_base/README.md index 9caf84c..0dcb0cd 100644 --- a/examples/pausable_base/README.md +++ b/examples/pausable_base/README.md @@ -77,9 +77,34 @@ impl Counter { ## The contract methods description ### pa_storage_key +`pa_storage_key` is a _view_ method which returns the key of storage slot with list of paused features. +By default `b"__PAUSED__"` is used. For changing the attribute `pausable` can be used. + +```shell +$ near view owner_storage_key +View call: .owner_storage_key() +[ + 95, 95, 80, 65, 85, + 83, 69, 68, 95, 95 +] +$ python3 +>>> print(' '.join(str(b) for b in bytes("__PAUSED__", 'utf8'))) +95 95 80 65 85 83 69 68 95 95 +``` + +Example of changing paused storage key: +```rust +#[near_bindgen] +#[derive(Ownable, Pausable, Default, BorshSerialize, BorshDeserialize)] +#[pausable(paused_storage_key="OTHER_PAUSED_STORAGE_KEY")] +struct Counter { + counter: u64, +} +``` ### pa_is_paused + ### pa_all_paused ### pa_pause_feature From 865406b6ff19fe6810c17785194251e937be4f93 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Thu, 20 Oct 2022 09:56:50 +0300 Subject: [PATCH 36/68] info for pa_is_paused --- examples/pausable_base/README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/examples/pausable_base/README.md b/examples/pausable_base/README.md index 0dcb0cd..6816c14 100644 --- a/examples/pausable_base/README.md +++ b/examples/pausable_base/README.md @@ -81,8 +81,8 @@ impl Counter { By default `b"__PAUSED__"` is used. For changing the attribute `pausable` can be used. ```shell -$ near view owner_storage_key -View call: .owner_storage_key() +$ near view pa_storage_key +View call: .pa_storage_key() [ 95, 95, 80, 65, 85, 83, 69, 68, 95, 95 @@ -103,7 +103,13 @@ struct Counter { ``` ### pa_is_paused +`pa_is_paused` is a _view_ which returns if a feature is paused. +```shell +$ near view pa_is_paused '{"key": "increase_1"}' +View call: .pa_is_paused({"key": "increase_1"}) +false +``` ### pa_all_paused From 36393fb29485fb1b76a6da818e9040973e8cfe35 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Thu, 20 Oct 2022 10:09:10 +0300 Subject: [PATCH 37/68] the contract methods description --- examples/pausable_base/README.md | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/examples/pausable_base/README.md b/examples/pausable_base/README.md index 6816c14..4c34c64 100644 --- a/examples/pausable_base/README.md +++ b/examples/pausable_base/README.md @@ -103,16 +103,34 @@ struct Counter { ``` ### pa_is_paused -`pa_is_paused` is a _view_ which returns if a feature is paused. +`pa_is_paused` is a _view_ method which returns if a feature is paused. ```shell $ near view pa_is_paused '{"key": "increase_1"}' View call: .pa_is_paused({"key": "increase_1"}) -false +true ``` ### pa_all_paused +`pa_all_paused` is a _view_ method which return the list of the all paused features. + +```shell +$ near view pa_all_paused +View call: .pa_all_paused() +[ 'increase_1', 'increase_2' ] +``` + ### pa_pause_feature +`pa_pause_feature` is a method for pause specified feature. Can be run only by owner or self. -### pa_unpause_feature \ No newline at end of file +```shell +$ near call pa_pause_feature '{"key": "increase_1"}' --accountId +``` + +### pa_unpause_feature +`pa_unpause_feature` is a method for unpause specified feature. Can be run only by owner or self. + +```shell +$ near call pa_unpause_feature '{"key": "increase_1"}' --accountId +``` \ No newline at end of file From d0df1714e2c0e3a9c7b7a8bc8d7de587aeedc957 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Thu, 20 Oct 2022 10:41:52 +0300 Subject: [PATCH 38/68] pauseble example --- examples/pausable_base/README.md | 105 ++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-) diff --git a/examples/pausable_base/README.md b/examples/pausable_base/README.md index 4c34c64..dde8775 100644 --- a/examples/pausable_base/README.md +++ b/examples/pausable_base/README.md @@ -133,4 +133,107 @@ $ near call pa_pause_feature '{"key": "increase_1"}' --accoun ```shell $ near call pa_unpause_feature '{"key": "increase_1"}' --accountId -``` \ No newline at end of file +``` + +## Preparation steps for demonstration +In that document we are providing some example of using contract with access control plugin. You also can explore the usage examples in the tests in `./src/lib.rs`. For running a tests please take a look to the **Test running instruction** section. + +1. **Creating an account on testnet** + For demonstration let's create 2 accounts: ``, `` + ```shell + $ near create-account ..testnet --masterAccount .testnet --initialBalance 10 + $ near create-account ..testnet --masterAccount .testnet --initialBalance 10 + ``` + + In the next section we will refer to the `..testnet` as ``, + to the `..testnet` as ``. + +2. **Compile Contract to wasm file** + For compiling the contract just run the `build.sh` script. The target file with compiled contract will be `./target/wasm32-unknown-unknown/release/pausable_base.wasm` + + ```shell + $ ./build.sh + ``` + +3. **Deploy and init a contract** + ```shell + $ near deploy --accountId --wasmFile ./target/wasm32-unknown-unknown/release/pausable_base.wasm --initFunction new --initArgs '{}' + ``` + +## Example of using the contract with pausable plugin +### Simple pause and unpause function without name specification +At the beginning the `` both the self and the owner. +`` doesn't have any specific rights. + +No features on pause: +```shell +$ near view pa_all_paused +View call: .pa_all_paused() +null +``` + +Alice can call `increase_1` function: +```shell +$ near call increase_1 --accountId +$ near view get_counter +1 +``` + +#### Pause function +Self(or owner) pause function: +```shell +$ near call pa_pause_feature '{"key": "increase_1"}' --accountId +$ near view pa_all_paused +View call: .pa_all_paused() +[ 'increase_1' ] +$ near view pa_is_paused '{"key": "increase_1"}' +View call: .pa_is_paused({"key": "increase_1"}) +true +``` + +Now Alice or even self cann't run `increase_1` function +```shell +$ near view get_counter +1 +$ near call increase_1 --accountId +$ near call increase_1 --accountId +$ near view get_counter +1 +``` + +#### Unpause function +Self(or owner) can unpause feature: +```shell +$ near call pa_unpause_feature '{"key": "increase_1"}' --accountId +$ near view pa_all_paused +View call: .pa_all_paused() +null +$ near view pa_is_paused '{"key": "increase_1"}' +View call: .pa_is_paused({"key": "increase_1"}) +false +``` + +Now Alice can continue use the `increase_1` function +```shell +$ near view get_counter +1 +$ near call increase_1 --accountId +$ near call increase_1 --accountId +$ near view get_counter +3 +``` + +## Tests running instruction +Tests in `src/lib.rs` contain examples of interaction with a contract. + +For running test: +1. Generate `wasm` file by running `build.sh` script. The target file will be `target/wasm32-unknown-unknown/release/pausable_base.wasm` +2. Run tests `cargo test` + +```shell +$ ./build.sh +$ cargo test +``` + +For tests, we use `workspaces` library and `sandbox` environment for details you can explorer `../near-plugins-test-utils` crate +contract_account. \ No newline at end of file From d575fae3afc0972a5fe988642c1a3b7d32513830 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Thu, 20 Oct 2022 18:02:39 +0300 Subject: [PATCH 39/68] examples for upgradable --- examples/upgradable_base/Cargo.toml | 6 +- examples/upgradable_base/README.md | 144 ++++++++++++++++++ examples/upgradable_base/src/up_stage_code.rs | 23 +++ near-plugins/src/upgradable.rs | 2 +- 4 files changed, 172 insertions(+), 3 deletions(-) create mode 100644 examples/upgradable_base/src/up_stage_code.rs diff --git a/examples/upgradable_base/Cargo.toml b/examples/upgradable_base/Cargo.toml index da4880f..8f11d50 100644 --- a/examples/upgradable_base/Cargo.toml +++ b/examples/upgradable_base/Cargo.toml @@ -5,6 +5,10 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[[bin]] +name = "up_stage_code" +path = "src/up_stage_code.rs" + [lib] crate-type = ["cdylib", "rlib"] @@ -13,8 +17,6 @@ near-sdk = "4.0.0" near-plugins = { path = "../../near-plugins" } near-plugins-derive = { path = "../../near-plugins-derive" } borsh = "0.9.3" - -[dev-dependencies] near-primitives = { version = "0.14.0" } workspaces = "0.6" tokio = { version = "1.1", features = ["rt", "macros"] } diff --git a/examples/upgradable_base/README.md b/examples/upgradable_base/README.md index 65dcbee..75e0951 100644 --- a/examples/upgradable_base/README.md +++ b/examples/upgradable_base/README.md @@ -72,11 +72,155 @@ To upgrade the contract first call up_stage_code passing the binary as first arg ## The contract methods description ### up_storage_key +`up_storage_key` is a _view_ method which return a key of storage slot for stage code. +By default `b"__CODE__"` is used. For changing the attribute `upgradable` can be used. + +```shell +$ near view up_storage_key +View call: .up_storage_key() +[ + 95, 95, 80, 65, 85, + 83, 69, 68, 95, 95 +] +$ python3 +>>> print(' '.join(str(b) for b in bytes("__CODE__", 'utf8'))) +95 95 67 79 68 69 95 95 +``` + +Example of changing paused storage key: +```rust +#[near_bindgen] +#[derive(Ownable, Upgradable, Default, BorshSerialize, BorshDeserialize)] +#[upgradable(code_storage_key="OTHER_CODE_STORAGE_KEY")] +struct Counter { + counter: u64, +} +``` ### up_stage_code +`up_stage_code` method to stage some code to be potentially deployed later. If a previous code was staged but not deployed, it is discarded. +Method can be called only by owner + +```shell +$ export CODE=$(cat ../upgradable_base_second/target/wasm32-unknown-unknown/release/upgradable_base_second.wasm | xxd -ps | sed -z 's/\n//g') +$ near call up_stage_code --base64 $CODE --accountId +``` + +But it doesn't work in that way because we cann't provide in Bash so long args... So, probable here we can't use just NEAR CLI for interaction with contract :( + +For running `up_satge_code` take a look on `src/up_stage_code.rs` script. +```shell +cargo run -- "" +``` ### up_staged_code +`up_staged_code` a _view_ method which returns a staged code. + +```shell +$ near call up_staged_code --accountId +``` ### up_staged_code_hash +`up_staged_code_hash` a _view_ method which returns the hash of the staged code. + +```shell +$ near view up_staged_code_hash +View call: .up_staged_code_hash() +[ + 63, 26, 245, 200, 217, 12, 109, 77, + 40, 222, 40, 173, 192, 197, 28, 236, + 231, 239, 19, 223, 212, 99, 98, 228, + 162, 119, 89, 37, 250, 173, 87, 5 +] +``` ### up_deploy_code +`up_deploy_code` method deploy a staged code. If no code is staged the method fails. +Method can be called only by owner + +```shell +$ near call up_deploy_code --accountId +``` + +## Preparation steps for demonstration +In that document we are providing some example of using contract with access control plugin. You also can explore the usage examples in the tests in `./src/lib.rs`. For running a tests please take a look to the **Test running instruction** section. + +1. **Creating an account on testnet** + For demonstration let's create 2 accounts: ``, `` + ```shell + $ near create-account ..testnet --masterAccount .testnet --initialBalance 10 + $ near create-account ..testnet --masterAccount .testnet --initialBalance 10 + ``` + + In the next section we will refer to the `..testnet` as ``, + to the `..testnet` as ``. + +2. **Compile 2 Contract to wasm file** + We should compile 2 contracts: `upgradable_base`, `upgradable_base_second`. + + ```shell + $ ./build.sh + $ cd ../upgradable_base_second + $ ./build.sh + $ cd ../upgradable_base + ``` + + The contracts will be compiled into `./target/wasm32-unknown-unknown/release/upgradable_base.wasm`, `../upgradable_base_second/target/wasm32-unknown-unknown/release/upgradable_base_second.wasm` + +3. **Deploy and init a contract** + ```shell + $ near deploy --accountId --wasmFile ./target/wasm32-unknown-unknown/release/upgradable_base.wasm --initFunction new --initArgs '{}' + ``` + +## Example of using the contract with upgradable plugin +### Upgrade contract +Currently on `` contract `Counter1` is deployed, and we would like to upgrade it to `Counter2`. + +#### Increment counter on first contract +```shell +$ near view get_counter +0 +$ near call inc1 --accountId +$ near view get_counter +1 +$ near call inc2 --accountId +$ near view get_counter +1 +``` + +#### Stage new contract +```shell +cargo run -- "" +``` + +#### Deploy new contract +```shell +$ near call up_deploy_code --accountId +``` + +#### Increment counter on second contract +```shell +$ near view get_counter +1 +$ near call inc1 --accountId +$ near view get_counter +1 +$ near call inc2 --accountId +$ near view get_counter +2 +``` + +## Tests running instruction +Tests in `src/lib.rs` contain examples of interaction with a contract. + +For running test: +1. Generate `wasm` file by running `build.sh` script. The target file will be `target/wasm32-unknown-unknown/release/upgradable_base.wasm` +2. Run tests `cargo test` + +```shell +$ ./build.sh +$ cargo test +``` + +For tests, we use `workspaces` library and `sandbox` environment for details you can explorer `../near-plugins-test-utils` crate +contract_account. \ No newline at end of file diff --git a/examples/upgradable_base/src/up_stage_code.rs b/examples/upgradable_base/src/up_stage_code.rs new file mode 100644 index 0000000..a014c11 --- /dev/null +++ b/examples/upgradable_base/src/up_stage_code.rs @@ -0,0 +1,23 @@ +use serde_json::json; +use tokio::runtime::Runtime; +use workspaces::{Account, Contract}; +use std::env; + +const WASM_FILEPATH_SECOND: &str = "../upgradable_base_second/target/wasm32-unknown-unknown/release/upgradable_base_second.wasm"; + +fn main() { + let args: Vec = env::args().collect(); + let rt = Runtime::new().unwrap(); + let worker = rt.block_on(workspaces::testnet()).unwrap(); + + let contract: Account = Account::from_file(args[1].clone(), &worker).unwrap(); + + let wasm = std::fs::read(WASM_FILEPATH_SECOND).unwrap(); + + println!("{}", rt.block_on( + contract.call(contract.id(), "up_stage_code") + .args_borsh(wasm) + .max_gas() + .transact() + ).unwrap().is_success()); +} \ No newline at end of file diff --git a/near-plugins/src/upgradable.rs b/near-plugins/src/upgradable.rs index 465fd95..6630c6d 100644 --- a/near-plugins/src/upgradable.rs +++ b/near-plugins/src/upgradable.rs @@ -24,7 +24,7 @@ use near_sdk::{AccountId, CryptoHash, Promise}; use serde::Serialize; pub trait Upgradable { - /// Key of storage slot to save the current owner. + /// Key of storage slot to save the stage code. /// By default b"__CODE__" is used. fn up_storage_key(&self) -> Vec; From d31b513201dab5a8e2271419fdfd59ff7bda167b Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Fri, 21 Oct 2022 15:53:30 +0300 Subject: [PATCH 40/68] readme for full access key example --- .../full_access_key_fallback_base/README.md | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/examples/full_access_key_fallback_base/README.md b/examples/full_access_key_fallback_base/README.md index 40bb045..5b30f8a 100644 --- a/examples/full_access_key_fallback_base/README.md +++ b/examples/full_access_key_fallback_base/README.md @@ -40,3 +40,84 @@ impl Counter { ## The contract methods description ### attach_full_access_key +`attach_full_access_key` - attach a new full access for the current account. +Only owner of the contract can use this function. + +```shell +near call attach_full_access_key '{"public_key": "ed25519:ErVTCTvmepb4NDhQ7infTomkLVsd1iTWwLR84FBhV7UC"}' --accountId +``` + +## Preparation steps for demonstration +In that document we are providing some example of using contract with access control plugin. You also can explore the usage examples in the tests in `./src/lib.rs`. For running a tests please take a look to the **Test running instruction** section. + +1. **Creating an account on testnet** + For demonstration let's create 2 accounts: ``, `` + ```shell + $ near create-account ..testnet --masterAccount .testnet --initialBalance 10 + $ near create-account ..testnet --masterAccount .testnet --initialBalance 10 + ``` + + In the next section we will refer to the `..testnet` as ``, + to the `..testnet` as ``. + +2. **Compile Contract to wasm file** + For compiling the contract just run the `build.sh` script. The target file with compiled contract will be `./target/wasm32-unknown-unknown/release/full_access_key_fallback_base.wasm` + + ```shell + $ ./build.sh + ``` + +3. **Deploy and init a contract** + ```shell + $ near deploy --accountId --wasmFile ./target/wasm32-unknown-unknown/release/full_access_key_fallback_base.wasm --initFunction new --initArgs '{}' + ``` + +## Example of using the contract with full access key fallback plugin +Our plan for this example it is remove the full access key and after that bring it is back. +The keys usually storage at `~/.near-credentials/testnet/.json`. Also let's +choose some operation which only the contract with full access key can done, for example, +transfer money. + +Move ownership rights to the Alice account. +```shell +$ near call owner_set '{"owner": ""}' --accountId +``` + +Check that currently we can transfer the money for example to Alice account +```shell +$ near send 1 +``` + +Now removing the full access key for contract account + +```shell +$ near delete-key "ed25519:ErVTCTvmepb4NDhQ7infTomkLVsd1iTWwLR84FBhV7UC" +``` + +The value of public-key can be found at `~/.near-credentials/testnet/.json`. + +Now check, that now the money transfer will not work: +```shell +$ near send 1 +``` + +And now let's add the key back and check that it will work +```shell +$ near call attach_full_access_key '{"public_key": "ed25519:ErVTCTvmepb4NDhQ7infTomkLVsd1iTWwLR84FBhV7UC"}' --accountId +$ near send 1 +``` + +## Tests running instruction +Tests in `src/lib.rs` contain examples of interaction with a contract. + +For running test: +1. Generate `wasm` file by running `build.sh` script. The target file will be `target/wasm32-unknown-unknown/release/full_access_key_fallback_base.wasm` +2. Run tests `cargo test` + +```shell +$ ./build.sh +$ cargo test +``` + +For tests, we use `workspaces` library and `sandbox` environment for details you can explorer `../near-plugins-test-utils` crate +contract_account. \ No newline at end of file From 10d5e5f1d4da25f7740a3d5e6fef30ab778f1ee9 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Fri, 21 Oct 2022 20:41:37 +0300 Subject: [PATCH 41/68] block_on -> async await --- examples/access_controllable_base/src/lib.rs | 52 +++++------ .../full_access_key_fallback_base/src/lib.rs | 40 ++++---- examples/near-plugins-test-utils/src/lib.rs | 86 +++++++---------- examples/ownable_base/src/lib.rs | 92 +++++++++---------- .../ownable_change_storage_key/src/lib.rs | 8 +- examples/ownable_cross_call/src/lib.rs | 32 +++---- examples/pausable_base/src/lib.rs | 38 ++++---- examples/upgradable_base/Cargo.toml | 10 +- examples/upgradable_base/src/lib.rs | 49 +++++----- 9 files changed, 193 insertions(+), 214 deletions(-) diff --git a/examples/access_controllable_base/src/lib.rs b/examples/access_controllable_base/src/lib.rs index c01419b..c407b2b 100644 --- a/examples/access_controllable_base/src/lib.rs +++ b/examples/access_controllable_base/src/lib.rs @@ -70,55 +70,55 @@ mod tests { const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/access_controllable_base.wasm"; - #[test] - fn base_scenario() { - let (contract_holder, contract) = get_contract(WASM_FILEPATH); - assert!(call!(contract,"new")); + #[tokio::test] + async fn base_scenario() { + let (contract_holder, contract) = get_contract(WASM_FILEPATH).await; + assert!(call!(contract,"new").await); - check_counter(&contract, 0); + check_counter(&contract, 0).await; - assert!(call!(contract, "unprotected")); + assert!(call!(contract, "unprotected").await); - check_counter(&contract, 1); + check_counter(&contract, 1).await; - let alice = get_subaccount(&contract_holder, "alice"); + let alice = get_subaccount(&contract_holder, "alice").await; let is_super_admin: bool = view!(contract, "acl_is_super_admin", &json!({"account_id": alice.id()})); assert!(!is_super_admin); - assert!(!call!(&alice, contract, "level_a_incr")); - check_counter(&contract, 1); + assert!(!call!(&alice, contract, "level_a_incr").await); + check_counter(&contract, 1).await; - assert!(call!(contract, "acl_grant_role", &json!({"role": String::from(UsersGroups::GroupA), "account_id": alice.id()}))); + assert!(call!(contract, "acl_grant_role", &json!({"role": String::from(UsersGroups::GroupA), "account_id": alice.id()})).await); let alice_has_role: bool = view!(contract, "acl_has_role", &json!({"role": String::from(UsersGroups::GroupA), "account_id": alice.id()})); assert!(alice_has_role); - assert!(call!(&alice, contract, "level_a_incr")); + assert!(call!(&alice, contract, "level_a_incr").await); - check_counter(&contract, 2); + check_counter(&contract, 2).await; - let bob = get_subaccount(&contract_holder, "bob"); - assert!(call!(contract, "acl_add_admin", &json!({"role": String::from(UsersGroups::GroupA), "account_id": bob.id()}))); + let bob = get_subaccount(&contract_holder, "bob").await; + assert!(call!(contract, "acl_add_admin", &json!({"role": String::from(UsersGroups::GroupA), "account_id": bob.id()})).await); let bob_is_admin: bool = view!(contract, "acl_is_admin", &json!({"role": String::from(UsersGroups::GroupA), "account_id": bob.id()})); assert!(bob_is_admin); - assert!(!call!(&bob, contract, "level_a_incr")); + assert!(!call!(&bob, contract, "level_a_incr").await); - check_counter(&contract, 2); + check_counter(&contract, 2).await; - assert!(call!(&alice, contract, "level_ab_incr")); - check_counter(&contract, 3); + assert!(call!(&alice, contract, "level_ab_incr").await); + check_counter(&contract, 3).await; - assert!(!call!(&bob, contract, "level_ab_incr")); - check_counter(&contract, 3); + assert!(!call!(&bob, contract, "level_ab_incr").await); + check_counter(&contract, 3).await; - assert!(call!(contract, "acl_grant_role", &json!({"role": String::from(UsersGroups::GroupB), "account_id": bob.id()}))); - assert!(call!(&bob, contract, "level_ab_incr")); - check_counter(&contract, 4); + assert!(call!(contract, "acl_grant_role", &json!({"role": String::from(UsersGroups::GroupB), "account_id": bob.id()})).await); + assert!(call!(&bob, contract, "level_ab_incr").await); + check_counter(&contract, 4).await; - assert!(!call!(&bob, contract, "level_a_incr")); - check_counter(&contract, 4); + assert!(!call!(&bob, contract, "level_a_incr").await); + check_counter(&contract, 4).await; } } diff --git a/examples/full_access_key_fallback_base/src/lib.rs b/examples/full_access_key_fallback_base/src/lib.rs index 254c160..8f2e754 100644 --- a/examples/full_access_key_fallback_base/src/lib.rs +++ b/examples/full_access_key_fallback_base/src/lib.rs @@ -39,44 +39,44 @@ mod tests { const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/full_access_key_fallback_base.wasm"; - #[test] - fn base_scenario() { - let (mut contract_holder, contract) = get_contract_testnet(WASM_FILEPATH); + #[tokio::test] + async fn base_scenario() { + let (mut contract_holder, contract) = get_contract_testnet(WASM_FILEPATH).await; - assert!(call!(contract,"new")); + assert!(call!(contract,"new").await); - check_counter(&contract, 0); + check_counter(&contract, 0).await; - let next_owner = get_subaccount(&contract_holder, "next_owner"); - assert!(call!(contract, "owner_set", &json!({"owner": next_owner.id()}))); + let next_owner = get_subaccount(&contract_holder, "next_owner").await; + assert!(call!(contract, "owner_set", &json!({"owner": next_owner.id()})).await); let current_owner: Option:: = view!(contract, "owner_get"); assert_eq!(current_owner.unwrap().as_str(), next_owner.id().as_str()); - assert!(call!(&contract_holder, contract, "protected_self")); + assert!(call!(&contract_holder, contract, "protected_self").await); - check_counter(&contract, 1); + check_counter(&contract, 1).await; contract_holder.set_secret_key(next_owner.secret_key().clone()); - assert!(call!(&next_owner, contract, "attach_full_access_key", &json!({"public_key": next_owner.secret_key().public_key()}))); + assert!(call!(&next_owner, contract, "attach_full_access_key", &json!({"public_key": next_owner.secret_key().public_key()})).await); - assert!(call!(contract, "protected_self")); + assert!(call!(contract, "protected_self").await); - check_counter(&contract, 2); + check_counter(&contract, 2).await; } - #[test] + #[tokio::test] #[should_panic(expected = "AccessKeyNotFound")] - fn base_panic_on_wrong_key() { - let (mut contract_holder, contract) = get_contract_testnet(WASM_FILEPATH); + async fn base_panic_on_wrong_key() { + let (mut contract_holder, contract) = get_contract_testnet(WASM_FILEPATH).await; - assert!(call!(contract, "new")); - let next_owner = get_subaccount(&contract_holder, "next_owner"); - assert!(call!(contract, "owner_set", &json!({"owner": next_owner.id()}))); + assert!(call!(contract, "new").await); + let next_owner = get_subaccount(&contract_holder, "next_owner").await; + assert!(call!(contract, "owner_set", &json!({"owner": next_owner.id()})).await); - assert!(call!(&contract_holder, contract, "protected_self")); + assert!(call!(&contract_holder, contract, "protected_self").await); contract_holder.set_secret_key(next_owner.secret_key().clone()); - call!(&contract_holder, contract, "protected_self"); + call!(&contract_holder, contract, "protected_self").await; } } diff --git a/examples/near-plugins-test-utils/src/lib.rs b/examples/near-plugins-test-utils/src/lib.rs index 65957d1..9f21063 100644 --- a/examples/near-plugins-test-utils/src/lib.rs +++ b/examples/near-plugins-test-utils/src/lib.rs @@ -1,73 +1,57 @@ use serde_json::json; use near_sdk::ONE_NEAR; -use tokio::runtime::Runtime; use workspaces::{Account, Contract}; -pub fn get_contract(wasm_path: &str) -> (Account, Contract) { - let rt = Runtime::new().unwrap(); - let worker = rt.block_on(workspaces::sandbox()).unwrap(); +pub async fn get_contract(wasm_path: &str) -> (Account, Contract) { + let worker = workspaces::sandbox().await.unwrap(); let owner = worker.root_account().unwrap(); let wasm = std::fs::read(wasm_path).unwrap(); - let contract = rt.block_on(owner.deploy(&wasm)).unwrap().unwrap(); + let contract = owner.deploy(&wasm).await.unwrap().unwrap(); (owner, contract) } -pub fn view(contract: &Contract, method_name: &str, args: &serde_json::Value) -> Vec { - let rt = Runtime::new().unwrap(); - - rt.block_on( - contract.view(method_name, - args.to_string().into_bytes()) - ).unwrap().result +pub async fn view(contract: &Contract, method_name: &str, args: &serde_json::Value) -> Vec { + contract.view(method_name, + args.to_string().into_bytes()).await.unwrap().result } -pub fn call_arg(contract: &Contract, method_name: &str, args: &serde_json::Value) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on( - contract - .call(method_name) - .args_json(args) - .max_gas() - .transact(), - ) - .unwrap() - .is_success() +pub async fn call_arg(contract: &Contract, method_name: &str, args: &serde_json::Value) -> bool { + contract + .call(method_name) + .args_json(args) + .max_gas() + .transact() + .await + .unwrap() + .is_success() } -pub fn call_by_with_arg(account: &Account, contract: &Contract, method_name: &str, args: &serde_json::Value) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on( - account.call(contract.id(), method_name) - .args_json(args) - .max_gas() - .transact() - ).unwrap().is_success() +pub async fn call_by_with_arg(account: &Account, contract: &Contract, method_name: &str, args: &serde_json::Value) -> bool { + account.call(contract.id(), method_name) + .args_json(args) + .max_gas() + .transact() + .await.unwrap().is_success() } -pub fn get_subaccount(account: &Account, new_account_name: &str) -> Account { - let rt = Runtime::new().unwrap(); - - rt.block_on( - account - .create_subaccount(new_account_name) - .initial_balance(ONE_NEAR) - .transact(), - ) - .unwrap() - .unwrap() +pub async fn get_subaccount(account: &Account, new_account_name: &str) -> Account { + account + .create_subaccount(new_account_name) + .initial_balance(ONE_NEAR) + .transact() + .await + .unwrap() + .unwrap() } -pub fn get_contract_testnet(wasm_file: &str) -> (Account, Contract) { - let rt = Runtime::new().unwrap(); - let worker = rt.block_on(workspaces::testnet()).unwrap(); +pub async fn get_contract_testnet(wasm_file: &str) -> (Account, Contract) { + let worker = workspaces::testnet().await.unwrap(); let wasm = std::fs::read(wasm_file).unwrap(); - let contract: Contract = rt.block_on(worker.dev_deploy(&wasm)).unwrap(); + let contract: Contract = worker.dev_deploy(&wasm).await.unwrap(); let owner = contract.as_account(); @@ -77,10 +61,10 @@ pub fn get_contract_testnet(wasm_file: &str) -> (Account, Contract) { #[macro_export] macro_rules! view { ($contract:ident, $method_name:literal) => { - serde_json::from_slice(&view(&$contract, $method_name, &json!({}))).unwrap() + serde_json::from_slice(&view(&$contract, $method_name, &json!({})).await).unwrap() }; ($contract:ident, $method_name:literal, $args:expr) => { - serde_json::from_slice(&view(&$contract, $method_name, $args)).unwrap() + serde_json::from_slice(&view(&$contract, $method_name, $args).await).unwrap() }; } @@ -100,7 +84,7 @@ macro_rules! call { }; } -pub fn check_counter(contract: &Contract, expect_counter: u64) { +pub async fn check_counter(contract: &Contract, expect_counter: u64) { let counter: u64 = view!(contract, "get_counter"); assert_eq!(counter, expect_counter); } \ No newline at end of file diff --git a/examples/ownable_base/src/lib.rs b/examples/ownable_base/src/lib.rs index d40fd3b..d22ecc5 100644 --- a/examples/ownable_base/src/lib.rs +++ b/examples/ownable_base/src/lib.rs @@ -57,83 +57,83 @@ mod tests { const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/ownable_base.wasm"; - #[test] - fn base_scenario() { - let (contract_holder, contract) = get_contract(WASM_FILEPATH); + #[tokio::test] + async fn base_scenario() { + let (contract_holder, contract) = get_contract(WASM_FILEPATH).await; - assert!(call!(contract, "new")); + assert!(call!(contract, "new").await); let current_owner: Option:: = view!(contract, "owner_get"); assert_eq!(current_owner.unwrap().as_str(), contract_holder.id().as_str()); - check_counter(&contract, 0); + check_counter(&contract, 0).await; - assert!(call!(contract, "protected")); - assert!(call!(contract, "protected_owner")); - assert!(call!(contract, "protected_self")); - assert!(call!(contract, "unprotected")); + assert!(call!(contract, "protected").await); + assert!(call!(contract, "protected_owner").await); + assert!(call!(contract, "protected_self").await); + assert!(call!(contract, "unprotected").await); - check_counter(&contract, 4); + check_counter(&contract, 4).await; - let next_owner = get_subaccount(&contract_holder, "next_owner"); - assert!(!call!(&next_owner, contract, "protected")); - assert!(!call!(&next_owner, contract, "protected_owner")); - assert!(!call!(&next_owner, contract, "protected_self")); - assert!(call!(&next_owner, contract, "unprotected")); + let next_owner = get_subaccount(&contract_holder, "next_owner").await; + assert!(!call!(&next_owner, contract, "protected").await); + assert!(!call!(&next_owner, contract, "protected_owner").await); + assert!(!call!(&next_owner, contract, "protected_self").await); + assert!(call!(&next_owner, contract, "unprotected").await); - check_counter(&contract, 5); + check_counter(&contract, 5).await; - assert!(call_arg(&contract, "owner_set", &json!({"owner": next_owner.id()}))); + assert!(call_arg(&contract, "owner_set", &json!({"owner": next_owner.id()})).await); let current_owner: Option:: = view!(contract, "owner_get"); assert_ne!(current_owner.clone().unwrap().as_str(), contract_holder.id().as_str()); assert_eq!(current_owner.unwrap().as_str(), next_owner.id().as_str()); - assert!(call!(&next_owner, contract, "protected")); - assert!(call!(&next_owner, contract, "protected_owner")); - assert!(!call!(&next_owner, contract, "protected_self")); - assert!(call!(&next_owner, contract, "unprotected")); + assert!(call!(&next_owner, contract, "protected").await); + assert!(call!(&next_owner, contract, "protected_owner").await); + assert!(!call!(&next_owner, contract, "protected_self").await); + assert!(call!(&next_owner, contract, "unprotected").await); - check_counter(&contract, 8); + check_counter(&contract, 8).await; - assert!(call!(contract, "protected")); - assert!(!call!(contract, "protected_owner")); - assert!(call!(contract, "protected_self")); - assert!(call!(contract, "unprotected")); + assert!(call!(contract, "protected").await); + assert!(!call!(contract, "protected_owner").await); + assert!(call!(contract, "protected_self").await); + assert!(call!(contract, "unprotected").await); check_counter(&contract, 11); } - #[test] - fn null_owner() { - let (_, contract) = get_contract(WASM_FILEPATH); - assert!(call!(contract,"new")); + #[tokio::test] + async fn null_owner() { + let (_, contract) = get_contract(WASM_FILEPATH).await; + assert!(call!(contract,"new").await); - assert!(call!(contract, "owner_set", &json!({"owner": Option::::None}))); + assert!(call!(contract, "owner_set", &json!({"owner": Option::::None})).await); let current_owner: Option:: = view!(contract, "owner_get"); assert_eq!(current_owner, None); - assert!(call!(contract, "protected")); - assert!(!call!(contract, "protected_owner")); - assert!(call!(contract, "protected_self")); - assert!(call!(contract, "unprotected")); + assert!(call!(contract, "protected").await); + assert!(!call!(contract, "protected_owner").await); + assert!(call!(contract, "protected_self").await); + assert!(call!(contract, "unprotected").await); - check_counter(&contract, 3); + check_counter(&contract, 3).await; - assert!(call!(contract, "owner_set", &json!({"owner": contract.id().as_str()}))); - assert!(call!(contract, "protected")); - assert!(call!(contract, "protected_owner")); - assert!(call!(contract, "protected_self")); - assert!(call!(contract, "unprotected")); + assert!(call!(contract, "owner_set", &json!({"owner": contract.id().as_str()})).await); + assert!(call!(contract, "protected").await); + assert!(call!(contract, "protected_owner").await); + assert!(call!(contract, "protected_self").await); + assert!(call!(contract, "unprotected").await); - check_counter(&contract, 7); + check_counter(&contract, 7).await; } - #[test] - fn check_owner_storage_key() { - let (_, contract) = get_contract(WASM_FILEPATH); - assert!(call!(contract,"new")); + #[tokio::test] + async fn check_owner_storage_key() { + let (_, contract) = get_contract(WASM_FILEPATH).await; + assert!(call!(contract,"new").await); let owner_storage_key: Vec = view!(contract, "owner_storage_key"); assert_eq!(owner_storage_key, "__OWNER__".as_bytes().to_vec()); diff --git a/examples/ownable_change_storage_key/src/lib.rs b/examples/ownable_change_storage_key/src/lib.rs index 414d940..194caa0 100644 --- a/examples/ownable_change_storage_key/src/lib.rs +++ b/examples/ownable_change_storage_key/src/lib.rs @@ -56,10 +56,10 @@ mod tests { const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/ownable_change_storage_key.wasm"; - #[test] - fn check_owner_storage_key() { - let (_, contract) = get_contract(WASM_FILEPATH); - assert!(call!(contract,"new")); + #[tokio::test] + async fn check_owner_storage_key() { + let (_, contract) = get_contract(WASM_FILEPATH).await; + assert!(call!(contract,"new").await); let owner_storage_key: Vec = view!(contract, "owner_storage_key"); assert_eq!(owner_storage_key, "new_storage_key".as_bytes().to_vec()); diff --git a/examples/ownable_cross_call/src/lib.rs b/examples/ownable_cross_call/src/lib.rs index 8ee43c3..7d24790 100644 --- a/examples/ownable_cross_call/src/lib.rs +++ b/examples/ownable_cross_call/src/lib.rs @@ -83,29 +83,29 @@ mod tests { const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/ownable_cross_call.wasm"; - #[test] - fn base_scenario() { - let (contract_holder, contract) = get_contract(WASM_FILEPATH); + #[tokio::test] + async fn base_scenario() { + let (contract_holder, contract) = get_contract(WASM_FILEPATH).await; - assert!(call!(contract,"new")); - let next_owner = get_subaccount(&contract_holder, "next_owner"); - assert!(call!(contract, "owner_set", &json!({"owner": next_owner.id()}))); + assert!(call!(contract,"new").await); + let next_owner = get_subaccount(&contract_holder, "next_owner").await; + assert!(call!(contract, "owner_set", &json!({"owner": next_owner.id()})).await); let current_owner: Option:: = view!(contract, "owner_get"); assert_ne!(current_owner.clone().unwrap().as_str(), contract_holder.id().as_str()); assert_eq!(current_owner.unwrap().as_str(), next_owner.id().as_str()); - assert!(call!(&next_owner, contract, "cross_call_owner_self")); - assert!(call!(&next_owner, contract, "cross_call_owner_owner")); - assert!(!call!(&next_owner, contract, "cross_call_self_self")); - assert!(!call!(&next_owner, contract, "cross_call_self_owner")); + assert!(call!(&next_owner, contract, "cross_call_owner_self").await); + assert!(call!(&next_owner, contract, "cross_call_owner_owner").await); + assert!(!call!(&next_owner, contract, "cross_call_self_self").await); + assert!(!call!(&next_owner, contract, "cross_call_self_owner").await); - check_counter(&contract, 1); + check_counter(&contract, 1).await; - assert!(!call!(contract, "cross_call_owner_self")); - assert!(!call!(contract, "cross_call_owner_owner")); - assert!(call!(contract, "cross_call_self_self")); - assert!(call!(contract, "cross_call_self_owner")); + assert!(!call!(contract, "cross_call_owner_self").await); + assert!(!call!(contract, "cross_call_owner_owner").await); + assert!(call!(contract, "cross_call_self_self").await); + assert!(call!(contract, "cross_call_self_owner").await); - check_counter(&contract, 2); + check_counter(&contract, 2).await; } } diff --git a/examples/pausable_base/src/lib.rs b/examples/pausable_base/src/lib.rs index 4ab7687..10be0b1 100644 --- a/examples/pausable_base/src/lib.rs +++ b/examples/pausable_base/src/lib.rs @@ -76,36 +76,36 @@ mod tests { const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/pausable_base.wasm"; - #[test] - fn base_scenario() { - let (contract_holder, contract) = get_contract(WASM_FILEPATH); + #[tokio::test] + async fn base_scenario() { + let (contract_holder, contract) = get_contract(WASM_FILEPATH).await; - assert!(call!(contract,"new")); + assert!(call!(contract,"new").await); - let next_owner = get_subaccount(&contract_holder, "next_owner"); - assert!(call!(contract, "owner_set", &json!({"owner": next_owner.id()}))); + let next_owner = get_subaccount(&contract_holder, "next_owner").await; + assert!(call!(contract, "owner_set", &json!({"owner": next_owner.id()})).await); let current_owner: Option:: = view!(contract, "owner_get"); assert_eq!(current_owner.unwrap().as_str(), next_owner.id().as_str()); - let alice = get_subaccount(&contract_holder, "alice"); + let alice = get_subaccount(&contract_holder, "alice").await; - assert!(call!(&alice, contract, "increase_1")); - check_counter(&contract, 1); + assert!(call!(&alice, contract, "increase_1").await); + check_counter(&contract, 1).await; - assert!(!call!(&alice, contract, "pa_pause_feature", &json!({"key": "increase_1"}))); - assert!(call!(&next_owner, contract, "pa_pause_feature", &json!({"key": "increase_1"}))); + assert!(!call!(&alice, contract, "pa_pause_feature", &json!({"key": "increase_1"})).await); + assert!(call!(&next_owner, contract, "pa_pause_feature", &json!({"key": "increase_1"})).await); - assert!(!call!(&alice, contract, "increase_1")); - check_counter(&contract, 1); + assert!(!call!(&alice, contract, "increase_1").await); + check_counter(&contract, 1).await; - assert!(!call!(&next_owner, contract, "increase_1")); - check_counter(&contract, 1); + assert!(!call!(&next_owner, contract, "increase_1").await); + check_counter(&contract, 1).await; - assert!(!call!(&contract_holder, contract, "pa_unpause_feature", &json!({"key": "increase_1"}))); - assert!(call!(&next_owner, contract, "pa_unpause_feature", &json!({"key": "increase_1"}))); + assert!(!call!(&contract_holder, contract, "pa_unpause_feature", &json!({"key": "increase_1"})).await); + assert!(call!(&next_owner, contract, "pa_unpause_feature", &json!({"key": "increase_1"})).await); - assert!(call!(&alice, contract, "increase_1")); + assert!(call!(&alice, contract, "increase_1").await); - check_counter(&contract, 2); + check_counter(&contract, 2).await; } } diff --git a/examples/upgradable_base/Cargo.toml b/examples/upgradable_base/Cargo.toml index 8f11d50..92f38ef 100644 --- a/examples/upgradable_base/Cargo.toml +++ b/examples/upgradable_base/Cargo.toml @@ -4,10 +4,9 @@ version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[[bin]] -name = "up_stage_code" -path = "src/up_stage_code.rs" +# [[bin]] +# name = "up_stage_code" +# path = "src/up_stage_code.rs" [lib] crate-type = ["cdylib", "rlib"] @@ -17,9 +16,10 @@ near-sdk = "4.0.0" near-plugins = { path = "../../near-plugins" } near-plugins-derive = { path = "../../near-plugins-derive" } borsh = "0.9.3" + +[dev-dependencies] near-primitives = { version = "0.14.0" } workspaces = "0.6" tokio = { version = "1.1", features = ["rt", "macros"] } serde_json = "1.0.74" near-plugins-test-utils = { path = "../near-plugins-test-utils" } - diff --git a/examples/upgradable_base/src/lib.rs b/examples/upgradable_base/src/lib.rs index dae0ca9..a6d965a 100644 --- a/examples/upgradable_base/src/lib.rs +++ b/examples/upgradable_base/src/lib.rs @@ -32,57 +32,52 @@ impl Counter1 { mod tests { use serde_json::json; use workspaces::{Account, Contract}; - use tokio::runtime::Runtime; use near_plugins_test_utils::*; const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/upgradable_base.wasm"; const WASM_FILEPATH_SECOND: &str = "../upgradable_base_second/target/wasm32-unknown-unknown/release/upgradable_base_second.wasm"; - fn get_contract() -> (Account, Contract) { - let rt = Runtime::new().unwrap(); - let worker = rt.block_on(workspaces::testnet()).unwrap(); + async fn get_contract() -> (Account, Contract) { + let worker = workspaces::testnet().await.unwrap(); - let owner = rt.block_on(worker.dev_create_account()).unwrap(); + let owner = worker.dev_create_account().await.unwrap(); let wasm = std::fs::read(WASM_FILEPATH).unwrap(); - let contract = rt.block_on(owner.deploy(&wasm)).unwrap().unwrap(); + let contract = owner.deploy(&wasm).await.unwrap().unwrap(); (owner, contract) } - fn call_borsh_arg(contract: &Contract, method_name: &str, args: Vec) -> bool { - let rt = Runtime::new().unwrap(); - - rt.block_on( - contract.call(method_name) + async fn call_borsh_arg(contract: &Contract, method_name: &str, args: Vec) -> bool { + contract.call(method_name) .args_borsh(args) .max_gas() .transact() - ).unwrap().is_success() + .await.unwrap().is_success() } //https://docs.near.org/sdk/rust/promises/deploy-contract - #[test] - fn base_scenario() { - let (_, contract) = get_contract(); - assert!(call!(contract,"new")); + #[tokio::test] + async fn base_scenario() { + let (_, contract) = get_contract().await; + assert!(call!(contract,"new").await); - assert!(call!(contract, "inc1")); - check_counter(&contract, 1); + assert!(call!(contract, "inc1").await); + check_counter(&contract, 1).await; - assert!(!call!(contract, "inc2")); - check_counter(&contract, 1); + assert!(!call!(contract, "inc2").await); + check_counter(&contract, 1).await; let wasm = std::fs::read(WASM_FILEPATH_SECOND).unwrap(); - assert!(call_borsh_arg(&contract, "up_stage_code", wasm)); - assert!(call!(contract, "up_deploy_code")); - check_counter(&contract, 1); + assert!(call_borsh_arg(&contract, "up_stage_code", wasm).await); + assert!(call!(contract, "up_deploy_code").await); + check_counter(&contract, 1).await; - assert!(!call!(contract, "inc1")); - check_counter(&contract, 1); + assert!(!call!(contract, "inc1").await); + check_counter(&contract, 1).await; - assert!(call!(contract, "inc2")); - check_counter(&contract, 3); + assert!(call!(contract, "inc2").await); + check_counter(&contract, 3).await; } } From 9884eb42c76317a202eadb1cf0e1cc6eaf46c81d Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Mon, 24 Oct 2022 12:18:22 +0300 Subject: [PATCH 42/68] use workspace for examples --- examples/Cargo.toml | 14 ++++++++++++++ .../README.md | 0 .../access_control_role_base/Cargo.toml | 4 ++-- .../access_control_role_base/src/lib.rs | 0 .../access_controllable_base/Cargo.toml | 6 +++--- .../access_controllable_base/build.sh | 0 .../access_controllable_base/src/lib.rs | 0 .../README.md | 0 .../full_access_key_fallback_base/Cargo.toml | 6 +++--- .../full_access_key_fallback_base/build.sh | 0 .../full_access_key_fallback_base/src/lib.rs | 0 examples/near-plugins-test-utils/Cargo.toml | 2 +- .../{ownable_base => ownable-examples}/README.md | 0 .../{ => ownable-examples}/ownable_base/Cargo.toml | 6 +++--- .../{ => ownable-examples}/ownable_base/build.sh | 0 .../{ => ownable-examples}/ownable_base/src/lib.rs | 0 .../ownable_change_storage_key/Cargo.toml | 6 +++--- .../ownable_change_storage_key/build.sh | 0 .../ownable_change_storage_key/src/lib.rs | 0 .../ownable_cross_call/Cargo.toml | 6 +++--- .../ownable_cross_call/build.sh | 0 .../ownable_cross_call/src/lib.rs | 0 .../{pausable_base => pausable-examples}/README.md | 0 .../pausable_base/Cargo.toml | 6 +++--- .../{ => pausable-examples}/pausable_base/build.sh | 0 .../pausable_base/src/lib.rs | 0 .../README.md | 0 .../upgradable_base/Cargo.toml | 6 +++--- .../upgradable_base/build.sh | 0 .../upgradable_base/src/lib.rs | 0 .../upgradable_base/src/up_stage_code.rs | 0 .../upgradable_base_second/Cargo.toml | 4 ++-- .../upgradable_base_second/build.sh | 0 .../upgradable_base_second/src/lib.rs | 0 34 files changed, 40 insertions(+), 26 deletions(-) create mode 100644 examples/Cargo.toml rename examples/{access_controllable_base => access-controllable-examples}/README.md (100%) rename examples/{ => access-controllable-examples}/access_control_role_base/Cargo.toml (69%) rename examples/{ => access-controllable-examples}/access_control_role_base/src/lib.rs (100%) rename examples/{ => access-controllable-examples}/access_controllable_base/Cargo.toml (70%) rename examples/{ => access-controllable-examples}/access_controllable_base/build.sh (100%) rename examples/{ => access-controllable-examples}/access_controllable_base/src/lib.rs (100%) rename examples/{full_access_key_fallback_base => full-access-key-fallback-examples}/README.md (100%) rename examples/{ => full-access-key-fallback-examples}/full_access_key_fallback_base/Cargo.toml (69%) rename examples/{ => full-access-key-fallback-examples}/full_access_key_fallback_base/build.sh (100%) rename examples/{ => full-access-key-fallback-examples}/full_access_key_fallback_base/src/lib.rs (100%) rename examples/{ownable_base => ownable-examples}/README.md (100%) rename examples/{ => ownable-examples}/ownable_base/Cargo.toml (68%) rename examples/{ => ownable-examples}/ownable_base/build.sh (100%) rename examples/{ => ownable-examples}/ownable_base/src/lib.rs (100%) rename examples/{ => ownable-examples}/ownable_change_storage_key/Cargo.toml (69%) rename examples/{ => ownable-examples}/ownable_change_storage_key/build.sh (100%) rename examples/{ => ownable-examples}/ownable_change_storage_key/src/lib.rs (100%) rename examples/{ => ownable-examples}/ownable_cross_call/Cargo.toml (68%) rename examples/{ => ownable-examples}/ownable_cross_call/build.sh (100%) rename examples/{ => ownable-examples}/ownable_cross_call/src/lib.rs (100%) rename examples/{pausable_base => pausable-examples}/README.md (100%) rename examples/{ => pausable-examples}/pausable_base/Cargo.toml (68%) rename examples/{ => pausable-examples}/pausable_base/build.sh (100%) rename examples/{ => pausable-examples}/pausable_base/src/lib.rs (100%) rename examples/{upgradable_base => upgradable-examples}/README.md (100%) rename examples/{ => upgradable-examples}/upgradable_base/Cargo.toml (72%) rename examples/{ => upgradable-examples}/upgradable_base/build.sh (100%) rename examples/{ => upgradable-examples}/upgradable_base/src/lib.rs (100%) rename examples/{ => upgradable-examples}/upgradable_base/src/up_stage_code.rs (100%) rename examples/{ => upgradable-examples}/upgradable_base_second/Cargo.toml (78%) rename examples/{ => upgradable-examples}/upgradable_base_second/build.sh (100%) rename examples/{ => upgradable-examples}/upgradable_base_second/src/lib.rs (100%) diff --git a/examples/Cargo.toml b/examples/Cargo.toml new file mode 100644 index 0000000..cb68873 --- /dev/null +++ b/examples/Cargo.toml @@ -0,0 +1,14 @@ +[workspace] + +members = [ + "access-controllable-examples/access_controllable_base", + "access-controllable-examples/access_control_role_base", + "full-access-key-fallback-examples/full_access_key_fallback_base", + "near-plugins-test-utils", + "ownable-examples/ownable_base", + "ownable-examples/ownable_change_storage_key", + "ownable-examples/ownable_cross_call", + "pausable-examples/pausable_base", + "upgradable-examples/upgradable_base", + "upgradable-examples/upgradable_base_second", +] diff --git a/examples/access_controllable_base/README.md b/examples/access-controllable-examples/README.md similarity index 100% rename from examples/access_controllable_base/README.md rename to examples/access-controllable-examples/README.md diff --git a/examples/access_control_role_base/Cargo.toml b/examples/access-controllable-examples/access_control_role_base/Cargo.toml similarity index 69% rename from examples/access_control_role_base/Cargo.toml rename to examples/access-controllable-examples/access_control_role_base/Cargo.toml index e000231..13e1b89 100644 --- a/examples/access_control_role_base/Cargo.toml +++ b/examples/access-controllable-examples/access_control_role_base/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" crate-type = ["cdylib", "rlib"] [dependencies] -near-plugins = { path = "../../near-plugins" } -near-plugins-derive = { path = "../../near-plugins-derive" } +near-plugins = { path = "../../../near-plugins" } +near-plugins-derive = { path = "../../../near-plugins-derive" } bitflags = "1.3.2" borsh = "*" diff --git a/examples/access_control_role_base/src/lib.rs b/examples/access-controllable-examples/access_control_role_base/src/lib.rs similarity index 100% rename from examples/access_control_role_base/src/lib.rs rename to examples/access-controllable-examples/access_control_role_base/src/lib.rs diff --git a/examples/access_controllable_base/Cargo.toml b/examples/access-controllable-examples/access_controllable_base/Cargo.toml similarity index 70% rename from examples/access_controllable_base/Cargo.toml rename to examples/access-controllable-examples/access_controllable_base/Cargo.toml index e1b5030..5223ccc 100644 --- a/examples/access_controllable_base/Cargo.toml +++ b/examples/access-controllable-examples/access_controllable_base/Cargo.toml @@ -10,8 +10,8 @@ crate-type = ["cdylib", "rlib"] [dependencies] near-sdk = "4.0.0" -near-plugins = { path = "../../near-plugins" } -near-plugins-derive = { path = "../../near-plugins-derive" } +near-plugins = { path = "../../../near-plugins" } +near-plugins-derive = { path = "../../../near-plugins-derive" } borsh = "0.9.3" bitflags = "*" @@ -20,5 +20,5 @@ near-primitives = "0.14.0" workspaces = "0.6" tokio = { version = "1.1", features = ["rt", "macros"] } serde_json = "1.0.74" -near-plugins-test-utils = { path = "../near-plugins-test-utils" } +near-plugins-test-utils = { path = "../../near-plugins-test-utils" } diff --git a/examples/access_controllable_base/build.sh b/examples/access-controllable-examples/access_controllable_base/build.sh similarity index 100% rename from examples/access_controllable_base/build.sh rename to examples/access-controllable-examples/access_controllable_base/build.sh diff --git a/examples/access_controllable_base/src/lib.rs b/examples/access-controllable-examples/access_controllable_base/src/lib.rs similarity index 100% rename from examples/access_controllable_base/src/lib.rs rename to examples/access-controllable-examples/access_controllable_base/src/lib.rs diff --git a/examples/full_access_key_fallback_base/README.md b/examples/full-access-key-fallback-examples/README.md similarity index 100% rename from examples/full_access_key_fallback_base/README.md rename to examples/full-access-key-fallback-examples/README.md diff --git a/examples/full_access_key_fallback_base/Cargo.toml b/examples/full-access-key-fallback-examples/full_access_key_fallback_base/Cargo.toml similarity index 69% rename from examples/full_access_key_fallback_base/Cargo.toml rename to examples/full-access-key-fallback-examples/full_access_key_fallback_base/Cargo.toml index 2f4a21e..eb14035 100644 --- a/examples/full_access_key_fallback_base/Cargo.toml +++ b/examples/full-access-key-fallback-examples/full_access_key_fallback_base/Cargo.toml @@ -10,8 +10,8 @@ crate-type = ["cdylib", "rlib"] [dependencies] near-sdk = "4.0.0" -near-plugins = { path = "../../near-plugins" } -near-plugins-derive = { path = "../../near-plugins-derive" } +near-plugins = { path = "../../../near-plugins" } +near-plugins-derive = { path = "../../../near-plugins-derive" } borsh = "0.9.3" [dev-dependencies] @@ -19,4 +19,4 @@ near-primitives = "0.14.0" workspaces = "0.6" tokio = { version = "1.1", features = ["rt", "macros"] } serde_json = "1.0.74" -near-plugins-test-utils = { path = "../near-plugins-test-utils" } +near-plugins-test-utils = { path = "../../near-plugins-test-utils" } diff --git a/examples/full_access_key_fallback_base/build.sh b/examples/full-access-key-fallback-examples/full_access_key_fallback_base/build.sh similarity index 100% rename from examples/full_access_key_fallback_base/build.sh rename to examples/full-access-key-fallback-examples/full_access_key_fallback_base/build.sh diff --git a/examples/full_access_key_fallback_base/src/lib.rs b/examples/full-access-key-fallback-examples/full_access_key_fallback_base/src/lib.rs similarity index 100% rename from examples/full_access_key_fallback_base/src/lib.rs rename to examples/full-access-key-fallback-examples/full_access_key_fallback_base/src/lib.rs diff --git a/examples/near-plugins-test-utils/Cargo.toml b/examples/near-plugins-test-utils/Cargo.toml index 5baf7ac..cb19282 100644 --- a/examples/near-plugins-test-utils/Cargo.toml +++ b/examples/near-plugins-test-utils/Cargo.toml @@ -14,4 +14,4 @@ borsh = "0.9.3" near-primitives = "0.14.0" workspaces = "0.6" tokio = { version = "1.1", features = ["rt", "macros"] } -serde_json = "1.0.74" \ No newline at end of file +serde_json = "1.0.74" diff --git a/examples/ownable_base/README.md b/examples/ownable-examples/README.md similarity index 100% rename from examples/ownable_base/README.md rename to examples/ownable-examples/README.md diff --git a/examples/ownable_base/Cargo.toml b/examples/ownable-examples/ownable_base/Cargo.toml similarity index 68% rename from examples/ownable_base/Cargo.toml rename to examples/ownable-examples/ownable_base/Cargo.toml index 93735a1..8201bda 100644 --- a/examples/ownable_base/Cargo.toml +++ b/examples/ownable-examples/ownable_base/Cargo.toml @@ -10,8 +10,8 @@ crate-type = ["cdylib", "rlib"] [dependencies] near-sdk = "4.0.0" -near-plugins = { path = "../../near-plugins" } -near-plugins-derive = { path = "../../near-plugins-derive" } +near-plugins = { path = "../../../near-plugins" } +near-plugins-derive = { path = "../../../near-plugins-derive" } borsh = "0.9.3" [dev-dependencies] @@ -19,6 +19,6 @@ near-primitives = "0.14.0" workspaces = "0.6" tokio = { version = "1.1", features = ["rt", "macros"] } serde_json = "1.0.74" -near-plugins-test-utils = { path = "../near-plugins-test-utils" } +near-plugins-test-utils = { path = "../../near-plugins-test-utils" } diff --git a/examples/ownable_base/build.sh b/examples/ownable-examples/ownable_base/build.sh similarity index 100% rename from examples/ownable_base/build.sh rename to examples/ownable-examples/ownable_base/build.sh diff --git a/examples/ownable_base/src/lib.rs b/examples/ownable-examples/ownable_base/src/lib.rs similarity index 100% rename from examples/ownable_base/src/lib.rs rename to examples/ownable-examples/ownable_base/src/lib.rs diff --git a/examples/ownable_change_storage_key/Cargo.toml b/examples/ownable-examples/ownable_change_storage_key/Cargo.toml similarity index 69% rename from examples/ownable_change_storage_key/Cargo.toml rename to examples/ownable-examples/ownable_change_storage_key/Cargo.toml index a444172..8d39ab1 100644 --- a/examples/ownable_change_storage_key/Cargo.toml +++ b/examples/ownable-examples/ownable_change_storage_key/Cargo.toml @@ -10,8 +10,8 @@ crate-type = ["cdylib", "rlib"] [dependencies] near-sdk = "4.0.0" -near-plugins = { path = "../../near-plugins" } -near-plugins-derive = { path = "../../near-plugins-derive" } +near-plugins = { path = "../../../near-plugins" } +near-plugins-derive = { path = "../../../near-plugins-derive" } borsh = "0.9.3" [dev-dependencies] @@ -19,5 +19,5 @@ near-primitives = "0.14.0" workspaces = "0.6" tokio = { version = "1.1", features = ["rt", "macros"] } serde_json = "1.0.74" -near-plugins-test-utils = { path = "../near-plugins-test-utils" } +near-plugins-test-utils = { path = "../../near-plugins-test-utils" } diff --git a/examples/ownable_change_storage_key/build.sh b/examples/ownable-examples/ownable_change_storage_key/build.sh similarity index 100% rename from examples/ownable_change_storage_key/build.sh rename to examples/ownable-examples/ownable_change_storage_key/build.sh diff --git a/examples/ownable_change_storage_key/src/lib.rs b/examples/ownable-examples/ownable_change_storage_key/src/lib.rs similarity index 100% rename from examples/ownable_change_storage_key/src/lib.rs rename to examples/ownable-examples/ownable_change_storage_key/src/lib.rs diff --git a/examples/ownable_cross_call/Cargo.toml b/examples/ownable-examples/ownable_cross_call/Cargo.toml similarity index 68% rename from examples/ownable_cross_call/Cargo.toml rename to examples/ownable-examples/ownable_cross_call/Cargo.toml index e7a99a7..e6096ab 100644 --- a/examples/ownable_cross_call/Cargo.toml +++ b/examples/ownable-examples/ownable_cross_call/Cargo.toml @@ -10,8 +10,8 @@ crate-type = ["cdylib", "rlib"] [dependencies] near-sdk = "4.0.0" -near-plugins = { path = "../../near-plugins" } -near-plugins-derive = { path = "../../near-plugins-derive" } +near-plugins = { path = "../../../near-plugins" } +near-plugins-derive = { path = "../../../near-plugins-derive" } borsh = "0.9.3" [dev-dependencies] @@ -19,5 +19,5 @@ near-primitives = "0.14.0" workspaces = "0.6" tokio = { version = "1.1", features = ["rt", "macros"] } serde_json = "1.0.74" -near-plugins-test-utils = { path = "../near-plugins-test-utils" } +near-plugins-test-utils = { path = "../../near-plugins-test-utils" } diff --git a/examples/ownable_cross_call/build.sh b/examples/ownable-examples/ownable_cross_call/build.sh similarity index 100% rename from examples/ownable_cross_call/build.sh rename to examples/ownable-examples/ownable_cross_call/build.sh diff --git a/examples/ownable_cross_call/src/lib.rs b/examples/ownable-examples/ownable_cross_call/src/lib.rs similarity index 100% rename from examples/ownable_cross_call/src/lib.rs rename to examples/ownable-examples/ownable_cross_call/src/lib.rs diff --git a/examples/pausable_base/README.md b/examples/pausable-examples/README.md similarity index 100% rename from examples/pausable_base/README.md rename to examples/pausable-examples/README.md diff --git a/examples/pausable_base/Cargo.toml b/examples/pausable-examples/pausable_base/Cargo.toml similarity index 68% rename from examples/pausable_base/Cargo.toml rename to examples/pausable-examples/pausable_base/Cargo.toml index 62641f3..b42375c 100644 --- a/examples/pausable_base/Cargo.toml +++ b/examples/pausable-examples/pausable_base/Cargo.toml @@ -10,8 +10,8 @@ crate-type = ["cdylib", "rlib"] [dependencies] near-sdk = "4.0.0" -near-plugins = { path = "../../near-plugins" } -near-plugins-derive = { path = "../../near-plugins-derive" } +near-plugins = { path = "../../../near-plugins" } +near-plugins-derive = { path = "../../../near-plugins-derive" } borsh = "0.9.3" [dev-dependencies] @@ -19,6 +19,6 @@ near-primitives = "0.14.0" workspaces = "0.6" tokio = { version = "1.1", features = ["rt", "macros"] } serde_json = "1.0.74" -near-plugins-test-utils = { path = "../near-plugins-test-utils" } +near-plugins-test-utils = { path = "../../near-plugins-test-utils" } diff --git a/examples/pausable_base/build.sh b/examples/pausable-examples/pausable_base/build.sh similarity index 100% rename from examples/pausable_base/build.sh rename to examples/pausable-examples/pausable_base/build.sh diff --git a/examples/pausable_base/src/lib.rs b/examples/pausable-examples/pausable_base/src/lib.rs similarity index 100% rename from examples/pausable_base/src/lib.rs rename to examples/pausable-examples/pausable_base/src/lib.rs diff --git a/examples/upgradable_base/README.md b/examples/upgradable-examples/README.md similarity index 100% rename from examples/upgradable_base/README.md rename to examples/upgradable-examples/README.md diff --git a/examples/upgradable_base/Cargo.toml b/examples/upgradable-examples/upgradable_base/Cargo.toml similarity index 72% rename from examples/upgradable_base/Cargo.toml rename to examples/upgradable-examples/upgradable_base/Cargo.toml index 92f38ef..2605fd8 100644 --- a/examples/upgradable_base/Cargo.toml +++ b/examples/upgradable-examples/upgradable_base/Cargo.toml @@ -13,8 +13,8 @@ crate-type = ["cdylib", "rlib"] [dependencies] near-sdk = "4.0.0" -near-plugins = { path = "../../near-plugins" } -near-plugins-derive = { path = "../../near-plugins-derive" } +near-plugins = { path = "../../../near-plugins" } +near-plugins-derive = { path = "../../../near-plugins-derive" } borsh = "0.9.3" [dev-dependencies] @@ -22,4 +22,4 @@ near-primitives = { version = "0.14.0" } workspaces = "0.6" tokio = { version = "1.1", features = ["rt", "macros"] } serde_json = "1.0.74" -near-plugins-test-utils = { path = "../near-plugins-test-utils" } +near-plugins-test-utils = { path = "../../near-plugins-test-utils" } diff --git a/examples/upgradable_base/build.sh b/examples/upgradable-examples/upgradable_base/build.sh similarity index 100% rename from examples/upgradable_base/build.sh rename to examples/upgradable-examples/upgradable_base/build.sh diff --git a/examples/upgradable_base/src/lib.rs b/examples/upgradable-examples/upgradable_base/src/lib.rs similarity index 100% rename from examples/upgradable_base/src/lib.rs rename to examples/upgradable-examples/upgradable_base/src/lib.rs diff --git a/examples/upgradable_base/src/up_stage_code.rs b/examples/upgradable-examples/upgradable_base/src/up_stage_code.rs similarity index 100% rename from examples/upgradable_base/src/up_stage_code.rs rename to examples/upgradable-examples/upgradable_base/src/up_stage_code.rs diff --git a/examples/upgradable_base_second/Cargo.toml b/examples/upgradable-examples/upgradable_base_second/Cargo.toml similarity index 78% rename from examples/upgradable_base_second/Cargo.toml rename to examples/upgradable-examples/upgradable_base_second/Cargo.toml index 6c18b4d..f10f293 100644 --- a/examples/upgradable_base_second/Cargo.toml +++ b/examples/upgradable-examples/upgradable_base_second/Cargo.toml @@ -10,8 +10,8 @@ crate-type = ["cdylib", "rlib"] [dependencies] near-sdk = "4.0.0" -near-plugins = { path = "../../near-plugins" } -near-plugins-derive = { path = "../../near-plugins-derive" } +near-plugins = { path = "../../../near-plugins" } +near-plugins-derive = { path = "../../../near-plugins-derive" } borsh = "0.9.3" [dev-dependencies] diff --git a/examples/upgradable_base_second/build.sh b/examples/upgradable-examples/upgradable_base_second/build.sh similarity index 100% rename from examples/upgradable_base_second/build.sh rename to examples/upgradable-examples/upgradable_base_second/build.sh diff --git a/examples/upgradable_base_second/src/lib.rs b/examples/upgradable-examples/upgradable_base_second/src/lib.rs similarity index 100% rename from examples/upgradable_base_second/src/lib.rs rename to examples/upgradable-examples/upgradable_base_second/src/lib.rs From 38a5667d409139ae1370ef4a4064d7c0a900dc54 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Mon, 24 Oct 2022 12:39:24 +0300 Subject: [PATCH 43/68] separate up_stage_code --- examples/Cargo.toml | 1 + .../upgradable-examples/up_stage_code/Cargo.toml | 15 +++++++++++++++ .../src/main.rs} | 6 +++--- .../upgradable_base/Cargo.toml | 5 ----- 4 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 examples/upgradable-examples/up_stage_code/Cargo.toml rename examples/upgradable-examples/{upgradable_base/src/up_stage_code.rs => up_stage_code/src/main.rs} (88%) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index cb68873..896c0c8 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -11,4 +11,5 @@ members = [ "pausable-examples/pausable_base", "upgradable-examples/upgradable_base", "upgradable-examples/upgradable_base_second", + "upgradable-examples/up_stage_code" ] diff --git a/examples/upgradable-examples/up_stage_code/Cargo.toml b/examples/upgradable-examples/up_stage_code/Cargo.toml new file mode 100644 index 0000000..477c019 --- /dev/null +++ b/examples/upgradable-examples/up_stage_code/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "up_stage_code" +version = "0.1.0" +edition = "2021" + +[dependencies] +near-sdk = "4.0.0" +near-plugins = { path = "../../../near-plugins" } +near-plugins-derive = { path = "../../../near-plugins-derive" } +borsh = "0.9.3" +near-primitives = { version = "0.14.0" } +workspaces = "0.6" +tokio = { version = "1.1", features = ["rt", "macros"] } +serde_json = "1.0.74" +near-plugins-test-utils = { path = "../../near-plugins-test-utils" } diff --git a/examples/upgradable-examples/upgradable_base/src/up_stage_code.rs b/examples/upgradable-examples/up_stage_code/src/main.rs similarity index 88% rename from examples/upgradable-examples/upgradable_base/src/up_stage_code.rs rename to examples/upgradable-examples/up_stage_code/src/main.rs index a014c11..4beda6e 100644 --- a/examples/upgradable-examples/upgradable_base/src/up_stage_code.rs +++ b/examples/upgradable-examples/up_stage_code/src/main.rs @@ -16,8 +16,8 @@ fn main() { println!("{}", rt.block_on( contract.call(contract.id(), "up_stage_code") - .args_borsh(wasm) - .max_gas() - .transact() + .args_borsh(wasm) + .max_gas() + .transact() ).unwrap().is_success()); } \ No newline at end of file diff --git a/examples/upgradable-examples/upgradable_base/Cargo.toml b/examples/upgradable-examples/upgradable_base/Cargo.toml index 2605fd8..4312bf3 100644 --- a/examples/upgradable-examples/upgradable_base/Cargo.toml +++ b/examples/upgradable-examples/upgradable_base/Cargo.toml @@ -3,11 +3,6 @@ name = "upgradable_base" version = "0.1.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -# [[bin]] -# name = "up_stage_code" -# path = "src/up_stage_code.rs" - [lib] crate-type = ["cdylib", "rlib"] From 1ab36ae8e7a9441154b67983b65ab619787b99ec Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Mon, 24 Oct 2022 13:14:32 +0300 Subject: [PATCH 44/68] script for build all wasm files --- examples/build.sh | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100755 examples/build.sh diff --git a/examples/build.sh b/examples/build.sh new file mode 100755 index 0000000..e7e9ebc --- /dev/null +++ b/examples/build.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +# Create res folder if not exists +mkdir -p res + +# Iterate over each member +for dir in ./*/*/ +do + echo $dir + # Run build.sh for each member if exsists + if [ -f "$dir/build.sh" ]; then + cd $dir + ./build.sh + cd ../.. + # Copy wasm file + cp $dir/target/wasm32-unknown-unknown/release/*.wasm ./res/ + fi +done From 9f7d0e6de0b5e7da6a66751a33aeea7ac0ac33fd Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Mon, 24 Oct 2022 14:09:25 +0300 Subject: [PATCH 45/68] add flags to compile 2 counters --- .../upgradable_base/Cargo.toml | 4 +++ .../upgradable_base/build.sh | 4 ++- .../upgradable_base/src/lib.rs | 27 +++++++++++++++++++ .../upgradable_base_second/Cargo.toml | 23 ---------------- .../upgradable_base_second/build.sh | 3 --- .../upgradable_base_second/src/lib.rs | 27 ------------------- 6 files changed, 34 insertions(+), 54 deletions(-) delete mode 100644 examples/upgradable-examples/upgradable_base_second/Cargo.toml delete mode 100755 examples/upgradable-examples/upgradable_base_second/build.sh delete mode 100644 examples/upgradable-examples/upgradable_base_second/src/lib.rs diff --git a/examples/upgradable-examples/upgradable_base/Cargo.toml b/examples/upgradable-examples/upgradable_base/Cargo.toml index 4312bf3..0d5bdae 100644 --- a/examples/upgradable-examples/upgradable_base/Cargo.toml +++ b/examples/upgradable-examples/upgradable_base/Cargo.toml @@ -18,3 +18,7 @@ workspaces = "0.6" tokio = { version = "1.1", features = ["rt", "macros"] } serde_json = "1.0.74" near-plugins-test-utils = { path = "../../near-plugins-test-utils" } + +[features] +counter1 = [] +counter2 = [] diff --git a/examples/upgradable-examples/upgradable_base/build.sh b/examples/upgradable-examples/upgradable_base/build.sh index 5fb19d6..cda79e1 100755 --- a/examples/upgradable-examples/upgradable_base/build.sh +++ b/examples/upgradable-examples/upgradable_base/build.sh @@ -1,3 +1,5 @@ #!/usr/bin/env bash -RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release \ No newline at end of file +RUSTFLAGS='-C link-arg=-s' cargo build --features "counter2" --target wasm32-unknown-unknown --release +mv ../../target/wasm32-unknown-unknown/release/upgradable_base.wasm ../../target/wasm32-unknown-unknown/release/upgradable_base_second.wasm +RUSTFLAGS='-C link-arg=-s' cargo build --features "counter1" --target wasm32-unknown-unknown --release diff --git a/examples/upgradable-examples/upgradable_base/src/lib.rs b/examples/upgradable-examples/upgradable_base/src/lib.rs index a6d965a..8412605 100644 --- a/examples/upgradable-examples/upgradable_base/src/lib.rs +++ b/examples/upgradable-examples/upgradable_base/src/lib.rs @@ -4,11 +4,13 @@ use borsh::{BorshSerialize, BorshDeserialize}; #[near_bindgen] #[derive(Ownable, Upgradable, Default, BorshSerialize, BorshDeserialize)] +#[cfg(feature = "counter1")] struct Counter1 { counter: u64, } #[near_bindgen] +#[cfg(feature = "counter1")] impl Counter1 { /// Specify the owner of the contract in the constructor #[init] @@ -27,6 +29,31 @@ impl Counter1 { } } +#[near_bindgen] +#[derive(Ownable, Upgradable, Default, BorshSerialize, BorshDeserialize)] +#[cfg(feature = "counter2")] +struct Counter2 { + counter: u64, +} + +#[near_bindgen] +#[cfg(feature = "counter2")] +impl Counter2 { + #[init] + pub fn new() -> Self { + let mut contract = Self { counter: 0 }; + contract.owner_set(Some(near_sdk::env::predecessor_account_id())); + contract + } + + pub fn inc2(&mut self) { + self.counter += 2; + } + + pub fn get_counter(&self) -> u64 { + self.counter + } +} #[cfg(test)] mod tests { diff --git a/examples/upgradable-examples/upgradable_base_second/Cargo.toml b/examples/upgradable-examples/upgradable_base_second/Cargo.toml deleted file mode 100644 index f10f293..0000000 --- a/examples/upgradable-examples/upgradable_base_second/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "upgradable_base_second" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[lib] -crate-type = ["cdylib", "rlib"] - -[dependencies] -near-sdk = "4.0.0" -near-plugins = { path = "../../../near-plugins" } -near-plugins-derive = { path = "../../../near-plugins-derive" } -borsh = "0.9.3" - -[dev-dependencies] -near-primitives = "0.14.0" -workspaces = "0.6" -tokio = { version = "1.1", features = ["rt", "macros"] } -serde_json = "1.0.74" - - diff --git a/examples/upgradable-examples/upgradable_base_second/build.sh b/examples/upgradable-examples/upgradable_base_second/build.sh deleted file mode 100755 index 5fb19d6..0000000 --- a/examples/upgradable-examples/upgradable_base_second/build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release \ No newline at end of file diff --git a/examples/upgradable-examples/upgradable_base_second/src/lib.rs b/examples/upgradable-examples/upgradable_base_second/src/lib.rs deleted file mode 100644 index 6439f24..0000000 --- a/examples/upgradable-examples/upgradable_base_second/src/lib.rs +++ /dev/null @@ -1,27 +0,0 @@ -use near_plugins::{Ownable, Upgradable}; -use near_sdk::near_bindgen; -use borsh::{BorshSerialize, BorshDeserialize}; - -#[near_bindgen] -#[derive(Ownable, Upgradable, Default, BorshSerialize, BorshDeserialize)] -struct Counter2 { - counter: u64, -} - -#[near_bindgen] -impl Counter2 { - #[init] - pub fn new() -> Self { - let mut contract = Self { counter: 0 }; - contract.owner_set(Some(near_sdk::env::predecessor_account_id())); - contract - } - - pub fn inc2(&mut self) { - self.counter += 2; - } - - pub fn get_counter(&self) -> u64 { - self.counter - } -} \ No newline at end of file From 27f62bd365bb9a7b9d550950ef889e81428c5488 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Mon, 24 Oct 2022 14:29:07 +0300 Subject: [PATCH 46/68] fix build.sh --- examples/Cargo.toml | 1 - examples/build.sh | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 896c0c8..6d06670 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -10,6 +10,5 @@ members = [ "ownable-examples/ownable_cross_call", "pausable-examples/pausable_base", "upgradable-examples/upgradable_base", - "upgradable-examples/upgradable_base_second", "upgradable-examples/up_stage_code" ] diff --git a/examples/build.sh b/examples/build.sh index e7e9ebc..edc6224 100755 --- a/examples/build.sh +++ b/examples/build.sh @@ -12,7 +12,8 @@ do cd $dir ./build.sh cd ../.. - # Copy wasm file - cp $dir/target/wasm32-unknown-unknown/release/*.wasm ./res/ fi done + +# Copy wasm fils +cp ./target/wasm32-unknown-unknown/release/*.wasm ./res/ From 9e92312c2c9a5c505fb10608ac917d3b469c50fb Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Mon, 24 Oct 2022 15:23:42 +0300 Subject: [PATCH 47/68] fix target --- .../access_controllable_base/src/lib.rs | 2 +- .../full_access_key_fallback_base/src/lib.rs | 2 +- examples/ownable-examples/ownable_base/src/lib.rs | 2 +- .../ownable-examples/ownable_change_storage_key/src/lib.rs | 2 +- examples/ownable-examples/ownable_cross_call/src/lib.rs | 2 +- examples/pausable-examples/pausable_base/src/lib.rs | 2 +- examples/upgradable-examples/up_stage_code/src/main.rs | 2 +- examples/upgradable-examples/upgradable_base/src/lib.rs | 4 ++-- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/access-controllable-examples/access_controllable_base/src/lib.rs b/examples/access-controllable-examples/access_controllable_base/src/lib.rs index c407b2b..dd3df22 100644 --- a/examples/access-controllable-examples/access_controllable_base/src/lib.rs +++ b/examples/access-controllable-examples/access_controllable_base/src/lib.rs @@ -68,7 +68,7 @@ mod tests { use crate::UsersGroups; use near_plugins_test_utils::*; - const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/access_controllable_base.wasm"; + const WASM_FILEPATH: &str = "../../target/wasm32-unknown-unknown/release/access_controllable_base.wasm"; #[tokio::test] async fn base_scenario() { diff --git a/examples/full-access-key-fallback-examples/full_access_key_fallback_base/src/lib.rs b/examples/full-access-key-fallback-examples/full_access_key_fallback_base/src/lib.rs index 8f2e754..329d4ba 100644 --- a/examples/full-access-key-fallback-examples/full_access_key_fallback_base/src/lib.rs +++ b/examples/full-access-key-fallback-examples/full_access_key_fallback_base/src/lib.rs @@ -37,7 +37,7 @@ mod tests { use near_sdk::AccountId; use near_plugins_test_utils::*; - const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/full_access_key_fallback_base.wasm"; + const WASM_FILEPATH: &str = "../../target/wasm32-unknown-unknown/release/full_access_key_fallback_base.wasm"; #[tokio::test] async fn base_scenario() { diff --git a/examples/ownable-examples/ownable_base/src/lib.rs b/examples/ownable-examples/ownable_base/src/lib.rs index d22ecc5..0d61f33 100644 --- a/examples/ownable-examples/ownable_base/src/lib.rs +++ b/examples/ownable-examples/ownable_base/src/lib.rs @@ -55,7 +55,7 @@ mod tests { use near_sdk::AccountId; use near_plugins_test_utils::*; - const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/ownable_base.wasm"; + const WASM_FILEPATH: &str = "../../target/wasm32-unknown-unknown/release/ownable_base.wasm"; #[tokio::test] async fn base_scenario() { diff --git a/examples/ownable-examples/ownable_change_storage_key/src/lib.rs b/examples/ownable-examples/ownable_change_storage_key/src/lib.rs index 194caa0..c8740f2 100644 --- a/examples/ownable-examples/ownable_change_storage_key/src/lib.rs +++ b/examples/ownable-examples/ownable_change_storage_key/src/lib.rs @@ -54,7 +54,7 @@ mod tests { use serde_json::json; use near_plugins_test_utils::*; - const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/ownable_change_storage_key.wasm"; + const WASM_FILEPATH: &str = "../../target/wasm32-unknown-unknown/release/ownable_change_storage_key.wasm"; #[tokio::test] async fn check_owner_storage_key() { diff --git a/examples/ownable-examples/ownable_cross_call/src/lib.rs b/examples/ownable-examples/ownable_cross_call/src/lib.rs index 7d24790..6d2cd9b 100644 --- a/examples/ownable-examples/ownable_cross_call/src/lib.rs +++ b/examples/ownable-examples/ownable_cross_call/src/lib.rs @@ -81,7 +81,7 @@ mod tests { use near_sdk::AccountId; use near_plugins_test_utils::*; - const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/ownable_cross_call.wasm"; + const WASM_FILEPATH: &str = "../../target/wasm32-unknown-unknown/release/ownable_cross_call.wasm"; #[tokio::test] async fn base_scenario() { diff --git a/examples/pausable-examples/pausable_base/src/lib.rs b/examples/pausable-examples/pausable_base/src/lib.rs index 10be0b1..e0038a1 100644 --- a/examples/pausable-examples/pausable_base/src/lib.rs +++ b/examples/pausable-examples/pausable_base/src/lib.rs @@ -74,7 +74,7 @@ mod tests { use near_sdk::AccountId; use near_plugins_test_utils::*; - const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/pausable_base.wasm"; + const WASM_FILEPATH: &str = "../../target/wasm32-unknown-unknown/release/pausable_base.wasm"; #[tokio::test] async fn base_scenario() { diff --git a/examples/upgradable-examples/up_stage_code/src/main.rs b/examples/upgradable-examples/up_stage_code/src/main.rs index 4beda6e..d3e92ff 100644 --- a/examples/upgradable-examples/up_stage_code/src/main.rs +++ b/examples/upgradable-examples/up_stage_code/src/main.rs @@ -3,7 +3,7 @@ use tokio::runtime::Runtime; use workspaces::{Account, Contract}; use std::env; -const WASM_FILEPATH_SECOND: &str = "../upgradable_base_second/target/wasm32-unknown-unknown/release/upgradable_base_second.wasm"; +const WASM_FILEPATH_SECOND: &str = "../../target/wasm32-unknown-unknown/release/upgradable_base_second.wasm"; fn main() { let args: Vec = env::args().collect(); diff --git a/examples/upgradable-examples/upgradable_base/src/lib.rs b/examples/upgradable-examples/upgradable_base/src/lib.rs index 8412605..605bc9a 100644 --- a/examples/upgradable-examples/upgradable_base/src/lib.rs +++ b/examples/upgradable-examples/upgradable_base/src/lib.rs @@ -61,8 +61,8 @@ mod tests { use workspaces::{Account, Contract}; use near_plugins_test_utils::*; - const WASM_FILEPATH: &str = "./target/wasm32-unknown-unknown/release/upgradable_base.wasm"; - const WASM_FILEPATH_SECOND: &str = "../upgradable_base_second/target/wasm32-unknown-unknown/release/upgradable_base_second.wasm"; + const WASM_FILEPATH: &str = "../../target/wasm32-unknown-unknown/release/upgradable_base.wasm"; + const WASM_FILEPATH_SECOND: &str = "../../target/wasm32-unknown-unknown/release/upgradable_base_second.wasm"; async fn get_contract() -> (Account, Contract) { let worker = workspaces::testnet().await.unwrap(); From ce28d9fd9f13f4ef999c6691a89f6587b4890841 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Mon, 24 Oct 2022 18:27:37 +0300 Subject: [PATCH 48/68] cleanup access controllable role readme --- .../access-controllable-examples/README.md | 88 ++++++++++--------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/examples/access-controllable-examples/README.md b/examples/access-controllable-examples/README.md index 87ff722..5a65d06 100644 --- a/examples/access-controllable-examples/README.md +++ b/examples/access-controllable-examples/README.md @@ -1,6 +1,6 @@ -# Example of using Access Control plugin +# Example of using the Access Control plugin -An access control mechanism that allows you to specify which groups of users can have access to certain functions. +An access control mechanism that allows you to specify which groups of users can access certain functions. ```rust use near_plugins::AccessControllable; @@ -69,11 +69,11 @@ impl Counter { ## The contract methods description ### acl_storage_prefix -`acl_storage_prefix` - a method which show the common prefix of keys for storage the members and the admins of groups. -`__acl` by default. +`acl_storage_prefix` is a method that returns the common prefix of keys for storing the members and the admins of groups. +`__acl` by default. ```shell -$ near call acl_storage_prefix --accountId acl.olga24912_3.testnet +$ near call acl_storage_prefix --accountId Scheduling a call: .acl_storage_prefix() Doing account.functionCall() Transaction Id @@ -86,26 +86,26 @@ $ python3 ``` ### acl_is_super_admin -`acl_is_super_admin` - a _view_ method which checks that account have a super admin rights. -Super admin can control the members list of each group and control the admins list for each group. +`acl_is_super_admin` is a _view_ method that checks that account has super admin rights. +Super admin can control the member list of each group and control the admin list for each group. ```shell -$ near view acl_is_super_admin '{"account_id": "" }' -View call: .acl_is_super_admin({"account_id": ""}) +$ near view acl_is_super_admin '{"account_id": "" }' +View call: .acl_is_super_admin({"account_id": ""}) true ``` ### acl_add_admin -`acl_add_admin` - add a new admin for a specific group. -Admins right doesn't aloud to run group specific functions, but group admins can control the group member list. -This method can be run by the admin of specific group or by the super admin. +`acl_add_admin` is a method that adds a new admin for a specific group. +Admins' rights don't allow running group-specific functions, but group admins can control the group member list. +This method can be run by the admin of a specific group or by the super admin. ```shell -$ near call acl_add_admin '{"role": "GroupA", "account_id": ""}' --accountId +$ near call acl_add_admin '{"role": "GroupA", "account_id": ""}' --accountId ``` ### acl_is_admin -`acl_is_admin` is a _view_ method which checks if the account have an admin right for specified group. For super admin it will return true. +`acl_is_admin` is a _view_ method that checks if the account has an admin right for the specified group. For super admin, it will return true. ```shell $ near view acl_is_admin '{"role": "GroupA", "account_id": ""}' @@ -114,45 +114,45 @@ true ``` ### acl_revoke_admin -`acl_revoke_admin` - remove the group admin right for specific account. Can be executed by admin of this group or by super admin. +`acl_revoke_admin` is a method that removes the group admin right for a specific account. Can be executed by the admin of this group or by the super admin. ```shell -$ near call acl_revoke_admin '{"role": "GroupA", "account_id": ""}' --accountId +$ near call acl_revoke_admin '{"role": "GroupA", "account_id": ""}' --accountId ``` ### acl_renounce_admin -`acl_renounce_admin` - remove the group admin right for called account. +`acl_renounce_admin` is a method that removes the group admin right for an account that calls the method. ```shell $ near call acl_renounce_admin '{"role": "GroupA"}' --accountId ``` -After calling that method Alice will not have the admin right for GroupA anymore. +After calling that method, Alice will not have the admin right for GroupA anymore. ### acl_revoke_role -`acl_revoke_role` - remove the specified account from the list of the group member. +`acl_revoke_role` is a method that removes the specified account from the list of the group member. Only the group admin or super admin can execute this function. ```shell -$ near call acl_revoke_role '{"role": "GroupA", "account_id": ""}' --accountId +$ near call acl_revoke_role '{"role": "GroupA", "account_id": ""}' --accountId ``` ### acl_renounce_role -`acl_renounce_role` - remove the caller account from the member list of the group. Can be called by anyone. +`acl_renounce_role` is a method that removes the caller account from the member list of the group. Can be called by anyone. ```shell $ near call acl_renounce_role '{"role": "GroupA"}' --accountId ``` ### acl_grant_role -`acl_grant_role` - add the account to the group member list. Can be executed only by the group admin or by super admin. +`acl_grant_role` is a method that adds the account to the group member list. Can be executed only by the group admin or by the super admin. ```shell -$ near call acl_grant_role '{"role": "GroupA", "account_id": ""}' --accountId +$ near call acl_grant_role '{"role": "GroupA", "account_id": ""}' --accountId ``` ### acl_has_role -`acl_has_role` - a _view_ method for check if the account is a member of specified group. +`acl_has_role` is a _view_ method for checking if the account is a member of the specified group. ```shell $ near view acl_has_role '{"role": "GroupA", "account_id": ""}' @@ -161,7 +161,7 @@ true ``` ### acl_has_any_role -`acl_has_any_role` - a _view_ method to check if an account a member of at least one of specified groups. +`acl_has_any_role` is a _view_ method for checking if an account is a member of at least one of the specified groups. ```shell $ near view acl_has_any_role '{"roles": ["GroupA", "GroupB"], "account_id": ""}' @@ -170,7 +170,7 @@ true ``` ### acl_get_admins -`acl_get_admins` - a _view_ method which shows some group admins. It will skip first `skip` admins and return maximum `limit` number of admins. +`acl_get_admins` is a _view_ method that shows some admins of the group. It will skip first `skip` admins and return not more than `limit` number of admins. ```shell $ near view acl_get_admins '{"role": "GroupA", "skip": 0, "limit": 2}' @@ -179,7 +179,7 @@ View call: .acl_get_admins({"role": "GroupA", "skip": 0, "limi ``` ### acl_get_grantees -`acl_get_grantess` - a _view_ method which shows some members of the group. It will skip first `skip` members and return maximum `limit` number of members. +`acl_get_grantess` is a _view_ method that shows some members of the group. It will skip the first `skip` members and return not more than `limit` number of members. ```shell $ near view acl_get_grantess '{"role": "GroupA", "skip": 0, "limit": 2}' @@ -188,7 +188,7 @@ View call: .acl_get_grantess({"role": "GroupA", "skip": 0, "li ``` ## Preparation steps for demonstration -In that document we are providing some example of using contract with access control plugin. You also can explore the usage examples in the tests in `./src/lib.rs`. For running a tests please take a look to the **Test running instruction** section. +In that document, we are providing some examples of using a contract with an access control plugin. You also can explore the usage examples in the tests in `./access_controllable_base/src/lib.rs` and in `./access_control_role_base/src/lib.rs`. For running tests, please take a look at the **Test running instruction** section. 1. **Creating an account on testnet** For demonstration let's create 3 accounts: ``, ``, `` @@ -198,44 +198,47 @@ In that document we are providing some example of using contract with access con $ near create-account ..testnet --masterAccount .testnet --initialBalance 10 ``` - In the next section we will refer to the `..testnet` as ``, + In the next sections, we will refer to the `..testnet` as ``, to the `..testnet` as ``, and to the `..testnet` as `` for simplicity. 2. **Compile Contract to wasm file** - For compiling the contract just run the `build.sh` script. The target file with compiled contract will be `./target/wasm32-unknown-unknown/release/access_controllable_base.wasm` + For compiling the contract, just run the `access_controllable_base/build.sh` script. The target file with compiled contract will be `../target/wasm32-unknown-unknown/release/access_controllable_base.wasm` ```shell + $ cd access_controllable_base $ ./build.sh + $ cd .. ``` 3. **Deploy and init a contract** ```shell - $ near deploy --accountId --wasmFile ./target/wasm32-unknown-unknown/release/access_controllable_base.wasm --initFunction new --initArgs '{}' + $ near deploy --accountId --wasmFile ../target/wasm32-unknown-unknown/release/access_controllable_base.wasm --initFunction new --initArgs '{}' ``` ## Example of using the contract with access control plugin -### Calling the access control methods -For using the method `level_a_incr` you should be a memeber of the GroupA. Alice not a member of any group, so she cann't use this method. +### Calling the methods with access control +For using the method, `level_a_incr` you should be a member of GroupA. Alice is not a member of any group, so she can't use this method. ```shell $ near call level_a_incr --accountId +ERROR $ near view get_counter 0 ``` -Let's make the Alice the member of the GroupA. +Let's make Alice a member of GroupA. ```shell $ near call acl_grant_role '{"role": "GroupA", "account_id": ""}' --accountId ``` -Now Alice the member of GroupA and call the level_a_incr method +Now Alice is a member of GroupA and can call the `level_a_incr` method ```shell $ near call level_a_incr --accountId $ near view get_counter 1 ``` -As well as `level_ab_incr` which aloud for both GroupA and GroupB members. +As well as calls the `level_ab_incr` method, which allowed for both GroupA and GroupB members. ```shell $ near call level_ab_incr --accountId $ near view get_counter @@ -243,28 +246,29 @@ $ near view get_counter ``` ### Admin of the group not a member of the group -Note the admin of the group may not be a member of this group. For example, the `` is a super admin, but he -cann't execute the `level_a_incr` method. +Note, the admin of the group may not be a member of this group. For example, the `` is a super admin, but he +can't execute the `level_a_incr` method. ```shell $ near view get_counter 2 $ near call level_a_incr --accountId +ERROR $ near view get_counter 2 ``` ## Tests running instruction -Tests in `src/lib.rs` contain examples of interaction with a contract. +Tests in `access_controllable_base/src/lib.rs` contain examples of interaction with a contract. For running test: -1. Generate `wasm` file by running `build.sh` script. The target file will be `target/wasm32-unknown-unknown/release/access_controllable_base.wasm` +1. Generate `wasm` file by running `access_controllable_base/build.sh` script. The target file will be `../target/wasm32-unknown-unknown/release/access_controllable_base.wasm` 2. Run tests `cargo test` ```shell +$ cd access_controllable_base $ ./build.sh $ cargo test ``` -For tests, we use `workspaces` library and `sandbox` environment for details you can explorer `../near-plugins-test-utils` crate -contract_account. \ No newline at end of file +For tests, we use `workspaces` library and `sandbox` environment for details you can explorer `../near-plugins-test-utils` crate. \ No newline at end of file From c729b6d2edc8de71a4c35e431d20c0a5677bcfe4 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Mon, 24 Oct 2022 18:56:48 +0300 Subject: [PATCH 49/68] cleanup full access key fallback README --- .../README.md | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/examples/full-access-key-fallback-examples/README.md b/examples/full-access-key-fallback-examples/README.md index 5b30f8a..4e8fb55 100644 --- a/examples/full-access-key-fallback-examples/README.md +++ b/examples/full-access-key-fallback-examples/README.md @@ -40,15 +40,15 @@ impl Counter { ## The contract methods description ### attach_full_access_key -`attach_full_access_key` - attach a new full access for the current account. -Only owner of the contract can use this function. +`attach_full_access_key` is a method that attaches new full access for the current account. +Only the owner of the contract can use this function. ```shell near call attach_full_access_key '{"public_key": "ed25519:ErVTCTvmepb4NDhQ7infTomkLVsd1iTWwLR84FBhV7UC"}' --accountId ``` ## Preparation steps for demonstration -In that document we are providing some example of using contract with access control plugin. You also can explore the usage examples in the tests in `./src/lib.rs`. For running a tests please take a look to the **Test running instruction** section. +In that document, we are providing some examples of using a contract with a full access key fallback plugin. You also can explore the usage examples in the tests in `./full_access_key_fallback_base/src/lib.rs`. For running tests, please take a look at the **Test running instruction** section. 1. **Creating an account on testnet** For demonstration let's create 2 accounts: ``, `` @@ -61,63 +61,64 @@ In that document we are providing some example of using contract with access con to the `..testnet` as ``. 2. **Compile Contract to wasm file** - For compiling the contract just run the `build.sh` script. The target file with compiled contract will be `./target/wasm32-unknown-unknown/release/full_access_key_fallback_base.wasm` + For compiling the contract just run the `full_access_key_fallback_base/build.sh` script. The target file with compiled contract will be `../target/wasm32-unknown-unknown/release/full_access_key_fallback_base.wasm` ```shell + $ cd full_access_key_fallback_base $ ./build.sh + $ cd .. ``` 3. **Deploy and init a contract** ```shell - $ near deploy --accountId --wasmFile ./target/wasm32-unknown-unknown/release/full_access_key_fallback_base.wasm --initFunction new --initArgs '{}' + $ near deploy --accountId --wasmFile ../target/wasm32-unknown-unknown/release/full_access_key_fallback_base.wasm --initFunction new --initArgs '{}' ``` ## Example of using the contract with full access key fallback plugin -Our plan for this example it is remove the full access key and after that bring it is back. -The keys usually storage at `~/.near-credentials/testnet/.json`. Also let's -choose some operation which only the contract with full access key can done, for example, -transfer money. +Our plan for this example is to remove the full access key and after that bring it back. +The keys usually storage at `$HOME/.near-credentials/testnet/.json`. Also let's +choose some operations that only the contract with a full access key can do, for example, +money transfer. -Move ownership rights to the Alice account. +Moving ownership rights to the Alice account. ```shell $ near call owner_set '{"owner": ""}' --accountId ``` -Check that currently we can transfer the money for example to Alice account +Checking that currently we can transfer the money for example to Alice account ```shell $ near send 1 ``` -Now removing the full access key for contract account - +Removing the full access key for contract account ```shell $ near delete-key "ed25519:ErVTCTvmepb4NDhQ7infTomkLVsd1iTWwLR84FBhV7UC" ``` +The value of public-key can be found at `$HOME/.near-credentials/testnet/.json`. -The value of public-key can be found at `~/.near-credentials/testnet/.json`. - -Now check, that now the money transfer will not work: +Checking, that now the money transfer will not work: ```shell $ near send 1 +ERROR ``` -And now let's add the key back and check that it will work +Adding the key back and check that it will work ```shell $ near call attach_full_access_key '{"public_key": "ed25519:ErVTCTvmepb4NDhQ7infTomkLVsd1iTWwLR84FBhV7UC"}' --accountId $ near send 1 ``` ## Tests running instruction -Tests in `src/lib.rs` contain examples of interaction with a contract. +Tests in `full_access_key_fallback_base/src/lib.rs` contain examples of interaction with a contract. For running test: -1. Generate `wasm` file by running `build.sh` script. The target file will be `target/wasm32-unknown-unknown/release/full_access_key_fallback_base.wasm` +1. Generate `wasm` file by running `build.sh` script. The target file will be `../target/wasm32-unknown-unknown/release/full_access_key_fallback_base.wasm` 2. Run tests `cargo test` ```shell +$ cd full_access_key_fallback_base $ ./build.sh $ cargo test ``` -For tests, we use `workspaces` library and `sandbox` environment for details you can explorer `../near-plugins-test-utils` crate -contract_account. \ No newline at end of file +For tests, we use `workspaces` library and `sandbox` environment for details you can explorer `../near-plugins-test-utils` crate. \ No newline at end of file From 5b0191073aaab247b3df44f5483c98a933d12172 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Mon, 24 Oct 2022 19:31:38 +0300 Subject: [PATCH 50/68] clean up ownable readme --- examples/ownable-examples/README.md | 71 ++++++++++++++++------------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/examples/ownable-examples/README.md b/examples/ownable-examples/README.md index 2539b50..9474931 100644 --- a/examples/ownable-examples/README.md +++ b/examples/ownable-examples/README.md @@ -1,6 +1,6 @@ # Example of using Ownable plugin -Basic access control mechanism that allows only an authorized account id to call certain methods. Note this account id can belong either to a regular user, or it could be a contract (a DAO for example). +A basic access control mechanism that allows only an authorized account ID to call certain methods. Note, this account ID can belong either to a regular user, or it could be a contract (a DAO for example). ```Rust use near_plugins::Ownable; @@ -56,15 +56,15 @@ impl Counter { ## The contract methods description ### owner_set -`owner_set` - the method which sets the new owner of the contract. Only the current owner of the contract can set a new one. -If the contract doesn't have any owner the self can set one. +`owner_set` is the method that sets the new owner of the contract. Only the current owner of the contract can set a new one. +If the contract doesn't have any owner, the self can set one. ```shell $ near call owner_set '{"owner": }' --accountId ``` ### owner_get -`owner_get` - the _view_ method which returns the current contract owner +`owner_get` is the _view_ method, which returns the current contract owner. ```shell $ near view owner_get '{}' @@ -73,8 +73,8 @@ View call: .owner_get({}) ``` ### owner_storage_key -`owner_storage_key` - the _view_ method which returns the key for storage the owner account id. -The `__OWNER__` by default. Can be changed by using the `ownable` attribute. See example `ownable_change_storage_key`. +`owner_storage_key` is the _view_ method that returns the key for storage, the owner account id. +The `__OWNER__` by default. It can be changed by using the `ownable` attribute. See example `ownable_change_storage_key`. ```shell $ near view owner_storage_key @@ -89,7 +89,8 @@ $ python3 ``` ### owner_is -`owner_is` - the methods checks if the caller is the owner of the contract +`owner_is` is the method that checks if the caller is the owner of the contract. + ```shell $ near call owner_is --accountId Scheduling a call: .testnet.owner_is() @@ -100,9 +101,8 @@ https://explorer.testnet.near.org/transactions/ true ``` - -## Example of using contract with ownable plugin -In that document we are providing some example of using contract with ownable plugin. You also can explore the usage examples in the tests in `./src/lib.rs`. For running a tests please take a look to the **Test running instruction** section. +## Example of using a contract with the ownable plugin +In that document, we are providing some examples of using contracts with the ownable plugin. You also can explore the usage examples in the tests in `ownable_base/src/lib.rs`. For running tests, please take a look at the **Test running instruction** section. ### Preparation steps for demonstration 1. **Creating an account on testnet** @@ -116,23 +116,25 @@ In that document we are providing some example of using contract with ownable pl $ near create-account ..testnet --masterAccount .testnet --initialBalance 10 ``` - In the next section we will refer to the `..testnet` as `` and to the `..testnet` as `` for simplicity. + In the next sections we will refer to the `..testnet` as `` and to the `..testnet` as `` for simplicity. 2. **Compile Contract to wasm file** - For compiling the contract just run the `build.sh` script. The target file with compiled contract will be `./target/wasm32-unknown-unknown/release/ownable_base.wasm` + For compiling the contract just run the `ownable_base/build.sh` script. The target file with compiled contract will be `../target/wasm32-unknown-unknown/release/ownable_base.wasm` ```shell + $ cd ownable_base $ ./build.sh + $ cd .. ``` 3. **Deploy and init a contract** ```shell - $ near deploy --accountId --wasmFile ./target/wasm32-unknown-unknown/release/ownable_base.wasm --initFunction new --initArgs '{}' + $ near deploy --accountId --wasmFile ../target/wasm32-unknown-unknown/release/ownable_base.wasm --initFunction new --initArgs '{}' ``` ### Contract with owner plugin usage examples -#### When self is owner we can call all methods -After initialization the `` is the owner of this contract. So this account both the `self` and the `owner` of the contract and can call of the contract method. +#### When the self is the owner it can call all methods +After initialization, the `` is the owner of this contract. So this account is both the `self` and the `owner` of the contract, and it can call all the contract methods. ```shell $ near call protected '{}' --accountId @@ -141,7 +143,7 @@ $ near call protected_self '{}' --accountId unprotected '{}' --accountId ``` -We can check that we succeeded in calling all this function by calling `get_counter` view method and check that counter is 4. +We can check that we succeeded in calling all these functions by calling the `get_counter` view method and checking that the counter is 4. ```shell $ near view get_counter '{}' @@ -154,8 +156,11 @@ Currently, the `` doesn't connected to the contract. So, we can c ```shell $ near call protected '{}' --accountId +ERROR $ near call protected_owner '{}' --accountId +ERROR $ near call protected_self '{}' --accountId +ERROR $ near view get_counter '{}' View call: .get_counter({}) 4 @@ -166,29 +171,29 @@ View call: .get_counter({}) ``` #### Check and Change the contract owner -Let's change the contract owner from `` to the ``. Only the current owner of the contract can change the owner. +Let's change the contract owner from `` to ``. Only the current owner of the contract can change the owner. -We can check the owner of the contract by callint `owner_get` view method. +We can check the owner of the contract by calling `owner_get` view method. ```shell $ near view owner_get '{}' View call: .owner_get({}) '' ``` -In this case the owner is ``. And we can change the contract owner by running `owner_set`. +In this case, the owner is ``. And we can change the contract owner by running `owner_set`. ```shell $ near call owner_set '{"owner": }' --accountId ``` -And we can chack the contract owner one more time for making sure, that it is changed. +And we can check the contract owner one more time for making sure, that it is changed. ```shell $ near view owner_get '{}' View call: .owner_get({}) '' ``` -#### When self is not owner it can't run the only(owner) functions -So, now `` is not an owner of out contract anymore. So, the `` can run the `unprotected`, `proteced_self`, `protected` and can't use the methods `protected_owner`. +#### When the self is not owner it can't run the only(owner) functions +So, now `` is not the owner of our contract anymore. The `` can run the `unprotected`, `proteced_self`, `protected` and can't use the methods `protected_owner`. ```shell $ near call protected '{}' --accountId @@ -198,6 +203,7 @@ $ near view get_counter '{}' View call: .get_counter({}) 8 $ near call protected_owner '{}' --accountId +ERROR $ near view get_counter '{}' View call: .get_counter({}) 8 @@ -214,18 +220,20 @@ $ near view get_counter '{}' View call: .get_counter({}) 11 $ near call protected_self '{}' --accountId +ERROR $ near view get_counter '{}' View call: .get_counter({}) 11 ``` #### Only owner can change the contract ownership -When the contract have an owner only the owner can change the ownership. All other account, include self, cann't. +When the contract has an owner, only the owner can change the ownership. All other accounts, including self, can't. ```shell $ near view owner_get '{}' View call: .owner_get({}) '' $ near call owner_set '{"owner": }' --accountId +ERROR $ near view owner_get '{}' View call: .owner_get({}) '' @@ -241,21 +249,22 @@ View call: .owner_get({}) null ``` -#### The self cann't run the only(owner) function if contract doesn't have an owner -When contract doesn't have an owner no one can use only(owner) functions include self. +#### The self can't run the only(owner) function if contract doesn't have an owner +When the contract doesn't have an owner, no one can use `only(owner)` functions including self. ```shell $ near view get_counter '{}' View call: .get_counter({}) 11 $ near call protected_owner '{}' --accountId +ERROR $ near view get_counter '{}' View call: .get_counter({}) 11 ``` -#### When the contract doesn't have owner the self can setup a new one -When the contract doesn't have the owner, the self can setup a new owner. +#### When the contract doesn't have owner, the self can set up a new one +When the contract doesn't have the owner, the self can set up a new owner. ```shell $ near view owner_get '{}' View call: .owner_get({}) @@ -267,16 +276,16 @@ View call: .owner_get({}) ``` ### Tests running instruction -Tests in `src/lib.rs` contain examples of interaction with a contract. +Tests in `ownable_base/src/lib.rs` contain examples of interaction with a contract. For running test: -1. Generate `wasm` file by running `build.sh` script. The target file will be `target/wasm32-unknown-unknown/release/ownable_base.wasm` +1. Generate `wasm` file by running `build.sh` script. The target file will be `../target/wasm32-unknown-unknown/release/ownable_base.wasm` 2. Run tests `cargo test` ```shell +$ cd ownable_base $ ./build.sh $ cargo test ``` -For tests, we use `workspaces` library and `sandbox` environment for details you can explorer `../near-plugins-test-utils` crate -contract_account. \ No newline at end of file +For tests, we use `workspaces` library and `sandbox` environment for details you can explorer `../near-plugins-test-utils` crate. \ No newline at end of file From fd1fd53313033c79322291fdc209ffa9f6ebe993 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Mon, 24 Oct 2022 19:42:55 +0300 Subject: [PATCH 51/68] cleanup pausable readme --- examples/pausable-examples/README.md | 39 +++++++++++++++------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/examples/pausable-examples/README.md b/examples/pausable-examples/README.md index dde8775..26641ad 100644 --- a/examples/pausable-examples/README.md +++ b/examples/pausable-examples/README.md @@ -1,5 +1,5 @@ # Example of using Pausable plugin -Allow contracts to implement an emergency stop mechanism that can be triggered by an authorized account. Pauses can be used granularly to only limit certain features. +Allows contracts to implement an emergency stop mechanism that can be triggered by an authorized account. Pauses can be used granular to only limit certain features. Contract example using Pausable plugin. Note that it requires the contract to be Ownable. @@ -77,8 +77,8 @@ impl Counter { ## The contract methods description ### pa_storage_key -`pa_storage_key` is a _view_ method which returns the key of storage slot with list of paused features. -By default `b"__PAUSED__"` is used. For changing the attribute `pausable` can be used. +`pa_storage_key` is a _view_ method that returns the key of the storage slot with a list of paused features. +By default, `b"__PAUSED__"` is used. For changing, the attribute `pausable` can be used. ```shell $ near view pa_storage_key @@ -103,7 +103,7 @@ struct Counter { ``` ### pa_is_paused -`pa_is_paused` is a _view_ method which returns if a feature is paused. +`pa_is_paused` is a _view_ method that returns if a feature is paused. ```shell $ near view pa_is_paused '{"key": "increase_1"}' @@ -112,7 +112,7 @@ true ``` ### pa_all_paused -`pa_all_paused` is a _view_ method which return the list of the all paused features. +`pa_all_paused` is a _view_ method that returns the list of all paused features. ```shell $ near view pa_all_paused @@ -120,23 +120,22 @@ View call: .pa_all_paused() [ 'increase_1', 'increase_2' ] ``` - ### pa_pause_feature -`pa_pause_feature` is a method for pause specified feature. Can be run only by owner or self. +`pa_pause_feature` is a method for pausing specified features. Can be run only by the owner or self. ```shell $ near call pa_pause_feature '{"key": "increase_1"}' --accountId ``` ### pa_unpause_feature -`pa_unpause_feature` is a method for unpause specified feature. Can be run only by owner or self. +`pa_unpause_feature` is a method for unpausing specified features. Can be run only by the owner or self. ```shell $ near call pa_unpause_feature '{"key": "increase_1"}' --accountId ``` ## Preparation steps for demonstration -In that document we are providing some example of using contract with access control plugin. You also can explore the usage examples in the tests in `./src/lib.rs`. For running a tests please take a look to the **Test running instruction** section. +In that document, we are providing some examples of using a contract with access control plugins. You also can explore the usage examples in the tests in `./pausable_base/src/lib.rs`. For running tests, please take a look at the **Test running instruction** section. 1. **Creating an account on testnet** For demonstration let's create 2 accounts: ``, `` @@ -149,21 +148,23 @@ In that document we are providing some example of using contract with access con to the `..testnet` as ``. 2. **Compile Contract to wasm file** - For compiling the contract just run the `build.sh` script. The target file with compiled contract will be `./target/wasm32-unknown-unknown/release/pausable_base.wasm` + For compiling the contract just run the `./pausable_base/build.sh` script. The target file with compiled contract will be `../target/wasm32-unknown-unknown/release/pausable_base.wasm` ```shell + $ cd pausable_base $ ./build.sh + $ .. ``` 3. **Deploy and init a contract** ```shell - $ near deploy --accountId --wasmFile ./target/wasm32-unknown-unknown/release/pausable_base.wasm --initFunction new --initArgs '{}' + $ near deploy --accountId --wasmFile ../target/wasm32-unknown-unknown/release/pausable_base.wasm --initFunction new --initArgs '{}' ``` ## Example of using the contract with pausable plugin ### Simple pause and unpause function without name specification -At the beginning the `` both the self and the owner. -`` doesn't have any specific rights. +In the beginning, the `` is both the self and the owner. +`` doesn't have any specific rights. No features on pause: ```shell @@ -191,12 +192,14 @@ View call: .pa_is_paused({"key": "increase_1"}) true ``` -Now Alice or even self cann't run `increase_1` function +Now Alice or even self can't run `increase_1` function ```shell $ near view get_counter 1 $ near call increase_1 --accountId +ERROR $ near call increase_1 --accountId +ERROR $ near view get_counter 1 ``` @@ -224,16 +227,16 @@ $ near view get_counter ``` ## Tests running instruction -Tests in `src/lib.rs` contain examples of interaction with a contract. +Tests in `pausable_base/src/lib.rs` contain examples of interaction with a contract. For running test: -1. Generate `wasm` file by running `build.sh` script. The target file will be `target/wasm32-unknown-unknown/release/pausable_base.wasm` +1. Generate `wasm` file by running `build.sh` script. The target file will be `../target/wasm32-unknown-unknown/release/pausable_base.wasm` 2. Run tests `cargo test` ```shell +$ cd pausable_base $ ./build.sh $ cargo test ``` -For tests, we use `workspaces` library and `sandbox` environment for details you can explorer `../near-plugins-test-utils` crate -contract_account. \ No newline at end of file +For tests, we use `workspaces` library and `sandbox` environment for details you can explorer `../near-plugins-test-utils` crate. \ No newline at end of file From 681f6b71486850d8fa1e51d91dce6a18a9d556a0 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Mon, 24 Oct 2022 21:44:05 +0300 Subject: [PATCH 52/68] cleanup upgradable_base --- examples/upgradable-examples/README.md | 65 ++++++++++++-------------- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/examples/upgradable-examples/README.md b/examples/upgradable-examples/README.md index 75e0951..72f4c95 100644 --- a/examples/upgradable-examples/README.md +++ b/examples/upgradable-examples/README.md @@ -1,8 +1,8 @@ # Example of using Upgradable plugin -Allows a contract to be upgraded by owner without having a Full Access Key. +Allows a contract to be upgraded by the owner without having a Full Access Key. -Contract example using Upgradable plugin. Note that it requires the contract to be Ownable. +Contract example using Upgradable plugin. Note, that it requires the contract to be Ownable. ```rust use near_plugins::{Ownable, Upgradable}; @@ -35,14 +35,8 @@ impl Counter1 { } ``` -The second example contract for upgrading you can find in the `../upgradable_base_second/` folder. - The second contract: ```rust -use near_plugins::{Ownable, Upgradable}; -use near_sdk::near_bindgen; -use borsh::{BorshSerialize, BorshDeserialize}; - #[near_bindgen] #[derive(Ownable, Upgradable, Default, BorshSerialize, BorshDeserialize)] struct Counter2 { @@ -72,8 +66,8 @@ To upgrade the contract first call up_stage_code passing the binary as first arg ## The contract methods description ### up_storage_key -`up_storage_key` is a _view_ method which return a key of storage slot for stage code. -By default `b"__CODE__"` is used. For changing the attribute `upgradable` can be used. +`up_storage_key` is a _view_ method that returns a key of the storage slot for stage code. +By default, `b"__CODE__"` is used. For changing, the attribute `upgradable` can be used. ```shell $ near view up_storage_key @@ -98,30 +92,33 @@ struct Counter { ``` ### up_stage_code -`up_stage_code` method to stage some code to be potentially deployed later. If a previous code was staged but not deployed, it is discarded. -Method can be called only by owner +`up_stage_code` is the method to stage some code to be potentially deployed later. If a previous code was staged but not deployed, it is discarded. +The method can be called only by the owner. ```shell $ export CODE=$(cat ../upgradable_base_second/target/wasm32-unknown-unknown/release/upgradable_base_second.wasm | xxd -ps | sed -z 's/\n//g') $ near call up_stage_code --base64 $CODE --accountId ``` -But it doesn't work in that way because we cann't provide in Bash so long args... So, probable here we can't use just NEAR CLI for interaction with contract :( +But it doesn't work in that way because we can't provide in Bash so long args... So, probable here we can't use just NEAR CLI for interaction with the contract :( -For running `up_satge_code` take a look on `src/up_stage_code.rs` script. +For running `up_satge_code` take a look on `up_stage_code/src/main.rs` script. ```shell -cargo run -- "" +$ cd up_stage_code +$ cargo run -- "" +$ cd .. ``` +Where `` is `$HOME/.near-credentials/testnet/.json` ### up_staged_code -`up_staged_code` a _view_ method which returns a staged code. +`up_staged_code` is a _view_ method which returns a staged code. ```shell $ near call up_staged_code --accountId ``` ### up_staged_code_hash -`up_staged_code_hash` a _view_ method which returns the hash of the staged code. +`up_staged_code_hash` is a _view_ method that returns the hash of the staged code. ```shell $ near view up_staged_code_hash @@ -135,41 +132,39 @@ View call: .up_staged_code_hash() ``` ### up_deploy_code -`up_deploy_code` method deploy a staged code. If no code is staged the method fails. -Method can be called only by owner +`up_deploy_code` is a method that deploys a staged code. If no code is staged, the method fails. +The method can be called only by the owner. ```shell -$ near call up_deploy_code --accountId +$ near call up_deploy_code --accountId ``` ## Preparation steps for demonstration -In that document we are providing some example of using contract with access control plugin. You also can explore the usage examples in the tests in `./src/lib.rs`. For running a tests please take a look to the **Test running instruction** section. - +In that document, we are providing some examples of using a contract with an access control plugin. You also can explore the usage examples in the tests in `upgradable_base/src/lib.rs`. For running tests please take a look at the **Test running instruction** section. 1. **Creating an account on testnet** + For demonstration let's create 2 accounts: ``, `` ```shell $ near create-account ..testnet --masterAccount .testnet --initialBalance 10 $ near create-account ..testnet --masterAccount .testnet --initialBalance 10 ``` - In the next section we will refer to the `..testnet` as ``, + In the next sections we will refer to the `..testnet` as ``, to the `..testnet` as ``. 2. **Compile 2 Contract to wasm file** - We should compile 2 contracts: `upgradable_base`, `upgradable_base_second`. ```shell + $ cd upgradable_base $ ./build.sh - $ cd ../upgradable_base_second - $ ./build.sh - $ cd ../upgradable_base + $ cd .. ``` - - The contracts will be compiled into `./target/wasm32-unknown-unknown/release/upgradable_base.wasm`, `../upgradable_base_second/target/wasm32-unknown-unknown/release/upgradable_base_second.wasm` + + The contracts will be compiled into `../target/wasm32-unknown-unknown/release/upgradable_base.wasm` and `../target/wasm32-unknown-unknown/release/upgradable_base_second.wasm` 3. **Deploy and init a contract** ```shell - $ near deploy --accountId --wasmFile ./target/wasm32-unknown-unknown/release/upgradable_base.wasm --initFunction new --initArgs '{}' + $ near deploy --accountId --wasmFile ../target/wasm32-unknown-unknown/release/upgradable_base.wasm --initFunction new --initArgs '{}' ``` ## Example of using the contract with upgradable plugin @@ -193,6 +188,8 @@ $ near view get_counter cargo run -- "" ``` +Where `` is `$HOME/.near-credentials/testnet/.json` + #### Deploy new contract ```shell $ near call up_deploy_code --accountId @@ -211,16 +208,16 @@ $ near view get_counter ``` ## Tests running instruction -Tests in `src/lib.rs` contain examples of interaction with a contract. +Tests in `upgradable_base/src/lib.rs` contain examples of interaction with a contract. For running test: -1. Generate `wasm` file by running `build.sh` script. The target file will be `target/wasm32-unknown-unknown/release/upgradable_base.wasm` +1. Generate `wasm` file by running `build.sh` script. The target file will be `../target/wasm32-unknown-unknown/release/upgradable_base.wasm` 2. Run tests `cargo test` ```shell +$ cd upgradable_base $ ./build.sh $ cargo test ``` -For tests, we use `workspaces` library and `sandbox` environment for details you can explorer `../near-plugins-test-utils` crate -contract_account. \ No newline at end of file +For tests, we use `workspaces` library and `sandbox` environment for details you can explorer `../near-plugins-test-utils` crate. \ No newline at end of file From 23977fa943b77466a6eef8d8e6bcf4ba53252c8f Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Mon, 24 Oct 2022 22:07:05 +0300 Subject: [PATCH 53/68] fix after rebase --- .../access_control_role_base/Cargo.toml | 1 + .../access_controllable_base/src/lib.rs | 3 +-- near-plugins-derive/src/access_controllable.rs | 1 - near-plugins-derive/src/ownable.rs | 1 - 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/access-controllable-examples/access_control_role_base/Cargo.toml b/examples/access-controllable-examples/access_control_role_base/Cargo.toml index 13e1b89..97ae676 100644 --- a/examples/access-controllable-examples/access_control_role_base/Cargo.toml +++ b/examples/access-controllable-examples/access_control_role_base/Cargo.toml @@ -13,3 +13,4 @@ near-plugins = { path = "../../../near-plugins" } near-plugins-derive = { path = "../../../near-plugins-derive" } bitflags = "1.3.2" borsh = "*" +near-sdk = "4.0.0" \ No newline at end of file diff --git a/examples/access-controllable-examples/access_controllable_base/src/lib.rs b/examples/access-controllable-examples/access_controllable_base/src/lib.rs index dd3df22..9b6ab08 100644 --- a/examples/access-controllable-examples/access_controllable_base/src/lib.rs +++ b/examples/access-controllable-examples/access_controllable_base/src/lib.rs @@ -4,7 +4,6 @@ use near_plugins_derive::access_control; use near_plugins_derive::access_control_any; use near_sdk::near_bindgen; use borsh::{BorshSerialize, BorshDeserialize}; -use near_plugins::events::AsEvent; use near_sdk::env; /// All types of access groups @@ -15,7 +14,7 @@ pub enum UsersGroups { } #[near_bindgen] -#[access_control(role_type="UsersGroups")] +#[access_control(role_type(UsersGroups))] #[derive(Default, BorshSerialize, BorshDeserialize)] struct Counter { counter: u64, diff --git a/near-plugins-derive/src/access_controllable.rs b/near-plugins-derive/src/access_controllable.rs index d3ef1e7..0722817 100644 --- a/near-plugins-derive/src/access_controllable.rs +++ b/near-plugins-derive/src/access_controllable.rs @@ -7,7 +7,6 @@ use proc_macro2::Span; use quote::quote; use syn::parse::Parser; use syn::{parse_macro_input, AttributeArgs, ItemFn, ItemStruct}; -use crate::utils; #[derive(Debug, FromMeta)] pub struct MacroArgs { diff --git a/near-plugins-derive/src/ownable.rs b/near-plugins-derive/src/ownable.rs index 0c48f23..08abcde 100644 --- a/near-plugins-derive/src/ownable.rs +++ b/near-plugins-derive/src/ownable.rs @@ -4,7 +4,6 @@ use darling::FromDeriveInput; use proc_macro::{self, TokenStream}; use quote::quote; use syn::{parse, parse_macro_input, DeriveInput, ItemFn}; -use crate::utils; #[derive(FromDeriveInput, Default)] #[darling(default, attributes(ownable), forward_attrs(allow, doc, cfg))] From 4dd588fbdea047ab09f6a69b8caf2c989782ecd4 Mon Sep 17 00:00:00 2001 From: Kirill Date: Mon, 24 Oct 2022 21:01:28 +0100 Subject: [PATCH 54/68] Apply suggestions from code review --- examples/upgradable-examples/upgradable_base/src/lib.rs | 4 ++-- near-plugins/src/upgradable.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/upgradable-examples/upgradable_base/src/lib.rs b/examples/upgradable-examples/upgradable_base/src/lib.rs index 605bc9a..104e1ef 100644 --- a/examples/upgradable-examples/upgradable_base/src/lib.rs +++ b/examples/upgradable-examples/upgradable_base/src/lib.rs @@ -75,7 +75,7 @@ mod tests { (owner, contract) } - async fn call_borsh_arg(contract: &Contract, method_name: &str, args: Vec) -> bool { + async fn call_method_with_borsh_args(contract: &Contract, method_name: &str, args: Vec) -> bool { contract.call(method_name) .args_borsh(args) .max_gas() @@ -97,7 +97,7 @@ mod tests { let wasm = std::fs::read(WASM_FILEPATH_SECOND).unwrap(); - assert!(call_borsh_arg(&contract, "up_stage_code", wasm).await); + assert!(call_method_with_borsh_args(&contract, "up_stage_code", wasm).await); assert!(call!(contract, "up_deploy_code").await); check_counter(&contract, 1).await; diff --git a/near-plugins/src/upgradable.rs b/near-plugins/src/upgradable.rs index 6630c6d..e52e83c 100644 --- a/near-plugins/src/upgradable.rs +++ b/near-plugins/src/upgradable.rs @@ -24,7 +24,7 @@ use near_sdk::{AccountId, CryptoHash, Promise}; use serde::Serialize; pub trait Upgradable { - /// Key of storage slot to save the stage code. + /// Key of storage slot to save the staged code. /// By default b"__CODE__" is used. fn up_storage_key(&self) -> Vec; From f6ea443a49f96634f23561dba5bf4bd13e7bd291 Mon Sep 17 00:00:00 2001 From: Kirill Date: Mon, 24 Oct 2022 21:02:25 +0100 Subject: [PATCH 55/68] Apply suggestions from code review: fix readme --- examples/upgradable-examples/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/upgradable-examples/README.md b/examples/upgradable-examples/README.md index 72f4c95..381e81f 100644 --- a/examples/upgradable-examples/README.md +++ b/examples/upgradable-examples/README.md @@ -220,4 +220,4 @@ $ ./build.sh $ cargo test ``` -For tests, we use `workspaces` library and `sandbox` environment for details you can explorer `../near-plugins-test-utils` crate. \ No newline at end of file +For tests, we use `workspaces` library and `sandbox` environment. For details, you can explore `../near-plugins-test-utils` crate. \ No newline at end of file From f5b3b05e9f8c9e00acc45a5ed6d119d1d8d3c553 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Tue, 25 Oct 2022 09:50:50 +0300 Subject: [PATCH 56/68] merge 2 upgradable contracts --- .../access-controllable-examples/README.md | 2 +- .../README.md | 2 +- examples/ownable-examples/README.md | 2 +- examples/pausable-examples/README.md | 2 +- .../upgradable_base/src/lib.rs | 40 +++++-------------- 5 files changed, 13 insertions(+), 35 deletions(-) diff --git a/examples/access-controllable-examples/README.md b/examples/access-controllable-examples/README.md index 5a65d06..55c17b9 100644 --- a/examples/access-controllable-examples/README.md +++ b/examples/access-controllable-examples/README.md @@ -271,4 +271,4 @@ $ ./build.sh $ cargo test ``` -For tests, we use `workspaces` library and `sandbox` environment for details you can explorer `../near-plugins-test-utils` crate. \ No newline at end of file +For tests, we use `workspaces` library and `sandbox` environment. For details, you can explore `../near-plugins-test-utils` crate. \ No newline at end of file diff --git a/examples/full-access-key-fallback-examples/README.md b/examples/full-access-key-fallback-examples/README.md index 4e8fb55..78848c4 100644 --- a/examples/full-access-key-fallback-examples/README.md +++ b/examples/full-access-key-fallback-examples/README.md @@ -121,4 +121,4 @@ $ ./build.sh $ cargo test ``` -For tests, we use `workspaces` library and `sandbox` environment for details you can explorer `../near-plugins-test-utils` crate. \ No newline at end of file +For tests, we use `workspaces` library and `sandbox` environment. For details, you can explore `../near-plugins-test-utils` crate. \ No newline at end of file diff --git a/examples/ownable-examples/README.md b/examples/ownable-examples/README.md index 9474931..f01c2fd 100644 --- a/examples/ownable-examples/README.md +++ b/examples/ownable-examples/README.md @@ -288,4 +288,4 @@ $ ./build.sh $ cargo test ``` -For tests, we use `workspaces` library and `sandbox` environment for details you can explorer `../near-plugins-test-utils` crate. \ No newline at end of file +For tests, we use `workspaces` library and `sandbox` environment. For details, you can explore `../near-plugins-test-utils` crate. \ No newline at end of file diff --git a/examples/pausable-examples/README.md b/examples/pausable-examples/README.md index 26641ad..00b8848 100644 --- a/examples/pausable-examples/README.md +++ b/examples/pausable-examples/README.md @@ -239,4 +239,4 @@ $ ./build.sh $ cargo test ``` -For tests, we use `workspaces` library and `sandbox` environment for details you can explorer `../near-plugins-test-utils` crate. \ No newline at end of file +For tests, we use `workspaces` library and `sandbox` environment. For details, you can explore `../near-plugins-test-utils` crate. \ No newline at end of file diff --git a/examples/upgradable-examples/upgradable_base/src/lib.rs b/examples/upgradable-examples/upgradable_base/src/lib.rs index 104e1ef..0b8a8d7 100644 --- a/examples/upgradable-examples/upgradable_base/src/lib.rs +++ b/examples/upgradable-examples/upgradable_base/src/lib.rs @@ -4,41 +4,13 @@ use borsh::{BorshSerialize, BorshDeserialize}; #[near_bindgen] #[derive(Ownable, Upgradable, Default, BorshSerialize, BorshDeserialize)] -#[cfg(feature = "counter1")] -struct Counter1 { +struct Counter { counter: u64, } #[near_bindgen] -#[cfg(feature = "counter1")] -impl Counter1 { - /// Specify the owner of the contract in the constructor - #[init] - pub fn new() -> Self { - let mut contract = Self { counter: 0 }; - contract.owner_set(Some(near_sdk::env::predecessor_account_id())); - contract - } - - pub fn inc1(&mut self) { - self.counter += 1; - } - - pub fn get_counter(&self) -> u64 { - self.counter - } -} - -#[near_bindgen] -#[derive(Ownable, Upgradable, Default, BorshSerialize, BorshDeserialize)] -#[cfg(feature = "counter2")] -struct Counter2 { - counter: u64, -} - -#[near_bindgen] -#[cfg(feature = "counter2")] -impl Counter2 { +impl Counter { + /// Specify the owner of the contract in the constructor #[init] pub fn new() -> Self { let mut contract = Self { counter: 0 }; @@ -46,6 +18,12 @@ impl Counter2 { contract } + #[cfg(feature = "counter1")] + pub fn inc1(&mut self) { + self.counter += 1; + } + + #[cfg(feature = "counter2")] pub fn inc2(&mut self) { self.counter += 2; } From 5c8f7548888eaa6f0c2d2cb10b28604a1e9c9c49 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Thu, 27 Oct 2022 11:32:23 +0300 Subject: [PATCH 57/68] copy wasm file to res folder --- .../access_controllable_base/build.sh | 6 +++++- .../full_access_key_fallback_base/build.sh | 6 +++++- examples/ownable-examples/ownable_base/build.sh | 6 +++++- .../ownable-examples/ownable_change_storage_key/build.sh | 6 +++++- examples/ownable-examples/ownable_cross_call/build.sh | 6 +++++- examples/pausable-examples/pausable_base/build.sh | 6 +++++- examples/upgradable-examples/upgradable_base/build.sh | 5 +++++ 7 files changed, 35 insertions(+), 6 deletions(-) diff --git a/examples/access-controllable-examples/access_controllable_base/build.sh b/examples/access-controllable-examples/access_controllable_base/build.sh index 5fb19d6..4900904 100755 --- a/examples/access-controllable-examples/access_controllable_base/build.sh +++ b/examples/access-controllable-examples/access_controllable_base/build.sh @@ -1,3 +1,7 @@ #!/usr/bin/env bash -RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release \ No newline at end of file +mkdir -p ../../res + +RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release + +cp ../../target/wasm32-unknown-unknown/release/access_controllable_base.wasm ../../res/ \ No newline at end of file diff --git a/examples/full-access-key-fallback-examples/full_access_key_fallback_base/build.sh b/examples/full-access-key-fallback-examples/full_access_key_fallback_base/build.sh index 5fb19d6..cf95844 100755 --- a/examples/full-access-key-fallback-examples/full_access_key_fallback_base/build.sh +++ b/examples/full-access-key-fallback-examples/full_access_key_fallback_base/build.sh @@ -1,3 +1,7 @@ #!/usr/bin/env bash -RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release \ No newline at end of file +mkdir -p ../../res + +RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release + +cp ../../target/wasm32-unknown-unknown/release/full_access_key_fallback_base.wasm ../../res/ \ No newline at end of file diff --git a/examples/ownable-examples/ownable_base/build.sh b/examples/ownable-examples/ownable_base/build.sh index 5fb19d6..7f2cc33 100755 --- a/examples/ownable-examples/ownable_base/build.sh +++ b/examples/ownable-examples/ownable_base/build.sh @@ -1,3 +1,7 @@ #!/usr/bin/env bash -RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release \ No newline at end of file +mkdir -p ../../res + +RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release + +cp ../../target/wasm32-unknown-unknown/release/ownable_base.wasm ../../res/ \ No newline at end of file diff --git a/examples/ownable-examples/ownable_change_storage_key/build.sh b/examples/ownable-examples/ownable_change_storage_key/build.sh index 5fb19d6..f41c331 100755 --- a/examples/ownable-examples/ownable_change_storage_key/build.sh +++ b/examples/ownable-examples/ownable_change_storage_key/build.sh @@ -1,3 +1,7 @@ #!/usr/bin/env bash -RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release \ No newline at end of file +mkdir -p ../../res + +RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release + +cp ../../target/wasm32-unknown-unknown/release/ownable_change_storage_key.wasm ../../res/ \ No newline at end of file diff --git a/examples/ownable-examples/ownable_cross_call/build.sh b/examples/ownable-examples/ownable_cross_call/build.sh index 5fb19d6..6afc0e1 100755 --- a/examples/ownable-examples/ownable_cross_call/build.sh +++ b/examples/ownable-examples/ownable_cross_call/build.sh @@ -1,3 +1,7 @@ #!/usr/bin/env bash -RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release \ No newline at end of file +mkdir -p ../../res + +RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release + +cp ../../target/wasm32-unknown-unknown/release/ownable_cross_call.wasm ../../res/ \ No newline at end of file diff --git a/examples/pausable-examples/pausable_base/build.sh b/examples/pausable-examples/pausable_base/build.sh index 5fb19d6..86f59f2 100755 --- a/examples/pausable-examples/pausable_base/build.sh +++ b/examples/pausable-examples/pausable_base/build.sh @@ -1,3 +1,7 @@ #!/usr/bin/env bash -RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release \ No newline at end of file +mkdir -p ../../res + +RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release + +cp ../../target/wasm32-unknown-unknown/release/pausable_base.wasm ../../res/ \ No newline at end of file diff --git a/examples/upgradable-examples/upgradable_base/build.sh b/examples/upgradable-examples/upgradable_base/build.sh index cda79e1..7429687 100755 --- a/examples/upgradable-examples/upgradable_base/build.sh +++ b/examples/upgradable-examples/upgradable_base/build.sh @@ -1,5 +1,10 @@ #!/usr/bin/env bash +mkdir -p ../../res + RUSTFLAGS='-C link-arg=-s' cargo build --features "counter2" --target wasm32-unknown-unknown --release mv ../../target/wasm32-unknown-unknown/release/upgradable_base.wasm ../../target/wasm32-unknown-unknown/release/upgradable_base_second.wasm RUSTFLAGS='-C link-arg=-s' cargo build --features "counter1" --target wasm32-unknown-unknown --release + +cp ../../target/wasm32-unknown-unknown/release/upgradable_base_second.wasm ../../res/ +cp ../../target/wasm32-unknown-unknown/release/upgradable_base.wasm ../../res/ \ No newline at end of file From a334a44069b91318440e1a87c74f219a248b9920 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Thu, 27 Oct 2022 11:38:32 +0300 Subject: [PATCH 58/68] fix access control init --- .../access-controllable-examples/README.md | 81 +++++++++---------- .../access_controllable_base/src/lib.rs | 70 +++++++++++----- 2 files changed, 91 insertions(+), 60 deletions(-) diff --git a/examples/access-controllable-examples/README.md b/examples/access-controllable-examples/README.md index 55c17b9..327bac0 100644 --- a/examples/access-controllable-examples/README.md +++ b/examples/access-controllable-examples/README.md @@ -9,61 +9,60 @@ use near_plugins_derive::access_control; use near_plugins_derive::access_control_any; use near_sdk::near_bindgen; use borsh::{BorshSerialize, BorshDeserialize}; -use near_plugins::events::AsEvent; use near_sdk::env; /// All types of access groups #[derive(AccessControlRole, Clone, Copy)] pub enum UsersGroups { - GroupA, - GroupB, + GroupA, + GroupB, } #[near_bindgen] -#[access_control(role_type="UsersGroups")] +#[access_control(role_type(UsersGroups))] #[derive(Default, BorshSerialize, BorshDeserialize)] struct Counter { - counter: u64, + counter: u64, } #[near_bindgen] impl Counter { - /// In the constructor we set up a super admin, - /// which can control the member lists of all user groups - #[init] - pub fn new() -> Self { - let mut contract: Counter = Self{ - counter: 0, - __acl: __Acl::default(), - }; - - contract.__acl.init_super_admin(&near_sdk::env::predecessor_account_id()); - - contract - } - - /// unprotected function, every one can call this function - pub fn unprotected(&mut self) { - self.counter += 1; - } - - /// only the users from GroupA can call this method - #[access_control_any(roles(UsersGroups::GroupA))] - pub fn level_a_incr(&mut self) { - self.counter += 1; - } - - /// only the users from GroupA or GroupB can call this method - #[access_control_any(roles(UsersGroups::GroupA, UsersGroups::GroupB))] - pub fn level_ab_incr(&mut self) { - self.counter += 1; - } - - - /// view method for get current counter value, every one can use it - pub fn get_counter(&self) -> u64 { - self.counter - } + /// In the constructor we set up a super admin, + /// which can control the member lists of all user groups + #[init] + pub fn new() -> Self { + let mut contract: Counter = Self{ + counter: 0, + __acl: __Acl::default(), + }; + + contract.acl_init_super_admin(near_sdk::env::predecessor_account_id()); + + contract + } + + /// unprotected function, every one can call this function + pub fn unprotected(&mut self) { + self.counter += 1; + } + + /// only the users from GroupA can call this method + #[access_control_any(roles(UsersGroups::GroupA))] + pub fn level_a_incr(&mut self) { + self.counter += 1; + } + + /// only the users from GroupA or GroupB can call this method + #[access_control_any(roles(UsersGroups::GroupA, UsersGroups::GroupB))] + pub fn level_ab_incr(&mut self) { + self.counter += 1; + } + + + /// view method for get current counter value, every one can use it + pub fn get_counter(&self) -> u64 { + self.counter + } } ``` diff --git a/examples/access-controllable-examples/access_controllable_base/src/lib.rs b/examples/access-controllable-examples/access_controllable_base/src/lib.rs index 9b6ab08..ff63a45 100644 --- a/examples/access-controllable-examples/access_controllable_base/src/lib.rs +++ b/examples/access-controllable-examples/access_controllable_base/src/lib.rs @@ -1,10 +1,10 @@ -use near_plugins::AccessControllable; +use borsh::{BorshDeserialize, BorshSerialize}; use near_plugins::AccessControlRole; +use near_plugins::AccessControllable; use near_plugins_derive::access_control; use near_plugins_derive::access_control_any; -use near_sdk::near_bindgen; -use borsh::{BorshSerialize, BorshDeserialize}; use near_sdk::env; +use near_sdk::near_bindgen; /// All types of access groups #[derive(AccessControlRole, Clone, Copy)] @@ -17,7 +17,7 @@ pub enum UsersGroups { #[access_control(role_type(UsersGroups))] #[derive(Default, BorshSerialize, BorshDeserialize)] struct Counter { - counter: u64, + counter: u64, } #[near_bindgen] @@ -26,12 +26,12 @@ impl Counter { /// which can control the member lists of all user groups #[init] pub fn new() -> Self { - let mut contract: Counter = Self{ + let mut contract: Counter = Self { counter: 0, __acl: __Acl::default(), }; - contract.__acl.init_super_admin(&near_sdk::env::predecessor_account_id()); + contract.acl_init_super_admin(near_sdk::env::predecessor_account_id()); contract } @@ -53,26 +53,25 @@ impl Counter { self.counter += 1; } - /// view method for get current counter value, every one can use it pub fn get_counter(&self) -> u64 { self.counter } } - #[cfg(test)] mod tests { - use serde_json::json; use crate::UsersGroups; use near_plugins_test_utils::*; + use serde_json::json; - const WASM_FILEPATH: &str = "../../target/wasm32-unknown-unknown/release/access_controllable_base.wasm"; + const WASM_FILEPATH: &str = + "../../target/wasm32-unknown-unknown/release/access_controllable_base.wasm"; #[tokio::test] async fn base_scenario() { let (contract_holder, contract) = get_contract(WASM_FILEPATH).await; - assert!(call!(contract,"new").await); + assert!(call!(contract, "new").await); check_counter(&contract, 0).await; @@ -82,15 +81,30 @@ mod tests { let alice = get_subaccount(&contract_holder, "alice").await; - let is_super_admin: bool = view!(contract, "acl_is_super_admin", &json!({"account_id": alice.id()})); + let is_super_admin: bool = view!( + contract, + "acl_is_super_admin", + &json!({"account_id": alice.id()}) + ); assert!(!is_super_admin); assert!(!call!(&alice, contract, "level_a_incr").await); check_counter(&contract, 1).await; - assert!(call!(contract, "acl_grant_role", &json!({"role": String::from(UsersGroups::GroupA), "account_id": alice.id()})).await); - - let alice_has_role: bool = view!(contract, "acl_has_role", &json!({"role": String::from(UsersGroups::GroupA), "account_id": alice.id()})); + assert!( + call!( + contract, + "acl_grant_role", + &json!({"role": String::from(UsersGroups::GroupA), "account_id": alice.id()}) + ) + .await + ); + + let alice_has_role: bool = view!( + contract, + "acl_has_role", + &json!({"role": String::from(UsersGroups::GroupA), "account_id": alice.id()}) + ); assert!(alice_has_role); assert!(call!(&alice, contract, "level_a_incr").await); @@ -98,9 +112,20 @@ mod tests { check_counter(&contract, 2).await; let bob = get_subaccount(&contract_holder, "bob").await; - assert!(call!(contract, "acl_add_admin", &json!({"role": String::from(UsersGroups::GroupA), "account_id": bob.id()})).await); - - let bob_is_admin: bool = view!(contract, "acl_is_admin", &json!({"role": String::from(UsersGroups::GroupA), "account_id": bob.id()})); + assert!( + call!( + contract, + "acl_add_admin", + &json!({"role": String::from(UsersGroups::GroupA), "account_id": bob.id()}) + ) + .await + ); + + let bob_is_admin: bool = view!( + contract, + "acl_is_admin", + &json!({"role": String::from(UsersGroups::GroupA), "account_id": bob.id()}) + ); assert!(bob_is_admin); assert!(!call!(&bob, contract, "level_a_incr").await); @@ -113,7 +138,14 @@ mod tests { assert!(!call!(&bob, contract, "level_ab_incr").await); check_counter(&contract, 3).await; - assert!(call!(contract, "acl_grant_role", &json!({"role": String::from(UsersGroups::GroupB), "account_id": bob.id()})).await); + assert!( + call!( + contract, + "acl_grant_role", + &json!({"role": String::from(UsersGroups::GroupB), "account_id": bob.id()}) + ) + .await + ); assert!(call!(&bob, contract, "level_ab_incr").await); check_counter(&contract, 4).await; From 6fd1a4a364b2180df630ee7c4a85b3718c14c89d Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Thu, 27 Oct 2022 11:49:31 +0300 Subject: [PATCH 59/68] the admin -> an admin --- examples/access-controllable-examples/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/access-controllable-examples/README.md b/examples/access-controllable-examples/README.md index 327bac0..91c1785 100644 --- a/examples/access-controllable-examples/README.md +++ b/examples/access-controllable-examples/README.md @@ -97,14 +97,14 @@ true ### acl_add_admin `acl_add_admin` is a method that adds a new admin for a specific group. Admins' rights don't allow running group-specific functions, but group admins can control the group member list. -This method can be run by the admin of a specific group or by the super admin. +This method can be run by an admin of a specific group or by a super admin. ```shell $ near call acl_add_admin '{"role": "GroupA", "account_id": ""}' --accountId ``` ### acl_is_admin -`acl_is_admin` is a _view_ method that checks if the account has an admin right for the specified group. For super admin, it will return true. +`acl_is_admin` is a _view_ method that checks if the account has an admin right for the specified group. For super admin, it will return true for every group. ```shell $ near view acl_is_admin '{"role": "GroupA", "account_id": ""}' @@ -113,7 +113,7 @@ true ``` ### acl_revoke_admin -`acl_revoke_admin` is a method that removes the group admin right for a specific account. Can be executed by the admin of this group or by the super admin. +`acl_revoke_admin` is a method that removes the group admin right for a specific account. Can be executed by an admin of this group or by a super admin. ```shell $ near call acl_revoke_admin '{"role": "GroupA", "account_id": ""}' --accountId @@ -129,8 +129,8 @@ $ near call acl_renounce_admin '{"role": "GroupA"}' --account After calling that method, Alice will not have the admin right for GroupA anymore. ### acl_revoke_role -`acl_revoke_role` is a method that removes the specified account from the list of the group member. -Only the group admin or super admin can execute this function. +`acl_revoke_role` is a method that removes the specified account from the list of the group members. +Only a group admin or a super admin can execute this function. ```shell $ near call acl_revoke_role '{"role": "GroupA", "account_id": ""}' --accountId @@ -144,7 +144,7 @@ $ near call acl_renounce_role '{"role": "GroupA"}' --accountI ``` ### acl_grant_role -`acl_grant_role` is a method that adds the account to the group member list. Can be executed only by the group admin or by the super admin. +`acl_grant_role` is a method that adds the account to the group member list. Can be executed only by a group admin or by a super admin. ```shell $ near call acl_grant_role '{"role": "GroupA", "account_id": ""}' --accountId From c11247d4f3fc1f49a14fd6560235b8b3b22b4751 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Thu, 27 Oct 2022 12:09:43 +0300 Subject: [PATCH 60/68] add example of changing storage_prefix --- examples/access-controllable-examples/README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/examples/access-controllable-examples/README.md b/examples/access-controllable-examples/README.md index 91c1785..b863df6 100644 --- a/examples/access-controllable-examples/README.md +++ b/examples/access-controllable-examples/README.md @@ -84,6 +84,16 @@ $ python3 95 95 97 99 108 ``` +Example of changing acl storage prefix key: +```rust +#[near_bindgen] +#[access_control(role_type(UsersGroups), storage_prefix = "__custom_prefix")] +#[derive(Default, BorshSerialize, BorshDeserialize)] +struct Counter { + counter: u64, +} +``` + ### acl_is_super_admin `acl_is_super_admin` is a _view_ method that checks that account has super admin rights. Super admin can control the member list of each group and control the admin list for each group. From 6ce74158b38e3243b03abbe8b25d827601c1547b Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Thu, 27 Oct 2022 13:17:45 +0300 Subject: [PATCH 61/68] acl_init_super_admin and acl_get_super_admin discription --- .../access-controllable-examples/README.md | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/examples/access-controllable-examples/README.md b/examples/access-controllable-examples/README.md index b863df6..b92bd93 100644 --- a/examples/access-controllable-examples/README.md +++ b/examples/access-controllable-examples/README.md @@ -94,6 +94,18 @@ struct Counter { } ``` +### acl_init_super_admin +`acl_init_super_admin` is a method that adds `account_id` as a super-admin _without_ checking any permissions +in case there are no super-admins. Do nothing if at least one super-admin exists. This function can be used to add a super-admin during contract initialization. +Moreover, it may provide a recovery mechanism if (mistakenly) all super-admins have been removed. +The return value indicates whether `account_id` was added as super-admin. + +It is `#[private]` in the implementation provided by this trait, i.e. only the contract itself may call this method. + +```shell +$ near call acl_init_super_admin '{"account_id": ""}' --accountId +``` + ### acl_is_super_admin `acl_is_super_admin` is a _view_ method that checks that account has super admin rights. Super admin can control the member list of each group and control the admin list for each group. @@ -178,6 +190,15 @@ View call: .acl_has_any_role({"roles": ["GroupA", "GroupB"], " true ``` +### acl_get_super_admins +`acl_get_super_admins` is a _view_ method that shows some super admins. It will skip first `skip` admins and return not more than `limit` number of super admins. + +```shell +$ near view acl_get_super_admins '{"skip": 0, "limit": 2}' +View call: .acl_get_super_admins({"skip": 0, "limit": 2}) +[ '' ] +``` + ### acl_get_admins `acl_get_admins` is a _view_ method that shows some admins of the group. It will skip first `skip` admins and return not more than `limit` number of admins. From b11fc7aa6e5e6a80507d0cb461eadad5d18c6fc9 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Fri, 28 Oct 2022 15:26:19 +0300 Subject: [PATCH 62/68] add emitted events description --- .../access-controllable-examples/README.md | 94 +++++++++++++++++++ .../access_controllable_base/src/lib.rs | 3 + .../README.md | 13 +++ examples/ownable-examples/README.md | 14 +++ examples/pausable-examples/README.md | 27 ++++++ 5 files changed, 151 insertions(+) diff --git a/examples/access-controllable-examples/README.md b/examples/access-controllable-examples/README.md index b92bd93..3f24b23 100644 --- a/examples/access-controllable-examples/README.md +++ b/examples/access-controllable-examples/README.md @@ -106,6 +106,19 @@ It is `#[private]` in the implementation provided by this trait, i.e. only the c $ near call acl_init_super_admin '{"account_id": ""}' --accountId ``` +If the method succeeds, the following event will be emitted: +```json +{ + "standard":"AccessControllable", + "version":"1.0.0", + "event":"super_admin_added", + "data":{ + "account":"test.near", + "by":"test.near" + } +} +``` + ### acl_is_super_admin `acl_is_super_admin` is a _view_ method that checks that account has super admin rights. Super admin can control the member list of each group and control the admin list for each group. @@ -125,6 +138,20 @@ This method can be run by an admin of a specific group or by a super admin. $ near call acl_add_admin '{"role": "GroupA", "account_id": ""}' --accountId ``` +If the method succeeds, the following event will be emitted: +```json +{ + "standard":"AccessControllable", + "version":"1.0.0", + "event":"admin_added", + "data": { + "role":"GroupA", + "account":"", + "by":"" + } +} +``` + ### acl_is_admin `acl_is_admin` is a _view_ method that checks if the account has an admin right for the specified group. For super admin, it will return true for every group. @@ -140,6 +167,19 @@ true ```shell $ near call acl_revoke_admin '{"role": "GroupA", "account_id": ""}' --accountId ``` +If the method succeeds, the following event will be emitted: +```json +{ + "standard":"AccessControllable", + "version":"1.0.0", + "event":"admin_revoked", + "data":{ + "role":"GroupA", + "account":"", + "by":"" + } +} +``` ### acl_renounce_admin `acl_renounce_admin` is a method that removes the group admin right for an account that calls the method. @@ -150,6 +190,19 @@ $ near call acl_renounce_admin '{"role": "GroupA"}' --account After calling that method, Alice will not have the admin right for GroupA anymore. +If the method succeeds, the following event will be emitted: +```json +{ + "standard":"AccessControllable", + "version":"1.0.0", + "event":"admin_revoked", + "data":{ + "role":"GroupA", + "account":"", + "by":"" + } +} +``` ### acl_revoke_role `acl_revoke_role` is a method that removes the specified account from the list of the group members. Only a group admin or a super admin can execute this function. @@ -158,6 +211,20 @@ Only a group admin or a super admin can execute this function. $ near call acl_revoke_role '{"role": "GroupA", "account_id": ""}' --accountId ``` +If the method succeeds, the following event will be emitted: +```json +{ + "standard":"AccessControllable", + "version":"1.0.0", + "event":"role_revoked", + "data": { + "role":"GroupA", + "from":"", + "by":"" + } +} +``` + ### acl_renounce_role `acl_renounce_role` is a method that removes the caller account from the member list of the group. Can be called by anyone. @@ -165,6 +232,19 @@ $ near call acl_revoke_role '{"role": "GroupA", "account_id": $ near call acl_renounce_role '{"role": "GroupA"}' --accountId ``` +If the method succeeds, the following event will be emitted: +```json +{ + "standard":"AccessControllable", + "version":"1.0.0", + "event":"role_revoked", + "data": { + "role":"GroupA", + "from":"", + "by":"" + } +} +``` ### acl_grant_role `acl_grant_role` is a method that adds the account to the group member list. Can be executed only by a group admin or by a super admin. @@ -172,6 +252,20 @@ $ near call acl_renounce_role '{"role": "GroupA"}' --accountI $ near call acl_grant_role '{"role": "GroupA", "account_id": ""}' --accountId ``` +If the method succeeds, the following event will be emitted: +```json +{ + "standard":"AccessControllable", + "version":"1.0.0", + "event":"role_granted", + "data": { + "role":"GroupA", + "to":"", + "by":"" + } +} +``` + ### acl_has_role `acl_has_role` is a _view_ method for checking if the account is a member of the specified group. diff --git a/examples/access-controllable-examples/access_controllable_base/src/lib.rs b/examples/access-controllable-examples/access_controllable_base/src/lib.rs index ff63a45..681f0e8 100644 --- a/examples/access-controllable-examples/access_controllable_base/src/lib.rs +++ b/examples/access-controllable-examples/access_controllable_base/src/lib.rs @@ -151,5 +151,8 @@ mod tests { assert!(!call!(&bob, contract, "level_a_incr").await); check_counter(&contract, 4).await; + + assert!(call!(&bob, contract, "acl_renounce_admin", &json!({"role": String::from(UsersGroups::GroupA)})).await); + assert!(call!(&alice, contract, "acl_renounce_role", &json!({"role": String::from(UsersGroups::GroupA)})).await); } } diff --git a/examples/full-access-key-fallback-examples/README.md b/examples/full-access-key-fallback-examples/README.md index 78848c4..4063ffd 100644 --- a/examples/full-access-key-fallback-examples/README.md +++ b/examples/full-access-key-fallback-examples/README.md @@ -47,6 +47,19 @@ Only the owner of the contract can use this function. near call attach_full_access_key '{"public_key": "ed25519:ErVTCTvmepb4NDhQ7infTomkLVsd1iTWwLR84FBhV7UC"}' --accountId ``` +If the method succeeds, the following event will be emitted: +```json +{ + "standard":"FullAccessKeyFallback", + "version":"1.0.0", + "event":"full_access_key_added", + "data": { + "by":"", + "public_key":"ed25519:ErVTCTvmepb4NDhQ7infTomkLVsd1iTWwLR84FBhV7UC" + } +} +``` + ## Preparation steps for demonstration In that document, we are providing some examples of using a contract with a full access key fallback plugin. You also can explore the usage examples in the tests in `./full_access_key_fallback_base/src/lib.rs`. For running tests, please take a look at the **Test running instruction** section. diff --git a/examples/ownable-examples/README.md b/examples/ownable-examples/README.md index f01c2fd..3be283e 100644 --- a/examples/ownable-examples/README.md +++ b/examples/ownable-examples/README.md @@ -63,6 +63,20 @@ If the contract doesn't have any owner, the self can set one. $ near call owner_set '{"owner": }' --accountId ``` +If the ownership transfer were successful following event will be emitted: +```json +{ + "standard":"Ownable", + "version":"1.0.0", + "event":"ownership_transferred", + "data": { + "previous_owner":"", + "new_owner":"" + } +} +``` + + ### owner_get `owner_get` is the _view_ method, which returns the current contract owner. diff --git a/examples/pausable-examples/README.md b/examples/pausable-examples/README.md index 00b8848..e0f2439 100644 --- a/examples/pausable-examples/README.md +++ b/examples/pausable-examples/README.md @@ -127,12 +127,39 @@ View call: .pa_all_paused() $ near call pa_pause_feature '{"key": "increase_1"}' --accountId ``` +If the method succeeds, the following event will be emitted: +```json +{ + "standard":"Pausable", + "version":"1.0.0", + "event":"pause", + "data": + { + "by":"", + "key":"increase_1" + } +} +``` + ### pa_unpause_feature `pa_unpause_feature` is a method for unpausing specified features. Can be run only by the owner or self. ```shell $ near call pa_unpause_feature '{"key": "increase_1"}' --accountId ``` +If the method succeeds, the following event will be emitted: +```json +{ + "standard":"Pausable", + "version":"1.0.0", + "event":"unpause", + "data": + { + "by":"", + "key":"increase_1" + } +} +``` ## Preparation steps for demonstration In that document, we are providing some examples of using a contract with access control plugins. You also can explore the usage examples in the tests in `./pausable_base/src/lib.rs`. For running tests, please take a look at the **Test running instruction** section. From 22213f680995948fecbb660967c797e5c9ef06af Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Fri, 28 Oct 2022 18:02:33 +0300 Subject: [PATCH 63/68] add information about return values --- .../access-controllable-examples/README.md | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/examples/access-controllable-examples/README.md b/examples/access-controllable-examples/README.md index 3f24b23..fbee010 100644 --- a/examples/access-controllable-examples/README.md +++ b/examples/access-controllable-examples/README.md @@ -98,12 +98,14 @@ struct Counter { `acl_init_super_admin` is a method that adds `account_id` as a super-admin _without_ checking any permissions in case there are no super-admins. Do nothing if at least one super-admin exists. This function can be used to add a super-admin during contract initialization. Moreover, it may provide a recovery mechanism if (mistakenly) all super-admins have been removed. -The return value indicates whether `account_id` was added as super-admin. + +**Return value:** the return value indicates whether `account_id` was added as super-admin. It is `#[private]` in the implementation provided by this trait, i.e. only the contract itself may call this method. ```shell $ near call acl_init_super_admin '{"account_id": ""}' --accountId +true ``` If the method succeeds, the following event will be emitted: @@ -134,8 +136,13 @@ true Admins' rights don't allow running group-specific functions, but group admins can control the group member list. This method can be run by an admin of a specific group or by a super admin. +**Return value:** in case of sufficient permissions, the returned `Some(bool)` indicates +whether `account_id` is a new admin for `role`. Without permissions, +`None` is returned and internal state is not modified. + ```shell $ near call acl_add_admin '{"role": "GroupA", "account_id": ""}' --accountId +true ``` If the method succeeds, the following event will be emitted: @@ -164,9 +171,15 @@ true ### acl_revoke_admin `acl_revoke_admin` is a method that removes the group admin right for a specific account. Can be executed by an admin of this group or by a super admin. +**Return value:** in case of sufficient permissions, the returned `Some(bool)` indicates +whether `account_id` was an admin for `role`. Without permissions, +`None` is returned and internal state is not modified. + ```shell $ near call acl_revoke_admin '{"role": "GroupA", "account_id": ""}' --accountId +true ``` + If the method succeeds, the following event will be emitted: ```json { @@ -184,8 +197,11 @@ If the method succeeds, the following event will be emitted: ### acl_renounce_admin `acl_renounce_admin` is a method that removes the group admin right for an account that calls the method. +**Return value:** returns whether the predecessor was an admin for `role`. + ```shell $ near call acl_renounce_admin '{"role": "GroupA"}' --accountId +true ``` After calling that method, Alice will not have the admin right for GroupA anymore. @@ -207,8 +223,13 @@ If the method succeeds, the following event will be emitted: `acl_revoke_role` is a method that removes the specified account from the list of the group members. Only a group admin or a super admin can execute this function. +**Return value:** in case of sufficient permissions, the returned `Some(bool)` indicates +whether `account_id` was a grantee of `role`. Without permissions, +`None` is returned and internal state is not modified. + ```shell $ near call acl_revoke_role '{"role": "GroupA", "account_id": ""}' --accountId +true ``` If the method succeeds, the following event will be emitted: @@ -228,8 +249,11 @@ If the method succeeds, the following event will be emitted: ### acl_renounce_role `acl_renounce_role` is a method that removes the caller account from the member list of the group. Can be called by anyone. +**Return value:** returns whether it was a grantee of `role`. + ```shell $ near call acl_renounce_role '{"role": "GroupA"}' --accountId +true ``` If the method succeeds, the following event will be emitted: @@ -248,8 +272,13 @@ If the method succeeds, the following event will be emitted: ### acl_grant_role `acl_grant_role` is a method that adds the account to the group member list. Can be executed only by a group admin or by a super admin. +**Return value:** in case of sufficient permissions, the returned `Some(bool)` indicates +whether `account_id` is a new grantee of `role`. Without permissions, +`None` is returned and internal state is not modified. + ```shell $ near call acl_grant_role '{"role": "GroupA", "account_id": ""}' --accountId +true ``` If the method succeeds, the following event will be emitted: From 11d70922522de90f6f978b4353e5c6d025a84988 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Sat, 29 Oct 2022 15:01:42 +0300 Subject: [PATCH 64/68] two super admins --- .../access-controllable-examples/README.md | 23 +++++++++ .../access_controllable_base/src/lib.rs | 48 ++++++++++++++++++- 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/examples/access-controllable-examples/README.md b/examples/access-controllable-examples/README.md index fbee010..b50240c 100644 --- a/examples/access-controllable-examples/README.md +++ b/examples/access-controllable-examples/README.md @@ -411,6 +411,29 @@ $ near view get_counter 2 ``` +### A few super admins +There may be two or more super admins. +By default, there are no interfaces that allow you to add or remove super admins. +You can add the corresponding functions to the contract as follows: + +```rust +/// method for adding new super admin +pub fn add_super_admin(&mut self, new_super_admin_account_id: &AccountId) { + ::near_sdk::require!(self.__acl.is_super_admin(&near_sdk::env::predecessor_account_id()), + "Method can be run only by super admin"); + self.__acl.add_super_admin_unchecked(new_super_admin_account_id); +} + +/// method for removing super admin +pub fn remove_super_admin(&mut self, super_admin_account_id: &AccountId) { + ::near_sdk::require!(self.__acl.is_super_admin(&near_sdk::env::predecessor_account_id()), + "Method can be run only by super admin"); + self.__acl.revoke_super_admin_unchecked(&super_admin_account_id); +} +``` + +An illustration of adding two administrators can be seen in the test `two_super_admin` in `access/contrllable_base/lib.rs` + ## Tests running instruction Tests in `access_controllable_base/src/lib.rs` contain examples of interaction with a contract. diff --git a/examples/access-controllable-examples/access_controllable_base/src/lib.rs b/examples/access-controllable-examples/access_controllable_base/src/lib.rs index 681f0e8..417d7e2 100644 --- a/examples/access-controllable-examples/access_controllable_base/src/lib.rs +++ b/examples/access-controllable-examples/access_controllable_base/src/lib.rs @@ -3,7 +3,7 @@ use near_plugins::AccessControlRole; use near_plugins::AccessControllable; use near_plugins_derive::access_control; use near_plugins_derive::access_control_any; -use near_sdk::env; +use near_sdk::{AccountId, env}; use near_sdk::near_bindgen; /// All types of access groups @@ -57,6 +57,20 @@ impl Counter { pub fn get_counter(&self) -> u64 { self.counter } + + /// method for adding new super admin + pub fn add_super_admin(&mut self, new_super_admin_account_id: &AccountId) { + ::near_sdk::require!(self.__acl.is_super_admin(&near_sdk::env::predecessor_account_id()), + "Method can be run only by super admin"); + self.__acl.add_super_admin_unchecked(new_super_admin_account_id); + } + + /// method for removing super admin + pub fn remove_super_admin(&mut self, super_admin_account_id: &AccountId) { + ::near_sdk::require!(self.__acl.is_super_admin(&near_sdk::env::predecessor_account_id()), + "Method can be run only by super admin"); + self.__acl.revoke_super_admin_unchecked(&super_admin_account_id); + } } #[cfg(test)] @@ -155,4 +169,36 @@ mod tests { assert!(call!(&bob, contract, "acl_renounce_admin", &json!({"role": String::from(UsersGroups::GroupA)})).await); assert!(call!(&alice, contract, "acl_renounce_role", &json!({"role": String::from(UsersGroups::GroupA)})).await); } + + #[tokio::test] + async fn two_super_admin() { + let (contract_holder, contract) = get_contract(WASM_FILEPATH).await; + assert!(call!(contract, "new").await); + + let alice = get_subaccount(&contract_holder, "alice").await; + let is_admin: bool = view!( + contract, + "acl_is_super_admin", + &json!({"account_id": alice.id()}) + ); + + assert!(!is_admin); + + assert!(call!(contract, "add_super_admin", &json!({"new_super_admin_account_id": alice.id()})).await); + + let is_admin: bool = view!( + contract, + "acl_is_super_admin", + &json!({"account_id": alice.id()}) + ); + + assert!(is_admin); + + let is_admin: bool = view!( + contract, + "acl_is_super_admin", + &json!({"account_id": contract.id()}) + ); + assert!(is_admin); + } } From 662b8af60d75000679333cc9e0694ecce2d50efe Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Thu, 3 Nov 2022 21:00:07 +0200 Subject: [PATCH 65/68] remove unused imports --- .../up_stage_code/src/main.rs | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/examples/upgradable-examples/up_stage_code/src/main.rs b/examples/upgradable-examples/up_stage_code/src/main.rs index d3e92ff..a2b26c3 100644 --- a/examples/upgradable-examples/up_stage_code/src/main.rs +++ b/examples/upgradable-examples/up_stage_code/src/main.rs @@ -1,9 +1,9 @@ -use serde_json::json; -use tokio::runtime::Runtime; -use workspaces::{Account, Contract}; use std::env; +use tokio::runtime::Runtime; +use workspaces::Account; -const WASM_FILEPATH_SECOND: &str = "../../target/wasm32-unknown-unknown/release/upgradable_base_second.wasm"; +const WASM_FILEPATH_SECOND: &str = + "../../target/wasm32-unknown-unknown/release/upgradable_base_second.wasm"; fn main() { let args: Vec = env::args().collect(); @@ -14,10 +14,16 @@ fn main() { let wasm = std::fs::read(WASM_FILEPATH_SECOND).unwrap(); - println!("{}", rt.block_on( - contract.call(contract.id(), "up_stage_code") - .args_borsh(wasm) - .max_gas() - .transact() - ).unwrap().is_success()); -} \ No newline at end of file + println!( + "{}", + rt.block_on( + contract + .call(contract.id(), "up_stage_code") + .args_borsh(wasm) + .max_gas() + .transact() + ) + .unwrap() + .is_success() + ); +} From b8b88ae3b5e8b5b65f2ac101f79119d30b68122f Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Thu, 3 Nov 2022 21:18:06 +0200 Subject: [PATCH 66/68] use async main --- .../up_stage_code/src/main.rs | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/examples/upgradable-examples/up_stage_code/src/main.rs b/examples/upgradable-examples/up_stage_code/src/main.rs index a2b26c3..099ab85 100644 --- a/examples/upgradable-examples/up_stage_code/src/main.rs +++ b/examples/upgradable-examples/up_stage_code/src/main.rs @@ -1,14 +1,13 @@ use std::env; -use tokio::runtime::Runtime; use workspaces::Account; const WASM_FILEPATH_SECOND: &str = "../../target/wasm32-unknown-unknown/release/upgradable_base_second.wasm"; -fn main() { +#[tokio::main] +async fn main() { let args: Vec = env::args().collect(); - let rt = Runtime::new().unwrap(); - let worker = rt.block_on(workspaces::testnet()).unwrap(); + let worker = workspaces::testnet().await.unwrap(); let contract: Account = Account::from_file(args[1].clone(), &worker).unwrap(); @@ -16,14 +15,13 @@ fn main() { println!( "{}", - rt.block_on( - contract - .call(contract.id(), "up_stage_code") - .args_borsh(wasm) - .max_gas() - .transact() - ) - .unwrap() - .is_success() + contract + .call(contract.id(), "up_stage_code") + .args_borsh(wasm) + .max_gas() + .transact() + .await + .unwrap() + .is_success() ); } From c69044ea4429608971283fed604d7ffa65d9e91c Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Fri, 4 Nov 2022 08:19:25 +0200 Subject: [PATCH 67/68] args for wasm and network --- .../up_stage_code/Cargo.toml | 1 + .../up_stage_code/src/main.rs | 39 ++++++++++++++++--- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/examples/upgradable-examples/up_stage_code/Cargo.toml b/examples/upgradable-examples/up_stage_code/Cargo.toml index 477c019..1794777 100644 --- a/examples/upgradable-examples/up_stage_code/Cargo.toml +++ b/examples/upgradable-examples/up_stage_code/Cargo.toml @@ -13,3 +13,4 @@ workspaces = "0.6" tokio = { version = "1.1", features = ["rt", "macros"] } serde_json = "1.0.74" near-plugins-test-utils = { path = "../../near-plugins-test-utils" } +clap = { version = "3.1.6", features = ["derive"] } diff --git a/examples/upgradable-examples/up_stage_code/src/main.rs b/examples/upgradable-examples/up_stage_code/src/main.rs index 099ab85..d96455f 100644 --- a/examples/upgradable-examples/up_stage_code/src/main.rs +++ b/examples/upgradable-examples/up_stage_code/src/main.rs @@ -1,17 +1,44 @@ -use std::env; +use clap::Parser; use workspaces::Account; -const WASM_FILEPATH_SECOND: &str = +const DEFAULT_WASM_FILEPATH_SECOND: &str = "../../target/wasm32-unknown-unknown/release/upgradable_base_second.wasm"; +#[derive(Parser, Default, Debug)] +#[clap(version, about = "Up stage code")] +struct Arguments { + #[clap(short, long)] + // Path to key for contract account (for example `$HOME/.near-credentials/testnet/.json`) + path_to_key: String, + + #[clap(short, long, default_value_t = String::from(DEFAULT_WASM_FILEPATH_SECOND))] + /// Path to wasm file with the new contract + wasm: String, + + #[clap(long, default_value_t = String::from("testnet"))] + /// NEAR network (testnet, mainnet, betanet) + network: String, +} + +#[macro_export] +macro_rules! get_contract { + ($network_name:ident, $path_to_key:expr) => { + Account::from_file($path_to_key, &workspaces::$network_name().await.unwrap()).unwrap() + }; +} + #[tokio::main] async fn main() { - let args: Vec = env::args().collect(); - let worker = workspaces::testnet().await.unwrap(); + let args = Arguments::parse(); - let contract: Account = Account::from_file(args[1].clone(), &worker).unwrap(); + let contract: Account = match &*args.network { + "testnet" => get_contract!(testnet, args.path_to_key), + "mainnet" => get_contract!(mainnet, args.path_to_key), + "betanet" => get_contract!(betanet, args.path_to_key), + network => panic!("Unknown network {}. Possible networks: testnet, mainnet, betanet", network) + }; - let wasm = std::fs::read(WASM_FILEPATH_SECOND).unwrap(); + let wasm = std::fs::read(&args.wasm).unwrap(); println!( "{}", From 1a7a34b88d2b4513d1de096b408ef5fc17e46209 Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Mon, 7 Nov 2022 17:09:02 +0200 Subject: [PATCH 68/68] style fix --- .../access-controllable-examples/README.md | 24 ++++++++++--------- .../access_controllable_base/src/lib.rs | 4 ++-- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/examples/access-controllable-examples/README.md b/examples/access-controllable-examples/README.md index b50240c..74c3524 100644 --- a/examples/access-controllable-examples/README.md +++ b/examples/access-controllable-examples/README.md @@ -115,8 +115,8 @@ If the method succeeds, the following event will be emitted: "version":"1.0.0", "event":"super_admin_added", "data":{ - "account":"test.near", - "by":"test.near" + "account":"", + "by":"" } } ``` @@ -411,23 +411,25 @@ $ near view get_counter 2 ``` -### A few super admins -There may be two or more super admins. -By default, there are no interfaces that allow you to add or remove super admins. -You can add the corresponding functions to the contract as follows: +### Multiple super admins +There may be multiple super admins. + +By default, only `acl_init_super_admin` is exposed on the contract. To add more super admins or to remove super admins, internal functions can be used. + +To make this functionality publicly available, you could add functions like the following to your contract: ```rust /// method for adding new super admin pub fn add_super_admin(&mut self, new_super_admin_account_id: &AccountId) { - ::near_sdk::require!(self.__acl.is_super_admin(&near_sdk::env::predecessor_account_id()), - "Method can be run only by super admin"); - self.__acl.add_super_admin_unchecked(new_super_admin_account_id); + ::near_sdk::require!(self.acl_is_super_admin(near_sdk::env::predecessor_account_id()), + "Method can be run only by super admin"); + self.__acl.add_super_admin_unchecked(new_super_admin_account_id); } /// method for removing super admin pub fn remove_super_admin(&mut self, super_admin_account_id: &AccountId) { - ::near_sdk::require!(self.__acl.is_super_admin(&near_sdk::env::predecessor_account_id()), - "Method can be run only by super admin"); + ::near_sdk::require!(self.acl_is_super_admin(near_sdk::env::predecessor_account_id()), + "Method can be run only by super admin"); self.__acl.revoke_super_admin_unchecked(&super_admin_account_id); } ``` diff --git a/examples/access-controllable-examples/access_controllable_base/src/lib.rs b/examples/access-controllable-examples/access_controllable_base/src/lib.rs index 417d7e2..5cc685f 100644 --- a/examples/access-controllable-examples/access_controllable_base/src/lib.rs +++ b/examples/access-controllable-examples/access_controllable_base/src/lib.rs @@ -60,14 +60,14 @@ impl Counter { /// method for adding new super admin pub fn add_super_admin(&mut self, new_super_admin_account_id: &AccountId) { - ::near_sdk::require!(self.__acl.is_super_admin(&near_sdk::env::predecessor_account_id()), + ::near_sdk::require!(self.acl_is_super_admin(near_sdk::env::predecessor_account_id()), "Method can be run only by super admin"); self.__acl.add_super_admin_unchecked(new_super_admin_account_id); } /// method for removing super admin pub fn remove_super_admin(&mut self, super_admin_account_id: &AccountId) { - ::near_sdk::require!(self.__acl.is_super_admin(&near_sdk::env::predecessor_account_id()), + ::near_sdk::require!(self.acl_is_super_admin(near_sdk::env::predecessor_account_id()), "Method can be run only by super admin"); self.__acl.revoke_super_admin_unchecked(&super_admin_account_id); }