Merge branch 'develop' into develop_mobile
|
|
@ -60,18 +60,42 @@ namespace currency
|
|||
return m_keys;
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
std::string account_base::get_seed_phrase() const
|
||||
void crypt_with_pass(const void* scr_data, std::size_t src_length, void* dst_data, const std::string& password)
|
||||
{
|
||||
crypto::chacha8_key key = AUTO_VAL_INIT(key);
|
||||
crypto::generate_chacha8_key(password, key);
|
||||
crypto::hash pass_hash = crypto::cn_fast_hash(password.data(), password.size());
|
||||
crypto::chacha8_iv iv = AUTO_VAL_INIT(iv);
|
||||
CHECK_AND_ASSERT_THROW_MES(sizeof(pass_hash) >= sizeof(iv), "Invalid configuration: hash size is less than keys_file_data.iv");
|
||||
iv = *((crypto::chacha8_iv*)&pass_hash);
|
||||
crypto::chacha8(scr_data, src_length, key, iv, (char*)dst_data);
|
||||
}
|
||||
|
||||
|
||||
std::string account_base::get_seed_phrase(const std::string& password) const
|
||||
{
|
||||
if (m_keys_seed_binary.empty())
|
||||
return "";
|
||||
std::string keys_seed_text = tools::mnemonic_encoding::binary2text(m_keys_seed_binary);
|
||||
std::string timestamp_word = currency::get_word_from_timstamp(m_creation_timestamp);
|
||||
|
||||
std::vector<unsigned char> processed_seed_binary = m_keys_seed_binary;
|
||||
if (!password.empty())
|
||||
{
|
||||
//encrypt seed phrase binary data
|
||||
crypt_with_pass(&m_keys_seed_binary[0], m_keys_seed_binary.size(), &processed_seed_binary[0], password);
|
||||
}
|
||||
|
||||
std::string keys_seed_text = tools::mnemonic_encoding::binary2text(processed_seed_binary);
|
||||
std::string timestamp_word = currency::get_word_from_timstamp(m_creation_timestamp, !password.empty());
|
||||
|
||||
// floor creation time to WALLET_BRAIN_DATE_QUANTUM to make checksum calculation stable
|
||||
uint64_t creation_timestamp_rounded = get_timstamp_from_word(timestamp_word);
|
||||
bool self_check_is_password_used = false;
|
||||
uint64_t creation_timestamp_rounded = get_timstamp_from_word(timestamp_word, self_check_is_password_used);
|
||||
CHECK_AND_ASSERT_THROW_MES(self_check_is_password_used == !password.empty(), "Account seed phrase internal error: password flag encoded wrong");
|
||||
|
||||
constexpr uint16_t checksum_max = tools::mnemonic_encoding::NUMWORDS >> 1; // maximum value of checksum
|
||||
crypto::hash h = crypto::cn_fast_hash(m_keys_seed_binary.data(), m_keys_seed_binary.size());
|
||||
std::string binary_for_check_sum((const char*)&m_keys_seed_binary[0], m_keys_seed_binary.size());
|
||||
binary_for_check_sum.append(password);
|
||||
crypto::hash h = crypto::cn_fast_hash(binary_for_check_sum.data(), binary_for_check_sum.size());
|
||||
*reinterpret_cast<uint64_t*>(&h) = creation_timestamp_rounded;
|
||||
h = crypto::cn_fast_hash(&h, sizeof h);
|
||||
uint64_t h_64 = *reinterpret_cast<uint64_t*>(&h);
|
||||
|
|
@ -104,7 +128,7 @@ namespace currency
|
|||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
bool account_base::restore_from_seed_phrase(const std::string& seed_phrase)
|
||||
bool account_base::restore_from_seed_phrase(const std::string& seed_phrase, const std::string& seed_password)
|
||||
{
|
||||
//cut the last timestamp word from restore_dats
|
||||
std::list<std::string> words;
|
||||
|
|
@ -138,9 +162,20 @@ namespace currency
|
|||
auditable_flag_and_checksum = tools::mnemonic_encoding::num_by_word(auditable_flag_and_checksum_word);
|
||||
|
||||
std::vector<unsigned char> keys_seed_binary = tools::mnemonic_encoding::text2binary(keys_seed_text);
|
||||
CHECK_AND_ASSERT_MES(keys_seed_binary.size(), false, "text2binary failed to convert the given text"); // don't prints event incorrect seed into the log for security
|
||||
std::vector<unsigned char> keys_seed_processed_binary = keys_seed_binary;
|
||||
|
||||
m_creation_timestamp = get_timstamp_from_word(timestamp_word);
|
||||
|
||||
bool has_password = false;
|
||||
m_creation_timestamp = get_timstamp_from_word(timestamp_word, has_password);
|
||||
//double check is password setting from timestamp word match with passed parameters
|
||||
CHECK_AND_ASSERT_MES(has_password != seed_password.empty(), false, "Seed phrase password wrong interpretation");
|
||||
if (has_password)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(!seed_password.empty(), false, "Seed phrase password wrong interpretation: internal error");
|
||||
crypt_with_pass(&keys_seed_binary[0], keys_seed_binary.size(), &keys_seed_processed_binary[0], seed_password);
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_MES(keys_seed_processed_binary.size(), false, "text2binary failed to convert the given text"); // don't prints event incorrect seed into the log for security
|
||||
|
||||
bool auditable_flag = false;
|
||||
|
||||
|
|
@ -150,7 +185,9 @@ namespace currency
|
|||
auditable_flag = (auditable_flag_and_checksum & 1) != 0; // auditable flag is the lower 1 bit
|
||||
uint16_t checksum = static_cast<uint16_t>(auditable_flag_and_checksum >> 1); // checksum -- everything else
|
||||
constexpr uint16_t checksum_max = tools::mnemonic_encoding::NUMWORDS >> 1; // maximum value of checksum
|
||||
crypto::hash h = crypto::cn_fast_hash(keys_seed_binary.data(), keys_seed_binary.size());
|
||||
std::string binary_for_check_sum((const char*)&keys_seed_processed_binary[0], keys_seed_processed_binary.size());
|
||||
binary_for_check_sum.append(seed_password);
|
||||
crypto::hash h = crypto::cn_fast_hash(binary_for_check_sum.data(), binary_for_check_sum.size());
|
||||
*reinterpret_cast<uint64_t*>(&h) = m_creation_timestamp;
|
||||
h = crypto::cn_fast_hash(&h, sizeof h);
|
||||
uint64_t h_64 = *reinterpret_cast<uint64_t*>(&h);
|
||||
|
|
@ -158,10 +195,10 @@ namespace currency
|
|||
CHECK_AND_ASSERT_MES(checksum == checksum_calculated, false, "seed phase has invalid checksum: " << checksum_calculated << ", while " << checksum << " is expected, check your words");
|
||||
}
|
||||
|
||||
bool r = restore_keys(keys_seed_binary);
|
||||
bool r = restore_keys(keys_seed_processed_binary);
|
||||
CHECK_AND_ASSERT_MES(r, false, "restore_keys failed");
|
||||
|
||||
m_keys_seed_binary = keys_seed_binary;
|
||||
m_keys_seed_binary = keys_seed_processed_binary;
|
||||
|
||||
if (auditable_flag)
|
||||
m_keys.account_address.flags |= ACCOUNT_PUBLIC_ADDRESS_FLAG_AUDITABLE;
|
||||
|
|
@ -169,6 +206,34 @@ namespace currency
|
|||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
bool account_base::is_seed_password_protected(const std::string& seed_phrase, bool& is_password_protected)
|
||||
{
|
||||
//cut the last timestamp word from restore_dats
|
||||
std::list<std::string> words;
|
||||
boost::split(words, seed_phrase, boost::is_space());
|
||||
|
||||
std::string timestamp_word;
|
||||
if (words.size() == SEED_PHRASE_V1_WORDS_COUNT)
|
||||
{
|
||||
// 24 seed words + one timestamp word = 25 total
|
||||
timestamp_word = words.back();
|
||||
}
|
||||
else if (words.size() == SEED_PHRASE_V2_WORDS_COUNT)
|
||||
{
|
||||
// 24 seed words + one timestamp word + one flags & checksum = 26 total
|
||||
words.erase(--words.end());
|
||||
timestamp_word = words.back();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
get_timstamp_from_word(timestamp_word, is_password_protected);
|
||||
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
bool account_base::restore_from_tracking_seed(const std::string& tracking_seed)
|
||||
{
|
||||
set_null();
|
||||
|
|
|
|||
|
|
@ -53,9 +53,9 @@ namespace currency
|
|||
const account_public_address& get_public_address() const { return m_keys.account_address; };
|
||||
std::string get_public_address_str() const;
|
||||
|
||||
std::string get_seed_phrase() const;
|
||||
std::string get_seed_phrase(const std::string& seed_password) const;
|
||||
std::string get_tracking_seed() const;
|
||||
bool restore_from_seed_phrase(const std::string& seed_phrase);
|
||||
bool restore_from_seed_phrase(const std::string& seed_phrase, const std::string& seed_password);
|
||||
bool restore_from_tracking_seed(const std::string& tracking_seed);
|
||||
|
||||
uint64_t get_createtime() const { return m_creation_timestamp; }
|
||||
|
|
@ -78,6 +78,7 @@ namespace currency
|
|||
|
||||
static std::string vector_of_chars_to_string(const std::vector<unsigned char>& v) { return std::string(v.begin(), v.end()); }
|
||||
static std::vector<unsigned char> string_to_vector_of_chars(const std::string& v) { return std::vector<unsigned char>(v.begin(), v.end()); }
|
||||
static bool is_seed_password_protected(const std::string& seed_phrase, bool& is_password_protected);
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(m_keys)
|
||||
|
|
|
|||
|
|
@ -150,9 +150,10 @@
|
|||
|
||||
#define WALLET_FILE_MAX_KEYS_SIZE 10000 //
|
||||
#define WALLET_BRAIN_DATE_OFFSET 1543622400
|
||||
#define WALLET_BRAIN_DATE_QUANTUM 604800 //by last word we encode a number of week since launch of the project,
|
||||
#define WALLET_BRAIN_DATE_QUANTUM 604800 //by last word we encode a number of week since launch of the project AND password flag,
|
||||
//which let us to address tools::mnemonic_encoding::NUMWORDS weeks after project launch
|
||||
//which is about 30 years
|
||||
//which is about 15 years
|
||||
#define WALLET_BRAIN_DATE_MAX_WEEKS_COUNT 800
|
||||
|
||||
#define OFFER_MAXIMUM_LIFE_TIME (60*60*24*30) // 30 days
|
||||
|
||||
|
|
|
|||
|
|
@ -1316,21 +1316,34 @@ namespace currency
|
|||
return reward;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
std::string get_word_from_timstamp(uint64_t timestamp)
|
||||
std::string get_word_from_timstamp(uint64_t timestamp, bool use_password)
|
||||
{
|
||||
uint64_t date_offset = timestamp > WALLET_BRAIN_DATE_OFFSET ? timestamp - WALLET_BRAIN_DATE_OFFSET : 0;
|
||||
uint64_t weeks_count = date_offset / WALLET_BRAIN_DATE_QUANTUM;
|
||||
CHECK_AND_ASSERT_THROW_MES(weeks_count < WALLET_BRAIN_DATE_MAX_WEEKS_COUNT, "SEED PHRASE need to be extended or refactored");
|
||||
|
||||
if (use_password)
|
||||
weeks_count += WALLET_BRAIN_DATE_MAX_WEEKS_COUNT;
|
||||
|
||||
CHECK_AND_ASSERT_THROW_MES(weeks_count < std::numeric_limits<uint32_t>::max(), "internal error: unable to convert to uint32, val = " << weeks_count);
|
||||
uint32_t weeks_count_32 = static_cast<uint32_t>(weeks_count);
|
||||
|
||||
return tools::mnemonic_encoding::word_by_num(weeks_count_32);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
uint64_t get_timstamp_from_word(std::string word)
|
||||
uint64_t get_timstamp_from_word(std::string word, bool& password_used)
|
||||
{
|
||||
uint64_t count_of_weeks = tools::mnemonic_encoding::num_by_word(word);
|
||||
if (count_of_weeks >= WALLET_BRAIN_DATE_MAX_WEEKS_COUNT)
|
||||
{
|
||||
count_of_weeks -= WALLET_BRAIN_DATE_MAX_WEEKS_COUNT;
|
||||
password_used = true;
|
||||
}
|
||||
else {
|
||||
password_used = false;
|
||||
}
|
||||
uint64_t timestamp = count_of_weeks * WALLET_BRAIN_DATE_QUANTUM + WALLET_BRAIN_DATE_OFFSET;
|
||||
|
||||
|
||||
return timestamp;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -291,8 +291,8 @@ namespace currency
|
|||
bool fill_tx_rpc_details(tx_rpc_extended_info& tei, const transaction& tx, const transaction_chain_entry* ptce, const crypto::hash& h, uint64_t timestamp, bool is_short = false);
|
||||
bool fill_block_rpc_details(block_rpc_extended_info& pei_rpc, const block_extended_info& bei_chain, const crypto::hash& h);
|
||||
void append_per_block_increments_for_tx(const transaction& tx, std::unordered_map<uint64_t, uint32_t>& gindices);
|
||||
std::string get_word_from_timstamp(uint64_t timestamp);
|
||||
uint64_t get_timstamp_from_word(std::string word);
|
||||
std::string get_word_from_timstamp(uint64_t timestamp, bool use_password);
|
||||
uint64_t get_timstamp_from_word(std::string word, bool& password_used);
|
||||
|
||||
template<class t_txin_v>
|
||||
typename std::conditional<std::is_const<t_txin_v>::value, const std::vector<txin_etc_details_v>, std::vector<txin_etc_details_v> >::type& get_txin_etc_options(t_txin_v& in)
|
||||
|
|
|
|||
|
|
@ -239,6 +239,28 @@ QString MainWindow::get_tx_pool_info()
|
|||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
|
||||
QString MainWindow::request_dummy()
|
||||
{
|
||||
static int code_ = 0;
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
PREPARE_RESPONSE(currency::COMMAND_RPC_GET_POOL_INFO::response, ar);
|
||||
if (code_ == 2)
|
||||
{
|
||||
code_ = -1;
|
||||
ar.error_code = API_RETURN_CODE_CORE_BUSY;
|
||||
}
|
||||
else
|
||||
{
|
||||
ar.error_code = API_RETURN_CODE_OK;
|
||||
}
|
||||
|
||||
++code_;
|
||||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
|
||||
|
||||
QString MainWindow::get_default_fee()
|
||||
{
|
||||
TRY_ENTRY();
|
||||
|
|
@ -1654,7 +1676,7 @@ QString MainWindow::restore_wallet(const QString& param)
|
|||
//return que_call2<view::restore_wallet_request>("restore_wallet", param, [this](const view::restore_wallet_request& owd, view::api_response& ar){
|
||||
PREPARE_ARG_FROM_JSON(view::restore_wallet_request, owd);
|
||||
PREPARE_RESPONSE(view::open_wallet_response, ar);
|
||||
ar.error_code = m_backend.restore_wallet(epee::string_encoding::utf8_to_wstring(owd.path), owd.pass, owd.restore_key, ar.response_data);
|
||||
ar.error_code = m_backend.restore_wallet(epee::string_encoding::utf8_to_wstring(owd.path), owd.pass, owd.seed_phrase, owd.seed_pass, ar.response_data);
|
||||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
|
|
@ -1855,9 +1877,9 @@ QString MainWindow::get_smart_wallet_info(const QString& param)
|
|||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
PREPARE_ARG_FROM_JSON(view::wallet_id_obj, wo);
|
||||
PREPARE_ARG_FROM_JSON(view::request_get_smart_wallet_info, wo);
|
||||
PREPARE_RESPONSE(view::get_restore_info_response, ar);
|
||||
ar.error_code = m_backend.get_wallet_restore_info(wo.wallet_id, ar.response_data.restore_key);
|
||||
ar.error_code = m_backend.get_wallet_restore_info(wo.wallet_id, ar.response_data.seed_phrase, wo.seed_password);
|
||||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
|
|
@ -1951,14 +1973,26 @@ QString MainWindow::open_url_in_browser(const QString& param)
|
|||
CATCH_ENTRY2(API_RETURN_CODE_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
|
||||
QString MainWindow::is_valid_restore_wallet_text(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
return m_backend.is_valid_brain_restore_data(param.toStdString()).c_str();
|
||||
PREPARE_ARG_FROM_JSON(view::is_valid_restore_wallet_text_param, rwtp);
|
||||
return m_backend.is_valid_brain_restore_data(rwtp.seed_phrase, rwtp.seed_password).c_str();
|
||||
CATCH_ENTRY2(API_RETURN_CODE_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
QString MainWindow::get_seed_phrase_info(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
PREPARE_ARG_FROM_JSON(view::is_valid_restore_wallet_text_param, rwtp);
|
||||
PREPARE_RESPONSE(view::seed_phrase_info, ar);
|
||||
ar.error_code = m_backend.get_seed_phrase_info(rwtp.seed_phrase, rwtp.seed_password, ar.response_data).c_str();
|
||||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
|
||||
void MainWindow::contextMenuEvent(QContextMenuEvent * event)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ public:
|
|||
QString is_autostart_enabled();
|
||||
QString toggle_autostart(const QString& param);
|
||||
QString is_valid_restore_wallet_text(const QString& param);
|
||||
QString get_seed_phrase_info(const QString& param);
|
||||
QString print_text(const QString& param);
|
||||
QString print_log(const QString& param);
|
||||
QString set_clipboard(const QString& param);
|
||||
|
|
@ -159,6 +160,9 @@ public:
|
|||
QString is_remnotenode_mode_preconfigured();
|
||||
QString start_backend(const QString& params);
|
||||
|
||||
//for test purposes onlys
|
||||
QString request_dummy();
|
||||
|
||||
signals:
|
||||
void quit_requested(const QString str);
|
||||
void update_daemon_state(const QString str);
|
||||
|
|
|
|||
10
src/gui/qt-daemon/html/assets/icons/close-wallet-blue.svg
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 34 34" style="enable-background:new 0 0 34 34;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#4db1ff;}
|
||||
</style>
|
||||
<polygon class="st0" points="31.9,4.9 29.1,2.1 17,14.2 4.9,2.1 2.1,4.9 14.2,17 2.1,29.1 4.9,31.9 17,19.8 29.1,31.9 31.9,29.1
|
||||
19.8,17 "/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 549 B |
10
src/gui/qt-daemon/html/assets/icons/receive-green.svg
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="icons" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 384 384" style="enable-background:new 0 0 384 384;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#5cda9d;}
|
||||
</style>
|
||||
<path id="receive" class="st0" d="M64.2,309.6l58.2-210.4l48.1,71.6L178,182l12.7,4.7l81.9,30.4L64.2,309.6 M0,384l384-170.3
|
||||
l-178.7-66.4L106.3,0L0,384L0,384z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 573 B |
10
src/gui/qt-daemon/html/assets/icons/send-red.svg
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="icons" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 384 384" style="enable-background:new 0 0 384 384;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#ff5252;}
|
||||
</style>
|
||||
<path id="send" class="st0" d="M319.8,74.4l-58.2,210.4l-48.1-71.6L206,202l-12.7-4.7l-81.9-30.4L319.8,74.4 M384,0L0,170.3
|
||||
l178.7,66.4L277.7,384L384,0L384,0z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 573 B |
0
src/gui/qt-daemon/html/assets/scss/layout/_settings.scss
Normal file
10
src/gui/qt-daemon/html/close-wallet-blue.svg
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 34 34" style="enable-background:new 0 0 34 34;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#4db1ff;}
|
||||
</style>
|
||||
<polygon class="st0" points="31.9,4.9 29.1,2.1 17,14.2 4.9,2.1 2.1,4.9 14.2,17 2.1,29.1 4.9,31.9 17,19.8 29.1,31.9 31.9,29.1
|
||||
19.8,17 "/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 549 B |
|
|
@ -5800,8 +5800,8 @@ __webpack_require__.r(__webpack_exports__);
|
|||
/*! no static exports found */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
__webpack_require__(/*! /Users/mekasan/Projects/Projects/zano/src/gui/qt-daemon/html_source/src/polyfills.ts */"./src/polyfills.ts");
|
||||
module.exports = __webpack_require__(/*! /Users/mekasan/Projects/Projects/zano/src/gui/qt-daemon/html_source/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/jit-polyfills.js */"./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/jit-polyfills.js");
|
||||
__webpack_require__(/*! /Users/mekasan/Projects/Projects/zano_v1/src/gui/qt-daemon/html_source/src/polyfills.ts */"./src/polyfills.ts");
|
||||
module.exports = __webpack_require__(/*! /Users/mekasan/Projects/Projects/zano_v1/src/gui/qt-daemon/html_source/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/jit-polyfills.js */"./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/jit-polyfills.js");
|
||||
|
||||
|
||||
/***/ })
|
||||
|
|
|
|||
10
src/gui/qt-daemon/html/receive-green.svg
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="icons" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 384 384" style="enable-background:new 0 0 384 384;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#5cda9d;}
|
||||
</style>
|
||||
<path id="receive" class="st0" d="M64.2,309.6l58.2-210.4l48.1,71.6L178,182l12.7,4.7l81.9,30.4L64.2,309.6 M0,384l384-170.3
|
||||
l-178.7-66.4L106.3,0L0,384L0,384z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 573 B |
10
src/gui/qt-daemon/html/send-red.svg
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="icons" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 384 384" style="enable-background:new 0 0 384 384;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#ff5252;}
|
||||
</style>
|
||||
<path id="send" class="st0" d="M319.8,74.4l-58.2,210.4l-48.1-71.6L206,202l-12.7-4.7l-81.9-30.4L319.8,74.4 M384,0L0,170.3
|
||||
l178.7,66.4L277.7,384L384,0L384,0z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 573 B |
|
|
@ -90280,12 +90280,12 @@ exports.byteLength = byteLength
|
|||
exports.toByteArray = toByteArray
|
||||
exports.fromByteArray = fromByteArray
|
||||
|
||||
var lookup = []
|
||||
var revLookup = []
|
||||
var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
|
||||
const lookup = []
|
||||
const revLookup = []
|
||||
const Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
|
||||
|
||||
var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
||||
for (var i = 0, len = code.length; i < len; ++i) {
|
||||
const code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
||||
for (let i = 0, len = code.length; i < len; ++i) {
|
||||
lookup[i] = code[i]
|
||||
revLookup[code.charCodeAt(i)] = i
|
||||
}
|
||||
|
|
@ -90296,7 +90296,7 @@ revLookup['-'.charCodeAt(0)] = 62
|
|||
revLookup['_'.charCodeAt(0)] = 63
|
||||
|
||||
function getLens (b64) {
|
||||
var len = b64.length
|
||||
const len = b64.length
|
||||
|
||||
if (len % 4 > 0) {
|
||||
throw new Error('Invalid string. Length must be a multiple of 4')
|
||||
|
|
@ -90304,10 +90304,10 @@ function getLens (b64) {
|
|||
|
||||
// Trim off extra bytes after placeholder bytes are found
|
||||
// See: https://github.com/beatgammit/base64-js/issues/42
|
||||
var validLen = b64.indexOf('=')
|
||||
let validLen = b64.indexOf('=')
|
||||
if (validLen === -1) validLen = len
|
||||
|
||||
var placeHoldersLen = validLen === len
|
||||
const placeHoldersLen = validLen === len
|
||||
? 0
|
||||
: 4 - (validLen % 4)
|
||||
|
||||
|
|
@ -90316,9 +90316,9 @@ function getLens (b64) {
|
|||
|
||||
// base64 is 4/3 + up to two characters of the original data
|
||||
function byteLength (b64) {
|
||||
var lens = getLens(b64)
|
||||
var validLen = lens[0]
|
||||
var placeHoldersLen = lens[1]
|
||||
const lens = getLens(b64)
|
||||
const validLen = lens[0]
|
||||
const placeHoldersLen = lens[1]
|
||||
return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
|
||||
}
|
||||
|
||||
|
|
@ -90327,21 +90327,21 @@ function _byteLength (b64, validLen, placeHoldersLen) {
|
|||
}
|
||||
|
||||
function toByteArray (b64) {
|
||||
var tmp
|
||||
var lens = getLens(b64)
|
||||
var validLen = lens[0]
|
||||
var placeHoldersLen = lens[1]
|
||||
let tmp
|
||||
const lens = getLens(b64)
|
||||
const validLen = lens[0]
|
||||
const placeHoldersLen = lens[1]
|
||||
|
||||
var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))
|
||||
const arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))
|
||||
|
||||
var curByte = 0
|
||||
let curByte = 0
|
||||
|
||||
// if there are placeholders, only get up to the last complete 4 chars
|
||||
var len = placeHoldersLen > 0
|
||||
const len = placeHoldersLen > 0
|
||||
? validLen - 4
|
||||
: validLen
|
||||
|
||||
var i
|
||||
let i
|
||||
for (i = 0; i < len; i += 4) {
|
||||
tmp =
|
||||
(revLookup[b64.charCodeAt(i)] << 18) |
|
||||
|
|
@ -90380,9 +90380,9 @@ function tripletToBase64 (num) {
|
|||
}
|
||||
|
||||
function encodeChunk (uint8, start, end) {
|
||||
var tmp
|
||||
var output = []
|
||||
for (var i = start; i < end; i += 3) {
|
||||
let tmp
|
||||
const output = []
|
||||
for (let i = start; i < end; i += 3) {
|
||||
tmp =
|
||||
((uint8[i] << 16) & 0xFF0000) +
|
||||
((uint8[i + 1] << 8) & 0xFF00) +
|
||||
|
|
@ -90393,17 +90393,15 @@ function encodeChunk (uint8, start, end) {
|
|||
}
|
||||
|
||||
function fromByteArray (uint8) {
|
||||
var tmp
|
||||
var len = uint8.length
|
||||
var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
|
||||
var parts = []
|
||||
var maxChunkLength = 16383 // must be multiple of 3
|
||||
let tmp
|
||||
const len = uint8.length
|
||||
const extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
|
||||
const parts = []
|
||||
const maxChunkLength = 16383 // must be multiple of 3
|
||||
|
||||
// go through the array every three bytes, we'll deal with trailing stuff later
|
||||
for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
|
||||
parts.push(encodeChunk(
|
||||
uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)
|
||||
))
|
||||
for (let i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
|
||||
parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))
|
||||
}
|
||||
|
||||
// pad the end with zeros, but make sure to not forget the extra bytes
|
||||
|
|
@ -93364,8 +93362,8 @@ var __WEBPACK_AMD_DEFINE_RESULT__;;(function (globalObject) {
|
|||
var base64 = __webpack_require__(/*! base64-js */ "./node_modules/base64-js/index.js")
|
||||
var ieee754 = __webpack_require__(/*! ieee754 */ "./node_modules/ieee754/index.js")
|
||||
var customInspectSymbol =
|
||||
(typeof Symbol === 'function' && typeof Symbol.for === 'function')
|
||||
? Symbol.for('nodejs.util.inspect.custom')
|
||||
(typeof Symbol === 'function' && typeof Symbol['for'] === 'function') // eslint-disable-line dot-notation
|
||||
? Symbol['for']('nodejs.util.inspect.custom') // eslint-disable-line dot-notation
|
||||
: null
|
||||
|
||||
exports.Buffer = Buffer
|
||||
|
|
@ -93469,7 +93467,7 @@ function from (value, encodingOrOffset, length) {
|
|||
}
|
||||
|
||||
if (ArrayBuffer.isView(value)) {
|
||||
return fromArrayLike(value)
|
||||
return fromArrayView(value)
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
|
|
@ -93550,7 +93548,7 @@ function alloc (size, fill, encoding) {
|
|||
if (fill !== undefined) {
|
||||
// Only pay attention to encoding if it's a string. This
|
||||
// prevents accidentally sending in a number that would
|
||||
// be interpretted as a start offset.
|
||||
// be interpreted as a start offset.
|
||||
return typeof encoding === 'string'
|
||||
? createBuffer(size).fill(fill, encoding)
|
||||
: createBuffer(size).fill(fill)
|
||||
|
|
@ -93617,6 +93615,14 @@ function fromArrayLike (array) {
|
|||
return buf
|
||||
}
|
||||
|
||||
function fromArrayView (arrayView) {
|
||||
if (isInstance(arrayView, Uint8Array)) {
|
||||
var copy = new Uint8Array(arrayView)
|
||||
return fromArrayBuffer(copy.buffer, copy.byteOffset, copy.byteLength)
|
||||
}
|
||||
return fromArrayLike(arrayView)
|
||||
}
|
||||
|
||||
function fromArrayBuffer (array, byteOffset, length) {
|
||||
if (byteOffset < 0 || array.byteLength < byteOffset) {
|
||||
throw new RangeError('"offset" is outside of buffer bounds')
|
||||
|
|
@ -93756,12 +93762,20 @@ Buffer.concat = function concat (list, length) {
|
|||
for (i = 0; i < list.length; ++i) {
|
||||
var buf = list[i]
|
||||
if (isInstance(buf, Uint8Array)) {
|
||||
buf = Buffer.from(buf)
|
||||
}
|
||||
if (!Buffer.isBuffer(buf)) {
|
||||
if (pos + buf.length > buffer.length) {
|
||||
Buffer.from(buf).copy(buffer, pos)
|
||||
} else {
|
||||
Uint8Array.prototype.set.call(
|
||||
buffer,
|
||||
buf,
|
||||
pos
|
||||
)
|
||||
}
|
||||
} else if (!Buffer.isBuffer(buf)) {
|
||||
throw new TypeError('"list" argument must be an Array of Buffers')
|
||||
} else {
|
||||
buf.copy(buffer, pos)
|
||||
}
|
||||
buf.copy(buffer, pos)
|
||||
pos += buf.length
|
||||
}
|
||||
return buffer
|
||||
|
|
@ -93843,7 +93857,7 @@ function slowToString (encoding, start, end) {
|
|||
return ''
|
||||
}
|
||||
|
||||
// Force coersion to uint32. This will also coerce falsey/NaN values to 0.
|
||||
// Force coercion to uint32. This will also coerce falsey/NaN values to 0.
|
||||
end >>>= 0
|
||||
start >>>= 0
|
||||
|
||||
|
|
@ -94194,10 +94208,6 @@ function asciiWrite (buf, string, offset, length) {
|
|||
return blitBuffer(asciiToBytes(string), buf, offset, length)
|
||||
}
|
||||
|
||||
function latin1Write (buf, string, offset, length) {
|
||||
return asciiWrite(buf, string, offset, length)
|
||||
}
|
||||
|
||||
function base64Write (buf, string, offset, length) {
|
||||
return blitBuffer(base64ToBytes(string), buf, offset, length)
|
||||
}
|
||||
|
|
@ -94253,11 +94263,9 @@ Buffer.prototype.write = function write (string, offset, length, encoding) {
|
|||
return utf8Write(this, string, offset, length)
|
||||
|
||||
case 'ascii':
|
||||
return asciiWrite(this, string, offset, length)
|
||||
|
||||
case 'latin1':
|
||||
case 'binary':
|
||||
return latin1Write(this, string, offset, length)
|
||||
return asciiWrite(this, string, offset, length)
|
||||
|
||||
case 'base64':
|
||||
// Warning: maxLength not taken into account in base64Write
|
||||
|
|
@ -94300,10 +94308,13 @@ function utf8Slice (buf, start, end) {
|
|||
while (i < end) {
|
||||
var firstByte = buf[i]
|
||||
var codePoint = null
|
||||
var bytesPerSequence = (firstByte > 0xEF) ? 4
|
||||
: (firstByte > 0xDF) ? 3
|
||||
: (firstByte > 0xBF) ? 2
|
||||
: 1
|
||||
var bytesPerSequence = (firstByte > 0xEF)
|
||||
? 4
|
||||
: (firstByte > 0xDF)
|
||||
? 3
|
||||
: (firstByte > 0xBF)
|
||||
? 2
|
||||
: 1
|
||||
|
||||
if (i + bytesPerSequence <= end) {
|
||||
var secondByte, thirdByte, fourthByte, tempCodePoint
|
||||
|
|
@ -94424,7 +94435,8 @@ function hexSlice (buf, start, end) {
|
|||
function utf16leSlice (buf, start, end) {
|
||||
var bytes = buf.slice(start, end)
|
||||
var res = ''
|
||||
for (var i = 0; i < bytes.length; i += 2) {
|
||||
// If bytes.length is odd, the last 8 bits must be ignored (same as node.js)
|
||||
for (var i = 0; i < bytes.length - 1; i += 2) {
|
||||
res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256))
|
||||
}
|
||||
return res
|
||||
|
|
@ -94466,6 +94478,7 @@ function checkOffset (offset, ext, length) {
|
|||
if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
|
||||
}
|
||||
|
||||
Buffer.prototype.readUintLE =
|
||||
Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
|
||||
offset = offset >>> 0
|
||||
byteLength = byteLength >>> 0
|
||||
|
|
@ -94481,6 +94494,7 @@ Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert)
|
|||
return val
|
||||
}
|
||||
|
||||
Buffer.prototype.readUintBE =
|
||||
Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
|
||||
offset = offset >>> 0
|
||||
byteLength = byteLength >>> 0
|
||||
|
|
@ -94497,24 +94511,28 @@ Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert)
|
|||
return val
|
||||
}
|
||||
|
||||
Buffer.prototype.readUint8 =
|
||||
Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
|
||||
offset = offset >>> 0
|
||||
if (!noAssert) checkOffset(offset, 1, this.length)
|
||||
return this[offset]
|
||||
}
|
||||
|
||||
Buffer.prototype.readUint16LE =
|
||||
Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
|
||||
offset = offset >>> 0
|
||||
if (!noAssert) checkOffset(offset, 2, this.length)
|
||||
return this[offset] | (this[offset + 1] << 8)
|
||||
}
|
||||
|
||||
Buffer.prototype.readUint16BE =
|
||||
Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
|
||||
offset = offset >>> 0
|
||||
if (!noAssert) checkOffset(offset, 2, this.length)
|
||||
return (this[offset] << 8) | this[offset + 1]
|
||||
}
|
||||
|
||||
Buffer.prototype.readUint32LE =
|
||||
Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
|
||||
offset = offset >>> 0
|
||||
if (!noAssert) checkOffset(offset, 4, this.length)
|
||||
|
|
@ -94525,6 +94543,7 @@ Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
|
|||
(this[offset + 3] * 0x1000000)
|
||||
}
|
||||
|
||||
Buffer.prototype.readUint32BE =
|
||||
Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
|
||||
offset = offset >>> 0
|
||||
if (!noAssert) checkOffset(offset, 4, this.length)
|
||||
|
|
@ -94642,6 +94661,7 @@ function checkInt (buf, value, offset, ext, max, min) {
|
|||
if (offset + ext > buf.length) throw new RangeError('Index out of range')
|
||||
}
|
||||
|
||||
Buffer.prototype.writeUintLE =
|
||||
Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
|
||||
value = +value
|
||||
offset = offset >>> 0
|
||||
|
|
@ -94661,6 +94681,7 @@ Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength,
|
|||
return offset + byteLength
|
||||
}
|
||||
|
||||
Buffer.prototype.writeUintBE =
|
||||
Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
|
||||
value = +value
|
||||
offset = offset >>> 0
|
||||
|
|
@ -94680,6 +94701,7 @@ Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength,
|
|||
return offset + byteLength
|
||||
}
|
||||
|
||||
Buffer.prototype.writeUint8 =
|
||||
Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
|
||||
value = +value
|
||||
offset = offset >>> 0
|
||||
|
|
@ -94688,6 +94710,7 @@ Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
|
|||
return offset + 1
|
||||
}
|
||||
|
||||
Buffer.prototype.writeUint16LE =
|
||||
Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
|
||||
value = +value
|
||||
offset = offset >>> 0
|
||||
|
|
@ -94697,6 +94720,7 @@ Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert
|
|||
return offset + 2
|
||||
}
|
||||
|
||||
Buffer.prototype.writeUint16BE =
|
||||
Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
|
||||
value = +value
|
||||
offset = offset >>> 0
|
||||
|
|
@ -94706,6 +94730,7 @@ Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert
|
|||
return offset + 2
|
||||
}
|
||||
|
||||
Buffer.prototype.writeUint32LE =
|
||||
Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
|
||||
value = +value
|
||||
offset = offset >>> 0
|
||||
|
|
@ -94717,6 +94742,7 @@ Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert
|
|||
return offset + 4
|
||||
}
|
||||
|
||||
Buffer.prototype.writeUint32BE =
|
||||
Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
|
||||
value = +value
|
||||
offset = offset >>> 0
|
||||
|
|
@ -94896,11 +94922,6 @@ Buffer.prototype.copy = function copy (target, targetStart, start, end) {
|
|||
if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') {
|
||||
// Use built-in when available, missing from IE11
|
||||
this.copyWithin(targetStart, start, end)
|
||||
} else if (this === target && start < targetStart && targetStart < end) {
|
||||
// descending copy from end
|
||||
for (var i = len - 1; i >= 0; --i) {
|
||||
target[i + targetStart] = this[i + start]
|
||||
}
|
||||
} else {
|
||||
Uint8Array.prototype.set.call(
|
||||
target,
|
||||
|
|
@ -98143,6 +98164,7 @@ var NotIdle = /** @class */ (function (_super) {
|
|||
/*! no static exports found */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
||||
exports.read = function (buffer, offset, isLE, mLen, nBytes) {
|
||||
var e, m
|
||||
var eLen = (nBytes * 8) - mLen - 1
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@ import {Transaction} from './transaction.model';
|
|||
import {BigNumber} from 'bignumber.js';
|
||||
|
||||
export class Wallet {
|
||||
stop_paginate: boolean;
|
||||
open_from_exist: boolean;
|
||||
updated = false;
|
||||
wallet_id: number;
|
||||
name: string;
|
||||
pass: string;
|
||||
|
|
|
|||
|
|
@ -198,6 +198,7 @@ export class BackendService {
|
|||
};
|
||||
}
|
||||
|
||||
const core_busy = Result.error_code === 'CORE_BUSY';
|
||||
const Status = (Result.error_code === 'OK' || Result.error_code === 'TRUE');
|
||||
|
||||
if (!Status && Status !== undefined && Result.error_code !== undefined) {
|
||||
|
|
@ -207,24 +208,44 @@ export class BackendService {
|
|||
|
||||
let res_error_code = false;
|
||||
if (typeof Result === 'object' && 'error_code' in Result && Result.error_code !== 'OK' && Result.error_code !== 'TRUE' && Result.error_code !== 'FALSE') {
|
||||
this.informerRun(Result.error_code, params, command);
|
||||
res_error_code = Result.error_code;
|
||||
if (core_busy) {
|
||||
setTimeout( () => {
|
||||
// this is will avoid update data when user
|
||||
// on other wallet after CORE_BUSY (blink of data)
|
||||
if (command !== 'get_recent_transfers') {
|
||||
this.runCommand(command, params, callback);
|
||||
} else {
|
||||
const current_wallet_id = this.variablesService.currentWallet.wallet_id;
|
||||
if (current_wallet_id === params.wallet_id) {
|
||||
this.runCommand(command, params, callback);
|
||||
}
|
||||
}
|
||||
}, 50);
|
||||
} else {
|
||||
this.informerRun(Result.error_code, params, command);
|
||||
res_error_code = Result.error_code;
|
||||
}
|
||||
}
|
||||
|
||||
// if ( command === 'get_offers_ex' ){
|
||||
// Service.printLog( "get_offers_ex offers count "+((data.offers)?data.offers.length:0) );
|
||||
// }
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback(Status, data, res_error_code);
|
||||
} else {
|
||||
return data;
|
||||
if (!core_busy) {
|
||||
if (typeof callback === 'function') {
|
||||
callback(Status, data, res_error_code);
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private runCommand(command, params?, callback?) {
|
||||
if (this.backendObject) {
|
||||
if (command === 'get_recent_transfers') {
|
||||
this.variablesService.get_recent_transfers = true;
|
||||
}
|
||||
const Action = this.backendObject[command];
|
||||
if (!Action) {
|
||||
BackendService.Debug(0, 'Run Command Error! Command "' + command + '" don\'t found in backendObject');
|
||||
|
|
@ -232,6 +253,9 @@ export class BackendService {
|
|||
const that = this;
|
||||
params = (typeof params === 'string') ? params : JSONBigNumber.stringify(params);
|
||||
if (params === undefined || params === '{}') {
|
||||
if (command === 'get_recent_transfers') {
|
||||
this.variablesService.get_recent_transfers = false;
|
||||
}
|
||||
Action(function (resultStr) {
|
||||
that.commandDebug(command, params, resultStr);
|
||||
return that.backendCallback(resultStr, params, callback, command);
|
||||
|
|
@ -632,14 +656,14 @@ export class BackendService {
|
|||
}
|
||||
}
|
||||
|
||||
getRecentTransfers( id, offset, count,exclude_mining_txs, callback) {
|
||||
getRecentTransfers( id, offset, count, exclude_mining_txs, callback) {
|
||||
const params = {
|
||||
wallet_id: id,
|
||||
offset: offset,
|
||||
count: count,
|
||||
exclude_mining_txs: exclude_mining_txs
|
||||
};
|
||||
this.runCommand('get_recent_transfers', params, callback);
|
||||
this.runCommand('get_recent_transfers', params, callback);
|
||||
}
|
||||
|
||||
getPoolInfo(callback) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { Injectable, NgZone } from '@angular/core';
|
|||
import { VariablesService } from './variables.service';
|
||||
import { PaginationStore } from './pagination.store';
|
||||
import * as _ from 'lodash';
|
||||
import {Store} from 'store';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
|
|
@ -11,17 +12,15 @@ export class PaginationService {
|
|||
constructor(
|
||||
private variables: VariablesService,
|
||||
private ngZone: NgZone,
|
||||
private paginationStore: PaginationStore
|
||||
private paginationStore: PaginationStore,
|
||||
) { }
|
||||
|
||||
paginate(currentPage = 1) {
|
||||
|
||||
if (currentPage < 1) {
|
||||
currentPage = 1;
|
||||
} else if (currentPage > this.variables.currentWallet.totalPages) {
|
||||
currentPage = this.variables.currentWallet.totalPages;
|
||||
}
|
||||
|
||||
let startPage: number, endPage: number;
|
||||
if (this.variables.currentWallet.totalPages <= this.variables.maxPages) {
|
||||
startPage = 1;
|
||||
|
|
@ -48,12 +47,13 @@ export class PaginationService {
|
|||
});
|
||||
}
|
||||
|
||||
getOffset() {
|
||||
getOffset(walletID) {
|
||||
const mining = this.variables.currentWallet.exclude_mining_txs;
|
||||
const currentPage = (this.variables.currentWallet.currentPage);
|
||||
let offset = (currentPage * this.variables.count);
|
||||
let offset = ((currentPage - 1) * this.variables.count);
|
||||
if (!mining) { return offset; }
|
||||
const pages = this.paginationStore.value;
|
||||
const value = this.paginationStore.value;
|
||||
const pages = value.filter(item => item.walletID === walletID);
|
||||
if (pages && pages.length) {
|
||||
const max = _.maxBy(pages, 'page');
|
||||
const isForward = this.paginationStore.isForward(pages, currentPage);
|
||||
|
|
@ -66,4 +66,37 @@ export class PaginationService {
|
|||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
calcPages(data) {
|
||||
if (data.total_history_items && (data && data.history)) {
|
||||
this.variables.currentWallet.totalPages = Math.ceil( data.total_history_items / this.variables.count);
|
||||
this.variables.currentWallet.totalPages > this.variables.maxPages
|
||||
? this.variables.currentWallet.pages = new Array(5).fill(1).map((value, index) => value + index)
|
||||
: this.variables.currentWallet.pages =
|
||||
new Array(this.variables.currentWallet.totalPages).fill(1).map((value, index) => value + index);
|
||||
} else if (this.variables.currentWallet.restore) {
|
||||
this.variables.currentWallet.totalPages = Math.ceil( data.history.length / this.variables.count);
|
||||
this.variables.currentWallet.totalPages > this.variables.maxPages
|
||||
? this.variables.currentWallet.pages = new Array(5).fill(1).map((value, index) => value + index)
|
||||
: this.variables.currentWallet.pages =
|
||||
new Array(this.variables.currentWallet.totalPages).fill(1).map((value, index) => value + index);
|
||||
}
|
||||
}
|
||||
|
||||
prepareHistory(data, status) {
|
||||
if (status && (data && data.total_history_items)) {
|
||||
this.variables.currentWallet.history.splice(0, this.variables.currentWallet.history.length);
|
||||
this.ngZone.run(() => {
|
||||
this.paginate(this.variables.currentWallet.currentPage);
|
||||
if (data.history.length !== 0) {
|
||||
this.variables.currentWallet.restore = false;
|
||||
this.variables.currentWallet.total_history_item = data.total_history_items;
|
||||
this.variables.currentWallet.prepareHistory(data.history);
|
||||
if (this.variables.currentWallet.currentPage === 1 && data.unconfirmed) {
|
||||
this.variables.currentWallet.prepareHistory(data.unconfirmed);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,17 @@
|
|||
import {Injectable} from '@angular/core';
|
||||
import {Observable, BehaviorSubject} from 'rxjs';
|
||||
import {VariablesService} from './variables.service';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
export interface Pages {
|
||||
page: number;
|
||||
page: number;
|
||||
offset: number;
|
||||
walletID: number;
|
||||
}
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class PaginationStore {
|
||||
constructor(
|
||||
private variablesService: VariablesService
|
||||
) {
|
||||
}
|
||||
) {}
|
||||
private subject = new BehaviorSubject<Pages[]>(null);
|
||||
pages$: Observable<Pages[]> = this.subject.asObservable();
|
||||
|
||||
|
|
@ -22,15 +19,13 @@ export class PaginationStore {
|
|||
const max = _.maxBy(pages, 'page');
|
||||
return !max || max.page < currentPage || max.page === currentPage;
|
||||
}
|
||||
setPage(pageNumber: number, offset: number) {
|
||||
const pages = this.subject.getValue();
|
||||
const current = (this.variablesService.currentWallet.currentPage);
|
||||
const isForward = this.isForward(pages, current);
|
||||
setPage(pageNumber: number, offset: number, walletID: number) {
|
||||
let newPages: Pages[] = [];
|
||||
const pages = this.subject.getValue();
|
||||
if (pages && pages.length) {
|
||||
newPages = pages.slice(0);
|
||||
}
|
||||
isForward ? newPages.push({page: pageNumber, offset}) : newPages.pop();
|
||||
newPages.push({page: pageNumber, offset, walletID});
|
||||
this.subject.next(newPages);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@ import {BigNumber} from 'bignumber.js';
|
|||
providedIn: 'root'
|
||||
})
|
||||
export class VariablesService {
|
||||
|
||||
public request_on_in = {};
|
||||
public stop_paginate = {};
|
||||
public sync_started = false;
|
||||
public digits = 12;
|
||||
public appPass = '';
|
||||
public appLogin = false;
|
||||
|
|
@ -36,6 +38,7 @@ export class VariablesService {
|
|||
progress_value: 0,
|
||||
progress_value_text: '0'
|
||||
};
|
||||
public get_recent_transfers = false; // avoid of execute function before collback complete
|
||||
public default_fee = '0.010000000000';
|
||||
public default_fee_big = new BigNumber('10000000000');
|
||||
|
||||
|
|
@ -71,7 +74,7 @@ export class VariablesService {
|
|||
public newContact: Contact = {name: null, address: null, notes: null};
|
||||
|
||||
public pattern = '^[a-zA-Z0-9_.\\\]\*\|\~\!\?\@\#\$\%\^\&\+\{\}\(\)\<\>\:\;\"\'\-\=\/\,\[\\\\]*$';
|
||||
|
||||
public after_sync_request: any = {};
|
||||
getExpMedTsEvent = new BehaviorSubject(null);
|
||||
getHeightAppEvent = new BehaviorSubject(null);
|
||||
getHeightMaxEvent = new BehaviorSubject(null);
|
||||
|
|
@ -162,6 +165,15 @@ export class VariablesService {
|
|||
return null;
|
||||
}
|
||||
|
||||
getNotLoadedWallet() {
|
||||
for (let i = 0; i < this.wallets.length; i++) {
|
||||
if (!this.wallets[i].loaded) {
|
||||
return this.wallets[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
startCountdown() {
|
||||
this.idle.within(this.settings.appLockTime).start();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {IntToMoneyPipe} from './_helpers/pipes/int-to-money.pipe';
|
|||
import {BigNumber} from 'bignumber.js';
|
||||
import {ModalService} from './_helpers/services/modal.service';
|
||||
import {UtilsService} from './_helpers/services/utils.service';
|
||||
import {Store} from 'store';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
|
|
@ -40,7 +41,8 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||
private ngZone: NgZone,
|
||||
private intToMoneyPipe: IntToMoneyPipe,
|
||||
private modalService: ModalService,
|
||||
private utilsService: UtilsService
|
||||
private utilsService: UtilsService,
|
||||
private store: Store
|
||||
) {
|
||||
translate.addLangs(['en', 'fr', 'de', 'it', 'pt']);
|
||||
translate.setDefaultLang('en');
|
||||
|
|
@ -129,7 +131,6 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||
const wallet_state = data.wallet_state;
|
||||
const is_mining = data.is_mining;
|
||||
const wallet = this.variablesService.getWallet(data.wallet_id);
|
||||
|
||||
// 1-synch, 2-ready, 3 - error
|
||||
if (wallet) {
|
||||
this.ngZone.run(() => {
|
||||
|
|
@ -157,21 +158,15 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||
if (wallet) {
|
||||
this.ngZone.run(() => {
|
||||
wallet.progress = (data.progress < 0) ? 0 : ((data.progress > 100) ? 100 : data.progress);
|
||||
if (!this.variablesService.sync_started) {
|
||||
this.variablesService.sync_started = true;
|
||||
}
|
||||
this.addToStore(wallet, true); // subscribe on data
|
||||
if (wallet.progress === 0) {
|
||||
wallet.loaded = false;
|
||||
} else if (wallet.progress === 100) {
|
||||
wallet.loaded = true;
|
||||
if (wallet.total_history_item) {
|
||||
wallet.totalPages = Math.ceil( wallet.total_history_item / this.variablesService.count);
|
||||
wallet.totalPages > this.variablesService.maxPages
|
||||
? wallet.pages = new Array(5).fill(1).map((value, index) => value + index)
|
||||
: wallet.pages = new Array(wallet.totalPages).fill(1).map((value, index) => value + index);
|
||||
} else if (wallet.restore) {
|
||||
wallet.totalPages = Math.ceil( wallet.history.length / this.variablesService.count);
|
||||
wallet.totalPages > this.variablesService.maxPages
|
||||
? wallet.pages = new Array(5).fill(1).map((value, index) => value + index)
|
||||
: wallet.pages = new Array(wallet.totalPages).fill(1).map((value, index) => value + index);
|
||||
}
|
||||
this.addToStore(wallet, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -722,6 +717,28 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
}
|
||||
|
||||
addToStore(wallet, boolean) {
|
||||
const value = this.store.value.sync;
|
||||
if (value && value.length) {
|
||||
const sync = value.filter(item => item.wallet_id === wallet.wallet_id);
|
||||
if (sync && sync.length) {
|
||||
const result = value.map(item => {
|
||||
if (item.wallet_id === wallet.wallet_id) {
|
||||
return {sync: boolean, wallet_id: wallet.wallet_id};
|
||||
} else {
|
||||
return item;
|
||||
}
|
||||
});
|
||||
this.store.set('sync', result);
|
||||
} else {
|
||||
value.push({sync: boolean, wallet_id: wallet.wallet_id});
|
||||
this.store.set('sync', value);
|
||||
}
|
||||
} else {
|
||||
this.store.set('sync', [{sync: boolean, wallet_id: wallet.wallet_id}]);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.intervalUpdateContractsState) {
|
||||
clearInterval(this.intervalUpdateContractsState);
|
||||
|
|
|
|||
|
|
@ -37,6 +37,11 @@ import { BackendService } from './_helpers/services/backend.service';
|
|||
import { ModalService } from './_helpers/services/modal.service';
|
||||
import { PaginationStore } from './_helpers/services/pagination.store';
|
||||
// SERVICES
|
||||
|
||||
// Feature module
|
||||
import { Store } from 'store';
|
||||
// Feature module
|
||||
|
||||
import { MoneyToIntPipe } from './_helpers/pipes/money-to-int.pipe';
|
||||
import { IntToMoneyPipe } from './_helpers/pipes/int-to-money.pipe';
|
||||
import { HistoryTypeMessagesPipe } from './_helpers/pipes/history-type-messages.pipe';
|
||||
|
|
@ -146,6 +151,7 @@ export function highchartsFactory() {
|
|||
ContextMenuModule.forRoot()
|
||||
],
|
||||
providers: [
|
||||
Store,
|
||||
BackendService,
|
||||
ModalService,
|
||||
PaginationStore,
|
||||
|
|
|
|||
|
|
@ -64,9 +64,16 @@
|
|||
}
|
||||
|
||||
&.send {
|
||||
|
||||
.status-transaction {
|
||||
mask: url(../../assets/icons/send.svg) no-repeat center;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.status-transaction::after {
|
||||
display: block;
|
||||
content:'';
|
||||
background:url("../../assets/icons/send-red.svg") no-repeat center;
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -125,10 +125,12 @@ export class OpenWalletModalComponent implements OnInit {
|
|||
}
|
||||
|
||||
skipWallet() {
|
||||
if (this.wallets.length) {
|
||||
this.wallets.splice(0, 1);
|
||||
this.ngOnInit();
|
||||
}
|
||||
this.ngZone.run(() => {
|
||||
if (this.wallets.length) {
|
||||
this.wallets.splice(0, 1);
|
||||
this.ngOnInit();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ export class OpenWalletComponent implements OnInit, OnDestroy {
|
|||
);
|
||||
new_wallet.alias = this.backend.getWalletAlias(new_wallet.address);
|
||||
new_wallet.currentPage = 1;
|
||||
new_wallet.open_from_exist = true;
|
||||
new_wallet.exclude_mining_txs = false;
|
||||
new_wallet.is_auditable = open_data['wi'].is_auditable;
|
||||
new_wallet.is_watch_only = open_data['wi'].is_watch_only;
|
||||
|
|
|
|||
|
|
@ -121,6 +121,8 @@ export class RestoreWalletComponent implements OnInit {
|
|||
}
|
||||
|
||||
runWallet() {
|
||||
// add flag when wallet was restored form seed
|
||||
this.variablesService.after_sync_request[this.wallet.id] = true;
|
||||
let exists = false;
|
||||
this.variablesService.wallets.forEach((wallet) => {
|
||||
if (wallet.address === this.variablesService.opening_wallet.address) {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<h3>{{ 'SIDEBAR.TITLE' | translate }}</h3><button (click)="goMainPage()">{{ 'SIDEBAR.ADD_NEW' | translate }}</button>
|
||||
</div>
|
||||
<div class="sidebar-accounts-list scrolled-content">
|
||||
<div class="sidebar-account" *ngFor="let wallet of variablesService.wallets" [class.active]="wallet?.wallet_id === walletActive" [routerLink]="['/wallet/' + wallet.wallet_id + '/history']">
|
||||
<div class="sidebar-account" *ngFor="let wallet of variablesService.wallets" [class.active]="wallet?.wallet_id === walletActive" [routerLink]="['/wallet/' + wallet.wallet_id + '/history']" [queryParams]="{sidenav: true}">
|
||||
<div class="wallet-type" (click)="goToAuditableWalletHelpPage($event)">
|
||||
<div class="content auditable" *ngIf="wallet.is_auditable && !wallet.is_watch_only">
|
||||
Auditable
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@
|
|||
flex-direction: column;
|
||||
flex: 1 1 auto;
|
||||
margin: 0 -3rem;
|
||||
overflow-y: overlay;
|
||||
overflow-y: auto;
|
||||
|
||||
.sidebar-account {
|
||||
position: relative;
|
||||
|
|
@ -112,15 +112,20 @@
|
|||
.icon {
|
||||
width: 1.3rem;
|
||||
height: 1.3rem;
|
||||
|
||||
&.close-wallet {
|
||||
mask: url(../../assets/icons/close-wallet.svg) no-repeat center;
|
||||
background-color: transparent;
|
||||
}
|
||||
&.close-wallet::after {
|
||||
display: block;
|
||||
content:'';
|
||||
background:url("../../assets/icons/close-wallet-blue.svg") no-repeat center;
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.sidebar-account-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
|
|||
|
|
@ -51,20 +51,39 @@
|
|||
<div *ngIf="activeTab === 'history'" class="pagination-wrapper">
|
||||
<div class="pagination">
|
||||
<div>
|
||||
<button [disabled]="variablesService.currentWallet.currentPage === 1" (click)="setPage(variablesService.currentWallet.currentPage - 1)"><</button>
|
||||
<button
|
||||
[ngClass]="{'disabled': sync_started || wallet}"
|
||||
[disabled]="variablesService.currentWallet.currentPage === 1 || sync_started || wallet"
|
||||
(click)="setPage(variablesService.currentWallet.currentPage - 1)">
|
||||
<
|
||||
</button>
|
||||
|
||||
<ng-container *ngIf="!mining">
|
||||
<button *ngFor="let page of variablesService.currentWallet.pages" [ngClass]="{ 'active': variablesService.currentWallet.currentPage === page }"
|
||||
<button [disabled]="sync_started || wallet"
|
||||
*ngFor="let page of variablesService.currentWallet.pages"
|
||||
[ngClass]="{ 'active': variablesService.currentWallet.currentPage === page,'disabled': sync_started || wallet }"
|
||||
(click)="setPage(page)">{{page}}</button>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="mining">
|
||||
<button [ngClass]="{ 'active': variablesService.currentWallet.currentPage }"
|
||||
(click)="setPage(variablesService.currentWallet.currentPage)">{{variablesService.currentWallet.currentPage}}</button>
|
||||
<button [ngClass]="{ 'active': variablesService.currentWallet.currentPage, 'disabled': sync_started || wallet}"
|
||||
[disabled]="stop_paginate || sync_started || wallet"
|
||||
(click)="setPage(variablesService.currentWallet.currentPage)">
|
||||
{{variablesService.currentWallet.currentPage}}
|
||||
</button>
|
||||
</ng-container>
|
||||
<button [disabled]="variablesService.currentWallet.currentPage === variablesService.currentWallet.totalPages" (click)="setPage(variablesService.currentWallet.currentPage + 1)">></button>
|
||||
|
||||
<button
|
||||
[disabled]="stop_paginate || sync_started || wallet"
|
||||
[ngClass]="{'disabled': sync_started || wallet}"
|
||||
(click)="setPage(variablesService.currentWallet.currentPage + 1)">
|
||||
>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
<div class="mining-transaction-switch">
|
||||
<span class="switch-text">Hide mining transactions</span>
|
||||
<div class="switch" (click)="toggleMiningTransactions(); $event.stopPropagation()">
|
||||
<div class="switch" [ngClass]="{'disabled': sync_started || wallet}" (click)="toggleMiningTransactions(); $event.stopPropagation()">
|
||||
<span class="option" *ngIf="mining">{{ 'STAKING.SWITCH.ON' | translate }}</span>
|
||||
<span class="circle" [class.on]="mining" [class.off]="!mining"></span>
|
||||
<span class="option" *ngIf="!mining">{{ 'STAKING.SWITCH.OFF' | translate }}</span>
|
||||
|
|
|
|||
|
|
@ -254,6 +254,14 @@
|
|||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
font-size: 1.2rem;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
.disabled {
|
||||
background-color: #18202a;
|
||||
color: #e0e0e0;
|
||||
opacity: 0.3;
|
||||
cursor: default;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,12 +4,15 @@ import { VariablesService } from '../_helpers/services/variables.service';
|
|||
import { BackendService } from '../_helpers/services/backend.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { IntToMoneyPipe } from '../_helpers/pipes/int-to-money.pipe';
|
||||
import { Subscription } from 'rxjs';
|
||||
import {Subscription} from 'rxjs';
|
||||
import { LOCKED_BALANCE_HELP_PAGE } from '../_shared/constants';
|
||||
|
||||
import icons from '../../assets/icons/icons.json';
|
||||
import { PaginationService } from '../_helpers/services/pagination.service';
|
||||
import { PaginationStore } from '../_helpers/services/pagination.store';
|
||||
import {PaginationService} from '../_helpers/services/pagination.service';
|
||||
import {PaginationStore} from '../_helpers/services/pagination.store';
|
||||
import {Store, Sync} from 'store';
|
||||
import {Wallet} from '../_helpers/models/wallet.model';
|
||||
import {distinctUntilChanged, filter} from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'app-wallet',
|
||||
|
|
@ -25,9 +28,11 @@ export class WalletComponent implements OnInit, OnDestroy {
|
|||
copyAnimationTimeout;
|
||||
balanceTooltip;
|
||||
activeTab = 'history';
|
||||
public mining:boolean = false;
|
||||
|
||||
public mining = false;
|
||||
public currentPage = 1;
|
||||
wallet: Wallet;
|
||||
sync_started = false;
|
||||
stop_paginate = false;
|
||||
|
||||
@ViewChild('scrolledContent') private scrolledContent: ElementRef;
|
||||
|
||||
|
|
@ -88,6 +93,7 @@ export class WalletComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
];
|
||||
aliasSubscription: Subscription;
|
||||
walletsSubscription: Subscription;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
|
|
@ -98,21 +104,81 @@ export class WalletComponent implements OnInit, OnDestroy {
|
|||
private translate: TranslateService,
|
||||
private intToMoneyPipe: IntToMoneyPipe,
|
||||
private pagination: PaginationService,
|
||||
private paginationStore: PaginationStore
|
||||
private paginationStore: PaginationStore,
|
||||
private store: Store,
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.subRouting1 = this.route.params.subscribe(params => {
|
||||
// set current wallet only by user click to avoid after sync show synchronized data
|
||||
this.walletID = +params['id'];
|
||||
this.variablesService.setCurrentWallet(this.walletID);
|
||||
this.walletsSubscription = this.store.select('sync').pipe(
|
||||
filter(Boolean),
|
||||
distinctUntilChanged(),
|
||||
).subscribe(value => {
|
||||
const data = value.filter((item: Sync) => item.wallet_id === this.walletID)[0];
|
||||
if (data && !data.sync) {
|
||||
let in_progress;
|
||||
const values = this.store.value.sync;
|
||||
if (values && values.length) {
|
||||
in_progress = values.filter(item => item.sync);
|
||||
this.variablesService.sync_started = !!(in_progress && in_progress.length);
|
||||
if (!in_progress) {
|
||||
this.variablesService.sync_started = false;
|
||||
}
|
||||
} else {
|
||||
this.variablesService.sync_started = false;
|
||||
}
|
||||
}
|
||||
let restore = false;
|
||||
if (this.variablesService.after_sync_request.hasOwnProperty(this.walletID)) {
|
||||
restore = this.variablesService.after_sync_request[this.walletID];
|
||||
}
|
||||
if (!this.variablesService.sync_started && restore && this.walletID === (data && data.wallet_id)) {
|
||||
this.wallet = this.variablesService.getNotLoadedWallet();
|
||||
if (this.wallet) {
|
||||
this.tick();
|
||||
}
|
||||
// if this is was restore wallet and it was selected on moment when sync completed
|
||||
this.getRecentTransfers();
|
||||
this.variablesService.after_sync_request[this.walletID] = false;
|
||||
}
|
||||
});
|
||||
let after_sync_request = false;
|
||||
if (this.variablesService.after_sync_request.hasOwnProperty(this.walletID)) {
|
||||
after_sync_request = this.variablesService.after_sync_request[this.walletID];
|
||||
}
|
||||
if (after_sync_request && !this.variablesService.sync_started) {
|
||||
// if user click on the wallet at the first time after restore.
|
||||
this.getRecentTransfers();
|
||||
}
|
||||
|
||||
if (this.variablesService.stop_paginate.hasOwnProperty(this.walletID)) {
|
||||
this.stop_paginate = this.variablesService.stop_paginate[this.walletID];
|
||||
} else {
|
||||
this.stop_paginate = false;
|
||||
}
|
||||
// this will hide pagination a bit earlier
|
||||
this.wallet = this.variablesService.getNotLoadedWallet();
|
||||
if (this.wallet) {
|
||||
this.tick();
|
||||
}
|
||||
|
||||
this.scrolledContent.nativeElement.scrollTop = 0;
|
||||
clearTimeout(this.copyAnimationTimeout);
|
||||
this.copyAnimation = false;
|
||||
this.mining = this.variablesService.currentWallet.exclude_mining_txs;
|
||||
|
||||
|
||||
if (this.variablesService.wallets.length === 1) {
|
||||
this.walletID = +params['id'];
|
||||
this.variablesService.setCurrentWallet(this.walletID);
|
||||
}
|
||||
});
|
||||
this.subRouting2 = this.router.events.subscribe(val => {
|
||||
if (val instanceof RoutesRecognized) {
|
||||
this.activeTab = val.urlAfterRedirects.split('/').pop();
|
||||
this.activeTab = val.urlAfterRedirects.replace('?sidenav=true', '').split('/').pop();
|
||||
if (val.state.root.firstChild && val.state.root.firstChild.firstChild) {
|
||||
for (let i = 0; i < this.tabs.length; i++) {
|
||||
this.tabs[i].active = (this.tabs[i].link === '/' + val.state.root.firstChild.firstChild.url[0].path);
|
||||
|
|
@ -138,10 +204,26 @@ export class WalletComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
});
|
||||
}
|
||||
resetPaginationValues() {
|
||||
this.ngZone.run(() => {
|
||||
const total_history_item = this.variablesService.currentWallet.total_history_item;
|
||||
const count = this.variablesService.count;
|
||||
this.variablesService.currentWallet.totalPages = Math.ceil( total_history_item / count);
|
||||
this.variablesService.currentWallet.exclude_mining_txs = this.mining;
|
||||
this.variablesService.currentWallet.currentPage = 1;
|
||||
|
||||
if (!this.variablesService.currentWallet.totalPages) {
|
||||
this.variablesService.currentWallet.totalPages = 1;
|
||||
}
|
||||
this.variablesService.currentWallet.totalPages > this.variablesService.maxPages
|
||||
? this.variablesService.currentWallet.pages = new Array(5).fill(1).map((value, index) => value + index)
|
||||
: this.variablesService.currentWallet.pages = new Array(this.variablesService.currentWallet.totalPages).fill(1).map((value, index) => value + index);
|
||||
})
|
||||
}
|
||||
|
||||
changeTab(index) {
|
||||
if (((this.tabs[index].link === '/send' || this.tabs[index].link === '/contracts' || this.tabs[index].link === '/staking') && (this.variablesService.daemon_state !== 2 || !this.variablesService.currentWallet.loaded))
|
||||
|| ((this.tabs[index].link === '/send' || this.tabs[index].link === '/contracts') && this.variablesService.currentWallet.is_watch_only && this.variablesService.currentWallet.is_auditable)) {
|
||||
|| ((this.tabs[index].link === '/send' || this.tabs[index].link === '/contracts') && this.variablesService.currentWallet.is_watch_only && this.variablesService.currentWallet.is_auditable)) {
|
||||
return;
|
||||
}
|
||||
this.tabs.forEach((tab) => {
|
||||
|
|
@ -195,49 +277,84 @@ export class WalletComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
public setPage(pageNumber: number) {
|
||||
// this is will allow pagination for wallets that was open from existed wallets'
|
||||
if (this.variablesService.currentWallet.open_from_exist && !this.variablesService.currentWallet.updated) {
|
||||
this.variablesService.get_recent_transfers = false;
|
||||
this.variablesService.currentWallet.updated = true;
|
||||
}
|
||||
if (pageNumber === this.variablesService.currentWallet.currentPage) {
|
||||
return;
|
||||
}
|
||||
this.variablesService.currentWallet.currentPage = pageNumber;
|
||||
this.getRecentTransfers();
|
||||
// if not running get_recent_transfers callback
|
||||
if (!this.variablesService.get_recent_transfers) {
|
||||
this.variablesService.currentWallet.currentPage = pageNumber;
|
||||
}
|
||||
if (!this.variablesService.get_recent_transfers) {
|
||||
this.getRecentTransfers();
|
||||
}
|
||||
}
|
||||
|
||||
toggleMiningTransactions() {
|
||||
this.mining = !this.mining;
|
||||
this.variablesService.currentWallet.exclude_mining_txs = this.mining;
|
||||
this.variablesService.currentWallet.currentPage = 1;
|
||||
this.getRecentTransfers();
|
||||
if (!this.variablesService.sync_started && !this.wallet) {
|
||||
const value = this.paginationStore.value;
|
||||
if (!value) {
|
||||
this.paginationStore.setPage(1, 0, this.walletID); // add back page for the first page
|
||||
} else {
|
||||
const pages = value.filter(item => item.walletID === this.walletID);
|
||||
if (!pages.length) {
|
||||
this.paginationStore.setPage(1, 0, this.walletID); // add back page for the first page
|
||||
}
|
||||
}
|
||||
this.mining = !this.mining;
|
||||
this.resetPaginationValues();
|
||||
this.getRecentTransfers();
|
||||
}
|
||||
}
|
||||
|
||||
tick() {
|
||||
const walletInterval = setInterval(() => {
|
||||
this.wallet = this.variablesService.getNotLoadedWallet();
|
||||
if (!this.wallet) {
|
||||
clearInterval(walletInterval);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
getRecentTransfers () {
|
||||
const offset = this.pagination.getOffset();
|
||||
const pages = this.paginationStore.value;
|
||||
if (!pages) {
|
||||
this.paginationStore.setPage(1, 40); // add back page for the first page
|
||||
}
|
||||
const offset = this.pagination.getOffset(this.walletID);
|
||||
const value = this.paginationStore.value;
|
||||
const pages = value ? value.filter(item => item.walletID === this.walletID) : [];
|
||||
|
||||
this.backend.getRecentTransfers(
|
||||
this.walletID,
|
||||
offset,
|
||||
this.variablesService.count, this.variablesService.currentWallet.exclude_mining_txs, (status, data) => {
|
||||
const page = (this.variablesService.currentWallet.currentPage + 1);
|
||||
this.paginationStore.setPage(page, data.last_item_index); // add back page for current page
|
||||
if (data.history.length < this.variablesService.count) {
|
||||
this.variablesService.currentWallet.totalPages = (page - 1); // stop paginate
|
||||
const isForward = this.paginationStore.isForward(pages, this.variablesService.currentWallet.currentPage);
|
||||
if (this.mining && isForward && pages && pages.length === 1) {
|
||||
this.variablesService.currentWallet.currentPage = 1; // set init page after navigation back
|
||||
}
|
||||
if (status && data.total_history_items) {
|
||||
this.variablesService.currentWallet.history.splice(0, this.variablesService.currentWallet.history.length);
|
||||
this.ngZone.run(() => {
|
||||
this.pagination.paginate(this.variablesService.currentWallet.currentPage);
|
||||
if (data.history.length !== 0) {
|
||||
this.variablesService.currentWallet.restore = false;
|
||||
this.variablesService.currentWallet.total_history_item = data.total_history_items;
|
||||
this.variablesService.currentWallet.prepareHistory(data.history);
|
||||
if (this.variablesService.currentWallet.currentPage === 1 && data.unconfirmed) {
|
||||
this.variablesService.currentWallet.prepareHistory(data.unconfirmed);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const history = (data && data.history);
|
||||
this.variablesService.stop_paginate[this.walletID] = history && history.length < this.variablesService.count || !history;
|
||||
this.stop_paginate = this.variablesService.stop_paginate[this.walletID];
|
||||
if (!this.variablesService.stop_paginate[this.walletID]) {
|
||||
const page = this.variablesService.currentWallet.currentPage + 1;
|
||||
if (isForward && this.mining && history && history.length === this.variablesService.count) {
|
||||
this.paginationStore.setPage(page, data.last_item_index, this.walletID); // add back page for current page
|
||||
}
|
||||
}
|
||||
|
||||
this.pagination.calcPages(data);
|
||||
this.pagination.prepareHistory(data, status);
|
||||
|
||||
this.ngZone.run(() => {
|
||||
this.variablesService.get_recent_transfers = false;
|
||||
if (this.variablesService.after_sync_request.hasOwnProperty(this.walletID)) {
|
||||
// this is will complete get_recent_transfers request
|
||||
// this will switch of
|
||||
this.variablesService.after_sync_request[this.walletID] = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -246,6 +363,9 @@ export class WalletComponent implements OnInit, OnDestroy {
|
|||
this.subRouting2.unsubscribe();
|
||||
this.queryRouting.unsubscribe();
|
||||
this.aliasSubscription.unsubscribe();
|
||||
if (this.walletsSubscription) {
|
||||
this.walletsSubscription.unsubscribe();
|
||||
}
|
||||
clearTimeout(this.copyAnimationTimeout);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 34 34" style="enable-background:new 0 0 34 34;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#4db1ff;}
|
||||
</style>
|
||||
<polygon class="st0" points="31.9,4.9 29.1,2.1 17,14.2 4.9,2.1 2.1,4.9 14.2,17 2.1,29.1 4.9,31.9 17,19.8 29.1,31.9 31.9,29.1
|
||||
19.8,17 "/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 549 B |
36
src/gui/qt-daemon/html_source/src/store.ts
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import { pluck, distinctUntilChanged } from 'rxjs/operators';
|
||||
import { Observable, BehaviorSubject } from 'rxjs';
|
||||
import { Wallet } from './app/_helpers/models/wallet.model';
|
||||
export interface Sync {
|
||||
sync: boolean;
|
||||
wallet_id: number;
|
||||
}
|
||||
|
||||
export interface State {
|
||||
wallets: Wallet[];
|
||||
sync: Sync[];
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
const state: State = {
|
||||
wallets: undefined,
|
||||
sync: undefined,
|
||||
};
|
||||
|
||||
export class Store {
|
||||
private subject = new BehaviorSubject<State>(state);
|
||||
private store = this.subject.asObservable().pipe(distinctUntilChanged());
|
||||
|
||||
get value() {
|
||||
return this.subject.value;
|
||||
}
|
||||
|
||||
select<T>(name: string): Observable<T> {
|
||||
return this.store.pipe(pluck(name));
|
||||
}
|
||||
|
||||
// tslint:disable-next-line:no-shadowed-variable
|
||||
set(name: string, state: any) {
|
||||
this.subject.next({ ...this.value, [name]: state });
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,11 @@
|
|||
"compileOnSave": false,
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"store": [
|
||||
"src/store.ts"
|
||||
]
|
||||
},
|
||||
"outDir": "./dist/out-tsc",
|
||||
"sourceMap": true,
|
||||
"declaration": false,
|
||||
|
|
|
|||
|
|
@ -46,13 +46,14 @@ namespace
|
|||
const command_line::arg_descriptor<std::string> arg_password = {"password", "Wallet password", "", true};
|
||||
const command_line::arg_descriptor<bool> arg_dont_refresh = { "no-refresh", "Do not refresh after load", false, true };
|
||||
const command_line::arg_descriptor<bool> arg_dont_set_date = { "no-set-creation-date", "Do not set wallet creation date", false, false };
|
||||
const command_line::arg_descriptor<bool> arg_print_brain_wallet = { "print-brain-wallet", "Print to conosole brain wallet", false, false };
|
||||
const command_line::arg_descriptor<int> arg_daemon_port = {"daemon-port", "Use daemon instance at port <arg> instead of default", 0};
|
||||
const command_line::arg_descriptor<uint32_t> arg_log_level = {"set-log", "", 0, true};
|
||||
const command_line::arg_descriptor<bool> arg_do_pos_mining = { "do-pos-mining", "Do PoS mining", false, false };
|
||||
const command_line::arg_descriptor<std::string> arg_pos_mining_reward_address = { "pos-mining-reward-address", "Block reward will be sent to the giving address if specified", "" };
|
||||
const command_line::arg_descriptor<std::string> arg_restore_wallet = { "restore-wallet", "Restore wallet from seed phrase or tracking seed and save it to <arg>", "" };
|
||||
const command_line::arg_descriptor<bool> arg_offline_mode = { "offline-mode", "Don't connect to daemon, work offline (for cold-signing process)", false, true };
|
||||
const command_line::arg_descriptor<std::string> arg_scan_for_wallet = { "scan-for-wallet", "", "", true };
|
||||
const command_line::arg_descriptor<std::string> arg_addr_to_compare = { "addr-to-compare", "", "", true };
|
||||
|
||||
const command_line::arg_descriptor< std::vector<std::string> > arg_command = {"command", ""};
|
||||
|
||||
|
|
@ -178,7 +179,6 @@ bool simple_wallet::help(const std::vector<std::string> &args/* = std::vector<st
|
|||
|
||||
simple_wallet::simple_wallet()
|
||||
: m_daemon_port(0),
|
||||
m_print_brain_wallet(false),
|
||||
m_do_refresh_after_load(false),
|
||||
m_do_not_set_date(false),
|
||||
m_do_pos_mining(false),
|
||||
|
|
@ -307,10 +307,6 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
|||
m_do_refresh_after_load = false;
|
||||
}
|
||||
|
||||
if (command_line::has_arg(vm, arg_print_brain_wallet))
|
||||
{
|
||||
m_print_brain_wallet = true;
|
||||
}
|
||||
|
||||
if (!m_generate_new.empty())
|
||||
{
|
||||
|
|
@ -336,9 +332,26 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
|||
fail_msg_writer() << "failed to read seed phrase";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool looks_like_tracking_seed = restore_seed_container.password().find(':') != std::string::npos;
|
||||
bool r = restore_wallet(m_restore_wallet, restore_seed_container.password(), pwd_container.password(), looks_like_tracking_seed);
|
||||
tools::password_container seed_password_container;
|
||||
|
||||
if (!looks_like_tracking_seed)
|
||||
{
|
||||
bool is_password_protected = false;
|
||||
bool sr = account_base::is_seed_password_protected(restore_seed_container.password(), is_password_protected);
|
||||
if (!sr)
|
||||
{
|
||||
fail_msg_writer() << "failed to parse seed phrase";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_password_protected && !seed_password_container.read_password("This seed is secured, to use it please enter the password:\n"))
|
||||
{
|
||||
fail_msg_writer() << "failed to read seed phrase";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool r = restore_wallet(m_restore_wallet, restore_seed_container.password(), pwd_container.password(), looks_like_tracking_seed, seed_password_container.password());
|
||||
CHECK_AND_ASSERT_MES(r, false, "wallet restoring failed");
|
||||
}
|
||||
else
|
||||
|
|
@ -400,10 +413,6 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas
|
|||
if (m_do_not_set_date)
|
||||
m_wallet->reset_creation_time(0);
|
||||
|
||||
if (m_print_brain_wallet)
|
||||
{
|
||||
std::cout << "Seed phrase (keep it in secret): " << m_wallet->get_account().get_seed_phrase() << std::endl << std::flush;
|
||||
}
|
||||
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
|
|
@ -422,7 +431,7 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas
|
|||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::restore_wallet(const std::string& wallet_file, const std::string& seed_or_tracking_seed, const std::string& password, bool tracking_wallet)
|
||||
bool simple_wallet::restore_wallet(const std::string& wallet_file, const std::string& seed_or_tracking_seed, const std::string& password, bool tracking_wallet, const std::string& seed_password)
|
||||
{
|
||||
m_wallet_file = wallet_file;
|
||||
|
||||
|
|
@ -434,13 +443,13 @@ bool simple_wallet::restore_wallet(const std::string& wallet_file, const std::st
|
|||
if (tracking_wallet)
|
||||
{
|
||||
// auditable watch-only aka tracking wallet
|
||||
m_wallet->restore(epee::string_encoding::utf8_to_wstring(wallet_file), password, seed_or_tracking_seed, true);
|
||||
m_wallet->restore(epee::string_encoding::utf8_to_wstring(wallet_file), password, seed_or_tracking_seed, true, "");
|
||||
message_writer(epee::log_space::console_color_white, true) << "Tracking wallet restored: " << m_wallet->get_account().get_public_address_str();
|
||||
}
|
||||
else
|
||||
{
|
||||
// normal or auditable wallet
|
||||
m_wallet->restore(epee::string_encoding::utf8_to_wstring(wallet_file), password, seed_or_tracking_seed, false);
|
||||
m_wallet->restore(epee::string_encoding::utf8_to_wstring(wallet_file), password, seed_or_tracking_seed, false, seed_password);
|
||||
message_writer(epee::log_space::console_color_white, true) << (m_wallet->is_auditable() ? "Auditable wallet" : "Wallet") << " restored: " << m_wallet->get_account().get_public_address_str();
|
||||
std::cout << "view key: " << string_tools::pod_to_hex(m_wallet->get_account().get_keys().view_secret_key) << std::endl << std::flush;
|
||||
if (m_wallet->is_auditable())
|
||||
|
|
@ -454,7 +463,11 @@ bool simple_wallet::restore_wallet(const std::string& wallet_file, const std::st
|
|||
fail_msg_writer() << "failed to restore wallet, check your " << (tracking_wallet ? "tracking seed!" : "seed phrase!") << ENDL << e.what();
|
||||
return false;
|
||||
}
|
||||
|
||||
catch (...)
|
||||
{
|
||||
fail_msg_writer() << "failed to restore wallet, check your " << (tracking_wallet ? "tracking seed!" : "seed phrase!") << ENDL;
|
||||
return false;
|
||||
}
|
||||
m_wallet->init(m_daemon_address);
|
||||
|
||||
success_msg_writer() <<
|
||||
|
|
@ -482,9 +495,6 @@ bool simple_wallet::open_wallet(const string &wallet_file, const std::string& pa
|
|||
m_wallet->load(epee::string_encoding::utf8_to_wstring(m_wallet_file), password);
|
||||
message_writer(epee::log_space::console_color_white, true) << "Opened" << (m_wallet->is_auditable() ? " auditable" : "") << (m_wallet->is_watch_only() ? " watch-only" : "") << " wallet: " << m_wallet->get_account().get_public_address_str();
|
||||
|
||||
if (m_print_brain_wallet)
|
||||
std::cout << "Seed phrase (keep it in secret): " << m_wallet->get_account().get_seed_phrase() << std::endl << std::flush;
|
||||
|
||||
break;
|
||||
}
|
||||
catch (const tools::error::wallet_load_notice_wallet_restored& /*e*/)
|
||||
|
|
@ -1359,9 +1369,24 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::show_seed(const std::vector<std::string> &args)
|
||||
{
|
||||
success_msg_writer() << "Here's your wallet's seed phrase. Write it down and keep in a safe place.";
|
||||
success_msg_writer(true) << "Anyone who knows the following 26 words can access your wallet:";
|
||||
std::cout << m_wallet->get_account().get_seed_phrase() << std::endl << std::flush;
|
||||
success_msg_writer() << "Please enter a password to secure this seed. Securing your seed is HIGHLY recommended. Leave password blank to stay unsecured.";
|
||||
success_msg_writer(true) << "Remember, restoring a wallet from Secured Seed can only be done if you know its password.";
|
||||
|
||||
tools::password_container seed_password_container1;
|
||||
if (!seed_password_container1.read_password("Enter seed password: "))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
tools::password_container seed_password_container2;
|
||||
if (!seed_password_container2.read_password("Confirm seed password: "))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(seed_password_container1.password() != seed_password_container2.password())
|
||||
{
|
||||
std::cout << "Error: password mismatch. Please make sure you entered the correct password and confirmed it" << std::endl << std::flush;
|
||||
}
|
||||
std::cout << m_wallet->get_account().get_seed_phrase(seed_password_container2.password()) << std::endl << std::flush;
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
|
@ -1712,6 +1737,109 @@ bool simple_wallet::sweep_below(const std::vector<std::string> &args)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
uint64_t
|
||||
get_tick_count__()
|
||||
{
|
||||
using namespace std::chrono;
|
||||
return duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool check_if_file_looks_like_a_wallet(const std::wstring& wallet_)
|
||||
{
|
||||
std::string keys_buff;
|
||||
|
||||
|
||||
boost::system::error_code e;
|
||||
bool exists = boost::filesystem::exists(wallet_, e);
|
||||
if (e || !exists)
|
||||
return false;
|
||||
|
||||
boost::filesystem::ifstream data_file;
|
||||
data_file.open(wallet_, std::ios_base::binary | std::ios_base::in);
|
||||
if (data_file.fail())
|
||||
return false;
|
||||
|
||||
tools::wallet_file_binary_header wbh = AUTO_VAL_INIT(wbh);
|
||||
|
||||
data_file.read((char*)&wbh, sizeof(wbh));
|
||||
if (data_file.fail())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wbh.m_signature != WALLET_FILE_SIGNATURE_OLD && wbh.m_signature != WALLET_FILE_SIGNATURE_V2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//std::cout << "\r \r";
|
||||
LOG_PRINT_L0("Found wallet file: " << epee::string_encoding::convert_to_ansii(wallet_));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool search_for_wallet_file(const std::wstring &search_here/*, const std::string &addr_to_compare*/)
|
||||
{
|
||||
if (search_here == L"/proc" || search_here == L"/bin" || search_here == L"/dev" || search_here == L"/etc"
|
||||
|| search_here == L"/lib" || search_here == L"/lib64" || search_here == L"/proc" || search_here == L"/run"
|
||||
|| search_here == L"/sbin" || search_here == L"/srv" || search_here == L"/sys" || search_here == L"/usr"
|
||||
|| search_here == L"/var")
|
||||
{
|
||||
LOG_PRINT_L0("Skiping " << epee::string_encoding::convert_to_ansii(search_here));
|
||||
return false;
|
||||
}
|
||||
|
||||
//LOG_PRINT_L0("FOLDER: " << epee::string_encoding::convert_to_ansii(search_here));
|
||||
static uint64_t last_tick = 0;
|
||||
using namespace boost::filesystem;
|
||||
//recursive_directory_iterator dir(search_here), end;
|
||||
try
|
||||
{
|
||||
for (auto& dir : boost::make_iterator_range(directory_iterator(search_here), {}))
|
||||
{
|
||||
boost::system::error_code ec = AUTO_VAL_INIT(ec);
|
||||
bool r = boost::filesystem::is_directory(dir.path(), ec);
|
||||
if (r)
|
||||
{
|
||||
if (get_tick_count__() - last_tick > 300)
|
||||
{
|
||||
last_tick = get_tick_count__();
|
||||
//std::cout << "\r \r ->" << dir.path();
|
||||
}
|
||||
bool r = search_for_wallet_file(dir.path().wstring());
|
||||
if (r)
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::system::error_code ec = AUTO_VAL_INIT(ec);
|
||||
bool r = boost::filesystem::is_regular_file(dir.path(), ec);
|
||||
if (!r)
|
||||
{
|
||||
//LOG_PRINT_L0("Skiping as not regular: " << epee::string_encoding::convert_to_ansii(dir.path().wstring()));
|
||||
return false;
|
||||
|
||||
}
|
||||
//LOG_PRINT_L0("FILE: " << dir.path().string());
|
||||
std::wstring pa = dir.path().wstring();
|
||||
r = check_if_file_looks_like_a_wallet(pa);
|
||||
if (r)
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception& /* ex*/)
|
||||
{
|
||||
//std::cout << "\r \r";
|
||||
LOG_PRINT_CYAN("Skip: " << search_here, LOG_LEVEL_0);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
#ifdef WIN32
|
||||
int wmain( int argc, wchar_t* argv_w[ ], wchar_t* envp[ ] )
|
||||
|
|
@ -1763,14 +1891,14 @@ int main(int argc, char* argv[])
|
|||
command_line::add_arg(desc_params, arg_log_level);
|
||||
command_line::add_arg(desc_params, arg_dont_refresh);
|
||||
command_line::add_arg(desc_params, arg_dont_set_date);
|
||||
command_line::add_arg(desc_params, arg_print_brain_wallet);
|
||||
command_line::add_arg(desc_params, arg_do_pos_mining);
|
||||
command_line::add_arg(desc_params, arg_pos_mining_reward_address);
|
||||
command_line::add_arg(desc_params, arg_restore_wallet);
|
||||
command_line::add_arg(desc_params, arg_offline_mode);
|
||||
command_line::add_arg(desc_params, command_line::arg_log_file);
|
||||
command_line::add_arg(desc_params, command_line::arg_log_level);
|
||||
|
||||
command_line::add_arg(desc_params, arg_scan_for_wallet);
|
||||
command_line::add_arg(desc_params, arg_addr_to_compare);
|
||||
|
||||
tools::wallet_rpc_server::init_options(desc_params);
|
||||
|
||||
|
|
@ -1827,6 +1955,17 @@ int main(int argc, char* argv[])
|
|||
log_space::get_set_log_detalisation_level(true, command_line::get_arg(vm, command_line::arg_log_level));
|
||||
}
|
||||
|
||||
|
||||
if (command_line::has_arg(vm, arg_scan_for_wallet))
|
||||
{
|
||||
log_space::log_singletone::add_logger(LOGGER_CONSOLE, nullptr, nullptr, LOG_LEVEL_4);
|
||||
LOG_PRINT_L0("Searching from "
|
||||
<< epee::string_encoding::convert_to_ansii(command_line::get_arg(vm, arg_scan_for_wallet)));
|
||||
|
||||
search_for_wallet_file(epee::string_encoding::convert_to_unicode(command_line::get_arg(vm, arg_scan_for_wallet)));
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
bool offline_mode = command_line::get_arg(vm, arg_offline_mode);
|
||||
|
||||
if (command_line::has_arg(vm, tools::wallet_rpc_server::arg_rpc_bind_port))
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ namespace currency
|
|||
|
||||
bool new_wallet(const std::string &wallet_file, const std::string& password, bool create_auditable_wallet);
|
||||
bool open_wallet(const std::string &wallet_file, const std::string& password);
|
||||
bool restore_wallet(const std::string& wallet_file, const std::string& seed_or_tracking_seed, const std::string& password, bool tracking_wallet);
|
||||
bool restore_wallet(const std::string& wallet_file, const std::string& seed_or_tracking_seed, const std::string& password, bool tracking_wallet, const std::string& seed_password);
|
||||
bool close_wallet();
|
||||
|
||||
bool help(const std::vector<std::string> &args = std::vector<std::string>());
|
||||
|
|
@ -163,7 +163,6 @@ namespace currency
|
|||
int m_daemon_port;
|
||||
bool m_do_refresh_after_load;
|
||||
bool m_do_not_set_date;
|
||||
bool m_print_brain_wallet;
|
||||
bool m_do_pos_mining;
|
||||
bool m_offline_mode;
|
||||
std::string m_restore_wallet;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,6 @@
|
|||
#define PROJECT_REVISION "7"
|
||||
#define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION
|
||||
|
||||
#define PROJECT_VERSION_BUILD_NO 105
|
||||
#define PROJECT_VERSION_BUILD_NO 110
|
||||
#define PROJECT_VERSION_BUILD_NO_STR STRINGIFY_EXPAND(PROJECT_VERSION_BUILD_NO)
|
||||
#define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO_STR "[" BUILD_COMMIT_ID "]"
|
||||
|
|
|
|||
|
|
@ -400,13 +400,13 @@ namespace plain_wallet
|
|||
return epee::serialization::store_t_to_json(err_result);
|
||||
}
|
||||
|
||||
std::string restore(const std::string& seed, const std::string& path, const std::string& password)
|
||||
std::string restore(const std::string& seed, const std::string& path, const std::string& password, const std::string& seed_password)
|
||||
{
|
||||
GET_INSTANCE_PTR(inst_ptr);
|
||||
|
||||
std::string full_path = get_wallets_folder() + path;
|
||||
epee::json_rpc::response<view::open_wallet_response, epee::json_rpc::dummy_error> ok_response = AUTO_VAL_INIT(ok_response);
|
||||
std::string rsp = inst_ptr->gwm.restore_wallet(epee::string_encoding::convert_to_unicode(full_path), password, seed, ok_response.result);
|
||||
std::string rsp = inst_ptr->gwm.restore_wallet(epee::string_encoding::convert_to_unicode(full_path), password, seed, seed_password, ok_response.result);
|
||||
if (rsp == API_RETURN_CODE_OK || rsp == API_RETURN_CODE_FILE_RESTORED)
|
||||
{
|
||||
if (rsp == API_RETURN_CODE_FILE_RESTORED)
|
||||
|
|
@ -526,7 +526,7 @@ namespace plain_wallet
|
|||
}
|
||||
async_callback = [job_id, rwr]()
|
||||
{
|
||||
std::string res = restore(rwr.restore_key, rwr.path, rwr.pass);
|
||||
std::string res = restore(rwr.seed_phrase, rwr.path, rwr.pass, rwr.seed_pass);
|
||||
put_result(job_id, res);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ namespace plain_wallet
|
|||
std::string get_connectivity_status();
|
||||
|
||||
std::string open(const std::string& path, const std::string& password);
|
||||
std::string restore(const std::string& seed, const std::string& path, const std::string& password);
|
||||
std::string restore(const std::string& seed, const std::string& path, const std::string& password, const std::string& seed_password);
|
||||
std::string generate(const std::string& path, const std::string& password);
|
||||
std::string get_opened_wallets();
|
||||
|
||||
|
|
|
|||
|
|
@ -272,6 +272,19 @@ public:
|
|||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
struct request_get_smart_wallet_info
|
||||
{
|
||||
uint64_t wallet_id;
|
||||
std::string seed_password;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(wallet_id)
|
||||
KV_SERIALIZE(seed_password)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
struct response_mining_estimate
|
||||
{
|
||||
uint64_t final_amount;
|
||||
|
|
@ -429,16 +442,43 @@ public:
|
|||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
struct is_valid_restore_wallet_text_param
|
||||
{
|
||||
std::string seed_phrase;
|
||||
std::string seed_password;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(seed_phrase)
|
||||
KV_SERIALIZE(seed_password)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct seed_phrase_info
|
||||
{
|
||||
bool syntax_correct;
|
||||
bool require_password;
|
||||
bool hash_sum_matched;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(syntax_correct)
|
||||
KV_SERIALIZE(require_password)
|
||||
KV_SERIALIZE(hash_sum_matched)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct restore_wallet_request
|
||||
{
|
||||
std::string pass;
|
||||
std::string seed_pass;
|
||||
std::string path;
|
||||
std::string restore_key;
|
||||
std::string seed_phrase;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(pass)
|
||||
KV_SERIALIZE(path)
|
||||
KV_SERIALIZE(restore_key)
|
||||
KV_SERIALIZE(seed_pass)
|
||||
KV_SERIALIZE(seed_phrase)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
|
@ -587,12 +627,10 @@ public:
|
|||
|
||||
struct get_restore_info_response
|
||||
{
|
||||
std::string restore_key;
|
||||
std::string error_code;
|
||||
std::string seed_phrase;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(restore_key)
|
||||
KV_SERIALIZE(error_code)
|
||||
KV_SERIALIZE(seed_phrase)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2347,7 +2347,7 @@ void wallet2::generate(const std::wstring& path, const std::string& pass, bool a
|
|||
store();
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::restore(const std::wstring& path, const std::string& pass, const std::string& seed_or_tracking_seed, bool tracking_wallet)
|
||||
void wallet2::restore(const std::wstring& path, const std::string& pass, const std::string& seed_or_tracking_seed, bool tracking_wallet, const std::string& seed_password)
|
||||
{
|
||||
bool r = false;
|
||||
clear();
|
||||
|
|
@ -2363,7 +2363,7 @@ void wallet2::restore(const std::wstring& path, const std::string& pass, const s
|
|||
}
|
||||
else
|
||||
{
|
||||
r = m_account.restore_from_seed_phrase(seed_or_tracking_seed);
|
||||
r = m_account.restore_from_seed_phrase(seed_or_tracking_seed, seed_password);
|
||||
init_log_prefix();
|
||||
THROW_IF_FALSE_WALLET_EX(r, error::wallet_wrong_seed_error, epee::string_encoding::convert_to_ansii(m_wallet_file));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -470,7 +470,7 @@ namespace tools
|
|||
|
||||
void assign_account(const currency::account_base& acc);
|
||||
void generate(const std::wstring& path, const std::string& password, bool auditable_wallet);
|
||||
void restore(const std::wstring& path, const std::string& pass, const std::string& seed_or_tracking_seed, bool tracking_wallet);
|
||||
void restore(const std::wstring& path, const std::string& pass, const std::string& seed_or_tracking_seed, bool tracking_wallet, const std::string& seed_password);
|
||||
void load(const std::wstring& path, const std::string& password);
|
||||
void store();
|
||||
void store(const std::wstring& path);
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ namespace tools
|
|||
res.path = epee::string_encoding::convert_to_ansii(m_wallet.get_wallet_path());
|
||||
res.transfers_count = m_wallet.get_recent_transfers_total_count();
|
||||
res.transfer_entries_count = m_wallet.get_transfer_entries_count();
|
||||
res.seed = m_wallet.get_account().get_seed_phrase();
|
||||
//res.seed = m_wallet.get_account().get_seed_phrase();
|
||||
std::map<uint64_t, uint64_t> distribution;
|
||||
m_wallet.get_utxo_distribution(distribution);
|
||||
for (const auto& ent : distribution)
|
||||
|
|
|
|||
|
|
@ -911,7 +911,7 @@ std::string wallets_manager::open_wallet(const std::wstring& path, const std::st
|
|||
w->get_unconfirmed_transfers(owr.recent_history.history, exclude_mining_txs);
|
||||
owr.wallet_local_bc_size = w->get_blockchain_current_size();
|
||||
//workaround for missed fee
|
||||
owr.seed = w->get_account().get_seed_phrase();
|
||||
//owr.seed = w->get_account().get_seed_phrase();
|
||||
break;
|
||||
}
|
||||
catch (const tools::error::file_not_found& /**/)
|
||||
|
|
@ -1015,7 +1015,7 @@ std::string wallets_manager::generate_wallet(const std::wstring& path, const std
|
|||
{
|
||||
w->generate(path, password, false);
|
||||
w->set_minimum_height(m_last_daemon_height);
|
||||
owr.seed = w->get_account().get_seed_phrase();
|
||||
//owr.seed = w->get_account().get_seed_phrase();
|
||||
}
|
||||
catch (const tools::error::file_exists&)
|
||||
{
|
||||
|
|
@ -1058,10 +1058,10 @@ std::string wallets_manager::is_pos_allowed()
|
|||
else
|
||||
return API_RETURN_CODE_FALSE;
|
||||
}
|
||||
std::string wallets_manager::is_valid_brain_restore_data(const std::string& seed_phrase)
|
||||
std::string wallets_manager::is_valid_brain_restore_data(const std::string& seed_phrase, const std::string& seed_password)
|
||||
{
|
||||
currency::account_base acc;
|
||||
if (acc.restore_from_seed_phrase(seed_phrase))
|
||||
if (acc.restore_from_seed_phrase(seed_phrase, seed_password))
|
||||
return API_RETURN_CODE_TRUE;
|
||||
|
||||
currency::account_public_address addr;
|
||||
|
|
@ -1081,11 +1081,25 @@ void wallets_manager::subscribe_to_core_events(currency::i_core_event_handler* p
|
|||
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string wallets_manager::get_seed_phrase_info(const std::string& seed_phrase, const std::string& seed_password, view::seed_phrase_info& result)
|
||||
{
|
||||
//cut the last timestamp word from restore_dats
|
||||
result.syntax_correct = currency::account_base::is_seed_password_protected(seed_phrase, result.require_password);
|
||||
if (result.syntax_correct)
|
||||
{
|
||||
currency::account_base acc;
|
||||
result.hash_sum_matched = acc.restore_from_seed_phrase(seed_phrase, seed_password);
|
||||
}
|
||||
return API_RETURN_CODE_OK;
|
||||
}
|
||||
|
||||
|
||||
void wallets_manager::get_gui_options(view::gui_options& opt)
|
||||
{
|
||||
opt = m_ui_opt;
|
||||
}
|
||||
std::string wallets_manager::restore_wallet(const std::wstring& path, const std::string& password, const std::string& restore_key, view::open_wallet_response& owr)
|
||||
std::string wallets_manager::restore_wallet(const std::wstring& path, const std::string& password, const std::string& seed_phrase, const std::string& seed_password, view::open_wallet_response& owr)
|
||||
{
|
||||
std::shared_ptr<tools::wallet2> w(new tools::wallet2());
|
||||
w->set_use_deffered_global_outputs(m_use_deffered_global_outputs);
|
||||
|
|
@ -1108,9 +1122,9 @@ std::string wallets_manager::restore_wallet(const std::wstring& path, const std:
|
|||
currency::account_base acc;
|
||||
try
|
||||
{
|
||||
bool auditable_watch_only = restore_key.find(':') != std::string::npos;
|
||||
w->restore(path, password, restore_key, auditable_watch_only);
|
||||
owr.seed = w->get_account().get_seed_phrase();
|
||||
bool auditable_watch_only = seed_phrase.find(':') != std::string::npos;
|
||||
w->restore(path, password, seed_phrase, auditable_watch_only, seed_password);
|
||||
//owr.seed = w->get_account().get_seed_phrase();
|
||||
}
|
||||
catch (const tools::error::file_exists&)
|
||||
{
|
||||
|
|
@ -1625,14 +1639,14 @@ std::string wallets_manager::get_mining_history(uint64_t wallet_id, tools::walle
|
|||
wo.w->get()->get_mining_history(mh);
|
||||
return API_RETURN_CODE_OK;
|
||||
}
|
||||
std::string wallets_manager::get_wallet_restore_info(uint64_t wallet_id, std::string& restore_key)
|
||||
std::string wallets_manager::get_wallet_restore_info(uint64_t wallet_id, std::string& seed_phrase, const std::string& seed_password)
|
||||
{
|
||||
GET_WALLET_OPT_BY_ID(wallet_id, wo);
|
||||
|
||||
if (wo.wallet_state != view::wallet_status_info::wallet_state_ready || wo.long_refresh_in_progress)
|
||||
return API_RETURN_CODE_CORE_BUSY;
|
||||
|
||||
restore_key = wo.w->get()->get_account().get_seed_phrase();
|
||||
seed_phrase = wo.w->get()->get_account().get_seed_phrase(seed_password);
|
||||
|
||||
return API_RETURN_CODE_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ public:
|
|||
bool get_opened_wallets(std::list<view::open_wallet_response>& result);
|
||||
std::string open_wallet(const std::wstring& path, const std::string& password, uint64_t txs_to_return, view::open_wallet_response& owr, bool exclude_mining_txs = false);
|
||||
std::string generate_wallet(const std::wstring& path, const std::string& password, view::open_wallet_response& owr);
|
||||
std::string restore_wallet(const std::wstring& path, const std::string& password, const std::string& restore_key, view::open_wallet_response& owr);
|
||||
std::string restore_wallet(const std::wstring& path, const std::string& password, const std::string& seed_phrase, const std::string& seed_password, view::open_wallet_response& owr);
|
||||
std::string invoke(uint64_t wallet_id, std::string params);
|
||||
std::string get_wallet_status(uint64_t wallet_id);
|
||||
std::string run_wallet(uint64_t wallet_id);
|
||||
|
|
@ -132,7 +132,7 @@ public:
|
|||
std::string stop_pos_mining(uint64_t wallet_id);
|
||||
std::string check_available_sources(uint64_t wallet_id, std::list<uint64_t>& amounts);
|
||||
std::string get_mining_history(uint64_t wallet_id, tools::wallet_public::mining_history& wrpc);
|
||||
std::string get_wallet_restore_info(uint64_t wallet_id, std::string& restore_key);
|
||||
std::string get_wallet_restore_info(uint64_t wallet_id, std::string& seed_phrase, const std::string& seed_password);
|
||||
std::string backup_wallet(uint64_t wallet_id, const std::wstring& path);
|
||||
std::string reset_wallet_password(uint64_t wallet_id, const std::string& pass);
|
||||
std::string is_wallet_password_valid(uint64_t wallet_id, const std::string& pass);
|
||||
|
|
@ -149,7 +149,8 @@ public:
|
|||
void toggle_pos_mining();
|
||||
std::string transfer(size_t wallet_id, const view::transfer_params& tp, currency::transaction& res_tx);
|
||||
std::string get_config_folder();
|
||||
std::string is_valid_brain_restore_data(const std::string& seed_phrase);
|
||||
std::string is_valid_brain_restore_data(const std::string& seed_phrase, const std::string& seed_password);
|
||||
std::string get_seed_phrase_info(const std::string& seed_phrase, const std::string& seed_password, view::seed_phrase_info& result);
|
||||
#ifndef MOBILE_WALLET_BUILD
|
||||
void subscribe_to_core_events(currency::i_core_event_handler* pevents_handler);
|
||||
//void unsubscribe_to_core_events();
|
||||
|
|
|
|||
|
|
@ -842,7 +842,7 @@ namespace db_test
|
|||
ptr = db_array[4];
|
||||
ASSERT_EQ(ptr->v, "X");
|
||||
|
||||
ASSERT_TRUE(db_array.clear());
|
||||
ASSERT_TRUE((db_array.clear()? true: false));
|
||||
|
||||
db_array.commit_transaction();
|
||||
|
||||
|
|
|
|||
|
|
@ -13,10 +13,10 @@ TEST(wallet_seed, store_restore_test)
|
|||
{
|
||||
currency::account_base acc;
|
||||
acc.generate();
|
||||
auto seed_phrase = acc.get_seed_phrase();
|
||||
auto seed_phrase = acc.get_seed_phrase("");
|
||||
|
||||
currency::account_base acc2;
|
||||
bool r = acc2.restore_from_seed_phrase(seed_phrase);
|
||||
bool r = acc2.restore_from_seed_phrase(seed_phrase, "");
|
||||
ASSERT_TRUE(r);
|
||||
|
||||
if (memcmp(&acc2.get_keys(), &acc.get_keys(), sizeof(currency::account_keys)))
|
||||
|
|
@ -29,10 +29,10 @@ TEST(wallet_seed, store_restore_test)
|
|||
{
|
||||
currency::account_base acc;
|
||||
acc.generate();
|
||||
auto seed_phrase = acc.get_seed_phrase();
|
||||
auto seed_phrase = acc.get_seed_phrase("");
|
||||
|
||||
currency::account_base acc2;
|
||||
bool r = acc2.restore_from_seed_phrase(seed_phrase);
|
||||
bool r = acc2.restore_from_seed_phrase(seed_phrase, "");
|
||||
ASSERT_TRUE(r);
|
||||
|
||||
if (memcmp(&acc2.get_keys(), &acc.get_keys(), sizeof(currency::account_keys)))
|
||||
|
|
@ -57,7 +57,7 @@ wallet_seed_entry wallet_seed_entries[] =
|
|||
{
|
||||
{
|
||||
// legacy 24-word seed phrase -- invalid
|
||||
"dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew",
|
||||
"dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew god",
|
||||
"",
|
||||
"",
|
||||
0,
|
||||
|
|
@ -66,7 +66,7 @@ wallet_seed_entry wallet_seed_entries[] =
|
|||
},
|
||||
{
|
||||
// old-style 25-word seed phrase -- valid
|
||||
"dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew",
|
||||
"dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew god",
|
||||
"5e051454d7226b5734ebd64f754b57db4c655ecda00bd324f1b241d0b6381c0f",
|
||||
"7dde5590fdf430568c00556ac2accf09da6cde9a29a4bc7d1cb6fd267130f006",
|
||||
0,
|
||||
|
|
@ -148,7 +148,41 @@ TEST(wallet_seed, basic_test)
|
|||
bool r = false;
|
||||
try
|
||||
{
|
||||
r = acc.restore_from_seed_phrase(wse.seed_phrase);
|
||||
r = acc.restore_from_seed_phrase(wse.seed_phrase, "");
|
||||
if (r)
|
||||
{
|
||||
for (size_t j = 0; j != 100; j++)
|
||||
{
|
||||
//generate random password
|
||||
std::string pass = epee::string_tools::pod_to_hex(crypto::cn_fast_hash(&j, sizeof(j)));
|
||||
if (j!= 0 && j < 64)
|
||||
{
|
||||
pass.resize(j);
|
||||
}
|
||||
//get secured seed
|
||||
std::string secured_seed = acc.get_seed_phrase(pass);
|
||||
|
||||
//try to restore it without password(should fail)
|
||||
currency::account_base acc2;
|
||||
bool r_fail = acc2.restore_from_seed_phrase(secured_seed, "");
|
||||
ASSERT_EQ(r_fail, false);
|
||||
|
||||
//try to restore it with wrong password
|
||||
bool r_fake_pass = acc2.restore_from_seed_phrase(secured_seed, "fake_password");
|
||||
if (r_fake_pass)
|
||||
{
|
||||
//accidentally checksumm matched(quite possible)
|
||||
ASSERT_EQ(false, acc2.get_keys() == acc.get_keys());
|
||||
}
|
||||
|
||||
//try to restore it from right password
|
||||
currency::account_base acc3;
|
||||
bool r_true_res = acc3.restore_from_seed_phrase(secured_seed, pass);
|
||||
ASSERT_EQ(true, r_true_res);
|
||||
ASSERT_EQ(true, acc3.get_keys() == acc.get_keys());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
|
|
|||