void rpc_client_impl::connect_to(const fc::ip::endpoint& remote_endpoint, const bts::blockchain::public_key_type& remote_public_key) { fc::buffered_istream_ptr buffered_istream; fc::buffered_ostream_ptr buffered_ostream; if( remote_public_key != bts::blockchain::public_key_type() ) { net::stcp_socket_ptr socket = std::make_shared<bts::net::stcp_socket>(); try { socket->connect_to(remote_endpoint); } catch ( const fc::exception& e ) { elog( "fatal: error opening RPC socket to endpoint ${endpoint}: ${e}", ("endpoint", remote_endpoint)("e", e.to_detail_string() ) ); throw; } std::vector<char> packed_signature(80, ' '); FC_ASSERT( socket->readsome(packed_signature.data(), packed_signature.size()) == 80, "Unexpected number of bytes read from RPC socket" ); fc::ecc::compact_signature signature; signature = fc::raw::unpack<fc::ecc::compact_signature>(packed_signature); wdump((signature)); FC_ASSERT(blockchain::public_key_type(fc::ecc::public_key(signature, fc::digest(socket->get_shared_secret()))) == remote_public_key, "Unable to establish secure connection with server."); buffered_istream = std::make_shared<fc::buffered_istream>(socket); buffered_ostream = std::make_shared<utilities::padding_ostream<>>(socket); } else { fc::tcp_socket_ptr socket = std::make_shared<fc::tcp_socket>(); try { socket->connect_to(remote_endpoint); } catch ( const fc::exception& e ) { elog( "fatal: error opening RPC socket to endpoint ${endpoint}: ${e}", ("endpoint", remote_endpoint)("e", e.to_detail_string() ) ); throw; } buffered_istream = std::make_shared<fc::buffered_istream>(socket); buffered_ostream = std::make_shared<fc::buffered_ostream>(socket); } _json_connection = std::make_shared<fc::rpc::json_connection>(std::move(buffered_istream), std::move(buffered_ostream)); _json_exec_loop_complete = fc::async([=](){ _json_connection->exec(); }, "json exec loop"); }
void rpc_client_impl::connect_to(const fc::ip::endpoint& remote_endpoint) { fc::tcp_socket_ptr socket = std::make_shared<fc::tcp_socket>(); try { socket->connect_to(remote_endpoint); } catch ( const fc::exception& e ) { elog( "fatal: error opening RPC socket to endpoint ${endpoint}: ${e}", ("endpoint", remote_endpoint)("e", e.to_detail_string() ) ); throw; } fc::buffered_istream_ptr buffered_istream = std::make_shared<fc::buffered_istream>(socket); fc::buffered_ostream_ptr buffered_ostream = std::make_shared<fc::buffered_ostream>(socket); _json_connection = std::make_shared<fc::rpc::json_connection>(std::move(buffered_istream), std::move(buffered_ostream)); _json_exec_loop_complete = fc::async([=](){ _json_connection->exec(); }, "json exec loop"); }
void register_methods( const fc::rpc::json_connection_ptr& con ) { std::cout<<"rpc login detected\n"; // don't capture the shared ptr, it would create a circular reference fc::rpc::json_connection* capture_con = con.get(); con->add_method( "login", [=]( const fc::variants& params ) -> fc::variant { FC_ASSERT( params.size() == 2 ); FC_ASSERT( params[0].as_string() == _config.rpc_user ) FC_ASSERT( params[1].as_string() == _config.rpc_password ) _login_set.insert( capture_con ); return fc::variant( true ); }); con->add_method( "getmargin", [=]( const fc::variants& params ) -> fc::variant { check_login( capture_con ); FC_ASSERT( params.size() == 1 ); FC_ASSERT( _chain_connected ); asset collat; asset due = _wallet.get_margin( params[0].as<asset::type>(), collat ); fc::mutable_variant_object info; info["collateral"] = fc::variant(chain.head_block_id()); info["owed"] = fc::variant(due); collat.amount *= 3; collat.amount /= 4; // info["min_call_price"] = info["avg_call_price"] = std::string( due/collat ); return fc::variant(info); }); con->add_method( "addmargin", [=]( const fc::variants& params ) -> fc::variant { check_login( capture_con ); FC_ASSERT( params.size() == 2 ); FC_ASSERT( _chain_connected ); asset collat = params[0].as<asset>(); FC_ASSERT( collat.unit == asset::bts ); auto trx = _wallet.add_margin( collat, params[1].as<asset::type>() ); broadcast_transaction(trx); return fc::variant(trx.id()); }); con->add_method( "getmarket", [=]( const fc::variants& params ) -> fc::variant { FC_ASSERT( _chain_connected ); FC_ASSERT( params.size() == 2 ); market_data data = chain.get_market( params[0].as<asset::type>(), params[1].as<asset::type>() ); return fc::variant(data); }); con->add_method( "getnewaddress", [=]( const fc::variants& params ) -> fc::variant { check_login( capture_con ); return fc::variant( _wallet.get_new_address() ); }); con->add_method( "transfer", [=]( const fc::variants& params ) -> fc::variant { FC_ASSERT( _chain_connected ); check_login( capture_con ); FC_ASSERT( params.size() == 2 ); auto amount = params[0].as<bts::blockchain::asset>(); auto addr = params[1].as_string(); auto trx = _wallet.transfer( amount, addr ); broadcast_transaction(trx); return fc::variant( trx.id() ); }); con->add_method( "getbalance", [=]( const fc::variants& params ) -> fc::variant { FC_ASSERT( _chain_connected ); check_login( capture_con ); FC_ASSERT( params.size() == 1 ); auto unit = params[0].as<bts::blockchain::asset::type>(); return fc::variant( _wallet.get_balance( unit ) ); }); con->add_method( "buy", [=]( const fc::variants& params ) -> fc::variant { FC_ASSERT( _chain_connected ); check_login( capture_con ); FC_ASSERT( params.size() == 2 ); auto amount = params[0].as<bts::blockchain::asset>(); auto ppu = params[1].as<bts::blockchain::asset>(); auto price_ratio = ppu / asset( 1.0, amount.unit ); auto required_input = amount * price_ratio; auto trx = buy( required_input, price_ratio ); return fc::variant( trx ); }); con->add_method( "sell", [=]( const fc::variants& params ) -> fc::variant { FC_ASSERT( _chain_connected ); check_login( capture_con ); FC_ASSERT( params.size() == 2 ); auto amount = params[0].as<bts::blockchain::asset>(); auto ppu = params[1].as<bts::blockchain::asset>(); auto price_ratio = ppu / asset( 1.0, amount.unit ); auto trx = sell( amount, price_ratio ); return fc::variant( trx ); }); con->add_method( "short_sell", [=]( const fc::variants& params ) -> fc::variant { FC_ASSERT( _chain_connected ); check_login( capture_con ); FC_ASSERT( params.size() == 2 ); auto amount = params[0].as<bts::blockchain::asset>(); auto ppu = params[1].as<bts::blockchain::asset>(); auto price_ratio = ppu / asset( 1.0, amount.unit ); auto trx = short_sell( amount, price_ratio ); return fc::variant( trx ); }); con->add_method( "cover", [=]( const fc::variants& params ) -> fc::variant { FC_ASSERT( _chain_connected ); check_login( capture_con ); FC_ASSERT( params.size() == 1 ); auto amount = params[0].as<bts::blockchain::asset>(); auto trx = _wallet.cover( amount ); broadcast_transaction( trx ); return fc::variant(trx.id()); }); con->add_method( "cancel_order", [=]( const fc::variants& params ) -> fc::variant { FC_ASSERT( _chain_connected ); check_login( capture_con ); FC_ASSERT( params.size() == 2 ); auto trx_id = params[0].as_string(); auto output_index = params[1].as_int64(); auto trx = cancel_open_bid( trx_id, output_index ); return fc::variant( trx ); }); con->add_method( "get_transaction", [=]( const fc::variants& params ) -> fc::variant { FC_ASSERT( params.size() == 1 ); return fc::variant( chain.fetch_transaction( params[0].as<transaction_id_type>() ) ); }); con->add_method( "get_block", [=]( const fc::variants& params ) -> fc::variant { FC_ASSERT( params.size() == 1 ); return fc::variant( chain.fetch_block( params[0].as_int64() ) ); }); con->add_method( "getinfo", [=]( const fc::variants& params ) -> fc::variant { fc::mutable_variant_object info; info["headblock_id"] = fc::variant(chain.head_block_id()); info["block_count"] = chain.head_block_num(); info["connected"] = _chain_connected; info["bts_supply"] = chain.current_bitshare_supply(); return fc::variant( info ); }); con->add_method( "validateaddress", [=]( const fc::variants& params ) -> fc::variant { FC_ASSERT( params.size() == 1 ); try { auto test = bts::address( params[0].as_string() ); return fc::variant(test.is_valid()); } catch ( const fc::exception& ) { return fc::variant(false); } }); con->add_method( "get_open_bids", [=]( const fc::variants& params ) -> fc::variant { check_login( capture_con ); return fc::variant( _wallet.get_open_bids() ); }); con->add_method( "get_open_short_sell", [=]( const fc::variants& params ) -> fc::variant { check_login( capture_con ); return fc::variant( _wallet.get_open_short_sell() ); }); con->add_method( "import_bts_privkey", [=]( const fc::variants& params ) -> fc::variant { check_login( capture_con ); bool rescan = false; FC_ASSERT( params.size() == 1 ); if( params.size() == 3 ) { rescan = params[2].as<bool>(); } auto hashed_parameter = fc::sha256( params[0].as_string() ); auto private_key = fc::ecc::private_key::regenerate( hashed_parameter ); _wallet.import_key( private_key ); if( rescan ) { _wallet.scan_chain(chain); } return fc::variant( true ); }); }
fc::optional<std::string> rpc_client_impl::currentwallet() { fc::variant result = _json_connection->async_call("currentwallet").wait(); return result.is_null() ? fc::optional<std::string>() : result.as_string(); }