diff --git a/contrib/epee/include/net/http_client.h b/contrib/epee/include/net/http_client.h
index a54318ebb..c5aeb9251 100644
--- a/contrib/epee/include/net/http_client.h
+++ b/contrib/epee/include/net/http_client.h
@@ -263,7 +263,6 @@ using namespace std;
 			blocked_mode_client m_net_client;
 			std::string m_host_buff;
 			std::string m_port;
-			unsigned int m_timeout;
 			std::string m_header_cache;
 			http_response_info m_response_info;
 			size_t m_len_in_summary;
@@ -276,23 +275,43 @@ using namespace std;
 			critical_section m_lock;
 
 		public:
-			void set_host_name(const std::string& name)
+			explicit http_simple_client()
+				: i_target_handler()
+				, m_net_client()
+				, m_host_buff()
+				, m_port()
+				, m_header_cache()
+				, m_response_info()
+				, m_len_in_summary(0)
+				, m_len_in_remain(0)
+				, m_pcontent_encoding_handler(nullptr)
+				, m_state()
+				, m_chunked_state()
+				, m_chunked_cache()
+				, m_lock()
+			{}
+
+			bool set_server(const std::string& address)
+			{
+				http::url_content parsed{};
+				const bool r = parse_url(address, parsed);
+				CHECK_AND_ASSERT_MES(r, false, "failed to parse url: " << address);
+				set_server(std::move(parsed.host), std::to_string(parsed.port));
+				return true;
+			}
+
+			void set_server(std::string host, std::string port)
 			{
 				CRITICAL_REGION_LOCAL(m_lock);
-				m_host_buff = name;
+				disconnect();
+				m_host_buff = std::move(host);
+				m_port = std::move(port);
 			}
-      bool connect(const std::string& host, int port, unsigned int timeout)
-      {
-        return connect(host, std::to_string(port), timeout);
-      }
-      bool connect(const std::string& host, const std::string& port, unsigned int timeout)
+
+      bool connect(std::chrono::milliseconds timeout)
       {
         CRITICAL_REGION_LOCAL(m_lock);
-        m_host_buff = host;
-        m_port = port;
-        m_timeout = timeout;
-
-        return m_net_client.connect(host,  port, timeout, timeout);
+        return m_net_client.connect(m_host_buff, m_port, timeout);
       }
 			//---------------------------------------------------------------------------
 			bool disconnect()
@@ -316,20 +335,20 @@ using namespace std;
 			}
 			//---------------------------------------------------------------------------
 			inline 
-				bool invoke_get(const std::string& uri, const std::string& body = std::string(), const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list())
+				bool invoke_get(const std::string& uri, std::chrono::milliseconds timeout, const std::string& body = std::string(), const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list())
 			{
 					CRITICAL_REGION_LOCAL(m_lock);
-					return invoke(uri, "GET", body, ppresponse_info, additional_params);
+					return invoke(uri, "GET", body, timeout, ppresponse_info, additional_params);
 			}
 
 			//---------------------------------------------------------------------------
-			inline bool invoke(const std::string& uri, const std::string& method, const std::string& body, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list())
+			inline bool invoke(const std::string& uri, const std::string& method, const std::string& body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list())
 			{
 				CRITICAL_REGION_LOCAL(m_lock);
 				if(!is_connected())
 				{
 					MDEBUG("Reconnecting...");
-					if(!connect(m_host_buff, m_port, m_timeout))
+					if(!connect(timeout))
 					{
 						MDEBUG("Failed to connect to " << m_host_buff << ":" << m_port);
 						return false;
@@ -347,27 +366,27 @@ using namespace std;
 				req_buff += "\r\n";
 				//--
 
-				bool res = m_net_client.send(req_buff);
+				bool res = m_net_client.send(req_buff, timeout);
 				CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND");
 				if(body.size())
-					res = m_net_client.send(body);
+					res = m_net_client.send(body, timeout);
 				CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND");
 
 				if(ppresponse_info)
 					*ppresponse_info = &m_response_info;
 
 				m_state = reciev_machine_state_header;
-				return handle_reciev();
+				return handle_reciev(timeout);
 			}
 			//---------------------------------------------------------------------------
-			inline bool invoke_post(const std::string& uri, const std::string& body,  const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list())
+			inline bool invoke_post(const std::string& uri, const std::string& body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list())
 			{
 				CRITICAL_REGION_LOCAL(m_lock);
-				return invoke(uri, "POST", body, ppresponse_info, additional_params);
+				return invoke(uri, "POST", body, timeout, ppresponse_info, additional_params);
 			}
 		private: 
 			//---------------------------------------------------------------------------
-			inline bool handle_reciev()
+			inline bool handle_reciev(std::chrono::milliseconds timeout)
 			{
 				CRITICAL_REGION_LOCAL(m_lock);
 				bool keep_handling = true;
@@ -377,7 +396,7 @@ using namespace std;
 				{
 					if(need_more_data)
 					{
-						if(!m_net_client.recv(recv_buffer))
+						if(!m_net_client.recv(recv_buffer, timeout))
 						{
 							MERROR("Unexpected recv fail");
 							m_state = reciev_machine_state_error;
@@ -878,33 +897,6 @@ using namespace std;
 				return true;
 			}
 		};
-
-
-
-    /************************************************************************/
-    /*                                                                      */
-    /************************************************************************/
-  //inline 
-    template<class t_transport>
-    bool invoke_request(const std::string& url, t_transport& tr, unsigned int timeout, const http_response_info** ppresponse_info, const std::string& method = "GET", const std::string& body = std::string(), const fields_list& additional_params = fields_list())
-    {
-      http::url_content u_c;
-      bool res = parse_url(url, u_c);
-
-      if(!tr.is_connected() && !u_c.host.empty())
-      {
-        CHECK_AND_ASSERT_MES(res, false, "failed to parse url: " << url);
-
-        if(!u_c.port)
-          u_c.port = 80;//default for http
-
-        res = tr.connect(u_c.host, static_cast<int>(u_c.port), timeout);
-        CHECK_AND_ASSERT_MES(res, false, "failed to connect " << u_c.host << ":" << u_c.port);
-      }
-
-      return tr.invoke(u_c.uri, method, body, ppresponse_info, additional_params);
-    }
-
 	}
 }
 }
diff --git a/contrib/epee/include/net/http_client_abstract_invoke.h b/contrib/epee/include/net/http_client_abstract_invoke.h
deleted file mode 100644
index 9b6ab4db8..000000000
--- a/contrib/epee/include/net/http_client_abstract_invoke.h
+++ /dev/null
@@ -1,101 +0,0 @@
-
-// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
-// All rights reserved.
-// 
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * 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.
-// * Neither the name of the Andrey N. Sabelnikov 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 OWNER  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.
-// 
-
-#pragma once
-#include "storages/serializeble_struct_helper.h"
-
-#undef MONERO_DEFAULT_LOG_CATEGORY
-#define MONERO_DEFAULT_LOG_CATEGORY "net.http"
-
-namespace epee
-{
-  namespace net_utils
-  {
-    namespace http
-    {
-      template<class TArg, class TResult, class TTransport>
-      bool invoke_http_json_remote_command(const std::string& url, TArg& out_struct, TResult& result_struct, TTransport& transport, unsigned int timeout = 5000, const std::string& method = "GET")
-      {
-        std::string req_param;
-        StorageNamed::InMemStorageSpace::json::store_t_to_json(out_struct, req_param);
-
-        const http_response_info* pri = NULL;
-        if(!invoke_request(url, transport, timeout, &pri, method, req_param))
-        {
-          LOG_PRINT_L1("Failed to invoke http request to  " << url);
-          return false;
-        }
-
-        if(!pri->m_response_code)
-        {
-          LOG_PRINT_L1("Failed to invoke http request to  " << url << ", internal error (null response ptr)");
-          return false;
-        }
-
-        if(pri->m_response_code != 200)
-        {
-          LOG_PRINT_L1("Failed to invoke http request to  " << url << ", wrong response code: " << pri->m_response_code);
-          return false;
-        }
-
-        return StorageNamed::InMemStorageSpace::json::load_t_from_json(result_struct, pri->m_body);
-      }
-
-
-
-      template<class TArg, class TResult, class TTransport>
-      bool invoke_http_bin_remote_command(const std::string& url, TArg& out_struct, TResult& result_struct, TTransport& transport, unsigned int timeout = 5000, const std::string& method = "GET")
-      {
-        std::string req_param;
-        epee::StorageNamed::save_struct_as_storage_to_buff(out_struct, req_param); 
-
-        const http_response_info* pri = NULL;
-        if(!invoke_request(url, transport, timeout, &pri, method, req_param))
-        {
-          LOG_PRINT_L1("Failed to invoke http request to  " << url);
-          return false;
-        }
-
-        if(!pri->m_response_code)
-        {
-          LOG_PRINT_L1("Failed to invoke http request to  " << url << ", internal error (null response ptr)");
-          return false;
-        }
-
-        if(pri->m_response_code != 200)
-        {
-          LOG_PRINT_L1("Failed to invoke http request to  " << url << ", wrong response code: " << pri->m_response_code);
-          return false;
-        }
-
-        return epee::StorageNamed::load_struct_from_storage_buff(result_struct, pri->m_body); 
-      }
-
-
-    }
-  }
-}
diff --git a/contrib/epee/include/net/net_helper.h b/contrib/epee/include/net/net_helper.h
index 22cea122f..432169990 100644
--- a/contrib/epee/include/net/net_helper.h
+++ b/contrib/epee/include/net/net_helper.h
@@ -37,6 +37,7 @@
 #include <ostream>
 #include <string>
 #include <boost/asio.hpp>
+#include <boost/asio/steady_timer.hpp>
 #include <boost/preprocessor/selection/min.hpp>
 #include <boost/lambda/bind.hpp>
 #include <boost/lambda/lambda.hpp>
@@ -98,7 +99,7 @@ namespace net_utils
 			// No deadline is required until the first socket operation is started. We
 			// set the deadline to positive infinity so that the actor takes no action
 			// until a specific deadline is set.
-			m_deadline.expires_at(boost::posix_time::pos_infin);
+			m_deadline.expires_at(std::chrono::steady_clock::time_point::max());
 
 			// Start the persistent actor that checks for deadline expiry.
 			check_deadline();
@@ -111,26 +112,16 @@ namespace net_utils
 			shutdown();
 		}
 
