Merge pull request #3792 from ethcore/dapps-accounts-rpc

Additional RPCs for dapps accounts management
This commit is contained in:
Gav Wood
2016-12-15 18:09:40 +01:00
committed by GitHub
11 changed files with 352 additions and 50 deletions

View File

@@ -340,7 +340,11 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
let dapp = id.0;
let store = take_weak!(self.accounts);
let accounts = try!(store.dapps_addresses(dapp.into()).map_err(|e| errors::internal("Could not fetch accounts.", e)));
let 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))
);
Ok(accounts.into_iter().map(Into::into).collect())
}

View File

@@ -164,19 +164,51 @@ impl<C: 'static> ParityAccounts for ParityAccountsClient<C> where C: MiningBlock
fn set_dapps_addresses(&self, dapp: DappId, addresses: Vec<RpcH160>) -> Result<bool, Error> {
let store = take_weak!(self.accounts);
let addresses = addresses.into_iter().map(Into::into).collect();
store.set_dapps_addresses(dapp.into(), addresses)
store.set_dapps_addresses(dapp.into(), into_vec(addresses))
.map_err(|e| errors::account("Couldn't set dapps addresses.", e))
.map(|_| true)
}
fn dapps_addresses(&self, dapp: DappId) -> Result<Vec<RpcH160>, Error> {
let store = take_weak!(self.accounts);
store.dapps_addresses(dapp.into())
.map_err(|e| errors::account("Couldn't get dapps addresses.", e))
.map(into_vec)
}
fn set_new_dapps_whitelist(&self, whitelist: Option<Vec<RpcH160>>) -> Result<bool, Error> {
let store = take_weak!(self.accounts);
store
.set_new_dapps_whitelist(whitelist.map(into_vec))
.map_err(|e| errors::account("Couldn't set dapps whitelist.", e))
.map(|_| true)
}
fn new_dapps_whitelist(&self) -> Result<Option<Vec<RpcH160>>, Error> {
let store = take_weak!(self.accounts);
store.new_dapps_whitelist()
.map_err(|e| errors::account("Couldn't get dapps whitelist.", e))
.map(|accounts| accounts.map(into_vec))
}
fn recent_dapps(&self) -> Result<Vec<DappId>, Error> {
let store = take_weak!(self.accounts);
store.recent_dapps()
.map_err(|e| errors::account("Couldn't get recent dapps.", e))
.map(into_vec)
}
fn import_geth_accounts(&self, addresses: Vec<RpcH160>) -> Result<Vec<RpcH160>, Error> {
let store = take_weak!(self.accounts);
store
.import_geth_accounts(addresses.into_iter().map(Into::into).collect(), false)
.map(|imported| imported.into_iter().map(Into::into).collect())
.import_geth_accounts(into_vec(addresses), false)
.map(into_vec)
.map_err(|e| errors::account("Couldn't import Geth accounts", e))
}
@@ -184,10 +216,12 @@ impl<C: 'static> ParityAccounts for ParityAccountsClient<C> where C: MiningBlock
try!(self.active());
let store = take_weak!(self.accounts);
Ok(store.list_geth_accounts(false)
.into_iter()
.map(Into::into)
.collect()
)
Ok(into_vec(store.list_geth_accounts(false)))
}
}
fn into_vec<A, B>(a: Vec<A>) -> Vec<B> where
A: Into<B>
{
a.into_iter().map(Into::into).collect()
}

View File

