diff --git a/src/wallet/api/pending_transaction.cpp b/src/wallet/api/pending_transaction.cpp
index 9783da5bc..ba84a3733 100644
--- a/src/wallet/api/pending_transaction.cpp
+++ b/src/wallet/api/pending_transaction.cpp
@@ -162,6 +162,44 @@ bool PendingTransactionImpl::commit(const std::string &filename, bool overwrite)
     return m_status == Status_Ok;
 }
 
+std::string PendingTransactionImpl::commit_string()
+{
+
+    std::string tx;
+    LOG_PRINT_L3("m_pending_tx size: " << m_pending_tx.size());
+
+    try {
+	tx = m_wallet.m_wallet->dump_tx_to_str(m_pending_tx);
+	m_status = Status_Ok;
+    } catch (const tools::error::daemon_busy&) {
+        // TODO: make it translatable with "tr"?
+        m_errorString = tr("daemon is busy. Please try again later.");
+        m_status = Status_Error;
+    } catch (const tools::error::no_connection_to_daemon&) {
+        m_errorString = tr("no connection to daemon. Please make sure daemon is running.");
+        m_status = Status_Error;
+    } catch (const tools::error::tx_rejected& e) {
+        std::ostringstream writer(m_errorString);
+        writer << (boost::format(tr("transaction %s was rejected by daemon with status: ")) % get_transaction_hash(e.tx())) <<  e.status();
+        std::string reason = e.reason();
+        m_status = Status_Error;
+        m_errorString = writer.str();
+        if (!reason.empty())
+          m_errorString  += string(tr(". Reason: ")) + reason;
+    } catch (const std::exception &e) {
+        m_errorString = string(tr("Unknown exception: ")) + e.what();
+        m_status = Status_Error;
+    } catch (...) {
+        m_errorString = tr("Unhandled exception");
+        LOG_ERROR(m_errorString);
+        m_status = Status_Error;
+    }
+    m_wallet.startRefresh();
+    if (m_status != Status_Ok)
+	return "";
+    return tx;
+}
+
 uint64_t PendingTransactionImpl::amount() const
 {
     uint64_t result = 0;
diff --git a/src/wallet/api/pending_transaction.h b/src/wallet/api/pending_transaction.h
index 9d8d754c0..0b9b09ece 100644
--- a/src/wallet/api/pending_transaction.h
+++ b/src/wallet/api/pending_transaction.h
@@ -45,6 +45,7 @@ public:
     ~PendingTransactionImpl();
     int status() const override;
     std::string errorString() const override;
+    std::string commit_string() override;
     bool commit(const std::string &filename = "", bool overwrite = false) override;
     uint64_t amount() const override;
     uint64_t dust() const override;
diff --git a/src/wallet/api/unsigned_transaction.cpp b/src/wallet/api/unsigned_transaction.cpp
index c549539e5..378e1886f 100644
--- a/src/wallet/api/unsigned_transaction.cpp
+++ b/src/wallet/api/unsigned_transaction.cpp
@@ -96,6 +96,28 @@ bool UnsignedTransactionImpl::sign(const std::string &signedFileName)
   return true;
 }
 
