diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 2c741c2e5..635f1bb41 100755 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -906,6 +906,12 @@ std::string wallet2::get_subaddress_as_str(const cryptonote::subaddress_index& i cryptonote::account_public_address address = get_subaddress(index); return cryptonote::get_account_address_as_str(m_nettype, !index.is_zero(), address); } + +//---------------------------------------------------------------------------------------------------- +std::string wallet2::get_integrated_address_as_str(const crypto::hash8& payment_id) const +{ + return cryptonote::get_account_integrated_address_as_str(m_nettype, get_address(), payment_id); +} //---------------------------------------------------------------------------------------------------- void wallet2::add_subaddress_account(const std::string& label) { diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 8e79779a2..ed02d7a28 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -629,6 +629,7 @@ namespace tools std::vector get_subaddress_spend_public_keys(uint32_t account, uint32_t begin, uint32_t end) const; std::string get_subaddress_as_str(const cryptonote::subaddress_index& index) const; std::string get_address_as_str() const { return get_subaddress_as_str({0, 0}); } + std::string get_integrated_address_as_str(const crypto::hash8& payment_id) const; void add_subaddress_account(const std::string& label); size_t get_num_subaddress_accounts() const { return m_subaddress_labels.size(); } size_t get_num_subaddresses(uint32_t index_major) const { return index_major < m_subaddress_labels.size() ? m_subaddress_labels[index_major].size() : 0; } diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 8c75031a7..d3491baae 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -1099,6 +1099,69 @@ namespace tools return true; } //------------------------------------------------------------------------------------------------------------------------------ + bool wallet_rpc_server::on_make_integrated_address(const wallet_rpc::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS::request& req, wallet_rpc::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS::response& res, epee::json_rpc::error& er) + { + if (!m_wallet) return not_open(er); + try + { + crypto::hash8 payment_id; + if (req.payment_id.empty()) + { + payment_id = crypto::rand(); + } + else + { + if (!tools::wallet2::parse_short_payment_id(req.payment_id,payment_id)) + { + er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID; + er.message = "Invalid payment ID"; + return false; + } + } + + res.integrated_address = m_wallet->get_integrated_address_as_str(payment_id); + res.payment_id = epee::string_tools::pod_to_hex(payment_id); + return true; + } + catch (const std::exception& e) + { + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); + return false; + } + return true; + } + //------------------------------------------------------------------------------------------------------------------------------ + bool wallet_rpc_server::on_split_integrated_address(const wallet_rpc::COMMAND_RPC_SPLIT_INTEGRATED_ADDRESS::request& req, wallet_rpc::COMMAND_RPC_SPLIT_INTEGRATED_ADDRESS::response& res, epee::json_rpc::error& er) + { + if (!m_wallet) return not_open(er); + try + { + cryptonote::address_parse_info info; + + if(!get_account_address_from_str(info, m_wallet->nettype(), req.integrated_address)) + { + er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS; + er.message = "Invalid address"; + return false; + } + if(!info.has_payment_id) + { + er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS; + er.message = "Address is not an integrated address"; + return false; + } + res.standard_address = get_account_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address); + res.payment_id = epee::string_tools::pod_to_hex(info.payment_id); + return true; + } + catch (const std::exception& e) + { + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); + return false; + } + 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) { if (!m_wallet) return not_open(er); diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h index 04e57db11..a68e12d97 100644 --- a/src/wallet/wallet_rpc_server.h +++ b/src/wallet/wallet_rpc_server.h @@ -95,6 +95,8 @@ namespace tools MAP_JON_RPC_WE("get_bulk_payments", on_get_bulk_payments, wallet_rpc::COMMAND_RPC_GET_BULK_PAYMENTS) MAP_JON_RPC_WE("incoming_transfers", on_incoming_transfers, wallet_rpc::COMMAND_RPC_INCOMING_TRANSFERS) MAP_JON_RPC_WE("query_key", on_query_key, wallet_rpc::COMMAND_RPC_QUERY_KEY) + MAP_JON_RPC_WE("make_integrated_address", on_make_integrated_address, wallet_rpc::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS) + MAP_JON_RPC_WE("split_integrated_address", on_split_integrated_address, wallet_rpc::COMMAND_RPC_SPLIT_INTEGRATED_ADDRESS) MAP_JON_RPC_WE("stop_wallet", on_stop_wallet, wallet_rpc::COMMAND_RPC_STOP_WALLET) MAP_JON_RPC_WE("rescan_blockchain", on_rescan_blockchain, wallet_rpc::COMMAND_RPC_RESCAN_BLOCKCHAIN) MAP_JON_RPC_WE("set_tx_notes", on_set_tx_notes, wallet_rpc::COMMAND_RPC_SET_TX_NOTES) @@ -158,6 +160,8 @@ namespace tools bool on_sweep_all(const wallet_rpc::COMMAND_RPC_SWEEP_ALL::request& req, wallet_rpc::COMMAND_RPC_SWEEP_ALL::response& res, epee::json_rpc::error& er); bool on_sweep_single(const wallet_rpc::COMMAND_RPC_SWEEP_SINGLE::request& req, wallet_rpc::COMMAND_RPC_SWEEP_SINGLE::response& res, epee::json_rpc::error& er); bool on_relay_tx(const wallet_rpc::COMMAND_RPC_RELAY_TX::request& req, wallet_rpc::COMMAND_RPC_RELAY_TX::response& res, epee::json_rpc::error& er); + bool on_make_integrated_address(const wallet_rpc::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS::request& req, wallet_rpc::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS::response& res, epee::json_rpc::error& er); + bool on_split_integrated_address(const wallet_rpc::COMMAND_RPC_SPLIT_INTEGRATED_ADDRESS::request& req, wallet_rpc::COMMAND_RPC_SPLIT_INTEGRATED_ADDRESS::response& res, epee::json_rpc::error& er); bool on_store(const wallet_rpc::COMMAND_RPC_STORE::request& req, wallet_rpc::COMMAND_RPC_STORE::response& res, epee::json_rpc::error& er); bool 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); bool on_get_bulk_payments(const wallet_rpc::COMMAND_RPC_GET_BULK_PAYMENTS::request& req, wallet_rpc::COMMAND_RPC_GET_BULK_PAYMENTS::response& res, epee::json_rpc::error& er); diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index e64f4a189..f264829ad 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -873,6 +873,53 @@ namespace wallet_rpc }; }; + struct COMMAND_RPC_MAKE_INTEGRATED_ADDRESS + { + struct request + { + std::string payment_id; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(payment_id) + END_KV_SERIALIZE_MAP() + }; + + struct response + { + std::string integrated_address; + std::string payment_id; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(integrated_address) + KV_SERIALIZE(payment_id) + END_KV_SERIALIZE_MAP() + }; + }; + + struct COMMAND_RPC_SPLIT_INTEGRATED_ADDRESS + { + struct request + { + std::string integrated_address; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(integrated_address) + END_KV_SERIALIZE_MAP() + }; + + struct response + { + std::string standard_address; + std::string payment_id; + bool is_subaddress; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(standard_address) + KV_SERIALIZE(payment_id) + KV_SERIALIZE(is_subaddress) + END_KV_SERIALIZE_MAP() + }; + }; struct COMMAND_RPC_STOP_WALLET {