aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/wallet_rpc_server.cpp213
-rw-r--r--src/wallet/wallet_rpc_server.h8
-rw-r--r--src/wallet/wallet_rpc_server_commands_defs.h73
3 files changed, 208 insertions, 86 deletions
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 2a259029d..21965c4c8 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -201,6 +201,73 @@ namespace tools
);
}
//------------------------------------------------------------------------------------------------------------------------------
+ void wallet_rpc_server::fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, const crypto::hash &payment_id, const tools::wallet2::payment_details &pd)
+ {
+ entry.txid = string_tools::pod_to_hex(pd.m_tx_hash);
+ entry.payment_id = string_tools::pod_to_hex(payment_id);
+ if (entry.payment_id.substr(16).find_first_not_of('0') == std::string::npos)
+ entry.payment_id = entry.payment_id.substr(0,16);
+ entry.height = pd.m_block_height;
+ entry.timestamp = pd.m_timestamp;
+ entry.amount = pd.m_amount;
+ entry.fee = 0; // TODO
+ entry.note = m_wallet.get_tx_note(pd.m_tx_hash);
+ entry.type = "in";
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
+ void wallet_rpc_server::fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, const tools::wallet2::confirmed_transfer_details &pd)
+ {
+ entry.txid = string_tools::pod_to_hex(txid);
+ entry.payment_id = string_tools::pod_to_hex(pd.m_payment_id);
+ if (entry.payment_id.substr(16).find_first_not_of('0') == std::string::npos)
+ entry.payment_id = entry.payment_id.substr(0,16);
+ entry.height = pd.m_block_height;
+ entry.timestamp = pd.m_timestamp;
+ entry.fee = pd.m_amount_in - pd.m_amount_out;
+ uint64_t change = pd.m_change == (uint64_t)-1 ? 0 : pd.m_change; // change may not be known
+ entry.amount = pd.m_amount_in - change - entry.fee;
+ entry.note = m_wallet.get_tx_note(txid);
+
+ for (const auto &d: pd.m_dests) {
+ entry.destinations.push_back(wallet_rpc::transfer_destination());
+ wallet_rpc::transfer_destination &td = entry.destinations.back();
+ td.amount = d.amount;
+ td.address = get_account_address_as_str(m_wallet.testnet(), d.addr);
+ }
+
+ entry.type = "out";
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
+ void wallet_rpc_server::fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, const tools::wallet2::unconfirmed_transfer_details &pd)
+ {
+ bool is_failed = pd.m_state == tools::wallet2::unconfirmed_transfer_details::failed;
+ entry.txid = string_tools::pod_to_hex(txid);
+ entry.payment_id = string_tools::pod_to_hex(pd.m_payment_id);
+ entry.payment_id = string_tools::pod_to_hex(pd.m_payment_id);
+ if (entry.payment_id.substr(16).find_first_not_of('0') == std::string::npos)
+ entry.payment_id = entry.payment_id.substr(0,16);
+ entry.height = 0;
+ entry.timestamp = pd.m_timestamp;
+ entry.fee = pd.m_amount_in - pd.m_amount_out;
+ entry.amount = pd.m_amount_in - pd.m_change - entry.fee;
+ entry.note = m_wallet.get_tx_note(txid);
+ entry.type = is_failed ? "failed" : "pending";
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
+ void wallet_rpc_server::fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &payment_id, const tools::wallet2::payment_details &pd)
+ {
+ entry.txid = string_tools::pod_to_hex(pd.m_tx_hash);
+ entry.payment_id = string_tools::pod_to_hex(payment_id);
+ if (entry.payment_id.substr(16).find_first_not_of('0') == std::string::npos)
+ entry.payment_id = entry.payment_id.substr(0,16);
+ entry.height = 0;
+ entry.timestamp = pd.m_timestamp;
+ entry.amount = pd.m_amount;
+ entry.fee = 0; // TODO
+ entry.note = m_wallet.get_tx_note(pd.m_tx_hash);
+ entry.type = "pool";
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
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)
{
try
@@ -1014,19 +1081,8 @@ namespace tools
std::list<std::pair<crypto::hash, tools::wallet2::payment_details>> payments;
m_wallet.get_payments(payments, min_height, max_height);
for (std::list<std::pair<crypto::hash, tools::wallet2::payment_details>>::const_iterator i = payments.begin(); i != payments.end(); ++i) {
- res.in.push_back(wallet_rpc::COMMAND_RPC_GET_TRANSFERS::entry());
- wallet_rpc::COMMAND_RPC_GET_TRANSFERS::entry &entry = res.in.back();
- const tools::wallet2::payment_details &pd = i->second;
-
- entry.txid = string_tools::pod_to_hex(pd.m_tx_hash);
- entry.payment_id = string_tools::pod_to_hex(i->first);
- if (entry.payment_id.substr(16).find_first_not_of('0') == std::string::npos)
- entry.payment_id = entry.payment_id.substr(0,16);
- entry.height = pd.m_block_height;
- entry.timestamp = pd.m_timestamp;
- entry.amount = pd.m_amount;
- entry.fee = 0; // TODO
- entry.note = m_wallet.get_tx_note(pd.m_tx_hash);
+ res.in.push_back(wallet_rpc::transfer_entry());
+ fill_transfer_entry(res.in.back(), i->second.m_tx_hash, i->first, i->second);
}
}
@@ -1035,27 +1091,8 @@ namespace tools
std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>> payments;
m_wallet.get_payments_out(payments, min_height, max_height);
for (std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>>::const_iterator i = payments.begin(); i != payments.end(); ++i) {
- res.out.push_back(wallet_rpc::COMMAND_RPC_GET_TRANSFERS::entry());
- wallet_rpc::COMMAND_RPC_GET_TRANSFERS::entry &entry = res.out.back();
- const tools::wallet2::confirmed_transfer_details &pd = i->second;
-
- entry.txid = string_tools::pod_to_hex(i->first);
- entry.payment_id = string_tools::pod_to_hex(i->second.m_payment_id);
- if (entry.payment_id.substr(16).find_first_not_of('0') == std::string::npos)
- entry.payment_id = entry.payment_id.substr(0,16);
- entry.height = pd.m_block_height;
- entry.timestamp = pd.m_timestamp;
- entry.fee = pd.m_amount_in - pd.m_amount_out;
- uint64_t change = pd.m_change == (uint64_t)-1 ? 0 : pd.m_change; // change may not be known
- entry.amount = pd.m_amount_in - change - entry.fee;
- entry.note = m_wallet.get_tx_note(i->first);
-
- for (const auto &d: pd.m_dests) {
- entry.destinations.push_back(wallet_rpc::transfer_destination());
- wallet_rpc::transfer_destination &td = entry.destinations.back();
- td.amount = d.amount;
- td.address = get_account_address_as_str(m_wallet.testnet(), d.addr);
- }
+ res.out.push_back(wallet_rpc::transfer_entry());
+ fill_transfer_entry(res.out.back(), i->first, i->second);
}
}
@@ -1067,20 +1104,9 @@ namespace tools
bool is_failed = pd.m_state == tools::wallet2::unconfirmed_transfer_details::failed;
if (!((req.failed && is_failed) || (!is_failed && req.pending)))
continue;
- std::list<wallet_rpc::COMMAND_RPC_GET_TRANSFERS::entry> &entries = is_failed ? res.failed : res.pending;
- entries.push_back(wallet_rpc::COMMAND_RPC_GET_TRANSFERS::entry());
- wallet_rpc::COMMAND_RPC_GET_TRANSFERS::entry &entry = entries.back();
-
- entry.txid = string_tools::pod_to_hex(i->first);
- entry.payment_id = string_tools::pod_to_hex(i->second.m_payment_id);
- entry.payment_id = string_tools::pod_to_hex(i->second.m_payment_id);
- if (entry.payment_id.substr(16).find_first_not_of('0') == std::string::npos)
- entry.payment_id = entry.payment_id.substr(0,16);
- entry.height = 0;
- entry.timestamp = pd.m_timestamp;
- entry.fee = pd.m_amount_in - pd.m_amount_out;
- entry.amount = pd.m_amount_in - pd.m_change - entry.fee;
- entry.note = m_wallet.get_tx_note(i->first);
+ std::list<wallet_rpc::transfer_entry> &entries = is_failed ? res.failed : res.pending;
+ entries.push_back(wallet_rpc::transfer_entry());
+ fill_transfer_entry(entries.back(), i->first, i->second);
}
}
@@ -1091,25 +1117,90 @@ namespace tools
std::list<std::pair<crypto::hash, tools::wallet2::payment_details>> payments;
m_wallet.get_unconfirmed_payments(payments);
for (std::list<std::pair<crypto::hash, tools::wallet2::payment_details>>::const_iterator i = payments.begin(); i != payments.end(); ++i) {
- res.pool.push_back(wallet_rpc::COMMAND_RPC_GET_TRANSFERS::entry());
- wallet_rpc::COMMAND_RPC_GET_TRANSFERS::entry &entry = res.pool.back();
- const tools::wallet2::payment_details &pd = i->second;
-
- entry.txid = string_tools::pod_to_hex(pd.m_tx_hash);
- entry.payment_id = string_tools::pod_to_hex(i->first);
- if (entry.payment_id.substr(16).find_first_not_of('0') == std::string::npos)
- entry.payment_id = entry.payment_id.substr(0,16);
- entry.height = 0;
- entry.timestamp = pd.m_timestamp;
- entry.amount = pd.m_amount;
- entry.fee = 0; // TODO
- entry.note = m_wallet.get_tx_note(pd.m_tx_hash);
+ res.pool.push_back(wallet_rpc::transfer_entry());
+ fill_transfer_entry(res.pool.back(), i->first, i->second);
}
}
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
+ bool wallet_rpc_server::on_get_transfer_by_txid(const wallet_rpc::COMMAND_RPC_GET_TRANSFER_BY_TXID::request& req, wallet_rpc::COMMAND_RPC_GET_TRANSFER_BY_TXID::response& res, epee::json_rpc::error& er)
+ {
+ if (m_wallet.restricted())
+ {
+ er.code = WALLET_RPC_ERROR_CODE_DENIED;
+ er.message = "Command unavailable in restricted mode.";
+ return false;
+ }
+
+ crypto::hash txid;
+ cryptonote::blobdata txid_blob;
+ if(!epee::string_tools::parse_hexstr_to_binbuff(req.txid, txid_blob))
+ {
+ er.code = WALLET_RPC_ERROR_CODE_WRONG_TXID;
+ er.message = "Transaction ID has invalid format";
+ return false;
+ }
+
+ if(sizeof(txid) == txid_blob.size())
+ {
+ txid = *reinterpret_cast<const crypto::hash*>(txid_blob.data());
+ }
+ else
+ {
+ er.code = WALLET_RPC_ERROR_CODE_WRONG_TXID;
+ er.message = "Transaction ID has invalid size: " + req.txid;
+ return false;
+ }
+
+ std::list<std::pair<crypto::hash, tools::wallet2::payment_details>> payments;
+ m_wallet.get_payments(payments, 0);
+ for (std::list<std::pair<crypto::hash, tools::wallet2::payment_details>>::const_iterator i = payments.begin(); i != payments.end(); ++i) {
+ if (i->first == txid)
+ {
+ fill_transfer_entry(res.transfer, i->second.m_tx_hash, i->first, i->second);
+ return true;
+ }
+ }
+
+ std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>> payments_out;
+ m_wallet.get_payments_out(payments_out, 0);
+ for (std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>>::const_iterator i = payments_out.begin(); i != payments_out.end(); ++i) {
+ if (i->first == txid)
+ {
+ fill_transfer_entry(res.transfer, i->first, i->second);
+ return true;
+ }
+ }
+
+ std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>> upayments;
+ m_wallet.get_unconfirmed_payments_out(upayments);
+ for (std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>>::const_iterator i = upayments.begin(); i != upayments.end(); ++i) {
+ if (i->first == txid)
+ {
+ fill_transfer_entry(res.transfer, i->first, i->second);
+ return true;
+ }
+ }
+
+ m_wallet.update_pool_state();
+
+ std::list<std::pair<crypto::hash, tools::wallet2::payment_details>> pool_payments;
+ m_wallet.get_unconfirmed_payments(pool_payments);
+ for (std::list<std::pair<crypto::hash, tools::wallet2::payment_details>>::const_iterator i = pool_payments.begin(); i != pool_payments.end(); ++i) {
+ if (i->second.m_tx_hash == txid)
+ {
+ fill_transfer_entry(res.transfer, i->first, i->second);
+ return true;
+ }
+ }
+
+ er.code = WALLET_RPC_ERROR_CODE_WRONG_TXID;
+ er.message = "Transaction not found.";
+ return false;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::on_export_key_images(const wallet_rpc::COMMAND_RPC_EXPORT_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_EXPORT_KEY_IMAGES::response& res, epee::json_rpc::error& er)
{
try
diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h
index 92deec043..4ff1b267f 100644
--- a/src/wallet/wallet_rpc_server.h
+++ b/src/wallet/wallet_rpc_server.h
@@ -78,6 +78,7 @@ namespace tools
MAP_JON_RPC_WE("set_tx_notes", on_set_tx_notes, wallet_rpc::COMMAND_RPC_SET_TX_NOTES)
MAP_JON_RPC_WE("get_tx_notes", on_get_tx_notes, wallet_rpc::COMMAND_RPC_GET_TX_NOTES)
MAP_JON_RPC_WE("get_transfers", on_get_transfers, wallet_rpc::COMMAND_RPC_GET_TRANSFERS)
+ MAP_JON_RPC_WE("get_transfer_by_txid", on_get_transfer_by_txid, wallet_rpc::COMMAND_RPC_GET_TRANSFER_BY_TXID)
MAP_JON_RPC_WE("sign", on_sign, wallet_rpc::COMMAND_RPC_SIGN)
MAP_JON_RPC_WE("verify", on_verify, wallet_rpc::COMMAND_RPC_VERIFY)
MAP_JON_RPC_WE("export_key_images", on_export_key_images, wallet_rpc::COMMAND_RPC_EXPORT_KEY_IMAGES)
@@ -107,6 +108,7 @@ namespace tools
bool on_set_tx_notes(const wallet_rpc::COMMAND_RPC_SET_TX_NOTES::request& req, wallet_rpc::COMMAND_RPC_SET_TX_NOTES::response& res, epee::json_rpc::error& er);
bool on_get_tx_notes(const wallet_rpc::COMMAND_RPC_GET_TX_NOTES::request& req, wallet_rpc::COMMAND_RPC_GET_TX_NOTES::response& res, epee::json_rpc::error& er);
bool on_get_transfers(const wallet_rpc::COMMAND_RPC_GET_TRANSFERS::request& req, wallet_rpc::COMMAND_RPC_GET_TRANSFERS::response& res, epee::json_rpc::error& er);
+ bool on_get_transfer_by_txid(const wallet_rpc::COMMAND_RPC_GET_TRANSFER_BY_TXID::request& req, wallet_rpc::COMMAND_RPC_GET_TRANSFER_BY_TXID::response& res, epee::json_rpc::error& er);
bool on_sign(const wallet_rpc::COMMAND_RPC_SIGN::request& req, wallet_rpc::COMMAND_RPC_SIGN::response& res, epee::json_rpc::error& er);
bool on_verify(const wallet_rpc::COMMAND_RPC_VERIFY::request& req, wallet_rpc::COMMAND_RPC_VERIFY::response& res, epee::json_rpc::error& er);
bool on_export_key_images(const wallet_rpc::COMMAND_RPC_EXPORT_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_EXPORT_KEY_IMAGES::response& res, epee::json_rpc::error& er);
@@ -117,6 +119,12 @@ namespace tools
//json rpc v2
bool on_query_key(const wallet_rpc::COMMAND_RPC_QUERY_KEY::request& req, wallet_rpc::COMMAND_RPC_QUERY_KEY::response& res, epee::json_rpc::error& er);
+ // helpers
+ void fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, const crypto::hash &payment_id, const tools::wallet2::payment_details &pd);
+ void fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, const tools::wallet2::confirmed_transfer_details &pd);
+ void fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, const tools::wallet2::unconfirmed_transfer_details &pd);
+ void fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &payment_id, const tools::wallet2::payment_details &pd);
+
wallet2& m_wallet;
std::string rpc_login_filename;
std::atomic<bool> m_stop;
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index 50b1613f9..ea0fc685f 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -525,6 +525,31 @@ namespace wallet_rpc
};
};
+ struct transfer_entry
+ {
+ std::string txid;
+ std::string payment_id;
+ uint64_t height;
+ uint64_t timestamp;
+ uint64_t amount;
+ uint64_t fee;
+ std::string note;
+ std::list<transfer_destination> destinations;
+ std::string type;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(txid);
+ KV_SERIALIZE(payment_id);
+ KV_SERIALIZE(height);
+ KV_SERIALIZE(timestamp);
+ KV_SERIALIZE(amount);
+ KV_SERIALIZE(fee);
+ KV_SERIALIZE(note);
+ KV_SERIALIZE(destinations);
+ KV_SERIALIZE(type);
+ END_KV_SERIALIZE_MAP()
+ };
+
struct COMMAND_RPC_GET_TRANSFERS
{
struct request
@@ -551,43 +576,41 @@ namespace wallet_rpc
END_KV_SERIALIZE_MAP()
};
- struct entry
+ struct response
+ {
+ std::list<transfer_entry> in;
+ std::list<transfer_entry> out;
+ std::list<transfer_entry> pending;
+ std::list<transfer_entry> failed;
+ std::list<transfer_entry> pool;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(in);
+ KV_SERIALIZE(out);
+ KV_SERIALIZE(pending);
+ KV_SERIALIZE(failed);
+ KV_SERIALIZE(pool);
+ END_KV_SERIALIZE_MAP()
+ };
+ };
+
+ struct COMMAND_RPC_GET_TRANSFER_BY_TXID
+ {
+ struct request
{
std::string txid;
- std::string payment_id;
- uint64_t height;
- uint64_t timestamp;
- uint64_t amount;
- uint64_t fee;
- std::string note;
- std::list<transfer_destination> destinations;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(txid);
- KV_SERIALIZE(payment_id);
- KV_SERIALIZE(height);
- KV_SERIALIZE(timestamp);
- KV_SERIALIZE(amount);
- KV_SERIALIZE(fee);
- KV_SERIALIZE(note);
- KV_SERIALIZE(destinations);
END_KV_SERIALIZE_MAP()
};
struct response
{
- std::list<entry> in;
- std::list<entry> out;
- std::list<entry> pending;
- std::list<entry> failed;
- std::list<entry> pool;
+ transfer_entry transfer;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(in);
- KV_SERIALIZE(out);
- KV_SERIALIZE(pending);
- KV_SERIALIZE(failed);
- KV_SERIALIZE(pool);
+ KV_SERIALIZE(transfer);
END_KV_SERIALIZE_MAP()
};
};