diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index ea1993c80..1856118f7 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -57,6 +57,7 @@
 #include "version.h"
 #include "crypto/crypto.h"  // for crypto::secret_key definition
 #include "mnemonics/electrum-words.h"
+#include "rapidjson/document.h"
 #include <stdexcept>
 
 #if defined(WIN32)
@@ -81,6 +82,7 @@ namespace
   const command_line::arg_descriptor<std::string> arg_generate_new_wallet = {"generate-new-wallet", sw::tr("Generate new wallet and save it to <arg> or <address>.wallet by default"), ""};
   const command_line::arg_descriptor<std::string> arg_generate_from_view_key = {"generate-from-view-key", sw::tr("Generate incoming-only wallet from view key"), ""};
   const command_line::arg_descriptor<std::string> arg_generate_from_keys = {"generate-from-keys", sw::tr("Generate wallet from private keys"), ""};
+  const command_line::arg_descriptor<std::string> arg_generate_from_json = {"generate-from-json", sw::tr("Generate wallet from JSON format file"), ""};
   const command_line::arg_descriptor<std::string> arg_daemon_address = {"daemon-address", sw::tr("Use daemon instance at <host>:<port>"), ""};
   const command_line::arg_descriptor<std::string> arg_daemon_host = {"daemon-host", sw::tr("Use daemon instance at host <arg> instead of localhost"), ""};
   const command_line::arg_descriptor<std::string> arg_password = {"password", sw::tr("Wallet password"), "", true};