@@ -354,11 +354,18 @@ fn rpc_eth_gas_price() {
#[test]
fn rpc_eth_accounts() {
let tester = EthTester::default();
let _address = tester.accounts_provider.new_account("").unwrap();
let address = tester.accounts_provider.new_account("").unwrap();
tester.accounts_provider.set_new_dapps_whitelist(None).unwrap();
// with current policy it should return the account
let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": [], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":[""#.to_owned() + &format!("0x{:?}", address) + r#""],"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
tester.accounts_provider.set_new_dapps_whitelist(Some(vec![1.into()])).unwrap();
// even with some account it should return empty list (no dapp detected)
let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": [], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":[],"id":1}"#;
let response = r#"{"jsonrpc":"2.0","result":["0x0000000000000000000000000000000000000001"],"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
// when we add visible address it should return that.

View File

@@ -117,7 +117,7 @@ fn should_be_able_to_set_meta() {
}
#[test]
fn rpc_parity_set_dapps_accounts() {
fn rpc_parity_set_and_get_dapps_accounts() {
// given
let tester = setup();
assert_eq!(tester.accounts.dapps_addresses("app1".into()).unwrap(), vec![]);
@@ -129,6 +129,52 @@ fn rpc_parity_set_dapps_accounts() {
// then
assert_eq!(tester.accounts.dapps_addresses("app1".into()).unwrap(), vec![10.into()]);
let request = r#"{"jsonrpc": "2.0", "method": "parity_getDappsAddresses","params":["app1"], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":["0x000000000000000000000000000000000000000a"],"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test]
fn rpc_parity_set_and_get_new_dapps_whitelist() {
// given
let tester = setup();
// when set to whitelist
let request = r#"{"jsonrpc": "2.0", "method": "parity_setNewDappsWhitelist","params":[["0x000000000000000000000000000000000000000a"]], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
// then
assert_eq!(tester.accounts.new_dapps_whitelist().unwrap(), Some(vec![10.into()]));
let request = r#"{"jsonrpc": "2.0", "method": "parity_getNewDappsWhitelist","params":[], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":["0x000000000000000000000000000000000000000a"],"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
// when set to empty
let request = r#"{"jsonrpc": "2.0", "method": "parity_setNewDappsWhitelist","params":[null], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
// then
assert_eq!(tester.accounts.new_dapps_whitelist().unwrap(), None);
let request = r#"{"jsonrpc": "2.0", "method": "parity_getNewDappsWhitelist","params":[], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test]
fn rpc_parity_recent_dapps() {
// given
let tester = setup();
// when
// trigger dapp usage
tester.accounts.note_dapp_used("dapp1".into()).unwrap();
// then
let request = r#"{"jsonrpc": "2.0", "method": "parity_listRecentDapps","params":[], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":["dapp1"],"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test]

View File

@@ -78,6 +78,24 @@ build_rpc_trait! {
#[rpc(name = "parity_setDappsAddresses")]
fn set_dapps_addresses(&self, DappId, Vec<H160>) -> Result<bool, Error>;
/// Gets accounts exposed for particular dapp.
#[rpc(name = "parity_getDappsAddresses")]
fn dapps_addresses(&self, DappId) -> Result<Vec<H160>, Error>;
/// Sets accounts exposed for new dapps.
/// `None` means that all accounts will be exposed.
#[rpc(name = "parity_setNewDappsWhitelist")]
fn set_new_dapps_whitelist(&self, Option<Vec<H160>>) -> Result<bool, Error>;
/// Gets accounts exposed for new dapps.
/// `None` means that all accounts will be exposed.
#[rpc(name = "parity_getNewDappsWhitelist")]
fn new_dapps_whitelist(&self) -> Result<Option<Vec<H160>>, Error>;
/// Sets accounts exposed for particular dapp.
#[rpc(name = "parity_listRecentDapps")]
fn recent_dapps(&self) -> Result<Vec<DappId>, Error>;
/// Imports a number of Geth accounts, with the list provided as the argument.
#[rpc(name = "parity_importGethAccounts")]
fn import_geth_accounts(&self, Vec<H160>) -> Result<Vec<H160>, Error>;

View File

@@ -26,6 +26,12 @@ impl Into<String> for DappId {
}
}
impl From<String> for DappId {
fn from(s: String) -> Self {
DappId(s)
}
}
#[cfg(test)]
mod tests {