Skip to content

Commit

Permalink
feat: finish rpc calls
Browse files Browse the repository at this point in the history
  • Loading branch information
tdelabro committed Jul 26, 2022
1 parent 8d9bd86 commit 224d4db
Show file tree
Hide file tree
Showing 9 changed files with 284 additions and 227 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ edition = "2021"
targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
serde = { version = "1.0.132", default-features = false, features = ["derive"] }
codec = { package = "parity-scale-codec", version = "3.0.0", features = [
"derive",
], default-features = false }
Expand All @@ -27,7 +28,6 @@ sp-std = { git = "https://github.com/paritytech/substrate", default-features = f
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.24" }

[dev-dependencies]
serde = { version = "1.0.132" }
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.24" }
pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.24" }

Expand Down
1 change: 1 addition & 0 deletions rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ sp-std = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate
sp-blockchain = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.24" }

pallet-supersig-rpc-runtime-api = { path = "./runtime-api" }
pallet-supersig = { path = ".." }
6 changes: 4 additions & 2 deletions rpc/runtime-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ scale-info = { version = "2.1.1", default-features = false, features = [
"derive",
] }

sp-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.24" , version = "4.0.0-dev"}
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.24" , version = "4.0.0-dev"}
sp-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.24", version = "4.0.0-dev" }
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.24", version = "4.0.0-dev" }

pallet-supersig = { path = "../.." }

[features]
default = ["std"]
Expand Down
11 changes: 9 additions & 2 deletions rpc/runtime-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,18 @@ use codec::Codec;
#[cfg(not(feature = "std"))]
use sp_std::prelude::Vec;

use pallet_supersig::{rpc::ProposalState, CallId, Role, SupersigId};

sp_api::decl_runtime_apis! {
pub trait SuperSigApi<AccountId>
pub trait SuperSigApi<AccountId, Call>
where
AccountId: Codec,
Call: Codec,
{
fn get_account_supersigs(origin: AccountId) -> Vec<u128>;
fn get_supersig_id(supersig_account: AccountId) -> Option<SupersigId>;
fn get_user_supersigs(who: AccountId) -> Vec<SupersigId>;
fn list_members(supersig_id: SupersigId) -> Vec<(AccountId, Role)>;
fn list_proposals(supersig_id: SupersigId) -> (Vec<ProposalState<AccountId, Call>>, u32);
fn get_proposal_state(supersig_id: SupersigId, call_id: CallId) -> Option<(ProposalState<AccountId, Call>, u32)>;
}
}
94 changes: 83 additions & 11 deletions rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,47 @@ use jsonrpsee::{
proc_macros::rpc,
types::error::{CallError, ErrorObject},
};
use sp_api::BlockId;
use sp_api::BlockT;
use sp_api::ProvideRuntimeApi;
use sp_api::{BlockId, BlockT, ProvideRuntimeApi};
use sp_blockchain::HeaderBackend;
use std::{marker::PhantomData, sync::Arc};

pub use pallet_supersig_rpc_runtime_api::SuperSigApi as SuperSigRuntimeApi;

use pallet_supersig::{rpc::ProposalState, CallId, Role, SupersigId};

#[rpc(client, server)]
pub trait SuperSigApi<BlockHash, AccountId> {
#[method(name = "superSig_getAccountSupersigs")]
fn get_account_supersigs(&self, who: AccountId, at: Option<BlockHash>) -> RpcResult<Vec<u128>>;
pub trait SuperSigApi<BlockHash, AccountId, Call> {
#[method(name = "superSig_getSupersigId")]
fn get_supersig_id(
&self,
supersig_account: AccountId,
at: Option<BlockHash>,
) -> RpcResult<Option<SupersigId>>;
#[method(name = "superSig_getUserSupersigs")]
fn get_user_supersigs(
&self,
who: AccountId,
at: Option<BlockHash>,
) -> RpcResult<Vec<SupersigId>>;
#[method(name = "superSig_listMembers")]
fn list_members(
&self,
supersig_id: SupersigId,
at: Option<BlockHash>,
) -> RpcResult<Vec<(AccountId, Role)>>;
#[method(name = "superSig_listProposals")]
fn list_proposals(
&self,
supersig_id: SupersigId,
at: Option<BlockHash>,
) -> RpcResult<(Vec<ProposalState<AccountId, Call>>, u32)>;
#[method(name = "superSig_getProposalState")]
fn get_proposal_state(
&self,
supersig_id: SupersigId,
call_id: CallId,
at: Option<BlockHash>,
) -> RpcResult<Option<(ProposalState<AccountId, Call>, u32)>>;
}

/// SuperSig RPC methods.
Expand All @@ -34,22 +63,65 @@ impl<Client, Block> SuperSig<Client, Block> {
}
}

impl<Client, Block, AccountId> SuperSigApiServer<<Block as BlockT>::Hash, AccountId>
impl<Client, Block, AccountId, Call> SuperSigApiServer<<Block as BlockT>::Hash, AccountId, Call>
for SuperSig<Client, Block>
where
Block: BlockT,
Client: Send + Sync + 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,
Client::Api: SuperSigRuntimeApi<Block, AccountId>,
Client::Api: SuperSigRuntimeApi<Block, AccountId, Call>,
AccountId: Codec,
Call: Codec,
{
fn get_account_supersigs(
fn get_supersig_id(
&self,
supersig_account: AccountId,
at: Option<<Block as BlockT>::Hash>,
) -> RpcResult<Option<SupersigId>> {
let api = self.client.runtime_api();
let at = BlockId::hash(at.unwrap_or_else(|| self.client.info().best_hash));
api.get_supersig_id(&at, supersig_account).map_err(runtime_error_into_rpc_err)
}

fn get_user_supersigs(
&self,
who: AccountId,
at: Option<<Block as BlockT>::Hash>,
) -> RpcResult<Vec<u128>> {
) -> RpcResult<Vec<SupersigId>> {
let api = self.client.runtime_api();
let at = BlockId::hash(at.unwrap_or_else(|| self.client.info().best_hash));
api.get_user_supersigs(&at, who).map_err(runtime_error_into_rpc_err)
}

fn list_members(
&self,
supersig_id: SupersigId,
at: Option<<Block as BlockT>::Hash>,
) -> RpcResult<Vec<(AccountId, Role)>> {
let api = self.client.runtime_api();
let at = BlockId::hash(at.unwrap_or_else(|| self.client.info().best_hash));
api.list_members(&at, supersig_id).map_err(runtime_error_into_rpc_err)
}

fn list_proposals(
&self,
supersig_id: SupersigId,
at: Option<<Block as BlockT>::Hash>,
) -> RpcResult<(Vec<ProposalState<AccountId, Call>>, u32)> {
let api = self.client.runtime_api();
let at = BlockId::hash(at.unwrap_or_else(|| self.client.info().best_hash));
api.list_proposals(&at, supersig_id).map_err(runtime_error_into_rpc_err)
}

fn get_proposal_state(
&self,
supersig_id: SupersigId,
call_id: CallId,
at: Option<<Block as BlockT>::Hash>,
) -> RpcResult<Option<(ProposalState<AccountId, Call>, u32)>> {
let api = self.client.runtime_api();
let at = BlockId::hash(at.unwrap_or_else(|| self.client.info().best_hash));
api.get_account_supersigs(&at, who).map_err(runtime_error_into_rpc_err)
api.get_proposal_state(&at, supersig_id, call_id)
.map_err(runtime_error_into_rpc_err)
}
}

Expand Down
77 changes: 2 additions & 75 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ pub use sp_runtime::traits::{
};
pub use sp_std::{boxed::Box, cmp::max, mem::size_of, prelude::Vec};

pub mod rpc;
pub mod types;
pub mod weights;

Expand Down Expand Up @@ -605,7 +606,7 @@ pub mod pallet {
}

impl<T: Config> Pallet<T> {
fn get_supersig_id_from_account(
pub fn get_supersig_id_from_account(
supersig_account: &T::AccountId,
) -> Result<SupersigId, pallet::Error<T>> {
if let Some((account, supersig_id)) = PalletId::try_from_sub_account(supersig_account) {
Expand Down Expand Up @@ -750,77 +751,3 @@ pub mod pallet {
}
}
}

// RPC calls

#[allow(dead_code)]
impl<T: Config> Pallet<T> {
pub fn get_account_supersigs(who: T::AccountId) -> Vec<SupersigId> {
Members::<T>::iter()
.filter_map(|(supersig_id, member_id, _)| {
if member_id == who {
Some(supersig_id)
} else {
None
}
})
.collect()
}

pub fn get_members_connected(which: SupersigId) -> Vec<(T::AccountId, Role)> {
Members::<T>::iter_prefix(which).collect()
}

// Return :
// Tuple :
// Vec<((Vec<u8>, T::AccountId, BalanceOf<T>), Vec<T::AccountId>)> :
// The tuple inside the vec is just a Call that is unwrap.
// The vec inside the vec is all the account id that have voted.
// The second parameter of the tuple is the total amount of members into the supersig.
pub fn get_proposals(
which: SupersigId,
) -> (
Vec<((Vec<u8>, T::AccountId, BalanceOf<T>), Vec<T::AccountId>)>,
u32,
) {
let member_count = Self::total_members(which);
let proposal_state = Calls::<T>::iter_prefix(which)
.map(|(call_id, call)| {
(
(call.data, call.provider, call.deposit),
MembersVotes::<T>::iter_prefix((which, call_id))
.filter_map(
|(account_id, vote)| {
if vote { Some(account_id) } else { None }
},
)
.collect(),
)
})
.collect();
(proposal_state, member_count)
}

// Return :
// Tuple :
// The bool is to define if the Call that is asked for state still exists.
// The vec is all the account id that have voted.
// The first u32 is the total amount of members in the supersig
// The second u32 is the total number of votes (not necessary because == members_votes.len())
pub fn get_proposal_state(
which: SupersigId,
call_id: CallId,
) -> (bool, Vec<T::AccountId>, u32, u32) {
let member_count = Self::total_members(which);
let votes = Self::votes(which, call_id);
let exists = !Self::calls(which, call_id).is_none();
let member_votes = MembersVotes::<T>::iter_prefix((which, call_id))
.filter_map(
|(account_id, vote)| {
if vote { Some(account_id) } else { None }
},
)
.collect();
(exists, member_votes, member_count, votes)
}
}
120 changes: 120 additions & 0 deletions src/rpc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
use codec::Decode;
use frame_support::Parameter;
pub use sp_std::{boxed::Box, cmp::max, mem::size_of, prelude::Vec};

use crate::{
pallet, CallId, Calls, Config, Error, Members, MembersVotes, Pallet, Role, SupersigId,
};

#[derive(Debug, Clone, PartialEq, Eq, Decode, serde::Serialize, serde::Deserialize)]
pub struct ProposalState<AccountId, Call> {
id: CallId,
call: Call,
provider: AccountId,
voters: Vec<AccountId>,
}

impl<AccoutId: Clone, Call: Parameter> ProposalState<AccoutId, Call> {
pub fn new(id: CallId, call: Call, provider: AccoutId, voters: Vec<AccoutId>) -> Self {
Self {
id,
call,
provider,
voters,
}
}

pub fn id(&self) -> &CallId {
&self.id
}

pub fn call(&self) -> &Call {
&self.call
}

pub fn provider(&self) -> &AccoutId {
&self.provider
}

pub fn voters(&self) -> &Vec<AccoutId> {
&self.voters
}
}

impl<T: Config> Pallet<T> {
pub fn get_supersig_id(supersig_account: &T::AccountId) -> Result<SupersigId, Error<T>> {
Self::get_supersig_id_from_account(supersig_account)
}

pub fn get_user_supersigs(who: T::AccountId) -> Vec<SupersigId> {
Members::<T>::iter()
.filter_map(|(supersig_id, member_id, _)| {
if member_id == who {
Some(supersig_id)
} else {
None
}
})
.collect()
}

pub fn list_members(supersig_id: SupersigId) -> Vec<(T::AccountId, Role)> {
Members::<T>::iter_prefix(supersig_id).collect()
}

pub fn list_proposals(
supersig_id: SupersigId,
) -> (
Vec<ProposalState<T::AccountId, <T as pallet::Config>::Call>>,
u32,
) {
let member_count = Self::total_members(supersig_id);
let proposal_state = Calls::<T>::iter_prefix(supersig_id)
.map(|(call_id, call)| {
let voters = MembersVotes::<T>::iter_prefix((supersig_id, call_id))
.filter_map(
|(account_id, vote)| {
if vote { Some(account_id) } else { None }
},
)
.collect();

ProposalState::new(
call_id,
<T as pallet::Config>::Call::decode(&mut &call.data[..]).unwrap(),
call.provider,
voters,
)
})
.collect();
(proposal_state, member_count)
}

pub fn get_proposal_state(
supersig_id: SupersigId,
call_id: CallId,
) -> Option<(
ProposalState<T::AccountId, <T as pallet::Config>::Call>,
u32,
)> {
let call = Self::calls(supersig_id, call_id)?;
let member_count = Self::total_members(supersig_id);
let voters = MembersVotes::<T>::iter_prefix((supersig_id, call_id))
.filter_map(
|(account_id, vote)| {
if vote { Some(account_id) } else { None }
},
)
.collect();

Some((
ProposalState::new(
call_id,
<T as pallet::Config>::Call::decode(&mut &call.data[..]).unwrap(),
call.provider,
voters,
),
member_count,
))
}
}
Loading

0 comments on commit 224d4db

Please sign in to comment.