aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
authorRiccardo Spagni <ric@spagni.net>2018-03-05 19:11:20 +0200
committerRiccardo Spagni <ric@spagni.net>2018-03-05 19:11:20 +0200
commit4f93f745284c10f12e2524f5211030085d9626cf (patch)
tree29b5f359a8f346305bcf7bf82f459f421bfaa7a7 /src/wallet
parentMerge pull request #3273 (diff)
parentWallet API: generalize 'bool testnet' to 'NetworkType nettype' (diff)
downloadmonero-4f93f745284c10f12e2524f5211030085d9626cf.tar.xz
Merge pull request #3277
0e7ad2e2 Wallet API: generalize 'bool testnet' to 'NetworkType nettype' (stoffu) af773211 Stagenet (stoffu) cc9a0bee command_line: allow args to depend on more than one args (stoffu) 55f8d917 command_line::get_arg: remove 'required' for dependent args as they're always optional (stoffu) 450306a0 command line: allow has_arg to handle arg_descriptor<bool,false,true> #3318 (stoffu) 9f9e095a Use `genesis_tx` parameter in `generate_genesis_block`. #3261 (Jean Pierre Dudey)
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/api/address_book.cpp6
-rw-r--r--src/wallet/api/transaction_history.cpp2
-rw-r--r--src/wallet/api/unsigned_transaction.cpp8
-rw-r--r--src/wallet/api/wallet.cpp32
-rw-r--r--src/wallet/api/wallet.h4
-rw-r--r--src/wallet/api/wallet2_api.h89
-rw-r--r--src/wallet/api/wallet_manager.cpp24
-rw-r--r--src/wallet/api/wallet_manager.h12
-rw-r--r--src/wallet/wallet2.cpp115
-rw-r--r--src/wallet/wallet2.h11
-rw-r--r--src/wallet/wallet_errors.h16
-rw-r--r--src/wallet/wallet_rpc_server.cpp38
12 files changed, 221 insertions, 136 deletions
diff --git a/src/wallet/api/address_book.cpp b/src/wallet/api/address_book.cpp
index 38c34a912..7ef011e06 100644
--- a/src/wallet/api/address_book.cpp
+++ b/src/wallet/api/address_book.cpp
@@ -49,7 +49,7 @@ bool AddressBookImpl::addRow(const std::string &dst_addr , const std::string &pa
clearStatus();
cryptonote::address_parse_info info;
- if(!cryptonote::get_account_address_from_str(info, m_wallet->m_wallet->testnet(), dst_addr)) {
+ if(!cryptonote::get_account_address_from_str(info, m_wallet->m_wallet->nettype(), dst_addr)) {
m_errorString = tr("Invalid destination address");
m_errorCode = Invalid_Address;
return false;
@@ -105,13 +105,13 @@ void AddressBookImpl::refresh()
tools::wallet2::address_book_row * row = &rows.at(i);
std::string payment_id = (row->m_payment_id == crypto::null_hash)? "" : epee::string_tools::pod_to_hex(row->m_payment_id);
- std::string address = cryptonote::get_account_address_as_str(m_wallet->m_wallet->testnet(), row->m_is_subaddress, row->m_address);
+ std::string address = cryptonote::get_account_address_as_str(m_wallet->m_wallet->nettype(), row->m_is_subaddress, row->m_address);
// convert the zero padded short payment id to integrated address
if (!row->m_is_subaddress && payment_id.length() > 16 && payment_id.substr(16).find_first_not_of('0') == std::string::npos) {
payment_id = payment_id.substr(0,16);
crypto::hash8 payment_id_short;
if(tools::wallet2::parse_short_payment_id(payment_id, payment_id_short)) {
- address = cryptonote::get_account_integrated_address_as_str(m_wallet->m_wallet->testnet(), row->m_address, payment_id_short);
+ address = cryptonote::get_account_integrated_address_as_str(m_wallet->m_wallet->nettype(), row->m_address, payment_id_short);
// Don't show payment id when integrated address is used
payment_id = "";
}
diff --git a/src/wallet/api/transaction_history.cpp b/src/wallet/api/transaction_history.cpp
index 95a055f8f..ba46a6904 100644
--- a/src/wallet/api/transaction_history.cpp
+++ b/src/wallet/api/transaction_history.cpp
@@ -181,7 +181,7 @@ void TransactionHistoryImpl::refresh()
// single output transaction might contain multiple transfers
for (const auto &d: pd.m_dests) {
- ti->m_transfers.push_back({d.amount, get_account_address_as_str(m_wallet->m_wallet->testnet(), d.is_subaddress, d.addr)});
+ ti->m_transfers.push_back({d.amount, get_account_address_as_str(m_wallet->m_wallet->nettype(), d.is_subaddress, d.addr)});
}
m_history.push_back(ti);
}
diff --git a/src/wallet/api/unsigned_transaction.cpp b/src/wallet/api/unsigned_transaction.cpp
index c6ebcb009..29910a3b6 100644
--- a/src/wallet/api/unsigned_transaction.cpp
+++ b/src/wallet/api/unsigned_transaction.cpp
@@ -144,10 +144,10 @@ bool UnsignedTransactionImpl::checkLoadedTx(const std::function<size_t()> get_nu
for (size_t d = 0; d < cd.splitted_dsts.size(); ++d)
{
const cryptonote::tx_destination_entry &entry = cd.splitted_dsts[d];
- std::string address, standard_address = get_account_address_as_str(m_wallet.testnet(), entry.is_subaddress, entry.addr);
+ std::string address, standard_address = get_account_address_as_str(m_wallet.m_wallet->nettype(), entry.is_subaddress, entry.addr);
if (has_encrypted_payment_id && !entry.is_subaddress)
{
- address = get_account_integrated_address_as_str(m_wallet.testnet(), entry.addr, payment_id8);
+ address = get_account_integrated_address_as_str(m_wallet.m_wallet->nettype(), entry.addr, payment_id8);
address += std::string(" (" + standard_address + " with encrypted payment id " + epee::string_tools::pod_to_hex(payment_id8) + ")");
}
else
@@ -205,7 +205,7 @@ bool UnsignedTransactionImpl::checkLoadedTx(const std::function<size_t()> get_nu
std::string change_string;
if (change > 0)
{
- std::string address = get_account_address_as_str(m_wallet.m_wallet->testnet(), get_tx(0).subaddr_account > 0, get_tx(0).change_dts.addr);
+ std::string address = get_account_address_as_str(m_wallet.m_wallet->nettype(), get_tx(0).subaddr_account > 0, get_tx(0).change_dts.addr);
change_string += (boost::format(tr("%s change to %s")) % cryptonote::print_money(change) % address).str();
}
else
@@ -297,7 +297,7 @@ std::vector<std::string> UnsignedTransactionImpl::recipientAddress() const
MERROR("empty destinations, skipped");
continue;
}
- result.push_back(cryptonote::get_account_address_as_str(m_wallet.m_wallet->testnet(), utx.dests[0].is_subaddress, utx.dests[0].addr));
+ result.push_back(cryptonote::get_account_address_as_str(m_wallet.m_wallet->nettype(), utx.dests[0].is_subaddress, utx.dests[0].addr));
}
return result;
}
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 7f8144129..0ed6601af 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -233,16 +233,16 @@ bool Wallet::paymentIdValid(const string &paiment_id)
return false;
}
-bool Wallet::addressValid(const std::string &str, bool testnet)
+bool Wallet::addressValid(const std::string &str, NetworkType nettype)
{
cryptonote::address_parse_info info;
- return get_account_address_from_str(info, testnet, str);
+ return get_account_address_from_str(info, static_cast<cryptonote::network_type>(nettype), str);
}
-bool Wallet::keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, bool testnet, std::string &error)
+bool Wallet::keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, NetworkType nettype, std::string &error)
{
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, testnet, address_string)) {
+ if(!get_account_address_from_str(info, static_cast<cryptonote::network_type>(nettype), address_string)) {
error = tr("Failed to parse address");
return false;
}
@@ -275,10 +275,10 @@ bool Wallet::keyValid(const std::string &secret_key_string, const std::string &a
return true;
}
-std::string Wallet::paymentIdFromAddress(const std::string &str, bool testnet)
+std::string Wallet::paymentIdFromAddress(const std::string &str, NetworkType nettype)
{
cryptonote::address_parse_info info;
- if (!get_account_address_from_str(info, testnet, str))
+ if (!get_account_address_from_str(info, static_cast<cryptonote::network_type>(nettype), str))
return "";
if (!info.has_payment_id)
return "";
@@ -300,7 +300,7 @@ void Wallet::debug(const std::string &str) {
}
///////////////////////// WalletImpl implementation ////////////////////////
-WalletImpl::WalletImpl(bool testnet)
+WalletImpl::WalletImpl(NetworkType nettype)
:m_wallet(nullptr)
, m_status(Wallet::Status_Ok)
, m_trustedDaemon(false)
@@ -310,7 +310,7 @@ WalletImpl::WalletImpl(bool testnet)
, m_rebuildWalletCache(false)
, m_is_connected(false)
{
- m_wallet = new tools::wallet2(testnet);
+ m_wallet = new tools::wallet2(static_cast<cryptonote::network_type>(nettype));
m_history = new TransactionHistoryImpl(this);
m_wallet2Callback = new Wallet2CallbackImpl(this);
m_wallet->callback(m_wallet2Callback);
@@ -388,7 +388,7 @@ bool WalletImpl::create(const std::string &path, const std::string &password, co
bool WalletImpl::createWatchOnly(const std::string &path, const std::string &password, const std::string &language) const
{
clearStatus();
- std::unique_ptr<tools::wallet2> view_wallet(new tools::wallet2(m_wallet->testnet()));
+ std::unique_ptr<tools::wallet2> view_wallet(new tools::wallet2(m_wallet->nettype()));
// Store same refresh height as original wallet
view_wallet->set_refresh_from_block_height(m_wallet->get_refresh_from_block_height());
@@ -469,7 +469,7 @@ bool WalletImpl::recoverFromKeysWithPassword(const std::string &path,
const std::string &spendkey_string)
{
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, m_wallet->testnet(), address_string))
+ if(!get_account_address_from_str(info, m_wallet->nettype(), address_string))
{
m_errorString = tr("failed to parse address");
m_status = Status_Error;
@@ -1079,7 +1079,7 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const
PendingTransactionImpl * transaction = new PendingTransactionImpl(*this);
do {
- if(!cryptonote::get_account_address_from_str(info, m_wallet->testnet(), dst_addr)) {
+ if(!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), dst_addr)) {
// TODO: copy-paste 'if treating as an address fails, try as url' from simplewallet.cpp:1982
m_status = Status_Error;
m_errorString = "Invalid destination address";
@@ -1464,7 +1464,7 @@ bool WalletImpl::checkTxKey(const std::string &txid_str, std::string tx_key_str,
}
cryptonote::address_parse_info info;
- if (!cryptonote::get_account_address_from_str(info, m_wallet->testnet(), address_str))
+ if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address_str))
{
m_status = Status_Error;
m_errorString = tr("Failed to parse address");
@@ -1496,7 +1496,7 @@ std::string WalletImpl::getTxProof(const std::string &txid_str, const std::strin
}
cryptonote::address_parse_info info;
- if (!cryptonote::get_account_address_from_str(info, m_wallet->testnet(), address_str))
+ if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address_str))
{
m_status = Status_Error;
m_errorString = tr("Failed to parse address");
@@ -1527,7 +1527,7 @@ bool WalletImpl::checkTxProof(const std::string &txid_str, const std::string &ad
}
cryptonote::address_parse_info info;
- if (!cryptonote::get_account_address_from_str(info, m_wallet->testnet(), address_str))
+ if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address_str))
{
m_status = Status_Error;
m_errorString = tr("Failed to parse address");
@@ -1615,7 +1615,7 @@ std::string WalletImpl::getReserveProof(bool all, uint32_t account_index, uint64
bool WalletImpl::checkReserveProof(const std::string &address, const std::string &message, const std::string &signature, bool &good, uint64_t &total, uint64_t &spent) const {
cryptonote::address_parse_info info;
- if (!cryptonote::get_account_address_from_str(info, m_wallet->testnet(), address))
+ if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address))
{
m_status = Status_Error;
m_errorString = tr("Failed to parse address");
@@ -1652,7 +1652,7 @@ bool WalletImpl::verifySignedMessage(const std::string &message, const std::stri
{
cryptonote::address_parse_info info;
- if (!cryptonote::get_account_address_from_str(info, m_wallet->testnet(), address))
+ if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address))
return false;
return m_wallet->verify(message, info.address, signature);
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index fcd53c3f8..9b4a0cc12 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -52,7 +52,7 @@ struct Wallet2CallbackImpl;
class WalletImpl : public Wallet
{
public:
- WalletImpl(bool testnet = false);
+ WalletImpl(NetworkType nettype = MAINNET);
~WalletImpl();
bool create(const std::string &path, const std::string &password,
const std::string &language);
@@ -115,7 +115,7 @@ public:
void setRecoveringFromSeed(bool recoveringFromSeed);
bool watchOnly() const;
bool rescanSpent();
- bool testnet() const {return m_wallet->testnet();}
+ NetworkType nettype() const {return static_cast<NetworkType>(m_wallet->nettype());}
void hardForkInfo(uint8_t &version, uint64_t &earliest_height) const;
bool useForkRules(uint8_t version, int64_t early_blocks) const;
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
index 1c4545a25..a6320545e 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -40,6 +40,12 @@
// Public interface for libwallet library
namespace Monero {
+enum NetworkType : uint8_t {
+ MAINNET = 0,
+ TESTNET,
+ STAGENET
+};
+
namespace Utils {
bool isAddressLocal(const std::string &hostaddr);
void onStartup();
@@ -358,7 +364,10 @@ struct Wallet
virtual std::string address(uint32_t accountIndex = 0, uint32_t addressIndex = 0) const = 0;
std::string mainAddress() const { return address(0, 0); }
virtual std::string path() const = 0;
- virtual bool testnet() const = 0;
+ virtual NetworkType nettype() const = 0;
+ bool mainnet() const { return nettype() == MAINNET; }
+ bool testnet() const { return nettype() == TESTNET; }
+ bool stagenet() const { return nettype() == STAGENET; }
//! returns current hard fork info
virtual void hardForkInfo(uint8_t &version, uint64_t &earliest_height) const = 0;
//! check if hard fork rules should be used
@@ -529,9 +538,21 @@ struct Wallet
static uint64_t amountFromDouble(double amount);
static std::string genPaymentId();
static bool paymentIdValid(const std::string &paiment_id);
- static bool addressValid(const std::string &str, bool testnet);
- static bool keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, bool testnet, std::string &error);
- static std::string paymentIdFromAddress(const std::string &str, bool testnet);
+ static bool addressValid(const std::string &str, NetworkType nettype);
+ static bool addressValid(const std::string &str, bool testnet) // deprecated
+ {
+ return addressValid(str, testnet ? MAINNET : TESTNET);
+ }
+ static bool keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, NetworkType nettype, std::string &error);
+ static bool keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, bool testnet, std::string &error) // deprecated
+ {
+ return keyValid(secret_key_string, address_string, isViewKey, testnet ? TESTNET : MAINNET, error);
+ }
+ static std::string paymentIdFromAddress(const std::string &str, NetworkType nettype);
+ static std::string paymentIdFromAddress(const std::string &str, bool testnet) // deprecated
+ {
+ return paymentIdFromAddress(str, testnet ? TESTNET : MAINNET);
+ }
static uint64_t maximumAllowedAmount();
// Easylogger wrapper
static void init(const char *argv0, const char *default_log_base_name);
@@ -750,47 +771,66 @@ struct WalletManager
* \param path Name of wallet file
* \param password Password of wallet file
* \param language Language to be used to generate electrum seed mnemonic
+ * \param nettype Network type
* \return Wallet instance (Wallet::status() needs to be called to check if created successfully)
*/
- virtual Wallet * createWallet(const std::string &path, const std::string &password, const std::string &language, bool testnet = false) = 0;
+ virtual Wallet * createWallet(const std::string &path, const std::string &password, const std::string &language, NetworkType nettype = MAINNET) = 0;
+ Wallet * createWallet(const std::string &path, const std::string &password, const std::string &language, bool testnet = false) // deprecated
+ {
+ return createWallet(path, password, language, testnet ? TESTNET : MAINNET);
+ }
/*!
* \brief Opens existing wallet
* \param path Name of wallet file
* \param password Password of wallet file
+ * \param nettype Network type
* \return Wallet instance (Wallet::status() needs to be called to check if opened successfully)
*/
- virtual Wallet * openWallet(const std::string &path, const std::string &password, bool testnet = false) = 0;
+ virtual Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype = MAINNET) = 0;
+ Wallet * openWallet(const std::string &path, const std::string &password, bool testnet = false) // deprecated
+ {
+ return openWallet(path, password, testnet ? TESTNET : MAINNET);
+ }
/*!
* \brief recovers existing wallet using mnemonic (electrum seed)
* \param path Name of wallet file to be created
* \param password Password of wallet file
* \param mnemonic mnemonic (25 words electrum seed)
- * \param testnet testnet
+ * \param nettype Network type
* \param restoreHeight restore from start height
* \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
*/
virtual Wallet * recoveryWallet(const std::string &path, const std::string &password, const std::string &mnemonic,
- bool testnet = false, uint64_t restoreHeight = 0) = 0;
+ NetworkType nettype = MAINNET, uint64_t restoreHeight = 0) = 0;
+ Wallet * recoveryWallet(const std::string &path, const std::string &password, const std::string &mnemonic,
+ bool testnet = false, uint64_t restoreHeight = 0) // deprecated
+ {
+ return recoveryWallet(path, password, mnemonic, testnet ? TESTNET : MAINNET, restoreHeight);
+ }
/*!
* \deprecated this method creates a wallet WITHOUT a passphrase, use the alternate recoverWallet() method
* \brief recovers existing wallet using mnemonic (electrum seed)
* \param path Name of wallet file to be created
* \param mnemonic mnemonic (25 words electrum seed)
- * \param testnet testnet
+ * \param nettype Network type
* \param restoreHeight restore from start height
* \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
*/
- virtual Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, bool testnet = false, uint64_t restoreHeight = 0) = 0;
+ virtual Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, NetworkType nettype = MAINNET, uint64_t restoreHeight = 0) = 0;
+ Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, bool testnet = false, uint64_t restoreHeight = 0) // deprecated
+ {
+ return recoveryWallet(path, mnemonic, testnet ? TESTNET : MAINNET, restoreHeight);
+ }
/*!
* \brief recovers existing wallet using keys. Creates a view only wallet if spend key is omitted
* \param path Name of wallet file to be created
* \param password Password of wallet file
* \param language language
- * \param testnet testnet
+ * \param nettype Network type
* \param restoreHeight restore from start height
* \param addressString public address
* \param viewKeyString view key
@@ -800,18 +840,29 @@ struct WalletManager
virtual Wallet * createWalletFromKeys(const std::string &path,
const std::string &password,
const std::string &language,
- bool testnet,
+ NetworkType nettype,
uint64_t restoreHeight,
const std::string &addressString,
const std::string &viewKeyString,
const std::string &spendKeyString = "") = 0;
+ Wallet * createWalletFromKeys(const std::string &path,
+ const std::string &password,
+ const std::string &language,
+ bool testnet,
+ uint64_t restoreHeight,
+ const std::string &addressString,
+ const std::string &viewKeyString,
+ const std::string &spendKeyString = "") // deprecated
+ {
+ return createWalletFromKeys(path, password, language, testnet ? TESTNET : MAINNET, restoreHeight, addressString, viewKeyString, spendKeyString);
+ }
/*!
* \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
* \param path Name of wallet file to be created
* \param language language
- * \param testnet testnet
+ * \param nettype Network type
* \param restoreHeight restore from start height
* \param addressString public address
* \param viewKeyString view key
@@ -820,11 +871,21 @@ struct WalletManager
*/
virtual Wallet * createWalletFromKeys(const std::string &path,
const std::string &language,
- bool testnet,
+ NetworkType nettype,
uint64_t restoreHeight,
const std::string &addressString,
const std::string &viewKeyString,
const std::string &spendKeyString = "") = 0;
+ Wallet * createWalletFromKeys(const std::string &path,
+ const std::string &language,
+ bool testnet,
+ uint64_t restoreHeight,
+ const std::string &addressString,
+ const std::string &viewKeyString,
+ const std::string &spendKeyString = "") // deprecated
+ {
+ return createWalletFromKeys(path, language, testnet ? TESTNET : MAINNET, restoreHeight, addressString, viewKeyString, spendKeyString);
+ }
/*!
* \brief Closes wallet. In case operation succeeded, wallet object deleted. in case operation failed, wallet object not deleted
diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp
index 22bc343fb..5b6df8a9c 100644
--- a/src/wallet/api/wallet_manager.cpp
+++ b/src/wallet/api/wallet_manager.cpp
@@ -60,46 +60,46 @@ namespace {
namespace Monero {
Wallet *WalletManagerImpl::createWallet(const std::string &path, const std::string &password,
- const std::string &language, bool testnet)
+ const std::string &language, NetworkType nettype)
{
- WalletImpl * wallet = new WalletImpl(testnet);
+ WalletImpl * wallet = new WalletImpl(nettype);
wallet->create(path, password, language);
return wallet;
}
-Wallet *WalletManagerImpl::openWallet(const std::string &path, const std::string &password, bool testnet)
+Wallet *WalletManagerImpl::openWallet(const std::string &path, const std::string &password, NetworkType nettype)
{
- WalletImpl * wallet = new WalletImpl(testnet);
+ WalletImpl * wallet = new WalletImpl(nettype);
wallet->open(path, password);
//Refresh addressBook
wallet->addressBook()->refresh();
return wallet;
}
-Wallet *WalletManagerImpl::recoveryWallet(const std::string &path, const std::string &mnemonic, bool testnet, uint64_t restoreHeight)
+Wallet *WalletManagerImpl::recoveryWallet(const std::string &path, const std::string &mnemonic, NetworkType nettype, uint64_t restoreHeight)
{
- return recoveryWallet(path, "", mnemonic, testnet, restoreHeight);
+ return recoveryWallet(path, "", mnemonic, nettype, restoreHeight);
}
Wallet *WalletManagerImpl::createWalletFromKeys(const std::string &path,
const std::string &language,
- bool testnet,
+ NetworkType nettype,
uint64_t restoreHeight,
const std::string &addressString,
const std::string &viewKeyString,
const std::string &spendKeyString)
{
- return createWalletFromKeys(path, "", language, testnet, restoreHeight,
+ return createWalletFromKeys(path, "", language, nettype, restoreHeight,
addressString, viewKeyString, spendKeyString);
}
Wallet *WalletManagerImpl::recoveryWallet(const std::string &path,
const std::string &password,
const std::string &mnemonic,
- bool testnet,
+ NetworkType nettype,
uint64_t restoreHeight)
{
- WalletImpl * wallet = new WalletImpl(testnet);
+ WalletImpl * wallet = new WalletImpl(nettype);
if(restoreHeight > 0){
wallet->setRefreshFromBlockHeight(restoreHeight);
}
@@ -110,13 +110,13 @@ Wallet *WalletManagerImpl::recoveryWallet(const std::string &path,
Wallet *WalletManagerImpl::createWalletFromKeys(const std::string &path,
const std::string &password,
const std::string &language,
- bool testnet,
+ NetworkType nettype,
uint64_t restoreHeight,
const std::string &addressString,
const std::string &viewKeyString,
const std::string &spendKeyString)
{
- WalletImpl * wallet = new WalletImpl(testnet);
+ WalletImpl * wallet = new WalletImpl(nettype);
if(restoreHeight > 0){
wallet->setRefreshFromBlockHeight(restoreHeight);
}
diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h
index 6a4d9de2e..409a6d499 100644
--- a/src/wallet/api/wallet_manager.h
+++ b/src/wallet/api/wallet_manager.h
@@ -38,27 +38,27 @@ class WalletManagerImpl : public WalletManager
{
public:
Wallet * createWallet(const std::string &path, const std::string &password,
- const std::string &language, bool testnet);
- Wallet * openWallet(const std::string &path, const std::string &password, bool testnet);
+ const std::string &language, NetworkType nettype);
+ Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype);
virtual Wallet * recoveryWallet(const std::string &path,
const std::string &password,
const std::string &mnemonic,
- bool testnet,
+ NetworkType nettype,
uint64_t restoreHeight);
virtual Wallet * createWalletFromKeys(const std::string &path,
const std::string &password,
const std::string &language,
- bool testnet,
+ NetworkType nettype,
uint64_t restoreHeight,
const std::string &addressString,
const std::string &viewKeyString,
const std::string &spendKeyString = "");
// next two methods are deprecated - use the above version which allow setting of a password
- virtual Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, bool testnet, uint64_t restoreHeight);
+ virtual Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, NetworkType nettype, uint64_t restoreHeight);
// deprecated: use createWalletFromKeys(..., password, ...) instead
virtual Wallet * createWalletFromKeys(const std::string &path,
const std::string &language,
- bool testnet,
+ NetworkType nettype,
uint64_t restoreHeight,
const std::string &addressString,
const std::string &viewKeyString,
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 08924fffa..9b2595716 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -118,6 +118,7 @@ struct options {
const command_line::arg_descriptor<int> daemon_port = {"daemon-port", tools::wallet2::tr("Use daemon instance at port <arg> instead of 18081"), 0};
const command_line::arg_descriptor<std::string> daemon_login = {"daemon-login", tools::wallet2::tr("Specify username[:password] for daemon RPC client"), "", true};
const command_line::arg_descriptor<bool> testnet = {"testnet", tools::wallet2::tr("For testnet. Daemon must also be launched with --testnet flag"), false};
+ const command_line::arg_descriptor<bool> stagenet = {"stagenet", tools::wallet2::tr("For stagenet. Daemon must also be launched with --stagenet flag"), false};
const command_line::arg_descriptor<bool> restricted = {"restricted-rpc", tools::wallet2::tr("Restricts to view-only commands"), false};
};
@@ -159,6 +160,7 @@ std::string get_size_string(const cryptonote::blobdata &tx)
std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variables_map& vm, const options& opts, const std::function<boost::optional<tools::password_container>(const char *, bool)> &password_prompter)
{
const bool testnet = command_line::get_arg(vm, opts.testnet);
+ const bool stagenet = command_line::get_arg(vm, opts.stagenet);
const bool restricted = command_line::get_arg(vm, opts.restricted);
auto daemon_address = command_line::get_arg(vm, opts.daemon_address);
@@ -187,13 +189,13 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl
if (!daemon_port)
{
- daemon_port = testnet ? config::testnet::RPC_DEFAULT_PORT : config::RPC_DEFAULT_PORT;
+ daemon_port = testnet ? config::testnet::RPC_DEFAULT_PORT : stagenet ? config::stagenet::RPC_DEFAULT_PORT : config::RPC_DEFAULT_PORT;
}
if (daemon_address.empty())
daemon_address = std::string("http://") + daemon_host + ":" + std::to_string(daemon_port);
- std::unique_ptr<tools::wallet2> wallet(new tools::wallet2(testnet, restricted));
+ std::unique_ptr<tools::wallet2> wallet(new tools::wallet2(testnet ? TESTNET : stagenet ? STAGENET : MAINNET, restricted));
wallet->init(std::move(daemon_address), std::move(login));
return wallet;
}
@@ -230,6 +232,8 @@ boost::optional<tools::password_container> get_password(const boost::program_opt
std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file, const boost::program_options::variables_map& vm, const options& opts, const std::function<boost::optional<tools::password_container>(const char *, bool)> &password_prompter)
{
const bool testnet = command_line::get_arg(vm, opts.testnet);
+ const bool stagenet = command_line::get_arg(vm, opts.stagenet);
+ const network_type nettype = testnet ? TESTNET : stagenet ? STAGENET : MAINNET;
/* GET_FIELD_FROM_JSON_RETURN_ON_ERROR Is a generic macro that can return
false. Gcc will coerce this into unique_ptr(nullptr), but clang correctly
@@ -329,7 +333,7 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file,
if (field_address_found)
{
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, testnet, field_address))
+ if(!get_account_address_from_str(info, nettype, field_address))
{
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("invalid address"));
}
@@ -388,7 +392,7 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file,
if (field_address_found)
{
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, testnet, field_address))
+ if(!get_account_address_from_str(info, nettype, field_address))
{
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, std::string(tools::wallet2::tr("failed to parse address: ")) + field_address);
}
@@ -589,12 +593,12 @@ 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"); }
-wallet2::wallet2(bool testnet, bool restricted):
+wallet2::wallet2(network_type nettype, bool restricted):
m_multisig_rescan_info(NULL),
m_multisig_rescan_k(NULL),
m_run(true),
m_callback(0),
- m_testnet(testnet),
+ m_nettype(nettype),
m_always_confirm_transfers(true),
m_print_ring_members(false),
m_store_tx_info(true),
@@ -634,6 +638,11 @@ bool wallet2::has_testnet_option(const boost::program_options::variables_map& vm
return command_line::get_arg(vm, options().testnet);
}
+bool wallet2::has_stagenet_option(const boost::program_options::variables_map& vm)
+{
+ return command_line::get_arg(vm, options().stagenet);
+}
+
void wallet2::init_options(boost::program_options::options_description& desc_params)
{
const options opts{};
@@ -644,6 +653,7 @@ void wallet2::init_options(boost::program_options::options_description& desc_par
command_line::add_arg(desc_params, opts.daemon_port);
command_line::add_arg(desc_params, opts.daemon_login);
command_line::add_arg(desc_params, opts.testnet);
+ command_line::add_arg(desc_params, opts.stagenet);
command_line::add_arg(desc_params, opts.restricted);
}
@@ -690,7 +700,7 @@ std::unique_ptr<wallet2> wallet2::make_dummy(const boost::program_options::varia
//----------------------------------------------------------------------------------------------------
bool wallet2::init(std::string daemon_address, boost::optional<epee::net_utils::http::login> daemon_login, uint64_t upper_transaction_size_limit, bool ssl)
{
- m_checkpoints.init_default_checkpoints(m_testnet);
+ m_checkpoints.init_default_checkpoints(m_nettype);
if(m_http_client.is_connected())
m_http_client.disconnect();
m_is_initialized = true;
@@ -836,12 +846,12 @@ crypto::public_key wallet2::get_subaddress_spend_public_key(const cryptonote::su
std::string wallet2::get_subaddress_as_str(const cryptonote::subaddress_index& index) const
{
cryptonote::account_public_address address = get_subaddress(index);
- return cryptonote::get_account_address_as_str(m_testnet, !index.is_zero(), address);
+ return cryptonote::get_account_address_as_str(m_nettype, !index.is_zero(), address);
}
//----------------------------------------------------------------------------------------------------
std::string wallet2::get_integrated_address_as_str(const crypto::hash8& payment_id) const
{
- return cryptonote::get_account_integrated_address_as_str(m_testnet, get_address(), payment_id);
+ return cryptonote::get_account_integrated_address_as_str(m_nettype, get_address(), payment_id);
}
//----------------------------------------------------------------------------------------------------
void wallet2::add_subaddress_account(const std::string& label)
@@ -2441,8 +2451,8 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable
value2.SetInt(m_auto_low_priority ? 1 : 0);
json.AddMember("auto_low_priority", value2, json.GetAllocator());
- value2.SetInt(m_testnet ? 1 :0);
- json.AddMember("testnet", value2, json.GetAllocator());
+ value2.SetUint(m_nettype);
+ json.AddMember("nettype", value2, json.GetAllocator());
// Serialize the JSON object
rapidjson::StringBuffer buffer;
@@ -2624,11 +2634,12 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
m_confirm_export_overwrite = field_confirm_export_overwrite;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, auto_low_priority, int, Int, false, true);
m_auto_low_priority = field_auto_low_priority;
- GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, testnet, int, Int, false, m_testnet);
- // Wallet is being opened with testnet flag, but is saved as a mainnet wallet
- THROW_WALLET_EXCEPTION_IF(m_testnet && !field_testnet, error::wallet_internal_error, "Mainnet wallet can not be opened as testnet wallet");
- // Wallet is being opened without testnet flag but is saved as a testnet wallet.
- THROW_WALLET_EXCEPTION_IF(!m_testnet && field_testnet, error::wallet_internal_error, "Testnet wallet can not be opened as mainnet wallet");
+ GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, nettype, uint8_t, Uint, false, static_cast<uint8_t>(m_nettype));
+ // The network type given in the program argument is inconsistent with the network type saved in the wallet
+ THROW_WALLET_EXCEPTION_IF(static_cast<uint8_t>(m_nettype) != field_nettype, error::wallet_internal_error,
+ (boost::format("%s wallet can not be opened as %s wallet")
+ % (field_nettype == 0 ? "Mainnet" : field_nettype == 1 ? "Testnet" : "Stagenet")
+ % (m_nettype == MAINNET ? "mainnet" : m_nettype == TESTNET ? "testnet" : "stagenet")).str());
}
else
{
@@ -2801,7 +2812,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
bool r = store_keys(m_keys_file, password, false);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
- r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_testnet));
+ r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype));
if(!r) MERROR("String with address text not saved");
}
@@ -2855,7 +2866,7 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip
bool r = store_keys(m_keys_file, password, false);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
- r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_testnet));
+ r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype));
if(!r) MERROR("String with address text not saved");
}
@@ -2945,7 +2956,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
bool r = store_keys(m_keys_file, password, true);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
- r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_testnet));
+ r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype));
if(!r) MERROR("String with address text not saved");
}
@@ -2992,7 +3003,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
bool r = store_keys(m_keys_file, password, false);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
- r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_testnet));
+ r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype));
if(!r) MERROR("String with address text not saved");
}
@@ -3033,7 +3044,7 @@ void wallet2::restore(const std::string& wallet_, const epee::wipeable_string& p
bool r = store_keys(m_keys_file, password, false);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
- r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_testnet));
+ r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype));
if(!r) MERROR("String with address text not saved");
}
cryptonote::block b;
@@ -3125,7 +3136,7 @@ std::string wallet2::make_multisig(const epee::wipeable_string &password,
bool r = store_keys(m_keys_file, password, false);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
- r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_testnet));
+ r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype));
if(!r) MERROR("String with address text not saved");
}
@@ -3225,7 +3236,7 @@ bool wallet2::finalize_multisig(const epee::wipeable_string &password, std::unor
bool r = store_keys(m_keys_file, password, false);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
- r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_testnet));
+ r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype));
if(!r) MERROR("String with address text not saved");
}
@@ -3535,7 +3546,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
{
THROW_WALLET_EXCEPTION_IF(true, error::file_read_error, m_keys_file);
}
- LOG_PRINT_L0("Loaded wallet keys file, with public address: " << m_account.get_public_address_str(m_testnet));
+ LOG_PRINT_L0("Loaded wallet keys file, with public address: " << m_account.get_public_address_str(m_nettype));
//keys loaded ok!
//try to load wallet file. but even if we failed, it is not big problem
@@ -3674,7 +3685,7 @@ void wallet2::trim_hashchain()
}
//----------------------------------------------------------------------------------------------------
void wallet2::check_genesis(const crypto::hash& genesis_hash) const {
- std::string what("Genesis block mismatch. You probably use wallet without testnet flag with blockchain from test network or vice versa");
+ std::string what("Genesis block mismatch. You probably use wallet without testnet (or stagenet) flag with blockchain from test (or stage) network or vice versa");
THROW_WALLET_EXCEPTION_IF(genesis_hash != m_blockchain.genesis(), error::wallet_internal_error, what);
}
@@ -3751,7 +3762,7 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
// save address to the new file
const std::string address_file = m_wallet_file + ".address.txt";
- r = file_io_utils::save_string_to_file(address_file, m_account.get_public_address_str(m_testnet));
+ r = file_io_utils::save_string_to_file(address_file, m_account.get_public_address_str(m_nettype));
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_wallet_file);
// remove old wallet file
r = boost::filesystem::remove(old_file);
@@ -4028,7 +4039,7 @@ bool wallet2::is_tx_spendtime_unlocked(uint64_t unlock_time, uint64_t block_heig
uint64_t current_time = static_cast<uint64_t>(time(NULL));
// XXX: this needs to be fast, so we'd need to get the starting heights
// from the daemon to be correct once voting kicks in
- uint64_t v2height = m_testnet ? 624634 : 1009827;
+ uint64_t v2height = m_nettype == TESTNET ? 624634 : m_nettype == STAGENET ? (uint64_t)-1/*TODO*/ : 1009827;
uint64_t leeway = block_height < v2height ? CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V1 : CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V2;
if(current_time + leeway >= unlock_time)
return true;
@@ -4316,7 +4327,7 @@ void wallet2::commit_tx(pending_tx& ptx)
{
cryptonote::COMMAND_RPC_SUBMIT_RAW_TX::request oreq;
cryptonote::COMMAND_RPC_SUBMIT_RAW_TX::response ores;
- oreq.address = get_account().get_public_address_str(m_testnet);
+ oreq.address = get_account().get_public_address_str(m_nettype);
oreq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
oreq.tx = epee::string_tools::buff_to_hex_nodelimer(tx_to_blob(ptx.tx));
m_daemon_rpc_mutex.lock();
@@ -4526,7 +4537,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, const std::string &signed_f
std::vector<crypto::secret_key> additional_tx_keys;
rct::multisig_out msout;
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sd.sources, sd.splitted_dsts, sd.change_dts.addr, sd.extra, ptx.tx, sd.unlock_time, tx_key, additional_tx_keys, sd.use_rct, bulletproof, m_multisig ? &msout : NULL);
- THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_nettype);
// we don't test tx size, because we don't know the current limit, due to not having a blockchain,
// and it's a bit pointless to fail there anyway, since it'd be a (good) guess only. We sign anyway,
// and if we really go over limit, the daemon will reject when it gets submitted. Chances are it's
@@ -4899,7 +4910,7 @@ bool wallet2::sign_multisig_tx(multisig_tx_set &exported_txs, std::vector<crypto
auto sources = sd.sources;
const bool bulletproof = sd.use_rct && (ptx.tx.rct_signatures.type == rct::RCTTypeFullBulletproof || ptx.tx.rct_signatures.type == rct::RCTTypeSimpleBulletproof);
bool r = cryptonote::construct_tx_with_tx_key(m_account.get_keys(), m_subaddresses, sources, sd.splitted_dsts, ptx.change_dts.addr, sd.extra, tx, sd.unlock_time, ptx.tx_key, ptx.additional_tx_keys, sd.use_rct, bulletproof, &msout);
- THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_nettype);
THROW_WALLET_EXCEPTION_IF(get_transaction_prefix_hash (tx) != get_transaction_prefix_hash(ptx.tx),
error::wallet_internal_error, "Transaction prefix does not match data");
@@ -5645,7 +5656,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination);
needed_money += dt.amount;
LOG_PRINT_L2("transfer: adding " << print_money(dt.amount) << ", for a total of " << print_money (needed_money));
- THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_nettype);
}
uint64_t found_money = 0;
@@ -5738,7 +5749,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
LOG_PRINT_L2("constructing tx");
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sources, splitted_dsts, change_dts.addr, extra, tx, unlock_time, tx_key, additional_tx_keys, false, false, m_multisig ? &msout : NULL);
LOG_PRINT_L2("constructed tx, r="<<r);
- THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_nettype);
THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
std::string key_images;
@@ -5802,7 +5813,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination);
needed_money += dt.amount;
LOG_PRINT_L2("transfer: adding " << print_money(dt.amount) << ", for a total of " << print_money (needed_money));
- THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_nettype);
}
// if this is a multisig wallet, create a list of multisig signers we can use
@@ -5942,7 +5953,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
auto sources_copy = sources;
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sources, splitted_dsts, change_dts.addr, extra, tx, unlock_time, tx_key, additional_tx_keys, true, bulletproof, m_multisig ? &msout : NULL);
LOG_PRINT_L2("constructed tx, r="<<r);
- THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, dsts, unlock_time, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, dsts, unlock_time, m_nettype);
THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
// work out the permutation done on sources
@@ -5987,7 +5998,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
auto sources_copy_copy = sources_copy;
bool r = cryptonote::construct_tx_with_tx_key(m_account.get_keys(), m_subaddresses, sources_copy_copy, splitted_dsts, change_dts.addr, extra, ms_tx, unlock_time,tx_key, additional_tx_keys, true, bulletproof, &msout);
LOG_PRINT_L2("constructed tx, r="<<r);
- THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_nettype);
THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
THROW_WALLET_EXCEPTION_IF(cryptonote::get_transaction_prefix_hash(ms_tx) != prefix_hash, error::wallet_internal_error, "Multisig txes do not share prefix");
multisig_sigs.push_back({ms_tx.rct_signatures, multisig_signers[signer_index], new_used_L, std::unordered_set<crypto::public_key>(), msout});
@@ -6157,7 +6168,7 @@ bool wallet2::light_wallet_login(bool &new_address)
m_light_wallet_connected = false;
cryptonote::COMMAND_RPC_LOGIN::request request;
cryptonote::COMMAND_RPC_LOGIN::response response;
- request.address = get_account().get_public_address_str(m_testnet);
+ request.address = get_account().get_public_address_str(m_nettype);
request.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
// Always create account if it doesn't exist.
request.create_account = true;
@@ -6184,7 +6195,7 @@ bool wallet2::light_wallet_import_wallet_request(cryptonote::COMMAND_RPC_IMPORT_
{
MDEBUG("Light wallet import wallet request");
cryptonote::COMMAND_RPC_IMPORT_WALLET_REQUEST::request oreq;
- oreq.address = get_account().get_public_address_str(m_testnet);
+ oreq.address = get_account().get_public_address_str(m_nettype);
oreq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
m_daemon_rpc_mutex.lock();
bool r = epee::net_utils::invoke_http_json("/import_wallet_request", oreq, response, m_http_client, rpc_timeout, "POST");
@@ -6203,7 +6214,7 @@ void wallet2::light_wallet_get_unspent_outs()
cryptonote::COMMAND_RPC_GET_UNSPENT_OUTS::response ores;
oreq.amount = "0";
- oreq.address = get_account().get_public_address_str(m_testnet);
+ oreq.address = get_account().get_public_address_str(m_nettype);
oreq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
// openMonero specific
oreq.dust_threshold = boost::lexical_cast<std::string>(::config::DEFAULT_DUST_THRESHOLD);
@@ -6353,7 +6364,7 @@ bool wallet2::light_wallet_get_address_info(cryptonote::COMMAND_RPC_GET_ADDRESS_
cryptonote::COMMAND_RPC_GET_ADDRESS_INFO::request request;
- request.address = get_account().get_public_address_str(m_testnet);
+ request.address = get_account().get_public_address_str(m_nettype);
request.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
m_daemon_rpc_mutex.lock();
bool r = epee::net_utils::invoke_http_json("/get_address_info", request, response, m_http_client, rpc_timeout, "POST");
@@ -6370,7 +6381,7 @@ void wallet2::light_wallet_get_address_txs()
cryptonote::COMMAND_RPC_GET_ADDRESS_TXS::request ireq;
cryptonote::COMMAND_RPC_GET_ADDRESS_TXS::response ires;
- ireq.address = get_account().get_public_address_str(m_testnet);
+ ireq.address = get_account().get_public_address_str(m_nettype);
ireq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
m_daemon_rpc_mutex.lock();
bool r = epee::net_utils::invoke_http_json("/get_address_txs", ireq, ires, m_http_client, rpc_timeout, "POST");
@@ -6695,7 +6706,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination);
needed_money += dt.amount;
LOG_PRINT_L2("transfer: adding " << print_money(dt.amount) << ", for a total of " << print_money (needed_money));
- THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, 0, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, 0, m_nettype);
}
// throw if attempting a transaction with no money
@@ -6923,7 +6934,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
while (!dsts.empty() && dsts[0].amount <= available_amount && estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size(), extra.size(), bulletproof) < TX_SIZE_TARGET(upper_transaction_size_limit))
{
// we can fully pay that destination
- LOG_PRINT_L2("We can fully pay " << get_account_address_as_str(m_testnet, dsts[0].is_subaddress, dsts[0].addr) <<
+ LOG_PRINT_L2("We can fully pay " << get_account_address_as_str(m_nettype, dsts[0].is_subaddress, dsts[0].addr) <<
" for " << print_money(dsts[0].amount));
tx.add(dsts[0].addr, dsts[0].is_subaddress, dsts[0].amount, original_output_index, m_merge_destinations);
available_amount -= dsts[0].amount;
@@ -6934,7 +6945,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
if (available_amount > 0 && !dsts.empty() && estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size(), extra.size(), bulletproof) < TX_SIZE_TARGET(upper_transaction_size_limit)) {
// we can partially fill that destination
- LOG_PRINT_L2("We can partially pay " << get_account_address_as_str(m_testnet, dsts[0].is_subaddress, dsts[0].addr) <<
+ LOG_PRINT_L2("We can partially pay " << get_account_address_as_str(m_nettype, dsts[0].is_subaddress, dsts[0].addr) <<
" for " << print_money(available_amount) << "/" << print_money(dsts[0].amount));
tx.add(dsts[0].addr, dsts[0].is_subaddress, available_amount, original_output_index, m_merge_destinations);
dsts[0].amount -= available_amount;
@@ -7004,7 +7015,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
if (i->amount > needed_fee)
{
uint64_t new_paid_amount = i->amount /*+ test_ptx.fee*/ - needed_fee;
- LOG_PRINT_L2("Adjusting amount paid to " << get_account_address_as_str(m_testnet, i->is_subaddress, i->addr) << " from " <<
+ LOG_PRINT_L2("Adjusting amount paid to " << get_account_address_as_str(m_nettype, i->is_subaddress, i->addr) << " from " <<
print_money(i->amount) << " to " << print_money(new_paid_amount) << " to accommodate " <<
print_money(needed_fee) << " fee");
dsts[0].amount += i->amount - new_paid_amount;
@@ -8431,16 +8442,16 @@ uint64_t wallet2::get_daemon_blockchain_target_height(string &err)
uint64_t wallet2::get_approximate_blockchain_height() const
{
// time of v2 fork
- const time_t fork_time = m_testnet ? 1448285909 : 1458748658;
+ const time_t fork_time = m_nettype == TESTNET ? 1448285909 : m_nettype == STAGENET ? (time_t)-1/*TODO*/ : 1458748658;
// v2 fork block
- const uint64_t fork_block = m_testnet ? 624634 : 1009827;
+ const uint64_t fork_block = m_nettype == TESTNET ? 624634 : m_nettype == STAGENET ? (uint64_t)-1/*TODO*/ : 1009827;
// avg seconds per block
const int seconds_per_block = DIFFICULTY_TARGET_V2;
// Calculated blockchain height
uint64_t approx_blockchain_height = fork_block + (time(NULL) - fork_time)/seconds_per_block;
// testnet got some huge rollbacks, so the estimation is way off
static const uint64_t approximate_testnet_rolled_back_blocks = 148540;
- if (m_testnet && approx_blockchain_height > approximate_testnet_rolled_back_blocks)
+ if (m_nettype == TESTNET && approx_blockchain_height > approximate_testnet_rolled_back_blocks)
approx_blockchain_height -= approximate_testnet_rolled_back_blocks;
LOG_PRINT_L2("Calculated blockchain height: " << approx_blockchain_height);
return approx_blockchain_height;
@@ -9421,7 +9432,7 @@ std::string wallet2::decrypt_with_view_secret_key(const std::string &ciphertext,
std::string wallet2::make_uri(const std::string &address, const std::string &payment_id, uint64_t amount, const std::string &tx_description, const std::string &recipient_name, std::string &error) const
{
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, testnet(), address))
+ if(!get_account_address_from_str(info, nettype(), address))
{
error = std::string("wrong address: ") + address;
return std::string();
@@ -9485,7 +9496,7 @@ bool wallet2::parse_uri(const std::string &uri, std::string &address, std::strin
address = ptr ? remainder.substr(0, ptr-remainder.c_str()) : remainder;
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, testnet(), address))
+ if(!get_account_address_from_str(info, nettype(), address))
{
error = std::string("URI has wrong address: ") + address;
return false;
@@ -9734,10 +9745,14 @@ std::vector<std::pair<uint64_t, uint64_t>> wallet2::estimate_backlog(uint64_t mi
}
//----------------------------------------------------------------------------------------------------
void wallet2::generate_genesis(cryptonote::block& b) const {
- if (m_testnet)
+ if (m_nettype == TESTNET)
{
cryptonote::generate_genesis_block(b, config::testnet::GENESIS_TX, config::testnet::GENESIS_NONCE);
}
+ else if (m_nettype == STAGENET)
+ {
+ cryptonote::generate_genesis_block(b, config::stagenet::GENESIS_TX, config::stagenet::GENESIS_NONCE);
+ }
else
{
cryptonote::generate_genesis_block(b, config::GENESIS_TX, config::GENESIS_NONCE);
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 127e70a26..57a61cb9d 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -147,6 +147,7 @@ namespace tools
static const char* tr(const char* str);
static bool has_testnet_option(const boost::program_options::variables_map& vm);
+ static bool has_stagenet_option(const boost::program_options::variables_map& vm);
static void init_options(boost::program_options::options_description& desc_params);
//! Uses stdin and stdout. Returns a wallet2 if no errors.
@@ -164,7 +165,7 @@ namespace tools
static bool verify_password(const std::string& keys_file_name, const epee::wipeable_string& password, bool no_spend_key, hw::device &hwdev);
- wallet2(bool testnet = false, bool restricted = false);
+ wallet2(cryptonote::network_type nettype = cryptonote::MAINNET, bool restricted = false);
struct multisig_info
{
@@ -637,7 +638,7 @@ namespace tools
void set_refresh_type(RefreshType refresh_type) { m_refresh_type = refresh_type; }
RefreshType get_refresh_type() const { return m_refresh_type; }
- bool testnet() const { return m_testnet; }
+ cryptonote::network_type nettype() const { return m_nettype; }
bool restricted() const { return m_restricted; }
bool watch_only() const { return m_watch_only; }
bool multisig(bool *ready = NULL, uint32_t *threshold = NULL, uint32_t *total = NULL) const;
@@ -1115,7 +1116,7 @@ namespace tools
i_wallet2_callback* m_callback;
bool m_key_on_device;
- bool m_testnet;
+ cryptonote::network_type m_nettype;
bool m_restricted;
std::string seed_language; /*!< Language of the mnemonics (seed). */
bool is_old_file_format; /*!< Whether the wallet file is of an old file format */
@@ -1646,7 +1647,7 @@ namespace tools
{
THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination);
needed_money += dt.amount;
- THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_nettype);
}
// randomly select inputs for transaction
@@ -1768,7 +1769,7 @@ namespace tools
std::vector<crypto::secret_key> additional_tx_keys;
rct::multisig_out msout;
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sources, splitted_dsts, change_dts.addr, extra, tx, unlock_time, tx_key, additional_tx_keys, false, false, m_multisig ? &msout : NULL);
- THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_nettype);
THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
std::string key_images;
diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h
index 5c1c49d5d..32a0231b1 100644
--- a/src/wallet/wallet_errors.h
+++ b/src/wallet/wallet_errors.h
@@ -529,13 +529,13 @@ namespace tools
, sources_t const & sources
, destinations_t const & destinations
, uint64_t unlock_time
- , bool testnet
+ , cryptonote::network_type nettype
)
: transfer_error(std::move(loc), "transaction was not constructed")
, m_sources(sources)
, m_destinations(destinations)
, m_unlock_time(unlock_time)
- , m_testnet(testnet)
+ , m_nettype(nettype)
{
}
@@ -569,7 +569,7 @@ namespace tools
for (size_t i = 0; i < m_destinations.size(); ++i)
{
const cryptonote::tx_destination_entry& dst = m_destinations[i];
- ss << "\n " << i << ": " << cryptonote::get_account_address_as_str(m_testnet, dst.is_subaddress, dst.addr) << " " <<
+ ss << "\n " << i << ": " << cryptonote::get_account_address_as_str(m_nettype, dst.is_subaddress, dst.addr) << " " <<
cryptonote::print_money(dst.amount);
}
@@ -582,7 +582,7 @@ namespace tools
sources_t m_sources;
destinations_t m_destinations;
uint64_t m_unlock_time;
- bool m_testnet;
+ cryptonote::network_type m_nettype;
};
//----------------------------------------------------------------------------------------------------
struct tx_rejected : public transfer_error
@@ -624,12 +624,12 @@ namespace tools
std::string && loc
, const std::vector<cryptonote::tx_destination_entry>& destinations
, uint64_t fee
- , bool testnet
+ , cryptonote::network_type nettype
)
: transfer_error(std::move(loc), "transaction sum + fee exceeds " + cryptonote::print_money(std::numeric_limits<uint64_t>::max()))
, m_destinations(destinations)
, m_fee(fee)
- , m_testnet(testnet)
+ , m_nettype(nettype)
{
}
@@ -644,7 +644,7 @@ namespace tools
", destinations:";
for (const auto& dst : m_destinations)
{
- ss << '\n' << cryptonote::print_money(dst.amount) << " -> " << cryptonote::get_account_address_as_str(m_testnet, dst.is_subaddress, dst.addr);
+ ss << '\n' << cryptonote::print_money(dst.amount) << " -> " << cryptonote::get_account_address_as_str(m_nettype, dst.is_subaddress, dst.addr);
}
return ss.str();
}
@@ -652,7 +652,7 @@ namespace tools
private:
std::vector<cryptonote::tx_destination_entry> m_destinations;
uint64_t m_fee;
- bool m_testnet;
+ cryptonote::network_type m_nettype;
};
//----------------------------------------------------------------------------------------------------
struct tx_too_big : public transfer_error
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 6d5419521..b50133e4a 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -280,7 +280,7 @@ namespace tools
entry.destinations.push_back(wallet_rpc::transfer_destination());
wallet_rpc::transfer_destination &td = entry.destinations.back();
td.amount = d.amount;
- td.address = get_account_address_as_str(m_wallet->testnet(), d.is_subaddress, d.addr);
+ td.address = get_account_address_as_str(m_wallet->nettype(), d.is_subaddress, d.addr);
}
entry.type = "out";
@@ -584,7 +584,7 @@ namespace tools
cryptonote::address_parse_info info;
cryptonote::tx_destination_entry de;
er.message = "";
- if(!get_account_address_from_str_or_url(info, m_wallet->testnet(), it->address,
+ if(!get_account_address_from_str_or_url(info, m_wallet->nettype(), it->address,
[&er](const std::string &url, const std::vector<std::string> &addresses, bool dnssec_valid)->std::string {
if (!dnssec_valid)
{
@@ -1075,7 +1075,7 @@ namespace tools
{
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, m_wallet->testnet(), req.integrated_address))
+ if(!get_account_address_from_str(info, m_wallet->nettype(), req.integrated_address))
{
er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
er.message = "Invalid address";
@@ -1087,7 +1087,7 @@ namespace tools
er.message = "Address is not an integrated address";
return false;
}
- res.standard_address = get_account_address_as_str(m_wallet->testnet(), info.is_subaddress, info.address);
+ res.standard_address = get_account_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address);
res.payment_id = epee::string_tools::pod_to_hex(info.payment_id);
return true;
}
@@ -1385,7 +1385,7 @@ namespace tools
cryptonote::address_parse_info info;
er.message = "";
- if(!get_account_address_from_str_or_url(info, m_wallet->testnet(), req.address,
+ if(!get_account_address_from_str_or_url(info, m_wallet->nettype(), req.address,
[&er](const std::string &url, const std::vector<std::string> &addresses, bool dnssec_valid)->std::string {
if (!dnssec_valid)
{
@@ -1595,7 +1595,7 @@ namespace tools
}
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, m_wallet->testnet(), req.address))
+ if(!get_account_address_from_str(info, m_wallet->nettype(), req.address))
{
er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
er.message = "Invalid address";
@@ -1628,7 +1628,7 @@ namespace tools
}
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, m_wallet->testnet(), req.address))
+ if(!get_account_address_from_str(info, m_wallet->nettype(), req.address))
{
er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
er.message = "Invalid address";
@@ -1661,7 +1661,7 @@ namespace tools
}
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, m_wallet->testnet(), req.address))
+ if(!get_account_address_from_str(info, m_wallet->nettype(), req.address))
{
er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
er.message = "Invalid address";
@@ -1768,7 +1768,7 @@ namespace tools
if (!m_wallet) return not_open(er);
cryptonote::address_parse_info info;
- if (!get_account_address_from_str(info, m_wallet->testnet(), req.address))
+ if (!get_account_address_from_str(info, m_wallet->nettype(), req.address))
{
er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
er.message = "Invalid address";
@@ -2058,7 +2058,7 @@ namespace tools
{
uint64_t idx = 0;
for (const auto &entry: ab)
- res.entries.push_back(wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY::entry{idx++, get_account_address_as_str(m_wallet->testnet(), entry.m_is_subaddress, entry.m_address), epee::string_tools::pod_to_hex(entry.m_payment_id), entry.m_description});
+ res.entries.push_back(wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY::entry{idx++, get_account_address_as_str(m_wallet->nettype(), entry.m_is_subaddress, entry.m_address), epee::string_tools::pod_to_hex(entry.m_payment_id), entry.m_description});
}
else
{
@@ -2071,7 +2071,7 @@ namespace tools
return false;
}
const auto &entry = ab[idx];
- res.entries.push_back(wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY::entry{idx, get_account_address_as_str(m_wallet->testnet(), entry.m_is_subaddress, entry.m_address), epee::string_tools::pod_to_hex(entry.m_payment_id), entry.m_description});
+ res.entries.push_back(wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY::entry{idx, get_account_address_as_str(m_wallet->nettype(), entry.m_is_subaddress, entry.m_address), epee::string_tools::pod_to_hex(entry.m_payment_id), entry.m_description});
}
}
return true;
@@ -2090,7 +2090,7 @@ namespace tools
cryptonote::address_parse_info info;
crypto::hash payment_id = crypto::null_hash;
er.message = "";
- if(!get_account_address_from_str_or_url(info, m_wallet->testnet(), req.address,
+ if(!get_account_address_from_str_or_url(info, m_wallet->nettype(), req.address,
[&er](const std::string &url, const std::vector<std::string> &addresses, bool dnssec_valid)->std::string {
if (!dnssec_valid)
{
@@ -2219,7 +2219,7 @@ namespace tools
}
cryptonote::COMMAND_RPC_START_MINING::request daemon_req = AUTO_VAL_INIT(daemon_req);
- daemon_req.miner_address = m_wallet->get_account().get_public_address_str(m_wallet->testnet());
+ daemon_req.miner_address = m_wallet->get_account().get_public_address_str(m_wallet->nettype());
daemon_req.threads_count = req.threads_count;
daemon_req.do_background_mining = req.do_background_mining;
daemon_req.ignore_battery = req.ignore_battery;
@@ -2535,7 +2535,7 @@ namespace tools
try
{
res.multisig_info = m_wallet->make_multisig(req.password, req.multisig_info, req.threshold);
- res.address = m_wallet->get_account().get_public_address_str(m_wallet->testnet());
+ res.address = m_wallet->get_account().get_public_address_str(m_wallet->nettype());
}
catch (const std::exception &e)
{
@@ -2706,7 +2706,7 @@ namespace tools
er.message = std::string("Error calling finalize_multisig: ") + e.what();
return false;
}
- res.address = m_wallet->get_account().get_public_address_str(m_wallet->testnet());
+ res.address = m_wallet->get_account().get_public_address_str(m_wallet->nettype());
return true;
}
@@ -2883,6 +2883,14 @@ int main(int argc, char** argv) {
std::unique_ptr<tools::wallet2> wal;
try
{
+ const bool testnet = tools::wallet2::has_testnet_option(*vm);
+ const bool stagenet = tools::wallet2::has_stagenet_option(*vm);
+ if (testnet && stagenet)
+ {
+ MERROR(tools::wallet_rpc_server::tr("Can't specify more than one of --testnet and --stagenet"));
+ return 1;
+ }
+
const auto wallet_file = command_line::get_arg(*vm, arg_wallet_file);
const auto from_json = command_line::get_arg(*vm, arg_from_json);
const auto wallet_dir = command_line::get_arg(*vm, arg_wallet_dir);