From 9de3ec3e2a48a4695b77c66add93c2fbf42affc2 Mon Sep 17 00:00:00 2001
From: Ilya Kitaev <mbg033@gmail.com>
Date: Fri, 23 Sep 2016 22:36:37 +0300
Subject: [PATCH 01/11] libwallet_api: Wallet::blockChainHeight,
 WalletListener::newBlock

---
 src/wallet/api/wallet.cpp          | 10 +++++-
 src/wallet/api/wallet.h            |  1 +
 src/wallet/wallet2_api.h           | 34 ++++++++++++++++++--
 tests/libwallet_api_tests/main.cpp | 51 ++++++++++++++++++++++++++++--
 4 files changed, 91 insertions(+), 5 deletions(-)

diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 49ccceb13..eef956e80 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -75,8 +75,12 @@ 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);
+
+        if (m_listener) {
+            m_listener->newBlock(height);
+            m_listener->updated();
+        }
     }
 
     virtual void on_money_received(uint64_t height, const cryptonote::transaction& tx, uint64_t amount)
@@ -413,6 +417,10 @@ uint64_t WalletImpl::unlockedBalance() const
     return m_wallet->unlocked_balance();
 }
 
+uint64_t WalletImpl::blockChainHeight() const
+{
+    return m_wallet->get_blockchain_current_height();
+}
 
 bool WalletImpl::refresh()
 {
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index 11880d555..1a34a04fd 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -75,6 +75,7 @@ public:
     bool trustedDaemon() const;
     uint64_t balance() const;
     uint64_t unlockedBalance() const;
+    uint64_t blockChainHeight() const;
     bool refresh();
     void refreshAsync();
     void setAutoRefreshInterval(int seconds);
diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h
index 2d2877856..08f010b32 100644
--- a/src/wallet/wallet2_api.h
+++ b/src/wallet/wallet2_api.h
@@ -114,11 +114,35 @@ struct TransactionHistory
 struct WalletListener
 {
     virtual ~WalletListener() = 0;
+    /**
+     * @brief moneySpent - called when money spent
+     * @param txId       - transaction id
+     * @param amount     - amount
+     */
     virtual void moneySpent(const std::string &txId, uint64_t amount) = 0;
+
+    /**
+     * @brief moneyReceived - called when money received
+     * @param txId          - transaction id
+     * @param amount        - amount
+     */
     virtual void moneyReceived(const std::string &txId, uint64_t amount) = 0;
-    // generic callback, called when any event (sent/received/block reveived/etc) happened with the wallet;
+
+    /**
+     * @brief newBlock      - called when new block received
+     * @param height        - block height
+     */
+    virtual void newBlock(uint64_t height) = 0;
+
+    /**
+     * @brief updated  - generic callback, called when any event (sent/received/block reveived/etc) happened with the wallet;
+     */
     virtual void updated() = 0;
-    // called when wallet refreshed by background thread or explicitly called be calling "refresh" synchronously
+
+
+    /**
+     * @brief refreshed - called when wallet refreshed by background thread or explicitly refreshed by calling "refresh" synchronously
+     */
     virtual void refreshed() = 0;
 };
 
@@ -211,6 +235,12 @@ struct Wallet
     virtual uint64_t balance() const = 0;
     virtual uint64_t unlockedBalance() const = 0;
 
+    /**
+     * @brief getBlockChainHeight - returns current blockchain height
+     * @return
+     */
+    virtual uint64_t blockChainHeight() const = 0;
+
     static std::string displayAmount(uint64_t amount);
     static uint64_t amountFromString(const std::string &amount);
     static uint64_t amountFromDouble(double amount);
diff --git a/tests/libwallet_api_tests/main.cpp b/tests/libwallet_api_tests/main.cpp
index 94f374285..af5549426 100644
--- a/tests/libwallet_api_tests/main.cpp
+++ b/tests/libwallet_api_tests/main.cpp
@@ -473,8 +473,6 @@ TEST_F(WalletTest1, WalletGeneratesIntegratedAddress)
 
 TEST_F(WalletTest1, WalletShowsBalance)
 {
-    // TODO: temporary disabled;
-    return;
     Bitmonero::Wallet * wallet1 = wmgr->openWallet(CURRENT_SRC_WALLET, TESTNET_WALLET_PASS, true);
     ASSERT_TRUE(wallet1->balance() > 0);
     ASSERT_TRUE(wallet1->unlockedBalance() > 0);
@@ -491,6 +489,14 @@ TEST_F(WalletTest1, WalletShowsBalance)
     ASSERT_TRUE(wmgr->closeWallet(wallet2));
 }
 
+TEST_F(WalletTest1, WalletReturnsBlockHeight)
+{
+    Bitmonero::Wallet * wallet1 = wmgr->openWallet(CURRENT_SRC_WALLET, TESTNET_WALLET_PASS, true);
+    ASSERT_TRUE(wallet1->blockChainHeight() > 0);
+    wmgr->closeWallet(wallet1);
+}
+
+
 TEST_F(WalletTest1, WalletRefresh)
 {
 
@@ -742,8 +748,10 @@ struct MyWalletListener : public Bitmonero::WalletListener
     std::condition_variable cv_receive;
     std::condition_variable cv_update;
     std::condition_variable cv_refresh;
+    std::condition_variable cv_newblock;
     bool send_triggered;
     bool receive_triggered;
+    bool newblock_triggered;
     bool update_triggered;
     bool refresh_triggered;
 
@@ -781,6 +789,14 @@ struct MyWalletListener : public Bitmonero::WalletListener
         cv_receive.notify_one();
     }
 
+    virtual void newBlock(uint64_t height)
+    {
+        std::cout << "wallet: " << wallet->address()
+                  <<", new block received, blockHeight: " << height << std::endl;
+        newblock_triggered = true;
+        cv_newblock.notify_one();
+    }
+
     virtual void updated()
     {
         std::cout << __FUNCTION__ << "Wallet updated";
@@ -918,6 +934,37 @@ TEST_F(WalletTest2, WalletCallbackReceived)
 }
 
 
+
+TEST_F(WalletTest2, WalletCallbackNewBlock)
+{
+
+    Bitmonero::Wallet * wallet_src = wmgr->openWallet(TESTNET_WALLET5_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());
+    uint64_t bc1 = wallet_src->blockChainHeight();
+    std::cout << "** Block height: " << bc1 << std::endl;
+
+
+    MyWalletListener * wallet_listener = new MyWalletListener(wallet_src);
+
+    // wait max 4 min for new block
+    std::chrono::seconds wait_for = std::chrono::seconds(60*4);
+    std::unique_lock<std::mutex> lock (wallet_listener->mutex);
+    std::cerr << "TEST: waiting on newblock lock...\n";
+    wallet_listener->cv_newblock.wait_for(lock, wait_for);
+    std::cerr << "TEST: newblock lock acquired...\n";
+    ASSERT_TRUE(wallet_listener->newblock_triggered);
+    ASSERT_TRUE(wallet_listener->update_triggered);
+    uint64_t bc2 = wallet_src->blockChainHeight();
+    std::cout << "** Block height: " << bc2 << std::endl;
+    ASSERT_TRUE(bc2 > bc1);
+    wmgr->closeWallet(wallet_src);
+
+}
+
+
+
 int main(int argc, char** argv)
 {
     // we can override default values for "TESTNET_DAEMON_ADDRESS" and "WALLETS_ROOT_DIR"

From 7b4a85b309aa0fb864d63a2fd6f1ae062aaa71dd Mon Sep 17 00:00:00 2001
From: Ilya Kitaev <mbg033@gmail.com>
Date: Mon, 26 Sep 2016 21:35:00 +0300
Subject: [PATCH 02/11] wallet2_api: added Wallet::daemonBlockChainHeight()

---
 src/wallet/api/wallet.cpp                     | 15 ++++++++++
 src/wallet/api/wallet.h                       |  5 ++--
 src/wallet/wallet2.cpp                        | 30 ++++++++++++++++++-
 src/wallet/wallet2.h                          |  1 +
 src/wallet/wallet2_api.h                      | 10 ++++++-
 tests/libwallet_api_tests/main.cpp            | 24 +++++++++++++--
 .../libwallet_api_tests/scripts/send_funds.sh |  2 --
 7 files changed, 78 insertions(+), 9 deletions(-)

diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index eef956e80..986deca1f 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -422,6 +422,21 @@ uint64_t WalletImpl::blockChainHeight() const
     return m_wallet->get_blockchain_current_height();
 }
 
+uint64_t WalletImpl::daemonBlockChainHeight() const
+{
+    std::string err;
+    uint64_t result = m_wallet->get_daemon_blockchain_height(err);
+    if (!err.empty()) {
+        LOG_ERROR(__FUNCTION__ << ": " << err);
+        m_errorString = err;
+        m_status = Status_Error;
+    } else {
+        m_status = Status_Ok;
+        m_errorString = "";
+    }
+    return result;
+}
+
 bool WalletImpl::refresh()
 {
     clearStatus();
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index 1a34a04fd..03801edac 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -76,6 +76,7 @@ public:
     uint64_t balance() const;
     uint64_t unlockedBalance() const;
     uint64_t blockChainHeight() const;
+    uint64_t daemonBlockChainHeight() const;
     bool refresh();
     void refreshAsync();
     void setAutoRefreshInterval(int seconds);
@@ -106,8 +107,8 @@ private:
     friend class TransactionHistoryImpl;
 
     tools::wallet2 * m_wallet;
-    std::atomic<int>  m_status;
-    std::string m_errorString;
+    mutable std::atomic<int>  m_status;
+    mutable std::string m_errorString;
     std::string m_password;
     TransactionHistoryImpl * m_history;
     bool        m_trustedDaemon;
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 3d4f93aff..07b305b4c 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -4050,7 +4050,35 @@ std::string wallet2::get_keys_file() const
 
 std::string wallet2::get_daemon_address() const
 {
-  return m_daemon_address;
+    return m_daemon_address;
+}
+
+uint64_t wallet2::get_daemon_blockchain_height(string &err)
+{
+    // XXX: DRY violation. copy-pasted from simplewallet.cpp:get_daemon_blockchain_height()
+    //      consider to move it from simplewallet to wallet2 ?
+    COMMAND_RPC_GET_HEIGHT::request req;
+    COMMAND_RPC_GET_HEIGHT::response res = boost::value_initialized<COMMAND_RPC_GET_HEIGHT::response>();
+    m_daemon_rpc_mutex.lock();
+    bool ok = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/getheight", req, res, m_http_client);
+    m_daemon_rpc_mutex.unlock();
+    // XXX: DRY violation. copy-pasted from simplewallet.cpp:interpret_rpc_response()
+    if (ok)
+    {
+      if (res.status == CORE_RPC_STATUS_BUSY)
+      {
+        err = "daemon is busy. Please try again later.";
+      }
+      else if (res.status != CORE_RPC_STATUS_OK)
+      {
+        err = res.status;
+      }
+    }
+    else
+    {
+      err = "possibly lost connection to daemon";
+    }
+    return res.height;
 }
 
 void wallet2::set_tx_note(const crypto::hash &txid, const std::string &note)
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 89b613d34..dd7cd19dc 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -400,6 +400,7 @@ namespace tools
     std::string get_wallet_file() const;
     std::string get_keys_file() const;
     std::string get_daemon_address() const;
+    uint64_t get_daemon_blockchain_height(std::string& err);
 
     std::vector<size_t> select_available_outputs_from_histogram(uint64_t count, bool atleast, bool unlocked, bool trusted_daemon);
     std::vector<size_t> select_available_outputs(const std::function<bool(const transfer_details &td)> &f);
diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h
index 08f010b32..f424f7258 100644
--- a/src/wallet/wallet2_api.h
+++ b/src/wallet/wallet2_api.h
@@ -236,11 +236,19 @@ struct Wallet
     virtual uint64_t unlockedBalance() const = 0;
 
     /**
-     * @brief getBlockChainHeight - returns current blockchain height
+     * @brief blockChainHeight - returns current blockchain height
      * @return
      */
     virtual uint64_t blockChainHeight() const = 0;
 
+    /**
+     * @brief daemonBlockChainHeight - returns daemon blockchain height
+     * @return 0 - in case error communicating with the daemon.
+     *             status() will return Status_Error and errorString() will return verbose error description
+     */
+    virtual uint64_t daemonBlockChainHeight() const = 0;
+
+
     static std::string displayAmount(uint64_t amount);
     static uint64_t amountFromString(const std::string &amount);
     static uint64_t amountFromDouble(double amount);
diff --git a/tests/libwallet_api_tests/main.cpp b/tests/libwallet_api_tests/main.cpp
index af5549426..7cba5b8b0 100644
--- a/tests/libwallet_api_tests/main.cpp
+++ b/tests/libwallet_api_tests/main.cpp
@@ -489,7 +489,7 @@ TEST_F(WalletTest1, WalletShowsBalance)
     ASSERT_TRUE(wmgr->closeWallet(wallet2));
 }
 
-TEST_F(WalletTest1, WalletReturnsBlockHeight)
+TEST_F(WalletTest1, WalletReturnsCurrentBlockHeight)
 {
     Bitmonero::Wallet * wallet1 = wmgr->openWallet(CURRENT_SRC_WALLET, TESTNET_WALLET_PASS, true);
     ASSERT_TRUE(wallet1->blockChainHeight() > 0);
@@ -497,6 +497,24 @@ TEST_F(WalletTest1, WalletReturnsBlockHeight)
 }
 
 
+TEST_F(WalletTest1, WalletReturnsDaemonBlockHeight)
+{
+    Bitmonero::Wallet * wallet1 = wmgr->openWallet(CURRENT_SRC_WALLET, TESTNET_WALLET_PASS, true);
+    // wallet not connected to daemon
+    ASSERT_TRUE(wallet1->daemonBlockChainHeight() == 0);
+    ASSERT_TRUE(wallet1->status() != Bitmonero::Wallet::Status_Ok);
+    ASSERT_FALSE(wallet1->errorString().empty());
+    wmgr->closeWallet(wallet1);
+
+    wallet1 = wmgr->openWallet(CURRENT_SRC_WALLET, TESTNET_WALLET_PASS, true);
+    // wallet connected to daemon
+    wallet1->init(TESTNET_DAEMON_ADDRESS, 0);
+    ASSERT_TRUE(wallet1->daemonBlockChainHeight() > 0);
+    std::cout << "daemonBlockChainHeight: " << wallet1->daemonBlockChainHeight() << std::endl;
+    wmgr->closeWallet(wallet1);
+}
+
+
 TEST_F(WalletTest1, WalletRefresh)
 {
 
@@ -942,7 +960,7 @@ TEST_F(WalletTest2, WalletCallbackNewBlock)
     // make sure testnet daemon is running
     ASSERT_TRUE(wallet_src->init(TESTNET_DAEMON_ADDRESS, 0));
     ASSERT_TRUE(wallet_src->refresh());
-    uint64_t bc1 = wallet_src->blockChainHeight();
+    uint64_t bc1 = wallet_src->currentBlockChainHeight();
     std::cout << "** Block height: " << bc1 << std::endl;
 
 
@@ -956,7 +974,7 @@ TEST_F(WalletTest2, WalletCallbackNewBlock)
     std::cerr << "TEST: newblock lock acquired...\n";
     ASSERT_TRUE(wallet_listener->newblock_triggered);
     ASSERT_TRUE(wallet_listener->update_triggered);
-    uint64_t bc2 = wallet_src->blockChainHeight();
+    uint64_t bc2 = wallet_src->currentBlockChainHeight();
     std::cout << "** Block height: " << bc2 << std::endl;
     ASSERT_TRUE(bc2 > bc1);
     wmgr->closeWallet(wallet_src);
diff --git a/tests/libwallet_api_tests/scripts/send_funds.sh b/tests/libwallet_api_tests/scripts/send_funds.sh
index b7f282b71..3ce923353 100755
--- a/tests/libwallet_api_tests/scripts/send_funds.sh
+++ b/tests/libwallet_api_tests/scripts/send_funds.sh
@@ -1,7 +1,5 @@
 #!/bin/bash
 
-
-
 function send_funds {
     local amount=$1
     local dest=$(cat "$2.address.txt")

From 3079c5756be459af57c8c866b339b4b98c1da1f2 Mon Sep 17 00:00:00 2001
From: Ilya Kitaev <mbg033@gmail.com>
Date: Mon, 26 Sep 2016 22:50:10 +0300
Subject: [PATCH 03/11] wallet2_api: milliseconds resolution for auto-refresh
 interval

---
 src/wallet/api/wallet.cpp | 16 ++++++++--------
 src/wallet/api/wallet.h   |  4 ++--
 src/wallet/wallet2_api.h  |  6 +++---
 3 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 986deca1f..9a001abf3 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -46,7 +46,7 @@ namespace Bitmonero {
 namespace {
     // copy-pasted from simplewallet
     static const size_t DEFAULT_MIXIN = 4;
-    static const int    DEFAULT_REFRESH_INTERVAL_SECONDS = 10;
+    static const int    DEFAULT_REFRESH_INTERVAL_MILLIS = 1000 * 10;
 }
 
 struct Wallet2CallbackImpl : public tools::i_wallet2_callback
@@ -79,7 +79,7 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback
 
         if (m_listener) {
             m_listener->newBlock(height);
-            m_listener->updated();
+            //  m_listener->updated();
         }
     }
 
@@ -174,7 +174,7 @@ WalletImpl::WalletImpl(bool testnet)
     m_refreshThreadDone = false;
     m_refreshEnabled = false;
 
-    m_refreshIntervalSeconds = DEFAULT_REFRESH_INTERVAL_SECONDS;
+    m_refreshIntervalMillis = DEFAULT_REFRESH_INTERVAL_MILLIS;
 
     m_refreshThread = boost::thread([this] () {
         this->refreshThreadFunc();
@@ -451,14 +451,14 @@ void WalletImpl::refreshAsync()
     m_refreshCV.notify_one();
 }
 
-void WalletImpl::setAutoRefreshInterval(int seconds)
+void WalletImpl::setAutoRefreshInterval(int millis)
 {
-    m_refreshIntervalSeconds = seconds;
+    m_refreshIntervalMillis = millis;
 }
 
 int WalletImpl::autoRefreshInterval() const
 {
-    return m_refreshIntervalSeconds;
+    return m_refreshIntervalMillis;
 }
 
 // TODO:
@@ -675,8 +675,8 @@ void WalletImpl::refreshThreadFunc()
         LOG_PRINT_L3(__FUNCTION__ << ": waiting for refresh...");
         // if auto refresh enabled, we wait for the "m_refreshIntervalSeconds" interval.
         // if not - we wait forever
-        if (m_refreshIntervalSeconds > 0) {
-            boost::posix_time::milliseconds wait_for_ms(m_refreshIntervalSeconds * 1000);
+        if (m_refreshIntervalMillis > 0) {
+            boost::posix_time::milliseconds wait_for_ms(m_refreshIntervalMillis);
             m_refreshCV.timed_wait(lock, wait_for_ms);
         } else {
             m_refreshCV.wait(lock);
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index 03801edac..d97a8f3b3 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -79,7 +79,7 @@ public:
     uint64_t daemonBlockChainHeight() const;
     bool refresh();
     void refreshAsync();
-    void setAutoRefreshInterval(int seconds);
+    void setAutoRefreshInterval(int millis);
     int autoRefreshInterval() const;
 
 
@@ -118,7 +118,7 @@ private:
     // multi-threaded refresh stuff
     std::atomic<bool> m_refreshEnabled;
     std::atomic<bool> m_refreshThreadDone;
-    std::atomic<int>  m_refreshIntervalSeconds;
+    std::atomic<int>  m_refreshIntervalMillis;
     // synchronizing  refresh loop;
     boost::mutex        m_refreshMutex;
 
diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h
index f424f7258..08e2ae16b 100644
--- a/src/wallet/wallet2_api.h
+++ b/src/wallet/wallet2_api.h
@@ -269,12 +269,12 @@ struct Wallet
 
     /**
      * @brief setAutoRefreshInterval - setup interval for automatic refresh.
-     * @param seconds - interval in seconds. if zero or less than zero - automatic refresh disabled;
+     * @param seconds - interval in millis. if zero or less than zero - automatic refresh disabled;
      */
-    virtual void setAutoRefreshInterval(int seconds) = 0;
+    virtual void setAutoRefreshInterval(int millis) = 0;
 
     /**
-     * @brief autoRefreshInterval - returns automatic refresh interval in seconds
+     * @brief autoRefreshInterval - returns automatic refresh interval in millis
      * @return
      */
     virtual int autoRefreshInterval() const = 0;

From 545a48f098916cfe8575964c66a14154ca8451c7 Mon Sep 17 00:00:00 2001
From: Ilya Kitaev <mbg033@gmail.com>
Date: Mon, 26 Sep 2016 23:29:53 +0300
Subject: [PATCH 04/11] formatting: 2-spaces indentation

---
 src/wallet/wallet2.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 07b305b4c..ea50ae10c 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -4050,7 +4050,7 @@ std::string wallet2::get_keys_file() const
 
 std::string wallet2::get_daemon_address() const
 {
-    return m_daemon_address;
+  return m_daemon_address;
 }
 
 uint64_t wallet2::get_daemon_blockchain_height(string &err)

From cda4cb969a1d0430c8256075ff2d479e9ad8145c Mon Sep 17 00:00:00 2001
From: Ilya Kitaev <mbg033@gmail.com>
Date: Mon, 26 Sep 2016 23:39:30 +0300
Subject: [PATCH 05/11] formatting: 2-spaces indentation

---
 src/wallet/wallet2.cpp | 40 ++++++++++++++++++++--------------------
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index ea50ae10c..80513b519 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -4055,30 +4055,30 @@ std::string wallet2::get_daemon_address() const
 
 uint64_t wallet2::get_daemon_blockchain_height(string &err)
 {
-    // XXX: DRY violation. copy-pasted from simplewallet.cpp:get_daemon_blockchain_height()
-    //      consider to move it from simplewallet to wallet2 ?
-    COMMAND_RPC_GET_HEIGHT::request req;
-    COMMAND_RPC_GET_HEIGHT::response res = boost::value_initialized<COMMAND_RPC_GET_HEIGHT::response>();
-    m_daemon_rpc_mutex.lock();
-    bool ok = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/getheight", req, res, m_http_client);
-    m_daemon_rpc_mutex.unlock();
-    // XXX: DRY violation. copy-pasted from simplewallet.cpp:interpret_rpc_response()
-    if (ok)
+  // XXX: DRY violation. copy-pasted from simplewallet.cpp:get_daemon_blockchain_height()
+  //      consider to move it from simplewallet to wallet2 ?
+  COMMAND_RPC_GET_HEIGHT::request req;
+  COMMAND_RPC_GET_HEIGHT::response res = boost::value_initialized<COMMAND_RPC_GET_HEIGHT::response>();
+  m_daemon_rpc_mutex.lock();
+  bool ok = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/getheight", req, res, m_http_client);
+  m_daemon_rpc_mutex.unlock();
+  // XXX: DRY violation. copy-pasted from simplewallet.cpp:interpret_rpc_response()
+  if (ok)
+  {
+    if (res.status == CORE_RPC_STATUS_BUSY)
     {
-      if (res.status == CORE_RPC_STATUS_BUSY)
-      {
-        err = "daemon is busy. Please try again later.";
-      }
-      else if (res.status != CORE_RPC_STATUS_OK)
-      {
-        err = res.status;
-      }
+      err = "daemon is busy. Please try again later.";
     }
-    else
+    else if (res.status != CORE_RPC_STATUS_OK)
     {
-      err = "possibly lost connection to daemon";
+      err = res.status;
     }
-    return res.height;
+  }
+  else
+  {
+    err = "possibly lost connection to daemon";
+  }
+  return res.height;
 }
 
 void wallet2::set_tx_note(const crypto::hash &txid, const std::string &note)

From a7882da2f6a80d732f6b2965a1a62e6976f7e916 Mon Sep 17 00:00:00 2001
From: Ilya Kitaev <mbg033@gmail.com>
Date: Tue, 27 Sep 2016 23:45:03 +0300
Subject: [PATCH 06/11] libwallet_api: tests: compilation errors fixed

---
 tests/libwallet_api_tests/main.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/libwallet_api_tests/main.cpp b/tests/libwallet_api_tests/main.cpp
index 7cba5b8b0..0b9bc4aa5 100644
--- a/tests/libwallet_api_tests/main.cpp
+++ b/tests/libwallet_api_tests/main.cpp
@@ -960,7 +960,7 @@ TEST_F(WalletTest2, WalletCallbackNewBlock)
     // make sure testnet daemon is running
     ASSERT_TRUE(wallet_src->init(TESTNET_DAEMON_ADDRESS, 0));
     ASSERT_TRUE(wallet_src->refresh());
-    uint64_t bc1 = wallet_src->currentBlockChainHeight();
+    uint64_t bc1 = wallet_src->blockChainHeight();
     std::cout << "** Block height: " << bc1 << std::endl;
 
 
@@ -974,7 +974,7 @@ TEST_F(WalletTest2, WalletCallbackNewBlock)
     std::cerr << "TEST: newblock lock acquired...\n";
     ASSERT_TRUE(wallet_listener->newblock_triggered);
     ASSERT_TRUE(wallet_listener->update_triggered);
-    uint64_t bc2 = wallet_src->currentBlockChainHeight();
+    uint64_t bc2 = wallet_src->blockChainHeight();
     std::cout << "** Block height: " << bc2 << std::endl;
     ASSERT_TRUE(bc2 > bc1);
     wmgr->closeWallet(wallet_src);

From 15c0882f4e00a31c8773f4de66ec06e6a3fd469c Mon Sep 17 00:00:00 2001
From: Ilya Kitaev <mbg033@gmail.com>
Date: Tue, 27 Sep 2016 23:47:50 +0300
Subject: [PATCH 07/11] libwallet_api: tests: test fixed according
 implementation

---
 tests/libwallet_api_tests/main.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/tests/libwallet_api_tests/main.cpp b/tests/libwallet_api_tests/main.cpp
index 0b9bc4aa5..dfd380f53 100644
--- a/tests/libwallet_api_tests/main.cpp
+++ b/tests/libwallet_api_tests/main.cpp
@@ -973,7 +973,6 @@ TEST_F(WalletTest2, WalletCallbackNewBlock)
     wallet_listener->cv_newblock.wait_for(lock, wait_for);
     std::cerr << "TEST: newblock lock acquired...\n";
     ASSERT_TRUE(wallet_listener->newblock_triggered);
-    ASSERT_TRUE(wallet_listener->update_triggered);
     uint64_t bc2 = wallet_src->blockChainHeight();
     std::cout << "** Block height: " << bc2 << std::endl;
     ASSERT_TRUE(bc2 > bc1);

From aef92f27d91ccc4ebca64e7dc84103cbc2e9d8a9 Mon Sep 17 00:00:00 2001
From: Ilya Kitaev <mbg033@gmail.com>
Date: Wed, 28 Sep 2016 00:02:35 +0300
Subject: [PATCH 08/11] libwallet_api: tests: fixed WalletCallbackReceived test

---
 tests/libwallet_api_tests/main.cpp | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/tests/libwallet_api_tests/main.cpp b/tests/libwallet_api_tests/main.cpp
index dfd380f53..87e0cc935 100644
--- a/tests/libwallet_api_tests/main.cpp
+++ b/tests/libwallet_api_tests/main.cpp
@@ -913,16 +913,17 @@ TEST_F(WalletTest2, WalletCallbackSent)
 TEST_F(WalletTest2, WalletCallbackReceived)
 {
 
-    Bitmonero::Wallet * wallet_src = wmgr->openWallet(TESTNET_WALLET5_NAME, TESTNET_WALLET_PASS, true);
+    Bitmonero::Wallet * wallet_src = wmgr->openWallet(CURRENT_SRC_WALLET, TESTNET_WALLET_PASS, true);
     // make sure testnet daemon is running
     ASSERT_TRUE(wallet_src->init(TESTNET_DAEMON_ADDRESS, 0));
     ASSERT_TRUE(wallet_src->refresh());
-    std::cout << "** Balance: " << wallet_src->displayAmount(wallet_src->balance()) <<  std::endl;
+    std::cout << "** Balance src1: " << wallet_src->displayAmount(wallet_src->balance()) <<  std::endl;
 
     Bitmonero::Wallet * wallet_dst = wmgr->openWallet(CURRENT_DST_WALLET, TESTNET_WALLET_PASS, true);
     ASSERT_TRUE(wallet_dst->init(TESTNET_DAEMON_ADDRESS, 0));
     ASSERT_TRUE(wallet_dst->refresh());
     uint64_t balance = wallet_dst->balance();
+    std::cout << "** Balance dst1: " << wallet_dst->displayAmount(wallet_dst->balance()) <<  std::endl;
     MyWalletListener * wallet_dst_listener = new MyWalletListener(wallet_dst);
 
     uint64_t amount = AMOUNT_1XMR * 5;
@@ -944,7 +945,10 @@ TEST_F(WalletTest2, WalletCallbackReceived)
     std::cerr << "TEST: receive lock acquired...\n";
     ASSERT_TRUE(wallet_dst_listener->receive_triggered);
     ASSERT_TRUE(wallet_dst_listener->update_triggered);
-    std::cout << "** Balance: " << wallet_dst->displayAmount(wallet_src->balance()) <<  std::endl;
+
+    std::cout << "** Balance src2: " << wallet_dst->displayAmount(wallet_src->balance()) <<  std::endl;
+    std::cout << "** Balance dst2: " << wallet_dst->displayAmount(wallet_dst->balance()) <<  std::endl;
+
     ASSERT_TRUE(wallet_dst->balance() > balance);
 
     wmgr->closeWallet(wallet_src);

From a6688200fb3f2608b80a419f8231647581a81ca0 Mon Sep 17 00:00:00 2001
From: Ilya Kitaev <mbg033@gmail.com>
Date: Wed, 28 Sep 2016 00:31:21 +0300
Subject: [PATCH 09/11] libwallet_api: explicitly return 0 in
 Wallet::daemonBlockChainHeight() on error

---
 src/wallet/api/wallet.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 9a001abf3..e249080b1 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -428,8 +428,10 @@ uint64_t WalletImpl::daemonBlockChainHeight() const
     uint64_t result = m_wallet->get_daemon_blockchain_height(err);
     if (!err.empty()) {
         LOG_ERROR(__FUNCTION__ << ": " << err);
+        result = 0;
         m_errorString = err;
         m_status = Status_Error;
+
     } else {
         m_status = Status_Ok;
         m_errorString = "";

From 25e5efc238bc72c0c71ae2e125288e080caa7efd Mon Sep 17 00:00:00 2001
From: Ilya Kitaev <mbg033@gmail.com>
Date: Wed, 28 Sep 2016 00:35:10 +0300
Subject: [PATCH 10/11] libwallet_api: Wallet::setAutoRefreshInterval sanity
 check

---
 src/wallet/api/wallet.cpp | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index e249080b1..eefb49e95 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -47,6 +47,8 @@ namespace {
     // copy-pasted from simplewallet
     static const size_t DEFAULT_MIXIN = 4;
     static const int    DEFAULT_REFRESH_INTERVAL_MILLIS = 1000 * 10;
+    // limit maximum refresh interval as one minute
+    static const int    MAX_REFRESH_INTERVAL_MILLIS = 1000 * 60 * 1;
 }
 
 struct Wallet2CallbackImpl : public tools::i_wallet2_callback
@@ -455,7 +457,13 @@ void WalletImpl::refreshAsync()
 
 void WalletImpl::setAutoRefreshInterval(int millis)
 {
-    m_refreshIntervalMillis = millis;
+    if (millis > MAX_REFRESH_INTERVAL_MILLIS) {
+        LOG_ERROR(__FUNCTION__<< ": invalid refresh interval " << millis
+                  << " ms, maximum allowed is " << MAX_REFRESH_INTERVAL_MILLIS << " ms");
+        m_refreshIntervalMillis = MAX_REFRESH_INTERVAL_MILLIS;
+    } else {
+        m_refreshIntervalMillis = millis;
+    }
 }
 
 int WalletImpl::autoRefreshInterval() const

From 2dacb193d0bc348003816cd660b4ac85f3ca21d0 Mon Sep 17 00:00:00 2001
From: Ilya Kitaev <mbg033@gmail.com>
Date: Wed, 28 Sep 2016 00:39:06 +0300
Subject: [PATCH 11/11] wallet2: wallet2::get_daemon_blockchain_height() clean
 error message on success

---
 src/wallet/wallet2.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 80513b519..ed4ab93de 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -4073,6 +4073,10 @@ uint64_t wallet2::get_daemon_blockchain_height(string &err)
     {
       err = res.status;
     }
+    else // success, cleaning up error message
+    {
+      err = "";
+    }
   }
   else
   {