@@ -716,7 +718,7 @@ bool simple_wallet::ask_wallet_create_if_needed()
   // add logic to error out if new wallet requested but named wallet file exists
   if (keys_file_exists || wallet_file_exists)
   {
-    if (!m_generate_new.empty() || m_restore_deterministic_wallet || !m_generate_from_view_key.empty() || !m_generate_from_keys.empty())
+    if (!m_generate_new.empty() || m_restore_deterministic_wallet || !m_generate_from_view_key.empty() || !m_generate_from_keys.empty() || !m_generate_from_json.empty())
     {
       fail_msg_writer() << tr("attempting to generate or restore wallet, but specified file(s) exist.  Exiting to not risk overwriting.");
       return false;
@@ -763,6 +765,13 @@ void simple_wallet::print_seed(std::string seed)
 //----------------------------------------------------------------------------------------------------
 static bool get_password(const boost::program_options::variables_map& vm, bool allow_entry, tools::password_container &pwd_container)
 {
+  // has_arg returns true even when the parameter is not passed ??
+  const std::string gfj = command_line::get_arg(vm, arg_generate_from_json);
+  if (!gfj.empty()) {
+    // will be in the json file, if any
+    return true;
+  }
+
   if (has_arg(vm, arg_password) && has_arg(vm, arg_password_file))
   {
     fail_msg_writer() << tr("can't specify more than one of --password and --password-file");
@@ -808,6 +817,153 @@ static bool get_password(const boost::program_options::variables_map& vm, bool a
   return false;
 }
 
+//----------------------------------------------------------------------------------------------------
+bool simple_wallet::generate_from_json(const boost::program_options::variables_map& vm, std::string &wallet_file, std::string &password)
+{
+  std::string buf;
+  bool r = epee::file_io_utils::load_file_to_string(m_generate_from_json, buf);
+  if (!r) {
+    fail_msg_writer() << tr("Failed to load file ") << m_generate_from_json;
+    return false;
+  }
+
+  rapidjson::Document json;
+  if (json.Parse(buf.c_str()).HasParseError()) {
+    fail_msg_writer() << tr("Failed to parse JSON");
+    return false;
+  }
+
+  if (!json.HasMember("version")) {
+    fail_msg_writer() << tr("Version not found in JSON");
+    return false;
+  }
+  unsigned int version = json["version"].GetUint();
+  const int current_version = 1;
+  if (version > current_version) {
+    fail_msg_writer() << boost::format(tr("Version %u too new, we can only grok up to %u")) % version % current_version;
+    return false;
+  }
+  if (!json.HasMember("filename")) {
+    fail_msg_writer() << tr("Filename not found in JSON");
+    return false;
+  }
+  std::string filename = json["filename"].GetString();
+
+  bool recover = false;
+  uint64_t scan_from_height = 0;
+  if (json.HasMember("scan_from_height")) {
+    scan_from_height = json["scan_from_height"].GetUint64();
+    recover = true;
+  }
+
+  password = "";
+  if (json.HasMember("password")) {
+    password = json["password"].GetString();
+  }
+
+  std::string viewkey_string("");
+  crypto::secret_key viewkey;
+  if (json.HasMember("viewkey")) {
+    viewkey_string = json["viewkey"].GetString();
+    cryptonote::blobdata viewkey_data;
+    if(!epee::string_tools::parse_hexstr_to_binbuff(viewkey_string, viewkey_data))
+    {
+      fail_msg_writer() << tr("failed to parse view key secret key");
+      return false;
+    }
+    viewkey = *reinterpret_cast<const crypto::secret_key*>(viewkey_data.data());
+  }
+
+  std::string spendkey_string("");
+  crypto::secret_key spendkey;
+  if (json.HasMember("spendkey")) {
+    spendkey_string = json["spendkey"].GetString();
+    cryptonote::blobdata spendkey_data;
+    if(!epee::string_tools::parse_hexstr_to_binbuff(spendkey_string, spendkey_data))
+    {
+      fail_msg_writer() << tr("failed to parse spend key secret key");
+      return false;
+    }
+    spendkey = *reinterpret_cast<const crypto::secret_key*>(spendkey_data.data());
+  }
+
+  std::string seed("");
+  std::string old_language;
+  if (json.HasMember("seed")) {
+    seed = json["seed"].GetString();
+    if (!crypto::ElectrumWords::words_to_bytes(seed, m_recovery_key, old_language))
+    {
+      fail_msg_writer() << tr("Electrum-style word list failed verification");
+      return false;
+    }
+    m_electrum_seed = seed;
+    m_restore_deterministic_wallet = true;
+  }
+
+  // compatibility checks
+  if (seed.empty() && viewkey_string.empty()) {
+    fail_msg_writer() << tr("At least one of Electrum-style word list and private view key must be specified");
+    return false;
+  }
+  if (!seed.empty() && (!viewkey_string.empty() || !spendkey_string.empty())) {
+    fail_msg_writer() << tr("Both Electrum-style word list and private key(s) specified");
+    return false;
+  }
+
+  m_wallet_file = filename;
+
+  bool was_deprecated_wallet = m_restore_deterministic_wallet && ((old_language == crypto::ElectrumWords::old_language_name) ||
+    crypto::ElectrumWords::get_is_old_style_seed(m_electrum_seed));
+  if (was_deprecated_wallet) {
+    fail_msg_writer() << tr("Cannot create deprecated wallets from JSON");
+    return false;
+  }
+
+  bool testnet = command_line::get_arg(vm, arg_testnet);
+  m_wallet.reset(new tools::wallet2(testnet));
+  m_wallet->callback(this);
+
+  try
+  {
+    if (!seed.empty())
+    {
+      m_wallet->generate(m_wallet_file, password, m_recovery_key, recover, false);
+    }
+    else
+    {
+      cryptonote::account_public_address address;
+      if (!crypto::secret_key_to_public_key(viewkey, address.m_view_public_key)) {
+        fail_msg_writer() << tr("failed to verify view key secret key");
+        return false;
+      }
+      if (!crypto::secret_key_to_public_key(spendkey, address.m_spend_public_key)) {
+        fail_msg_writer() << tr("failed to verify spend key secret key");
+        return false;
+      }
+
+      if (spendkey_string.empty())
+      {
+        m_wallet->generate(m_wallet_file, password, address, viewkey);
+      }
+      else
+      {
+        m_wallet->generate(m_wallet_file, password, address, spendkey, viewkey);
+      }
+    }
+  }
+  catch (const std::exception& e)
+  {
+    fail_msg_writer() << tr("failed to generate new wallet: ") << e.what();
+    return false;
+  }
+
+  m_wallet->set_refresh_from_block_height(scan_from_height);
+
+  wallet_file = m_wallet_file;
+
+  return r;
+}
+
 //----------------------------------------------------------------------------------------------------
 bool simple_wallet::init(const boost::program_options::variables_map& vm)
 {
@@ -820,12 +976,12 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
     return false;
   }
 
-  if((!m_generate_new.empty()) + (!m_wallet_file.empty()) + (!m_generate_from_view_key.empty()) + (!m_generate_from_keys.empty()) > 1)
+  if((!m_generate_new.empty()) + (!m_wallet_file.empty()) + (!m_generate_from_view_key.empty()) + (!m_generate_from_keys.empty()) + (!m_generate_from_json.empty()) > 1)
   {
-    fail_msg_writer() << tr("can't specify more than one of --generate-new-wallet=\"wallet_name\", --wallet-file=\"wallet_name\", --generate-from-view-key=\"wallet_name\" and --generate-from-keys=\"wallet_name\"");
+    fail_msg_writer() << tr("can't specify more than one of --generate-new-wallet=\"wallet_name\", --wallet-file=\"wallet_name\", --generate-from-view-key=\"wallet_name\", --generate-from-json=\"jsonfilename\" and --generate-from-keys=\"wallet_name\"");
     return false;
   }
-  else if (m_generate_new.empty() && m_wallet_file.empty() && m_generate_from_view_key.empty() && m_generate_from_keys.empty())
+  else if (m_generate_new.empty() && m_wallet_file.empty() && m_generate_from_view_key.empty() && m_generate_from_keys.empty() && m_generate_from_json.empty())
   {
     if(!ask_wallet_create_if_needed()) return false;
   }
@@ -847,7 +1003,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
   if (!get_password(vm, true, pwd_container))
     return false;
 
-  if (!m_generate_new.empty() || m_restore_deterministic_wallet || !m_generate_from_view_key.empty() || !m_generate_from_keys.empty())
+  if (!m_generate_new.empty() || m_restore_deterministic_wallet || !m_generate_from_view_key.empty() || !m_generate_from_keys.empty() || !m_generate_from_json.empty())
   {
     if (m_wallet_file.empty()) m_wallet_file = m_generate_new;  // alias for simplicity later
 
@@ -993,6 +1149,12 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
       bool r = new_wallet(m_wallet_file, pwd_container.password(), address, spendkey, viewkey, testnet);
       CHECK_AND_ASSERT_MES(r, false, tr("account creation failed"));
     }
+    else if (!m_generate_from_json.empty())
+    {
+      std::string wallet_file, password; // we don't need to remember them
+      if (!generate_from_json(vm, wallet_file, password))
+        return false;
+    }
     else
     {
       bool r = new_wallet(m_wallet_file, pwd_container.password(), m_recovery_key, m_restore_deterministic_wallet,
@@ -1023,6 +1185,7 @@ bool simple_wallet::handle_command_line(const boost::program_options::variables_
   m_generate_new                  = command_line::get_arg(vm, arg_generate_new_wallet);
   m_generate_from_view_key        = command_line::get_arg(vm, arg_generate_from_view_key);
   m_generate_from_keys            = command_line::get_arg(vm, arg_generate_from_keys);
+  m_generate_from_json            = command_line::get_arg(vm, arg_generate_from_json);
   m_daemon_address                = command_line::get_arg(vm, arg_daemon_address);
   m_daemon_host                   = command_line::get_arg(vm, arg_daemon_host);
   m_daemon_port                   = command_line::get_arg(vm, arg_daemon_port);
@@ -2575,6 +2738,7 @@ int main(int argc, char* argv[])
   command_line::add_arg(desc_params, arg_generate_new_wallet);
   command_line::add_arg(desc_params, arg_generate_from_view_key);
   command_line::add_arg(desc_params, arg_generate_from_keys);
+  command_line::add_arg(desc_params, arg_generate_from_json);
   command_line::add_arg(desc_params, arg_password);
   command_line::add_arg(desc_params, arg_password_file);
   command_line::add_arg(desc_params, arg_daemon_address);
@@ -2707,11 +2871,21 @@ int main(int argc, char* argv[])
     if (daemon_address.empty())
       daemon_address = std::string("http://") + daemon_host + ":" + std::to_string(daemon_port);
 
+    std::string password;
+    const std::string gfj = command_line::get_arg(vm, arg_generate_from_json);
+    if (!gfj.empty()) {
+      if (!w.generate_from_json(vm, wallet_file, password))
+        return 1;
+    }
+    else {
+      password = pwd_container.password();
+    }
+
     tools::wallet2 wal(testnet,restricted);
     try
     {
       LOG_PRINT_L0(sw::tr("Loading wallet..."));
-      wal.load(wallet_file, pwd_container.password());
+      wal.load(wallet_file, password);
       wal.init(daemon_address);
       wal.refresh();
       LOG_PRINT_GREEN(sw::tr("Loaded ok"), LOG_LEVEL_0);
diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h
index d1617dbf4..7dadb8536 100644
--- a/src/simplewallet/simplewallet.h
+++ b/src/simplewallet/simplewallet.h
@@ -69,6 +69,7 @@ namespace cryptonote
     bool run();
     void stop();
     void interrupt();
+    bool generate_from_json(const boost::program_options::variables_map& vm, std::string &wallet_file, std::string &password);
 
     //wallet *create_wallet();
     bool process_command(const std::vector<std::string> &args);
@@ -221,6 +222,7 @@ namespace cryptonote
     std::string m_generate_new;
     std::string m_generate_from_view_key;
     std::string m_generate_from_keys;
+    std::string m_generate_from_json;
     std::string m_import_path;
 
     std::string m_electrum_seed;  // electrum-style seed parameter
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 2afe08cb1..1c7187cf0 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -490,7 +490,7 @@ void wallet2::process_new_blockchain_entry(const cryptonote::block& b, const cry
   //handle transactions from new block
     
   //optimization: seeking only for blocks that are not older then the wallet creation time plus 1 day. 1 day is for possible user incorrect time setup
-  if(b.timestamp + 60*60*24 > m_account.get_createtime())
+  if(b.timestamp + 60*60*24 > m_account.get_createtime() && height >= m_refresh_from_block_height)
   {
     TIME_MEASURE_START(miner_tx_handle_time);
     process_new_transaction(b.miner_tx, height, true);
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index f798f404d..e7b002925 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -88,10 +88,10 @@ namespace tools
     };
 
   private:
-    wallet2(const wallet2&) : m_run(true), m_callback(0), m_testnet(false), m_always_confirm_transfers (false), m_store_tx_info(true), m_default_mixin(0), m_refresh_type(RefreshOptimizeCoinbase), m_auto_refresh(true) {}
+    wallet2(const wallet2&) : m_run(true), m_callback(0), m_testnet(false), m_always_confirm_transfers (false), m_store_tx_info(true), m_default_mixin(0), m_refresh_type(RefreshOptimizeCoinbase), m_auto_refresh(true), m_refresh_from_block_height(0) {}
 
   public:
-    wallet2(bool testnet = false, bool restricted = false) : m_run(true), m_callback(0), m_testnet(testnet), m_restricted(restricted), is_old_file_format(false), m_store_tx_info(true), m_default_mixin(0), m_refresh_type(RefreshOptimizeCoinbase), m_auto_refresh(true) {}
+    wallet2(bool testnet = false, bool restricted = false) : m_run(true), m_callback(0), m_testnet(testnet), m_restricted(restricted), is_old_file_format(false), m_store_tx_info(true), m_default_mixin(0), m_refresh_type(RefreshOptimizeCoinbase), m_auto_refresh(true), m_refresh_from_block_height(0) {}
     struct transfer_details
     {
       uint64_t m_block_height;
@@ -226,6 +226,8 @@ namespace tools
     cryptonote::account_base& get_account(){return m_account;}
     const cryptonote::account_base& get_account()const{return m_account;}
 
+    void set_refresh_from_block_height(uint64_t height) {m_refresh_from_block_height = height;}
+
     // upper_transaction_size_limit as defined below is set to 
     // approximately 125% of the fixed minimum allowable penalty
     // free block size. TODO: fix this so that it actually takes
@@ -319,6 +321,9 @@ namespace tools
       if(ver < 9)
         return;
       a & m_confirmed_txs;
+      if(ver < 11)
+        return;
+      a & m_refresh_from_block_height;
     }
 
     /*!
@@ -430,9 +435,10 @@ namespace tools
     uint32_t m_default_mixin;
     RefreshType m_refresh_type;
     bool m_auto_refresh;
+    uint64_t m_refresh_from_block_height;
   };
 }
-BOOST_CLASS_VERSION(tools::wallet2, 10)
+BOOST_CLASS_VERSION(tools::wallet2, 11)
 BOOST_CLASS_VERSION(tools::wallet2::payment_details, 0)
 BOOST_CLASS_VERSION(tools::wallet2::unconfirmed_transfer_details, 2)
 BOOST_CLASS_VERSION(tools::wallet2::confirmed_transfer_details, 1)