multi-ownable

A NEAR plugin enables multiple Accounts to share ownership of a contract. Calls are stored in hashed form, so storage requirements are very low.

test

cargo test -- --nocapture

usage

multi-ownable can be addeded to your contract via a macro:

rust // Arguments: // 1. name of your contract // 2. name of the field where the multi ownable state is stored // 3. enum type for possible multisig calls // 4. callback function to process completed multisig calls crate::impl_multi_ownable!(Contract, multi_ownable, MultiOwnableCall, on_call);

Here is a full working example of how to use multi-ownable

```rust // import "implmultiownable" and "MultiOwnableData" use multiownable::{implmultiownable, MultiOwnableData}; use nearsdk::borsh::{self, BorshDeserialize, BorshSerialize}; use nearsdk::{env, nearbindgen, require, AccountId, BorshStorageKey, PanicOnDefault};

[near_bindgen]

[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)]

pub struct Contract { multi_ownable: MultiOwnableData, // add this to the Contract number: u64, }

[derive(BorshSerialize, BorshStorageKey)]

enum StorageKey { Owners, MultiOwnableCalls, }

[near_bindgen]

impl Contract { #[init] pub fn new(ownerid: AccountId) -> Self { let mut this = Self { number: 0, multiownable: MultiOwnableData::new(StorageKey::Owners, StorageKey::MultiOwnableCalls), }; // initialize multiownable in the "new" func of your Contract this.initmultiownable(vec![ownerid.clone()], 1); this }

pub fn get_number(&self) -> u64 { self.number }

// arguments are received as a json string fn oncall(&mut self, callname: MultiOwnableCall, arguments: &str) { match callname { MultiOwnableCall::UpdateNumber => self.updatenumber(arguments), MultiOwnableCall::DoSomethingElse => self.dosomethingelse(arguments), } }

#[private] fn updatenumber(&mut self, args: &str) { // first, deserialize your arguments let UpdateNumberArgs { number } = nearsdk::serdejson::from_str(&args).expect("Invalid SetRewardRateArgs"); self.number = number; }

#[private] fn dosomething_else(&self, _args: &str) { // do something else } }

// an argument struct for "update_number" call

[derive(Serialize, Deserialize, Clone)]

[serde(crate = "near_sdk::serde")]

pub struct UpdateNumberArgs { pub number: u64, }

// create an enum to match possible multisig calls // make sure to both "rename" and "alias" your fields to be snake_case

[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, Clone)]

[serde(crate = "near_sdk::serde")]

pub enum MultiOwnableCall { #[serde(rename = "updatenumber", alias = "updatenumber")] UpdateNumber, #[serde(rename = "dosomethingelse", alias = "dosomethingelse")] DoSomethingElse, }

crate::implmultiownable!(Contract, multiownable, MultiOwnableCall, oncall);

```