fc::variant execute_interactive_command(const std::string& command, const fc::variants& arguments) { if (command == "sendtoaddress") { // the raw json version sends immediately, in the interactive version we want to // generate the transaction, have the user confirm it, then broadcast it interactive_sendtoaddress(command, arguments); } else if( command == "listdelegates" ) { if( arguments.size() == 2 ) _self->list_delegates( arguments[1].as<int64_t>() ); else _self->list_delegates( ); } else if (command == "rescan") return interactive_rescan(command, arguments); else if(command == "quit") { FC_THROW_EXCEPTION(canceled_exception, "quit command issued"); } else { return execute_command_and_prompt_for_passwords(command, arguments); } }
fc::variant rpc_server_impl::getbalance(const fc::variants& params) { bts::blockchain::asset_type unit = 0; if (params.size() == 1) unit = params[0].as<bts::blockchain::asset_type>(); return fc::variant( _client->get_wallet()->get_balance( unit ) ); }
fc::variant rpc_server_impl::rescan(const fc::variants& params) { uint32_t block_num = 0; if (params.size() == 1) block_num = (uint32_t)params[0].as_int64(); _client->get_wallet()->scan_chain(*_client->get_chain(), block_num); return fc::variant(true); }
fc::variant rpc_server_impl::get_send_address_label( const fc::variants& params ) { FC_ASSERT( params.size() == 1 ); std::unordered_map<bts::blockchain::address,std::string> addresses = _client->get_wallet()->get_send_addresses(); auto itr = addresses.find( params[0].as<address>() ); if( itr == addresses.end() ) return fc::variant(); return fc::variant(itr->second); }
fc::variant rpc_server_impl::getnewaddress(const fc::variants& params) { std::string account; if (params.size() == 1) account = params[0].as_string(); bts::blockchain::address new_address = _client->get_wallet()->new_receive_address(account); return fc::variant(new_address); }
fc::variant rpc_server_impl::add_send_address( const fc::variants& params ) { FC_ASSERT( params.size() == 2 ); auto foreign_address = params[0].as<address>(); auto label = params[1].as_string(); _client->get_wallet()->add_send_address( foreign_address, label ); return fc::variant(true); }
fc::variant rpc_server_impl::import_private_key(const fc::variants& params) { FC_ASSERT( params.size() == 2 ); fc::sha256 hash(params[0].as_string()); auto label = params[1].as_string(); fc::ecc::private_key privkey = fc::ecc::private_key::regenerate(hash); _client->get_wallet()->import_key(privkey, label); _client->get_wallet()->save(); return fc::variant(true); }
fc::variant rpc_server_impl::_create_sendtoaddress_transaction(const fc::variants& params) { bts::blockchain::address destination_address = params[0].as<bts::blockchain::address>(); bts::blockchain::asset amount = params[1].as<bts::blockchain::asset>(); std::string comment; if (params.size() >= 3) comment = params[2].as_string(); // TODO: we're currently ignoring optional parameter 4, [to-comment] return fc::variant(_client->get_wallet()->transfer(amount, destination_address, comment)); }
fc::variant rpc_server_impl::importprivkey(const fc::variants& params) { FC_ASSERT( params.size() == 2 ); auto wif = params[0].as_string(); auto label = params[1].as_string(); FC_ASSERT( !"Importing from WIF format not yet implemented" ); // TODO: convert bitcoin wallet import format wif to privakey //_client->get_wallet()->import_key(privkey, label); _client->get_wallet()->save(); return fc::variant(true); }
fc::variant rpc_server_impl::sendtoaddress(const fc::variants& params) { bts::blockchain::address destination_address = params[0].as<bts::blockchain::address>(); bts::blockchain::asset amount = params[1].as<bts::blockchain::asset>(); std::string comment; if (params.size() >= 3) comment = params[2].as_string(); // TODO: we're currently ignoring optional 4, [to-comment] bts::blockchain::signed_transaction trx = _client->get_wallet()->transfer(amount, destination_address, comment); _client->broadcast_transaction(trx); return fc::variant( trx.id() ); }
// Parse the given line into a command and arguments, returning them in the form our // json-rpc server functions require them. void parse_json_command(const std::string& line_to_parse, std::string& command, fc::variants& arguments) { // the first whitespace-separated token on the line should be an un-quoted // JSON-RPC command name command.clear(); arguments.clear(); std::string::const_iterator iter = std::find_if(line_to_parse.begin(), line_to_parse.end(), ::isspace); if (iter != line_to_parse.end()) { // then there are arguments to this function size_t first_space_pos = iter - line_to_parse.begin(); command = line_to_parse.substr(0, first_space_pos); fc::istream_ptr argument_stream = std::make_shared<fc::stringstream>((line_to_parse.substr(first_space_pos + 1))); fc::buffered_istream buffered_argument_stream(argument_stream); while (1) { try { arguments.emplace_back(fc::json::from_stream(buffered_argument_stream)); } catch (fc::eof_exception&) { break; } catch (fc::parse_error_exception& e) { FC_RETHROW_EXCEPTION(e, error, "Error parsing argument ${argument_number} of command \"${command}\": ${detail}", ("argument_number", arguments.size() + 1)("command", command)("detail", e.get_log())); } } } else { // no arguments command = line_to_parse; } }
fc::variant execute_interactive_command(const std::string& command, const fc::variants& arguments) { if (command == "wallet_create" || command == "wallet_change_passphrase") { if( command == "wallet_create" ) { auto wallet_name = arguments[0].as_string(); if( fc::exists( _client->get_wallet()->get_data_directory() / wallet_name ) ) { std::cout << "Wallet \"" << wallet_name << "\" already exists\n"; FC_THROW_EXCEPTION(invalid_arg_exception, ""); } } return execute_wallet_command_with_passphrase_query( command, arguments, "new passphrase", true ); } else if ( command == "unlock" || command == "open" || command == "wallet_open" || command == "wallet_open_file" || command == "wallet_unlock") { if( command == "wallet_open" || command == "open" ) { auto wallet_name = arguments[0].as_string(); if( !fc::exists( _client->get_wallet()->get_data_directory() / wallet_name ) ) { std::cout << "Wallet \"" << wallet_name << "\" not found\n"; FC_THROW_EXCEPTION(invalid_arg_exception, ""); } } else if( command == "wallet_open_file" ) { auto filename = arguments[0].as<fc::path>(); if( !fc::exists( filename ) ) { std::cout << "File \"" << filename.generic_string() << "\" not found\n"; FC_THROW_EXCEPTION(invalid_arg_exception, ""); } } return execute_wallet_command_with_passphrase_query( command, arguments, "passphrase" ); } else if (command == "wallet_import_bitcoin") { auto filename = arguments[0].as<fc::path>(); if( !fc::exists( filename ) ) { std::cout << "File \"" << filename.generic_string() << "\" not found\n"; FC_THROW_EXCEPTION(invalid_arg_exception, ""); } try /* Try empty password first */ { auto new_arguments = arguments; new_arguments.push_back( fc::variant( "" ) ); return _rpc_server->direct_invoke_method( command, new_arguments ); } catch( const fc::exception& e ) { ilog( "failed with empty password: ${e}", ("e",e.to_detail_string() ) ); } return execute_wallet_command_with_passphrase_query( command, arguments, "imported wallet passphrase" ); } else if (command == "wallet_export_to_json") { auto filename = arguments[0].as<fc::path>(); if( fc::exists( filename ) ) { std::cout << "File \"" << filename.generic_string() << "\" already exists\n"; FC_THROW_EXCEPTION(invalid_arg_exception, ""); } } else if (command == "wallet_create_from_json") { auto filename = arguments[0].as<fc::path>(); auto wallet_name = arguments[1].as_string(); if( !fc::exists( filename ) ) { std::cout << "File \"" << filename.generic_string() << "\" not found\n"; FC_THROW_EXCEPTION(invalid_arg_exception, ""); } if( fc::exists( _client->get_wallet()->get_data_directory() / wallet_name ) ) { std::cout << "Wallet \"" << wallet_name << "\" already exists\n"; FC_THROW_EXCEPTION(invalid_arg_exception, ""); } return execute_wallet_command_with_passphrase_query( command, arguments, "imported wallet passphrase" ); } else if(command == "wallet_rescan_blockchain") { if ( ! _client->get_wallet()->is_open() ) interactive_open_wallet(); std::cout << "Rescanning blockchain...\n"; uint32_t start; if (arguments.size() == 0) start = 1; else start = arguments[0].as<uint32_t>(); while(true) { try { for(int i = 0; i < 100; i++) std::cout << "-"; std::cout << "\n"; uint32_t next_step = 0; auto cb = [start, next_step](uint32_t cur, uint32_t last, uint32_t cur_trx, uint32_t last_trx) mutable { if (((100*(cur - start)) / (last - start)) > next_step) { std::cout << "="; next_step++; } }; _client->get_wallet()->scan_chain(start, cb); std::cout << "\n"; return fc::variant("Scan complete."); } catch( const rpc_wallet_open_needed_exception& ) { interactive_open_wallet(); } } } else if(command == "quit") { FC_THROW_EXCEPTION(canceled_exception, "quit command issued"); } return execute_command(command, arguments); }