+std::string UnsignedTransactionImpl::signAsString()
+{
+  if(m_wallet.watchOnly())
+  {
+     m_errorString = tr("This is a watch only wallet");
+     m_status = Status_Error;
+     return "";
+  }
+  tools::wallet2::signed_tx_set signed_txes;
+  std::vector<tools::wallet2::pending_tx> ptx;
+  try
+  {
+    return m_wallet.m_wallet->sign_tx_dump_to_str(m_unsigned_tx_set, ptx, signed_txes);
+  }
+  catch (const std::exception &e)
+  {
+    m_errorString = string(tr("Failed to sign transaction")) + e.what();
+    m_status = Status_Error;
+    return "";
+  }
+}
+
 //----------------------------------------------------------------------------------------------------
 bool UnsignedTransactionImpl::checkLoadedTx(const std::function<size_t()> get_num_txes, const std::function<const tools::wallet2::tx_construction_data&(size_t)> &get_tx, const std::string &extra_message)
 {
diff --git a/src/wallet/api/unsigned_transaction.h b/src/wallet/api/unsigned_transaction.h
index b07d43fb1..6a4d87b53 100644
--- a/src/wallet/api/unsigned_transaction.h
+++ b/src/wallet/api/unsigned_transaction.h
@@ -53,6 +53,7 @@ public:
     uint64_t txCount() const override;
     // sign txs and save to file
     bool sign(const std::string &signedFileName) override;
+    std::string signAsString() override;
     std::string confirmationMessage() const override {return m_confirmationMessage;}
     uint64_t minMixinCount() const override;
 
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index c8257919d..44b386f3d 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -1134,6 +1134,27 @@ UnsignedTransaction *WalletImpl::loadUnsignedTx(const std::string &unsigned_file
   return transaction;
 }
 
+UnsignedTransaction *WalletImpl::loadUnsignedTxFromString(const std::string &data) {
+  clearStatus();
+  UnsignedTransactionImpl * transaction = new UnsignedTransactionImpl(*this);
+  if (checkBackgroundSync("cannot load tx") || !m_wallet->parse_unsigned_tx_from_str(data, transaction->m_unsigned_tx_set)){
+    setStatusError(tr("Failed to load unsigned transactions"));
+    transaction->m_status = UnsignedTransaction::Status::Status_Error;
+    transaction->m_errorString = errorString();
+
+    return transaction;
+  }
+
+  // Check tx data and construct confirmation message
+  std::string extra_message;
+  if (!std::get<2>(transaction->m_unsigned_tx_set.transfers).empty())
+    extra_message = (boost::format("%u outputs to import. ") % (unsigned)std::get<2>(transaction->m_unsigned_tx_set.transfers).size()).str();
+  transaction->checkLoadedTx([&transaction](){return transaction->m_unsigned_tx_set.txes.size();}, [&transaction](size_t n)->const tools::wallet2::tx_construction_data&{return transaction->m_unsigned_tx_set.txes[n];}, extra_message);
+  setStatus(transaction->status(), transaction->errorString());
+
+  return transaction;
+}
+
 bool WalletImpl::submitTransaction(const string &fileName) {
   clearStatus();
   if (checkBackgroundSync("cannot submit tx"))
@@ -1154,6 +1175,48 @@ bool WalletImpl::submitTransaction(const string &fileName) {
   return true;
 }
 
+bool WalletImpl::submitTransactionFromString(const string &data) {
+  clearStatus();
+  if (checkBackgroundSync("cannot submit tx"))
+    return false;
+  std::unique_ptr<PendingTransactionImpl> transaction(new PendingTransactionImpl(*this));
+
+  bool r = m_wallet->parse_tx_from_str(data, transaction->m_pending_tx, NULL);
+  if (!r) {
+    setStatus(Status_Ok, tr("Failed to load transaction from string"));
+    return false;
+  }
+
+  if(!transaction->commit()) {
+    setStatusError(transaction->m_errorString);
+    return false;
+  }
+
+  return true;
+}
+
+std::string WalletImpl::exportKeyImagesAsString(bool all)
+{
+  if (m_wallet->watch_only())
+  {
+    setStatusError(tr("Wallet is view only"));
+    return "";
+  }
+  if (checkBackgroundSync("cannot export key images"))
+    return "";
+
+  try
+  {
+      return m_wallet->export_key_images_string(all);
+  }
+  catch (const std::exception &e)
+  {
+    LOG_ERROR("Error exporting key images: " << e.what());
+    setStatusError(e.what());
+    return "";
+  }
+}
+
 bool WalletImpl::exportKeyImages(const string &filename, bool all) 
 {
   if (m_wallet->watch_only())
@@ -1181,6 +1244,31 @@ bool WalletImpl::exportKeyImages(const string &filename, bool all)
   return true;
 }
 
+bool WalletImpl::importKeyImagesFromString(const std::string &data)
+{
+  if (checkBackgroundSync("cannot import key images"))
+    return false;
+  if (!trustedDaemon()) {
+    setStatusError(tr("Key images can only be imported with a trusted daemon"));
+    return false;
+  }
+  try
+  {
+    uint64_t spent = 0, unspent = 0;
+    uint64_t height = m_wallet->import_key_images_string(data, spent, unspent);
+    LOG_PRINT_L2("Signed key images imported to height " << height << ", "
+        << print_money(spent) << " spent, " << print_money(unspent) << " unspent");
+  }
+  catch (const std::exception &e)
+  {
+    LOG_ERROR("Error exporting key images: " << e.what());
+    setStatusError(string(tr("Failed to import key images: ")) + e.what());
+    return false;
+  }
+
+  return true;
+}
+
 bool WalletImpl::importKeyImages(const string &filename)
 {
   if (checkBackgroundSync("cannot import key images"))
@@ -1206,6 +1294,29 @@ bool WalletImpl::importKeyImages(const string &filename)
   return true;
 }
 
+std::string WalletImpl::exportOutputsAsString(bool all)
+{
+    if (checkBackgroundSync("cannot export outputs"))
+        return "";
+    if (m_wallet->key_on_device())
+    {
+        setStatusError(string(tr("Not supported on HW wallets.")));
+        return "";
+    }
+
+    try
+    {
+        return m_wallet->export_outputs_to_str(all);
+    }
+    catch (const std::exception &e)
+    {
+        LOG_ERROR("Error exporting outputs: " << e.what());
+        setStatusError(string(tr("Error exporting outputs: ")) + e.what());
+        return "";
+    }
+    return "";
+}
+
 bool WalletImpl::exportOutputs(const string &filename, bool all)
 {
     if (checkBackgroundSync("cannot export outputs"))
@@ -1238,6 +1349,32 @@ bool WalletImpl::exportOutputs(const string &filename, bool all)
     return true;
 }
 
+bool WalletImpl::importOutputsFromString(const std::string &data)
+{
+    if (checkBackgroundSync("cannot import outputs"))
+        return false;
+    if (m_wallet->key_on_device())
+    {
+        setStatusError(string(tr("Not supported on HW wallets.")));
+        return false;
+    }
+
+
+    try
+    {
+        size_t n_outputs = m_wallet->import_outputs_from_str(data);
+        LOG_PRINT_L2(std::to_string(n_outputs) << " outputs imported");
+    }
+    catch (const std::exception &e)
+    {
+        LOG_ERROR("Failed to import outputs: " << e.what());
+        setStatusError(string(tr("Failed to import outputs: ")) + e.what());
+        return false;
+    }
+
+    return true;
+}
+
 bool WalletImpl::importOutputs(const string &filename)
 {
     if (checkBackgroundSync("cannot import outputs"))
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index d48d7f130..2364f0741 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -166,10 +166,16 @@ public:
                                         std::set<uint32_t> subaddr_indices = {}) override;
     virtual PendingTransaction * createSweepUnmixableTransaction() override;
     bool submitTransaction(const std::string &fileName) override;
+    bool submitTransactionFromString(const std::string &fileName) override;
     virtual UnsignedTransaction * loadUnsignedTx(const std::string &unsigned_filename) override;
+    virtual UnsignedTransaction * loadUnsignedTxFromString(const std::string &unsigned_filename) override;
+    std::string exportKeyImagesAsString(bool all = false) override;
     bool exportKeyImages(const std::string &filename, bool all = false) override;
+    bool importKeyImagesFromString(const std::string &data) override;
     bool importKeyImages(const std::string &filename) override;
+    std::string exportOutputsAsString(bool all = false) override;
     bool exportOutputs(const std::string &filename, bool all = false) override;
+    bool importOutputsFromString(const std::string &data) override;
     bool importOutputs(const std::string &filename) override;
     bool scanTransactions(const std::vector<std::string> &txids) override;
 
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
index c374d1574..cd4206e6c 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -89,6 +89,8 @@ struct PendingTransaction
     virtual ~PendingTransaction() = 0;
     virtual int status() const = 0;
     virtual std::string errorString() const = 0;
+    // return string of transaction gives the same content which would be saved to file with commit(filename)
+    virtual std::string commit_string() = 0;
     // commit transaction or save to file if filename is provided.
     virtual bool commit(const std::string &filename = "", bool overwrite = false) = 0;
     virtual uint64_t amount() const = 0;
@@ -161,6 +163,11 @@ struct UnsignedTransaction
     * return - true on success
     */
     virtual bool sign(const std::string &signedFileName) = 0;
+   /*!
+    * @brief sign - Sign txs and return as string
+    * return - true on success
+    */
+    virtual std::string signAsString() = 0;
 };
 
 /**
@@ -895,11 +902,24 @@ struct Wallet
     */
     virtual UnsignedTransaction * loadUnsignedTx(const std::string &unsigned_filename) = 0;
     
+   /*!
+    * \brief loadUnsignedTxFromString  - creates transaction from unsigned tx string
+    * \return                - UnsignedTransaction object. caller is responsible to check UnsignedTransaction::status()
+    *                          after object returned
+    */
+    virtual UnsignedTransaction * loadUnsignedTxFromString(const std::string &unsigned_filename) = 0;
+
    /*!
     * \brief submitTransaction - submits transaction in signed tx file
     * \return                  - true on success
     */
     virtual bool submitTransaction(const std::string &fileName) = 0;
+
+   /*!
+    * \brief submitTransactionFromString - submits transaction in signed tx file
+    * \return                  - true on success
+    */
+    virtual bool submitTransactionFromString(const std::string &fileName) = 0;
     
 
     /*!
@@ -916,6 +936,13 @@ struct Wallet
     virtual uint64_t estimateTransactionFee(const std::vector<std::pair<std::string, uint64_t>> &destinations,
                                             PendingTransaction::Priority priority) const = 0;
 
+   /*!
+    * \brief exportKeyImages - exports key images as string
+    * \param all - export all key images or only those that have not yet been exported
+    * \return                  - key images as std::string
+    */
+    virtual std::string exportKeyImagesAsString(bool all = false) = 0;
+
    /*!
     * \brief exportKeyImages - exports key images to file
     * \param filename
@@ -923,6 +950,13 @@ struct Wallet
     * \return                  - true on success
     */
     virtual bool exportKeyImages(const std::string &filename, bool all = false) = 0;
+
+   /*!
+    * \brief importKeyImagesFromString - imports key images from string for UR use.
+    * \param data
+    * \return                  - true on success
+    */
+    virtual bool importKeyImagesFromString(const std::string &data) = 0;
    
    /*!
     * \brief importKeyImages - imports key images from file
@@ -932,12 +966,25 @@ struct Wallet
     virtual bool importKeyImages(const std::string &filename) = 0;
 
     /*!
-     * \brief importOutputs - exports outputs to file
+     * \brief exportOutputsAsString - exports outputs to a string for UR
+     * \return                  - true on success
+     */
+    virtual std::string exportOutputsAsString(bool all = false) = 0;
+
+    /*!
+     * \brief exportOutputs - exports outputs to file
      * \param filename
      * \return                  - true on success
      */
     virtual bool exportOutputs(const std::string &filename, bool all = false) = 0;
 
+    /*!
+     * \brief importOutputsFromString - imports outputs from string for UR
+     * \param filename
+     * \return                  - true on success
+     */
+    virtual bool importOutputsFromString(const std::string &data) = 0;
+
     /*!
      * \brief importOutputs - imports outputs from file
      * \param filename
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index fa9c51bb2..0bf3ff8c1 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -13262,9 +13262,8 @@ crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::walle
   return tx_pub_key;
 }
 
-bool wallet2::export_key_images(const std::string &filename, bool all) const
+std::string wallet2::export_key_images_string(bool all) const
 {
-  PERF_TIMER(export_key_images);
   std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = export_key_images(all);
   std::string magic(KEY_IMAGE_EXPORT_FILE_MAGIC, strlen(KEY_IMAGE_EXPORT_FILE_MAGIC));
   const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address;
@@ -13287,8 +13286,13 @@ bool wallet2::export_key_images(const std::string &filename, bool all) const
 
   // encrypt data, keep magic plaintext
   PERF_TIMER(export_key_images_encrypt);
-  std::string ciphertext = encrypt_with_view_secret_key(data);
-  return save_to_file(filename, magic + ciphertext);
+  return magic + encrypt_with_view_secret_key(data);
+}
+
+bool wallet2::export_key_images(const std::string &filename, bool all) const
+{
+  PERF_TIMER(export_key_images);
+  return save_to_file(filename, export_key_images_string(all));
 }
 
 //----------------------------------------------------------------------------------------------------
@@ -13353,10 +13357,16 @@ uint64_t wallet2::import_key_images(const std::string &filename, uint64_t &spent
 
   THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, std::string(tr("failed to read file ")) + filename);
 
+  return import_key_images_string(data, spent, unspent);
+}
+
+uint64_t wallet2::import_key_images_string(const std::string &keyImages, uint64_t &spent, uint64_t &unspent)
+{
+  std::string data = keyImages;
   const size_t magiclen = strlen(KEY_IMAGE_EXPORT_FILE_MAGIC);
   if (data.size() < magiclen || memcmp(data.data(), KEY_IMAGE_EXPORT_FILE_MAGIC, magiclen))
   {
-    THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Bad key image export file magic in ") + filename);
+    THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Bad key image export file magic"));
   }
 
   try
@@ -13366,24 +13376,24 @@ uint64_t wallet2::import_key_images(const std::string &filename, uint64_t &spent
   }
   catch (const std::exception &e)
   {
-    THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Failed to decrypt ") + filename + ": " + e.what());
+    THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Failed to decrypt: ") + e.what());
   }
 
   const size_t headerlen = 4 + 2 * sizeof(crypto::public_key);
-  THROW_WALLET_EXCEPTION_IF(data.size() < headerlen, error::wallet_internal_error, std::string("Bad data size from file ") + filename);
+  THROW_WALLET_EXCEPTION_IF(data.size() < headerlen, error::wallet_internal_error, std::string("Bad data size"));
   const uint32_t offset = (uint8_t)data[0] | (((uint8_t)data[1]) << 8) | (((uint8_t)data[2]) << 16) | (((uint8_t)data[3]) << 24);
   const crypto::public_key &public_spend_key = *(const crypto::public_key*)&data[4];
   const crypto::public_key &public_view_key = *(const crypto::public_key*)&data[4 + sizeof(crypto::public_key)];
   const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address;
   if (public_spend_key != keys.m_spend_public_key || public_view_key != keys.m_view_public_key)
   {
-    THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string( "Key images from ") + filename + " are for a different account");
+    THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string( "Key images are from a different account" ));
   }
   THROW_WALLET_EXCEPTION_IF(offset > m_transfers.size(), error::wallet_internal_error, "Offset larger than known outputs");
 
   const size_t record_size = sizeof(crypto::key_image) + sizeof(crypto::signature);
   THROW_WALLET_EXCEPTION_IF((data.size() - headerlen) % record_size,
-      error::wallet_internal_error, std::string("Bad data size from file ") + filename);
+      error::wallet_internal_error, std::string("Bad data size"));
   size_t nki = (data.size() - headerlen) / record_size;
 
   std::vector<std::pair<crypto::key_image, crypto::signature>> ski;
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 7228f1907..1da82e734 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -1630,10 +1630,12 @@ private:
     void import_payments_out(const std::list<std::pair<crypto::hash,wallet2::confirmed_transfer_details>> &confirmed_payments);
     std::tuple<size_t, crypto::hash, std::vector<crypto::hash>> export_blockchain() const;
     void import_blockchain(const std::tuple<size_t, crypto::hash, std::vector<crypto::hash>> &bc);
+    std::string export_key_images_string(bool all = false) const;
     bool export_key_images(const std::string &filename, bool all = false) const;
     std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> export_key_images(bool all = false) const;
     uint64_t import_key_images(const std::vector<std::pair<crypto::key_image, crypto::signature>> &signed_key_images, size_t offset, uint64_t &spent, uint64_t &unspent, bool check_spent = true);
     uint64_t import_key_images(const std::string &filename, uint64_t &spent, uint64_t &unspent);
+    uint64_t import_key_images_string(const std::string &data, uint64_t &spent, uint64_t &unspent);
     bool import_key_images(std::vector<crypto::key_image> key_images, size_t offset=0, boost::optional<std::unordered_set<size_t>> selected_transfers=boost::none);
     bool import_key_images(signed_tx_set & signed_tx, size_t offset=0, bool only_selected_transfers=false);
     crypto::public_key get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const;