45 #include <boost/format.hpp> 47 #include <unordered_map> 51 #include <boost/locale.hpp> 52 #include <boost/filesystem.hpp> 58 #undef ELECTRONEUM_DEFAULT_LOG_CATEGORY 59 #define ELECTRONEUM_DEFAULT_LOG_CATEGORY "WalletAPI" 66 static const int DEFAULT_REFRESH_INTERVAL_MILLIS = 1000 * 10;
68 static const int MAX_REFRESH_INTERVAL_MILLIS = 1000 * 60 * 1;
70 static const int DEFAULT_REMOTE_NODE_REFRESH_INTERVAL_MILLIS = 1000 * 10;
72 static const int DEFAULT_CONNECTION_TIMEOUT_MILLIS = 1000 * 30;
78 dir = dir.remove_filename();
79 dir /=
".shared-ringdb";
89 throw runtime_error(
"Wallet is not initialized yet");
94 throw runtime_error(
"Wallet is not multisig");
98 throw runtime_error(
"Multisig wallet is not finalized yet");
101 void checkMultisigWalletReady(
const std::unique_ptr<tools::wallet2> &wallet) {
102 return checkMultisigWalletReady(wallet.get());
107 throw runtime_error(
"Wallet is not initialized yet");
112 throw runtime_error(
"Wallet is not multisig");
116 throw runtime_error(
"Multisig wallet is already finalized");
119 void checkMultisigWalletNotReady(
const std::unique_ptr<tools::wallet2> &wallet) {
120 return checkMultisigWalletNotReady(wallet.get());
128 : m_listener(nullptr)
141 m_listener = listener;
154 if(
height >= m_wallet->m_wallet->get_refresh_from_block_height() ||
height % 1000 == 0) {
157 m_listener->newBlock(
height);
168 <<
", tx: " << tx_hash
170 <<
", idx: " << subaddr_index);
172 if (m_listener && m_wallet->synchronized()) {
173 m_listener->etnReceived(tx_hash, amount);
174 m_listener->updated();
184 <<
", tx: " << tx_hash
186 <<
", idx: " << subaddr_index);
188 if (m_listener && m_wallet->synchronized()) {
189 m_listener->unconfirmedETNReceived(tx_hash, amount);
190 m_listener->updated();
200 <<
", tx: " << tx_hash
202 <<
", idx: " << subaddr_index);
204 if (m_listener && m_wallet->synchronized()) {
205 m_listener->etnSpent(tx_hash, amount);
206 m_listener->updated();
219 m_listener->newBlock(
height);
227 m_listener->etnReceived(tx_hash, amount);
235 m_listener->unconfirmedETNReceived(tx_hash, amount);
243 m_listener->etnSpent(tx_hash, amount);
250 m_listener->onDeviceButtonRequest(code);
257 m_listener->onDeviceButtonPressed();
264 auto pin = m_listener->onDevicePinRequest();
275 auto passphrase = m_listener->onDevicePassphraseRequest(on_device);
276 if (!on_device && passphrase) {
296 WalletListener::~WalletListener() {}
304 uint64_t Wallet::amountFromString(
const string &amount)
313 std::stringstream ss;
315 return amountFromString(ss.str());
325 bool Wallet::paymentIdValid(
const string &paiment_id)
346 error =
tr(
"Failed to parse address");
353 error =
tr(
"Failed to parse key");
361 error =
tr(
"failed to verify key");
364 bool matchAddress =
false;
366 matchAddress =
info.address.m_view_public_key == pkey;
368 matchAddress =
info.address.m_spend_public_key == pkey;
371 error =
tr(
"key does not match address");
383 if (!
info.has_payment_id)
390 return std::numeric_limits<uint64_t>::max();
396 std::locale::global(boost::locale::generator().generate(
""));
397 boost::filesystem::path::imbue(std::locale());
422 , m_status(
Wallet::Status_Ok)
423 , m_wallet2Callback(nullptr)
424 , m_recoveringFromSeed(
false)
425 , m_recoveringFromDevice(
false)
426 , m_synchronized(
false)
427 , m_rebuildWalletCache(
false)
428 , m_is_connected(
false)
429 , m_refreshShouldRescan(
false)
431 m_wallet.reset(
new tools::wallet2(static_cast<cryptonote::network_type>(
nettype), kdf_rounds,
true));
434 m_wallet->callback(m_wallet2Callback.get());
435 m_refreshThreadDone =
false;
436 m_refreshEnabled =
false;
442 m_refreshIntervalMillis = DEFAULT_REFRESH_INTERVAL_MILLIS;
444 m_refreshThread = boost::thread([
this] () {
445 this->refreshThreadFunc();
454 m_wallet->callback(NULL);
462 if (m_wallet2Callback->getListener()) {
463 m_wallet2Callback->getListener()->onSetWallet(
nullptr);
473 m_recoveringFromSeed =
false;
474 m_recoveringFromDevice =
false;
475 bool keys_file_exists;
476 bool wallet_file_exists;
479 LOG_PRINT_L3(
"keys_file_exists: " << std::boolalpha << keys_file_exists << std::noboolalpha
480 <<
" wallet_file_exists: " << std::boolalpha << wallet_file_exists << std::noboolalpha);
484 if (keys_file_exists || wallet_file_exists) {
485 std::string error =
"attempting to generate or restore wallet, but specified file(s) exist. Exiting to not risk overwriting.";
487 setStatusCritical(
error);
491 m_wallet->set_seed_language(language);
494 recovery_val = m_wallet->generate(
path, password,
secret_key,
false,
false);
495 m_password = password;
497 }
catch (
const std::exception &e) {
498 LOG_ERROR(
"Error creating wallet: " << e.what());
499 setStatusCritical(e.what());
509 std::unique_ptr<tools::wallet2> view_wallet(
new tools::wallet2(m_wallet->nettype()));
514 bool keys_file_exists;
515 bool wallet_file_exists;
518 LOG_PRINT_L3(
"keys_file_exists: " << std::boolalpha << keys_file_exists << std::noboolalpha
519 <<
" wallet_file_exists: " << std::boolalpha << wallet_file_exists << std::noboolalpha);
522 if (keys_file_exists || wallet_file_exists) {
523 std::string error =
"attempting to generate view only wallet, but specified file(s) exist. Exiting to not risk overwriting.";
525 setStatusError(
error);
531 const crypto::secret_key viewkey = m_wallet->get_account().get_keys().m_view_secret_key;
539 auto outputs = m_wallet->export_outputs();
543 auto bc = m_wallet->export_blockchain();
547 auto payments = m_wallet->export_payments();
551 std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>> out_payments;
552 m_wallet->get_payments_out(out_payments, 0);
557 auto key_images = m_wallet->export_key_images();
560 view_wallet->
import_key_images(key_images.second, key_images.first, spent, unspent,
false);
562 }
catch (
const std::exception &e) {
563 LOG_ERROR(
"Error creating view only wallet: " << e.what());
564 setStatusError(e.what());
568 view_wallet->
store();
591 setStatusError(
tr(
"failed to parse address"));
597 bool has_spendkey =
false;
598 if (!spendkey_string.empty()) {
602 setStatusError(
tr(
"failed to parse secret spend key"));
610 bool has_viewkey =
true;
612 if (viewkey_string.empty()) {
617 setStatusError(
tr(
"Neither view key nor spend key supplied, cancelled"));
625 setStatusError(
tr(
"failed to parse secret view key"));
634 setStatusError(
tr(
"failed to verify secret spend key"));
637 if (
info.address.m_spend_public_key != pkey) {
638 setStatusError(
tr(
"spend key does not match address"));
644 setStatusError(
tr(
"failed to verify secret view key"));
647 if (
info.address.m_view_public_key != pkey) {
648 setStatusError(
tr(
"view key does not match address"));
655 if (has_spendkey && has_viewkey) {
657 LOG_PRINT_L1(
"Generated new wallet from spend key and view key");
659 if(!has_spendkey && has_viewkey) {
660 m_wallet->generate(
path, password,
info.address, viewkey);
661 LOG_PRINT_L1(
"Generated new view only wallet from keys");
663 if(has_spendkey && !has_viewkey) {
664 m_wallet->generate(
path, password,
spendkey,
true,
false);
666 LOG_PRINT_L1(
"Generated deterministic wallet from spend key with seed language: " + language);
670 catch (
const std::exception& e) {
671 setStatusError(
string(
tr(
"failed to generate new wallet: ")) + e.what());
680 m_recoveringFromSeed =
false;
681 m_recoveringFromDevice =
true;
684 m_wallet->restore(
path, password, device_name);
685 LOG_PRINT_L1(
"Generated new wallet from device: " + device_name);
687 catch (
const std::exception& e) {
688 setStatusError(
string(
tr(
"failed to generate new wallet: ")) + e.what());
702 m_recoveringFromSeed =
false;
703 m_recoveringFromDevice =
false;
707 bool keys_file_exists;
708 bool wallet_file_exists;
710 if(!wallet_file_exists){
712 m_rebuildWalletCache =
true;
714 m_wallet->set_ring_database(get_default_ringdb_path(m_wallet->nettype()));
715 m_wallet->load(
path, password);
717 m_password = password;
718 }
catch (
const std::exception &e) {
719 LOG_ERROR(
"Error opening wallet: " << e.what());
720 setStatusCritical(e.what());
733 m_errorString.clear();
736 setStatusError(
tr(
"Electrum seed is empty"));
740 m_recoveringFromSeed =
true;
741 m_recoveringFromDevice =
false;
745 setStatusError(
tr(
"Electrum-style word list failed verification"));
753 m_wallet->set_seed_language(old_language);
754 m_wallet->generate(
path, password, recovery_key,
true,
false);
756 }
catch (
const std::exception &e) {
757 setStatusCritical(e.what());
774 LOG_ERROR(
"Status_Critical - not saving wallet");
783 }
catch (
const std::exception &e) {
784 setStatusCritical(e.what());
785 LOG_ERROR(
"Error closing wallet: " << e.what());
794 m_wallet->get_seed(
seed);
800 return m_wallet->get_seed_language();
805 m_wallet->set_seed_language(arg);
810 boost::lock_guard<boost::mutex> l(m_statusMutex);
816 boost::lock_guard<boost::mutex> l(m_statusMutex);
817 return m_errorString;
821 boost::lock_guard<boost::mutex> l(m_statusMutex);
830 m_wallet->change_password(m_wallet->get_wallet_file(), m_password, password);
831 m_password = password;
832 }
catch (
const std::exception &e) {
833 setStatusError(e.what());
843 }
catch (
const std::exception &e) {
844 setStatusError(e.what());
853 m_wallet->get_account().get_device().set_passphrase(
epee::wipeable_string(passphrase.data(), passphrase.size()));
854 }
catch (
const std::exception &e) {
855 setStatusError(e.what());
862 return m_wallet->get_subaddress_as_str({accountIndex, addressIndex});
871 return m_wallet->get_integrated_address_as_str(pid);
899 }
catch (
const std::exception&) {
906 return m_wallet->path();
916 m_wallet->store_to(
path, m_password);
918 }
catch (
const std::exception &e) {
919 LOG_ERROR(
"Error saving wallet: " << e.what());
920 setStatusError(e.what());
929 return m_wallet->get_wallet_file();
934 return m_wallet->get_keys_file();
940 m_wallet->set_light_wallet(lightWallet);
941 if(daemon_username !=
"")
942 m_daemon_login.emplace(daemon_username, daemon_password);
943 return doInit(
daemon_address, upper_transaction_size_limit, use_ssl);
948 return m_wallet->light_wallet_login(isNewWallet);
956 if(!m_wallet->light_wallet_import_wallet_request(
response)){
957 setStatusError(
tr(
"Failed to send import wallet request"));
963 request_fulfilled =
response.request_fulfilled;
964 payment_address =
response.payment_address;
967 catch (
const std::exception &e)
969 LOG_ERROR(
"Error sending import wallet request: " << e.what());
970 setStatusError(e.what());
978 m_wallet->set_refresh_from_block_height(refresh_from_block_height);
983 m_recoveringFromSeed = recoveringFromSeed;
988 m_recoveringFromDevice = recoveringFromDevice;
993 m_wallet->set_subaddress_lookahead(major, minor);
998 return m_wallet->balance(accountIndex, public_blockchain);
1003 return m_wallet->unlocked_balance(accountIndex, public_blockchain);
1008 if(m_wallet->light_wallet()) {
1009 return m_wallet->get_light_wallet_scanned_block_height();
1011 return m_wallet->get_blockchain_current_height();
1015 return m_wallet->get_approximate_blockchain_height();
1020 return m_wallet->estimate_blockchain_height();
1025 if(m_wallet->light_wallet()) {
1026 return m_wallet->get_light_wallet_scanned_block_height();
1028 if (!m_is_connected)
1031 uint64_t result = m_wallet->get_daemon_blockchain_height(err);
1035 setStatusError(err);
1044 if(m_wallet->light_wallet()) {
1045 return m_wallet->get_light_wallet_blockchain_height();
1047 if (!m_is_connected)
1050 uint64_t result = m_wallet->get_daemon_blockchain_target_height(err);
1054 setStatusError(err);
1064 bool WalletImpl::daemonSynced()
const 1074 return m_synchronized;
1088 LOG_PRINT_L3(__FUNCTION__ <<
": Refreshing asynchronously..");
1090 m_refreshCV.notify_one();
1096 m_refreshShouldRescan =
true;
1103 m_refreshShouldRescan =
true;
1109 if (millis > MAX_REFRESH_INTERVAL_MILLIS) {
1110 LOG_ERROR(__FUNCTION__<<
": invalid refresh interval " << millis
1111 <<
" ms, maximum allowed is " << MAX_REFRESH_INTERVAL_MILLIS <<
" ms");
1112 m_refreshIntervalMillis = MAX_REFRESH_INTERVAL_MILLIS;
1114 m_refreshIntervalMillis = millis;
1120 return m_refreshIntervalMillis;
1126 if (!m_wallet->load_unsigned_tx(unsigned_filename,
transaction->m_unsigned_tx_set)){
1127 setStatusError(
tr(
"Failed to load unsigned transactions"));
1132 if (!
transaction->m_unsigned_tx_set.transfers.second.empty())
1133 extra_message = (boost::format(
"%u outputs to import. ") % (unsigned)
transaction->m_unsigned_tx_set.transfers.second.size()).str();
1144 bool r = m_wallet->load_tx(fileName,
transaction->m_pending_tx);
1146 setStatus(
Status_Ok,
tr(
"Failed to load transaction from file"));
1160 if (m_wallet->watch_only())
1162 setStatusError(
tr(
"Wallet is view only"));
1168 if (!m_wallet->export_key_images(
filename))
1170 setStatusError(
tr(
"failed to save file ") +
filename);
1174 catch (
const std::exception &e)
1176 LOG_ERROR(
"Error exporting key images: " << e.what());
1177 setStatusError(e.what());
1186 setStatusError(
tr(
"Key images can only be imported with a trusted daemon"));
1196 catch (
const std::exception &e)
1198 LOG_ERROR(
"Error exporting key images: " << e.what());
1199 setStatusError(
string(
tr(
"Failed to import key images: ")) + e.what());
1208 m_wallet->add_subaddress_account(label);
1212 return m_wallet->get_num_subaddress_accounts();
1216 return m_wallet->get_num_subaddresses(accountIndex);
1220 m_wallet->add_subaddress(accountIndex, label);
1226 return m_wallet->get_subaddress_label({accountIndex, addressIndex});
1228 catch (
const std::exception &e)
1230 LOG_ERROR(
"Error getting subaddress label: " << e.what());
1231 setStatusError(
string(
tr(
"Failed to get subaddress label: ")) + e.what());
1239 return m_wallet->set_subaddress_label({accountIndex, addressIndex}, label);
1241 catch (
const std::exception &e)
1243 LOG_ERROR(
"Error setting subaddress label: " << e.what());
1244 setStatusError(
string(
tr(
"Failed to set subaddress label: ")) + e.what());
1258 return m_wallet->get_multisig_info();
1259 }
catch (
const exception& e) {
1260 LOG_ERROR(
"Error on generating multisig info: " << e.what());
1261 setStatusError(
string(
tr(
"Failed to get multisig info: ")) + e.what());
1271 if (m_wallet->multisig()) {
1272 throw runtime_error(
"Wallet is already multisig");
1276 }
catch (
const exception& e) {
1277 LOG_ERROR(
"Error on making multisig wallet: " << e.what());
1278 setStatusError(
string(
tr(
"Failed to make multisig: ")) + e.what());
1287 checkMultisigWalletNotReady(m_wallet);
1290 }
catch (
const exception& e) {
1291 LOG_ERROR(
"Error on exchanging multisig keys: " << e.what());
1292 setStatusError(
string(
tr(
"Failed to make multisig: ")) + e.what());
1301 checkMultisigWalletNotReady(m_wallet);
1307 setStatusError(
tr(
"Failed to finalize multisig wallet creation"));
1308 }
catch (
const exception& e) {
1309 LOG_ERROR(
"Error on finalizing multisig wallet creation: " << e.what());
1310 setStatusError(
string(
tr(
"Failed to finalize multisig wallet creation: ")) + e.what());
1319 checkMultisigWalletReady(m_wallet);
1321 auto blob = m_wallet->export_multisig();
1324 }
catch (
const exception& e) {
1325 LOG_ERROR(
"Error on exporting multisig images: " << e.what());
1326 setStatusError(
string(
tr(
"Failed to export multisig images: ")) + e.what());
1335 checkMultisigWalletReady(m_wallet);
1337 std::vector<std::string> blobs;
1338 blobs.reserve(images.size());
1340 for (
const auto& image: images) {
1343 LOG_ERROR(
"Failed to parse imported multisig images");
1344 setStatusError(
tr(
"Failed to parse imported multisig images"));
1351 return m_wallet->import_multisig(blobs);
1352 }
catch (
const exception& e) {
1353 LOG_ERROR(
"Error on importing multisig images: " << e.what());
1354 setStatusError(
string(
tr(
"Failed to import multisig images: ")) + e.what());
1363 checkMultisigWalletReady(m_wallet);
1365 return m_wallet->has_multisig_partial_key_images();
1366 }
catch (
const exception& e) {
1367 LOG_ERROR(
"Error on checking for partial multisig key images: " << e.what());
1368 setStatusError(
string(
tr(
"Failed to check for partial multisig key images: ")) + e.what());
1377 checkMultisigWalletReady(m_wallet);
1381 throw runtime_error(
"Failed to deserialize multisig transaction");
1385 if (!m_wallet->load_multisig_tx(binary, txSet, {})) {
1386 throw runtime_error(
"couldn't parse multisig transaction data");
1390 ptx->m_pending_tx = txSet.
m_ptx;
1394 }
catch (exception& e) {
1395 LOG_ERROR(
"Error on restoring multisig transaction: " << e.what());
1396 setStatusError(
string(
tr(
"Failed to restore multisig transaction: ")) + e.what());
1424 size_t fake_outs_count = mixin_count > 0 ? mixin_count : m_wallet->default_mixin();
1425 if (fake_outs_count == 0)
1426 fake_outs_count = DEFAULT_MIXIN;
1427 fake_outs_count = m_wallet->adjust_mixin(fake_outs_count);
1429 uint32_t adjusted_priority = m_wallet->adjust_priority(static_cast<uint32_t>(priority));
1436 setStatusError(
tr(
"Invalid destination address"));
1441 std::vector<uint8_t> extra;
1443 if (!
info.has_payment_id && !payment_id.empty()) {
1456 memcpy(payment_id.data,
info.payment_id.data, 8);
1457 memset(payment_id.data + 8, 0, 24);
1465 setStatusError(
tr(
"payment id has invalid format, expected 16 or 64 character hex string: ") + payment_id);
1469 else if (
info.has_payment_id) {
1472 memcpy(payment_id.data,
info.payment_id.data, 8);
1473 memset(payment_id.data + 8, 0, 24);
1488 vector<cryptonote::tx_destination_entry> dsts;
1496 transaction->m_pending_tx = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 ,
1498 extra, subaddr_account, subaddr_indices);
1501 if (subaddr_indices.empty())
1503 for (
uint32_t index = 0; index < m_wallet->get_num_subaddresses(subaddr_account); ++index)
1504 subaddr_indices.insert(index);
1506 transaction->m_pending_tx = m_wallet->create_transactions_all(0,
info.address,
info.is_subaddress, 1, fake_outs_count, 0 ,
1508 extra, subaddr_account, subaddr_indices);
1514 auto tx_set = m_wallet->make_multisig_tx_set(
transaction->m_pending_tx);
1520 setStatusError(
tr(
"daemon is busy. Please try again later."));
1522 setStatusError(
tr(
"no connection to daemon. Please make sure daemon is running."));
1524 setStatusError(
tr(
"RPC error: ") + e.
to_string());
1526 setStatusError((boost::format(
tr(
"failed to get outputs to mix: %s")) % e.what()).str());
1528 std::ostringstream writer;
1530 writer << boost::format(
tr(
"not enough ETN to transfer, available only %s, sent amount %s")) %
1533 setStatusError(writer.str());
1535 std::ostringstream writer;
1537 writer << boost::format(
tr(
"not enough ETN to transfer, overall balance only %s, sent amount %s")) %
1540 setStatusError(writer.str());
1542 std::ostringstream writer;
1544 writer << boost::format(
tr(
"not enough ETN to transfer, available only %s, transaction amount %s = %s + %s (fee)")) %
1549 setStatusError(writer.str());
1551 std::ostringstream writer;
1552 writer <<
tr(
"not enough outputs.");
1553 for (
const std::pair<uint64_t, uint64_t> outs_for_amount : e.
scanty_outs()) {
1554 writer <<
"\n" <<
tr(
"output amount") <<
" = " <<
print_etn(outs_for_amount.first) <<
", " <<
tr(
"found outputs to use") <<
" = " << outs_for_amount.second;
1556 writer <<
"\n" <<
tr(
"Please sweep unmixable outputs.");
1557 setStatusError(writer.str());
1559 setStatusError(
tr(
"transaction was not constructed"));
1561 std::ostringstream writer;
1563 setStatusError(writer.str());
1565 setStatusError(e.what());
1567 setStatusError(
tr(
"one of destinations is zero"));
1569 setStatusError(
tr(
"failed to find a suitable way to split transactions"));
1571 setStatusError(
string(
tr(
"unknown transfer error: ")) + e.what());
1573 setStatusError(
string(
tr(
"internal error: ")) + e.what());
1574 }
catch (
const std::exception& e) {
1575 setStatusError(
string(
tr(
"unexpected error: ")) + e.what());
1577 setStatusError(
tr(
"unknown error"));
1597 transaction->m_pending_tx = m_wallet->create_unmixable_sweep_transactions();
1602 setStatusError(
tr(
"daemon is busy. Please try again later."));
1604 setStatusError(
tr(
"no connection to daemon. Please make sure daemon is running."));
1606 setStatusError(
tr(
"RPC error: ") + e.
to_string());
1608 setStatusError(
tr(
"failed to get outputs to mix"));
1611 std::ostringstream writer;
1613 writer << boost::format(
tr(
"not enough ETN to transfer, available only %s, sent amount %s")) %
1616 setStatusError(writer.str());
1619 std::ostringstream writer;
1621 writer << boost::format(
tr(
"not enough ETN to transfer, overall balance only %s, sent amount %s")) %
1624 setStatusError(writer.str());
1627 std::ostringstream writer;
1629 writer << boost::format(
tr(
"not enough ETN to transfer, available only %s, transaction amount %s = %s + %s (fee)")) %
1634 setStatusError(writer.str());
1636 std::ostringstream writer;
1637 writer <<
tr(
"not enough outputs.");
1638 for (
const std::pair<uint64_t, uint64_t> outs_for_amount : e.
scanty_outs()) {
1639 writer <<
"\n" <<
tr(
"output amount") <<
" = " <<
print_etn(outs_for_amount.first) <<
", " <<
tr(
"found outputs to use") <<
" = " << outs_for_amount.second;
1641 setStatusError(writer.str());
1643 setStatusError(
tr(
"transaction was not constructed"));
1645 std::ostringstream writer;
1647 setStatusError(writer.str());
1649 setStatusError(e.what());
1651 setStatusError(
tr(
"one of destinations is zero"));
1653 setStatusError(
tr(
"failed to find a suitable way to split transactions"));
1655 setStatusError(
string(
tr(
"unknown transfer error: ")) + e.what());
1657 setStatusError(
string(
tr(
"internal error: ")) + e.what());
1658 }
catch (
const std::exception& e) {
1659 setStatusError(
string(
tr(
"unexpected error: ")) + e.what());
1661 setStatusError(
tr(
"unknown error"));
1676 return m_history.get();
1681 return m_addressBook.get();
1686 return m_subaddress.get();
1691 return m_subaddressAccount.get();
1697 m_wallet2Callback->setListener(l);
1702 return m_wallet->default_mixin();
1707 m_wallet->default_mixin(arg);
1717 m_wallet->set_tx_note(htxid, note);
1728 return m_wallet->get_tx_note(htxid);
1736 setStatusError(
tr(
"Failed to parse txid"));
1741 std::vector<crypto::secret_key> additional_tx_keys;
1742 if (m_wallet->get_tx_key(txid, tx_key, additional_tx_keys))
1745 std::ostringstream oss;
1747 for (
size_t i = 0; i < additional_tx_keys.size(); ++i)
1753 setStatusError(
tr(
"no tx keys found for this txid"));
1763 setStatusError(
tr(
"Failed to parse txid"));
1768 std::vector<crypto::secret_key> additional_tx_keys;
1771 setStatusError(
tr(
"Failed to parse tx key"));
1774 tx_key_str = tx_key_str.substr(64);
1775 while (!tx_key_str.empty())
1777 additional_tx_keys.resize(additional_tx_keys.size() + 1);
1780 setStatusError(
tr(
"Failed to parse tx key"));
1783 tx_key_str = tx_key_str.substr(64);
1789 setStatusError(
tr(
"Failed to parse address"));
1795 m_wallet->check_tx_key(txid, tx_key, additional_tx_keys,
info.address, received, in_pool, confirmations);
1799 catch (
const std::exception &e)
1801 setStatusError(e.what());
1811 setStatusError(
tr(
"Failed to parse txid"));
1818 setStatusError(
tr(
"Failed to parse address"));
1825 return m_wallet->get_tx_proof(txid,
info.address,
info.is_subaddress,
message);
1827 catch (
const std::exception &e)
1829 setStatusError(e.what());
1839 setStatusError(
tr(
"Failed to parse txid"));
1846 setStatusError(
tr(
"Failed to parse address"));
1852 good = m_wallet->check_tx_proof(txid,
info.address,
info.is_subaddress,
message,
signature, received, in_pool, confirmations);
1856 catch (
const std::exception &e)
1858 setStatusError(e.what());
1867 setStatusError(
tr(
"Failed to parse txid"));
1874 return m_wallet->get_spend_proof(txid,
message);
1876 catch (
const std::exception &e)
1878 setStatusError(e.what());
1888 setStatusError(
tr(
"Failed to parse txid"));
1898 catch (
const std::exception &e)
1900 setStatusError(e.what());
1909 boost::optional<std::pair<uint32_t, uint64_t>> account_minreserve;
1912 account_minreserve = std::make_pair(account_index, amount);
1914 return m_wallet->get_reserve_proof(account_minreserve,
message);
1916 catch (
const std::exception &e)
1918 setStatusError(e.what());
1927 setStatusError(
tr(
"Failed to parse address"));
1930 if (
info.is_subaddress)
1932 setStatusError(
tr(
"Address must not be a subaddress"));
1943 catch (
const std::exception &e)
1945 setStatusError(e.what());
1952 return m_wallet->sign(
message);
1970 if (!m_wallet->multisig(&ready) || !ready) {
1972 m_errorString =
tr(
"The wallet must be in multisig ready state");
1977 return m_wallet->sign_multisig_participant(
message);
1978 }
catch (
const std::exception& e) {
1980 m_errorString = e.what();
1994 m_errorString =
tr(
"Given string is not a key");
2001 }
catch (
const std::exception& e) {
2003 m_errorString = e.what();
2011 bool result = m_wallet->check_connection(NULL, NULL, DEFAULT_CONNECTION_TIMEOUT_MILLIS);
2013 setStatusError(
"Error connecting to daemon at " + m_wallet->get_daemon_address());
2024 m_is_connected = m_wallet->check_connection(&
version, NULL, DEFAULT_CONNECTION_TIMEOUT_MILLIS);
2025 if (!m_is_connected)
2035 m_wallet->set_trusted_daemon(arg);
2040 return m_wallet->is_trusted_daemon();
2045 return m_wallet->watch_only();
2048 void WalletImpl::clearStatus()
const 2050 boost::lock_guard<boost::mutex> l(m_statusMutex);
2052 m_errorString.clear();
2067 boost::lock_guard<boost::mutex> l(m_statusMutex);
2072 void WalletImpl::refreshThreadFunc()
2074 LOG_PRINT_L3(__FUNCTION__ <<
": starting refresh thread");
2077 boost::mutex::scoped_lock lock(m_refreshMutex);
2078 if (m_refreshThreadDone) {
2081 LOG_PRINT_L3(__FUNCTION__ <<
": waiting for refresh...");
2084 if (m_refreshIntervalMillis > 0) {
2085 boost::posix_time::milliseconds wait_for_ms(m_refreshIntervalMillis.load());
2086 m_refreshCV.timed_wait(lock, wait_for_ms);
2088 m_refreshCV.wait(lock);
2091 LOG_PRINT_L3(__FUNCTION__ <<
": refresh lock acquired...");
2092 LOG_PRINT_L3(__FUNCTION__ <<
": m_refreshEnabled: " << m_refreshEnabled);
2094 LOG_PRINT_L3(__FUNCTION__ <<
": m_refreshShouldRescan: " << m_refreshShouldRescan);
2095 if (m_refreshEnabled) {
2100 LOG_PRINT_L3(__FUNCTION__ <<
": refresh thread stopped");
2103 void WalletImpl::doRefresh()
2105 bool rescan = m_refreshShouldRescan.exchange(
false);
2107 boost::lock_guard<boost::mutex> guarg(m_refreshMutex2);
2109 LOG_PRINT_L3(__FUNCTION__ <<
": doRefresh, rescan = "<<rescan);
2112 if (m_wallet->light_wallet() || daemonSynced()) {
2114 m_wallet->rescan_blockchain(
false);
2116 if (!m_synchronized) {
2117 m_synchronized =
true;
2122 if (m_history->count() == 0) {
2123 m_history->refresh();
2125 m_wallet->find_and_save_rings(
false);
2127 LOG_PRINT_L3(__FUNCTION__ <<
": skipping refresh - daemon is not synced");
2129 }
catch (
const std::exception &e) {
2130 setStatusError(e.what());
2132 }
while(!rescan && (rescan=m_refreshShouldRescan.exchange(
false)));
2134 if (m_wallet2Callback->getListener()) {
2135 m_wallet2Callback->getListener()->refreshed();
2142 if (!m_refreshEnabled) {
2143 LOG_PRINT_L2(__FUNCTION__ <<
": refresh started/resumed...");
2144 m_refreshEnabled =
true;
2145 m_refreshCV.notify_one();
2151 void WalletImpl::stopRefresh()
2153 if (!m_refreshThreadDone) {
2154 m_refreshEnabled =
false;
2155 m_refreshThreadDone =
true;
2156 m_refreshCV.notify_one();
2157 m_refreshThread.join();
2165 if (!m_refreshThreadDone) {
2166 m_refreshEnabled =
false;
2171 bool WalletImpl::isNewWallet()
const 2178 return !(
blockChainHeight() > 1 || m_recoveringFromSeed || m_recoveringFromDevice || m_rebuildWalletCache) && !
watchOnly();
2181 void WalletImpl::pendingTxPostProcess(PendingTransactionImpl *
pending)
2184 if (!m_wallet->get_account().get_device().has_tx_cold_sign()){
2189 std::vector<cryptonote::address_parse_info> dsts_info;
2191 m_wallet->cold_sign_tx(
pending->m_pending_tx, exported_txs, dsts_info,
pending->m_tx_device_aux);
2198 if (!m_wallet->init(
daemon_address, m_daemon_login, boost::asio::ip::tcp::endpoint{}, upper_transaction_size_limit))
2204 if (isNewWallet() && daemonSynced()) {
2209 if (m_rebuildWalletCache)
2210 LOG_PRINT_L2(__FUNCTION__ <<
": Rebuilding wallet cache, fast refresh until block " << m_wallet->get_refresh_from_block_height());
2214 m_refreshIntervalMillis = DEFAULT_REFRESH_INTERVAL_MILLIS;
2217 m_refreshIntervalMillis = DEFAULT_REMOTE_NODE_REFRESH_INTERVAL_MILLIS;
2224 return m_wallet->parse_uri(uri,
address, payment_id, amount, tx_description, recipient_name, unknown_parameters,
error);
2236 setStatusError(
tr(
"Rescan spent can only be used with a trusted daemon"));
2240 m_wallet->rescan_spent();
2241 }
catch (
const std::exception &e) {
2242 LOG_ERROR(__FUNCTION__ <<
" error: " << e.what());
2243 setStatusError(e.what());
2252 m_wallet->get_hard_fork_info(
version, earliest_height);
2257 return m_wallet->use_fork_rules(
version,early_blocks);
2262 std::vector<std::pair<uint64_t, uint64_t>> raw_outputs;
2263 raw_outputs.reserve(outputs.size());
2264 uint64_t amount = std::numeric_limits<uint64_t>::max(), offset, num_offsets;
2267 if (sscanf(str.c_str(),
"@%" PRIu64, &amount) == 1)
2269 if (amount == std::numeric_limits<uint64_t>::max())
2271 setStatusError(
"First line is not an amount");
2274 if (sscanf(str.c_str(),
"%" PRIu64 "*%" PRIu64, &offset, &num_offsets) == 2 && num_offsets <= std::numeric_limits<uint64_t>::max() - offset)
2276 while (num_offsets--)
2277 raw_outputs.push_back(std::make_pair(amount, offset++));
2279 else if (sscanf(str.c_str(),
"%" PRIu64, &offset) == 1)
2281 raw_outputs.push_back(std::make_pair(amount, offset));
2285 setStatusError(
tr(
"Invalid output: ") + str);
2289 bool ret = m_wallet->set_blackballed_outputs(raw_outputs, add);
2292 setStatusError(
tr(
"Failed to mark outputs as spent"));
2303 setStatusError(
tr(
"Failed to parse output amount"));
2308 setStatusError(
tr(
"Failed to parse output offset"));
2311 bool ret = m_wallet->blackball_output(std::make_pair(raw_amount, raw_offset));
2314 setStatusError(
tr(
"Failed to mark output as spent"));
2325 setStatusError(
tr(
"Failed to parse output amount"));
2330 setStatusError(
tr(
"Failed to parse output offset"));
2333 bool ret = m_wallet->unblackball_output(std::make_pair(raw_amount, raw_offset));
2336 setStatusError(
tr(
"Failed to mark output as unspent"));
2347 setStatusError(
tr(
"Failed to parse key image"));
2350 bool ret = m_wallet->get_ring(raw_key_image, ring);
2353 setStatusError(
tr(
"Failed to get ring"));
2364 setStatusError(
tr(
"Failed to parse txid"));
2367 std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> raw_rings;
2368 bool ret = m_wallet->get_rings(raw_txid, raw_rings);
2371 setStatusError(
tr(
"Failed to get rings"));
2374 for (
const auto &r: raw_rings)
2386 setStatusError(
tr(
"Failed to parse key image"));
2389 bool ret = m_wallet->set_ring(raw_key_image, ring, relative);
2392 setStatusError(
tr(
"Failed to set ring"));
2400 m_wallet->segregate_pre_fork_outputs(segregate);
2405 m_wallet->segregation_height(
height);
2410 m_wallet->key_reuse_mitigation2(mitigation);
2415 return m_wallet->lock_keys_file();
2420 return m_wallet->unlock_keys_file();
2425 return m_wallet->is_keys_file_locked();
2430 return m_wallet->cold_key_image_sync(spent, unspent);
void setListener(WalletListener *listener)
bool recoverFromDevice(const std::string &path, const std::string &password, const std::string &device_name)
virtual std::string getUserNote(const std::string &txid) const override
getUserNote - return an arbitrary string note attached to a txid
virtual bool checkTxProof(const std::string &txid, const std::string &address, const std::string &message, const std::string &signature, bool &good, uint64_t &received, bool &in_pool, uint64_t &confirmations) override
size_t importMultisigImages(const std::vector< std::string > &images) override
importMultisigImages - imports other participants' multisig images
void setSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex, const std::string &label) override
setSubaddressLabel - sets the label of the specified subaddress
virtual std::string signMessage(const std::string &message) override
bool create(const std::string &path, const std::string &password, const std::string &language)
void rescanBlockchainAsync() override
rescanBlockchainAsync - rescans wallet asynchronously, starting from genesys
virtual void on_skip_transaction(uint64_t height, const crypto::hash &txid, const cryptonote::transaction &tx)
void setRecoveringFromDevice(bool recoveringFromDevice) override
setRecoveringFromDevice - set state to recovering from device
virtual bool blackballOutput(const std::string &amount, const std::string &offset) override
blackballs an output
virtual PendingTransaction * createSweepUnmixableTransaction() override
createSweepUnmixableTransaction creates transaction with unmixable outputs.
bool setPassword(const std::string &password) override
virtual void segregatePreForkOutputs(bool segregate) override
sets whether pre-fork outs are to be segregated
The TransactionHistory - interface for displaying transaction history.
virtual void setDefaultMixin(uint32_t arg) override
setDefaultMixin - setum number of mixins to be used for new transactions
std::string publicViewKey() const override
publicViewKey - returns public view key
const std::string & get_language_name() const
Returns the name of the language.
WalletListener * m_listener
Transaction-like interface for sending etn.
virtual boost::optional< epee::wipeable_string > on_device_pin_request()
virtual bool checkSpendProof(const std::string &txid, const std::string &message, const std::string &signature, bool &good) const override
uint64_t unlockedBalance(uint32_t accountIndex=0, bool public_blockchain=false) const override
virtual bool parse_uri(const std::string &uri, std::string &address, std::string &payment_id, uint64_t &amount, std::string &tx_description, std::string &recipient_name, std::vector< std::string > &unknown_parameters, std::string &error) override
virtual std::string signMultisigParticipant(const std::string &message) const override
signMultisigParticipant signs given message with the multisig public signer key
std::string secretViewKey() const override
secretViewKey - returns secret view key
virtual bool unblackballOutput(const std::string &amount, const std::string &offset) override
unblackballs an output
#define MCWARNING(cat, x)
std::string publicSpendKey() const override
publicSpendKey - returns public spend key
friend class AddressBookImpl
PendingTransaction * createTransaction(const std::string &dst_addr, const std::string &payment_id, optional< uint64_t > amount, uint32_t mixin_count, PendingTransaction::Priority priority=PendingTransaction::Priority_Low, uint32_t subaddr_account=0, std::set< uint32_t > subaddr_indices={}) override
createTransaction creates transaction. if dst_addr is an integrated address, payment_id is ignored ...
bool connectToDaemon() override
connectToDaemon - connects to the daemon. TODO: check if it can be removed
#define CRYPTONOTE_DISPLAY_DECIMAL_POINT
virtual bool getRings(const std::string &txid, std::vector< std::pair< std::string, std::vector< uint64_t >>> &rings) const override
gets the rings used for a txid, if any
epee::misc_utils::struct_init< response_t > response
virtual void segregationHeight(uint64_t height) override
sets the height where segregation should occur
bool close(bool store=true)
std::string print_etn(uint64_t amount, unsigned int decimal_point)
const std::string old_language_name
bool finalizeMultisig(const std::vector< std::string > &extraMultisigInfo) override
finalizeMultisig - finalizes N - 1 / N multisig wallets creation
friend struct Wallet2CallbackImpl
std::string mlog_get_default_log_path(const char *default_filename)
std::string getSeedLanguage() const override
uint64_t daemonBlockChainTargetHeight() const override
daemonBlockChainTargetHeight - returns daemon blockchain target height
virtual void startRefresh() override
StartRefresh - Start/resume refresh thread (refresh every 10 seconds)
void mlog_configure(const std::string &filename_base, bool console, const std::size_t max_log_file_size=MAX_LOG_FILE_SIZE, const std::size_t max_log_files=MAX_LOG_FILES)
bool trustedDaemon() const override
virtual std::string getReserveProof(bool all, uint32_t account_index, uint64_t amount, const std::string &message) const override
getReserveProof - Generates a proof that proves the reserve of unspent funds Parameters account_index...
bool useForkRules(uint8_t version, int64_t early_blocks) const override
check if hard fork rules should be used
virtual bool verifyMessageWithPublicKey(const std::string &message, const std::string &publicKey, const std::string &signature) const override
verifyMessageWithPublicKey verifies that message was signed with the given public key ...
bool exportKeyImages(const std::string &filename) override
exportKeyImages - exports key images to file
virtual void on_unconfirmed_etn_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction &tx, uint64_t amount, const cryptonote::subaddress_index &subaddr_index)
virtual bool unlockKeysFile() override
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
bool hasMultisigPartialKeyImages() const override
hasMultisigPartialKeyImages - checks if wallet needs to import multisig key images from other partici...
std::string errorString() const override
in case error status, returns error string
virtual void on_etn_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction &tx, uint64_t amount, const cryptonote::subaddress_index &subaddr_index, uint64_t unlock_time)
virtual void on_lw_etn_received(uint64_t height, const crypto::hash &txid, uint64_t amount)
bool words_to_bytes(const epee::wipeable_string &words, epee::wipeable_string &dst, size_t len, bool duplicate, std::string &language_name)
Converts seed words to bytes (secret key).
virtual bool isKeysFileLocked() override
returns true if the keys file is locked
virtual std::string getTxProof(const std::string &txid, const std::string &address, const std::string &message) const override
bool recoverFromKeys(const std::string &path, const std::string &language, const std::string &address_string, const std::string &viewkey_string, const std::string &spendkey_string="")
virtual void on_device_progress(const hw::device_progress &event)
virtual bool blackballOutputs(const std::vector< std::string > &outputs, bool add) override
blackballs a set of outputs
virtual void disposeTransaction(PendingTransaction *t) override
disposeTransaction - destroys transaction object
virtual void setListener(WalletListener *l) override
bool open(const std::string &path, const std::string &password)
bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit=0, const std::string &daemon_username="", const std::string &daemon_password="", bool use_ssl=false, bool lightWallet=false) override
init - initializes wallet with daemon connection params. if daemon_address is local address...
void statusWithErrorString(int &status, std::string &errorString) const override
returns both error and error string atomically. suggested to use in instead of status() and errorStri...
std::string integratedAddress(const std::string &payment_id) const override
integratedAddress - returns integrated address for current wallet address and given payment_id...
uint64_t estimateBlockChainHeight() const override
estimateBlockChainHeight - returns estimate blockchain height. More accurate than approximateBlockCha...
void setTrustedDaemon(bool arg) override
Holds cryptonote related classes and helpers.
virtual void pauseRefresh() override
pauseRefresh - pause refresh thread
virtual void on_new_block(uint64_t height, const cryptonote::block &block)
friend class SubaddressAccountImpl
std::string address(uint32_t accountIndex=0, uint32_t addressIndex=0) const override
bool parse_amount(uint64_t &amount, const std::string &str_amount_)
virtual bool lockKeysFile() override
locks/unlocks the keys file; returns true on success
bool rescanBlockchain() override
rescanBlockchain - rescans the wallet, updating transactions from daemon
virtual void on_lw_etn_spent(uint64_t height, const crypto::hash &txid, uint64_t amount)
bool isAddressLocal(const std::string &address)
virtual bool verifySignedMessage(const std::string &message, const std::string &address, const std::string &signature) const override
verifySignedMessage - verify a signature matches a given message
friend class TransactionHistoryImpl
PendingTransaction * restoreMultisigTransaction(const std::string &signData) override
restoreMultisigTransaction creates PendingTransaction from signData
virtual SubaddressAccount * subaddressAccount() override
bool rescanSpent() override
static void error(const std::string &category, const std::string &str)
virtual AddressBook * addressBook() override
void setSeedLanguage(const std::string &arg) override
void hardForkInfo(uint8_t &version, uint64_t &earliest_height) const override
returns current hard fork info
bool setDevicePin(const std::string &password) override
bool exportMultisigImages(std::string &images) override
exportMultisigImages - exports transfers' key images
The AddressBook - interface for Book.
bool recover(const std::string &path, const std::string &password, const std::string &seed)
unsigned __int64 uint64_t
MultisigState multisig() const override
multisig - returns current state of multisig wallet creation process
virtual bool checkTxKey(const std::string &txid, std::string tx_key, const std::string &address, uint64_t &received, bool &in_pool, uint64_t &confirmations) override
std::string getMultisigInfo() const override
getMultisigInfo
virtual TransactionHistory * history() override
virtual bool setUserNote(const std::string &txid, const std::string ¬e) override
setUserNote - attach an arbitrary string note to a txid
void refreshAsync() override
refreshAsync - refreshes wallet asynchronously.
Transaction-like interface for sending etn.
virtual void on_device_button_request(uint64_t code)
bool refresh() override
refresh - refreshes the wallet, updating transactions from daemon
version
Supported socks variants.
virtual std::string getSpendProof(const std::string &txid, const std::string &message) const override
virtual bool lightWalletLogin(bool &isNewWallet) const override
Light wallet authenticate and login.
Device getDeviceType() const override
Queries backing device for wallet keys.
std::string message("Message requiring signing")
virtual void keyReuseMitigation2(bool mitigation) override
secondary key reuse mitigation
WalletListener * getListener() const
void addSubaddress(uint32_t accountIndex, const std::string &label) override
addSubaddress - appends a new subaddress at the end of the last minor index of the specified subaddre...
bool importKeyImages(const std::string &filename) override
importKeyImages - imports key images from file
void setRecoveringFromSeed(bool recoveringFromSeed) override
setRecoveringFromSeed - set state recover form seed
account_public_address addr
uint64_t blockChainHeight() const override
blockChainHeight - returns current blockchain height
bool createWatchOnly(const std::string &path, const std::string &password, const std::string &language) const override
createWatchOnly - Creates a watch only wallet
virtual double progress() const
friend class UnsignedTransactionImpl
void setRefreshFromBlockHeight(uint64_t refresh_from_block_height) override
setRefreshFromBlockHeight - start refresh from block height on recover
bool setDevicePassphrase(const std::string &password) override
virtual bool setRing(const std::string &key_image, const std::vector< uint64_t > &ring, bool relative) override
sets the ring used for a key image
virtual uint32_t defaultMixin() const override
defaultMixin - returns number of mixins used in transactions
virtual bool checkReserveProof(const std::string &address, const std::string &message, const std::string &signature, bool &good, uint64_t &total, uint64_t &spent) const override
std::string seed() const override
const T & move(const T &t)
int autoRefreshInterval() const override
autoRefreshInterval - returns automatic refresh interval in millis
bool watchOnly() const override
watchOnly - checks if wallet is watch only
void * memcpy(void *a, const void *b, size_t c)
std::string makeMultisig(const std::vector< std::string > &info, uint32_t threshold) override
makeMultisig - switches wallet in multisig state. The one and only creation phase for N / N wallets ...
size_t numSubaddressAccounts() const override
numSubaddressAccounts - returns the number of existing subaddress accounts
New English word list and map.
bool recoverFromKeysWithPassword(const std::string &path, const std::string &password, const std::string &language, const std::string &address_string, const std::string &viewkey_string, const std::string &spendkey_string="")
crypto::hash get_transaction_hash(const transaction &t)
friend class PendingTransactionImpl
bool add_extra_nonce_to_tx_extra(std::vector< uint8_t > &tx_extra, const blobdata &extra_nonce)
size_t numSubaddresses(uint32_t accountIndex) const override
numSubaddresses - returns the number of existing subaddresses associated with the specified subaddres...
bool get_account_address_from_str(address_parse_info &info, network_type nettype, std::string const &str)
NetworkType nettype() const override
bool synchronized() const override
synchronized - checks if wallet was ever synchronized
std::string secretSpendKey() const override
secretSpendKey - returns secret spend key
Mnemonic seed generation and wallet restoration from them.
uint64_t balance(uint32_t accountIndex=0, bool public_blockchain=false) const override
bool submitTransaction(const std::string &fileName) override
submitTransaction - submits transaction in signed tx file
virtual boost::optional< epee::wipeable_string > on_device_passphrase_request(bool on_device)
std::string publicMultisigSignerKey() const override
publicMultisigSignerKey - returns public signer key
int status() const override
returns wallet status (Status_Ok | Status_Error)
uint64_t daemonBlockChainHeight() const override
daemonBlockChainHeight - returns daemon blockchain height
virtual bool lightWalletImportWalletRequest(std::string &payment_id, uint64_t &fee, bool &new_request, bool &request_fulfilled, std::string &payment_address, std::string &status) override
Initiates a light wallet import wallet request.
bool store(const std::string &path) override
store - stores wallet to file.
static void info(const std::string &category, const std::string &str)
virtual std::string getTxKey(const std::string &txid) const override
Wallet2CallbackImpl(WalletImpl *wallet)
std::string getSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex) const override
getSubaddressLabel - gets the label of the specified subaddress
std::string exchangeMultisigKeys(const std::vector< std::string > &info) override
exchange_multisig_keys - provides additional key exchange round for arbitrary multisig schemes (like ...
virtual void on_lw_new_block(uint64_t height)
virtual std::string getDefaultDataDir() const override
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
void set_payment_id_to_tx_extra_nonce(blobdata &extra_nonce, const crypto::hash &payment_id)
uint64_t approximateBlockChainHeight() const override
approximateBlockChainHeight - returns approximate blockchain height calculated from date/time ...
void setAutoRefreshInterval(int millis) override
setAutoRefreshInterval - setup interval for automatic refresh.
virtual void on_etn_spent(uint64_t height, const crypto::hash &txid, const cryptonote::transaction &in_tx, uint64_t amount, const cryptonote::transaction &spend_tx, const cryptonote::subaddress_index &subaddr_index)
ConnectionStatus connected() const override
connected - checks if the wallet connected to the daemon
virtual void on_lw_unconfirmed_etn_received(uint64_t height, const crypto::hash &txid, uint64_t amount)
void setSubaddressLookahead(uint32_t major, uint32_t minor) override
setSubaddressLookahead - set size of subaddress lookahead
virtual bool getRing(const std::string &key_image, std::vector< uint64_t > &ring) const override
gets the ring used for a key image, if any
virtual UnsignedTransaction * loadUnsignedTx(const std::string &unsigned_filename) override
loadUnsignedTx - creates transaction from unsigned tx file
virtual void on_device_button_pressed()
std::string filename() const override
filename - returns wallet filename
error
Tracks LMDB error codes.
std::string keysFilename() const override
keysFilename - returns keys filename. usually this formed as "wallet_filename".keys ...
#define ELECTRONEUM_DEFAULT_LOG_CATEGORY
virtual Subaddress * subaddress() override
#define CORE_RPC_VERSION_MAJOR
void addSubaddressAccount(const std::string &label) override
addSubaddressAccount - appends a new subaddress account at the end of the last major index of existin...
virtual uint64_t coldKeyImageSync(uint64_t &spent, uint64_t &unspent) override
cold-device protocol key image sync
std::string path() const override
friend class SubaddressImpl
Interface for wallet operations. TODO: check if /include/IWallet.h is still actual.