Limiting accounts returned by parity_accountInfo (#3931)

* Limiting accountNames returned by parity_accountNames

* Fixing middleware

* Change RPC interface

* Enhance tests for RPC layer

* UI uses parity_allAccountsInfo

* Update dapps to use parity_accountsInfo

* Don't filter by uuid (deprecated)

* Consistency in calls

* Fix js tests (missed stub call)
This commit is contained in:
Tomasz Drwięga 2016-12-23 18:52:02 +01:00 committed by Gav Wood
parent 546246c56b
commit 27ba0e6922
26 changed files with 145 additions and 119 deletions

View File

@ -51,16 +51,16 @@ impl Endpoint for RpcEndpoint {
} }
} }
const MIDDLEWARE_METHOD: &'static str = "eth_accounts";
struct RpcMiddleware { struct RpcMiddleware {
handler: Arc<IoHandler>, handler: Arc<IoHandler>,
methods: Vec<String>,
} }
impl RpcMiddleware { impl RpcMiddleware {
fn new(handler: Arc<IoHandler>) -> Self { fn new(handler: Arc<IoHandler>) -> Self {
RpcMiddleware { RpcMiddleware {
handler: handler, handler: handler,
methods: vec!["eth_accounts".into(), "parity_accountsInfo".into()],
} }
} }
@ -68,9 +68,9 @@ impl RpcMiddleware {
fn augment_request(&self, request: &mut Request, meta: Option<Meta>) { fn augment_request(&self, request: &mut Request, meta: Option<Meta>) {
use jsonrpc_core::{Call, Params, to_value}; use jsonrpc_core::{Call, Params, to_value};
fn augment_call(call: &mut Call, meta: Option<&Meta>) { fn augment_call(call: &mut Call, meta: Option<&Meta>, methods: &Vec<String>) {
match (call, meta) { match (call, meta) {
(&mut Call::MethodCall(ref mut method_call), Some(meta)) if &method_call.method == MIDDLEWARE_METHOD => { (&mut Call::MethodCall(ref mut method_call), Some(meta)) if methods.contains(&method_call.method) => {
let session = to_value(&meta.app_id); let session = to_value(&meta.app_id);
let params = match method_call.params { let params = match method_call.params {
@ -86,10 +86,10 @@ impl RpcMiddleware {
} }
match *request { match *request {
Request::Single(ref mut call) => augment_call(call, meta.as_ref()), Request::Single(ref mut call) => augment_call(call, meta.as_ref(), &self.methods),
Request::Batch(ref mut vec) => { Request::Batch(ref mut vec) => {
for mut call in vec { for mut call in vec {
augment_call(call, meta.as_ref()) augment_call(call, meta.as_ref(), &self.methods)
} }
}, },
} }

View File

@ -19,19 +19,23 @@ import BigNumber from 'bignumber.js';
import { toChecksumAddress } from '../../abi/util/address'; import { toChecksumAddress } from '../../abi/util/address';
export function outAccountInfo (infos) { export function outAccountInfo (infos) {
const ret = {}; return Object
.keys(infos)
.reduce((ret, _address) => {
const info = infos[_address];
const address = outAddress(_address);
Object.keys(infos).forEach((address) => { ret[address] = {
const info = infos[address]; name: info.name
};
ret[outAddress(address)] = { if (info.meta) {
name: info.name, ret[address].uuid = info.uuid;
uuid: info.uuid, ret[address].meta = JSON.parse(info.meta);
meta: JSON.parse(info.meta) }
};
});
return ret; return ret;
}, {});
} }
export function outAddress (address) { export function outAddress (address) {

View File

@ -35,6 +35,14 @@ describe('api/format/output', () => {
} }
}); });
}); });
it('returns objects without meta & uuid as required', () => {
expect(outAccountInfo(
{ '0x63cf90d3f0410092fc0fca41846f596223979195': { name: 'name' } }
)).to.deep.equal({
'0x63Cf90D3f0410092FC0fca41846f596223979195': { name: 'name' }
});
});
}); });
describe('outAddress', () => { describe('outAddress', () => {

View File

@ -27,18 +27,18 @@ export default class Parity {
.execute('parity_acceptNonReservedPeers'); .execute('parity_acceptNonReservedPeers');
} }
accounts () {
return this._transport
.execute('parity_accounts')
.then(outAccountInfo);
}
accountsInfo () { accountsInfo () {
return this._transport return this._transport
.execute('parity_accountsInfo') .execute('parity_accountsInfo')
.then(outAccountInfo); .then(outAccountInfo);
} }
allAccountsInfo () {
return this._transport
.execute('parity_allAccountsInfo')
.then(outAccountInfo);
}
addReservedPeer (encode) { addReservedPeer (encode) {
return this._transport return this._transport
.execute('parity_addReservedPeer', encode); .execute('parity_addReservedPeer', encode);

View File

@ -24,7 +24,7 @@ import Signer from './signer';
const events = { const events = {
'logging': { module: 'logging' }, 'logging': { module: 'logging' },
'eth_blockNumber': { module: 'eth' }, 'eth_blockNumber': { module: 'eth' },
'parity_accountsInfo': { module: 'personal' }, 'parity_allAccountsInfo': { module: 'personal' },
'eth_accounts': { module: 'personal' }, 'eth_accounts': { module: 'personal' },
'signer_requestsToConfirm': { module: 'signer' } 'signer_requestsToConfirm': { module: 'signer' }
}; };

View File

@ -46,9 +46,9 @@ export default class Personal {
_accountsInfo = () => { _accountsInfo = () => {
return this._api.parity return this._api.parity
.accountsInfo() .allAccountsInfo()
.then((info) => { .then((info) => {
this._updateSubscriptions('parity_accountsInfo', null, info); this._updateSubscriptions('parity_allAccountsInfo', null, info);
}); });
} }

View File

@ -28,16 +28,16 @@ const TEST_LIST = ['0xfa64203C044691aA57251aF95f4b48d85eC00Dd5'];
function stubApi (accounts, info) { function stubApi (accounts, info) {
const _calls = { const _calls = {
accountsInfo: [], allAccountsInfo: [],
listAccounts: [] listAccounts: []
}; };
return { return {
_calls, _calls,
parity: { parity: {
accountsInfo: () => { allAccountsInfo: () => {
const stub = sinon.stub().resolves(info || TEST_INFO)(); const stub = sinon.stub().resolves(info || TEST_INFO)();
_calls.accountsInfo.push(stub); _calls.allAccountsInfo.push(stub);
return stub; return stub;
} }
}, },
@ -86,8 +86,8 @@ describe('api/subscriptions/personal', () => {
expect(personal.isStarted).to.be.true; expect(personal.isStarted).to.be.true;
}); });
it('calls parity_accountsInfo', () => { it('calls parity_allAccountsInfo', () => {
expect(api._calls.accountsInfo.length).to.be.ok; expect(api._calls.allAccountsInfo.length).to.be.ok;
}); });
it('calls eth_accounts', () => { it('calls eth_accounts', () => {
@ -96,7 +96,7 @@ describe('api/subscriptions/personal', () => {
it('updates subscribers', () => { it('updates subscribers', () => {
expect(cb.firstCall).to.have.been.calledWith('eth_accounts', null, TEST_LIST); expect(cb.firstCall).to.have.been.calledWith('eth_accounts', null, TEST_LIST);
expect(cb.secondCall).to.have.been.calledWith('parity_accountsInfo', null, TEST_INFO); expect(cb.secondCall).to.have.been.calledWith('parity_allAccountsInfo', null, TEST_INFO);
}); });
}); });
@ -112,7 +112,7 @@ describe('api/subscriptions/personal', () => {
}); });
it('calls personal_accountsInfo', () => { it('calls personal_accountsInfo', () => {
expect(api._calls.accountsInfo.length).to.be.ok; expect(api._calls.allAccountsInfo.length).to.be.ok;
}); });
it('calls personal_listAccounts', () => { it('calls personal_listAccounts', () => {

View File

@ -83,7 +83,7 @@ export default class Application extends Component {
Promise Promise
.all([ .all([
attachInstances(), attachInstances(),
api.parity.accounts() api.parity.accountsInfo()
]) ])
.then(([{ managerInstance, registryInstance, tokenregInstance }, accountsInfo]) => { .then(([{ managerInstance, registryInstance, tokenregInstance }, accountsInfo]) => {
accountsInfo = accountsInfo || {}; accountsInfo = accountsInfo || {};
@ -95,7 +95,7 @@ export default class Application extends Component {
accounts: Object accounts: Object
.keys(accountsInfo) .keys(accountsInfo)
.sort((a, b) => { .sort((a, b) => {
return (accountsInfo[b].uuid || '').localeCompare(accountsInfo[a].uuid || ''); return (accountsInfo[b].name || '').localeCompare(accountsInfo[a].name || '');
}) })
.reduce((accounts, address) => { .reduce((accounts, address) => {
accounts[address] = Object.assign(accountsInfo[address], { address }); accounts[address] = Object.assign(accountsInfo[address], { address });

View File

@ -126,7 +126,7 @@ export default class Deployment extends Component {
const { baseText, name, nameError, tla, tlaError, totalSupply, totalSupplyError } = this.state; const { baseText, name, nameError, tla, tlaError, totalSupply, totalSupplyError } = this.state;
const hasError = !!(nameError || tlaError || totalSupplyError); const hasError = !!(nameError || tlaError || totalSupplyError);
const error = `${styles.input} ${styles.error}`; const error = `${styles.input} ${styles.error}`;
const addresses = Object.keys(accounts).filter((address) => accounts[address].uuid); const addresses = Object.keys(accounts);
// <div className={ styles.input }> // <div className={ styles.input }>
// <label>global registration</label> // <label>global registration</label>

View File

@ -94,10 +94,7 @@ export default class Overview extends Component {
loadOwners () { loadOwners () {
const { accounts } = this.context; const { accounts } = this.context;
const addresses = Object const addresses = Object.keys(accounts);
.values(accounts)
.filter((account) => account.uuid)
.map((account) => account.address);
loadOwnedTokens(addresses) loadOwnedTokens(addresses)
.then(({ tokens, total }) => { .then(({ tokens, total }) => {

View File

@ -303,12 +303,9 @@ export default class Send extends Component {
loadBalances () { loadBalances () {
const { accounts } = this.context; const { accounts } = this.context;
const myAccounts = Object const addresses = Object.keys(accounts);
.values(accounts)
.filter((account) => account.uuid)
.map((account) => account.address);
loadBalances(myAccounts) loadBalances(addresses)
.then((_tokens) => { .then((_tokens) => {
const tokens = _tokens.filter((token) => { const tokens = _tokens.filter((token) => {
for (let index = 0; index < token.balances.length; index++) { for (let index = 0; index < token.balances.length; index++) {

View File

@ -26,7 +26,6 @@ let instance = null;
export default class DappsStore { export default class DappsStore {
@observable accounts = []; @observable accounts = [];
@observable addresses = [];
@observable apps = []; @observable apps = [];
@observable contractOwner = null; @observable contractOwner = null;
@observable currentAccount = null; @observable currentAccount = null;
@ -191,7 +190,7 @@ export default class DappsStore {
@action setAccounts = (accountsInfo) => { @action setAccounts = (accountsInfo) => {
transaction(() => { transaction(() => {
this.addresses = Object this.accounts = Object
.keys(accountsInfo) .keys(accountsInfo)
.map((address) => { .map((address) => {
const account = accountsInfo[address]; const account = accountsInfo[address];
@ -199,7 +198,6 @@ export default class DappsStore {
return account; return account;
}); });
this.accounts = this.addresses.filter((account) => account.uuid);
this.currentAccount = this.accounts[0]; this.currentAccount = this.accounts[0];
}); });
@ -315,7 +313,7 @@ export default class DappsStore {
this this
.setApps(appsInfo.map(([appId, owner]) => { .setApps(appsInfo.map(([appId, owner]) => {
const isOwner = !!this.accounts.find((account) => account.address === owner); const isOwner = !!this.accounts.find((account) => account.address === owner);
const account = this.addresses.find((account) => account.address === owner); const account = this.accounts.find((account) => account.address === owner);
const id = api.util.bytesToHex(appId); const id = api.util.bytesToHex(appId);
return { return {
@ -445,7 +443,7 @@ export default class DappsStore {
_loadAccounts () { _loadAccounts () {
return api.parity return api.parity
.accounts() .accountsInfo()
.then(this.setAccounts) .then(this.setAccounts)
.catch((error) => { .catch((error) => {
console.error('Store:loadAccounts', error); console.error('Store:loadAccounts', error);

View File

@ -28,7 +28,7 @@ export function attachInterface () {
return Promise return Promise
.all([ .all([
registry.getAddress.call({}, [api.util.sha3('githubhint'), 'A']), registry.getAddress.call({}, [api.util.sha3('githubhint'), 'A']),
api.parity.accounts() api.parity.accountsInfo()
]); ]);
}) })
.then(([address, accountsInfo]) => { .then(([address, accountsInfo]) => {
@ -37,7 +37,6 @@ export function attachInterface () {
const contract = api.newContract(abis.githubhint, address); const contract = api.newContract(abis.githubhint, address);
const accounts = Object const accounts = Object
.keys(accountsInfo) .keys(accountsInfo)
.filter((address) => accountsInfo[address].uuid)
.reduce((obj, address) => { .reduce((obj, address) => {
const account = accountsInfo[address]; const account = accountsInfo[address];

View File

@ -20,14 +20,14 @@ export const set = (addresses) => ({ type: 'addresses set', addresses });
export const fetch = () => (dispatch) => { export const fetch = () => (dispatch) => {
return api.parity return api.parity
.accounts() .accountsInfo()
.then((accountsInfo) => { .then((accountsInfo) => {
const addresses = Object const addresses = Object
.keys(accountsInfo) .keys(accountsInfo)
.map((address) => ({ .map((address) => ({
...accountsInfo[address], ...accountsInfo[address],
address, address,
isAccount: !!accountsInfo[address].uuid isAccount: true
})); }));
dispatch(set(addresses)); dispatch(set(addresses));
}) })

View File

@ -49,7 +49,7 @@ export function attachInterface (callback) {
return Promise return Promise
.all([ .all([
registry.getAddress.call({}, [api.util.sha3('signaturereg'), 'A']), registry.getAddress.call({}, [api.util.sha3('signaturereg'), 'A']),
api.parity.accounts() api.parity.accountsInfo()
]); ]);
}) })
.then(([address, accountsInfo]) => { .then(([address, accountsInfo]) => {
@ -58,7 +58,6 @@ export function attachInterface (callback) {
const contract = api.newContract(abis.signaturereg, address); const contract = api.newContract(abis.signaturereg, address);
const accounts = Object const accounts = Object
.keys(accountsInfo) .keys(accountsInfo)
.filter((address) => accountsInfo[address].uuid)
.reduce((obj, address) => { .reduce((obj, address) => {
const info = accountsInfo[address] || {}; const info = accountsInfo[address] || {};

View File

@ -36,11 +36,10 @@ export const setSelectedAccount = (address) => ({
export const loadAccounts = () => (dispatch) => { export const loadAccounts = () => (dispatch) => {
api.parity api.parity
.accounts() .accountsInfo()
.then((accountsInfo) => { .then((accountsInfo) => {
const accountsList = Object const accountsList = Object
.keys(accountsInfo) .keys(accountsInfo)
.filter((address) => accountsInfo[address].uuid)
.map((address) => ({ .map((address) => ({
...accountsInfo[address], ...accountsInfo[address],
address address

View File

@ -26,7 +26,7 @@ export default {
} }
}, },
accounts: { accountsInfo: {
desc: 'returns a map of accounts as an object', desc: 'returns a map of accounts as an object',
params: [], params: [],
returns: { returns: {
@ -36,20 +36,12 @@ export default {
name: { name: {
type: String, type: String,
desc: 'Account name' desc: 'Account name'
},
meta: {
type: String,
desc: 'Encoded JSON string the defines additional account metadata'
},
uuid: {
type: String,
desc: 'The account Uuid, or null if not available/unknown/not applicable.'
} }
} }
} }
}, },
accountsInfo: { allAccountsInfo: {
desc: 'returns a map of accounts as an object', desc: 'returns a map of accounts as an object',
params: [], params: [],
returns: { returns: {

View File

@ -60,7 +60,7 @@ export default class Balances {
subscribeAccountsInfo () { subscribeAccountsInfo () {
this._api this._api
.subscribe('parity_accountsInfo', (error, accountsInfo) => { .subscribe('parity_allAccountsInfo', (error, accountsInfo) => {
if (error) { if (error) {
return; return;
} }

View File

@ -29,9 +29,9 @@ export default class Personal {
_subscribeAccountsInfo () { _subscribeAccountsInfo () {
this._api this._api
.subscribe('parity_accountsInfo', (error, accountsInfo) => { .subscribe('parity_allAccountsInfo', (error, accountsInfo) => {
if (error) { if (error) {
console.error('parity_accountsInfo', error); console.error('parity_allAccountsInfo', error);
return; return;
} }
@ -41,7 +41,7 @@ export default class Personal {
_removeDeleted () { _removeDeleted () {
this._api.parity this._api.parity
.accountsInfo() .allAccountsInfo()
.then((accountsInfo) => { .then((accountsInfo) => {
return Promise.all( return Promise.all(
Object Object

View File

@ -41,7 +41,7 @@ export default class Store {
_checkAccounts () { _checkAccounts () {
this._api.parity this._api.parity
.accountsInfo() .allAccountsInfo()
.then((info) => { .then((info) => {
const accounts = Object.keys(info).filter((address) => info[address].uuid); const accounts = Object.keys(info).filter((address) => info[address].uuid);

View File

@ -17,7 +17,7 @@
//! Parity-specific rpc implementation. //! Parity-specific rpc implementation.
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use std::str::FromStr; use std::str::FromStr;
use std::collections::BTreeMap; use std::collections::{BTreeMap, HashSet};
use util::{RotatingLogger, Address}; use util::{RotatingLogger, Address};
use util::misc::version_data; use util::misc::version_data;
@ -40,7 +40,7 @@ use v1::types::{
Peers, Transaction, RpcSettings, Histogram, Peers, Transaction, RpcSettings, Histogram,
TransactionStats, LocalTransactionStatus, TransactionStats, LocalTransactionStatus,
BlockNumber, ConsensusCapability, VersionInfo, BlockNumber, ConsensusCapability, VersionInfo,
OperationsInfo, ChainStatus, OperationsInfo, DappId, ChainStatus,
}; };
use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings}; use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings};
use v1::helpers::dispatch::DEFAULT_MAC; use v1::helpers::dispatch::DEFAULT_MAC;
@ -111,7 +111,36 @@ impl<C, M, S: ?Sized, U> Parity for ParityClient<C, M, S, U> where
M: MinerService + 'static, M: MinerService + 'static,
C: MiningBlockChainClient + 'static, C: MiningBlockChainClient + 'static,
S: SyncProvider + 'static, S: SyncProvider + 'static,
U: UpdateService + 'static { U: UpdateService + 'static,
{
fn accounts_info(&self, dapp: Trailing<DappId>) -> Result<BTreeMap<String, BTreeMap<String, String>>, Error> {
try!(self.active());
let dapp = dapp.0;
let store = take_weak!(self.accounts);
let dapp_accounts = try!(store
.note_dapp_used(dapp.clone().into())
.and_then(|_| store.dapps_addresses(dapp.into()))
.map_err(|e| errors::internal("Could not fetch accounts.", e))
).into_iter().collect::<HashSet<_>>();
let info = try!(store.accounts_info().map_err(|e| errors::account("Could not fetch account info.", e)));
let other = store.addresses_info().expect("addresses_info always returns Ok; qed");
Ok(info
.into_iter()
.chain(other.into_iter())
.filter(|&(ref a, _)| dapp_accounts.contains(a))
.map(|(a, v)| {
let m = map![
"name".to_owned() => v.name
];
(format!("0x{}", a.hex()), m)
})
.collect()
)
}
fn transactions_limit(&self) -> Result<usize, Error> { fn transactions_limit(&self) -> Result<usize, Error> {
try!(self.active()); try!(self.active());
@ -350,24 +379,6 @@ impl<C, M, S: ?Sized, U> Parity for ParityClient<C, M, S, U> where
take_weak!(self.sync).enode().ok_or_else(errors::network_disabled) take_weak!(self.sync).enode().ok_or_else(errors::network_disabled)
} }
fn accounts(&self) -> Result<BTreeMap<String, BTreeMap<String, String>>, Error> {
try!(self.active());
let store = take_weak!(self.accounts);
let info = try!(store.accounts_info().map_err(|e| errors::account("Could not fetch account info.", e)));
let other = store.addresses_info().expect("addresses_info always returns Ok; qed");
Ok(info.into_iter().chain(other.into_iter()).map(|(a, v)| {
let mut m = map![
"name".to_owned() => v.name,
"meta".to_owned() => v.meta
];
if let &Some(ref uuid) = &v.uuid {
m.insert("uuid".to_owned(), format!("{}", uuid));
}
(format!("0x{}", a.hex()), m)
}).collect())
}
fn consensus_capability(&self) -> Result<ConsensusCapability, Error> { fn consensus_capability(&self) -> Result<ConsensusCapability, Error> {
try!(self.active()); try!(self.active());
let updater = take_weak!(self.updater); let updater = take_weak!(self.updater);

View File

@ -23,7 +23,7 @@ use ethkey::{Brain, Generator};
use ethcore::account_provider::AccountProvider; use ethcore::account_provider::AccountProvider;
use ethcore::client::MiningBlockChainClient; use ethcore::client::MiningBlockChainClient;
use jsonrpc_core::{Value, Error, to_value}; use jsonrpc_core::Error;
use v1::traits::ParityAccounts; use v1::traits::ParityAccounts;
use v1::types::{H160 as RpcH160, H256 as RpcH256, DappId}; use v1::types::{H160 as RpcH160, H256 as RpcH256, DappId};
use v1::helpers::errors; use v1::helpers::errors;
@ -51,23 +51,21 @@ impl<C> ParityAccountsClient<C> where C: MiningBlockChainClient {
} }
impl<C: 'static> ParityAccounts for ParityAccountsClient<C> where C: MiningBlockChainClient { impl<C: 'static> ParityAccounts for ParityAccountsClient<C> where C: MiningBlockChainClient {
fn accounts_info(&self) -> Result<BTreeMap<String, Value>, Error> { fn all_accounts_info(&self) -> Result<BTreeMap<String, BTreeMap<String, String>>, Error> {
try!(self.active()); try!(self.active());
let store = take_weak!(self.accounts); let store = take_weak!(self.accounts);
let info = try!(store.accounts_info().map_err(|e| errors::account("Could not fetch account info.", e))); let info = try!(store.accounts_info().map_err(|e| errors::account("Could not fetch account info.", e)));
let other = store.addresses_info().expect("addresses_info always returns Ok; qed"); let other = store.addresses_info().expect("addresses_info always returns Ok; qed");
Ok(other.into_iter().chain(info.into_iter()).map(|(a, v)| { Ok(info.into_iter().chain(other.into_iter()).map(|(a, v)| {
let m = map![ let mut m = map![
"name".to_owned() => to_value(&v.name), "name".to_owned() => v.name,
"meta".to_owned() => to_value(&v.meta), "meta".to_owned() => v.meta
"uuid".to_owned() => if let &Some(ref uuid) = &v.uuid {
to_value(uuid)
} else {
Value::Null
}
]; ];
(format!("0x{}", a.hex()), Value::Object(m)) if let &Some(ref uuid) = &v.uuid {
m.insert("uuid".to_owned(), format!("{}", uuid));
}
(format!("0x{}", a.hex()), m)
}).collect()) }).collect())
} }

View File

@ -99,6 +99,30 @@ impl Dependencies {
} }
} }
#[test]
fn rpc_parity_accounts_info() {
let deps = Dependencies::new();
let io = deps.default_client();
deps.accounts.new_account("").unwrap();
let accounts = deps.accounts.accounts().unwrap();
assert_eq!(accounts.len(), 1);
let address = accounts[0];
deps.accounts.set_account_name(address.clone(), "Test".to_owned()).unwrap();
deps.accounts.set_account_meta(address.clone(), "{foo: 69}".to_owned()).unwrap();
let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 1}"#;
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"name\":\"Test\"}}}},\"id\":1}}", address.hex());
assert_eq!(io.handle_request_sync(request), Some(response));
// Change the whitelist
deps.accounts.set_new_dapps_whitelist(Some(vec![1.into()])).unwrap();
let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 1}"#;
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{}},\"id\":1}}");
assert_eq!(io.handle_request_sync(request), Some(response));
}
#[test] #[test]
fn rpc_parity_consensus_capability() { fn rpc_parity_consensus_capability() {
let deps = Dependencies::new(); let deps = Dependencies::new();

View File

@ -68,7 +68,7 @@ fn should_be_able_to_get_account_info() {
tester.accounts.set_account_name(address.clone(), "Test".to_owned()).unwrap(); tester.accounts.set_account_name(address.clone(), "Test".to_owned()).unwrap();
tester.accounts.set_account_meta(address.clone(), "{foo: 69}".to_owned()).unwrap(); tester.accounts.set_account_meta(address.clone(), "{foo: 69}".to_owned()).unwrap();
let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_allAccountsInfo", "params": [], "id": 1}"#;
let res = tester.io.handle_request_sync(request); let res = tester.io.handle_request_sync(request);
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{foo: 69}}\",\"name\":\"Test\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid); let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{foo: 69}}\",\"name\":\"Test\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid);
assert_eq!(res, Some(response)); assert_eq!(res, Some(response));
@ -89,7 +89,7 @@ fn should_be_able_to_set_name() {
let uuid = tester.accounts.accounts_info().unwrap().get(&address).unwrap().uuid.as_ref().unwrap().clone(); let uuid = tester.accounts.accounts_info().unwrap().get(&address).unwrap().uuid.as_ref().unwrap().clone();
let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_allAccountsInfo", "params": [], "id": 1}"#;
let res = tester.io.handle_request_sync(request); let res = tester.io.handle_request_sync(request);
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{}}\",\"name\":\"Test\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid); let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{}}\",\"name\":\"Test\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid);
assert_eq!(res, Some(response)); assert_eq!(res, Some(response));
@ -110,7 +110,7 @@ fn should_be_able_to_set_meta() {
let uuid = tester.accounts.accounts_info().unwrap().get(&address).unwrap().uuid.as_ref().unwrap().clone(); let uuid = tester.accounts.accounts_info().unwrap().get(&address).unwrap().uuid.as_ref().unwrap().clone();
let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_allAccountsInfo", "params": [], "id": 1}"#;
let res = tester.io.handle_request_sync(request); let res = tester.io.handle_request_sync(request);
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{foo: 69}}\",\"name\":\"\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid); let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{foo: 69}}\",\"name\":\"\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid);
assert_eq!(res, Some(response)); assert_eq!(res, Some(response));
@ -210,9 +210,9 @@ fn should_be_able_to_remove_address() {
assert_eq!(res, Some(response.into())); assert_eq!(res, Some(response.into()));
// verify it exists // verify it exists
let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 2}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_allAccountsInfo", "params": [], "id": 2}"#;
let res = tester.io.handle_request_sync(request); let res = tester.io.handle_request_sync(request);
let response = r#"{"jsonrpc":"2.0","result":{"0x000baba1000baba2000baba3000baba4000baba5":{"meta":"{}","name":"Test","uuid":null}},"id":2}"#; let response = r#"{"jsonrpc":"2.0","result":{"0x000baba1000baba2000baba3000baba4000baba5":{"meta":"{}","name":"Test"}},"id":2}"#;
assert_eq!(res, Some(response.into())); assert_eq!(res, Some(response.into()));
// remove the address // remove the address
@ -222,7 +222,7 @@ fn should_be_able_to_remove_address() {
assert_eq!(res, Some(response.into())); assert_eq!(res, Some(response.into()));
// verify empty // verify empty
let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 4}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_allAccountsInfo", "params": [], "id": 4}"#;
let res = tester.io.handle_request_sync(request); let res = tester.io.handle_request_sync(request);
let response = r#"{"jsonrpc":"2.0","result":{},"id":4}"#; let response = r#"{"jsonrpc":"2.0","result":{},"id":4}"#;
assert_eq!(res, Some(response.into())); assert_eq!(res, Some(response.into()));

View File

@ -26,12 +26,16 @@ use v1::types::{
Peers, Transaction, RpcSettings, Histogram, Peers, Transaction, RpcSettings, Histogram,
TransactionStats, LocalTransactionStatus, TransactionStats, LocalTransactionStatus,
BlockNumber, ConsensusCapability, VersionInfo, BlockNumber, ConsensusCapability, VersionInfo,
OperationsInfo, ChainStatus, OperationsInfo, DappId, ChainStatus,
}; };
build_rpc_trait! { build_rpc_trait! {
/// Parity-specific rpc interface. /// Parity-specific rpc interface.
pub trait Parity { pub trait Parity {
/// Returns accounts information.
#[rpc(name = "parity_accountsInfo")]
fn accounts_info(&self, Trailing<DappId>) -> Result<BTreeMap<String, BTreeMap<String, String>>, Error>;
/// Returns current transactions limit. /// Returns current transactions limit.
#[rpc(name = "parity_transactionsLimit")] #[rpc(name = "parity_transactionsLimit")]
fn transactions_limit(&self) -> Result<usize, Error>; fn transactions_limit(&self) -> Result<usize, Error>;
@ -159,10 +163,6 @@ build_rpc_trait! {
#[rpc(name = "parity_enode")] #[rpc(name = "parity_enode")]
fn enode(&self) -> Result<String, Error>; fn enode(&self) -> Result<String, Error>;
/// Returns accounts information.
#[rpc(name = "parity_accounts")]
fn accounts(&self) -> Result<BTreeMap<String, BTreeMap<String, String>>, Error>;
/// Returns information on current consensus capability. /// Returns information on current consensus capability.
#[rpc(name = "parity_consensusCapability")] #[rpc(name = "parity_consensusCapability")]
fn consensus_capability(&self) -> Result<ConsensusCapability, Error>; fn consensus_capability(&self) -> Result<ConsensusCapability, Error>;

View File

@ -17,15 +17,15 @@
//! Parity Accounts-related rpc interface. //! Parity Accounts-related rpc interface.
use std::collections::BTreeMap; use std::collections::BTreeMap;
use jsonrpc_core::{Value, Error}; use jsonrpc_core::Error;
use v1::types::{H160, H256, DappId}; use v1::types::{H160, H256, DappId};
build_rpc_trait! { build_rpc_trait! {
/// Personal Parity rpc interface. /// Personal Parity rpc interface.
pub trait ParityAccounts { pub trait ParityAccounts {
/// Returns accounts information. /// Returns accounts information.
#[rpc(name = "parity_accountsInfo")] #[rpc(name = "parity_allAccountsInfo")]
fn accounts_info(&self) -> Result<BTreeMap<String, Value>, Error>; fn all_accounts_info(&self) -> Result<BTreeMap<String, BTreeMap<String, String>>, Error>;
/// Creates new account from the given phrase using standard brainwallet mechanism. /// Creates new account from the given phrase using standard brainwallet mechanism.
/// Second parameter is password for the new account. /// Second parameter is password for the new account.