From f83f3cbd9647b679e5c9460970b99bd2e9141858 Mon Sep 17 00:00:00 2001 From: Ilya Kitaev Date: Wed, 20 Apr 2016 13:01:00 +0300 Subject: api implementation splitted over separate files --- src/wallet/api/wallet.cpp | 411 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 411 insertions(+) create mode 100644 src/wallet/api/wallet.cpp (limited to 'src/wallet/api/wallet.cpp') diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp new file mode 100644 index 000000000..e42f04cf7 --- /dev/null +++ b/src/wallet/api/wallet.cpp @@ -0,0 +1,411 @@ +// Copyright (c) 2014-2016, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + + +#include "wallet.h" +#include "pending_transaction.h" +#include "common_defines.h" + +#include "mnemonics/electrum-words.h" +#include + +using namespace std; +using namespace cryptonote; + +namespace Bitmonero { + +namespace { + // copy-pasted from simplewallet + static const size_t DEFAULT_MIX = 4; +} + +Wallet::~Wallet() {} + +string Wallet::displayAmount(uint64_t amount) +{ + return cryptonote::print_money(amount); +} + +///////////////////////// WalletImpl implementation //////////////////////// +WalletImpl::WalletImpl(bool testnet) + :m_wallet(nullptr), m_status(Wallet::Status_Ok) +{ + m_wallet = new tools::wallet2(testnet); +} + +WalletImpl::~WalletImpl() +{ + delete m_wallet; +} + +bool WalletImpl::create(const std::string &path, const std::string &password, const std::string &language) +{ + + clearStatus(); + + bool keys_file_exists; + bool wallet_file_exists; + tools::wallet2::wallet_exists(path, keys_file_exists, wallet_file_exists); + // TODO: figure out how to setup logger; + LOG_PRINT_L3("wallet_path: " << path << ""); + LOG_PRINT_L3("keys_file_exists: " << std::boolalpha << keys_file_exists << std::noboolalpha + << " wallet_file_exists: " << std::boolalpha << wallet_file_exists << std::noboolalpha); + + + // add logic to error out if new wallet requested but named wallet file exists + if (keys_file_exists || wallet_file_exists) { + m_errorString = "attempting to generate or restore wallet, but specified file(s) exist. Exiting to not risk overwriting."; + LOG_ERROR(m_errorString); + m_status = Status_Error; + return false; + } + // TODO: validate language + m_wallet->set_seed_language(language); + crypto::secret_key recovery_val, secret_key; + try { + recovery_val = m_wallet->generate(path, password, secret_key, false, false); + m_password = password; + m_status = Status_Ok; + } catch (const std::exception &e) { + LOG_ERROR("Error creating wallet: " << e.what()); + m_status = Status_Error; + m_errorString = e.what(); + return false; + } + + return true; +} + +bool WalletImpl::open(const std::string &path, const std::string &password) +{ + clearStatus(); + try { + // TODO: handle "deprecated" + m_wallet->load(path, password); + + m_password = password; + } catch (const std::exception &e) { + LOG_ERROR("Error opening wallet: " << e.what()); + m_status = Status_Error; + m_errorString = e.what(); + } + return m_status == Status_Ok; +} + +bool WalletImpl::recover(const std::string &path, const std::string &seed) +{ + clearStatus(); + m_errorString.clear(); + if (seed.empty()) { + m_errorString = "Electrum seed is empty"; + LOG_ERROR(m_errorString); + m_status = Status_Error; + return false; + } + + crypto::secret_key recovery_key; + std::string old_language; + if (!crypto::ElectrumWords::words_to_bytes(seed, recovery_key, old_language)) { + m_errorString = "Electrum-style word list failed verification"; + m_status = Status_Error; + return false; + } + + try { + m_wallet->set_seed_language(old_language); + m_wallet->generate(path, "", recovery_key, true, false); + // TODO: wallet->init(daemon_address); + } catch (const std::exception &e) { + m_status = Status_Error; + m_errorString = e.what(); + } + return m_status == Status_Ok; +} + +bool WalletImpl::close() +{ + clearStatus(); + bool result = false; + try { + m_wallet->store(); + m_wallet->stop(); + result = true; + } catch (const std::exception &e) { + m_status = Status_Error; + m_errorString = e.what(); + LOG_ERROR("Error closing wallet: " << e.what()); + } + return result; +} + +std::string WalletImpl::seed() const +{ + std::string seed; + if (m_wallet) + m_wallet->get_seed(seed); + return seed; +} + +std::string WalletImpl::getSeedLanguage() const +{ + return m_wallet->get_seed_language(); +} + +void WalletImpl::setSeedLanguage(const std::string &arg) +{ + m_wallet->set_seed_language(arg); +} + +int WalletImpl::status() const +{ + return m_status; +} + +std::string WalletImpl::errorString() const +{ + return m_errorString; +} + +bool WalletImpl::setPassword(const std::string &password) +{ + clearStatus(); + try { + m_wallet->rewrite(m_wallet->get_wallet_file(), password); + m_password = password; + } catch (const std::exception &e) { + m_status = Status_Error; + m_errorString = e.what(); + } + return m_status == Status_Ok; +} + +std::string WalletImpl::address() const +{ + return m_wallet->get_account().get_public_address_str(m_wallet->testnet()); +} + +bool WalletImpl::store(const std::string &path) +{ + clearStatus(); + try { + if (path.empty()) { + m_wallet->store(); + } else { + m_wallet->store_to(path, m_password); + } + } catch (const std::exception &e) { + LOG_ERROR("Error storing wallet: " << e.what()); + m_status = Status_Error; + m_errorString = e.what(); + } + + return m_status == Status_Ok; +} + +bool WalletImpl::init(const std::string &daemon_address, uint64_t upper_transaction_size_limit) +{ + clearStatus(); + try { + m_wallet->init(daemon_address, upper_transaction_size_limit); + } catch (const std::exception &e) { + LOG_ERROR("Error initializing wallet: " << e.what()); + m_status = Status_Error; + m_errorString = e.what(); + } + + return m_status == Status_Ok; +} + +uint64_t WalletImpl::balance() const +{ + return m_wallet->balance(); +} + +uint64_t WalletImpl::unlockedBalance() const +{ + return m_wallet->unlocked_balance(); +} + + +bool WalletImpl::refresh() +{ + clearStatus(); + try { + m_wallet->refresh(); + } catch (const std::exception &e) { + m_status = Status_Error; + m_errorString = e.what(); + } + return m_status == Status_Ok; +} + +// TODO: +// 1 - properly handle payment id (add another menthod with explicit 'payment_id' param) +// 2 - check / design how "Transaction" can be single interface +// (instead of few different data structures within wallet2 implementation: +// - pending_tx; +// - transfer_details; +// - payment_details; +// - unconfirmed_transfer_details; +// - confirmed_transfer_details) +PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, uint64_t amount) +{ + clearStatus(); + vector dsts; + cryptonote::tx_destination_entry de; + bool has_payment_id; + crypto::hash8 new_payment_id; + + // TODO: (https://bitcointalk.org/index.php?topic=753252.msg9985441#msg9985441) + size_t fake_outs_count = m_wallet->default_mixin(); + if (fake_outs_count == 0) + fake_outs_count = DEFAULT_MIX; + + TransactionImpl * transaction = new TransactionImpl(this); + + do { + + if(!cryptonote::get_account_integrated_address_from_str(de.addr, has_payment_id, new_payment_id, m_wallet->testnet(), dst_addr)) { + // TODO: copy-paste 'if treating as an address fails, try as url' from simplewallet.cpp:1982 + m_status = Status_Error; + m_errorString = "Invalid destination address"; + break; + } + + de.amount = amount; + if (de.amount <= 0) { + m_status = Status_Error; + m_errorString = "Invalid amount"; + break; + } + + dsts.push_back(de); + //std::vector ptx_vector; + std::vector extra; + + + try { + transaction->m_pending_tx = m_wallet->create_transactions(dsts, fake_outs_count, 0 /* unlock_time */, 0 /* unused fee arg*/, extra); + + } catch (const tools::error::daemon_busy&) { + // TODO: make it translatable with "tr"? + m_errorString = tr("daemon is busy. Please try again later."); + m_status = Status_Error; + } catch (const tools::error::no_connection_to_daemon&) { + m_errorString = tr("no connection to daemon. Please make sure daemon is running."); + m_status = Status_Error; + } catch (const tools::error::wallet_rpc_error& e) { + m_errorString = tr("RPC error: ") + e.to_string(); + m_status = Status_Error; + } catch (const tools::error::get_random_outs_error&) { + m_errorString = tr("failed to get random outputs to mix"); + m_status = Status_Error; + + } catch (const tools::error::not_enough_money& e) { + m_status = Status_Error; + std::ostringstream writer(m_errorString); + + writer << boost::format(tr("not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee)")) % + print_money(e.available()) % + print_money(e.tx_amount() + e.fee()) % + print_money(e.tx_amount()) % + print_money(e.fee()); + + } catch (const tools::error::not_enough_outs_to_mix& e) { + std::ostringstream writer(m_errorString); + writer << tr("not enough outputs for specified mixin_count") << " = " << e.mixin_count() << ":"; + for (const cryptonote::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& outs_for_amount : e.scanty_outs()) { + writer << "\n" << tr("output amount") << " = " << print_money(outs_for_amount.amount) << ", " << tr("found outputs to mix") << " = " << outs_for_amount.outs.size(); + } + m_status = Status_Error; + } catch (const tools::error::tx_not_constructed&) { + m_errorString = tr("transaction was not constructed"); + m_status = Status_Error; + } catch (const tools::error::tx_rejected& e) { + std::ostringstream writer(m_errorString); + writer << (boost::format(tr("transaction %s was rejected by daemon with status: ")) % get_transaction_hash(e.tx())) << e.status(); + m_status = Status_Error; + } catch (const tools::error::tx_sum_overflow& e) { + m_errorString = e.what(); + m_status = Status_Error; + } catch (const tools::error::zero_destination&) { + m_errorString = tr("one of destinations is zero"); + m_status = Status_Error; + } catch (const tools::error::tx_too_big& e) { + m_errorString = tr("failed to find a suitable way to split transactions"); + m_status = Status_Error; + } catch (const tools::error::transfer_error& e) { + m_errorString = string(tr("unknown transfer error: ")) + e.what(); + m_status = Status_Error; + } catch (const tools::error::wallet_internal_error& e) { + m_errorString = string(tr("internal error: ")) + e.what(); + m_status = Status_Error; + } catch (const std::exception& e) { + m_errorString = string(tr("unexpected error: ")) + e.what(); + m_status = Status_Error; + } catch (...) { + m_errorString = tr("unknown error"); + m_status = Status_Error; + } + } while (false); + + transaction->m_status = m_status; + transaction->m_errorString = m_errorString; + return transaction; +} + +void WalletImpl::disposeTransaction(PendingTransaction *t) +{ + delete t; +} + +TransactionHistory *WalletImpl::history() const +{ + return nullptr; +} + +bool WalletImpl::connectToDaemon() +{ + bool result = m_wallet->check_connection(); + m_status = result ? Status_Ok : Status_Error; + if (!result) { + m_errorString = "Error connecting to daemon at " + m_wallet->get_daemon_address(); + } + return result; +} + +void WalletImpl::clearStatus() +{ + m_status = Status_Ok; + m_errorString.clear(); +} + + +} // namespace -- cgit v1.2.3 From b6aaf53a6074e8e7181da5c3275e9fef56bf20da Mon Sep 17 00:00:00 2001 From: Ilya Kitaev Date: Wed, 20 Apr 2016 13:17:27 +0300 Subject: transaction history api in progress --- src/wallet/api/pending_transaction.cpp | 16 +++++++------- src/wallet/api/transaction_history.cpp | 39 ++++++++++++++++++++++++++++++++++ src/wallet/api/transaction_history.h | 17 ++++++++++++--- src/wallet/api/wallet.cpp | 2 +- src/wallet/api/wallet.h | 7 ++++-- src/wallet/wallet2_api.h | 3 +-- 6 files changed, 68 insertions(+), 16 deletions(-) (limited to 'src/wallet/api/wallet.cpp') diff --git a/src/wallet/api/pending_transaction.cpp b/src/wallet/api/pending_transaction.cpp index e9791ec35..db40851b4 100644 --- a/src/wallet/api/pending_transaction.cpp +++ b/src/wallet/api/pending_transaction.cpp @@ -48,28 +48,28 @@ namespace Bitmonero { PendingTransaction::~PendingTransaction() {} -TransactionImpl::TransactionImpl(WalletImpl *wallet) +PendingTransactionImpl::PendingTransactionImpl(WalletImpl *wallet) : m_wallet(wallet) { } -TransactionImpl::~TransactionImpl() +PendingTransactionImpl::~PendingTransactionImpl() { } -int TransactionImpl::status() const +int PendingTransactionImpl::status() const { return m_status; } -string TransactionImpl::errorString() const +string PendingTransactionImpl::errorString() const { return m_errorString; } -bool TransactionImpl::commit() +bool PendingTransactionImpl::commit() { LOG_PRINT_L0("m_pending_tx size: " << m_pending_tx.size()); @@ -105,7 +105,7 @@ bool TransactionImpl::commit() return m_status == Status_Ok; } -uint64_t TransactionImpl::amount() const +uint64_t PendingTransactionImpl::amount() const { uint64_t result = 0; for (const auto &ptx : m_pending_tx) { @@ -116,7 +116,7 @@ uint64_t TransactionImpl::amount() const return result; } -uint64_t TransactionImpl::dust() const +uint64_t PendingTransactionImpl::dust() const { uint32_t result = 0; for (const auto & ptx : m_pending_tx) { @@ -125,7 +125,7 @@ uint64_t TransactionImpl::dust() const return result; } -uint64_t TransactionImpl::fee() const +uint64_t PendingTransactionImpl::fee() const { uint32_t result = 0; for (const auto ptx : m_pending_tx) { diff --git a/src/wallet/api/transaction_history.cpp b/src/wallet/api/transaction_history.cpp index f1aba14cb..6cc5a961c 100644 --- a/src/wallet/api/transaction_history.cpp +++ b/src/wallet/api/transaction_history.cpp @@ -30,4 +30,43 @@ #include "transaction_history.h" +#include +namespace Bitmonero { + +TransactionHistoryImpl::TransactionHistoryImpl(WalletImpl *wallet) +{ + +} + +TransactionHistoryImpl::~TransactionHistoryImpl() +{ + +} + +int TransactionHistoryImpl::count() const +{ + return 0; +} + +TransactionInfo *TransactionHistoryImpl::transaction(const std::string &id) const +{ + return nullptr; +} + +std::vector TransactionHistoryImpl::getAll() const +{ + return std::vector(); +} + +void TransactionHistoryImpl::refresh() +{ + +} + +TransactionInfo *TransactionHistoryImpl::transaction(int index) const +{ + return nullptr; +} + +} diff --git a/src/wallet/api/transaction_history.h b/src/wallet/api/transaction_history.h index cab0e0dbc..1ff729b54 100644 --- a/src/wallet/api/transaction_history.h +++ b/src/wallet/api/transaction_history.h @@ -32,12 +32,23 @@ namespace Bitmonero { +class TransactionInfo; +class WalletImpl; + class TransactionHistoryImpl : public TransactionHistory { +public: + TransactionHistoryImpl(WalletImpl * wallet); + ~TransactionHistoryImpl(); virtual int count() const; - virtual TransactionInfo * transaction(int index) const = 0; - virtual TransactionInfo * transaction(const std::string &id) const = 0; - virtual std::vector getAll() const = 0; + virtual TransactionInfo * transaction(int index) const; + virtual TransactionInfo * transaction(const std::string &id) const; + virtual std::vector getAll() const; + virtual void refresh(); + +private: + std::vector m_history; + WalletImpl *m_wallet; }; } diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index e42f04cf7..a665fff95 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -288,7 +288,7 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, uint64 if (fake_outs_count == 0) fake_outs_count = DEFAULT_MIX; - TransactionImpl * transaction = new TransactionImpl(this); + PendingTransactionImpl * transaction = new PendingTransactionImpl(this); do { diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index 35db38f67..6a654b13e 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -38,7 +38,8 @@ namespace Bitmonero { - +class TransactionHistoryImpl; +class PendingTransactionImpl; class WalletImpl : public Wallet { @@ -72,7 +73,9 @@ private: void clearStatus(); private: - friend class TransactionImpl; + friend class PendingTransactionImpl; + friend class TransactionHistoryImpl; + tools::wallet2 * m_wallet; int m_status; std::string m_errorString; diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h index cb0211c4a..37d9ee86b 100644 --- a/src/wallet/wallet2_api.h +++ b/src/wallet/wallet2_api.h @@ -63,8 +63,7 @@ struct TransactionHistory virtual TransactionInfo * transaction(int index) const = 0; virtual TransactionInfo * transaction(const std::string &id) const = 0; virtual std::vector getAll() const = 0; - // TODO: - // refresh(); + virtual void refresh() = 0; }; -- cgit v1.2.3 From 02c9df5de247d6f8fb95e1b9272cef2b37be10f8 Mon Sep 17 00:00:00 2001 From: Ilya Kitaev Date: Fri, 22 Apr 2016 13:21:08 +0300 Subject: Wallet API : transaction history in progress --- src/wallet/api/transaction_history.cpp | 39 ++++++++++++++++++++++++++++------ src/wallet/api/transaction_history.h | 2 ++ src/wallet/api/transaction_info.cpp | 11 +++++++++- src/wallet/api/transaction_info.h | 10 ++++++--- src/wallet/api/wallet.cpp | 5 ++++- src/wallet/api/wallet.h | 1 + src/wallet/wallet2_api.h | 29 +++++++++++++------------ tests/libwallet_api_tests/main.cpp | 28 ++++++++++++++++++++++++ 8 files changed, 100 insertions(+), 25 deletions(-) (limited to 'src/wallet/api/wallet.cpp') diff --git a/src/wallet/api/transaction_history.cpp b/src/wallet/api/transaction_history.cpp index 3ebcc041e..185cd164f 100644 --- a/src/wallet/api/transaction_history.cpp +++ b/src/wallet/api/transaction_history.cpp @@ -35,14 +35,20 @@ #include "crypto/hash.h" #include "wallet/wallet2.h" -#include "contrib/epee/include/string_tools.h" + #include #include +using namespace epee; + namespace Bitmonero { +TransactionHistory::~TransactionHistory() {} + + TransactionHistoryImpl::TransactionHistoryImpl(WalletImpl *wallet) + : m_wallet(wallet) { } @@ -54,7 +60,7 @@ TransactionHistoryImpl::~TransactionHistoryImpl() int TransactionHistoryImpl::count() const { - return 0; + return m_history.size(); } TransactionInfo *TransactionHistoryImpl::transaction(const std::string &id) const @@ -64,7 +70,7 @@ TransactionInfo *TransactionHistoryImpl::transaction(const std::string &id) cons std::vector TransactionHistoryImpl::getAll() const { - return std::vector(); + return m_history; } void TransactionHistoryImpl::refresh() @@ -73,9 +79,18 @@ void TransactionHistoryImpl::refresh() uint64_t min_height = 0; uint64_t max_height = (uint64_t)-1; - // TODO: delete old transactions; + // delete old transactions; + for (auto t : m_history) + delete t; std::list> payments; + + // transactions are stored in wallet2: + // - confirmed_transfer_details - out transfers + // - unconfirmed_transfer_details - pending out transfers + // - payment_details - input transfers + + // payments are "input transactions"; m_wallet->m_wallet->get_payments(payments, min_height, max_height); for (std::list>::const_iterator i = payments.begin(); i != payments.end(); ++i) { const tools::wallet2::payment_details &pd = i->second; @@ -83,9 +98,19 @@ void TransactionHistoryImpl::refresh() if (payment_id.substr(16).find_first_not_of('0') == std::string::npos) payment_id = payment_id.substr(0,16); // TODO - TransactionInfo * ti = new TransactionInfo(); - - //output.insert(std::make_pair(pd.m_block_height, std::make_pair(true, (boost::format("%20.20s %s %s %s") % print_money(pd.m_amount) % string_tools::pod_to_hex(pd.m_tx_hash) % payment_id % "-").str()))); + TransactionInfoImpl * ti = new TransactionInfoImpl(); + ti->m_paymentid = payment_id; + ti->m_amount = pd.m_amount; + ti->m_direction = TransactionInfo::Direction_In; + ti->m_hash = string_tools::pod_to_hex(pd.m_tx_hash); + // TODO: + // ti->m_timestamp = pd.m_timestamp; + m_history.push_back(ti); + + /* output.insert(std::make_pair(pd.m_block_height, std::make_pair(true, (boost::format("%20.20s %s %s %s") + % print_money(pd.m_amount) + % string_tools::pod_to_hex(pd.m_tx_hash) + % payment_id % "-").str())));*/ } } diff --git a/src/wallet/api/transaction_history.h b/src/wallet/api/transaction_history.h index 1ff729b54..171fd2210 100644 --- a/src/wallet/api/transaction_history.h +++ b/src/wallet/api/transaction_history.h @@ -47,6 +47,8 @@ public: virtual void refresh(); private: + + // TransactionHistory is responsible of memory management std::vector m_history; WalletImpl *m_wallet; }; diff --git a/src/wallet/api/transaction_info.cpp b/src/wallet/api/transaction_info.cpp index 8de4e555f..c28c52355 100644 --- a/src/wallet/api/transaction_info.cpp +++ b/src/wallet/api/transaction_info.cpp @@ -35,7 +35,16 @@ using namespace std; namespace Bitmonero { +TransactionInfo::~TransactionInfo() {} + TransactionInfoImpl::TransactionInfoImpl() + : m_direction(Direction_Out) + , m_hold(false) + , m_failed(false) + , m_amount(0) + , m_fee(0) + , m_blockheight(0) + , m_timestamp(0) { } @@ -71,7 +80,7 @@ uint64_t TransactionInfoImpl::fee() const return 0; } -string TransactionInfoImpl::address() const +string TransactionInfoImpl::hash() const { return ""; } diff --git a/src/wallet/api/transaction_info.h b/src/wallet/api/transaction_info.h index 3aae19a64..945b0d9ed 100644 --- a/src/wallet/api/transaction_info.h +++ b/src/wallet/api/transaction_info.h @@ -41,12 +41,16 @@ class TransactionInfoImpl : public TransactionInfo public: TransactionInfoImpl(); ~TransactionInfoImpl(); + //! in/out virtual int direction() const; + //! true if hold virtual bool isHold() const; virtual bool isFailed() const; virtual uint64_t amount() const; + //! always 0 for incoming txes virtual uint64_t fee() const; - virtual std::string address() const; + + virtual std::string hash() const; virtual std::time_t timestamp() const; virtual std::string paymentId() const; @@ -56,8 +60,8 @@ private: bool m_failed; uint64_t m_amount; uint64_t m_fee; - uint64_t b_blockheight; - std::string m_address; + uint64_t m_blockheight; + std::string m_hash; std::time_t m_timestamp; std::string m_paymentid; diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index a665fff95..5f32908de 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -31,6 +31,7 @@ #include "wallet.h" #include "pending_transaction.h" +#include "transaction_history.h" #include "common_defines.h" #include "mnemonics/electrum-words.h" @@ -58,10 +59,12 @@ WalletImpl::WalletImpl(bool testnet) :m_wallet(nullptr), m_status(Wallet::Status_Ok) { m_wallet = new tools::wallet2(testnet); + m_history = new TransactionHistoryImpl(this); } WalletImpl::~WalletImpl() { + delete m_history; delete m_wallet; } @@ -388,7 +391,7 @@ void WalletImpl::disposeTransaction(PendingTransaction *t) TransactionHistory *WalletImpl::history() const { - return nullptr; + return m_history; } bool WalletImpl::connectToDaemon() diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index 6a654b13e..3eaaec59e 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -80,6 +80,7 @@ private: int m_status; std::string m_errorString; std::string m_password; + TransactionHistoryImpl * m_history; }; diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h index 37d9ee86b..c4843d33f 100644 --- a/src/wallet/wallet2_api.h +++ b/src/wallet/wallet2_api.h @@ -56,17 +56,6 @@ struct PendingTransaction virtual uint64_t fee() const = 0; }; -struct TransactionInfo; -struct TransactionHistory -{ - virtual int count() const; - virtual TransactionInfo * transaction(int index) const = 0; - virtual TransactionInfo * transaction(const std::string &id) const = 0; - virtual std::vector getAll() const = 0; - virtual void refresh() = 0; -}; - - /** * @brief The TransactionInfo - interface for displaying transaction information */ @@ -76,16 +65,30 @@ struct TransactionInfo Direction_In, Direction_Out }; - + virtual ~TransactionInfo() = 0; virtual int direction() const = 0; virtual bool isHold() const = 0; virtual bool isFailed() const = 0; virtual uint64_t amount() const = 0; virtual uint64_t fee() const = 0; - virtual std::string address() const = 0; + virtual std::string hash() const = 0; virtual std::time_t timestamp() const = 0; virtual std::string paymentId() const = 0; }; +/** + * @brief The TransactionHistory - interface for displaying transaction history + */ +struct TransactionHistory +{ + virtual ~TransactionHistory() = 0; + virtual int count() const = 0; + virtual TransactionInfo * transaction(int index) const = 0; + virtual TransactionInfo * transaction(const std::string &id) const = 0; + virtual std::vector getAll() const = 0; + virtual void refresh() = 0; +}; + + /** * @brief Interface for wallet operations. diff --git a/tests/libwallet_api_tests/main.cpp b/tests/libwallet_api_tests/main.cpp index dee874cd6..6921e6c3a 100644 --- a/tests/libwallet_api_tests/main.cpp +++ b/tests/libwallet_api_tests/main.cpp @@ -29,7 +29,10 @@ // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers #include "gtest/gtest.h" + #include "wallet/wallet2_api.h" +#include "cryptonote_core/cryptonote_format_utils.h" + #include #include @@ -284,6 +287,31 @@ TEST_F(WalletManagerTest, WalletTransaction) ASSERT_TRUE(wmgr->closeWallet(wallet1)); } +TEST_F(WalletManagerTest, WalletHistory) +{ + Bitmonero::Wallet * wallet1 = wmgr->openWallet(TESTNET_WALLET_NAME, TESTNET_WALLET_PASS, true); + // make sure testnet daemon is running + ASSERT_TRUE(wallet1->init(TESTNET_DAEMON_ADDRESS, 0)); + ASSERT_TRUE(wallet1->refresh()); + Bitmonero::TransactionHistory * history = wallet1->history(); + history->refresh(); + ASSERT_TRUE(history->count() > 0); + auto transaction_print = [=] (Bitmonero::TransactionInfo * t) { + std::cout << "d: " + << (t->direction() == Bitmonero::TransactionInfo::Direction_In ? "in" : "out") + << ", a: " << t->amount() + << ", h: " << t->hash() + << std::endl; + }; + + for (auto t: history->getAll()) { + ASSERT_TRUE(t != nullptr); + transaction_print(t); + } + + +} + int main(int argc, char** argv) -- cgit v1.2.3 From 566166aafd29bbca1f4916d4383752945892eb20 Mon Sep 17 00:00:00 2001 From: Ilya Kitaev Date: Tue, 26 Apr 2016 13:46:20 +0300 Subject: merged with upstream --- src/wallet/CMakeLists.txt | 3 +- src/wallet/api/utils.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++++++ src/wallet/api/wallet.cpp | 19 ++++++++++-- src/wallet/api/wallet.h | 3 ++ src/wallet/wallet2_api.h | 5 +++ 5 files changed, 106 insertions(+), 3 deletions(-) create mode 100644 src/wallet/api/utils.cpp (limited to 'src/wallet/api/wallet.cpp') diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt index 33af4f30d..49f936f5c 100644 --- a/src/wallet/CMakeLists.txt +++ b/src/wallet/CMakeLists.txt @@ -36,7 +36,8 @@ set(wallet_sources api/wallet_manager.cpp api/transaction_info.cpp api/transaction_history.cpp - api/pending_transaction.cpp) + api/pending_transaction.cpp + api/utils.cpp) set(wallet_headers) diff --git a/src/wallet/api/utils.cpp b/src/wallet/api/utils.cpp new file mode 100644 index 000000000..aa85323f0 --- /dev/null +++ b/src/wallet/api/utils.cpp @@ -0,0 +1,79 @@ +// Copyright (c) 2014-2016, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + + + +#include "include_base_utils.h" // LOG_PRINT_x +#include "net/http_client.h" // epee::net_utils::... +#include + +using namespace std; + +namespace Bitmonero { +namespace Utils { + + +// copy-pasted from simplewallet. + +bool isAddressLocal(const std::string &address) +{ + // extract host + epee::net_utils::http::url_content u_c; + if (!epee::net_utils::parse_url(address, u_c)) + { + LOG_PRINT_L1("Failed to determine whether daemon is local, assuming not"); + return false; + } + if (u_c.host.empty()) + { + LOG_PRINT_L1("Failed to determine whether daemon is local, assuming not"); + return false; + } + + // resolve to IP + boost::asio::io_service io_service; + boost::asio::ip::tcp::resolver resolver(io_service); + boost::asio::ip::tcp::resolver::query query(u_c.host, ""); + boost::asio::ip::tcp::resolver::iterator i = resolver.resolve(query); + while (i != boost::asio::ip::tcp::resolver::iterator()) + { + const boost::asio::ip::tcp::endpoint &ep = *i; + if (ep.address().is_loopback()) + return true; + ++i; + } + + return false; +} + +} + + +} // namespace diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 5f32908de..d9d24b4f0 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -56,7 +56,7 @@ string Wallet::displayAmount(uint64_t amount) ///////////////////////// WalletImpl implementation //////////////////////// WalletImpl::WalletImpl(bool testnet) - :m_wallet(nullptr), m_status(Wallet::Status_Ok) + :m_wallet(nullptr), m_status(Wallet::Status_Ok), m_trustedDaemon(false) { m_wallet = new tools::wallet2(testnet); m_history = new TransactionHistoryImpl(this); @@ -237,6 +237,10 @@ bool WalletImpl::init(const std::string &daemon_address, uint64_t upper_transact clearStatus(); try { m_wallet->init(daemon_address, upper_transaction_size_limit); + if (Utils::isAddressLocal(daemon_address)) { + this->setTrustedDaemon(true); + } + } catch (const std::exception &e) { LOG_ERROR("Error initializing wallet: " << e.what()); m_status = Status_Error; @@ -315,7 +319,8 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, uint64 try { - transaction->m_pending_tx = m_wallet->create_transactions(dsts, fake_outs_count, 0 /* unlock_time */, 0 /* unused fee arg*/, extra); + transaction->m_pending_tx = m_wallet->create_transactions(dsts, fake_outs_count, 0 /* unlock_time */, + 0 /* unused fee arg*/, extra, m_trustedDaemon); } catch (const tools::error::daemon_busy&) { // TODO: make it translatable with "tr"? @@ -404,6 +409,16 @@ bool WalletImpl::connectToDaemon() return result; } +void WalletImpl::setTrustedDaemon(bool arg) +{ + m_trustedDaemon = arg; +} + +bool WalletImpl::trustedDaemon() const +{ + return m_trustedDaemon; +} + void WalletImpl::clearStatus() { m_status = Status_Ok; diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index 3eaaec59e..3671c2f7a 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -62,6 +62,8 @@ public: bool store(const std::string &path); bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit); bool connectToDaemon(); + void setTrustedDaemon(bool arg); + bool trustedDaemon() const; uint64_t balance() const; uint64_t unlockedBalance() const; bool refresh(); @@ -81,6 +83,7 @@ private: std::string m_errorString; std::string m_password; TransactionHistoryImpl * m_history; + bool m_trustedDaemon; }; diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h index 4954db0d2..ab715dbf9 100644 --- a/src/wallet/wallet2_api.h +++ b/src/wallet/wallet2_api.h @@ -38,6 +38,9 @@ // Public interface for libwallet library namespace Bitmonero { + namespace Utils { + bool isAddressLocal(const std::string &hostaddr); + } /** * @brief Transaction-like interface for sending money */ @@ -117,6 +120,8 @@ struct Wallet virtual bool store(const std::string &path) = 0; virtual bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit) = 0; virtual bool connectToDaemon() = 0; + virtual void setTrustedDaemon(bool arg) = 0; + virtual bool trustedDaemon() const = 0; virtual uint64_t balance() const = 0; virtual uint64_t unlockedBalance() const = 0; static std::string displayAmount(uint64_t amount); -- cgit v1.2.3 From 5dbd2b8fc3aa97f3a2e14a378cf6b7afd16bd4e2 Mon Sep 17 00:00:00 2001 From: Ilya Kitaev Date: Thu, 5 May 2016 22:24:00 +0300 Subject: started WalletListener --- src/wallet/api/wallet.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++++++- src/wallet/api/wallet.h | 4 ++++ src/wallet/wallet2_api.h | 8 +++++++ 3 files changed, 65 insertions(+), 1 deletion(-) (limited to 'src/wallet/api/wallet.cpp') diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index d9d24b4f0..6170000b7 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -47,6 +47,47 @@ namespace { static const size_t DEFAULT_MIX = 4; } +struct Wallet2CallbackImpl : public tools::i_wallet2_callback +{ + + ~Wallet2CallbackImpl() + { + + } + + void setListener(WalletListener * listener) + { + // TODO; + } + + WalletListener * getListener() const + { + return m_listener; + } + + virtual void on_new_block(uint64_t height, const cryptonote::block& block) + { + // TODO; + } + virtual void on_money_received(uint64_t height, const cryptonote::transaction& tx, size_t out_index) + { + // TODO; + + } + virtual void on_money_spent(uint64_t height, const cryptonote::transaction& in_tx, size_t out_index, + const cryptonote::transaction& spend_tx) + { + // TODO; + } + + virtual void on_skip_transaction(uint64_t height, const cryptonote::transaction& tx) + { + // TODO; + } + + WalletListener * m_listener; +}; + Wallet::~Wallet() {} string Wallet::displayAmount(uint64_t amount) @@ -56,14 +97,17 @@ string Wallet::displayAmount(uint64_t amount) ///////////////////////// WalletImpl implementation //////////////////////// WalletImpl::WalletImpl(bool testnet) - :m_wallet(nullptr), m_status(Wallet::Status_Ok), m_trustedDaemon(false) + :m_wallet(nullptr), m_status(Wallet::Status_Ok), m_trustedDaemon(false), + m_wallet2Callback(nullptr) { m_wallet = new tools::wallet2(testnet); m_history = new TransactionHistoryImpl(this); + m_wallet2Callback = new Wallet2CallbackImpl; } WalletImpl::~WalletImpl() { + delete m_wallet2Callback; delete m_history; delete m_wallet; } @@ -399,6 +443,14 @@ TransactionHistory *WalletImpl::history() const return m_history; } +void WalletImpl::setListener(WalletListener *l) +{ + // TODO thread synchronization; + m_wallet2Callback->setListener(l); +} + + + bool WalletImpl::connectToDaemon() { bool result = m_wallet->check_connection(); diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index 3671c2f7a..c0fa31003 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -40,6 +40,7 @@ namespace Bitmonero { class TransactionHistoryImpl; class PendingTransactionImpl; +struct Wallet2CallbackImpl; class WalletImpl : public Wallet { @@ -70,6 +71,7 @@ public: PendingTransaction * createTransaction(const std::string &dst_addr, uint64_t amount); virtual void disposeTransaction(PendingTransaction * t); virtual TransactionHistory * history() const; + virtual void setListener(WalletListener * l); private: void clearStatus(); @@ -84,6 +86,8 @@ private: std::string m_password; TransactionHistoryImpl * m_history; bool m_trustedDaemon; + WalletListener * m_walletListener; + Wallet2CallbackImpl * m_wallet2Callback; }; diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h index 43f5c9472..8e0830746 100644 --- a/src/wallet/wallet2_api.h +++ b/src/wallet/wallet2_api.h @@ -103,6 +103,13 @@ struct TransactionHistory }; +struct WalletListener +{ + virtual ~WalletListener() = 0; + virtual void moneySpent(const std::string &txId, uint64_t amount); + virtual void moneyReceived(const std::string &txId, uint64_t amount); +}; + /** * @brief Interface for wallet operations. @@ -141,6 +148,7 @@ struct Wallet virtual PendingTransaction * createTransaction(const std::string &dst_addr, uint64_t amount) = 0; virtual void disposeTransaction(PendingTransaction * t) = 0; virtual TransactionHistory * history() const = 0; + virtual void setListener(WalletListener *) = 0; }; /** -- cgit v1.2.3 From 27d86b73c63c7eea0473f11df348fc6a4a3b3e65 Mon Sep 17 00:00:00 2001 From: Ilya Kitaev Date: Fri, 13 May 2016 16:25:31 +0300 Subject: WalletListener::moneySpent(), WalletListener::moneyReceived() --- src/wallet/api/wallet.cpp | 23 +++++++++++++++++++++-- src/wallet/wallet2_api.h | 1 + 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'src/wallet/api/wallet.cpp') diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 6170000b7..5819e42bc 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -57,7 +57,7 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback void setListener(WalletListener * listener) { - // TODO; + m_listener = listener; } WalletListener * getListener() const @@ -68,16 +68,35 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback virtual void on_new_block(uint64_t height, const cryptonote::block& block) { // TODO; + LOG_PRINT_L3(__FUNCTION__ << ": new block. height: " << height); } + virtual void on_money_received(uint64_t height, const cryptonote::transaction& tx, size_t out_index) { - // TODO; + std::string tx_hash = epee::string_tools::pod_to_hex(get_transaction_hash(tx)); + uint64_t amount = tx.vout[out_index].amount; + + LOG_PRINT_L3(__FUNCTION__ << ": money received. height: " << height + << ", tx: " << tx_hash + << ", amount: " << print_money(amount)); + if (m_listener) { + m_listener->moneyReceived(tx_hash, amount); + } } + virtual void on_money_spent(uint64_t height, const cryptonote::transaction& in_tx, size_t out_index, const cryptonote::transaction& spend_tx) { // TODO; + std::string tx_hash = epee::string_tools::pod_to_hex(get_transaction_hash(spend_tx)); + uint64_t amount = in_tx.vout[out_index].amount; + LOG_PRINT_L3(__FUNCTION__ << ": money spent. height: " << height + << ", tx: " << tx_hash + << ", amount: " << print_money(amount)); + if (m_listener) { + m_listener->moneySpent(tx_hash, amount); + } } virtual void on_skip_transaction(uint64_t height, const cryptonote::transaction& tx) diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h index 8e0830746..d38fd6708 100644 --- a/src/wallet/wallet2_api.h +++ b/src/wallet/wallet2_api.h @@ -108,6 +108,7 @@ struct WalletListener virtual ~WalletListener() = 0; virtual void moneySpent(const std::string &txId, uint64_t amount); virtual void moneyReceived(const std::string &txId, uint64_t amount); + // TODO: on_skip_transaction; }; -- cgit v1.2.3 From 40087a745f7677d29642c9ff86e1583c34ed1748 Mon Sep 17 00:00:00 2001 From: Ilya Kitaev Date: Mon, 16 May 2016 13:11:44 +0300 Subject: WalletListener::moneySpent test --- src/wallet/api/wallet.cpp | 8 ++ src/wallet/wallet2_api.h | 4 +- tests/libwallet_api_tests/main.cpp | 207 +++++++++++++++++++++++++++---------- 3 files changed, 164 insertions(+), 55 deletions(-) (limited to 'src/wallet/api/wallet.cpp') diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 5819e42bc..440642291 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -50,6 +50,12 @@ namespace { struct Wallet2CallbackImpl : public tools::i_wallet2_callback { + Wallet2CallbackImpl() + : m_listener(nullptr) + { + + } + ~Wallet2CallbackImpl() { @@ -109,6 +115,8 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback Wallet::~Wallet() {} +WalletListener::~WalletListener() {} + string Wallet::displayAmount(uint64_t amount) { return cryptonote::print_money(amount); diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h index d38fd6708..7841c299d 100644 --- a/src/wallet/wallet2_api.h +++ b/src/wallet/wallet2_api.h @@ -106,8 +106,8 @@ struct TransactionHistory struct WalletListener { virtual ~WalletListener() = 0; - virtual void moneySpent(const std::string &txId, uint64_t amount); - virtual void moneyReceived(const std::string &txId, uint64_t amount); + virtual void moneySpent(const std::string &txId, uint64_t amount) = 0; + virtual void moneyReceived(const std::string &txId, uint64_t amount) = 0; // TODO: on_skip_transaction; }; diff --git a/tests/libwallet_api_tests/main.cpp b/tests/libwallet_api_tests/main.cpp index 35d0c8e9d..bdcf889ef 100644 --- a/tests/libwallet_api_tests/main.cpp +++ b/tests/libwallet_api_tests/main.cpp @@ -37,12 +37,47 @@ #include #include +#include +#include using namespace std; //unsigned int epee::g_test_dbg_lock_sleep = 0; +namespace Consts +{ + +// TODO: add test wallets to the source tree (as they have some balance mined)? +// TODO: get rid of hardcoded paths + +const char * WALLET_NAME = "testwallet"; +const char * WALLET_NAME_COPY = "testwallet_copy"; +const char * WALLET_NAME_WITH_DIR = "walletdir/testwallet_test"; +const char * WALLET_NAME_WITH_DIR_NON_WRITABLE = "/var/walletdir/testwallet_test"; +const char * WALLET_PASS = "password"; +const char * WALLET_PASS2 = "password22"; +const char * WALLET_LANG = "English"; + +const char * TESTNET_WALLET_NAME = "/home/mbg033/dev/monero/testnet/wallet_01.bin"; +const char * TESTNET_WALLET3_NAME = "/home/mbg033/dev/monero/testnet/wallet_03.bin"; +const char * TESTNET_WALLET4_NAME = "/home/mbg033/dev/monero/testnet/wallet_04.bin"; +const char * TESTNET_WALLET_PASS = ""; + + +const char * TESTNET_DAEMON_ADDRESS = "localhost:38081"; +const uint64_t AMOUNT_10XMR = 10000000000000L; +const uint64_t AMOUNT_5XMR = 50000000000000L; + +const char * RECIPIENT_WALLET_ADDRESS = "9uekQVGj7NjSAREnZ8cUsRagWDdjvdhpwUKhsL95oXngBnZXZ1RzH8R6UJbU1R7wim9yKbSjxuoQ22ERRkEochGECj66oP3"; +const char * TESTNET_WALLET3_ADDRESS = "A11cBpRDqpTCneSL3KNBvGWM6PfxG7QrxNVCcMiZeuAD3fQA9Z366DegFLYHKrMnDm8QixPziRn4kVcWPFtn6aCSR1Hp7sg"; +const char * TESTNET_WALLET4_ADDRESS = "A21wicxbhUSKa6twequhKCCG8wYEGZ7viYRLW7mBXtWyheyY8C8XwUJG5PSjULDs1q7hndkihtFgybWjagvchrNg1Y588hM"; + +} + + +using namespace Consts; + struct Utils { static void deleteWallet(const std::string & walletname) @@ -58,39 +93,29 @@ struct Utils std::cout << "** removing dir recursively: " << path << std::endl; boost::filesystem::remove_all(path); } + + static void print_transaction(Bitmonero::TransactionInfo * t) + { + + std::cout << "d: " + << (t->direction() == Bitmonero::TransactionInfo::Direction_In ? "in" : "out") + << ", pe: " << (t->isPending() ? "true" : "false") + << ", bh: " << t->blockHeight() + << ", a: " << Bitmonero::Wallet::displayAmount(t->amount()) + << ", f: " << Bitmonero::Wallet::displayAmount(t->fee()) + << ", h: " << t->hash() + << ", pid: " << t->paymentId() + << std::endl; + } }; -struct WalletManagerTest : public testing::Test +struct DISABLED_WalletManagerTest : public testing::Test { Bitmonero::WalletManager * wmgr; - const char * WALLET_NAME = "testwallet"; - const char * WALLET_NAME_COPY = "testwallet_copy"; - const char * WALLET_NAME_WITH_DIR = "walletdir/testwallet_test"; - const char * WALLET_NAME_WITH_DIR_NON_WRITABLE = "/var/walletdir/testwallet_test"; - const char * WALLET_PASS = "password"; - const char * WALLET_PASS2 = "password22"; - const char * WALLET_LANG = "English"; - - - // TODO: add test wallets to the source tree (as they have some balance mined)? - const char * TESTNET_WALLET_NAME = "/home/mbg033/dev/monero/testnet/wallet_01.bin"; - const char * TESTNET_WALLET3_NAME = "/home/mbg033/dev/monero/testnet/wallet_03.bin"; - const char * TESTNET_WALLET4_NAME = "/home/mbg033/dev/monero/testnet/wallet_04.bin"; - const char * TESTNET_WALLET_PASS = ""; - - - const char * TESTNET_DAEMON_ADDRESS = "localhost:38081"; - const uint64_t AMOUNT_10XMR = 10000000000000L; - const uint64_t AMOUNT_5XMR = 50000000000000L; - - const char * RECIPIENT_WALLET_ADDRESS = "9uekQVGj7NjSAREnZ8cUsRagWDdjvdhpwUKhsL95oXngBnZXZ1RzH8R6UJbU1R7wim9yKbSjxuoQ22ERRkEochGECj66oP3"; - const char * TESTNET_WALLET3_ADDRESS = "A11cBpRDqpTCneSL3KNBvGWM6PfxG7QrxNVCcMiZeuAD3fQA9Z366DegFLYHKrMnDm8QixPziRn4kVcWPFtn6aCSR1Hp7sg"; - const char * TESTNET_WALLET4_ADDRESS = "A21wicxbhUSKa6twequhKCCG8wYEGZ7viYRLW7mBXtWyheyY8C8XwUJG5PSjULDs1q7hndkihtFgybWjagvchrNg1Y588hM"; - - WalletManagerTest() + DISABLED_WalletManagerTest() { std::cout << __FUNCTION__ << std::endl; wmgr = Bitmonero::WalletManagerFactory::getWalletManager(); @@ -99,29 +124,42 @@ struct WalletManagerTest : public testing::Test } - ~WalletManagerTest() + ~DISABLED_WalletManagerTest() { std::cout << __FUNCTION__ << std::endl; //deleteWallet(WALLET_NAME); } - static void print_transaction(Bitmonero::TransactionInfo * t) +}; + + +struct DISABLED_WalletTest1 : public testing::Test +{ + Bitmonero::WalletManager * wmgr; + + DISABLED_WalletTest1() { + wmgr = Bitmonero::WalletManagerFactory::getWalletManager(); + } - std::cout << "d: " - << (t->direction() == Bitmonero::TransactionInfo::Direction_In ? "in" : "out") - << ", pe: " << (t->isPending() ? "true" : "false") - << ", bh: " << t->blockHeight() - << ", a: " << Bitmonero::Wallet::displayAmount(t->amount()) - << ", f: " << Bitmonero::Wallet::displayAmount(t->fee()) - << ", h: " << t->hash() - << ", pid: " << t->paymentId() - << std::endl; + +}; + + +struct WalletTest2 : public testing::Test +{ + Bitmonero::WalletManager * wmgr; + + WalletTest2() + { + wmgr = Bitmonero::WalletManagerFactory::getWalletManager(); } + + }; -TEST_F(WalletManagerTest, WalletManagerCreatesWallet) +TEST_F(DISABLED_WalletManagerTest, WalletManagerCreatesWallet) { Bitmonero::Wallet * wallet = wmgr->createWallet(WALLET_NAME, WALLET_PASS, WALLET_LANG); @@ -138,7 +176,7 @@ TEST_F(WalletManagerTest, WalletManagerCreatesWallet) } -TEST_F(WalletManagerTest, WalletManagerOpensWallet) +TEST_F(DISABLED_WalletManagerTest, WalletManagerOpensWallet) { Bitmonero::Wallet * wallet1 = wmgr->createWallet(WALLET_NAME, WALLET_PASS, WALLET_LANG); @@ -151,7 +189,7 @@ TEST_F(WalletManagerTest, WalletManagerOpensWallet) } -TEST_F(WalletManagerTest, WalletManagerChangesPassword) +TEST_F(DISABLED_WalletManagerTest, WalletManagerChangesPassword) { Bitmonero::Wallet * wallet1 = wmgr->createWallet(WALLET_NAME, WALLET_PASS, WALLET_LANG); std::string seed1 = wallet1->seed(); @@ -167,7 +205,7 @@ TEST_F(WalletManagerTest, WalletManagerChangesPassword) -TEST_F(WalletManagerTest, WalletManagerRecoversWallet) +TEST_F(DISABLED_WalletManagerTest, WalletManagerRecoversWallet) { Bitmonero::Wallet * wallet1 = wmgr->createWallet(WALLET_NAME, WALLET_PASS, WALLET_LANG); std::string seed1 = wallet1->seed(); @@ -183,7 +221,7 @@ TEST_F(WalletManagerTest, WalletManagerRecoversWallet) } -TEST_F(WalletManagerTest, WalletManagerStoresWallet1) +TEST_F(DISABLED_WalletManagerTest, WalletManagerStoresWallet1) { Bitmonero::Wallet * wallet1 = wmgr->createWallet(WALLET_NAME, WALLET_PASS, WALLET_LANG); std::string seed1 = wallet1->seed(); @@ -200,7 +238,7 @@ TEST_F(WalletManagerTest, WalletManagerStoresWallet1) } -TEST_F(WalletManagerTest, WalletManagerStoresWallet2) +TEST_F(DISABLED_WalletManagerTest, WalletManagerStoresWallet2) { Bitmonero::Wallet * wallet1 = wmgr->createWallet(WALLET_NAME, WALLET_PASS, WALLET_LANG); std::string seed1 = wallet1->seed(); @@ -216,7 +254,7 @@ TEST_F(WalletManagerTest, WalletManagerStoresWallet2) ASSERT_TRUE(wmgr->closeWallet(wallet1)); } -TEST_F(WalletManagerTest, WalletManagerStoresWallet3) +TEST_F(DISABLED_WalletManagerTest, WalletManagerStoresWallet3) { Bitmonero::Wallet * wallet1 = wmgr->createWallet(WALLET_NAME, WALLET_PASS, WALLET_LANG); std::string seed1 = wallet1->seed(); @@ -238,7 +276,7 @@ TEST_F(WalletManagerTest, WalletManagerStoresWallet3) } -TEST_F(WalletManagerTest, WalletManagerStoresWallet4) +TEST_F(DISABLED_WalletManagerTest, WalletManagerStoresWallet4) { Bitmonero::Wallet * wallet1 = wmgr->createWallet(WALLET_NAME, WALLET_PASS, WALLET_LANG); std::string seed1 = wallet1->seed(); @@ -260,7 +298,8 @@ TEST_F(WalletManagerTest, WalletManagerStoresWallet4) } -TEST_F(WalletManagerTest, WalletShowsBalance) + +TEST_F(DISABLED_WalletTest1, WalletShowsBalance) { Bitmonero::Wallet * wallet1 = wmgr->openWallet(TESTNET_WALLET_NAME, TESTNET_WALLET_PASS, true); ASSERT_TRUE(wallet1->balance() > 0); @@ -278,7 +317,7 @@ TEST_F(WalletManagerTest, WalletShowsBalance) ASSERT_TRUE(wmgr->closeWallet(wallet2)); } -TEST_F(WalletManagerTest, WalletRefresh) +TEST_F(DISABLED_WalletTest1, WalletRefresh) { Bitmonero::Wallet * wallet1 = wmgr->openWallet(TESTNET_WALLET_NAME, TESTNET_WALLET_PASS, true); // make sure testnet daemon is running @@ -287,7 +326,7 @@ TEST_F(WalletManagerTest, WalletRefresh) ASSERT_TRUE(wmgr->closeWallet(wallet1)); } -TEST_F(WalletManagerTest, WalletTransaction) +TEST_F(DISABLED_WalletTest1, WalletTransaction) { Bitmonero::Wallet * wallet1 = wmgr->openWallet(TESTNET_WALLET_NAME, TESTNET_WALLET_PASS, true); // make sure testnet daemon is running @@ -308,7 +347,7 @@ TEST_F(WalletManagerTest, WalletTransaction) ASSERT_TRUE(wmgr->closeWallet(wallet1)); } -TEST_F(WalletManagerTest, WalletHistory) +TEST_F(DISABLED_WalletTest1, WalletHistory) { Bitmonero::Wallet * wallet1 = wmgr->openWallet(TESTNET_WALLET_NAME, TESTNET_WALLET_PASS, true); // make sure testnet daemon is running @@ -321,11 +360,11 @@ TEST_F(WalletManagerTest, WalletHistory) for (auto t: history->getAll()) { ASSERT_TRUE(t != nullptr); - print_transaction(t); + Utils::print_transaction(t); } } -TEST_F(WalletManagerTest, WalletTransactionAndHistory) +TEST_F(DISABLED_WalletTest1, WalletTransactionAndHistory) { Bitmonero::Wallet * wallet_src = wmgr->openWallet(TESTNET_WALLET3_NAME, TESTNET_WALLET_PASS, true); // make sure testnet daemon is running @@ -339,7 +378,7 @@ TEST_F(WalletManagerTest, WalletTransactionAndHistory) std::cout << "**** Transactions before transfer (" << count1 << ")" << std::endl; for (auto t: history->getAll()) { ASSERT_TRUE(t != nullptr); - print_transaction(t); + Utils::print_transaction(t); } Bitmonero::PendingTransaction * tx = wallet_src->createTransaction(TESTNET_WALLET4_ADDRESS, AMOUNT_10XMR * 5); @@ -352,11 +391,73 @@ TEST_F(WalletManagerTest, WalletTransactionAndHistory) std::cout << "**** Transactions after transfer (" << history->count() << ")" << std::endl; for (auto t: history->getAll()) { ASSERT_TRUE(t != nullptr); - print_transaction(t); + Utils::print_transaction(t); } } +struct MyWalletListener : public Bitmonero::WalletListener +{ + + Bitmonero::Wallet * wallet; + uint64_t total_tx; + uint64_t total_rx; + std::timed_mutex guard; + + MyWalletListener(Bitmonero::Wallet * wallet) + : total_tx(0), total_rx(0) + { + this->wallet = wallet; + this->wallet->setListener(this); + } + + virtual void moneySpent(const string &txId, uint64_t amount) + { + std::cout << "wallet: " << wallet->address() << " just spent money (" + << txId << ", " << wallet->displayAmount(amount) << ")" << std::endl; + total_tx += amount; + guard.unlock(); + } + + virtual void moneyReceived(const string &txId, uint64_t amount) + { + std::cout << "wallet: " << wallet->address() << " just received money (" + << txId << ", " << wallet->displayAmount(amount) << ")" << std::endl; + total_rx += amount; + guard.unlock(); + } +}; + +TEST_F(WalletTest2, WalletCallbackSent) +{ + + Bitmonero::Wallet * wallet_src = wmgr->openWallet(TESTNET_WALLET3_NAME, TESTNET_WALLET_PASS, true); + // make sure testnet daemon is running + ASSERT_TRUE(wallet_src->init(TESTNET_DAEMON_ADDRESS, 0)); + ASSERT_TRUE(wallet_src->refresh()); + MyWalletListener * wallet_src_listener = new MyWalletListener(wallet_src); + std::cout << "** Balance: " << wallet_src->displayAmount(wallet_src->balance()) << std::endl; + /* + Bitmonero::Wallet * wallet_dst = wmgr->openWallet(TESTNET_WALLET4_NAME, TESTNET_WALLET_PASS, true); + ASSERT_TRUE(wallet_dst->init(TESTNET_DAEMON_ADDRESS, 0)); + ASSERT_TRUE(wallet_dst->refresh()); + MyWalletListener * wallet_dst_listener = new MyWalletListener(wallet_dst); + */ + + + uint64_t amount = AMOUNT_10XMR * 5; + std::cout << "** Sending " << Bitmonero::Wallet::displayAmount(amount) << " to " << TESTNET_WALLET4_ADDRESS; + Bitmonero::PendingTransaction * tx = wallet_src->createTransaction(TESTNET_WALLET4_ADDRESS, AMOUNT_10XMR * 5); + ASSERT_TRUE(tx->status() == Bitmonero::PendingTransaction::Status_Ok); + ASSERT_TRUE(tx->commit()); + + std::chrono::seconds wait_for = std::chrono::seconds(60*3); + + wallet_src_listener->guard.lock(); + wallet_src_listener->guard.try_lock_for(wait_for); + ASSERT_TRUE(wallet_src_listener->total_tx != 0); + +} int main(int argc, char** argv) { -- cgit v1.2.3 From c554055ce435ae2752820ba317d801f143804b3c Mon Sep 17 00:00:00 2001 From: Ilya Kitaev Date: Fri, 10 Jun 2016 12:51:09 +0300 Subject: Wallet::filename, Wallet::keysFilename, tests for move wallet --- src/wallet/api/wallet.cpp | 10 ++++++++++ src/wallet/api/wallet.h | 2 ++ src/wallet/wallet2_api.h | 17 +++++++++++++++++ tests/libwallet_api_tests/main.cpp | 29 +++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+) (limited to 'src/wallet/api/wallet.cpp') diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 440642291..5b68387ea 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -303,6 +303,16 @@ bool WalletImpl::store(const std::string &path) return m_status == Status_Ok; } +string WalletImpl::filename() const +{ + return m_wallet->get_wallet_file(); +} + +string WalletImpl::keysFilename() const +{ + return m_wallet->get_keys_file(); +} + bool WalletImpl::init(const std::string &daemon_address, uint64_t upper_transaction_size_limit) { clearStatus(); diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index c0fa31003..c402ef53c 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -61,6 +61,8 @@ public: bool setPassword(const std::string &password); std::string address() const; bool store(const std::string &path); + std::string filename() const; + std::string keysFilename() const; bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit); bool connectToDaemon(); void setTrustedDaemon(bool arg); diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h index b98bb8661..bf5ddc3c7 100644 --- a/src/wallet/wallet2_api.h +++ b/src/wallet/wallet2_api.h @@ -135,7 +135,24 @@ struct Wallet virtual std::string errorString() const = 0; virtual bool setPassword(const std::string &password) = 0; virtual std::string address() const = 0; + /*! + * \brief store - stores wallet to file. + * \param path - main filename to store wallet to. additionally stores address file and keys file. + * to store to the same file - just pass empty string; + * \return + */ virtual bool store(const std::string &path) = 0; + /*! + * \brief filename - returns wallet filename + * \return + */ + virtual std::string filename() const = 0; + /*! + * \brief keysFilename - returns keys filename. usually this formed as "wallet_filename".keys + * \return + */ + virtual std::string keysFilename() const = 0; + virtual bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit) = 0; virtual bool connectToDaemon() = 0; virtual void setTrustedDaemon(bool arg) = 0; diff --git a/tests/libwallet_api_tests/main.cpp b/tests/libwallet_api_tests/main.cpp index 91636d522..595e3ccfb 100644 --- a/tests/libwallet_api_tests/main.cpp +++ b/tests/libwallet_api_tests/main.cpp @@ -210,6 +210,35 @@ TEST_F(WalletManagerTest, WalletManagerOpensWallet) std::cout << "** seed: " << wallet2->seed() << std::endl; } +TEST_F(WalletManagerTest, WalletManagerStoresWallet) +{ + + Bitmonero::Wallet * wallet1 = wmgr->createWallet(WALLET_NAME, WALLET_PASS, WALLET_LANG); + std::string seed1 = wallet1->seed(); + wallet1->store(""); + ASSERT_TRUE(wmgr->closeWallet(wallet1)); + Bitmonero::Wallet * wallet2 = wmgr->openWallet(WALLET_NAME, WALLET_PASS); + ASSERT_TRUE(wallet2->status() == Bitmonero::Wallet::Status_Ok); + ASSERT_TRUE(wallet2->seed() == seed1); +} + + +TEST_F(WalletManagerTest, WalletManagerMovesWallet) +{ + + Bitmonero::Wallet * wallet1 = wmgr->createWallet(WALLET_NAME, WALLET_PASS, WALLET_LANG); + std::string WALLET_NAME_MOVED = std::string("/tmp/") + WALLET_NAME + ".moved"; + std::string seed1 = wallet1->seed(); + ASSERT_TRUE(wallet1->store(WALLET_NAME_MOVED)); + + Bitmonero::Wallet * wallet2 = wmgr->openWallet(WALLET_NAME_MOVED, WALLET_PASS); + ASSERT_TRUE(wallet2->filename() == WALLET_NAME_MOVED); + ASSERT_TRUE(wallet2->keysFilename() == WALLET_NAME_MOVED + ".keys"); + ASSERT_TRUE(wallet2->status() == Bitmonero::Wallet::Status_Ok); + ASSERT_TRUE(wallet2->seed() == seed1); +} + + /* TEST_F(WalletManagerTest, WalletManagerChangesPassword) { -- cgit v1.2.3 From 3ac20a46b38f88757c57cbcf8581cade312b7936 Mon Sep 17 00:00:00 2001 From: Ilya Kitaev Date: Fri, 10 Jun 2016 13:52:10 +0300 Subject: wallet::default_mixin exposed to public interface as Wallet::setDefaultMixin, Wallet::defaultMixin; wallet::create_transaction_2 used in Wallet::createTransaction --- src/wallet/api/wallet.cpp | 11 ++++++++++- src/wallet/api/wallet.h | 2 ++ src/wallet/wallet2_api.h | 10 ++++++++++ tests/libwallet_api_tests/main.cpp | 2 ++ 4 files changed, 24 insertions(+), 1 deletion(-) (limited to 'src/wallet/api/wallet.cpp') diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 5b68387ea..f6d7a561e 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -400,7 +400,7 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, uint64 try { - transaction->m_pending_tx = m_wallet->create_transactions(dsts, fake_outs_count, 0 /* unlock_time */, + transaction->m_pending_tx = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */, 0 /* unused fee arg*/, extra, m_trustedDaemon); } catch (const tools::error::daemon_busy&) { @@ -486,6 +486,15 @@ void WalletImpl::setListener(WalletListener *l) m_wallet2Callback->setListener(l); } +uint32_t WalletImpl::defaultMixin() const +{ + return m_wallet->default_mixin(); +} + +void WalletImpl::setDefaultMixin(uint32_t arg) +{ + m_wallet->default_mixin(arg); +} bool WalletImpl::connectToDaemon() diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index c402ef53c..6c8913c25 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -74,6 +74,8 @@ public: virtual void disposeTransaction(PendingTransaction * t); virtual TransactionHistory * history() const; virtual void setListener(WalletListener * l); + virtual uint32_t defaultMixin() const; + virtual void setDefaultMixin(uint32_t arg); private: void clearStatus(); diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h index bf5ddc3c7..62231820b 100644 --- a/src/wallet/wallet2_api.h +++ b/src/wallet/wallet2_api.h @@ -167,6 +167,16 @@ struct Wallet virtual void disposeTransaction(PendingTransaction * t) = 0; virtual TransactionHistory * history() const = 0; virtual void setListener(WalletListener *) = 0; + /*! + * \brief defaultMixin - returns number of mixins used in transactions + * \return + */ + virtual uint32_t defaultMixin() const = 0; + /*! + * \brief setDefaultMixin - setum number of mixins to be used for new transactions + * \param arg + */ + virtual void setDefaultMixin(uint32_t arg) = 0; }; /** diff --git a/tests/libwallet_api_tests/main.cpp b/tests/libwallet_api_tests/main.cpp index 595e3ccfb..935cfd884 100644 --- a/tests/libwallet_api_tests/main.cpp +++ b/tests/libwallet_api_tests/main.cpp @@ -401,6 +401,8 @@ TEST_F(WalletTest1, WalletTransaction) ASSERT_TRUE(wallet1->status() == Bitmonero::PendingTransaction::Status_Ok); std::string recepient_address = Utils::get_wallet_address(CURRENT_DST_WALLET, TESTNET_WALLET_PASS); + wallet1->setDefaultMixin(1); + ASSERT_TRUE(wallet1->defaultMixin() == 1); Bitmonero::PendingTransaction * transaction = wallet1->createTransaction( recepient_address, AMOUNT_10XMR); -- cgit v1.2.3 From 3318addafaf6ac7b5489f7d774083a84dce7dfa0 Mon Sep 17 00:00:00 2001 From: Ilya Kitaev Date: Thu, 16 Jun 2016 16:42:33 +0300 Subject: double/string to monero integer convertion methods --- src/wallet/api/wallet.cpp | 17 +++++++++++++++++ src/wallet/wallet2_api.h | 2 ++ tests/libwallet_api_tests/main.cpp | 16 ++++++++++++++-- 3 files changed, 33 insertions(+), 2 deletions(-) (limited to 'src/wallet/api/wallet.cpp') diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index f6d7a561e..1f414b3bf 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -36,6 +36,7 @@ #include "mnemonics/electrum-words.h" #include +#include using namespace std; using namespace cryptonote; @@ -122,6 +123,22 @@ string Wallet::displayAmount(uint64_t amount) return cryptonote::print_money(amount); } +uint64_t Wallet::amountFromString(const string &amount) +{ + uint64_t result; + cryptonote::parse_amount(result, amount); + return result; +} + +uint64_t Wallet::amountFromDouble(double amount) +{ + std::stringstream ss; + ss << std::fixed << std::setprecision(CRYPTONOTE_DISPLAY_DECIMAL_POINT) << amount; + return amountFromString(ss.str()); +} + + + ///////////////////////// WalletImpl implementation //////////////////////// WalletImpl::WalletImpl(bool testnet) :m_wallet(nullptr), m_status(Wallet::Status_Ok), m_trustedDaemon(false), diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h index 62231820b..34c18f77f 100644 --- a/src/wallet/wallet2_api.h +++ b/src/wallet/wallet2_api.h @@ -160,6 +160,8 @@ struct Wallet virtual uint64_t balance() const = 0; virtual uint64_t unlockedBalance() const = 0; static std::string displayAmount(uint64_t amount); + static uint64_t amountFromString(const std::string &amount); + static uint64_t amountFromDouble(double amount); // TODO? // virtual uint64_t unlockedDustBalance() const = 0; virtual bool refresh() = 0; diff --git a/tests/libwallet_api_tests/main.cpp b/tests/libwallet_api_tests/main.cpp index 935cfd884..849d76e1b 100644 --- a/tests/libwallet_api_tests/main.cpp +++ b/tests/libwallet_api_tests/main.cpp @@ -247,7 +247,7 @@ TEST_F(WalletManagerTest, WalletManagerChangesPassword) ASSERT_TRUE(wallet1->setPassword(WALLET_PASS2)); ASSERT_TRUE(wmgr->closeWallet(wallet1)); Bitmonero::Wallet * wallet2 = wmgr->openWallet(WALLET_NAME, WALLET_PASS2); - ASSERT_TRUE(wallet2->status() == Bitmonero::Wallet::Status_Ok); + ASSERT_TRUE(wallet2->status() == Bitmonero::Wallet::Status_Ok);quint64 ASSERT_TRUE(wallet2->seed() == seed1); ASSERT_TRUE(wmgr->closeWallet(wallet2)); Bitmonero::Wallet * wallet3 = wmgr->openWallet(WALLET_NAME, WALLET_PASS); @@ -390,7 +390,19 @@ TEST_F(WalletTest1, WalletRefresh) } +TEST_F(WalletTest1, WalletConvertsToString) +{ + std::string strAmount = Bitmonero::Wallet::displayAmount(AMOUNT_5XMR); + ASSERT_TRUE(AMOUNT_5XMR == Bitmonero::Wallet::amountFromString(strAmount)); + + ASSERT_TRUE(AMOUNT_5XMR == Bitmonero::Wallet::amountFromDouble(5.0)); + ASSERT_TRUE(AMOUNT_10XMR == Bitmonero::Wallet::amountFromDouble(10.0)); + ASSERT_TRUE(AMOUNT_1XMR == Bitmonero::Wallet::amountFromDouble(1.0)); + +} + +/* TEST_F(WalletTest1, WalletTransaction) { Bitmonero::Wallet * wallet1 = wmgr->openWallet(CURRENT_SRC_WALLET, TESTNET_WALLET_PASS, true); @@ -415,7 +427,7 @@ TEST_F(WalletTest1, WalletTransaction) ASSERT_FALSE(wallet1->balance() == balance); ASSERT_TRUE(wmgr->closeWallet(wallet1)); } - +*/ TEST_F(WalletTest1, WalletHistory) { Bitmonero::Wallet * wallet1 = wmgr->openWallet(CURRENT_SRC_WALLET, TESTNET_WALLET_PASS, true); -- cgit v1.2.3 From f1c4a376af916604e2b142a1169d610f631bd91c Mon Sep 17 00:00:00 2001 From: Ilya Kitaev Date: Mon, 20 Jun 2016 22:56:30 +0300 Subject: Wallet::createTransaction: added mixin_count param --- src/wallet/api/wallet.cpp | 18 ++++++++++------- src/wallet/api/wallet.h | 2 +- src/wallet/wallet2_api.h | 13 ++++++++++-- tests/libwallet_api_tests/main.cpp | 41 +++++++++++++++++++++++++++++++++++++- 4 files changed, 63 insertions(+), 11 deletions(-) (limited to 'src/wallet/api/wallet.cpp') diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 1f414b3bf..d72ebc8da 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -45,7 +45,7 @@ namespace Bitmonero { namespace { // copy-pasted from simplewallet - static const size_t DEFAULT_MIX = 4; + static const size_t DEFAULT_MIXIN = 4; } struct Wallet2CallbackImpl : public tools::i_wallet2_callback @@ -380,7 +380,7 @@ bool WalletImpl::refresh() // - payment_details; // - unconfirmed_transfer_details; // - confirmed_transfer_details) -PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, uint64_t amount) +PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, uint64_t amount, uint32_t mixin_count) { clearStatus(); vector dsts; @@ -389,9 +389,10 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, uint64 crypto::hash8 new_payment_id; // TODO: (https://bitcointalk.org/index.php?topic=753252.msg9985441#msg9985441) - size_t fake_outs_count = m_wallet->default_mixin(); + + size_t fake_outs_count = mixin_count > 0 ? mixin_count : m_wallet->default_mixin(); if (fake_outs_count == 0) - fake_outs_count = DEFAULT_MIX; + fake_outs_count = DEFAULT_MIXIN; PendingTransactionImpl * transaction = new PendingTransactionImpl(this); @@ -436,27 +437,30 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, uint64 } catch (const tools::error::not_enough_money& e) { m_status = Status_Error; - std::ostringstream writer(m_errorString); + std::ostringstream writer; writer << boost::format(tr("not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee)")) % print_money(e.available()) % print_money(e.tx_amount() + e.fee()) % print_money(e.tx_amount()) % print_money(e.fee()); + m_errorString = writer.str(); } catch (const tools::error::not_enough_outs_to_mix& e) { - std::ostringstream writer(m_errorString); + std::ostringstream writer; writer << tr("not enough outputs for specified mixin_count") << " = " << e.mixin_count() << ":"; for (const cryptonote::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& outs_for_amount : e.scanty_outs()) { writer << "\n" << tr("output amount") << " = " << print_money(outs_for_amount.amount) << ", " << tr("found outputs to mix") << " = " << outs_for_amount.outs.size(); } + m_errorString = writer.str(); m_status = Status_Error; } catch (const tools::error::tx_not_constructed&) { m_errorString = tr("transaction was not constructed"); m_status = Status_Error; } catch (const tools::error::tx_rejected& e) { - std::ostringstream writer(m_errorString); + std::ostringstream writer; writer << (boost::format(tr("transaction %s was rejected by daemon with status: ")) % get_transaction_hash(e.tx())) << e.status(); + m_errorString = writer.str(); m_status = Status_Error; } catch (const tools::error::tx_sum_overflow& e) { m_errorString = e.what(); diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index 6c8913c25..016116e96 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -70,7 +70,7 @@ public: uint64_t balance() const; uint64_t unlockedBalance() const; bool refresh(); - PendingTransaction * createTransaction(const std::string &dst_addr, uint64_t amount); + PendingTransaction * createTransaction(const std::string &dst_addr, uint64_t amount, uint32_t mixin_count); virtual void disposeTransaction(PendingTransaction * t); virtual TransactionHistory * history() const; virtual void setListener(WalletListener * l); diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h index 34c18f77f..de0b50591 100644 --- a/src/wallet/wallet2_api.h +++ b/src/wallet/wallet2_api.h @@ -128,7 +128,6 @@ struct Wallet virtual std::string seed() const = 0; virtual std::string getSeedLanguage() const = 0; virtual void setSeedLanguage(const std::string &arg) = 0; - // virtual void setListener(Listener * listener) = 0; //! returns wallet status (Status_Ok | Status_Error) virtual int status() const = 0; //! in case error status, returns error string @@ -159,13 +158,23 @@ struct Wallet virtual bool trustedDaemon() const = 0; virtual uint64_t balance() const = 0; virtual uint64_t unlockedBalance() const = 0; + static std::string displayAmount(uint64_t amount); static uint64_t amountFromString(const std::string &amount); static uint64_t amountFromDouble(double amount); + // TODO? // virtual uint64_t unlockedDustBalance() const = 0; virtual bool refresh() = 0; - virtual PendingTransaction * createTransaction(const std::string &dst_addr, uint64_t amount) = 0; + /*! + * \brief createTransaction creates transaction + * \param dst_addr destination address as string + * \param amount amount + * \param mixin_count mixin count. if 0 passed, wallet will use default value + * \return PendingTransaction object. caller is responsible to check PendingTransaction::status() + * after object returned + */ + virtual PendingTransaction * createTransaction(const std::string &dst_addr, uint64_t amount, uint32_t mixin_count) = 0; virtual void disposeTransaction(PendingTransaction * t) = 0; virtual TransactionHistory * history() const = 0; virtual void setListener(WalletListener *) = 0; diff --git a/tests/libwallet_api_tests/main.cpp b/tests/libwallet_api_tests/main.cpp index 849d76e1b..ddd6969c6 100644 --- a/tests/libwallet_api_tests/main.cpp +++ b/tests/libwallet_api_tests/main.cpp @@ -428,6 +428,45 @@ TEST_F(WalletTest1, WalletTransaction) ASSERT_TRUE(wmgr->closeWallet(wallet1)); } */ + +TEST_F(WalletTest1, WalletTransactionWithMixin) +{ + + std::vector mixins; + // 2,3,4,5,6,7,8,9,10,15,20,25 can we do it like that? + mixins.push_back(2); mixins.push_back(3); mixins.push_back(4); mixins.push_back(5); mixins.push_back(6); + mixins.push_back(7); mixins.push_back(8); mixins.push_back(9); mixins.push_back(10); mixins.push_back(15); + mixins.push_back(20); mixins.push_back(25); + + + Bitmonero::Wallet * wallet1 = wmgr->openWallet(CURRENT_SRC_WALLET, TESTNET_WALLET_PASS, true); + + + // make sure testnet daemon is running + ASSERT_TRUE(wallet1->init(TESTNET_DAEMON_ADDRESS, 0)); + ASSERT_TRUE(wallet1->refresh()); + uint64_t balance = wallet1->balance(); + ASSERT_TRUE(wallet1->status() == Bitmonero::PendingTransaction::Status_Ok); + + std::string recepient_address = Utils::get_wallet_address(CURRENT_DST_WALLET, TESTNET_WALLET_PASS); + for (auto mixin : mixins) { + std::cerr << "Transaction mixin count: " << mixin << std::endl; + Bitmonero::PendingTransaction * transaction = wallet1->createTransaction( + recepient_address, AMOUNT_5XMR, mixin); + + std::cerr << "Transaction status: " << transaction->status() << std::endl; + std::cerr << "Transaction fee: " << Bitmonero::Wallet::displayAmount(transaction->fee()) << std::endl; + std::cerr << "Transaction error: " << transaction->errorString() << std::endl; + ASSERT_TRUE(transaction->status() == Bitmonero::PendingTransaction::Status_Ok); + wallet1->disposeTransaction(transaction); + } + + wallet1->refresh(); + + ASSERT_TRUE(wallet1->balance() == balance); + ASSERT_TRUE(wmgr->closeWallet(wallet1)); +} + TEST_F(WalletTest1, WalletHistory) { Bitmonero::Wallet * wallet1 = wmgr->openWallet(CURRENT_SRC_WALLET, TESTNET_WALLET_PASS, true); @@ -465,7 +504,7 @@ TEST_F(WalletTest1, WalletTransactionAndHistory) std::string wallet4_addr = Utils::get_wallet_address(CURRENT_DST_WALLET, TESTNET_WALLET_PASS); - Bitmonero::PendingTransaction * tx = wallet_src->createTransaction(wallet4_addr, AMOUNT_10XMR * 5); + Bitmonero::PendingTransaction * tx = wallet_src->createTransaction(wallet4_addr, AMOUNT_10XMR * 5, 0); ASSERT_TRUE(tx->status() == Bitmonero::PendingTransaction::Status_Ok); ASSERT_TRUE(tx->commit()); history = wallet_src->history(); -- cgit v1.2.3