-		inline void set_recv_timeout(int reciev_timeout)
-		{
-			m_reciev_timeout = reciev_timeout;
-		}
-
     inline
-      bool connect(const std::string& addr, int port, unsigned int connect_timeout, unsigned int reciev_timeout, const std::string& bind_ip = "0.0.0.0")
+      bool connect(const std::string& addr, int port, std::chrono::milliseconds timeout, const std::string& bind_ip = "0.0.0.0")
     {
-      return connect(addr, std::to_string(port), connect_timeout, reciev_timeout, bind_ip);
+      return connect(addr, std::to_string(port), timeout, bind_ip);
     }
 
     inline
-			bool connect(const std::string& addr, const std::string& port, unsigned int connect_timeout, unsigned int reciev_timeout, const std::string& bind_ip = "0.0.0.0")
+			bool connect(const std::string& addr, const std::string& port, std::chrono::milliseconds timeout, const std::string& bind_ip = "0.0.0.0")
 		{
-			m_connect_timeout = connect_timeout;
-			m_reciev_timeout = reciev_timeout;
       m_connected = false;
-			if(!m_reciev_timeout)
-				m_reciev_timeout = m_connect_timeout;
-
 			try
 			{
 				m_socket.close();
@@ -164,7 +155,7 @@ namespace net_utils
 				}
 
 				
-				m_deadline.expires_from_now(boost::posix_time::milliseconds(m_connect_timeout));
+				m_deadline.expires_from_now(timeout);
 
 
 				boost::system::error_code ec = boost::asio::error::would_block;
@@ -179,7 +170,7 @@ namespace net_utils
 				if (!ec && m_socket.is_open())
 				{
 					m_connected = true;
-					m_deadline.expires_at(boost::posix_time::pos_infin);
+					m_deadline.expires_at(std::chrono::steady_clock::time_point::max());
 					return true;
 				}else
 				{
@@ -231,12 +222,12 @@ namespace net_utils
 
 
 		inline 
-		bool send(const std::string& buff)
+		bool send(const std::string& buff, std::chrono::milliseconds timeout)
 		{
 
 			try
 			{
-				m_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout));
+				m_deadline.expires_from_now(timeout);
 
 				// Set up the variable that receives the result of the asynchronous
 				// operation. The error code is set to would_block to signal that the
@@ -264,7 +255,7 @@ namespace net_utils
 					return false;
 				}else
 				{
-					m_deadline.expires_at(boost::posix_time::pos_infin);
+					m_deadline.expires_at(std::chrono::steady_clock::time_point::max());
 				}
 			}
 
@@ -322,7 +313,7 @@ namespace net_utils
 					return false;
 				}else
 				{
-					m_deadline.expires_at(boost::posix_time::pos_infin);
+					m_deadline.expires_at(std::chrono::steady_clock::time_point::max());
 				}
 			}
 
@@ -350,7 +341,7 @@ namespace net_utils
 		}
 
 		inline 
-		bool recv(std::string& buff)
+		bool recv(std::string& buff, std::chrono::milliseconds timeout)
 		{
 
 			try
@@ -358,7 +349,7 @@ namespace net_utils
 				// Set a deadline for the asynchronous operation. Since this function uses
 				// a composed operation (async_read_until), the deadline applies to the
 				// entire operation, rather than individual reads from the socket.
-				m_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout));
+				m_deadline.expires_from_now(timeout);
 
 				// Set up the variable that receives the result of the asynchronous
 				// operation. The error code is set to would_block to signal that the
