diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f2ee53a..dc71cc25 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,8 +55,10 @@ message("Generated with config types: ${CMAKE_CONFIGURATION_TYPES}, and built ty enable_testing() +set(OPENSSL_USE_STATIC_LIBS TRUE) # link statically find_package(OpenSSL REQUIRED) + if(APPLE) set(CMAKE_OSX_DEPLOYMENT_TARGET 10.10.5) endif() diff --git a/src/currency_core/currency_format_utils_transactions.h b/src/currency_core/currency_format_utils_transactions.h index 29b70bc4..d123a54a 100644 --- a/src/currency_core/currency_format_utils_transactions.h +++ b/src/currency_core/currency_format_utils_transactions.h @@ -91,7 +91,7 @@ namespace currency struct tx_destination_entry { - uint64_t amount; //money + uint64_t amount = 0; //money std::list addr; //destination address, in case of 1 address - txout_to_key, in case of more - txout_multisig size_t minimum_sigs = 0; //if txout_multisig: minimum signatures that are required to spend this output (minimum_sigs <= addr.size()) IF txout_to_key - not used uint64_t amount_to_provide = 0; //amount money that provided by initial creator of tx, used with partially created transactions diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 9537390a..858a4e0c 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -225,6 +225,8 @@ simple_wallet::simple_wallet() m_cmd_binder.set_handler("export_history", boost::bind(&simple_wallet::submit_transfer, this,ph::_1), "Export transaction history in CSV file"); m_cmd_binder.set_handler("tor_enable", boost::bind(&simple_wallet::tor_enable, this, _1), "Enable relaying transactions over TOR network(enabled by default)"); m_cmd_binder.set_handler("tor_disable", boost::bind(&simple_wallet::tor_disable, this, _1), "Enable relaying transactions over TOR network(enabled by default)"); + m_cmd_binder.set_handler("deploy_new_asset", boost::bind(&simple_wallet::deploy_new_asset, this, _1), "Deploys new asset in the network, with current wallet as a maintainer"); + } //---------------------------------------------------------------------------------------------------- simple_wallet::~simple_wallet() @@ -756,7 +758,15 @@ bool simple_wallet::refresh(const std::vector& args) //---------------------------------------------------------------------------------------------------- bool simple_wallet::show_balance(const std::vector& args/* = std::vector()*/) { - success_msg_writer() << "balance: " << print_money(m_wallet->balance()) << ", unlocked balance: " << print_money(m_wallet->unlocked_balance()); + std::list balances; + uint64_t mined = 0; + m_wallet->balance(balances, mined); + std::stringstream ss; + for (const tools::wallet_public::asset_balance_entry& b : balances) + { + ss << std::setw(21) << print_fixed_decimal_point(b.total, b.asset_info.decimal_point) << "\t" << b.asset_info.ticker << ENDL; + } + success_msg_writer() << "Balance: " << ENDL << ss.str(); return true; } //---------------------------------------------------------------------------------------------------- @@ -1227,6 +1237,19 @@ bool simple_wallet::validate_wrap_status(uint64_t amount) } } //---------------------------------------------------------------------------------------------------- +bool preprocess_asset_id(std::string& address_arg, crypto::hash& asset_id) +{ + auto p = address_arg.find(':'); + if (p == std::string::npos) + return true; + std::string asset_id_str = address_arg.substr(0, p); + std::string address_itself = address_arg.substr(p+1, address_arg.size()); + if (!epee::string_tools::parse_tpod_from_hex_string(asset_id_str, asset_id)) + return false; + address_arg = address_itself; + return true; +} +//---------------------------------------------------------------------------------------------------- bool simple_wallet::transfer(const std::vector &args_) { if (!try_connect_to_daemon()) @@ -1272,8 +1295,8 @@ bool simple_wallet::transfer(const std::vector &args_) for (size_t i = 0; i < local_args.size(); i += 2) { std::string integrated_payment_id; - currency::tx_destination_entry de; - de.addr.resize(1); + currency::tx_destination_entry de = AUTO_VAL_INIT(de); + de.addr.resize(1); bool ok = currency::parse_amount(de.amount, local_args[i + 1]); if (!ok || 0 == de.amount) @@ -1282,6 +1305,12 @@ bool simple_wallet::transfer(const std::vector &args_) ", expected number from 0 to " << print_money(std::numeric_limits::max()); return true; } + + if (!preprocess_asset_id(local_args[i], de.asset_id)) + { + fail_msg_writer() << "address is wrong: " << local_args[i]; + return true; + } //check if address looks like wrapped address if (is_address_like_wrapped(local_args[i])) @@ -1307,7 +1336,8 @@ bool simple_wallet::transfer(const std::vector &args_) de.addr.front() = acc; wrapped_transaction = true; //encrypt body with a special way - }else if(!(de.addr.size() == 1 && m_wallet->get_transfer_address(local_args[i], de.addr.front(), integrated_payment_id))) + } + else if(!(de.addr.size() == 1 && m_wallet->get_transfer_address(local_args[i], de.addr.front(), integrated_payment_id))) { fail_msg_writer() << "wrong address: " << local_args[i]; return true; @@ -1754,7 +1784,39 @@ bool simple_wallet::tor_disable(const std::vector &args) success_msg_writer(true) << "TOR relaying disabled"; return true; } +//---------------------------------------------------------------------------------------------------- +bool simple_wallet::deploy_new_asset(const std::vector &args) +{ + asset_descriptor_base adb = AUTO_VAL_INIT(adb); + if (!args.size() || args.size() > 1) + { + fail_msg_writer() << "invalid agruments count: " << args.size() << ", expected 1"; + } + bool r = epee::serialization::load_t_from_json_file(adb, args[0]); + if (!r) + { + fail_msg_writer() << "Failed to load json file with asset specification: " << args[0]; + } + tx_destination_entry td = AUTO_VAL_INIT(td); + td.addr.push_back(m_wallet->get_account().get_public_address()); + td.amount = adb.current_supply; + td.asset_id = currency::ffff_hash; + std::vector destinations; + destinations.push_back(td); + currency::transaction result_tx = AUTO_VAL_INIT(result_tx); + crypto::hash result_asset_id = currency::null_hash; + m_wallet->publish_new_asset(adb, destinations, result_tx, result_asset_id); + success_msg_writer(true) << "New asset deployed: " << ENDL + << "Asset ID: "<< result_asset_id << ENDL + << "Title: " << adb.full_name << ENDL + << "Ticker: " << adb.ticker << ENDL + << "Emitted: " << print_fixed_decimal_point(adb.current_supply, adb.decimal_point) << ENDL + << "Max emission: " << print_fixed_decimal_point(adb.total_max_supply, adb.decimal_point) << ENDL + ; + + return true; +} //---------------------------------------------------------------------------------------------------- bool simple_wallet::sweep_below(const std::vector &args) { diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index f5138544..6c92c634 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -88,6 +88,7 @@ namespace currency bool sweep_below(const std::vector &args); bool tor_enable(const std::vector &args); bool tor_disable(const std::vector &args); + bool deploy_new_asset(const std::vector &args); bool validate_wrap_status(uint64_t amount); bool get_alias_from_daemon(const std::string& alias_name, currency::extra_alias_entry_base& ai); diff --git a/src/wallet/view_iface.h b/src/wallet/view_iface.h index 85bb353e..70d60bfe 100644 --- a/src/wallet/view_iface.h +++ b/src/wallet/view_iface.h @@ -35,10 +35,12 @@ namespace view { std::string address; std::string amount; + crypto::hash asset_id; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(address) KV_SERIALIZE(amount) + KV_SERIALIZE_POD_AS_HEX_STRING(asset_id) END_KV_SERIALIZE_MAP() }; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index a3b5884f..bb7cd199 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1782,7 +1782,7 @@ void wallet2::handle_pulled_blocks(size_t& blocks_added, std::atomic& stop m_chain.clear(); } } - else if (height == processed_blocks_count) + else if (height == processed_blocks_count && been_matched_block) { //regular block handling //self check @@ -2319,6 +2319,8 @@ bool wallet2::scan_unconfirmed_outdate_tx() //---------------------------------------------------------------------------------------------------- void wallet2::refresh(size_t & blocks_fetched, bool& received_money, std::atomic& stop) { + load_whitelisted_tokens_if_not_loaded(); + received_money = false; blocks_fetched = 0; size_t added_blocks = 0; @@ -3142,31 +3144,42 @@ bool wallet2::balance(std::unordered_map& balances, uint64_t& mined) const { + load_whitelisted_tokens_if_not_loaded(); std::unordered_map balances_map; this->balance(balances_map, mined); for (const auto& item : balances_map) { + asset_descriptor_base native_asset_info = AUTO_VAL_INIT(native_asset_info); + native_asset_info.full_name = CURRENCY_NAME_SHORT_BASE; + native_asset_info.ticker = CURRENCY_NAME_ABR; + native_asset_info.decimal_point = CURRENCY_DISPLAY_DECIMAL_POINT; const asset_descriptor_base* asset_ptr = nullptr; //check if asset is whitelisted or customly added - auto it = m_whitelisted_assets.find(item.first); - if (it == m_whitelisted_assets.end()) + if (item.first == currency::null_hash) { - //check if it custom asset - auto it_cust = m_custom_assets.find(item.first); - if (it_cust == m_custom_assets.end()) - { - continue; - } - else - { - asset_ptr = &it_cust->second; - } + asset_ptr = &native_asset_info; } else { - asset_ptr = &it->second; - } - + auto it = m_whitelisted_assets.find(item.first); + if (it == m_whitelisted_assets.end()) + { + //check if it custom asset + auto it_cust = m_custom_assets.find(item.first); + if (it_cust == m_custom_assets.end()) + { + continue; + } + else + { + asset_ptr = &it_cust->second; + } + } + else + { + asset_ptr = &it->second; + } + } balances.push_back(wallet_public::asset_balance_entry()); wallet_public::asset_balance_entry& new_item = balances.back(); static_cast(new_item) = item.second; @@ -3209,8 +3222,9 @@ bool wallet2::delete_custom_asset_id(const crypto::hash& asset_id) return true; } //---------------------------------------------------------------------------------------------------- -bool wallet2::load_whitelisted_tokens_list() +bool wallet2::load_whitelisted_tokens() const { + m_whitelisted_assets.clear(); std::string body; wallet_public::assets_whitelist aw = AUTO_VAL_INIT(aw); if (epee::net_utils::get_http_json_t(WALLET_ASSETS_WHITELIST_URL, aw)) @@ -3223,6 +3237,15 @@ bool wallet2::load_whitelisted_tokens_list() return true; } //---------------------------------------------------------------------------------------------------- +bool wallet2::load_whitelisted_tokens_if_not_loaded() const +{ + if (m_whitelisted_assets.size()) + { + return true; + } + return load_whitelisted_tokens(); +} +//---------------------------------------------------------------------------------------------------- void wallet2::get_transfers(wallet2::transfer_container& incoming_transfers) const { incoming_transfers = m_transfers; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 737e8beb..ad23389e 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -901,7 +901,8 @@ namespace tools bool add_custom_asset_id(const crypto::hash& asset_id); bool delete_custom_asset_id(const crypto::hash& asset_id); - bool load_whitelisted_tokens_list(); + bool load_whitelisted_tokens_if_not_loaded() const; + bool load_whitelisted_tokens()const; /* create_htlc_proposal: if htlc_hash == null_hash, then this wallet is originator of the atomic process, and @@ -1100,7 +1101,7 @@ private: std::unordered_map m_tx_keys; std::unordered_map m_own_asset_descriptors; std::unordered_map m_custom_assets; //assets that manually added by user - std::unordered_map m_whitelisted_assets; //assets that manually added by user + mutable std::unordered_map m_whitelisted_assets; //assets that whitelisted std::multimap m_htlcs; //map [expired_if_more_then] -> height of expiration diff --git a/src/wallet/wallets_manager.cpp b/src/wallet/wallets_manager.cpp index 16357bb5..ac3c266e 100644 --- a/src/wallet/wallets_manager.cpp +++ b/src/wallet/wallets_manager.cpp @@ -943,7 +943,6 @@ std::string wallets_manager::open_wallet(const std::wstring& path, const std::st w->load(path, password); if (w->is_watch_only() && !w->is_auditable()) return API_RETURN_CODE_WALLET_WATCH_ONLY_NOT_SUPPORTED; - w->load_whitelisted_tokens_list(); w->get_recent_transfers_history(owr.recent_history.history, 0, txs_to_return, owr.recent_history.total_history_items, owr.recent_history.last_item_index, exclude_mining_txs); //w->get_unconfirmed_transfers(owr.recent_history.unconfirmed);