mirror of
https://git.wownero.com/wownero/wownero.git
synced 2024-08-15 01:03:23 +00:00
Misc. wallet API and wallet2 changes
This commit is contained in:
parent
1840e844db
commit
3ea6587022
12 changed files with 336 additions and 34 deletions
|
@ -67,7 +67,10 @@ void SubaddressImpl::refresh(uint32_t accountIndex)
|
|||
clearRows();
|
||||
for (size_t i = 0; i < m_wallet->m_wallet->get_num_subaddresses(accountIndex); ++i)
|
||||
{
|
||||
m_rows.push_back(new SubaddressRow(i, m_wallet->m_wallet->get_subaddress_as_str({accountIndex, (uint32_t)i}), m_wallet->m_wallet->get_subaddress_label({accountIndex, (uint32_t)i})));
|
||||
m_rows.push_back(new SubaddressRow(i,
|
||||
m_wallet->m_wallet->get_subaddress_as_str({accountIndex, (uint32_t)i}),
|
||||
m_wallet->m_wallet->get_subaddress_label({accountIndex, (uint32_t)i}),
|
||||
m_wallet->m_wallet->get_subaddress_used({accountIndex, (uint32_t)i})));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -199,6 +199,9 @@ void TransactionHistoryImpl::refresh()
|
|||
ti->m_transfers.push_back({d.amount, d.address(m_wallet->m_wallet->nettype(), pd.m_payment_id)});
|
||||
}
|
||||
|
||||
for (const auto &r: pd.m_rings) {
|
||||
ti->m_rings.push_back({string_tools::pod_to_hex(r.first), cryptonote::relative_output_offsets_to_absolute(r.second)});
|
||||
}
|
||||
m_history.push_back(ti);
|
||||
}
|
||||
|
||||
|
@ -229,10 +232,15 @@ void TransactionHistoryImpl::refresh()
|
|||
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)
|
||||
|
||||
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)});
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &r: pd.m_rings) {
|
||||
ti->m_rings.push_back({string_tools::pod_to_hex(r.first), cryptonote::relative_output_offsets_to_absolute(r.second)});
|
||||
}
|
||||
m_history.push_back(ti);
|
||||
}
|
||||
|
||||
|
|
|
@ -139,6 +139,11 @@ const std::vector<TransactionInfo::Transfer> &TransactionInfoImpl::transfers() c
|
|||
return m_transfers;
|
||||
}
|
||||
|
||||
const std::vector<std::pair<std::string, std::vector<uint64_t>>> &TransactionInfoImpl::rings() const
|
||||
{
|
||||
return m_rings;
|
||||
}
|
||||
|
||||
uint64_t TransactionInfoImpl::confirmations() const
|
||||
{
|
||||
return m_confirmations;
|
||||
|
|
|
@ -63,6 +63,8 @@ public:
|
|||
virtual uint64_t confirmations() const override;
|
||||
virtual uint64_t unlockTime() const override;
|
||||
|
||||
virtual const std::vector<std::pair<std::string, std::vector<uint64_t>>> &rings() const override;
|
||||
|
||||
private:
|
||||
int m_direction;
|
||||
bool m_pending;
|
||||
|
@ -81,6 +83,7 @@ private:
|
|||
std::vector<Transfer> m_transfers;
|
||||
uint64_t m_confirmations;
|
||||
uint64_t m_unlock_time;
|
||||
std::vector<std::pair<std::string, std::vector<uint64_t>>> m_rings;
|
||||
|
||||
friend class TransactionHistoryImpl;
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "transaction_history.h"
|
||||
#include "address_book.h"
|
||||
#include "subaddress.h"
|
||||
#include "coins.h"
|
||||
#include "subaddress_account.h"
|
||||
#include "common_defines.h"
|
||||
#include "common/util.h"
|
||||
|
@ -167,11 +168,8 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback
|
|||
<< ", tx: " << tx_hash
|
||||
<< ", amount: " << print_money(amount)
|
||||
<< ", idx: " << subaddr_index);
|
||||
// do not signal on received tx if wallet is not syncronized completely
|
||||
if (m_listener && m_wallet->synchronized()) {
|
||||
m_listener->moneyReceived(tx_hash, amount);
|
||||
m_listener->updated();
|
||||
}
|
||||
m_listener->moneyReceived(tx_hash, amount);
|
||||
m_listener->updated();
|
||||
}
|
||||
|
||||
virtual void on_unconfirmed_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index)
|
||||
|
@ -183,11 +181,8 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback
|
|||
<< ", tx: " << tx_hash
|
||||
<< ", amount: " << print_money(amount)
|
||||
<< ", idx: " << subaddr_index);
|
||||
// do not signal on received tx if wallet is not syncronized completely
|
||||
if (m_listener && m_wallet->synchronized()) {
|
||||
m_listener->unconfirmedMoneyReceived(tx_hash, amount);
|
||||
m_listener->updated();
|
||||
}
|
||||
m_listener->unconfirmedMoneyReceived(tx_hash, amount);
|
||||
m_listener->updated();
|
||||
}
|
||||
|
||||
virtual void on_money_spent(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& in_tx,
|
||||
|
@ -199,11 +194,8 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback
|
|||
<< ", tx: " << tx_hash
|
||||
<< ", amount: " << print_money(amount)
|
||||
<< ", idx: " << subaddr_index);
|
||||
// do not signal on sent tx if wallet is not syncronized completely
|
||||
if (m_listener && m_wallet->synchronized()) {
|
||||
m_listener->moneySpent(tx_hash, amount);
|
||||
m_listener->updated();
|
||||
}
|
||||
m_listener->moneySpent(tx_hash, amount);
|
||||
m_listener->updated();
|
||||
}
|
||||
|
||||
virtual void on_skip_transaction(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx)
|
||||
|
@ -437,6 +429,7 @@ WalletImpl::WalletImpl(NetworkType nettype, uint64_t kdf_rounds)
|
|||
m_refreshEnabled = false;
|
||||
m_addressBook.reset(new AddressBookImpl(this));
|
||||
m_subaddress.reset(new SubaddressImpl(this));
|
||||
m_coins.reset(new CoinsImpl(this));
|
||||
m_subaddressAccount.reset(new SubaddressAccountImpl(this));
|
||||
|
||||
|
||||
|
@ -764,6 +757,35 @@ bool WalletImpl::recover(const std::string &path, const std::string &password, c
|
|||
return status() == Status_Ok;
|
||||
}
|
||||
|
||||
bool WalletImpl::recoverDeterministicWalletFromSpendKey(const std::string &path, const std::string &password, const std::string &language, const std::string &spendkey_string)
|
||||
{
|
||||
clearStatus();
|
||||
m_errorString.clear();
|
||||
|
||||
m_recoveringFromSeed = true;
|
||||
m_recoveringFromDevice = false;
|
||||
|
||||
// parse spend key
|
||||
crypto::secret_key spendkey;
|
||||
if (!spendkey_string.empty()) {
|
||||
cryptonote::blobdata spendkey_data;
|
||||
if(!epee::string_tools::parse_hexstr_to_binbuff(spendkey_string, spendkey_data) || spendkey_data.size() != sizeof(crypto::secret_key))
|
||||
{
|
||||
setStatusError(tr("failed to parse secret spend key"));
|
||||
return false;
|
||||
}
|
||||
spendkey = *reinterpret_cast<const crypto::secret_key*>(spendkey_data.data());
|
||||
}
|
||||
|
||||
try {
|
||||
m_wallet->generate(path, password, spendkey, true, false);
|
||||
setSeedLanguage(language);
|
||||
} catch (const std::exception &e) {
|
||||
setStatusCritical(e.what());
|
||||
}
|
||||
return status() == Status_Ok;
|
||||
}
|
||||
|
||||
bool WalletImpl::close(bool store)
|
||||
{
|
||||
|
||||
|
@ -1705,6 +1727,137 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const
|
|||
return createTransactionMultDest(std::vector<string> {dst_addr}, payment_id, amount ? (std::vector<uint64_t> {*amount}) : (optional<std::vector<uint64_t>>()), mixin_count, priority, subaddr_account, subaddr_indices);
|
||||
}
|
||||
|
||||
PendingTransaction *WalletImpl::createTransactionSingle(const string &key_image, const string &dst_addr,
|
||||
const size_t outputs, PendingTransaction::Priority priority)
|
||||
{
|
||||
clearStatus();
|
||||
// Pause refresh thread while creating transaction
|
||||
pauseRefresh();
|
||||
|
||||
cryptonote::address_parse_info info;
|
||||
|
||||
size_t fake_outs_count = m_wallet->adjust_mixin(m_wallet->default_mixin());
|
||||
|
||||
uint32_t adjusted_priority = m_wallet->adjust_priority(static_cast<uint32_t>(priority));
|
||||
|
||||
PendingTransactionImpl * transaction = new PendingTransactionImpl(*this);
|
||||
|
||||
do {
|
||||
std::vector<uint8_t> extra;
|
||||
std::string extra_nonce;
|
||||
vector<cryptonote::tx_destination_entry> dsts;
|
||||
|
||||
bool error = false;
|
||||
|
||||
crypto::key_image ki;
|
||||
if (!epee::string_tools::hex_to_pod(key_image, ki))
|
||||
{
|
||||
setStatusError(tr("failed to parse key image"));
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), dst_addr))
|
||||
{
|
||||
setStatusError(tr("Invalid destination address"));
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
if (info.has_payment_id) {
|
||||
if (!extra_nonce.empty()) {
|
||||
setStatusError(tr("a single transaction cannot use more than one payment id"));
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, info.payment_id);
|
||||
}
|
||||
if (error) {
|
||||
break;
|
||||
}
|
||||
if (!extra_nonce.empty() && !add_extra_nonce_to_tx_extra(extra, extra_nonce)) {
|
||||
setStatusError(tr("failed to set up payment id, though it was decoded correctly"));
|
||||
break;
|
||||
}
|
||||
try {
|
||||
transaction->m_pending_tx = m_wallet->create_transactions_single(ki, info.address, info.is_subaddress,
|
||||
outputs, fake_outs_count, 0 /* unlock time */, priority, extra);
|
||||
|
||||
pendingTxPostProcess(transaction);
|
||||
|
||||
if (multisig().isMultisig) {
|
||||
auto tx_set = m_wallet->make_multisig_tx_set(transaction->m_pending_tx);
|
||||
transaction->m_pending_tx = tx_set.m_ptx;
|
||||
transaction->m_signers = tx_set.m_signers;
|
||||
}
|
||||
} catch (const tools::error::daemon_busy&) {
|
||||
// TODO: make it translatable with "tr"?
|
||||
setStatusError(tr("daemon is busy. Please try again later."));
|
||||
} catch (const tools::error::no_connection_to_daemon&) {
|
||||
setStatusError(tr("no connection to daemon. Please make sure daemon is running."));
|
||||
} catch (const tools::error::wallet_rpc_error& e) {
|
||||
setStatusError(tr("RPC error: ") + e.to_string());
|
||||
} catch (const tools::error::get_outs_error &e) {
|
||||
setStatusError((boost::format(tr("failed to get outputs to mix: %s")) % e.what()).str());
|
||||
} catch (const tools::error::not_enough_unlocked_money& e) {
|
||||
std::ostringstream writer;
|
||||
|
||||
writer << boost::format(tr("not enough money to transfer, available only %s, sent amount %s")) %
|
||||
print_money(e.available()) %
|
||||
print_money(e.tx_amount());
|
||||
setStatusError(writer.str());
|
||||
} catch (const tools::error::not_enough_money& e) {
|
||||
std::ostringstream writer;
|
||||
|
||||
writer << boost::format(tr("not enough money to transfer, overall balance only %s, sent amount %s")) %
|
||||
print_money(e.available()) %
|
||||
print_money(e.tx_amount());
|
||||
setStatusError(writer.str());
|
||||
} catch (const tools::error::tx_not_possible& e) {
|
||||
std::ostringstream writer;
|
||||
|
||||
writer << boost::format(tr("not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee)")) %
|
||||
print_money(e.available()) %
|
||||
print_money(e.tx_amount() + e.fee()) %
|
||||
print_money(e.tx_amount()) %
|
||||
print_money(e.fee());
|
||||
setStatusError(writer.str());
|
||||
} catch (const tools::error::not_enough_outs_to_mix& e) {
|
||||
std::ostringstream writer;
|
||||
writer << tr("not enough outputs for specified ring size") << " = " << (e.mixin_count() + 1) << ":";
|
||||
for (const std::pair<uint64_t, uint64_t> outs_for_amount : e.scanty_outs()) {
|
||||
writer << "\n" << tr("output amount") << " = " << print_money(outs_for_amount.first) << ", " << tr("found outputs to use") << " = " << outs_for_amount.second;
|
||||
}
|
||||
writer << "\n" << tr("Please sweep unmixable outputs.");
|
||||
setStatusError(writer.str());
|
||||
} catch (const tools::error::tx_not_constructed&) {
|
||||
setStatusError(tr("transaction was not constructed"));
|
||||
} catch (const tools::error::tx_rejected& e) {
|
||||
std::ostringstream writer;
|
||||
writer << (boost::format(tr("transaction %s was rejected by daemon with status: ")) % get_transaction_hash(e.tx())) << e.status();
|
||||
setStatusError(writer.str());
|
||||
} catch (const tools::error::tx_sum_overflow& e) {
|
||||
setStatusError(e.what());
|
||||
} catch (const tools::error::zero_destination&) {
|
||||
setStatusError(tr("one of destinations is zero"));
|
||||
} catch (const tools::error::tx_too_big& e) {
|
||||
setStatusError(tr("failed to find a suitable way to split transactions"));
|
||||
} catch (const tools::error::transfer_error& e) {
|
||||
setStatusError(string(tr("unknown transfer error: ")) + e.what());
|
||||
} catch (const tools::error::wallet_internal_error& e) {
|
||||
setStatusError(string(tr("internal error: ")) + e.what());
|
||||
} catch (const std::exception& e) {
|
||||
setStatusError(string(tr("unexpected error: ")) + e.what());
|
||||
} catch (...) {
|
||||
setStatusError(tr("unknown error"));
|
||||
}
|
||||
} while (false);
|
||||
|
||||
statusWithErrorString(transaction->m_status, transaction->m_errorString);
|
||||
// Resume refresh thread
|
||||
startRefresh();
|
||||
return transaction;
|
||||
}
|
||||
|
||||
PendingTransaction *WalletImpl::createSweepUnmixableTransaction()
|
||||
|
||||
{
|
||||
|
@ -1824,6 +1977,11 @@ AddressBook *WalletImpl::addressBook()
|
|||
return m_addressBook.get();
|
||||
}
|
||||
|
||||
Coins *WalletImpl::coins()
|
||||
{
|
||||
return m_coins.get();
|
||||
}
|
||||
|
||||
Subaddress *WalletImpl::subaddress()
|
||||
{
|
||||
return m_subaddress.get();
|
||||
|
|
|
@ -46,6 +46,7 @@ class PendingTransactionImpl;
|
|||
class UnsignedTransactionImpl;
|
||||
class AddressBookImpl;
|
||||
class SubaddressImpl;
|
||||
class CoinsImpl;
|
||||
class SubaddressAccountImpl;
|
||||
struct Wallet2CallbackImpl;
|
||||
class PendingTransactionInfoImpl;
|
||||
|
@ -78,6 +79,10 @@ public:
|
|||
const std::string &address_string,
|
||||
const std::string &viewkey_string,
|
||||
const std::string &spendkey_string = "");
|
||||
bool recoverDeterministicWalletFromSpendKey(const std::string &path,
|
||||
const std::string &password,
|
||||
const std::string &language,
|
||||
const std::string &spendkey_string);
|
||||
bool recoverFromDevice(const std::string &path,
|
||||
const std::string &password,
|
||||
const std::string &device_name);
|
||||
|
@ -165,6 +170,10 @@ public:
|
|||
PendingTransaction::Priority priority = PendingTransaction::Priority_Low,
|
||||
uint32_t subaddr_account = 0,
|
||||
std::set<uint32_t> subaddr_indices = {}) override;
|
||||
|
||||
PendingTransaction * createTransactionSingle(const std::string &key_image, const std::string &dst_addr,
|
||||
size_t outputs = 1, PendingTransaction::Priority priority = PendingTransaction::Priority_Low) override;
|
||||
|
||||
virtual PendingTransaction * createSweepUnmixableTransaction() override;
|
||||
bool submitTransaction(const std::string &fileName) override;
|
||||
virtual UnsignedTransaction * loadUnsignedTx(const std::string &unsigned_filename) override;
|
||||
|
@ -181,6 +190,7 @@ public:
|
|||
PendingTransaction::Priority priority) const override;
|
||||
virtual TransactionHistory * history() override;
|
||||
virtual AddressBook * addressBook() override;
|
||||
virtual Coins * coins() override;
|
||||
virtual Subaddress * subaddress() override;
|
||||
virtual SubaddressAccount * subaddressAccount() override;
|
||||
virtual void setListener(WalletListener * l) override;
|
||||
|
@ -248,6 +258,7 @@ private:
|
|||
friend struct Wallet2CallbackImpl;
|
||||
friend class AddressBookImpl;
|
||||
friend class SubaddressImpl;
|
||||
friend class CoinsImpl;
|
||||
friend class SubaddressAccountImpl;
|
||||
friend class PendingTransactionInfoImpl;
|
||||
friend class TransactionConstructionInfoImpl;
|
||||
|
@ -261,6 +272,7 @@ private:
|
|||
std::unique_ptr<Wallet2CallbackImpl> m_wallet2Callback;
|
||||
std::unique_ptr<AddressBookImpl> m_addressBook;
|
||||
std::unique_ptr<SubaddressImpl> m_subaddress;
|
||||
std::unique_ptr<CoinsImpl> m_coins;
|
||||
std::unique_ptr<SubaddressAccountImpl> m_subaddressAccount;
|
||||
|
||||
// multi-threaded refresh stuff
|
||||
|
|
|
@ -249,6 +249,7 @@ struct TransactionInfo
|
|||
virtual std::string paymentId() const = 0;
|
||||
//! only applicable for output transactions
|
||||
virtual const std::vector<Transfer> & transfers() const = 0;
|
||||
virtual const std::vector<std::pair<std::string, std::vector<uint64_t>>> & rings() const = 0;
|
||||
};
|
||||
/**
|
||||
* @brief The TransactionHistory - interface for displaying transaction history
|
||||
|
@ -311,22 +312,66 @@ struct AddressBook
|
|||
virtual int lookupPaymentID(const std::string &payment_id) const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The CoinsInfo - interface for displaying coins information
|
||||
*/
|
||||
struct CoinsInfo
|
||||
{
|
||||
virtual ~CoinsInfo() = 0;
|
||||
|
||||
virtual uint64_t blockHeight() const = 0;
|
||||
virtual std::string hash() const = 0;
|
||||
virtual size_t internalOutputIndex() const = 0;
|
||||
virtual uint64_t globalOutputIndex() const = 0;
|
||||
virtual bool spent() const = 0;
|
||||
virtual bool frozen() const = 0;
|
||||
virtual uint64_t spentHeight() const = 0;
|
||||
virtual uint64_t amount() const = 0;
|
||||
virtual bool rct() const = 0;
|
||||
virtual bool keyImageKnown() const = 0;
|
||||
virtual size_t pkIndex() const = 0;
|
||||
virtual uint32_t subaddrIndex() const = 0;
|
||||
virtual uint32_t subaddrAccount() const = 0;
|
||||
virtual std::string address() const = 0;
|
||||
virtual std::string addressLabel() const = 0;
|
||||
virtual std::string keyImage() const = 0;
|
||||
virtual uint64_t unlockTime() const = 0;
|
||||
virtual bool unlocked() const = 0;
|
||||
virtual std::string pubKey() const = 0;
|
||||
virtual bool coinbase() const = 0;
|
||||
};
|
||||
|
||||
struct Coins
|
||||
{
|
||||
virtual ~Coins() = 0;
|
||||
virtual int count() const = 0;
|
||||
virtual CoinsInfo * coin(int index) const = 0;
|
||||
virtual std::vector<CoinsInfo*> getAll() const = 0;
|
||||
virtual void refresh() = 0;
|
||||
virtual void setFrozen(int index) = 0;
|
||||
virtual void thaw(int index) = 0;
|
||||
virtual bool isTransferUnlocked(uint64_t unlockTime, uint64_t blockHeight) = 0;
|
||||
};
|
||||
|
||||
struct SubaddressRow {
|
||||
public:
|
||||
SubaddressRow(std::size_t _rowId, const std::string &_address, const std::string &_label):
|
||||
SubaddressRow(std::size_t _rowId, const std::string &_address, const std::string &_label, bool _used):
|
||||
m_rowId(_rowId),
|
||||
m_address(_address),
|
||||
m_label(_label) {}
|
||||
m_label(_label),
|
||||
m_used(_used) {}
|
||||
|
||||
private:
|
||||
std::size_t m_rowId;
|
||||
std::string m_address;
|
||||
std::string m_label;
|
||||
bool m_used;
|
||||
public:
|
||||
std::string extra;
|
||||
std::string getAddress() const {return m_address;}
|
||||
std::string getLabel() const {return m_label;}
|
||||
std::size_t getRowId() const {return m_rowId;}
|
||||
bool isUsed() const {return m_used;}
|
||||
};
|
||||
|
||||
struct Subaddress
|
||||
|
@ -920,6 +965,18 @@ struct Wallet
|
|||
uint32_t subaddr_account = 0,
|
||||
std::set<uint32_t> subaddr_indices = {}) = 0;
|
||||
|
||||
/*!
|
||||
* \brief createTransactionSingle creates transaction with single input
|
||||
* \param key_image key image as string
|
||||
* \param dst_addr destination address as string
|
||||
* \param priority
|
||||
* \return PendingTransaction object. caller is responsible to check PendingTransaction::status()
|
||||
* after object returned
|
||||
*/
|
||||
|
||||
virtual PendingTransaction * createTransactionSingle(const std::string &key_image, const std::string &dst_addr,
|
||||
size_t outputs = 1, PendingTransaction::Priority = PendingTransaction::Priority_Low) = 0;
|
||||
|
||||
/*!
|
||||
* \brief createSweepUnmixableTransaction creates transaction with unmixable outputs.
|
||||
* \return PendingTransaction object. caller is responsible to check PendingTransaction::status()
|
||||
|
@ -1007,6 +1064,7 @@ struct Wallet
|
|||
|
||||
virtual TransactionHistory * history() = 0;
|
||||
virtual AddressBook * addressBook() = 0;
|
||||
virtual Coins * coins() = 0;
|
||||
virtual Subaddress * subaddress() = 0;
|
||||
virtual SubaddressAccount * subaddressAccount() = 0;
|
||||
virtual void setListener(WalletListener *) = 0;
|
||||
|
@ -1063,7 +1121,8 @@ struct Wallet
|
|||
/*
|
||||
* \brief signMessage - sign a message with the spend private key
|
||||
* \param message - the message to sign (arbitrary byte data)
|
||||
* \return the signature
|
||||
* \param address - the address to make the signature with, defaults to primary address (optional)
|
||||
* \return the signature, empty string if the address is invalid or does not belong to the wallet
|
||||
*/
|
||||
virtual std::string signMessage(const std::string &message) = 0;
|
||||
/*!
|
||||
|
@ -1264,6 +1323,25 @@ struct WalletManager
|
|||
return createWalletFromKeys(path, password, language, testnet ? TESTNET : MAINNET, restoreHeight, addressString, viewKeyString, spendKeyString);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief recover deterministic wallet from spend key.
|
||||
* \param path Name of wallet file to be created
|
||||
* \param password Password of wallet file
|
||||
* \param language language
|
||||
* \param nettype Network type
|
||||
* \param restoreHeight restore from start height
|
||||
* \param spendKeyString spend key
|
||||
* \param kdf_rounds Number of rounds for key derivation function
|
||||
* \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
|
||||
*/
|
||||
virtual Wallet * createDeterministicWalletFromSpendKey(const std::string &path,
|
||||
const std::string &password,
|
||||
const std::string &language,
|
||||
NetworkType nettype,
|
||||
uint64_t restoreHeight,
|
||||
const std::string &spendKeyString,
|
||||
uint64_t kdf_rounds = 1) = 0;
|
||||
|
||||
/*!
|
||||
* \deprecated this method creates a wallet WITHOUT a passphrase, use createWalletFromKeys(..., password, ...) instead
|
||||
* \brief recovers existing wallet using keys. Creates a view only wallet if spend key is omitted
|
||||
|
|
|
@ -122,6 +122,22 @@ Wallet *WalletManagerImpl::createWalletFromKeys(const std::string &path,
|
|||
return wallet;
|
||||
}
|
||||
|
||||
Wallet *WalletManagerImpl::createDeterministicWalletFromSpendKey(const std::string &path,
|
||||
const std::string &password,
|
||||
const std::string &language,
|
||||
NetworkType nettype,
|
||||
uint64_t restoreHeight,
|
||||
const std::string &spendkey_string,
|
||||
uint64_t kdf_rounds)
|
||||
{
|
||||
WalletImpl * wallet = new WalletImpl(nettype, kdf_rounds);
|
||||
if(restoreHeight > 0){
|
||||
wallet->setRefreshFromBlockHeight(restoreHeight);
|
||||
}
|
||||
wallet->recoverDeterministicWalletFromSpendKey(path, password, language, spendkey_string);
|
||||
return wallet;
|
||||
}
|
||||
|
||||
Wallet *WalletManagerImpl::createWalletFromDevice(const std::string &path,
|
||||
const std::string &password,
|
||||
NetworkType nettype,
|
||||
|
|
|
@ -67,6 +67,13 @@ public:
|
|||
const std::string &addressString,
|
||||
const std::string &viewKeyString,
|
||||
const std::string &spendKeyString = "") override;
|
||||
virtual Wallet * createDeterministicWalletFromSpendKey(const std::string &path,
|
||||
const std::string &password,
|
||||
const std::string &language,
|
||||
NetworkType nettype,
|
||||
uint64_t restoreHeight,
|
||||
const std::string &spendkey_string,
|
||||
uint64_t kdf_rounds) override;
|
||||
virtual Wallet * createWalletFromDevice(const std::string &path,
|
||||
const std::string &password,
|
||||
NetworkType nettype,
|
||||
|
|
|
@ -160,7 +160,7 @@ boost::optional<std::string> NodeRPCProxy::get_target_height(uint64_t &height)
|
|||
auto res = get_info();
|
||||
if (res)
|
||||
return res;
|
||||
height = m_target_height;
|
||||
height = m_target_height > m_height ? m_target_height : m_height;
|
||||
return boost::optional<std::string>();
|
||||
}
|
||||
|
||||
|
|
|
@ -1577,6 +1577,14 @@ void wallet2::add_subaddress_account(const std::string& label)
|
|||
m_subaddress_labels[index_major][0] = label;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::get_subaddress_used(const cryptonote::subaddress_index& index)
|
||||
{
|
||||
return std::find_if(m_transfers.begin(), m_transfers.end(),
|
||||
[this, index](const transfer_details &td) {
|
||||
return td.m_subaddr_index == index;
|
||||
}) != m_transfers.end();
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::add_subaddress(uint32_t index_major, const std::string& label)
|
||||
{
|
||||
THROW_WALLET_EXCEPTION_IF(index_major >= m_subaddress_labels.size(), error::account_index_outofbound);
|
||||
|
@ -2168,13 +2176,14 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
|||
uint64_t amount = tx.vout[o].amount ? tx.vout[o].amount : tx_scan_info[o].amount;
|
||||
if (!pool)
|
||||
{
|
||||
m_transfers.push_back(transfer_details{});
|
||||
transfer_details& td = m_transfers.back();
|
||||
td.m_block_height = height;
|
||||
td.m_internal_output_index = o;
|
||||
td.m_global_output_index = o_indices[o];
|
||||
td.m_tx = (const cryptonote::transaction_prefix&)tx;
|
||||
td.m_txid = txid;
|
||||
boost::unique_lock<boost::shared_mutex> lock(m_transfers_mutex);
|
||||
m_transfers.push_back(transfer_details{});
|
||||
transfer_details& td = m_transfers.back();
|
||||
td.m_block_height = height;
|
||||
td.m_internal_output_index = o;
|
||||
td.m_global_output_index = o_indices[o];
|
||||
td.m_tx = (const cryptonote::transaction_prefix&)tx;
|
||||
td.m_txid = txid;
|
||||
td.m_key_image = tx_scan_info[o].ki;
|
||||
td.m_key_image_known = !m_watch_only && !m_multisig;
|
||||
if (!td.m_key_image_known)
|
||||
|
@ -2270,12 +2279,13 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
|||
uint64_t extra_amount = amount - m_transfers[kit->second].amount();
|
||||
if (!pool)
|
||||
{
|
||||
boost::unique_lock<boost::shared_mutex> lock(m_transfers_mutex);
|
||||
transfer_details &td = m_transfers[kit->second];
|
||||
td.m_block_height = height;
|
||||
td.m_internal_output_index = o;
|
||||
td.m_global_output_index = o_indices[o];
|
||||
td.m_tx = (const cryptonote::transaction_prefix&)tx;
|
||||
td.m_txid = txid;
|
||||
td.m_block_height = height;
|
||||
td.m_internal_output_index = o;
|
||||
td.m_global_output_index = o_indices[o];
|
||||
td.m_tx = (const cryptonote::transaction_prefix&)tx;
|
||||
td.m_txid = txid;
|
||||
td.m_amount = amount;
|
||||
td.m_pk_index = pk_index - 1;
|
||||
td.m_subaddr_index = tx_scan_info[o].received->index;
|
||||
|
|
|
@ -907,6 +907,7 @@ private:
|
|||
std::string get_subaddress_as_str(const cryptonote::subaddress_index& index) const;
|
||||
std::string get_address_as_str() const { return get_subaddress_as_str({0, 0}); }
|
||||
std::string get_integrated_address_as_str(const crypto::hash8& payment_id) const;
|
||||
bool get_subaddress_used(const cryptonote::subaddress_index& index);
|
||||
void add_subaddress_account(const std::string& label);
|
||||
size_t get_num_subaddress_accounts() const { return m_subaddress_labels.size(); }
|
||||
size_t get_num_subaddresses(uint32_t index_major) const { return index_major < m_subaddress_labels.size() ? m_subaddress_labels[index_major].size() : 0; }
|
||||
|
@ -1552,6 +1553,7 @@ private:
|
|||
|
||||
static std::string get_default_daemon_address() { CRITICAL_REGION_LOCAL(default_daemon_address_lock); return default_daemon_address; }
|
||||
|
||||
boost::shared_mutex m_transfers_mutex;
|
||||
private:
|
||||
/*!
|
||||
* \brief Stores wallet information to wallet file.
|
||||
|
|
Loading…
Reference in a new issue