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:
parent
546246c56b
commit
27ba0e6922
@ -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)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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', () => {
|
||||||
|
@ -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);
|
||||||
|
@ -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' }
|
||||||
};
|
};
|
||||||
|
@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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', () => {
|
||||||
|
@ -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 });
|
||||||
|
@ -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>
|
||||||
|
@ -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 }) => {
|
||||||
|
@ -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++) {
|
||||||
|
@ -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);
|
||||||
|
@ -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];
|
||||||
|
|
||||||
|
@ -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));
|
||||||
})
|
})
|
||||||
|
@ -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] || {};
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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: {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -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()));
|
||||||
|
@ -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>;
|
||||||
|
@ -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.
|
||||||
|
Loading…
Reference in New Issue
Block a user