diff --git a/.gitmodules b/.gitmodules index 6cf0fbb..016cffe 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "external/monero-cpp"] path = external/monero-cpp - url = https://github.com/monero-ecosystem/monero-cpp.git + url = https://github.com/woodser/monero-cpp.git [submodule "external/QR-Code-generator"] path = external/QR-Code-generator url = https://github.com/nayuki/QR-Code-generator.git diff --git a/qml/pages/subpages/WalletPage.qml b/qml/pages/subpages/WalletPage.qml index ccc63ca..e726280 100644 --- a/qml/pages/subpages/WalletPage.qml +++ b/qml/pages/subpages/WalletPage.qml @@ -94,7 +94,7 @@ Page { TextField { id: balanceLockedText visible: (settingsDialog.balanceDisplay == 2) ? false : true - property double balance: !Wallet.opened ? 0.000000000000 : Wallet.balanceLocked + property double balance: !Wallet.opened || (Wallet.balanceLocked == Wallet.balanceUnlocked) ? 0.000000000000 : Wallet.balanceLocked - Wallet.balanceUnlocked text: balance.toFixed(settingsDialog.balanceAmountPrecision) font.bold: !balanceUnlockedText.visible ? true : false font.pointSize: !balanceUnlockedText.visible ? 48 : 24 diff --git a/src/core/wallet.cpp b/src/core/wallet.cpp index a45b091..cd51fdf 100644 --- a/src/core/wallet.cpp +++ b/src/core/wallet.cpp @@ -271,6 +271,7 @@ void neroshop::Wallet::transfer(const std::string& address, double amount) { //uint64_t deducted_amount = (monero_to_piconero + fee); std::string tx_hash = monero_wallet_obj->relay_tx(*sent_tx); // recipient receives notification within 5 seconds std::cout << "Tx hash: " << tx_hash << "\n"; + monero_utils::free(sent_tx); }); std::future future_result = transfer_task.get_future(); @@ -279,6 +280,51 @@ void neroshop::Wallet::transfer(const std::string& address, double amount) { worker.detach(); // join may block but detach won't//void transfer_result = future_result.get(); } //------------------------------------------------------- +void neroshop::Wallet::transfer(const std::vector>& payment_addresses) { // untested + if(!monero_wallet_obj.get()) throw std::runtime_error("monero_wallet_full is not opened"); + if(!monero_wallet_obj.get()->is_synced()) throw std::runtime_error("wallet is not synced with a daemon"); + + monero_tx_config tx_config = monero_tx_config(); + tx_config.m_account_index = 0; // withdraw funds from this account + tx_config.m_relay = false; // create transaction and relay to the network if true + + double piconero = 0.000000000001; + // Calculate the total amount owed + double total_amount = 0.000000000000; + for (const auto& address : payment_addresses) { + total_amount += address.second; + } + std::cout << "Total amount to pay: " << total_amount << " (xmr)\n"; + // Check if balance is sufficient + uint64_t total_to_piconero = total_amount / piconero; + std::cout << "Wallet balance (spendable): " << monero_wallet_obj->get_unlocked_balance() << " (picos)\n"; + std::cout << "Amount to send: " << total_to_piconero << " (picos)\n"; + if(monero_wallet_obj->get_unlocked_balance() < total_to_piconero) { + neroshop::print("Wallet balance is insufficient", 1); return; + } + // Add each destination + std::vector> destinations; // specify the recipients and their amounts + for(const auto& address : payment_addresses) { + // Check if address is valid + if(!monero_utils::is_valid_address(address.first, monero_wallet_obj->get_network_type())) { + neroshop::print(address.first + " is not a valid Monero address", 1); + continue; // skip to the next address + } + // Convert monero to piconero + uint64_t monero_to_piconero = address.second / piconero; //std::cout << neroshop::string::precision(address.second, 12) << " xmr to piconero: " << monero_to_piconero << "\n"; + destinations.push_back(std::make_shared(address.first, monero_to_piconero)); + // Print address and amount + std::cout << "Address: " << address.first << ", Amount: " << address.second << std::endl; + } + tx_config.m_destinations = destinations; + + // Create the transaction, confirm with the user, and relay to the network + std::shared_ptr created_tx = monero_wallet_obj->create_tx(tx_config); + uint64_t fee = created_tx->m_fee.get(); // "Are you sure you want to send ...?" + monero_wallet_obj->relay_tx(*created_tx); // recipient receives notification within 5 seconds + monero_utils::free(created_tx); +} +//------------------------------------------------------- std::string neroshop::Wallet::sign_message(const std::string& message, monero_message_signature_type signature_type) const { if(!monero_wallet_obj.get()) throw std::runtime_error("monero_wallet_full is not opened"); return monero_wallet_obj->sign_message(message, signature_type, 0, 0); @@ -301,12 +347,6 @@ monero::monero_subaddress neroshop::Wallet::create_subaddress(unsigned int accou } //------------------------------------------------------- //------------------------------------------------------- -void neroshop::Wallet::sweep_all(const std::string& address) { - if(!monero_wallet_obj.get()) throw std::runtime_error("monero_wallet_full is not opened"); - //std::vector< std::shared_ptr< monero_tx_wallet > > monero::monero_wallet_full::sweep_dust ( bool relay = false ) -} // sends entire balance, including dust to an address // "sweep_all
" -//------------------------------------------------------- -//------------------------------------------------------- // NOTE: It is IMPOSSIBLE to change the network type of a pre-existing monero wallet, but it can be set before its creation void neroshop::Wallet::set_network_type(monero::monero_network_type network_type) { if(get_network_type() == network_type) return; diff --git a/src/core/wallet.hpp b/src/core/wallet.hpp index f710cf5..c78aac7 100644 --- a/src/core/wallet.hpp +++ b/src/core/wallet.hpp @@ -56,7 +56,8 @@ public: monero::monero_subaddress create_subaddress(unsigned int account_idx, const std::string & label = "") const; // generates a new subaddress from main account // monero addresses start with 4 or 8 void transfer(const std::string& address, double amount); // "transfer" will be used for sending refunds - void sweep_all(const std::string& address); // sends entire balance, including dust to an address // "sweep_all
" + void transfer(const std::vector>& payment_addresses); + std::string address_new() const; // this function has been replaced by create_subaddress() and is deprecated. Will be removed soon unsigned int address_book_add(const std::string& address, std::string description = ""); // "address_book add
" void address_book_delete(unsigned int index); // "address_book delete 0" diff --git a/src/gui/wallet_controller.hpp b/src/gui/wallet_controller.hpp index f4103d1..6771653 100644 --- a/src/gui/wallet_controller.hpp +++ b/src/gui/wallet_controller.hpp @@ -25,15 +25,7 @@ class WalletController : public QObject, public monero_wallet_listener Q_PROPERTY(double balanceUnlocked READ getBalanceUnlocked NOTIFY balanceChanged); Q_PROPERTY(QVariantList transfers READ getTransfers NOTIFY transfersChanged); //Q_PROPERTY( READ NOTIFY) -public: - // I don't know how to use or compare enums in QML. It never works, but oh well :| - enum KeyfileStatus { - KeyfileStatus_Ok = 0, - KeyfileStatus_Wrong_Password, - KeyfileStatus_No_Matching_Passwords, - KeyfileStatus_Exists, - }; - Q_ENUM(KeyfileStatus) +public: // functions (for use in QML) Q_INVOKABLE int createRandomWallet(const QString& password, const QString& confirm_pwd, const QString& path); Q_INVOKABLE int restoreFromSeed(const QString& seed); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d3c1b08..c7fcb43 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -17,7 +17,7 @@ set(neroshop_database_src set(neroshop_network_src ${NEROSHOP_CORE_SRC_DIR}/network/i2p.cpp - ${NEROSHOP_CORE_SRC_DIR}/network/tor.cpp + #[[${NEROSHOP_CORE_SRC_DIR}/network/tor.cpp]] ) set(neroshop_price_src @@ -429,7 +429,7 @@ set(lua_src liblua.a) # network_test set(test_network "network_test") add_executable(${test_network} network_test.cpp ${neroshop_srcs}) -target_link_libraries(${test_network} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${raft_src} ${libuv_src} ${curl_src} ${monero_src} ${lua_src}) +target_link_libraries(${test_network} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${raft_src} ${curl_src} ${monero_src} ${lua_src}) # network_uv test #[[set(test_network_uv "network_uv_test") add_executable(${test_network_uv} network_test_uv.cpp ${neroshop_srcs}) @@ -437,30 +437,30 @@ target_link_libraries(${test_network_uv} ${monero_cpp_src} ${sqlite_src} ${qr_co # utility test set(test_utility "utility_test") add_executable(${test_utility} utility_test.cpp ${neroshop_srcs}) -target_link_libraries(${test_utility} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${raft_src} ${libuv_src} ${curl_src} ${monero_src} ${lua_src}) +target_link_libraries(${test_utility} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${raft_src} ${curl_src} ${monero_src} ${lua_src}) # auth_test set(test_auth "auth_test") add_executable(${test_auth} auth_test.cpp ${neroshop_srcs}) -target_link_libraries(${test_auth} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${raft_src} ${libuv_src} ${curl_src} ${monero_src} ${lua_src}) +target_link_libraries(${test_auth} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${raft_src} ${curl_src} ${monero_src} ${lua_src}) # uuid_test set(test_uuid "uuid_test") add_executable(${test_uuid} uuid_test.cpp) # qr_code_test set(test_qr_code "qr_test") add_executable(${test_qr_code} qr_test.cpp ${neroshop_srcs}) -target_link_libraries(${test_qr_code} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${raft_src} ${libuv_src} ${curl_src} ${monero_src} ${lua_src}) +target_link_libraries(${test_qr_code} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${raft_src} ${curl_src} ${monero_src} ${lua_src}) # encryption_test set(test_crypt "encryption_test") add_executable(${test_crypt} encryption_test.cpp ${neroshop_srcs}) -target_link_libraries(${test_crypt} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${raft_src} ${libuv_src} ${curl_src} ${monero_src} ${lua_src}) +target_link_libraries(${test_crypt} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${raft_src} ${curl_src} ${monero_src} ${lua_src}) # signing_test set(test_sign "signing_test") add_executable(${test_sign} signing_test.cpp ${neroshop_srcs}) -target_link_libraries(${test_sign} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${raft_src} ${libuv_src} ${curl_src} ${monero_src} ${lua_src}) +target_link_libraries(${test_sign} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${raft_src} ${curl_src} ${monero_src} ${lua_src}) # sign_verify_test set(test_sign_verify "sign_verify_test") add_executable(${test_sign_verify} sign_verify_test.cpp ${neroshop_srcs}) -target_link_libraries(${test_sign_verify} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${raft_src} ${libuv_src} ${curl_src} ${monero_src} ${lua_src}) +target_link_libraries(${test_sign_verify} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${raft_src} ${curl_src} ${monero_src} ${lua_src}) # Qt gui_test set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) @@ -471,17 +471,21 @@ add_executable(${test_gui_qt} main_window.ui main_window.cpp gui_qt_test.cpp ${n #[[target_]] include_directories(#[[${test_gui_qt} ]] /usr/include/x86_64-linux-gnu/qt5/ /usr/include/x86_64-linux-gnu/qt5/QtWidgets/) #target_compile_definitions(${test_gui_qt} PRIVATE ) -target_link_libraries(${test_gui_qt} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${raft_src} ${libuv_src} ${curl_src} ${monero_src} ${lua_src}) +target_link_libraries(${test_gui_qt} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${raft_src} ${curl_src} ${monero_src} ${lua_src}) # escrow_test set(test_escrow "escrow_test") add_executable(${test_escrow} escrow.cpp ${neroshop_srcs}) -target_link_libraries(${test_escrow} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${raft_src} ${libuv_src} ${curl_src} ${monero_src} ${lua_src}) +target_link_libraries(${test_escrow} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${raft_src} ${curl_src} ${monero_src} ${lua_src}) + +set(test_wallet "wallet_test") +add_executable(${test_wallet} wallet_test.cpp ${neroshop_srcs}) +target_link_libraries(${test_wallet} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${raft_src} ${curl_src} ${monero_src} ${lua_src}) #[[ set(test_ "") add_executable(${test_} .cpp ${neroshop_srcs}) -target_link_libraries(${test_} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${raft_src} ${libuv_src} ${curl_src} ${monero_src} ${lua_src}) +target_link_libraries(${test_} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${raft_src} ${curl_src} ${monero_src} ${lua_src}) ]] ###################################### @@ -501,8 +505,11 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") target_link_libraries(${test_auth} ${posix_src}) target_link_libraries(${test_qr_code} ${posix_src}) target_link_libraries(${test_crypt} ${posix_src}) + target_link_libraries(${test_sign} ${posix_src}) target_link_libraries(${test_sign_verify} ${posix_src}) target_link_libraries(${test_gui_qt} ${posix_src}) + target_link_libraries(${test_escrow} ${posix_src}) + target_link_libraries(${test_wallet} ${posix_src}) #target_link_libraries(${test_} ${posix_src}) find_package(X11 REQUIRED) if(X11_FOUND) diff --git a/tests/wallet_test.cpp b/tests/wallet_test.cpp new file mode 100644 index 0000000..d5c7c93 --- /dev/null +++ b/tests/wallet_test.cpp @@ -0,0 +1,24 @@ +#include +#include "../src/core/wallet.hpp" + +int main() { + + neroshop::Wallet *wallet = new neroshop::Wallet(); + wallet->create_random("", "", "random_wallet"); + + // This isn't working?? + wallet->daemon_connect_remote("node2.monerodevs.org", "38089"); + + // Your vector of payment addresses + std::vector> payment_addresses = { + {"Address1", 1.0}, + {"Address2", 0.5}, + {"Address3", 0.25} + }; + + sleep(900); // wait for node to finish syncing? + + wallet->transfer(payment_addresses); + + return 0; +}