diff --git a/html/js/cn_util.js b/html/js/cn_util.js index 7bea2bd..5623465 100644 --- a/html/js/cn_util.js +++ b/html/js/cn_util.js @@ -40,6 +40,11 @@ var cnUtil = (function(initConfig) { var ENCRYPTED_PAYMENT_ID_TAIL = 141; var CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = config.addressPrefix; var CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = config.integratedAddressPrefix; + if (config.testnet === true) + { + CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = config.addressPrefixTestnet; + CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = config.integratedAddressPrefixTestnet; + } var UINT64_MAX = new JSBigInt(2).pow(64); var CURRENT_TX_VERSION = 2; var OLD_TX_VERSION = 1; diff --git a/html/js/config.js b/html/js/config.js index cb7f044..84275c8 100755 --- a/html/js/config.js +++ b/html/js/config.js @@ -1,6 +1,6 @@ var config = { apiUrl: "http://127.0.0.1:1984/", - testnet: false, + testnet: true, coinUnitPlaces: 12, txMinConfirms: 10, coinSymbol: 'XMR', diff --git a/src/CurrentBlockchainStatus.cpp b/src/CurrentBlockchainStatus.cpp index afd4aa7..ed2dd14 100644 --- a/src/CurrentBlockchainStatus.cpp +++ b/src/CurrentBlockchainStatus.cpp @@ -581,6 +581,8 @@ CurrentBlockchainStatus::start_tx_search_thread(XmrAccount acc) return true; } + + bool CurrentBlockchainStatus::ping_search_thread(const string& address) { @@ -589,7 +591,7 @@ CurrentBlockchainStatus::ping_search_thread(const string& address) if (searching_threads.count(address) == 0) { // thread does not exist - cout << "does not exist" << endl; + cout << "thread for " << address << " does not exist" << endl; return false; } @@ -598,6 +600,28 @@ CurrentBlockchainStatus::ping_search_thread(const string& address) return true; } +bool +CurrentBlockchainStatus::get_xmr_address_viewkey( + const string& address_str, + account_public_address& address, + secret_key& viewkey) +{ + std::lock_guard lck (searching_threads_map_mtx); + + if (searching_threads.count(address_str) == 0) + { + // thread does not exist + cout << "thread for " << address_str << " does not exist" << endl; + return false; + } + + address = searching_threads[address_str].get()->get_xmr_address_viewkey().first; + viewkey = searching_threads[address_str].get()->get_xmr_address_viewkey().second; + + return true; +}; + + bool CurrentBlockchainStatus::set_new_searched_blk_no(const string& address, uint64_t new_value) { diff --git a/src/CurrentBlockchainStatus.h b/src/CurrentBlockchainStatus.h index a031494..da69923 100644 --- a/src/CurrentBlockchainStatus.h +++ b/src/CurrentBlockchainStatus.h @@ -141,7 +141,8 @@ struct CurrentBlockchainStatus get_payment_id_as_string(const transaction& tx); static output_data_t - get_output_key(uint64_t amount, uint64_t global_amount_index); + get_output_key(uint64_t amount, + uint64_t global_amount_index); // definitions of these function are at the end of this file // due to forward declaraions of TxSearch @@ -152,7 +153,13 @@ struct CurrentBlockchainStatus ping_search_thread(const string& address); static bool - set_new_searched_blk_no(const string& address, uint64_t new_value); + get_xmr_address_viewkey(const string& address_str, + account_public_address& address, + secret_key& viewkey); + + static bool + set_new_searched_blk_no(const string& address, + uint64_t new_value); static void clean_search_thread_map(); diff --git a/src/TxSearch.cpp b/src/TxSearch.cpp index 7ea48aa..8fc252d 100644 --- a/src/TxSearch.cpp +++ b/src/TxSearch.cpp @@ -159,7 +159,8 @@ TxSearch::search() // can filter out false positives. for (transaction& tx: blk_txs) { - + // Class that is resposnible for idenficitaction of our outputs + // and inputs in a given tx. OutputInputIdentification oi_identification {&address, &viewkey, &tx}; // FIRSt step. @@ -454,5 +455,10 @@ TxSearch::populate_known_outputs() } } +pair +TxSearch::get_xmr_address_viewkey() const +{ + return make_pair(address, viewkey); +} } \ No newline at end of file diff --git a/src/TxSearch.h b/src/TxSearch.h index 614ed98..4d5660c 100644 --- a/src/TxSearch.h +++ b/src/TxSearch.h @@ -64,7 +64,7 @@ class TxSearch shared_ptr xmr_accounts; // address and viewkey for this search thread. - cryptonote::account_public_address address; + account_public_address address; secret_key viewkey; public: @@ -91,6 +91,9 @@ public: void populate_known_outputs(); + pair + get_xmr_address_viewkey() const; + }; diff --git a/src/YourMoneroRequests.cpp b/src/YourMoneroRequests.cpp index 7c1dbfe..8019178 100644 --- a/src/YourMoneroRequests.cpp +++ b/src/YourMoneroRequests.cpp @@ -7,6 +7,7 @@ #include "YourMoneroRequests.h" #include "ssqlses.h" +#include "OutputInputIdentification.h" namespace xmreg { @@ -152,7 +153,8 @@ YourMoneroRequests::get_address_txs(const shared_ptr< Session > session, const B { "scanned_block_height", 0}, // taken from Accounts table { "start_height", 0}, // blockchain hieght when acc was created { "transaction_height", 0}, // not used. it is here to match mymonero - { "blockchain_height", 0} // current blockchain height + { "blockchain_height", 0}, // current blockchain height + { "transactions", json::array()} }; @@ -171,7 +173,8 @@ YourMoneroRequests::get_address_txs(const shared_ptr< Session > session, const B vector txs; - if (xmr_accounts->select_txs_for_account_spendability_check(acc.id, txs)) { + if (xmr_accounts->select_txs_for_account_spendability_check(acc.id, txs)) + { json j_txs = json::array(); @@ -225,11 +228,41 @@ YourMoneroRequests::get_address_txs(const shared_ptr< Session > session, const B } // if (xmr_accounts->select(xmr_address, acc)) + + // append txs found in mempool to the json returned + + account_public_address address_parsed; + secret_key viewkey_parsed; + + if (CurrentBlockchainStatus::get_xmr_address_viewkey( + xmr_address, address_parsed, viewkey_parsed)) + { + json j_mempool_tx = find_txs_in_mempool(&address_parsed, &viewkey_parsed); + + if(!j_mempool_tx.empty()) + { + uint64_t total_received_mempool {0}; + + for (json& j_tx: j_mempool_tx) + { + cout << "mempool j_tx[\"total_received\"]:" + << j_tx["total_received"] + << endl; + total_received_mempool += j_tx["total_received"].get(); + j_response["transactions"].push_back(j_tx); + } + + j_response["total_received"] = j_response["total_received"].get() + + total_received_mempool; + } + + } + string response_body = j_response.dump(); auto response_headers = make_headers({{ "Content-Length", to_string(response_body.size())}}); - session->close( OK, response_body, response_headers); + session->close(OK, response_body, response_headers); } void @@ -746,9 +779,62 @@ YourMoneroRequests::get_current_blockchain_height() } -// define static variables +json +YourMoneroRequests::find_txs_in_mempool( + const account_public_address* address, + const secret_key* viewkey) +{ + vector txs_to_check = CurrentBlockchainStatus::get_mempool_txs(); + + json j_transactions = json::array(); + + uint64_t current_height = CurrentBlockchainStatus::get_current_blockchain_height(); + + for (const transaction& tx: txs_to_check) + { + // Class that is resposnible for idenficitaction of our outputs + // and inputs in a given tx. + OutputInputIdentification oi_identification {address, viewkey, &tx}; + + // FIRSt step. to search for the incoming xmr, we use address, viewkey and + // outputs public key. + oi_identification.identify_outputs(); + + //vector amount_specific_indices; + + // if we identified some outputs as ours, + // save them into json to be returned. + if (!oi_identification.identified_outputs.empty()) + { + json j_tx; + + j_tx["id"] = 0; + j_tx["hash"] = oi_identification.tx_hash_str; + j_tx["timestamp"] = get_current_time(); + j_tx["total_received"] = oi_identification.total_received; + j_tx["total_sent"] = 0; + j_tx["unlock_time"] = 0; + j_tx["height"] = current_height; // put large value of height, + // just to indicate that we dont have + // height and that in frontend it will + // appear us unconfirmed. + j_tx["payment_id"] = ""; + j_tx["coinbase"] = false; + j_tx["mixin"] = get_mixin_no(tx) - 1; + + j_transactions.push_back(j_tx); + } + + } // for (const transaction& tx: txs_to_check) + return j_transactions; + +} + + +// define static variables bool YourMoneroRequests::show_logs = false; } + diff --git a/src/YourMoneroRequests.h b/src/YourMoneroRequests.h index c7a3632..cd64bfb 100644 --- a/src/YourMoneroRequests.h +++ b/src/YourMoneroRequests.h @@ -60,7 +60,7 @@ public: * and check mysql if address/account exist. If yes, * it returns this account. If not, it creates new one. * - * Once this complites, a thread is tarted that looks + * Once this complites, a thread is started that looks * for txs belonging to that account. * * @param session a Restbed session @@ -106,6 +106,33 @@ public: inline uint64_t get_current_blockchain_height(); + +private: + + /** + * Search for our txs in the mempool + * + * The method searches for our txs (outputs and inputs) + * in the mempool. It does basically same what TxSearch class is + * doing. The difference is that TxSearch class searches in a thread + * in a blockchain. It does not scan for tx in mempool. This is because + * TxSearch writes what it finds into database for permament storage. + * However txs in mempool are not permament. Also since we want to + * give the end user quick update on incoming/outging tx, this method + * will be executed whenever frontend wants. By default it is every + * 10 seconds. TxSearch class is timed independetly of the frontend. + * Also since we dont write here anything to the database, we + * return a json that will be appended to json produced by get_address_tx + * and similar function. The outputs here cant be spent anyway. This is + * only for end user information. The txs found here will be written + * to database later on by TxSearch thread when they will be added + * to the blockchain. + * + * @return json + */ + json + find_txs_in_mempool(const account_public_address* address, + const secret_key* viewkey); };