@@ -404,7 +395,7 @@ namespace net_utils
 				}else
 				{
                     MTRACE("READ ENDS: Success. bytes_tr: " << bytes_transfered);
-					m_deadline.expires_at(boost::posix_time::pos_infin);
+					m_deadline.expires_at(std::chrono::steady_clock::time_point::max());
 				}
 
 				/*if(!bytes_transfered)
@@ -432,7 +423,7 @@ namespace net_utils
 
 		}
 
-		inline bool recv_n(std::string& buff, int64_t sz)
+		inline bool recv_n(std::string& buff, int64_t sz, std::chrono::milliseconds timeout)
 		{
 
 			try
@@ -440,7 +431,7 @@ namespace net_utils
 				// Set a deadline for the asynchronous operation. Since this function uses
 				// a composed operation (async_read_until), the deadline applies to the
 				// entire operation, rather than individual reads from the socket.
-				m_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout));
+				m_deadline.expires_from_now(timeout);
 
 				// Set up the variable that receives the result of the asynchronous
 				// operation. The error code is set to would_block to signal that the
@@ -477,7 +468,7 @@ namespace net_utils
 					return false;
 				}else
 				{
-					m_deadline.expires_at(boost::posix_time::pos_infin);
+					m_deadline.expires_at(std::chrono::steady_clock::time_point::max());
 				}
 
 				if(bytes_transfered != buff.size())
@@ -539,7 +530,7 @@ namespace net_utils
 			// Check whether the deadline has passed. We compare the deadline against
 			// the current time since a new asynchronous operation may have moved the
 			// deadline before this actor had a chance to run.
-			if (m_deadline.expires_at() <= boost::asio::deadline_timer::traits_type::now())
+			if (m_deadline.expires_at() <= std::chrono::steady_clock::now())
 			{
 				// The deadline has passed. The socket is closed so that any outstanding
 				// asynchronous operations are cancelled. This allows the blocked
@@ -550,7 +541,7 @@ namespace net_utils
 
 				// There is no longer an active deadline. The expiry is set to positive
 				// infinity so that the actor takes no action until a new deadline is set.
-				m_deadline.expires_at(boost::posix_time::pos_infin);
+				m_deadline.expires_at(std::chrono::steady_clock::time_point::max());
 			}
 
 			// Put the actor back to sleep.
@@ -562,11 +553,9 @@ namespace net_utils
 	protected:
 		boost::asio::io_service m_io_service;
 		boost::asio::ip::tcp::socket m_socket;
-		int m_connect_timeout;
-		int m_reciev_timeout;
 		bool m_initialized;
 		bool m_connected;
-		boost::asio::deadline_timer m_deadline;
+		boost::asio::steady_timer m_deadline;
 		volatile uint32_t m_shutdowned;
 	};
 
diff --git a/contrib/epee/include/storages/http_abstract_invoke.h b/contrib/epee/include/storages/http_abstract_invoke.h
index 00ee8a4ad..36177c7e0 100644
--- a/contrib/epee/include/storages/http_abstract_invoke.h
+++ b/contrib/epee/include/storages/http_abstract_invoke.h
@@ -35,28 +35,28 @@ namespace epee
   namespace net_utils
   {
     template<class t_request, class t_response, class t_transport>
-    bool invoke_http_json_remote_command2(const std::string& url, t_request& out_struct, t_response& result_struct, t_transport& transport, unsigned int timeout = 5000, const std::string& method = "GET")
+    bool invoke_http_json(const std::string& uri, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const std::string& method = "GET")
     {
       std::string req_param;
       if(!serialization::store_t_to_json(out_struct, req_param))
         return false;
 
       const http::http_response_info* pri = NULL;
-      if(!invoke_request(url, transport, timeout, &pri, method, req_param))
+      if(!transport.invoke(uri, method, req_param, timeout, std::addressof(pri)))
       {
-        LOG_PRINT_L1("Failed to invoke http request to  " << url);
+        LOG_PRINT_L1("Failed to invoke http request to  " << uri);
         return false;
       }
 
-      if(!pri->m_response_code)
+      if(!pri)
       {
-        LOG_PRINT_L1("Failed to invoke http request to  " << url << ", internal error (null response ptr)");
+        LOG_PRINT_L1("Failed to invoke http request to  " << uri << ", internal error (null response ptr)");
         return false;
       }
 
       if(pri->m_response_code != 200)
       {
-        LOG_PRINT_L1("Failed to invoke http request to  " << url << ", wrong response code: " << pri->m_response_code);
+        LOG_PRINT_L1("Failed to invoke http request to  " << uri << ", wrong response code: " << pri->m_response_code);
         return false;
       }
 
@@ -66,28 +66,28 @@ namespace epee
 
 
     template<class t_request, class t_response, class t_transport>
-    bool invoke_http_bin_remote_command2(const std::string& url, t_request& out_struct, t_response& result_struct, t_transport& transport, unsigned int timeout = 5000, const std::string& method = "GET")
+    bool invoke_http_bin(const std::string& uri, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const std::string& method = "GET")
     {
       std::string req_param;
       if(!serialization::store_t_to_binary(out_struct, req_param))
         return false;
 
       const http::http_response_info* pri = NULL;
-      if(!invoke_request(url, transport, timeout, &pri, method, req_param))
+      if(!transport.invoke(uri, method, req_param, timeout, std::addressof(pri)))
       {
-        LOG_PRINT_L1("Failed to invoke http request to  " << url);
+        LOG_PRINT_L1("Failed to invoke http request to  " << uri);
         return false;
       }
 
-      if(!pri->m_response_code)
+      if(!pri)
       {
-        LOG_PRINT_L1("Failed to invoke http request to  " << url << ", internal error (null response ptr)");
+        LOG_PRINT_L1("Failed to invoke http request to  " << uri << ", internal error (null response ptr)");
         return false;
       }
 
       if(pri->m_response_code != 200)
       {
-        LOG_PRINT_L1("Failed to invoke http request to  " << url << ", wrong response code: " << pri->m_response_code);
+        LOG_PRINT_L1("Failed to invoke http request to  " << uri << ", wrong response code: " << pri->m_response_code);
         return false;
       }
 
@@ -95,15 +95,15 @@ namespace epee
     }
 
     template<class t_request, class t_response, class t_transport>
-    bool invoke_http_json_rpc(const std::string& url, const std::string& method_name, t_request& out_struct, t_response& result_struct, t_transport& transport, unsigned int timeout = 5000, const std::string& http_method = "GET", const std::string& req_id = "0")
+    bool invoke_http_json_rpc(const std::string& uri, std::string method_name, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const std::string& http_method = "GET", const std::string& req_id = "0")
     {
       epee::json_rpc::request<t_request> req_t = AUTO_VAL_INIT(req_t);
       req_t.jsonrpc = "2.0";
       req_t.id = req_id;
-      req_t.method = method_name;
+      req_t.method = std::move(method_name);
       req_t.params = out_struct;
       epee::json_rpc::response<t_response, epee::json_rpc::error> resp_t = AUTO_VAL_INIT(resp_t);
-      if(!epee::net_utils::invoke_http_json_remote_command2(url, req_t, resp_t, transport, timeout, http_method))
+      if(!epee::net_utils::invoke_http_json(uri, req_t, resp_t, transport, timeout, http_method))
       {
         return false;
       }
@@ -117,9 +117,9 @@ namespace epee
     }
 
     template<class t_command, class t_transport>
-    bool invoke_http_json_rpc(const std::string& url, typename t_command::request& out_struct, typename t_command::response& result_struct, t_transport& transport, unsigned int timeout = 5000, const std::string& http_method = "GET", const std::string& req_id = "0")
+    bool invoke_http_json_rpc(const std::string& uri, typename t_command::request& out_struct, typename t_command::response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const std::string& http_method = "GET", const std::string& req_id = "0")
     {
-      return invoke_http_json_rpc(url, t_command::methodname(), out_struct, result_struct, transport, timeout, http_method, req_id);
+      return invoke_http_json_rpc(uri, t_command::methodname(), out_struct, result_struct, transport, timeout, http_method, req_id);
     }
 
   }
diff --git a/src/common/http_connection.h b/src/common/http_connection.h
index 156474cdd..8a786361a 100644
--- a/src/common/http_connection.h
+++ b/src/common/http_connection.h
@@ -28,6 +28,7 @@
 
 #pragma once
 
+#include <chrono>
 #include "string_tools.h"
 #include "net/http_client.h"
 
@@ -38,20 +39,16 @@ private:
   epee::net_utils::http::http_simple_client * mp_http_client;
   bool m_ok;
 public:
-  static unsigned int const TIMEOUT = 200000;
+  static constexpr std::chrono::seconds TIMEOUT()
+  {
+    return std::chrono::minutes(3) + std::chrono::seconds(30);
+  }
 
-  t_http_connection(
-      epee::net_utils::http::http_simple_client * p_http_client
-    , uint32_t ip
-    , uint16_t port
-    )
+  t_http_connection(epee::net_utils::http::http_simple_client* p_http_client)
     : mp_http_client(p_http_client)
     , m_ok(false)
   {
-    // TODO fix http client so that it accepts properly typed arguments
-    std::string ip_str = epee::string_tools::get_ip_string_from_int32(ip);
-    std::string port_str = boost::lexical_cast<std::string>(port);
-    m_ok = mp_http_client->connect(ip_str, port_str, TIMEOUT);
+    m_ok = mp_http_client->connect(TIMEOUT());
   }
 
   ~t_http_connection()
diff --git a/src/common/rpc_client.h b/src/common/rpc_client.h
index 9c0036198..f5ecc8b50 100644
--- a/src/common/rpc_client.h
+++ b/src/common/rpc_client.h
@@ -34,7 +34,6 @@
 #include "storages/http_abstract_invoke.h"
 #include "net/http_client.h"
 #include "string_tools.h"
-#include <boost/lexical_cast.hpp>
 
 namespace tools
 {
@@ -42,27 +41,16 @@ namespace tools
   {
   private:
     epee::net_utils::http::http_simple_client m_http_client;
-    uint32_t m_ip;
-    uint16_t m_port;
   public:
     t_rpc_client(
         uint32_t ip
       , uint16_t port
       )
       : m_http_client{}
-      , m_ip{ip}
-      , m_port{port}
-    {}
-
-    std::string build_url(std::string const & relative_url) const
     {
-      std::string result =
-              "http://"
-             + epee::string_tools::get_ip_string_from_int32(m_ip)
-             + ":"
-             + boost::lexical_cast<std::string>(m_port)
-             + relative_url;
-      return result;
+      m_http_client.set_server(
+        epee::string_tools::get_ip_string_from_int32(ip), std::to_string(port)
+      );
     }
 
     template <typename T_req, typename T_res>
@@ -72,8 +60,7 @@ namespace tools
       , std::string const & method_name
       )
     {
-      std::string rpc_url = build_url("/json_rpc");
-      t_http_connection connection(&m_http_client, m_ip, m_port);
+      t_http_connection connection(&m_http_client);
 
       bool ok = connection.is_open();
       if (!ok)
@@ -81,7 +68,7 @@ namespace tools
         fail_msg_writer() << "Couldn't connect to daemon";
         return false;
       }
-      ok = ok && epee::net_utils::invoke_http_json_rpc(rpc_url, method_name, req, res, m_http_client);
+      ok = ok && epee::net_utils::invoke_http_json_rpc("/json_rpc", method_name, req, res, m_http_client, t_http_connection::TIMEOUT());
       if (!ok)
       {
         fail_msg_writer() << "Daemon request failed";
@@ -101,11 +88,10 @@ namespace tools
       , std::string const & fail_msg
       )
     {
-      std::string rpc_url = build_url("/json_rpc");
-      t_http_connection connection(&m_http_client, m_ip, m_port);
+      t_http_connection connection(&m_http_client);
 
       bool ok = connection.is_open();
-      ok = ok && epee::net_utils::invoke_http_json_rpc(rpc_url, method_name, req, res, m_http_client);
+      ok = ok && epee::net_utils::invoke_http_json_rpc("/json_rpc", method_name, req, res, m_http_client, t_http_connection::TIMEOUT());
       if (!ok)
       {
         fail_msg_writer() << "Couldn't connect to daemon";
@@ -130,11 +116,10 @@ namespace tools
       , std::string const & fail_msg
       )
     {
-      std::string rpc_url = build_url(relative_url);
-      t_http_connection connection(&m_http_client, m_ip, m_port);
+      t_http_connection connection(&m_http_client);
 
       bool ok = connection.is_open();
-      ok = ok && epee::net_utils::invoke_http_json_remote_command2(rpc_url, req, res, m_http_client);
+      ok = ok && epee::net_utils::invoke_http_json(relative_url, req, res, m_http_client, t_http_connection::TIMEOUT());
       if (!ok)
       {
         fail_msg_writer() << "Couldn't connect to daemon";
@@ -153,7 +138,7 @@ namespace tools
 
     bool check_connection()
     {
-      t_http_connection connection(&m_http_client, m_ip, m_port);
+      t_http_connection connection(&m_http_client);
       return connection.is_open();
     }
   };
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index e006cf5f3..c7487cae8 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -1163,6 +1163,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
   }
   catch (const std::exception &e) { }
 
+  m_http_client.set_server(m_wallet->get_daemon_address());
   m_wallet->callback(this);
   return true;
 }
@@ -1560,7 +1561,7 @@ bool simple_wallet::start_mining(const std::vector<std::string>& args)
   }
 
   COMMAND_RPC_START_MINING::response res;
-  bool r = net_utils::invoke_http_json_remote_command2(m_wallet->get_daemon_address() + "/start_mining", req, res, m_http_client);
+  bool r = net_utils::invoke_http_json("/start_mining", req, res, m_http_client);
   std::string err = interpret_rpc_response(r, res.status);
   if (err.empty())
     success_msg_writer() << tr("Mining started in daemon");
@@ -1577,7 +1578,7 @@ bool simple_wallet::stop_mining(const std::vector<std::string>& args)
   assert(m_wallet);
   COMMAND_RPC_STOP_MINING::request req;
   COMMAND_RPC_STOP_MINING::response res;
-  bool r = net_utils::invoke_http_json_remote_command2(m_wallet->get_daemon_address() + "/stop_mining", req, res, m_http_client);
+  bool r = net_utils::invoke_http_json("/stop_mining", req, res, m_http_client);
   std::string err = interpret_rpc_response(r, res.status);
   if (err.empty())
     success_msg_writer() << tr("Mining stopped in daemon");
@@ -1594,7 +1595,7 @@ bool simple_wallet::save_bc(const std::vector<std::string>& args)
   assert(m_wallet);
   COMMAND_RPC_SAVE_BC::request req;
   COMMAND_RPC_SAVE_BC::response res;
-  bool r = net_utils::invoke_http_json_remote_command2(m_wallet->get_daemon_address() + "/save_bc", req, res, m_http_client);
+  bool r = net_utils::invoke_http_json("/save_bc", req, res, m_http_client);
   std::string err = interpret_rpc_response(r, res.status);
   if (err.empty())
     success_msg_writer() << tr("Blockchain saved");
@@ -1883,7 +1884,7 @@ uint64_t simple_wallet::get_daemon_blockchain_height(std::string& err)
 
   COMMAND_RPC_GET_HEIGHT::request req;
   COMMAND_RPC_GET_HEIGHT::response res = boost::value_initialized<COMMAND_RPC_GET_HEIGHT::response>();
-  bool r = net_utils::invoke_http_json_remote_command2(m_wallet->get_daemon_address() + "/getheight", req, res, m_http_client);
+  bool r = net_utils::invoke_http_json("/getheight", req, res, m_http_client);
   err = interpret_rpc_response(r, res.status);
   return res.height;
 }
@@ -1994,7 +1995,7 @@ bool simple_wallet::print_ring_members(const std::vector<tools::wallet2::pending
         req.outputs[j].index = absolute_offsets[j];
       }
       COMMAND_RPC_GET_OUTPUTS_BIN::response res = AUTO_VAL_INIT(res);
-      bool r = net_utils::invoke_http_bin_remote_command2(m_wallet->get_daemon_address() + "/get_outs.bin", req, res, m_http_client);
+      bool r = net_utils::invoke_http_bin("/get_outs.bin", req, res, m_http_client);
       err = interpret_rpc_response(r, res.status);
       if (!err.empty())
       {
@@ -3196,7 +3197,7 @@ bool simple_wallet::check_tx_key(const std::vector<std::string> &args_)
   COMMAND_RPC_GET_TRANSACTIONS::request req;
   COMMAND_RPC_GET_TRANSACTIONS::response res;
   req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid));
-  if (!net_utils::invoke_http_json_remote_command2(m_wallet->get_daemon_address() + "/gettransactions", req, res, m_http_client) ||
+  if (!net_utils::invoke_http_json("/gettransactions", req, res, m_http_client) ||
       (res.txs.size() != 1 && res.txs_as_hex.size() != 1))
   {
     fail_msg_writer() << tr("failed to get transaction from daemon");
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index c1cc5d10d..9e40d2e02 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -646,12 +646,12 @@ string WalletImpl::keysFilename() const
 bool WalletImpl::init(const std::string &daemon_address, uint64_t upper_transaction_size_limit)
 {
     clearStatus();
-    doInit(daemon_address, upper_transaction_size_limit);
+    if (!doInit(daemon_address, upper_transaction_size_limit))
+        return false;
     bool result = this->refresh();
     // enabling background refresh thread
     startRefresh();
     return result;
-
 }
 
 void WalletImpl::initAsync(const string &daemon_address, uint64_t upper_transaction_size_limit)
@@ -1362,9 +1362,10 @@ bool WalletImpl::isNewWallet() const
     return !(blockChainHeight() > 1 || m_recoveringFromSeed || m_rebuildWalletCache) && !watchOnly();
 }
 
-void WalletImpl::doInit(const string &daemon_address, uint64_t upper_transaction_size_limit)
+bool WalletImpl::doInit(const string &daemon_address, uint64_t upper_transaction_size_limit)
 {
-    m_wallet->init(daemon_address, upper_transaction_size_limit);
+    if (!m_wallet->init(daemon_address, upper_transaction_size_limit))
+       return false;
 
     // in case new wallet, this will force fast-refresh (pulling hashes instead of blocks)
     // If daemon isn't synced a calculated block height will be used instead
@@ -1383,8 +1384,7 @@ void WalletImpl::doInit(const string &daemon_address, uint64_t upper_transaction
         this->setTrustedDaemon(false);
         m_refreshIntervalMillis = DEFAULT_REMOTE_NODE_REFRESH_INTERVAL_MILLIS;
     }
-        
-
+    return true;
 }
 
 bool WalletImpl::parse_uri(const std::string &uri, std::string &address, std::string &payment_id, uint64_t &amount, std::string &tx_description, std::string &recipient_name, std::vector<std::string> &unknown_parameters, std::string &error)
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index 16a7f5d95..7daf63e43 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -133,7 +133,7 @@ private:
     bool daemonSynced() const;
     void stopRefresh();
     bool isNewWallet() const;
-    void doInit(const std::string &daemon_address, uint64_t upper_transaction_size_limit);
+    bool doInit(const std::string &daemon_address, uint64_t upper_transaction_size_limit);
 
 
 private:
diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp
index fcb39d1f3..c761cc6d2 100644
--- a/src/wallet/api/wallet_manager.cpp
+++ b/src/wallet/api/wallet_manager.cpp
@@ -43,6 +43,15 @@ namespace epee {
     unsigned int g_test_dbg_lock_sleep = 0;
 }
 
+namespace {
+    template<typename Request, typename Response>
+    bool connect_and_invoke(const std::string& address, const std::string& path, const Request& request, Response& response)
+    {
+        epee::net_utils::http::http_simple_client client{};
+        return client.set_server(address) && epee::net_utils::invoke_http_json(path, request, response, client);
+    }
+}
+
 namespace Monero {
 
 Wallet *WalletManagerImpl::createWallet(const std::string &path, const std::string &password,
@@ -161,9 +170,7 @@ bool WalletManagerImpl::connected(uint32_t *version) const
     req_t.jsonrpc = "2.0";
     req_t.id = epee::serialization::storage_entry(0);
     req_t.method = "get_version";
-    epee::net_utils::http::http_simple_client http_client;
-    bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/json_rpc", req_t, resp_t, http_client);
-    if (!r)
+    if (!connect_and_invoke(m_daemonAddress, "/json_rpc", req_t, resp_t))
       return false;
 
     if (version)
@@ -209,8 +216,7 @@ bool WalletManagerImpl::checkPayment(const std::string &address_text, const std:
   cryptonote::COMMAND_RPC_GET_TRANSACTIONS::request req;
   cryptonote::COMMAND_RPC_GET_TRANSACTIONS::response res;
   req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid));
-  epee::net_utils::http::http_simple_client http_client;
-  if (!epee::net_utils::invoke_http_json_remote_command2(daemon_address + "/gettransactions", req, res, http_client) ||
+  if (!connect_and_invoke(m_daemonAddress, "/gettransactions", req, res) ||
       (res.txs.size() != 1 && res.txs_as_hex.size() != 1))
   {
     error = tr("failed to get transaction from daemon");
@@ -328,8 +334,7 @@ uint64_t WalletManagerImpl::blockchainHeight() const
     cryptonote::COMMAND_RPC_GET_INFO::request ireq;
     cryptonote::COMMAND_RPC_GET_INFO::response ires;
 
-    epee::net_utils::http::http_simple_client http_client;
-    if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/getinfo", ireq, ires, http_client))
+    if (!connect_and_invoke(m_daemonAddress, "/getinfo", ireq, ires))
       return 0;
     return ires.height;
 }
@@ -339,8 +344,7 @@ uint64_t WalletManagerImpl::blockchainTargetHeight() const
     cryptonote::COMMAND_RPC_GET_INFO::request ireq;
     cryptonote::COMMAND_RPC_GET_INFO::response ires;
 
-    epee::net_utils::http::http_simple_client http_client;
-    if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/getinfo", ireq, ires, http_client))
+    if (!connect_and_invoke(m_daemonAddress, "/getinfo", ireq, ires))
       return 0;
     return ires.target_height >= ires.height ? ires.target_height : ires.height;
 }
@@ -350,8 +354,7 @@ uint64_t WalletManagerImpl::networkDifficulty() const
     cryptonote::COMMAND_RPC_GET_INFO::request ireq;
     cryptonote::COMMAND_RPC_GET_INFO::response ires;
 
-    epee::net_utils::http::http_simple_client http_client;
-    if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/getinfo", ireq, ires, http_client))
+    if (!connect_and_invoke(m_daemonAddress, "/getinfo", ireq, ires))
       return 0;
     return ires.difficulty;
 }
@@ -362,7 +365,7 @@ double WalletManagerImpl::miningHashRate() const
     cryptonote::COMMAND_RPC_MINING_STATUS::response mres;
 
     epee::net_utils::http::http_simple_client http_client;
-    if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/mining_status", mreq, mres, http_client))
+    if (!connect_and_invoke(m_daemonAddress, "/mining_status", mreq, mres))
       return 0.0;
     if (!mres.active)
       return 0.0;
@@ -382,7 +385,7 @@ void WalletManagerImpl::hardForkInfo(uint8_t &version, uint64_t &earliest_height
     req_t.id = epee::serialization::storage_entry(0);
     req_t.method = "hard_fork_info";
     req_t.params.version = 0;
-    bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/json_rpc", req_t, resp_t, http_client);
+    bool r = connect_and_invoke(m_daemonAddress, "/json_rpc", req_t, resp_t);
     if (!r || resp_t.result.status != CORE_RPC_STATUS_OK)
         return;
     version = resp_t.result.version;
@@ -394,8 +397,7 @@ uint64_t WalletManagerImpl::blockTarget() const
     cryptonote::COMMAND_RPC_GET_INFO::request ireq;
     cryptonote::COMMAND_RPC_GET_INFO::response ires;
 
-    epee::net_utils::http::http_simple_client http_client;
-    if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/getinfo", ireq, ires, http_client))
+    if (!connect_and_invoke(m_daemonAddress, "/getinfo", ireq, ires))
         return 0;
     return ires.target;
 }
@@ -405,8 +407,7 @@ bool WalletManagerImpl::isMining() const
     cryptonote::COMMAND_RPC_MINING_STATUS::request mreq;
     cryptonote::COMMAND_RPC_MINING_STATUS::response mres;
 
-    epee::net_utils::http::http_simple_client http_client;
-    if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/mining_status", mreq, mres, http_client))
+    if (!connect_and_invoke(m_daemonAddress, "/mining_status", mreq, mres))
       return false;
     return mres.active;
 }
@@ -419,8 +420,7 @@ bool WalletManagerImpl::startMining(const std::string &address, uint32_t threads
     mreq.miner_address = address;
     mreq.threads_count = threads;
 
-    epee::net_utils::http::http_simple_client http_client;
-    if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/start_mining", mreq, mres, http_client))
+    if (!connect_and_invoke(m_daemonAddress, "/start_mining", mreq, mres))
       return false;
     return mres.status == CORE_RPC_STATUS_OK;
 }
@@ -430,8 +430,7 @@ bool WalletManagerImpl::stopMining()
     cryptonote::COMMAND_RPC_STOP_MINING::request mreq;
     cryptonote::COMMAND_RPC_STOP_MINING::response mres;
 
-    epee::net_utils::http::http_simple_client http_client;
-    if (!epee::net_utils::invoke_http_json_remote_command2(m_daemonAddress + "/stop_mining", mreq, mres, http_client))
+    if (!connect_and_invoke(m_daemonAddress, "/stop_mining", mreq, mres))
       return false;
     return mres.status == CORE_RPC_STATUS_OK;
 }
diff --git a/src/wallet/node_rpc_proxy.cpp b/src/wallet/node_rpc_proxy.cpp
index d7f755e36..cc249b5cc 100644
--- a/src/wallet/node_rpc_proxy.cpp
+++ b/src/wallet/node_rpc_proxy.cpp
@@ -36,18 +36,16 @@ using namespace epee;
 namespace tools
 {
 
-void NodeRPCProxy::init(const std::string &daemon_address)
-{
-  m_daemon_address = daemon_address;
-
-  m_height = 0;
-  m_height_time = 0;
-  for (auto &slot: m_earliest_height)
-    slot = 0;
-  m_dynamic_per_kb_fee_estimate = 0;
-  m_dynamic_per_kb_fee_estimate_cached_height = 0;
-  m_dynamic_per_kb_fee_estimate_grace_blocks = 0;
-}
+NodeRPCProxy::NodeRPCProxy(epee::net_utils::http::http_simple_client &http_client, boost::mutex &mutex)
+  : m_http_client(http_client)
+  , m_daemon_rpc_mutex(mutex)
+  , m_height(0)
+  , m_height_time(0)
+  , m_earliest_height()
+  , m_dynamic_per_kb_fee_estimate(0)
+  , m_dynamic_per_kb_fee_estimate_cached_height(0)
+  , m_dynamic_per_kb_fee_estimate_grace_blocks(0)
+{}
 
 boost::optional<std::string> NodeRPCProxy::get_height(uint64_t &height)
 {
@@ -58,7 +56,7 @@ boost::optional<std::string> NodeRPCProxy::get_height(uint64_t &height)
     cryptonote::COMMAND_RPC_GET_HEIGHT::response res = AUTO_VAL_INIT(res);
 
     m_daemon_rpc_mutex.lock();
-    bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/getheight", req, res, m_http_client);
+    bool r = net_utils::invoke_http_json("/getheight", req, res, m_http_client);
     m_daemon_rpc_mutex.unlock();
     CHECK_AND_ASSERT_MES(r, std::string(), "Failed to connect to daemon");
     CHECK_AND_ASSERT_MES(res.status != CORE_RPC_STATUS_BUSY, res.status, "Failed to connect to daemon");
@@ -87,7 +85,7 @@ boost::optional<std::string> NodeRPCProxy::get_earliest_height(uint8_t version,
     req_t.id = epee::serialization::storage_entry(0);
     req_t.method = "hard_fork_info";
     req_t.params.version = version;
-    bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client);
+    bool r = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client);
     m_daemon_rpc_mutex.unlock();
     CHECK_AND_ASSERT_MES(r, std::string(), "Failed to connect to daemon");
     CHECK_AND_ASSERT_MES(resp_t.result.status != CORE_RPC_STATUS_BUSY, resp_t.result.status, "Failed to connect to daemon");
@@ -117,7 +115,7 @@ boost::optional<std::string> NodeRPCProxy::get_dynamic_per_kb_fee_estimate(uint6
     req_t.id = epee::serialization::storage_entry(0);
     req_t.method = "get_fee_estimate";
     req_t.params.grace_blocks = grace_blocks;
-    bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client);
+    bool r = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client);
     m_daemon_rpc_mutex.unlock();
     CHECK_AND_ASSERT_MES(r, std::string(), "Failed to connect to daemon");
     CHECK_AND_ASSERT_MES(resp_t.result.status != CORE_RPC_STATUS_BUSY, resp_t.result.status, "Failed to connect to daemon");
diff --git a/src/wallet/node_rpc_proxy.h b/src/wallet/node_rpc_proxy.h
index 1ae716dab..e2f42d541 100644
--- a/src/wallet/node_rpc_proxy.h
+++ b/src/wallet/node_rpc_proxy.h
@@ -39,10 +39,7 @@ namespace tools
 class NodeRPCProxy
 {
 public:
-  NodeRPCProxy(epee::net_utils::http::http_simple_client &http_client, boost::mutex &mutex):
-    m_http_client(http_client), m_daemon_rpc_mutex(mutex) { init(""); }
-
-  void init(const std::string &daemon_address);
+  NodeRPCProxy(epee::net_utils::http::http_simple_client &http_client, boost::mutex &mutex);
 
   boost::optional<std::string> get_height(uint64_t &height);
   void set_height(uint64_t h);
@@ -50,7 +47,6 @@ public:
   boost::optional<std::string> get_dynamic_per_kb_fee_estimate(uint64_t grace_blocks, uint64_t &fee);
 
 private:
-  std::string m_daemon_address;
   epee::net_utils::http::http_simple_client &m_http_client;
   boost::mutex &m_daemon_rpc_mutex;
 
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 14f180e00..2e4550879 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -164,7 +164,7 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl
     daemon_address = std::string("http://") + daemon_host + ":" + std::to_string(daemon_port);
 
   std::unique_ptr<tools::wallet2> wallet(new tools::wallet2(testnet, restricted));
-  wallet->init(daemon_address);
+  wallet->init(std::move(daemon_address));
   return wallet;
 }
 
@@ -418,6 +418,7 @@ namespace tools
 // for now, limit to 30 attempts.  TODO: discuss a good number to limit to.
 const size_t MAX_SPLIT_ATTEMPTS = 30;
 
+constexpr const std::chrono::seconds wallet2::rpc_timeout;
 const char* wallet2::tr(const char* str) { return i18n_translate(str, "tools::wallet2"); }
 
 bool wallet2::has_testnet_option(const boost::program_options::variables_map& vm)
@@ -484,11 +485,11 @@ std::pair<std::unique_ptr<wallet2>, password_container> wallet2::make_new(const
 }
 
 //----------------------------------------------------------------------------------------------------
-void wallet2::init(const std::string& daemon_address, uint64_t upper_transaction_size_limit)
+bool wallet2::init(std::string daemon_address, uint64_t upper_transaction_size_limit)
 {
   m_upper_transaction_size_limit = upper_transaction_size_limit;
-  m_daemon_address = daemon_address;
-  m_node_rpc_proxy.init(m_daemon_address);
+  m_daemon_address = std::move(daemon_address);
+  return m_http_client.set_server(get_daemon_address());
 }
 //----------------------------------------------------------------------------------------------------
 bool wallet2::is_deterministic() const
@@ -1169,7 +1170,7 @@ void wallet2::pull_blocks(uint64_t start_height, uint64_t &blocks_start_height,
 
   req.start_height = start_height;
   m_daemon_rpc_mutex.lock();
-  bool r = net_utils::invoke_http_bin_remote_command2(m_daemon_address + "/getblocks.bin", req, res, m_http_client, WALLET_RCP_CONNECTION_TIMEOUT);
+  bool r = net_utils::invoke_http_bin("/getblocks.bin", req, res, m_http_client, rpc_timeout);
   m_daemon_rpc_mutex.unlock();
   THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "getblocks.bin");
   THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "getblocks.bin");
@@ -1191,7 +1192,7 @@ void wallet2::pull_hashes(uint64_t start_height, uint64_t &blocks_start_height,
 
   req.start_height = start_height;
   m_daemon_rpc_mutex.lock();
-  bool r = net_utils::invoke_http_bin_remote_command2(m_daemon_address + "/gethashes.bin", req, res, m_http_client, WALLET_RCP_CONNECTION_TIMEOUT);
+  bool r = net_utils::invoke_http_bin("/gethashes.bin", req, res, m_http_client, rpc_timeout);
   m_daemon_rpc_mutex.unlock();
   THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "gethashes.bin");
   THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "gethashes.bin");
@@ -1353,7 +1354,7 @@ void wallet2::update_pool_state()
   cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL::request req;
   cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL::response res;
   m_daemon_rpc_mutex.lock();
-  bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemon_address + "/get_transaction_pool", req, res, m_http_client, 200000);
+  bool r = epee::net_utils::invoke_http_json("/get_transaction_pool", req, res, m_http_client, rpc_timeout);
   m_daemon_rpc_mutex.unlock();
   THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_transaction_pool");
   THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_transaction_pool");
@@ -1461,7 +1462,7 @@ void wallet2::update_pool_state()
           req.txs_hashes.push_back(it.id_hash);
           req.decode_as_json = false;
           m_daemon_rpc_mutex.lock();
-          bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemon_address + "/gettransactions", req, res, m_http_client, 200000);
+          bool r = epee::net_utils::invoke_http_json("/gettransactions", req, res, m_http_client, rpc_timeout);
           m_daemon_rpc_mutex.unlock();
           if (r && res.status == CORE_RPC_STATUS_OK)
           {
@@ -2262,15 +2263,7 @@ bool wallet2::check_connection(uint32_t *version, uint32_t timeout)
 
   if(!m_http_client.is_connected())
   {
-    net_utils::http::url_content u;
-    net_utils::parse_url(m_daemon_address, u);
-
-    if(!u.port)
-    {
-      u.port = m_testnet ? config::testnet::RPC_DEFAULT_PORT : config::RPC_DEFAULT_PORT;
-    }
-
-    if (!m_http_client.connect(u.host, std::to_string(u.port), timeout))
+    if (!m_http_client.connect(std::chrono::milliseconds(timeout)))
       return false;
   }
 
@@ -2281,7 +2274,7 @@ bool wallet2::check_connection(uint32_t *version, uint32_t timeout)
     req_t.jsonrpc = "2.0";
     req_t.id = epee::serialization::storage_entry(0);
     req_t.method = "get_version";
-    bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client);
+    bool r = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client);
     if (!r || resp_t.result.status != CORE_RPC_STATUS_OK)
       *version = 0;
     else
@@ -2602,7 +2595,7 @@ void wallet2::rescan_spent()
   COMMAND_RPC_IS_KEY_IMAGE_SPENT::response daemon_resp = AUTO_VAL_INIT(daemon_resp);
   req.key_images = key_images;
   m_daemon_rpc_mutex.lock();
-  bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemon_address + "/is_key_image_spent", req, daemon_resp, m_http_client, 200000);
+  bool r = epee::net_utils::invoke_http_json("/is_key_image_spent", req, daemon_resp, m_http_client, rpc_timeout);
   m_daemon_rpc_mutex.unlock();
   THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "is_key_image_spent");
   THROW_WALLET_EXCEPTION_IF(daemon_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "is_key_image_spent");
@@ -2976,7 +2969,7 @@ void wallet2::commit_tx(pending_tx& ptx)
   req.do_not_relay = false;
   COMMAND_RPC_SEND_RAW_TX::response daemon_send_resp;
   m_daemon_rpc_mutex.lock();
-  bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemon_address + "/sendrawtransaction", req, daemon_send_resp, m_http_client, 200000);
+  bool r = epee::net_utils::invoke_http_json("/sendrawtransaction", req, daemon_send_resp, m_http_client, rpc_timeout);
   m_daemon_rpc_mutex.unlock();
   THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "sendrawtransaction");
   THROW_WALLET_EXCEPTION_IF(daemon_send_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "sendrawtransaction");
@@ -3437,7 +3430,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
     req_t.params.amounts.resize(std::distance(req_t.params.amounts.begin(), end));
     req_t.params.unlocked = true;
     req_t.params.recent_cutoff = time(NULL) - RECENT_OUTPUT_ZONE;
-    bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client);
+    bool r = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client);
     m_daemon_rpc_mutex.unlock();
     THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "transfer_selected");
     THROW_WALLET_EXCEPTION_IF(resp_t.result.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_output_histogram");
@@ -3564,7 +3557,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
 
     // get the keys for those
     m_daemon_rpc_mutex.lock();
-    r = epee::net_utils::invoke_http_bin_remote_command2(m_daemon_address + "/get_outs.bin", req, daemon_resp, m_http_client, 200000);
+    r = epee::net_utils::invoke_http_bin("/get_outs.bin", req, daemon_resp, m_http_client, rpc_timeout);
     m_daemon_rpc_mutex.unlock();
     THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_outs.bin");
     THROW_WALLET_EXCEPTION_IF(daemon_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_outs.bin");
@@ -4636,7 +4629,7 @@ std::vector<size_t> wallet2::select_available_outputs_from_histogram(uint64_t co
   req_t.params.min_count = count;
   req_t.params.max_count = 0;
   req_t.params.unlocked = unlocked;
-  bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client);
+  bool r = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client);
   m_daemon_rpc_mutex.unlock();
   THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "select_available_unmixable_outputs");
   THROW_WALLET_EXCEPTION_IF(resp_t.result.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_output_histogram");
@@ -4675,7 +4668,7 @@ uint64_t wallet2::get_num_rct_outputs()
   req_t.params.amounts.push_back(0);
   req_t.params.min_count = 0;
   req_t.params.max_count = 0;
-  bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client);
+  bool r = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client);
   m_daemon_rpc_mutex.unlock();
   THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_num_rct_outputs");
   THROW_WALLET_EXCEPTION_IF(resp_t.result.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_output_histogram");
@@ -4784,7 +4777,7 @@ uint64_t wallet2::get_daemon_blockchain_target_height(string &err)
   req_t.jsonrpc = "2.0";
   req_t.id = epee::serialization::storage_entry(0);
   req_t.method = "get_info";
-  bool ok = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client);
+  bool ok = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client);
   m_daemon_rpc_mutex.unlock();
   if (ok)
   {
@@ -5097,7 +5090,7 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag
   }
 
   m_daemon_rpc_mutex.lock();
-  bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemon_address + "/is_key_image_spent", req, daemon_resp, m_http_client, 200000);
+  bool r = epee::net_utils::invoke_http_json("/is_key_image_spent", req, daemon_resp, m_http_client, rpc_timeout);
   m_daemon_rpc_mutex.unlock();
   THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "is_key_image_spent");
   THROW_WALLET_EXCEPTION_IF(daemon_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "is_key_image_spent");
@@ -5407,7 +5400,7 @@ uint64_t wallet2::get_blockchain_height_by_date(uint16_t year, uint8_t month, ui
       height_mid,
       height_max
     };
-    bool r = net_utils::invoke_http_bin_remote_command2(get_daemon_address() + "/getblocks_by_height.bin", req, res, m_http_client);
+    bool r = net_utils::invoke_http_bin("/getblocks_by_height.bin", req, res, m_http_client);
     if (!r || res.status != CORE_RPC_STATUS_OK)
     {
       std::ostringstream oss;
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index e136c568c..91d4db47e 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -61,8 +61,6 @@
 #undef MONERO_DEFAULT_LOG_CATEGORY
 #define MONERO_DEFAULT_LOG_CATEGORY "wallet.wallet2"
 
-#define WALLET_RCP_CONNECTION_TIMEOUT                          200000
-
 class Serialization_portability_wallet_Test;
 
 namespace tools
@@ -96,6 +94,8 @@ namespace tools
   {
     friend class ::Serialization_portability_wallet_Test;
   public:
+    static constexpr const std::chrono::seconds rpc_timeout = std::chrono::minutes(3) + std::chrono::seconds(30);
+
     enum RefreshType {
       RefreshFull,
       RefreshOptimizeCoinbase,
@@ -107,7 +107,7 @@ namespace tools
     wallet2(const wallet2&) : m_run(true), m_callback(0), m_testnet(false), m_always_confirm_transfers(true), m_print_ring_members(false), m_store_tx_info(true), m_default_mixin(0), m_default_priority(0), m_refresh_type(RefreshOptimizeCoinbase), m_auto_refresh(true), m_refresh_from_block_height(0), m_confirm_missing_payment_id(true), m_node_rpc_proxy(m_http_client, m_daemon_rpc_mutex) {}
 
   public:
-    static const char* tr(const char* str);// { return i18n_translate(str, "cryptonote::simple_wallet"); }
+    static const char* tr(const char* str);
 
     static bool has_testnet_option(const boost::program_options::variables_map& vm);
     static void init_options(boost::program_options::options_description& desc_params);
@@ -342,8 +342,8 @@ namespace tools
     // free block size. TODO: fix this so that it actually takes
     // into account the current median block size rather than
     // the minimum block size.
-    void init(const std::string& daemon_address = "http://localhost:8080", uint64_t upper_transaction_size_limit = 0);
     bool deinit();
+    bool init(std::string daemon_address = "http://localhost:8080", uint64_t upper_transaction_size_limit = 0);
 
     void stop() { m_run.store(false, std::memory_order_relaxed); }
 
@@ -1018,7 +1018,7 @@ namespace tools
       }
 
       m_daemon_rpc_mutex.lock();
-      bool r = epee::net_utils::invoke_http_bin_remote_command2(m_daemon_address + "/getrandom_outs.bin", req, daemon_resp, m_http_client, 200000);
+      bool r = epee::net_utils::invoke_http_bin("/getrandom_outs.bin", req, daemon_resp, m_http_client, rpc_timeout);
       m_daemon_rpc_mutex.unlock();
       THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "getrandom_outs.bin");
       THROW_WALLET_EXCEPTION_IF(daemon_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "getrandom_outs.bin");
diff --git a/tests/functional_tests/transactions_flow_test.cpp b/tests/functional_tests/transactions_flow_test.cpp
index 73c79c237..5666f49bf 100644
--- a/tests/functional_tests/transactions_flow_test.cpp
+++ b/tests/functional_tests/transactions_flow_test.cpp
@@ -159,14 +159,14 @@ bool transactions_flow_test(std::string& working_folder,
   epee::net_utils::http::http_simple_client http_client;
   COMMAND_RPC_STOP_MINING::request daemon1_req = AUTO_VAL_INIT(daemon1_req);
   COMMAND_RPC_STOP_MINING::response daemon1_rsp = AUTO_VAL_INIT(daemon1_rsp);
-  bool r = net_utils::invoke_http_json_remote_command2(daemon_addr_a + "/stop_mine", daemon1_req, daemon1_rsp, http_client, 10000);
+  bool r = http_client.set_server(daemon_addr_a) && net_utils::invoke_http_json("/stop_mine", daemon1_req, daemon1_rsp, http_client, std::chrono::seconds(10));
   CHECK_AND_ASSERT_MES(r, false, "failed to stop mining");
 
   COMMAND_RPC_START_MINING::request daemon_req = AUTO_VAL_INIT(daemon_req);
   COMMAND_RPC_START_MINING::response daemon_rsp = AUTO_VAL_INIT(daemon_rsp);
   daemon_req.miner_address = w1.get_account().get_public_address_str(false);
   daemon_req.threads_count = 9;
-  r = net_utils::invoke_http_json_remote_command2(daemon_addr_a + "/start_mining", daemon_req, daemon_rsp, http_client, 10000);
+  r = net_utils::invoke_http_json("/start_mining", daemon_req, daemon_rsp, http_client, std::chrono::seconds(10));
   CHECK_AND_ASSERT_MES(r, false, "failed to get getrandom_outs");
   CHECK_AND_ASSERT_MES(daemon_rsp.status == CORE_RPC_STATUS_OK, false, "failed to getrandom_outs.bin");