aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorluigi1111 <luigi1111w@gmail.com>2021-05-12 16:55:38 -0500
committerluigi1111 <luigi1111w@gmail.com>2021-05-12 16:55:38 -0500
commita080c0be9c5da26011ec715d158c1430ef99b3e8 (patch)
treeebff5394dc25ed38a1b3f209ccf5db383a41bde4
parentMerge pull request #7680 (diff)
parentwallet_api: import / export output function (diff)
downloadmonero-a080c0be9c5da26011ec715d158c1430ef99b3e8.tar.xz
Merge pull request #7678
dedcd63 wallet_api: import / export output function (tobtoht) 6e22710 expose set_offline to wallet api (benevanoff) 02e9a41 wallet_api: add isDeterministic() (tobtoht) def5819 wallet_api: add seed_offset param to seed() (tobtoht) 73959c6 wallet_api: store fee for incoming txs in history (Ben Evanoff) 712f362 wallet api: allow wallet to fetch all key images via api (benevanoff) 153d08d Allow tx note edits via TransactionHistory object in wallet/api (dsc) 2abd7b1 wallet_api: TransactionHistory - fill unconfirmed out payments dests (xiphon) 9a50bef Extend TransactionInfo with coinbase and description attributes in wallet/api (dsc) 22bb6a6 Allow AddressBook description edits via wallet/api interface (dsc)
-rw-r--r--src/wallet/api/address_book.cpp19
-rw-r--r--src/wallet/api/address_book.h1
-rw-r--r--src/wallet/api/transaction_history.cpp22
-rw-r--r--src/wallet/api/transaction_history.h1
-rw-r--r--src/wallet/api/transaction_info.cpp11
-rw-r--r--src/wallet/api/transaction_info.h4
-rw-r--r--src/wallet/api/wallet.cpp79
-rw-r--r--src/wallet/api/wallet.h9
-rw-r--r--src/wallet/api/wallet2_api.h34
9 files changed, 172 insertions, 8 deletions
diff --git a/src/wallet/api/address_book.cpp b/src/wallet/api/address_book.cpp
index f69a69ca3..96090d9f5 100644
--- a/src/wallet/api/address_book.cpp
+++ b/src/wallet/api/address_book.cpp
@@ -70,6 +70,25 @@ bool AddressBookImpl::addRow(const std::string &dst_addr , const std::string &pa
return r;
}
+bool AddressBookImpl::setDescription(std::size_t index, const std::string &description)
+{
+ clearStatus();
+
+ const auto ab = m_wallet->m_wallet->get_address_book();
+ if (index >= ab.size()){
+ return false;
+ }
+
+ tools::wallet2::address_book_row entry = ab[index];
+ entry.m_description = description;
+ bool r = m_wallet->m_wallet->set_address_book_row(index, entry.m_address, NULL, entry.m_description, entry.m_is_subaddress);
+ if (r)
+ refresh();
+ else
+ m_errorCode = General_Error;
+ return r;
+}
+
void AddressBookImpl::refresh()
{
LOG_PRINT_L2("Refreshing addressbook");
diff --git a/src/wallet/api/address_book.h b/src/wallet/api/address_book.h
index f287969f3..e22f474fb 100644
--- a/src/wallet/api/address_book.h
+++ b/src/wallet/api/address_book.h
@@ -45,6 +45,7 @@ public:
void refresh() override;
std::vector<AddressBookRow*> getAll() const override;
bool addRow(const std::string &dst_addr , const std::string &payment_id, const std::string &description) override;
+ bool setDescription(std::size_t index, const std::string &description) override;
bool deleteRow(std::size_t rowId) override;
// Error codes. See AddressBook:ErrorCode enum in wallet2_api.h
diff --git a/src/wallet/api/transaction_history.cpp b/src/wallet/api/transaction_history.cpp
index bcb300889..d8e4aab65 100644
--- a/src/wallet/api/transaction_history.cpp
+++ b/src/wallet/api/transaction_history.cpp
@@ -92,6 +92,17 @@ std::vector<TransactionInfo *> TransactionHistoryImpl::getAll() const
return m_history;
}
+void TransactionHistoryImpl::setTxNote(const std::string &txid, const std::string &note)
+{
+ cryptonote::blobdata txid_data;
+ if(!epee::string_tools::parse_hexstr_to_binbuff(txid, txid_data) || txid_data.size() != sizeof(crypto::hash))
+ return;
+ const crypto::hash htxid = *reinterpret_cast<const crypto::hash*>(txid_data.data());
+
+ m_wallet->m_wallet->set_tx_note(htxid, note);
+ refresh();
+}
+
void TransactionHistoryImpl::refresh()
{
// multithreaded access:
@@ -126,10 +137,13 @@ void TransactionHistoryImpl::refresh()
payment_id = payment_id.substr(0,16);
TransactionInfoImpl * ti = new TransactionInfoImpl();
ti->m_paymentid = payment_id;
+ ti->m_coinbase = pd.m_coinbase;
ti->m_amount = pd.m_amount;
+ ti->m_fee = pd.m_fee;
ti->m_direction = TransactionInfo::Direction_In;
ti->m_hash = string_tools::pod_to_hex(pd.m_tx_hash);
ti->m_blockheight = pd.m_block_height;
+ ti->m_description = m_wallet->m_wallet->get_tx_note(pd.m_tx_hash);
ti->m_subaddrIndex = { pd.m_subaddr_index.minor };
ti->m_subaddrAccount = pd.m_subaddr_index.major;
ti->m_label = m_wallet->m_wallet->get_subaddress_label(pd.m_subaddr_index);
@@ -173,6 +187,7 @@ void TransactionHistoryImpl::refresh()
ti->m_direction = TransactionInfo::Direction_Out;
ti->m_hash = string_tools::pod_to_hex(hash);
ti->m_blockheight = pd.m_block_height;
+ ti->m_description = m_wallet->m_wallet->get_tx_note(hash);
ti->m_subaddrIndex = pd.m_subaddr_indices;
ti->m_subaddrAccount = pd.m_subaddr_account;
ti->m_label = pd.m_subaddr_indices.size() == 1 ? m_wallet->m_wallet->get_subaddress_label({pd.m_subaddr_account, *pd.m_subaddr_indices.begin()}) : "";
@@ -183,6 +198,7 @@ void TransactionHistoryImpl::refresh()
for (const auto &d: pd.m_dests) {
ti->m_transfers.push_back({d.amount, d.address(m_wallet->m_wallet->nettype(), pd.m_payment_id)});
}
+
m_history.push_back(ti);
}
@@ -207,11 +223,16 @@ void TransactionHistoryImpl::refresh()
ti->m_failed = is_failed;
ti->m_pending = true;
ti->m_hash = string_tools::pod_to_hex(hash);
+ ti->m_description = m_wallet->m_wallet->get_tx_note(hash);
ti->m_subaddrIndex = pd.m_subaddr_indices;
ti->m_subaddrAccount = pd.m_subaddr_account;
ti->m_label = pd.m_subaddr_indices.size() == 1 ? m_wallet->m_wallet->get_subaddress_label({pd.m_subaddr_account, *pd.m_subaddr_indices.begin()}) : "";
ti->m_timestamp = pd.m_timestamp;
ti->m_confirmations = 0;
+ for (const auto &d : pd.m_dests)
+ {
+ ti->m_transfers.push_back({d.amount, d.address(m_wallet->m_wallet->nettype(), pd.m_payment_id)});
+ }
m_history.push_back(ti);
}
@@ -230,6 +251,7 @@ void TransactionHistoryImpl::refresh()
ti->m_direction = TransactionInfo::Direction_In;
ti->m_hash = string_tools::pod_to_hex(pd.m_tx_hash);
ti->m_blockheight = pd.m_block_height;
+ ti->m_description = m_wallet->m_wallet->get_tx_note(pd.m_tx_hash);
ti->m_pending = true;
ti->m_subaddrIndex = { pd.m_subaddr_index.minor };
ti->m_subaddrAccount = pd.m_subaddr_index.major;
diff --git a/src/wallet/api/transaction_history.h b/src/wallet/api/transaction_history.h
index 8f3805788..60f12d771 100644
--- a/src/wallet/api/transaction_history.h
+++ b/src/wallet/api/transaction_history.h
@@ -45,6 +45,7 @@ public:
virtual TransactionInfo * transaction(const std::string &id) const;
virtual std::vector<TransactionInfo*> getAll() const;
virtual void refresh();
+ virtual void setTxNote(const std::string &txid, const std::string &note);
private:
diff --git a/src/wallet/api/transaction_info.cpp b/src/wallet/api/transaction_info.cpp
index 5ae3a6937..33e7856db 100644
--- a/src/wallet/api/transaction_info.cpp
+++ b/src/wallet/api/transaction_info.cpp
@@ -45,6 +45,7 @@ TransactionInfoImpl::TransactionInfoImpl()
: m_direction(Direction_Out)
, m_pending(false)
, m_failed(false)
+ , m_coinbase(false)
, m_amount(0)
, m_fee(0)
, m_blockheight(0)
@@ -77,6 +78,11 @@ bool TransactionInfoImpl::isFailed() const
return m_failed;
}
+bool TransactionInfoImpl::isCoinbase() const
+{
+ return m_coinbase;
+}
+
uint64_t TransactionInfoImpl::amount() const
{
return m_amount;
@@ -92,6 +98,11 @@ uint64_t TransactionInfoImpl::blockHeight() const
return m_blockheight;
}
+std::string TransactionInfoImpl::description() const
+{
+ return m_description;
+}
+
std::set<uint32_t> TransactionInfoImpl::subaddrIndex() const
{
return m_subaddrIndex;
diff --git a/src/wallet/api/transaction_info.h b/src/wallet/api/transaction_info.h
index 73bb7689d..8bc36a8e9 100644
--- a/src/wallet/api/transaction_info.h
+++ b/src/wallet/api/transaction_info.h
@@ -46,10 +46,12 @@ public:
//! true if hold
virtual bool isPending() const override;
virtual bool isFailed() const override;
+ virtual bool isCoinbase() const override;
virtual uint64_t amount() const override;
//! always 0 for incoming txes
virtual uint64_t fee() const override;
virtual uint64_t blockHeight() const override;
+ virtual std::string description() const override;
virtual std::set<uint32_t> subaddrIndex() const override;
virtual uint32_t subaddrAccount() const override;
virtual std::string label() const override;
@@ -65,9 +67,11 @@ private:
int m_direction;
bool m_pending;
bool m_failed;
+ bool m_coinbase;
uint64_t m_amount;
uint64_t m_fee;
uint64_t m_blockheight;
+ std::string m_description;
std::set<uint32_t> m_subaddrIndex; // always unique index for incoming transfers; can be multiple indices for outgoing transfers
uint32_t m_subaddrAccount;
std::string m_label;
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 9acc8484c..b2ffce229 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -791,11 +791,11 @@ bool WalletImpl::close(bool store)
return result;
}
-std::string WalletImpl::seed() const
+std::string WalletImpl::seed(const std::string& seed_offset) const
{
epee::wipeable_string seed;
if (m_wallet)
- m_wallet->get_seed(seed);
+ m_wallet->get_seed(seed, seed_offset);
return std::string(seed.data(), seed.size()); // TODO
}
@@ -1168,7 +1168,7 @@ bool WalletImpl::submitTransaction(const string &fileName) {
return true;
}
-bool WalletImpl::exportKeyImages(const string &filename)
+bool WalletImpl::exportKeyImages(const string &filename, bool all)
{
if (m_wallet->watch_only())
{
@@ -1178,7 +1178,7 @@ bool WalletImpl::exportKeyImages(const string &filename)
try
{
- if (!m_wallet->export_key_images(filename))
+ if (!m_wallet->export_key_images(filename), all)
{
setStatusError(tr("failed to save file ") + filename);
return false;
@@ -1216,6 +1216,68 @@ bool WalletImpl::importKeyImages(const string &filename)
return true;
}
+bool WalletImpl::exportOutputs(const string &filename, bool all)
+{
+ if (m_wallet->key_on_device())
+ {
+ setStatusError(string(tr("Not supported on HW wallets.")) + filename);
+ return false;
+ }
+
+ try
+ {
+ std::string data = m_wallet->export_outputs_to_str(all);
+ bool r = m_wallet->save_to_file(filename, data);
+ if (!r)
+ {
+ LOG_ERROR("Failed to save file " << filename);
+ setStatusError(string(tr("Failed to save file: ")) + filename);
+ return false;
+ }
+ }
+ catch (const std::exception &e)
+ {
+ LOG_ERROR("Error exporting outputs: " << e.what());
+ setStatusError(string(tr("Error exporting outputs: ")) + e.what());
+ return false;
+ }
+
+ LOG_PRINT_L2("Outputs exported to " << filename);
+ return true;
+}
+
+bool WalletImpl::importOutputs(const string &filename)
+{
+ if (m_wallet->key_on_device())
+ {
+ setStatusError(string(tr("Not supported on HW wallets.")) + filename);
+ return false;
+ }
+
+ std::string data;
+ bool r = m_wallet->load_from_file(filename, data);
+ if (!r)
+ {
+ LOG_ERROR("Failed to read file: " << filename);
+ setStatusError(string(tr("Failed to read file: ")) + filename);
+ 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;
+}
+
void WalletImpl::addSubaddressAccount(const std::string& label)
{
m_wallet->add_subaddress_account(label);
@@ -2104,6 +2166,11 @@ bool WalletImpl::watchOnly() const
return m_wallet->watch_only();
}
+bool WalletImpl::isDeterministic() const
+{
+ return m_wallet->is_deterministic();
+}
+
void WalletImpl::clearStatus() const
{
boost::lock_guard<boost::mutex> l(m_statusMutex);
@@ -2305,6 +2372,10 @@ bool WalletImpl::rescanSpent()
return true;
}
+void WalletImpl::setOffline(bool offline)
+{
+ m_wallet->set_offline(offline);
+}
void WalletImpl::hardForkInfo(uint8_t &version, uint64_t &earliest_height) const
{
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index 3bf3e759b..ce2d7d7e4 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -81,7 +81,7 @@ public:
const std::string &device_name);
Device getDeviceType() const override;
bool close(bool store = true);
- std::string seed() const override;
+ std::string seed(const std::string& seed_offset = "") const override;
std::string getSeedLanguage() const override;
void setSeedLanguage(const std::string &arg) override;
// void setListener(Listener *) {}
@@ -129,6 +129,7 @@ public:
void setRecoveringFromDevice(bool recoveringFromDevice) override;
void setSubaddressLookahead(uint32_t major, uint32_t minor) override;
bool watchOnly() const override;
+ bool isDeterministic() const override;
bool rescanSpent() override;
NetworkType nettype() const override {return static_cast<NetworkType>(m_wallet->nettype());}
void hardForkInfo(uint8_t &version, uint64_t &earliest_height) const override;
@@ -164,8 +165,10 @@ public:
virtual PendingTransaction * createSweepUnmixableTransaction() override;
bool submitTransaction(const std::string &fileName) override;
virtual UnsignedTransaction * loadUnsignedTx(const std::string &unsigned_filename) override;
- bool exportKeyImages(const std::string &filename) override;
+ bool exportKeyImages(const std::string &filename, bool all = false) override;
bool importKeyImages(const std::string &filename) override;
+ bool exportOutputs(const std::string &filename, bool all = false) override;
+ bool importOutputs(const std::string &filename) override;
virtual void disposeTransaction(PendingTransaction * t) override;
virtual uint64_t estimateTransactionFee(const std::vector<std::pair<std::string, uint64_t>> &destinations,
@@ -181,6 +184,8 @@ public:
virtual bool setCacheAttribute(const std::string &key, const std::string &val) override;
virtual std::string getCacheAttribute(const std::string &key) const override;
+ virtual void setOffline(bool offline) override;
+
virtual bool setUserNote(const std::string &txid, const std::string &note) override;
virtual std::string getUserNote(const std::string &txid) const override;
virtual std::string getTxKey(const std::string &txid) const override;
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
index 999823ff1..e34332734 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -182,9 +182,11 @@ struct TransactionInfo
virtual int direction() const = 0;
virtual bool isPending() const = 0;
virtual bool isFailed() const = 0;
+ virtual bool isCoinbase() const = 0;
virtual uint64_t amount() const = 0;
virtual uint64_t fee() const = 0;
virtual uint64_t blockHeight() const = 0;
+ virtual std::string description() const = 0;
virtual std::set<uint32_t> subaddrIndex() const = 0;
virtual uint32_t subaddrAccount() const = 0;
virtual std::string label() const = 0;
@@ -208,6 +210,7 @@ struct TransactionHistory
virtual TransactionInfo * transaction(const std::string &id) const = 0;
virtual std::vector<TransactionInfo*> getAll() const = 0;
virtual void refresh() = 0;
+ virtual void setTxNote(const std::string &txid, const std::string &note) = 0;
};
/**
@@ -250,6 +253,7 @@ struct AddressBook
virtual std::vector<AddressBookRow*> getAll() const = 0;
virtual bool addRow(const std::string &dst_addr , const std::string &payment_id, const std::string &description) = 0;
virtual bool deleteRow(std::size_t rowId) = 0;
+ virtual bool setDescription(std::size_t index, const std::string &description) = 0;
virtual void refresh() = 0;
virtual std::string errorString() const = 0;
virtual int errorCode() const = 0;
@@ -442,7 +446,7 @@ struct Wallet
};
virtual ~Wallet() = 0;
- virtual std::string seed() const = 0;
+ virtual std::string seed(const std::string& seed_offset = "") const = 0;
virtual std::string getSeedLanguage() const = 0;
virtual void setSeedLanguage(const std::string &arg) = 0;
//! returns wallet status (Status_Ok | Status_Error)
@@ -623,6 +627,12 @@ struct Wallet
virtual bool watchOnly() const = 0;
/**
+ * @brief isDeterministic - checks if wallet keys are deterministic
+ * @return - true if deterministic
+ */
+ virtual bool isDeterministic() const = 0;
+
+ /**
* @brief blockChainHeight - returns current blockchain height
* @return
*/
@@ -897,9 +907,10 @@ struct Wallet
/*!
* \brief exportKeyImages - exports key images to file
* \param filename
+ * \param all - export all key images or only those that have not yet been exported
* \return - true on success
*/
- virtual bool exportKeyImages(const std::string &filename) = 0;
+ virtual bool exportKeyImages(const std::string &filename, bool all = false) = 0;
/*!
* \brief importKeyImages - imports key images from file
@@ -908,6 +919,19 @@ struct Wallet
*/
virtual bool importKeyImages(const std::string &filename) = 0;
+ /*!
+ * \brief importOutputs - exports outputs to file
+ * \param filename
+ * \return - true on success
+ */
+ virtual bool exportOutputs(const std::string &filename, bool all = false) = 0;
+
+ /*!
+ * \brief importOutputs - imports outputs from file
+ * \param filename
+ * \return - true on success
+ */
+ virtual bool importOutputs(const std::string &filename) = 0;
virtual TransactionHistory * history() = 0;
virtual AddressBook * addressBook() = 0;
@@ -1003,6 +1027,12 @@ struct Wallet
* \return true on success
*/
virtual bool rescanSpent() = 0;
+
+ /*
+ * \brief setOffline - toggle set offline on/off
+ * \param offline - true/false
+ */
+ virtual void setOffline(bool offline) = 0;
//! blackballs a set of outputs
virtual bool blackballOutputs(const std::vector<std::string> &outputs, bool add) = 0;