// Copyright 2015, 2016 Ethcore (UK) Ltd. // This file is part of Parity. // Parity is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // Parity is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with Parity. If not, see . use ethcore::ethstore::{EthStore, SecretStore, import_accounts, read_geth_accounts}; use ethcore::ethstore::dir::DiskDirectory; use ethcore::account_provider::AccountProvider; use helpers::{password_prompt, password_from_file}; #[derive(Debug, PartialEq)] pub enum AccountCmd { New(NewAccount), List(String), Import(ImportAccounts), ImportFromGeth(ImportFromGethAccounts) } #[derive(Debug, PartialEq)] pub struct NewAccount { pub iterations: u32, pub path: String, pub password_file: Option, } #[derive(Debug, PartialEq)] pub struct ImportAccounts { pub from: Vec, pub to: String, } /// Parameters for geth accounts' import #[derive(Debug, PartialEq)] pub struct ImportFromGethAccounts { /// import mainnet (false) or testnet (true) accounts pub testnet: bool, /// directory to import accounts to pub to: String, } pub fn execute(cmd: AccountCmd) -> Result { match cmd { AccountCmd::New(new_cmd) => new(new_cmd), AccountCmd::List(path) => list(path), AccountCmd::Import(import_cmd) => import(import_cmd), AccountCmd::ImportFromGeth(import_geth_cmd) => import_geth(import_geth_cmd) } } fn keys_dir(path: String) -> Result { DiskDirectory::create(path).map_err(|e| format!("Could not open keys directory: {}", e)) } fn secret_store(dir: Box, iterations: Option) -> Result { match iterations { Some(i) => EthStore::open_with_iterations(dir, i), _ => EthStore::open(dir) }.map_err(|e| format!("Could not open keys store: {}", e)) } fn new(n: NewAccount) -> Result { let password: String = match n.password_file { Some(file) => try!(password_from_file(file)), None => try!(password_prompt()), }; let dir = Box::new(try!(keys_dir(n.path))); let secret_store = Box::new(try!(secret_store(dir, Some(n.iterations)))); let acc_provider = AccountProvider::new(secret_store); let new_account = try!(acc_provider.new_account(&password).map_err(|e| format!("Could not create new account: {}", e))); Ok(format!("{:?}", new_account)) } fn list(path: String) -> Result { let dir = Box::new(try!(keys_dir(path))); let secret_store = Box::new(try!(secret_store(dir, None))); let acc_provider = AccountProvider::new(secret_store); let accounts = acc_provider.accounts(); let result = accounts.into_iter() .map(|a| format!("{:?}", a)) .collect::>() .join("\n"); Ok(result) } fn import(i: ImportAccounts) -> Result { let to = try!(keys_dir(i.to)); let mut imported = 0; for path in &i.from { let from = DiskDirectory::at(path); imported += try!(import_accounts(&from, &to).map_err(|_| "Importing accounts failed.")).len(); } Ok(format!("{} account(s) imported", imported)) } fn import_geth(i: ImportFromGethAccounts) -> Result { use std::io::ErrorKind; use ethcore::ethstore::Error; let dir = Box::new(try!(keys_dir(i.to))); let secret_store = Box::new(try!(secret_store(dir, None))); let geth_accounts = read_geth_accounts(i.testnet); match secret_store.import_geth_accounts(geth_accounts, i.testnet) { Ok(v) => Ok(format!("Successfully imported {} account(s) from geth.", v.len())), Err(Error::Io(ref io_err)) if io_err.kind() == ErrorKind::NotFound => Err("Failed to find geth keys folder.".into()), Err(err) => Err(format!("Import geth accounts failed. {}", err)) } }