From d999356e78922fb0ccd830c1d6a81dd836d462d2 Mon Sep 17 00:00:00 2001 From: smk762 Date: Thu, 22 Aug 2024 01:14:41 +0800 Subject: [PATCH 1/3] add timesync service --- .../sync/timesync.checker.service.cpp | 116 ++++++++++++++++++ .../sync/timesync.checker.service.hpp | 60 +++++++++ 2 files changed, 176 insertions(+) create mode 100644 src/core/atomicdex/services/sync/timesync.checker.service.cpp create mode 100644 src/core/atomicdex/services/sync/timesync.checker.service.hpp diff --git a/src/core/atomicdex/services/sync/timesync.checker.service.cpp b/src/core/atomicdex/services/sync/timesync.checker.service.cpp new file mode 100644 index 0000000000..b74efa0927 --- /dev/null +++ b/src/core/atomicdex/services/sync/timesync.checker.service.cpp @@ -0,0 +1,116 @@ +/****************************************************************************** + * Copyright © 2013-2024 The Komodo Platform Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * Komodo Platform software, including this file may be copied, modified, * + * propagated or distributed except according to the terms contained in the * + * LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + +#include +#include "atomicdex/services/sync/timesync.checker.service.hpp" +#include "atomicdex/utilities/cpprestsdk.utilities.hpp" + +namespace +{ + constexpr const char* g_timesync_endpoint = "https://worldtimeapi.org"; + web::http::client::http_client_config g_timesync_cfg{[]() + { + web::http::client::http_client_config cfg; + cfg.set_validate_certificates(false); + cfg.set_timeout(std::chrono::seconds(5)); + return cfg; + }()}; + t_http_client_ptr g_timesync_client = std::make_unique(FROM_STD_STR(g_timesync_endpoint), g_timesync_cfg); + pplx::cancellation_token_source g_synctoken_source; + + pplx::task + async_fetch_timesync() + { + web::http::http_request req; + req.set_method(web::http::methods::GET); + req.set_request_uri(FROM_STD_STR("api/timezone/UTC")); + SPDLOG_INFO("req: {}", TO_STD_STR(req.to_string())); + return g_timesync_client->request(req, g_synctoken_source.get_token()); + } + + bool get_timesync_info_rpc(web::http::http_response resp_http) + { + using namespace std::string_literals; + nlohmann::json resp; + bool sync_ok = false; + std::string resp_str = TO_STD_STR(resp_http.extract_string(true).get()); + if (resp_http.status_code() != 200) + { + SPDLOG_ERROR("Cannot reach the endpoint [{}]: {}", g_timesync_endpoint); + } + else + { + resp = nlohmann::json::parse(resp_str); + int8_t epoch_ts = resp["unixtime"]; + int8_t current_ts = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + int8_t ts_diff = epoch_ts - current_ts; + if (abs(ts_diff) < 60) + { + sync_ok = true; + } + SPDLOG_WARN("TIME SYNC STATUS [{}]", sync_ok); + } + return sync_ok; + } +} // namespace + + +namespace atomic_dex +{ + timesync_checker_service::timesync_checker_service(entt::registry& registry, QObject* parent) : QObject(parent), system(registry) + { + m_timesync_clock = std::chrono::high_resolution_clock::now(); + fetch_timesync_info(); + } + + void timesync_checker_service::update() + { + using namespace std::chrono_literals; + + const auto now = std::chrono::high_resolution_clock::now(); + const auto s = std::chrono::duration_cast(now - m_timesync_clock); + if (s >= 1min) + { + fetch_timesync_info(); + m_timesync_clock = std::chrono::high_resolution_clock::now(); + } + } + + void timesync_checker_service::fetch_timesync_info() + { + if (is_timesync_fetching) + return; + is_timesync_fetching = true; + emit isTimesyncFetchingChanged(); + async_fetch_timesync() + .then([this](web::http::http_response resp) { + + this->m_timesync_info = get_timesync_info_rpc(resp); + is_timesync_fetching = false; + emit isTimesyncFetchingChanged(); + emit timesyncInfoChanged(); + }) + .then(&handle_exception_pplx_task); + } + + bool timesync_checker_service::get_timesync_info() const + { + return *m_timesync_info; + } + +} // namespace atomic_dex + + diff --git a/src/core/atomicdex/services/sync/timesync.checker.service.hpp b/src/core/atomicdex/services/sync/timesync.checker.service.hpp new file mode 100644 index 0000000000..e3ccb86eea --- /dev/null +++ b/src/core/atomicdex/services/sync/timesync.checker.service.hpp @@ -0,0 +1,60 @@ +/****************************************************************************** + * Copyright © 2013-2024 The Komodo Platform Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * Komodo Platform software, including this file may be copied, modified, * + * propagated or distributed except according to the terms contained in the * + * LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + +#pragma once + +#include +#include + +#include +#include + +#include + +namespace atomic_dex +{ + class timesync_checker_service final : public QObject, public ag::ecs::pre_update_system + { + Q_OBJECT + + Q_PROPERTY(QVariant timesyncInfo READ get_timesync_info NOTIFY timesyncInfoChanged) + Q_PROPERTY(bool isTimesyncFetching READ get_is_timesync_fetching NOTIFY isTimesyncFetchingChanged) + + using t_timesync_time_point = std::chrono::high_resolution_clock::time_point; + using t_bool_synchronized = boost::synchronized_value; + + t_bool_synchronized m_timesync_info; + t_timesync_time_point m_timesync_clock; + t_bool_synchronized is_timesync_fetching; + + void fetch_timesync_info(); + + public: + explicit timesync_checker_service(entt::registry& registry, QObject* parent = nullptr); + ~timesync_checker_service() final = default; + + void update() final; + + [[nodiscard]] bool get_timesync_info() const; + [[nodiscard]] bool get_is_timesync_fetching() const noexcept { return *is_timesync_fetching; } + + signals: + void timesyncInfoChanged(); + void isTimesyncFetchingChanged(); + }; +} // namespace atomic_dex + +REFL_AUTO(type(atomic_dex::timesync_checker_service)) From c20f43adbdd8488ebd5e4d934b478b1be5683873 Mon Sep 17 00:00:00 2001 From: smk762 Date: Thu, 22 Aug 2024 01:15:07 +0800 Subject: [PATCH 2/3] include timesync service --- src/app/app.cpp | 15 ++++++++++++++- src/app/app.hpp | 4 ++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/app/app.cpp b/src/app/app.cpp index 8036d57e47..f2bf63ef11 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -44,6 +44,7 @@ #include "atomicdex/services/price/komodo_prices/komodo.prices.provider.hpp" #include "atomicdex/services/price/coingecko/coingecko.wallet.charts.hpp" #include "atomicdex/services/price/orderbook.scanner.service.hpp" +#include "atomicdex/services/sync/timesync.checker.service.hpp" namespace { @@ -498,6 +499,7 @@ namespace atomic_dex system_manager_.create_system(system_manager_); system_manager_.create_system(); system_manager_.create_system(); + system_manager_.create_system(); system_manager_.create_system(system_manager_); system_manager_.create_system(system_manager_); system_manager_.create_system( @@ -910,7 +912,18 @@ namespace atomic_dex } } // namespace atomic_dex -//! update checker +//! time sync checker +namespace atomic_dex +{ + timesync_checker_service* application::get_timesync_checker_service() const + { + auto ptr = const_cast(std::addressof(system_manager_.get_system())); + assert(ptr != nullptr); + return ptr; + } +} // namespace atomic_dex + +//! zcash_params checker namespace atomic_dex { zcash_params_service* application::get_zcash_params_service() const diff --git a/src/app/app.hpp b/src/app/app.hpp index e6d26b7fd1..6e1e93a9fe 100644 --- a/src/app/app.hpp +++ b/src/app/app.hpp @@ -50,6 +50,7 @@ #include "atomicdex/services/price/global.provider.hpp" #include "atomicdex/services/update/update.checker.service.hpp" #include "atomicdex/services/update/zcash.params.service.hpp" +#include "atomicdex/services/sync/timesync.checker.service.hpp" #include "atomicdex/utilities/qt.utilities.hpp" namespace ag = antara::gaming; @@ -75,6 +76,7 @@ namespace atomic_dex Q_PROPERTY(settings_page* settings_pg READ get_settings_page NOTIFY settingsPageChanged) Q_PROPERTY(qt_wallet_manager* wallet_mgr READ get_wallet_mgr NOTIFY walletMgrChanged) Q_PROPERTY(update_checker_service* updateCheckerService READ get_update_checker_service NOTIFY updateCheckerServiceChanged) + Q_PROPERTY(timesync_checker_service* timesyncCheckerService READ get_timesync_checker_service NOTIFY timesyncCheckerServiceChanged) Q_PROPERTY(zcash_params_service* zcash_params READ get_zcash_params_service NOTIFY zcashParamsServiceChanged) //! Private function @@ -135,6 +137,7 @@ namespace atomic_dex qt_wallet_manager* get_wallet_mgr() const; internet_service_checker* get_internet_checker() const; update_checker_service* get_update_checker_service() const; + timesync_checker_service* get_timesync_checker_service() const; [[nodiscard]] zcash_params_service* get_zcash_params_service() const; exporter_service* get_exporter_service() const; @@ -180,6 +183,7 @@ namespace atomic_dex void walletPageChanged(); void ordersChanged(); void updateCheckerServiceChanged(); + void timesyncCheckerServiceChanged(); void zcashParamsServiceChanged(); void tradingPageChanged(); void settingsPageChanged(); From 90b1d025b9a045db9f391fb446b2b80dd13e2560 Mon Sep 17 00:00:00 2001 From: smk762 Date: Thu, 22 Aug 2024 21:03:09 +0800 Subject: [PATCH 3/3] add tooltip and default to portoflio when dex disabled --- .../Dex/Exchange/Trade/FeeIcon.qml | 4 +-- atomic_defi_design/Dex/Sidebar/Center.qml | 24 ++++++++++++- .../Dex/Sidebar/FigurativeLine.qml | 11 ++++++ .../sync/timesync.checker.service.cpp | 34 ++++++++++--------- .../sync/timesync.checker.service.hpp | 4 +-- 5 files changed, 56 insertions(+), 21 deletions(-) diff --git a/atomic_defi_design/Dex/Exchange/Trade/FeeIcon.qml b/atomic_defi_design/Dex/Exchange/Trade/FeeIcon.qml index a5f65a9ba9..883e5e13d1 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/FeeIcon.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/FeeIcon.qml @@ -24,12 +24,12 @@ DefaultText { visible: mouse_area.containsMouse contentItem: ColumnLayout { - DefaultText { + DexLabel { id: tx_fee_text text_value: General.txFeeText(trade_info, base, false) font.pixelSize: Style.textSizeSmall4 } - DefaultText { + DexLabel { text_value: General.tradingFeeText(trade_info, base, false) font.pixelSize: tx_fee_text.font.pixelSize } diff --git a/atomic_defi_design/Dex/Sidebar/Center.qml b/atomic_defi_design/Dex/Sidebar/Center.qml index 89ab94df97..a3e2586d90 100644 --- a/atomic_defi_design/Dex/Sidebar/Center.qml +++ b/atomic_defi_design/Dex/Sidebar/Center.qml @@ -15,6 +15,25 @@ MouseArea height: lineHeight * 5 hoverEnabled: true + Connections + { + target: API.app.timesyncCheckerService + + function onTimesyncInfoChanged() + { + if (!API.app.timesyncCheckerService.timesyncInfo) + { + _dexLine.timesyncInfo = false + if (currentLineType === Main.LineType.DEX) currentLineType = Main.LineType.Portfolio + root.lineSelected(Main.LineType.Portfolio); + } + else + { + _dexLine.timesyncInfo = true + } + } + } + Connections { target: parent.parent @@ -84,12 +103,15 @@ MouseArea FigurativeLine { id: _dexLine + property var timesyncInfo: API.app.timesyncCheckerService.timesyncInfo Layout.fillWidth: true type: Main.LineType.DEX + label.color: timesyncInfo ? Dex.CurrentTheme.foregroundColor : Dex.CurrentTheme.textDisabledColor label.text: qsTr("DEX") // isExpanded ? qsTr("DEX") : "" icon.source: General.image_path + "menu-exchange-white.svg" - onClicked: lineSelected(type) + onClicked: timesyncInfo ? lineSelected(type) : null + disabled_tt_text: timesyncInfo ? "" : qsTr("DEX is disabled due to system clock synchronization issues. Please check your device time settings.") } FigurativeLine diff --git a/atomic_defi_design/Dex/Sidebar/FigurativeLine.qml b/atomic_defi_design/Dex/Sidebar/FigurativeLine.qml index 540ca6e11b..a747a36e7f 100644 --- a/atomic_defi_design/Dex/Sidebar/FigurativeLine.qml +++ b/atomic_defi_design/Dex/Sidebar/FigurativeLine.qml @@ -1,12 +1,14 @@ import QtQuick 2.12 import "../Components" +import "../Constants" import Dex.Themes 1.0 as Dex // FigurativeLine acts the same as Line but contains a figurative icon on the left of its label Line { property alias icon: _icon + property string disabled_tt_text: "" DefaultImage { @@ -26,4 +28,13 @@ Line currentLineType === type && type != Main.LineType.Support ? Dex.CurrentTheme.sidebarLineTextSelected : Dex.CurrentTheme.foregroundColor } + + DexTooltip + { + visible: mouseArea.containsMouse && disabled_tt_text + delay: 500 + timeout: 5000 + text: disabled_tt_text + font.pixelSize: Style.textSizeSmall4 + } } diff --git a/src/core/atomicdex/services/sync/timesync.checker.service.cpp b/src/core/atomicdex/services/sync/timesync.checker.service.cpp index b74efa0927..2909368a4e 100644 --- a/src/core/atomicdex/services/sync/timesync.checker.service.cpp +++ b/src/core/atomicdex/services/sync/timesync.checker.service.cpp @@ -37,7 +37,6 @@ namespace web::http::http_request req; req.set_method(web::http::methods::GET); req.set_request_uri(FROM_STD_STR("api/timezone/UTC")); - SPDLOG_INFO("req: {}", TO_STD_STR(req.to_string())); return g_timesync_client->request(req, g_synctoken_source.get_token()); } @@ -54,14 +53,13 @@ namespace else { resp = nlohmann::json::parse(resp_str); - int8_t epoch_ts = resp["unixtime"]; - int8_t current_ts = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); - int8_t ts_diff = epoch_ts - current_ts; + int64_t epoch_ts = resp["unixtime"]; + int64_t current_ts = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + int64_t ts_diff = epoch_ts - current_ts; if (abs(ts_diff) < 60) { sync_ok = true; } - SPDLOG_WARN("TIME SYNC STATUS [{}]", sync_ok); } return sync_ok; } @@ -73,42 +71,46 @@ namespace atomic_dex timesync_checker_service::timesync_checker_service(entt::registry& registry, QObject* parent) : QObject(parent), system(registry) { m_timesync_clock = std::chrono::high_resolution_clock::now(); - fetch_timesync_info(); + m_timesync_status = true; + fetch_timesync_status(); } void timesync_checker_service::update() { using namespace std::chrono_literals; - const auto now = std::chrono::high_resolution_clock::now(); - const auto s = std::chrono::duration_cast(now - m_timesync_clock); - if (s >= 1min) + int64_t m_timesync_clock_ts = std::chrono::duration_cast(m_timesync_clock.time_since_epoch()).count(); + int64_t now_ts = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + int64_t ts_diff = now_ts - m_timesync_clock_ts; + if (abs(ts_diff) >= 60) { - fetch_timesync_info(); + fetch_timesync_status(); m_timesync_clock = std::chrono::high_resolution_clock::now(); } } - void timesync_checker_service::fetch_timesync_info() + void timesync_checker_service::fetch_timesync_status() { if (is_timesync_fetching) + { return; + } is_timesync_fetching = true; emit isTimesyncFetchingChanged(); async_fetch_timesync() .then([this](web::http::http_response resp) { - - this->m_timesync_info = get_timesync_info_rpc(resp); - is_timesync_fetching = false; - emit isTimesyncFetchingChanged(); + this->m_timesync_status = get_timesync_info_rpc(resp); emit timesyncInfoChanged(); }) .then(&handle_exception_pplx_task); + is_timesync_fetching = false; + emit isTimesyncFetchingChanged(); + } bool timesync_checker_service::get_timesync_info() const { - return *m_timesync_info; + return *m_timesync_status; } } // namespace atomic_dex diff --git a/src/core/atomicdex/services/sync/timesync.checker.service.hpp b/src/core/atomicdex/services/sync/timesync.checker.service.hpp index e3ccb86eea..54b3f73bf5 100644 --- a/src/core/atomicdex/services/sync/timesync.checker.service.hpp +++ b/src/core/atomicdex/services/sync/timesync.checker.service.hpp @@ -36,11 +36,11 @@ namespace atomic_dex using t_timesync_time_point = std::chrono::high_resolution_clock::time_point; using t_bool_synchronized = boost::synchronized_value; - t_bool_synchronized m_timesync_info; + t_bool_synchronized m_timesync_status; t_timesync_time_point m_timesync_clock; t_bool_synchronized is_timesync_fetching; - void fetch_timesync_info(); + void fetch_timesync_status(); public: explicit timesync_checker_service(entt::registry& registry, QObject* parent = nullptr);