2014-08-13 10:38:35 +00:00
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
2014-04-02 16:00:17 +00:00
# include "include_base_utils.h"
using namespace epee ;
# include "wallet_rpc_server.h"
# include "common/command_line.h"
# include "cryptonote_core/cryptonote_format_utils.h"
# include "cryptonote_core/account.h"
# include "misc_language.h"
2014-04-29 16:26:45 +00:00
# include "string_tools.h"
2014-04-02 16:00:17 +00:00
# include "crypto/hash.h"
namespace tools
{
//-----------------------------------------------------------------------------------
const command_line : : arg_descriptor < std : : string > wallet_rpc_server : : arg_rpc_bind_port = { " rpc-bind-port " , " Starts wallet as rpc server for wallet operations, sets bind port for server " , " " , true } ;
const command_line : : arg_descriptor < std : : string > wallet_rpc_server : : arg_rpc_bind_ip = { " rpc-bind-ip " , " Specify ip to bind rpc server " , " 127.0.0.1 " } ;
void wallet_rpc_server : : init_options ( boost : : program_options : : options_description & desc )
{
command_line : : add_arg ( desc , arg_rpc_bind_ip ) ;
command_line : : add_arg ( desc , arg_rpc_bind_port ) ;
}
//------------------------------------------------------------------------------------------------------------------------------
wallet_rpc_server : : wallet_rpc_server ( wallet2 & w ) : m_wallet ( w )
{ }
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server : : run ( )
{
m_net_server . add_idle_handler ( [ this ] ( ) {
2014-08-13 10:51:37 +00:00
try {
m_wallet . refresh ( ) ;
} catch ( const std : : exception & ex ) {
LOG_ERROR ( " Exception at while refreshing, what= " < < ex . what ( ) ) ;
}
2014-04-02 16:00:17 +00:00
return true ;
} , 20000 ) ;
//DO NOT START THIS SERVER IN MORE THEN 1 THREADS WITHOUT REFACTORING
return epee : : http_server_impl_base < wallet_rpc_server , connection_context > : : run ( 1 , true ) ;
}
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server : : handle_command_line ( const boost : : program_options : : variables_map & vm )
{
m_bind_ip = command_line : : get_arg ( vm , arg_rpc_bind_ip ) ;
m_port = command_line : : get_arg ( vm , arg_rpc_bind_port ) ;
return true ;
}
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server : : init ( const boost : : program_options : : variables_map & vm )
{
m_net_server . set_threads_prefix ( " RPC " ) ;
bool r = handle_command_line ( vm ) ;
CHECK_AND_ASSERT_MES ( r , false , " Failed to process command line in core_rpc_server " ) ;
return epee : : http_server_impl_base < wallet_rpc_server , connection_context > : : init ( m_port , m_bind_ip ) ;
}
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server : : on_getbalance ( const wallet_rpc : : COMMAND_RPC_GET_BALANCE : : request & req , wallet_rpc : : COMMAND_RPC_GET_BALANCE : : response & res , epee : : json_rpc : : error & er , connection_context & cntx )
{
try
{
res . balance = m_wallet . balance ( ) ;
res . unlocked_balance = m_wallet . unlocked_balance ( ) ;
}
catch ( std : : exception & e )
{
er . code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR ;
er . message = e . what ( ) ;
return false ;
}
return true ;
}
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server : : on_transfer ( const wallet_rpc : : COMMAND_RPC_TRANSFER : : request & req , wallet_rpc : : COMMAND_RPC_TRANSFER : : response & res , epee : : json_rpc : : error & er , connection_context & cntx )
{
std : : vector < cryptonote : : tx_destination_entry > dsts ;
2014-06-25 17:21:42 +00:00
for ( auto it = req . destinations . begin ( ) ; it ! = req . destinations . end ( ) ; it + + ) {
2014-04-02 16:00:17 +00:00
cryptonote : : tx_destination_entry de ;
2014-08-13 10:51:37 +00:00
if ( ! m_wallet . currency ( ) . parseAccountAddressString ( it - > address , de . addr ) ) {
2014-04-02 16:00:17 +00:00
er . code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS ;
er . message = std : : string ( " WALLET_RPC_ERROR_CODE_WRONG_ADDRESS: " ) + it - > address ;
return false ;
}
de . amount = it - > amount ;
dsts . push_back ( de ) ;
}
2014-06-25 17:21:42 +00:00
std : : vector < uint8_t > extra ;
if ( ! req . payment_id . empty ( ) ) {
std : : string payment_id_str = req . payment_id ;
crypto : : hash payment_id ;
if ( ! wallet2 : : parse_payment_id ( payment_id_str , payment_id ) ) {
er . code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID ;
er . message = " Payment id has invalid format: \" " + payment_id_str + " \" , expected 64-character string " ;
return false ;
}
std : : string extra_nonce ;
cryptonote : : set_payment_id_to_tx_extra_nonce ( extra_nonce , payment_id ) ;
if ( ! cryptonote : : add_extra_nonce_to_tx_extra ( extra , extra_nonce ) ) {
er . code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID ;
er . message = " Something went wrong with payment_id. Please check its format: \" " + payment_id_str + " \" , expected 64-character string " ;
return false ;
}
}
try {
2014-08-13 10:51:37 +00:00
cryptonote : : Transaction tx ;
2014-06-25 17:21:42 +00:00
m_wallet . transfer ( dsts , req . mixin , req . unlock_time , req . fee , extra , tx ) ;
2014-04-02 16:00:17 +00:00
res . tx_hash = boost : : lexical_cast < std : : string > ( cryptonote : : get_transaction_hash ( tx ) ) ;
return true ;
2014-06-25 17:21:42 +00:00
} catch ( const tools : : error : : daemon_busy & e ) {
2014-04-02 16:00:17 +00:00
er . code = WALLET_RPC_ERROR_CODE_DAEMON_IS_BUSY ;
er . message = e . what ( ) ;
2014-04-29 16:26:45 +00:00
return false ;
2014-06-25 17:21:42 +00:00
} catch ( const std : : exception & e ) {
2014-04-02 16:00:17 +00:00
er . code = WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR ;
er . message = e . what ( ) ;
2014-04-29 16:26:45 +00:00
return false ;
2014-06-25 17:21:42 +00:00
} catch ( . . . ) {
2014-04-02 16:00:17 +00:00
er . code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR ;
er . message = " WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR " ;
2014-04-29 16:26:45 +00:00
return false ;
2014-04-02 16:00:17 +00:00
}
return true ;
}
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server : : on_store ( const wallet_rpc : : COMMAND_RPC_STORE : : request & req , wallet_rpc : : COMMAND_RPC_STORE : : response & res , epee : : json_rpc : : error & er , connection_context & cntx )
{
try
{
m_wallet . store ( ) ;
}
catch ( std : : exception & e )
{
er . code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR ;
er . message = e . what ( ) ;
return false ;
}
return true ;
}
//------------------------------------------------------------------------------------------------------------------------------
2014-04-29 16:26:45 +00:00
bool wallet_rpc_server : : on_get_payments ( const wallet_rpc : : COMMAND_RPC_GET_PAYMENTS : : request & req , wallet_rpc : : COMMAND_RPC_GET_PAYMENTS : : response & res , epee : : json_rpc : : error & er , connection_context & cntx )
{
crypto : : hash payment_id ;
cryptonote : : blobdata payment_id_blob ;
if ( ! epee : : string_tools : : parse_hexstr_to_binbuff ( req . payment_id , payment_id_blob ) )
{
er . code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID ;
er . message = " Payment ID has invald format " ;
return false ;
}
if ( sizeof ( payment_id ) ! = payment_id_blob . size ( ) )
{
er . code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID ;
er . message = " Payment ID has invalid size " ;
return false ;
}
payment_id = * reinterpret_cast < const crypto : : hash * > ( payment_id_blob . data ( ) ) ;
res . payments . clear ( ) ;
std : : list < wallet2 : : payment_details > payment_list ;
m_wallet . get_payments ( payment_id , payment_list ) ;
for ( auto payment : payment_list )
{
wallet_rpc : : payment_details rpc_payment ;
rpc_payment . tx_hash = epee : : string_tools : : pod_to_hex ( payment . m_tx_hash ) ;
rpc_payment . amount = payment . m_amount ;
rpc_payment . block_height = payment . m_block_height ;
rpc_payment . unlock_time = payment . m_unlock_time ;
res . payments . push_back ( rpc_payment ) ;
}
return true ;
}
//------------------------------------------------------------------------------------------------------------------------------
}