From 16b866ccbd98e5a0b1e732ff9f39f60ce14ec682 Mon Sep 17 00:00:00 2001 From: Stefan Date: Wed, 13 Jul 2022 18:45:18 +0200 Subject: [PATCH] chore(CPP): Enhance type safety using phantom types Important changes: - Converted the easy to mix strings to named types as phantom types - Renamed `AccountDto`s to `MultiAccount` to better match the status-go domain knowledge. - Renamed MultiAccount to ChatOrWalletAccount to better match its multi purpose and don't confuse with the MultiAccount domain knowledge. - Remove libs/CMakeLists.txt Note: Tried to use the fluent::NamedType but it doesn't work with nlohmann_json, gave up finding why. Therefore I extracted only the needed functionality for the simple types we use. Updates: #6321 --- .gitignore | 1 + CMakeLists.txt | 11 ++- app/CMakeLists.txt | 4 +- .../Application/Navigation/CMakeLists.txt | 1 - app/res/CMakeLists.txt | 15 ---- libs/Assets/CMakeLists.txt | 1 - libs/CMakeLists.txt | 6 -- libs/Helpers/CMakeLists.txt | 1 + libs/Helpers/src/Helpers/NamedType.h | 70 ++++++++++++++++++ libs/Helpers/src/Helpers/conversions.cpp | 7 +- libs/Helpers/src/Helpers/conversions.h | 13 +++- libs/Onboarding/CMakeLists.txt | 4 +- .../Status/Onboarding/ConfirmPasswordPage.qml | 3 - .../Onboarding/Accounts/AccountsService.cpp | 72 +++++++++---------- .../src/Onboarding/Accounts/AccountsService.h | 34 ++++----- .../Accounts/AccountsServiceInterface.h | 16 ++--- ...edAccountDto.h => GeneratedMultiAccount.h} | 24 +++---- .../Accounts/{AccountDto.h => MultiAccount.h} | 18 +++-- libs/Onboarding/src/Onboarding/CMakeLists.txt | 4 +- .../src/Onboarding/Common/Constants.h | 14 ++-- .../src/Onboarding/NewAccountController.h | 2 +- .../src/Onboarding/OnboardingController.cpp | 4 +- .../src/Onboarding/OnboardingController.h | 4 +- .../Onboarding/src/Onboarding/UserAccount.cpp | 9 ++- libs/Onboarding/src/Onboarding/UserAccount.h | 10 +-- libs/Onboarding/tests/CMakeLists.txt | 4 -- .../ScopedTestAccount.cpp | 4 +- .../OnboardingTestHelpers/ScopedTestAccount.h | 4 +- libs/Onboarding/tests/ServiceMock.h | 12 ++-- libs/StatusGoQt/CMakeLists.txt | 6 +- .../src/StatusGo/Accounts/Accounts.cpp | 23 +++--- .../src/StatusGo/Accounts/Accounts.h | 20 +++--- .../src/StatusGo/Accounts/AccountsAPI.cpp | 18 ++--- .../src/StatusGo/Accounts/AccountsAPI.h | 18 ++--- ...ltiAccount.cpp => ChatOrWalletAccount.cpp} | 8 +-- .../StatusGo/Accounts/ChatOrWalletAccount.h | 42 +++++++++++ .../src/StatusGo/Accounts/MultiAccount.h | 42 ----------- .../src/StatusGo/Accounts/accounts_types.h | 16 +++++ libs/StatusGoQt/src/StatusGo/Types.h | 4 ++ libs/StatusGoQt/src/StatusGo/Utils.cpp | 10 +-- libs/StatusGoQt/src/StatusGo/Utils.h | 5 +- .../src/StatusGo/Wallet/DerivedAddress.h | 14 ++-- .../src/StatusGo/Wallet/WalletApi.cpp | 8 ++- .../src/StatusGo/Wallet/WalletApi.h | 7 +- libs/StatusQ/CMakeLists.txt | 1 - .../qml/Status/Containers/CMakeLists.txt | 1 - .../qml/Status/Controls/CMakeLists.txt | 1 - .../Status/Controls/Navigation/CMakeLists.txt | 1 - libs/StatusQ/qml/Status/Core/CMakeLists.txt | 1 - .../qml/Status/Core/Theme/CMakeLists.txt | 1 - libs/StatusQ/tests/CMakeLists.txt | 3 +- test/libs/StatusGoQt/test_accounts.cpp | 40 +++++------ test/libs/StatusGoQt/test_wallet.cpp | 10 +-- 53 files changed, 383 insertions(+), 289 deletions(-) delete mode 100644 app/res/CMakeLists.txt delete mode 100644 libs/CMakeLists.txt create mode 100644 libs/Helpers/src/Helpers/NamedType.h rename libs/Onboarding/src/Onboarding/Accounts/{GeneratedAccountDto.h => GeneratedMultiAccount.h} (87%) rename libs/Onboarding/src/Onboarding/Accounts/{AccountDto.h => MultiAccount.h} (69%) rename libs/StatusGoQt/src/StatusGo/Accounts/{MultiAccount.cpp => ChatOrWalletAccount.cpp} (84%) create mode 100644 libs/StatusGoQt/src/StatusGo/Accounts/ChatOrWalletAccount.h delete mode 100644 libs/StatusGoQt/src/StatusGo/Accounts/MultiAccount.h create mode 100644 libs/StatusGoQt/src/StatusGo/Accounts/accounts_types.h diff --git a/.gitignore b/.gitignore index b72b96f4e..7211f11f7 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ noBackup/ *.log .update.timestamp .vscode +*.code-workspace .tours bin/ /bottles/ diff --git a/CMakeLists.txt b/CMakeLists.txt index ca95540b5..5bcbaf589 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,9 +27,18 @@ endif() # status-desktop application add_subdirectory(vendor) -add_subdirectory(libs) + +add_subdirectory(libs/ApplicationCore) +add_subdirectory(libs/Assets) +add_subdirectory(libs/Helpers) +add_subdirectory(libs/Onboarding) +add_subdirectory(libs/StatusGoQt) +add_subdirectory(libs/StatusQ) + add_subdirectory(app) + add_subdirectory(test/libs/StatusGoQt) + # TODO: temporary not to duplicate resources until we switch to c++ app then it can be refactored add_subdirectory(resources) add_subdirectory(ui/imports/assets) diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 79d239680..49c026cb5 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -32,6 +32,9 @@ qt6_add_qml_module(${PROJECT_NAME} qml/Status/Application/MainShortcuts.qml qml/Status/Application/StatusWindow.qml + SOURCES + res/app.qrc + OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Status/Application ) @@ -47,7 +50,6 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE BUILD_SOURCE_DIR=${CMAKE_SOUR add_subdirectory(qml/Status/Application/Navigation) add_subdirectory(src) -add_subdirectory(res) include(${CMAKE_SOURCE_DIR}/cmake/platform_specific.cmake) string(TOLOWER ${PROJECT_ORGANIZATION_NAME} URL_ORGANIZATION_NAME) diff --git a/app/qml/Status/Application/Navigation/CMakeLists.txt b/app/qml/Status/Application/Navigation/CMakeLists.txt index 7f98709d7..37f49e960 100644 --- a/app/qml/Status/Application/Navigation/CMakeLists.txt +++ b/app/qml/Status/Application/Navigation/CMakeLists.txt @@ -14,7 +14,6 @@ qt6_add_qml_module(${PROJECT_NAME} URI Status.Application.Navigation VERSION 1.0 - # TODO: temporary until we make qt_target_qml_sources work QML_FILES StatusNavigationBar.qml StatusNavigationButton.qml diff --git a/app/res/CMakeLists.txt b/app/res/CMakeLists.txt deleted file mode 100644 index 9f524c7b9..000000000 --- a/app/res/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -# TODO workaround until Qt6 API is clarified -target_sources(${PROJECT_NAME} - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/app.qrc - - ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt -) - -# TODO find out why it isn't working -# -#qt6_target_qml_sources(${PROJECT_NAME} -# RESOURCES -# qtquickcontrols2.conf -# PREFIX "" -#) diff --git a/libs/Assets/CMakeLists.txt b/libs/Assets/CMakeLists.txt index 5b61a04fc..7fa74d4e8 100644 --- a/libs/Assets/CMakeLists.txt +++ b/libs/Assets/CMakeLists.txt @@ -20,7 +20,6 @@ qt6_add_qml_module(Assets URI Status.Assets VERSION 1.0 - # TODO: temporary until we make qt_target_qml_sources work QML_FILES qml/Status/Assets/Resources.qml diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt deleted file mode 100644 index 323f1768e..000000000 --- a/libs/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -add_subdirectory(ApplicationCore) -add_subdirectory(Assets) -add_subdirectory(Helpers) -add_subdirectory(Onboarding) -add_subdirectory(StatusGoQt) -add_subdirectory(StatusQ) diff --git a/libs/Helpers/CMakeLists.txt b/libs/Helpers/CMakeLists.txt index eb12f1df9..b62a364ab 100644 --- a/libs/Helpers/CMakeLists.txt +++ b/libs/Helpers/CMakeLists.txt @@ -71,5 +71,6 @@ target_sources(Helpers ${CMAKE_CURRENT_SOURCE_DIR}/src/Helpers/helpers.h ${CMAKE_CURRENT_SOURCE_DIR}/src/Helpers/logs.h ${CMAKE_CURRENT_SOURCE_DIR}/src/Helpers/logs.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/Helpers/NamedType.h ${CMAKE_CURRENT_SOURCE_DIR}/src/Helpers/Singleton.h ) diff --git a/libs/Helpers/src/Helpers/NamedType.h b/libs/Helpers/src/Helpers/NamedType.h new file mode 100644 index 000000000..0be388fc9 --- /dev/null +++ b/libs/Helpers/src/Helpers/NamedType.h @@ -0,0 +1,70 @@ +#pragma once + +#include + +#include +#include + +using json = nlohmann::json; + +namespace Status::Helpers { + +template +using IsNotReference = typename std::enable_if::value, void>::type; + +/// Featureless version of https://github.com/joboccara/NamedType that works with nlohmann::json +template +class NamedType +{ +public: + using UnderlyingType = T; + + // constructor + explicit constexpr NamedType(T const& value) : m_value(value) {} + template> + explicit constexpr NamedType(T&& value) : m_value(std::move(value)) {} + explicit constexpr NamedType() = default; + + // get + constexpr T& get() { return m_value; } + constexpr std::remove_reference_t const& get() const {return m_value; } + + bool operator<(const NamedType &) const = default; + bool operator>(const NamedType &) const = default; + bool operator<=(const NamedType &) const = default; + bool operator>=(const NamedType &) const = default; + bool operator==(const NamedType &) const = default; + bool operator!=(const NamedType &) const = default; + +private: + T m_value; +}; + +template +void to_json(json& j, const NamedType& p) { + j = p.get(); +} + +template +void from_json(const json& j, NamedType& p) { + p = NamedType{j.get()}; +} + +} + +namespace std +{ + +template +struct hash> +{ + using NamedType = Status::Helpers::NamedType; + using checkIfHashable = typename std::enable_if::type; + + size_t operator()(NamedType const& x) const + { + return std::hash()(x.get()); + } +}; + +} diff --git a/libs/Helpers/src/Helpers/conversions.cpp b/libs/Helpers/src/Helpers/conversions.cpp index d9c3fd97a..5fc472e32 100644 --- a/libs/Helpers/src/Helpers/conversions.cpp +++ b/libs/Helpers/src/Helpers/conversions.cpp @@ -4,13 +4,8 @@ namespace fs = std::filesystem; namespace Status { -QString toQString(const std::string &str) -{ - return QString::fromStdString(str); -} - QString toQString(const fs::path &path) { - return toQString(path.string()); + return QString::fromStdString(path.string()); } fs::path toPath(const QString &pathStr) { diff --git a/libs/Helpers/src/Helpers/conversions.h b/libs/Helpers/src/Helpers/conversions.h index cf0ca95f6..5c72d7f77 100644 --- a/libs/Helpers/src/Helpers/conversions.h +++ b/libs/Helpers/src/Helpers/conversions.h @@ -12,8 +12,8 @@ using json = nlohmann::json; namespace Status { -QString toQString(const std::string& str); QString toQString(const std::filesystem::path& path); + std::filesystem::path toPath(const QString& pathStr); } // namespace Status @@ -42,4 +42,15 @@ struct adl_serializer { } }; +template +struct adl_serializer> { + static void to_json(json& j, const std::optional& opt) { + j = opt.value(); + } + + static void from_json(const json& j, std::optional& opt) { + opt.emplace(j.get()); + } +}; + } // namespace nlohmann diff --git a/libs/Onboarding/CMakeLists.txt b/libs/Onboarding/CMakeLists.txt index 111d47336..f0be36cfe 100644 --- a/libs/Onboarding/CMakeLists.txt +++ b/libs/Onboarding/CMakeLists.txt @@ -37,6 +37,9 @@ add_subdirectory(src) add_subdirectory(tests) target_link_libraries(Onboarding + PUBLIC + Status::StatusGoQt + PRIVATE Qt6::Quick Qt6::Qml @@ -45,7 +48,6 @@ target_link_libraries(Onboarding Status::ApplicationCore Status::Helpers - Status::StatusGoQt Status::StatusGoConfig ) diff --git a/libs/Onboarding/qml/Status/Onboarding/ConfirmPasswordPage.qml b/libs/Onboarding/qml/Status/Onboarding/ConfirmPasswordPage.qml index 9d13257f0..415264772 100644 --- a/libs/Onboarding/qml/Status/Onboarding/ConfirmPasswordPage.qml +++ b/libs/Onboarding/qml/Status/Onboarding/ConfirmPasswordPage.qml @@ -11,9 +11,6 @@ SetupNewProfilePageBase { TempTextInput { id: confirmPasswordInput - // TODO: remove this developer helper - text: qsTr("1234567890") - width: 416 height: 44 diff --git a/libs/Onboarding/src/Onboarding/Accounts/AccountsService.cpp b/libs/Onboarding/src/Onboarding/Accounts/AccountsService.cpp index 392c666c7..726b59823 100644 --- a/libs/Onboarding/src/Onboarding/Accounts/AccountsService.cpp +++ b/libs/Onboarding/src/Onboarding/Accounts/AccountsService.cpp @@ -26,12 +26,12 @@ getDataFromFile(const fs::path &path) return data; } -namespace Status::Onboarding -{ - namespace StatusGo = Status::StatusGo; namespace Utils = Status::StatusGo::Utils; +namespace Status::Onboarding +{ + AccountsService::AccountsService() : m_isFirstTimeAccountLogin(false) { @@ -49,32 +49,32 @@ bool AccountsService::init(const fs::path& statusgoDataDir) for(const auto &genAddressObj : response.result) { - auto gAcc = GeneratedAccountDto::toGeneratedAccountDto(genAddressObj.toObject()); + auto gAcc = GeneratedMultiAccount::toGeneratedMultiAccount(genAddressObj.toObject()); gAcc.alias = generateAlias(gAcc.derivedAccounts.whisper.publicKey); m_generatedAccounts.push_back(std::move(gAcc)); } return true; } -std::vector AccountsService::openAndListAccounts() +std::vector AccountsService::openAndListAccounts() { auto response = StatusGo::Accounts::openAccounts(m_statusgoDataDir.c_str()); if(response.containsError()) { qWarning() << response.error.message; - return std::vector(); + return std::vector(); } const auto multiAccounts = response.result; - std::vector result; + std::vector result; for(const auto &value : multiAccounts) { - result.push_back(AccountDto::toAccountDto(value.toObject())); + result.push_back(MultiAccount::toMultiAccount(value.toObject())); } return result; } -const std::vector& AccountsService::generatedAccounts() const +const std::vector& AccountsService::generatedAccounts() const { return m_generatedAccounts; } @@ -91,7 +91,7 @@ bool AccountsService::setupAccountAndLogin(const QString &accountId, const QStri QJsonObject settings(getAccountSettings(accountId, installationId, displayName)); QJsonObject nodeConfig(getDefaultNodeConfig(installationId)); - QString hashedPassword(Utils::hashString(password)); + auto hashedPassword(Utils::hashPassword(password)); // This initialize the DB if first time running. Required for storing accounts if(StatusGo::Accounts::openAccounts(m_statusgoDataDir.c_str()).containsError()) @@ -105,12 +105,12 @@ bool AccountsService::setupAccountAndLogin(const QString &accountId, const QStri return getLoggedInAccount().isValid(); } -const AccountDto& AccountsService::getLoggedInAccount() const +const MultiAccount& AccountsService::getLoggedInAccount() const { return m_loggedInAccount; } -const GeneratedAccountDto& AccountsService::getImportedAccount() const +const GeneratedMultiAccount& AccountsService::getImportedAccount() const { return m_importedAccount; } @@ -127,7 +127,7 @@ bool AccountsService::setKeyStoreDir(const QString &key) return !response.containsError(); } -QString AccountsService::login(AccountDto account, const QString& password) +QString AccountsService::login(MultiAccount account, const QString& password) { // This is a requirement. Make it more explicit into the status go module if(!setKeyStoreDir(account.keyUid)) @@ -137,7 +137,7 @@ QString AccountsService::login(AccountDto account, const QString& password) if(StatusGo::Accounts::openAccounts(m_statusgoDataDir.c_str()).containsError()) return QString("Failed to open accounts before logging in"); - QString hashedPassword(Utils::hashString(password)); + auto hashedPassword(Utils::hashPassword(password)); QString thumbnailImage; QString largeImage; @@ -157,8 +157,8 @@ QString AccountsService::login(AccountDto account, const QString& password) void AccountsService::clear() { m_generatedAccounts.clear(); - m_loggedInAccount = AccountDto(); - m_importedAccount = GeneratedAccountDto(); + m_loggedInAccount = MultiAccount(); + m_importedAccount = GeneratedMultiAccount(); m_isFirstTimeAccountLogin = false; } @@ -174,15 +174,15 @@ QString AccountsService::generateAlias(const QString& publicKey) return response.result; } -void AccountsService::deleteMultiAccount(const AccountDto &account) +void AccountsService::deleteMultiAccount(const MultiAccount &account) { StatusGo::Accounts::deleteMultiaccount(account.keyUid, m_keyStoreDir); } -DerivedAccounts AccountsService::storeDerivedAccounts(const QString& accountId, const QString& hashedPassword, - const QVector& paths) +DerivedAccounts AccountsService::storeDerivedAccounts(const QString& accountId, const StatusGo::HashedPassword& password, + const std::vector &paths) { - auto response = StatusGo::Accounts::storeDerivedAccounts(accountId, hashedPassword, paths); + auto response = StatusGo::Accounts::storeDerivedAccounts(accountId, password, paths); if(response.containsError()) { qWarning() << response.error.message; @@ -191,31 +191,31 @@ DerivedAccounts AccountsService::storeDerivedAccounts(const QString& accountId, return DerivedAccounts::toDerivedAccounts(response.result); } -StoredAccountDto AccountsService::storeAccount(const QString& accountId, const QString& hashedPassword) +StoredMultiAccount AccountsService::storeAccount(const QString& accountId, const StatusGo::HashedPassword& password) { - auto response = StatusGo::Accounts::storeAccount(accountId, hashedPassword); + auto response = StatusGo::Accounts::storeAccount(accountId, password); if(response.containsError()) { qWarning() << response.error.message; - return StoredAccountDto(); + return StoredMultiAccount(); } - return toStoredAccountDto(response.result); + return toStoredMultiAccount(response.result); } -AccountDto AccountsService::saveAccountAndLogin(const QString& hashedPassword, const QJsonObject& account, +MultiAccount AccountsService::saveAccountAndLogin(const StatusGo::HashedPassword& password, const QJsonObject& account, const QJsonArray& subaccounts, const QJsonObject& settings, const QJsonObject& config) { - if(!StatusGo::Accounts::saveAccountAndLogin(hashedPassword, account, subaccounts, settings, config)) { + if(!StatusGo::Accounts::saveAccountAndLogin(password, account, subaccounts, settings, config)) { qWarning() << "Failed saving acccount" << account.value("name"); - return AccountDto(); + return MultiAccount(); } m_isFirstTimeAccountLogin = true; - return AccountDto::toAccountDto(account); + return MultiAccount::toMultiAccount(account); } -QJsonObject AccountsService::prepareAccountJsonObject(const GeneratedAccountDto& account, const QString &displayName) const +QJsonObject AccountsService::prepareAccountJsonObject(const GeneratedMultiAccount& account, const QString &displayName) const { return QJsonObject{{"name", displayName.isEmpty() ? account.alias : displayName}, {"address", account.address}, @@ -225,7 +225,7 @@ QJsonObject AccountsService::prepareAccountJsonObject(const GeneratedAccountDto& QJsonObject AccountsService::getAccountDataForAccountId(const QString &accountId, const QString &displayName) const { - for(const GeneratedAccountDto &acc : m_generatedAccounts) + for(const GeneratedMultiAccount &acc : m_generatedAccounts) { if(acc.id == accountId) { @@ -245,7 +245,7 @@ QJsonObject AccountsService::getAccountDataForAccountId(const QString &accountId return QJsonObject(); } -QJsonArray AccountsService::prepareSubaccountJsonObject(const GeneratedAccountDto& account, const QString &displayName) const +QJsonArray AccountsService::prepareSubaccountJsonObject(const GeneratedMultiAccount& account, const QString &displayName) const { return { QJsonObject{ @@ -253,7 +253,7 @@ QJsonArray AccountsService::prepareSubaccountJsonObject(const GeneratedAccountDt {"address", account.derivedAccounts.defaultWallet.address}, {"color", "#4360df"}, {"wallet", true}, - {"path", Constants::General::PathDefaultWallet}, + {"path", Constants::General::PathDefaultWallet.get()}, {"name", "Status account"}, {"derived-from", account.address} }, @@ -261,7 +261,7 @@ QJsonArray AccountsService::prepareSubaccountJsonObject(const GeneratedAccountDt {"public-key", account.derivedAccounts.whisper.publicKey}, {"address", account.derivedAccounts.whisper.address}, {"name", displayName.isEmpty() ? account.alias : displayName}, - {"path", Constants::General::PathWhisper}, + {"path", Constants::General::PathWhisper.get()}, {"chat", true}, {"derived-from", ""} } @@ -271,7 +271,7 @@ QJsonArray AccountsService::prepareSubaccountJsonObject(const GeneratedAccountDt QJsonArray AccountsService::getSubaccountDataForAccountId(const QString& accountId, const QString &displayName) const { // "All these for loops with a nested if cry for a std::find_if :)" - for(const GeneratedAccountDto &acc : m_generatedAccounts) + for(const GeneratedMultiAccount &acc : m_generatedAccounts) { if(acc.id == accountId) { @@ -302,7 +302,7 @@ QString AccountsService::generateSigningPhrase(int count) const return words.join(" "); } -QJsonObject AccountsService::prepareAccountSettingsJsonObject(const GeneratedAccountDto& account, +QJsonObject AccountsService::prepareAccountSettingsJsonObject(const GeneratedMultiAccount& account, const QString& installationId, const QString& displayName) const { @@ -348,7 +348,7 @@ QJsonObject AccountsService::prepareAccountSettingsJsonObject(const GeneratedAcc QJsonObject AccountsService::getAccountSettings(const QString& accountId, const QString& installationId, const QString &displayName) const { - for(const GeneratedAccountDto &acc : m_generatedAccounts) + for(const GeneratedMultiAccount &acc : m_generatedAccounts) if(acc.id == accountId) { diff --git a/libs/Onboarding/src/Onboarding/Accounts/AccountsService.h b/libs/Onboarding/src/Onboarding/Accounts/AccountsService.h index 6642052a0..10893e669 100644 --- a/libs/Onboarding/src/Onboarding/Accounts/AccountsService.h +++ b/libs/Onboarding/src/Onboarding/Accounts/AccountsService.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "AccountsServiceInterface.h" namespace Status::Onboarding @@ -25,18 +27,18 @@ public: bool init(const fs::path& statusgoDataDir) override; /// \see ServiceInterface - [[nodiscard]] std::vector openAndListAccounts() override; + [[nodiscard]] std::vector openAndListAccounts() override; /// \see ServiceInterface - [[nodiscard]] const std::vector& generatedAccounts() const override; + [[nodiscard]] const std::vector& generatedAccounts() const override; /// \see ServiceInterface bool setupAccountAndLogin(const QString& accountId, const QString& password, const QString& displayName) override; /// \see ServiceInterface - [[nodiscard]] const AccountDto& getLoggedInAccount() const override; + [[nodiscard]] const MultiAccount& getLoggedInAccount() const override; - [[nodiscard]] const GeneratedAccountDto& getImportedAccount() const override; + [[nodiscard]] const GeneratedMultiAccount& getImportedAccount() const override; /// \see ServiceInterface [[nodiscard]] bool isFirstTimeAccountLogin() const override; @@ -44,34 +46,34 @@ public: /// \see ServiceInterface bool setKeyStoreDir(const QString &key) override; - QString login(AccountDto account, const QString& password) override; + QString login(MultiAccount account, const QString& password) override; void clear() override; QString generateAlias(const QString& publicKey) override; - void deleteMultiAccount(const AccountDto &account) override; + void deleteMultiAccount(const MultiAccount &account) override; private: - QJsonObject prepareAccountJsonObject(const GeneratedAccountDto& account, const QString& displayName) const; + QJsonObject prepareAccountJsonObject(const GeneratedMultiAccount& account, const QString& displayName) const; - DerivedAccounts storeDerivedAccounts(const QString& accountId, const QString& hashedPassword, - const QVector& paths); - StoredAccountDto storeAccount(const QString& accountId, const QString& hashedPassword); + DerivedAccounts storeDerivedAccounts(const QString& accountId, const StatusGo::HashedPassword& password, + const std::vector& paths); + StoredMultiAccount storeAccount(const QString& accountId, const StatusGo::HashedPassword& password); - AccountDto saveAccountAndLogin(const QString& hashedPassword, const QJsonObject& account, + MultiAccount saveAccountAndLogin(const StatusGo::HashedPassword& password, const QJsonObject& account, const QJsonArray& subaccounts, const QJsonObject& settings, const QJsonObject& config); QJsonObject getAccountDataForAccountId(const QString& accountId, const QString& displayName) const; - QJsonArray prepareSubaccountJsonObject(const GeneratedAccountDto& account, const QString& displayName) const; + QJsonArray prepareSubaccountJsonObject(const GeneratedMultiAccount& account, const QString& displayName) const; QJsonArray getSubaccountDataForAccountId(const QString& accountId, const QString& displayName) const; QString generateSigningPhrase(int count) const; - QJsonObject prepareAccountSettingsJsonObject(const GeneratedAccountDto& account, + QJsonObject prepareAccountSettingsJsonObject(const GeneratedMultiAccount& account, const QString& installationId, const QString& displayName) const; @@ -80,14 +82,14 @@ private: QJsonObject getDefaultNodeConfig(const QString& installationId) const; private: - std::vector m_generatedAccounts; + std::vector m_generatedAccounts; fs::path m_statusgoDataDir; fs::path m_keyStoreDir; bool m_isFirstTimeAccountLogin; // TODO: don't see the need for this state here - AccountDto m_loggedInAccount; - GeneratedAccountDto m_importedAccount; + MultiAccount m_loggedInAccount; + GeneratedMultiAccount m_importedAccount; // Here for now. Extract them if used by other services static constexpr auto m_keyStoreDirName = "keystore"; diff --git a/libs/Onboarding/src/Onboarding/Accounts/AccountsServiceInterface.h b/libs/Onboarding/src/Onboarding/Accounts/AccountsServiceInterface.h index fbc609396..c8887ff08 100644 --- a/libs/Onboarding/src/Onboarding/Accounts/AccountsServiceInterface.h +++ b/libs/Onboarding/src/Onboarding/Accounts/AccountsServiceInterface.h @@ -1,7 +1,7 @@ #pragma once -#include "AccountDto.h" -#include "GeneratedAccountDto.h" +#include "MultiAccount.h" +#include "GeneratedMultiAccount.h" #include @@ -20,18 +20,18 @@ public: virtual bool init(const fs::path& statusgoDataDir) = 0; /// opens database and returns accounts list. - [[nodiscard]] virtual std::vector openAndListAccounts() = 0; + [[nodiscard]] virtual std::vector openAndListAccounts() = 0; /// Retrieve cached accounts generated in \c init - [[nodiscard]] virtual const std::vector& generatedAccounts() const = 0; + [[nodiscard]] virtual const std::vector& generatedAccounts() const = 0; /// Configure an generated account. \a accountID must be sourced from \c generatedAccounts virtual bool setupAccountAndLogin(const QString& accountID, const QString& password, const QString& displayName) = 0; /// Account that is currently logged-in - [[nodiscard]] virtual const AccountDto& getLoggedInAccount() const = 0; + [[nodiscard]] virtual const MultiAccount& getLoggedInAccount() const = 0; - [[nodiscard]] virtual const GeneratedAccountDto& getImportedAccount() const = 0; + [[nodiscard]] virtual const GeneratedMultiAccount& getImportedAccount() const = 0; /// Check if the login was never done in the current \c data directory [[nodiscard]] virtual bool isFirstTimeAccountLogin() const = 0; @@ -39,13 +39,13 @@ public: /// Set and initializes the keystore directory. \see StatusGo::General::initKeystore virtual bool setKeyStoreDir(const QString &key) = 0; - virtual QString login(AccountDto account, const QString& password) = 0; + virtual QString login(MultiAccount account, const QString& password) = 0; virtual void clear() = 0; virtual QString generateAlias(const QString& publicKey) = 0; - virtual void deleteMultiAccount(const AccountDto &account) = 0; + virtual void deleteMultiAccount(const MultiAccount &account) = 0; }; using AccountsServiceInterfacePtr = std::shared_ptr; diff --git a/libs/Onboarding/src/Onboarding/Accounts/GeneratedAccountDto.h b/libs/Onboarding/src/Onboarding/Accounts/GeneratedMultiAccount.h similarity index 87% rename from libs/Onboarding/src/Onboarding/Accounts/GeneratedAccountDto.h rename to libs/Onboarding/src/Onboarding/Accounts/GeneratedMultiAccount.h index 37aa54186..00c3cdc31 100644 --- a/libs/Onboarding/src/Onboarding/Accounts/GeneratedAccountDto.h +++ b/libs/Onboarding/src/Onboarding/Accounts/GeneratedMultiAccount.h @@ -50,19 +50,19 @@ struct DerivedAccounts for(const auto &derivationPath : jsonObj.keys()) { auto derivedObj = jsonObj.value(derivationPath).toObject(); - if(derivationPath == Constants::General::PathWhisper) + if(derivationPath == Constants::General::PathWhisper.get()) { result.whisper = DerivedAccountDetails::toDerivedAccountDetails(derivedObj, derivationPath); } - else if(derivationPath == Constants::General::PathWalletRoot) + else if(derivationPath == Constants::General::PathWalletRoot.get()) { result.walletRoot = DerivedAccountDetails::toDerivedAccountDetails(derivedObj, derivationPath); } - else if(derivationPath == Constants::General::PathDefaultWallet) + else if(derivationPath == Constants::General::PathDefaultWallet.get()) { result.defaultWallet = DerivedAccountDetails::toDerivedAccountDetails(derivedObj, derivationPath); } - else if(derivationPath == Constants::General::PathEIP1581) + else if(derivationPath == Constants::General::PathEIP1581.get()) { result.eip1581 = DerivedAccountDetails::toDerivedAccountDetails(derivedObj, derivationPath); } @@ -72,28 +72,28 @@ struct DerivedAccounts } }; -struct StoredAccountDto +struct StoredMultiAccount { QString publicKey; QString address; }; -static StoredAccountDto toStoredAccountDto(const QJsonObject& jsonObj) +static StoredMultiAccount toStoredMultiAccount(const QJsonObject& jsonObj) { - auto result = StoredAccountDto(); + auto result = StoredMultiAccount(); try { result.address = Json::getMandatoryProp(jsonObj, "address")->toString(); result.publicKey = Json::getMandatoryProp(jsonObj, "publicKey")->toString(); } catch (std::exception e) { - qWarning() << QString("Mapping StoredAccountDto failed: %1").arg(e.what()); + qWarning() << QString("Mapping StoredMultiAccount failed: %1").arg(e.what()); } return result; } -struct GeneratedAccountDto +struct GeneratedMultiAccount { QString id; QString publicKey; @@ -110,9 +110,9 @@ struct GeneratedAccountDto return !(id.isEmpty() || publicKey.isEmpty() || address.isEmpty() || keyUid.isEmpty()); } - static GeneratedAccountDto toGeneratedAccountDto(const QJsonObject& jsonObj) + static GeneratedMultiAccount toGeneratedMultiAccount(const QJsonObject& jsonObj) { - auto result = GeneratedAccountDto(); + auto result = GeneratedMultiAccount(); try { @@ -130,7 +130,7 @@ struct GeneratedAccountDto } catch (std::exception e) { - qWarning() << QString("Mapping GeneratedAccountDto failed: %1").arg(e.what()); + qWarning() << QString("Mapping GeneratedMultiAccount failed: %1").arg(e.what()); } return result; diff --git a/libs/Onboarding/src/Onboarding/Accounts/AccountDto.h b/libs/Onboarding/src/Onboarding/Accounts/MultiAccount.h similarity index 69% rename from libs/Onboarding/src/Onboarding/Accounts/AccountDto.h rename to libs/Onboarding/src/Onboarding/Accounts/MultiAccount.h index 69fe1df6a..8e2dbcc18 100644 --- a/libs/Onboarding/src/Onboarding/Accounts/AccountDto.h +++ b/libs/Onboarding/src/Onboarding/Accounts/MultiAccount.h @@ -4,14 +4,18 @@ #include "Common/SigningPhrases.h" #include "Common/Json.h" +#include + #include +namespace Accounts = Status::StatusGo::Accounts; + // TODO: Move to StatusGo library namespace Status::Onboarding { -// TODO: refactor it to MultiAccount -struct AccountDto +/// \note equivalent of status-go's multiaccounts.Account@multiaccounts/database.go +struct MultiAccount { QString name; long timestamp; @@ -20,16 +24,16 @@ struct AccountDto // TODO images // TODO colorHash // TODO colorId - QString address; + Accounts::EOAddress address; bool isValid() const { return !(name.isEmpty() || keyUid.isEmpty()); } - static AccountDto toAccountDto(const QJsonObject& jsonObj) + static MultiAccount toMultiAccount(const QJsonObject& jsonObj) { - auto result = AccountDto(); + auto result = MultiAccount(); try { @@ -43,13 +47,13 @@ struct AccountDto } result.keycardPairing = Json::getMandatoryProp(jsonObj, "keycard-pairing")->toString(); result.keyUid = Json::getMandatoryProp(jsonObj, "key-uid")->toString(); - result.address = Json::getProp(jsonObj, "address")->toString(); + result.address = Accounts::EOAddress(Json::getProp(jsonObj, "address")->toString()); /// TODO: investigate unhandled `photo-path` value } catch (std::exception e) { - qWarning() << QObject::tr("Mapping AccountDto failed: %1").arg(e.what()); + qWarning() << QString("Mapping MultiAccount failed: %1").arg(e.what()); } return result; diff --git a/libs/Onboarding/src/Onboarding/CMakeLists.txt b/libs/Onboarding/src/Onboarding/CMakeLists.txt index c65abf4cb..8e74519db 100644 --- a/libs/Onboarding/src/Onboarding/CMakeLists.txt +++ b/libs/Onboarding/src/Onboarding/CMakeLists.txt @@ -6,8 +6,8 @@ target_sources(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/UserAccount.h ${CMAKE_CURRENT_SOURCE_DIR}/UserAccountsModel.h - ${CMAKE_CURRENT_SOURCE_DIR}/Accounts/AccountDto.h - ${CMAKE_CURRENT_SOURCE_DIR}/Accounts/GeneratedAccountDto.h + ${CMAKE_CURRENT_SOURCE_DIR}/Accounts/MultiAccount.h + ${CMAKE_CURRENT_SOURCE_DIR}/Accounts/GeneratedMultiAccount.h ${CMAKE_CURRENT_SOURCE_DIR}/Accounts/AccountsService.h ${CMAKE_CURRENT_SOURCE_DIR}/Accounts/AccountsServiceInterface.h diff --git a/libs/Onboarding/src/Onboarding/Common/Constants.h b/libs/Onboarding/src/Onboarding/Common/Constants.h index 11a3f2dc8..6597150bd 100644 --- a/libs/Onboarding/src/Onboarding/Common/Constants.h +++ b/libs/Onboarding/src/Onboarding/Common/Constants.h @@ -1,8 +1,12 @@ #pragma once +#include + #include #include +namespace Accounts = Status::StatusGo::Accounts; + namespace Status::Constants { @@ -34,15 +38,15 @@ namespace General inline const auto ZeroAddress = u"0x0000000000000000000000000000000000000000"_qs; - inline const auto PathWalletRoot = u"m/44'/60'/0'/0"_qs; + inline const Accounts::DerivationPath PathWalletRoot{u"m/44'/60'/0'/0"_qs}; // EIP1581 Root Key, the extended key from which any whisper key/encryption key can be derived - inline const auto PathEIP1581 = u"m/43'/60'/1581'"_qs; + inline const Accounts::DerivationPath PathEIP1581{u"m/43'/60'/1581'"_qs}; // BIP44-0 Wallet key, the default wallet key - inline const auto PathDefaultWallet = PathWalletRoot + u"/0"_qs; + inline const Accounts::DerivationPath PathDefaultWallet{PathWalletRoot.get() + u"/0"_qs}; // EIP1581 Chat Key 0, the default whisper key - inline const auto PathWhisper = PathEIP1581 + u"/0'/0"_qs; + inline const Accounts::DerivationPath PathWhisper{PathEIP1581.get() + u"/0'/0"_qs}; - inline const QVector AccountDefaultPaths {PathWalletRoot, PathEIP1581, PathWhisper, PathDefaultWallet}; + inline const std::vector AccountDefaultPaths {PathWalletRoot, PathEIP1581, PathWhisper, PathDefaultWallet}; } } diff --git a/libs/Onboarding/src/Onboarding/NewAccountController.h b/libs/Onboarding/src/Onboarding/NewAccountController.h index ea2e26d3a..cf3856c73 100644 --- a/libs/Onboarding/src/Onboarding/NewAccountController.h +++ b/libs/Onboarding/src/Onboarding/NewAccountController.h @@ -3,7 +3,7 @@ #include "UserAccountsModel.h" #include "Accounts/AccountsServiceInterface.h" -#include "Accounts/AccountDto.h" +#include "Accounts/MultiAccount.h" #include diff --git a/libs/Onboarding/src/Onboarding/OnboardingController.cpp b/libs/Onboarding/src/Onboarding/OnboardingController.cpp index addbc4d58..8dd80f303 100644 --- a/libs/Onboarding/src/Onboarding/OnboardingController.cpp +++ b/libs/Onboarding/src/Onboarding/OnboardingController.cpp @@ -17,7 +17,7 @@ OnboardingController::OnboardingController(AccountsServiceInterfacePtr accountsS { // Init accounts std::vector> accounts; for(auto &account : getOpenedAccounts()) { - accounts.push_back(std::make_shared(std::make_unique(std::move(account)))); + accounts.push_back(std::make_shared(std::make_unique(std::move(account)))); } m_accounts = std::make_shared(std::move(accounts)); } @@ -38,7 +38,7 @@ void OnboardingController::onLogin(const QString& error) emit accountLoginError(error); } -std::vector OnboardingController::getOpenedAccounts() const +std::vector OnboardingController::getOpenedAccounts() const { return m_accountsService->openAndListAccounts(); } diff --git a/libs/Onboarding/src/Onboarding/OnboardingController.h b/libs/Onboarding/src/Onboarding/OnboardingController.h index 665ad187b..a8fca1a59 100644 --- a/libs/Onboarding/src/Onboarding/OnboardingController.h +++ b/libs/Onboarding/src/Onboarding/OnboardingController.h @@ -2,7 +2,7 @@ #include "UserAccountsModel.h" -#include "Accounts/AccountDto.h" +#include "Accounts/MultiAccount.h" #include #include @@ -38,7 +38,7 @@ public: ~OnboardingController(); /// Retrieve available accounts - std::vector getOpenedAccounts() const; + std::vector getOpenedAccounts() const; /// Login user account /// TODO: \a user should be of type \c UserAccount but this doesn't work with Qt6 CMake API. Investigate and fix later on diff --git a/libs/Onboarding/src/Onboarding/UserAccount.cpp b/libs/Onboarding/src/Onboarding/UserAccount.cpp index be4541311..7bc6d9f62 100644 --- a/libs/Onboarding/src/Onboarding/UserAccount.cpp +++ b/libs/Onboarding/src/Onboarding/UserAccount.cpp @@ -1,12 +1,11 @@ #include "UserAccount.h" -#include "Accounts/AccountDto.h" - +#include "Accounts/MultiAccount.h" namespace Status::Onboarding { -UserAccount::UserAccount(std::unique_ptr data) +UserAccount::UserAccount(std::unique_ptr data) : QObject() , m_data(std::move(data)) { @@ -18,12 +17,12 @@ const QString &UserAccount::name() const return m_data->name; } -const AccountDto &UserAccount::accountData() const +const MultiAccount &UserAccount::accountData() const { return *m_data; } -void UserAccount::updateAccountData(const AccountDto& newData) +void UserAccount::updateAccountData(const MultiAccount& newData) { std::vector> notifyUpdates; diff --git a/libs/Onboarding/src/Onboarding/UserAccount.h b/libs/Onboarding/src/Onboarding/UserAccount.h index 1a2fafaff..aaad40d5c 100644 --- a/libs/Onboarding/src/Onboarding/UserAccount.h +++ b/libs/Onboarding/src/Onboarding/UserAccount.h @@ -5,7 +5,7 @@ namespace Status::Onboarding { -class AccountDto; +class MultiAccount; /*! * \brief Represents a user account in Onboarding Presentation Layer @@ -21,18 +21,18 @@ class UserAccount: public QObject Q_PROPERTY(QString name READ name NOTIFY nameChanged) public: - explicit UserAccount(std::unique_ptr data); + explicit UserAccount(std::unique_ptr data); const QString &name() const; - const AccountDto& accountData() const; - void updateAccountData(const AccountDto& newData); + const MultiAccount& accountData() const; + void updateAccountData(const MultiAccount& newData); signals: void nameChanged(); private: - std::unique_ptr m_data; + std::unique_ptr m_data; }; } diff --git a/libs/Onboarding/tests/CMakeLists.txt b/libs/Onboarding/tests/CMakeLists.txt index 5445ad9be..8e02dd4d5 100644 --- a/libs/Onboarding/tests/CMakeLists.txt +++ b/libs/Onboarding/tests/CMakeLists.txt @@ -41,12 +41,8 @@ target_link_libraries(${PROJECT_NAME} Status::OnboardingTestHelpers Status::Onboarding - - # TODO tmp - Status::StatusGoQt ) - include(GoogleTest) gtest_add_tests( TARGET ${PROJECT_NAME} diff --git a/libs/Onboarding/tests/OnboardingTestHelpers/ScopedTestAccount.cpp b/libs/Onboarding/tests/OnboardingTestHelpers/ScopedTestAccount.cpp index 76c37a498..b8a1a1024 100644 --- a/libs/Onboarding/tests/OnboardingTestHelpers/ScopedTestAccount.cpp +++ b/libs/Onboarding/tests/OnboardingTestHelpers/ScopedTestAccount.cpp @@ -110,7 +110,7 @@ void ScopedTestAccount::logOut() throw std::runtime_error("ScopedTestAccount - failed logging out"); } -Accounts::MultiAccount ScopedTestAccount::firstChatAccount() +Accounts::ChatOrWalletAccount ScopedTestAccount::firstChatAccount() { auto accounts = Accounts::getAccounts(); auto chatIt = std::find_if(accounts.begin(), accounts.end(), [](const auto& a) { @@ -121,7 +121,7 @@ Accounts::MultiAccount ScopedTestAccount::firstChatAccount() return *chatIt; } -Accounts::MultiAccount ScopedTestAccount::firstWalletAccount() +Accounts::ChatOrWalletAccount ScopedTestAccount::firstWalletAccount() { auto accounts = Accounts::getAccounts(); auto walletIt = std::find_if(accounts.begin(), accounts.end(), [](const auto& a) { diff --git a/libs/Onboarding/tests/OnboardingTestHelpers/ScopedTestAccount.h b/libs/Onboarding/tests/OnboardingTestHelpers/ScopedTestAccount.h index 015acca96..5ddeed7e3 100644 --- a/libs/Onboarding/tests/OnboardingTestHelpers/ScopedTestAccount.h +++ b/libs/Onboarding/tests/OnboardingTestHelpers/ScopedTestAccount.h @@ -36,8 +36,8 @@ public: void processMessages(size_t millis, std::function shouldWaitUntilTimeout); void logOut(); - static Accounts::MultiAccount firstChatAccount(); - static Accounts::MultiAccount firstWalletAccount(); + static Accounts::ChatOrWalletAccount firstChatAccount(); + static Accounts::ChatOrWalletAccount firstWalletAccount(); QString password() const { return m_accountPassword; }; diff --git a/libs/Onboarding/tests/ServiceMock.h b/libs/Onboarding/tests/ServiceMock.h index 1a3fd5a10..937077399 100644 --- a/libs/Onboarding/tests/ServiceMock.h +++ b/libs/Onboarding/tests/ServiceMock.h @@ -21,17 +21,17 @@ public: virtual ~AccountsServiceMock() override {}; MOCK_METHOD(bool, init, (const fs::path&), (override)); - MOCK_METHOD(std::vector, openAndListAccounts, (), (override)); - MOCK_METHOD(const std::vector&, generatedAccounts, (), (const, override)); + MOCK_METHOD(std::vector, openAndListAccounts, (), (override)); + MOCK_METHOD(const std::vector&, generatedAccounts, (), (const, override)); MOCK_METHOD(bool, setupAccountAndLogin, (const QString&, const QString&, const QString&), (override)); - MOCK_METHOD(const Onboarding::AccountDto&, getLoggedInAccount, (), (const, override)); - MOCK_METHOD(const Onboarding::GeneratedAccountDto&, getImportedAccount, (), (const, override)); + MOCK_METHOD(const Onboarding::MultiAccount&, getLoggedInAccount, (), (const, override)); + MOCK_METHOD(const Onboarding::GeneratedMultiAccount&, getImportedAccount, (), (const, override)); MOCK_METHOD(bool, isFirstTimeAccountLogin, (), (const, override)); MOCK_METHOD(bool, setKeyStoreDir, (const QString&), (override)); - MOCK_METHOD(QString, login, (Onboarding::AccountDto, const QString&), (override)); + MOCK_METHOD(QString, login, (Onboarding::MultiAccount, const QString&), (override)); MOCK_METHOD(void, clear, (), (override)); MOCK_METHOD(QString, generateAlias, (const QString&), (override)); - MOCK_METHOD(void, deleteMultiAccount, (const Onboarding::AccountDto&), (override)); + MOCK_METHOD(void, deleteMultiAccount, (const Onboarding::MultiAccount&), (override)); }; } diff --git a/libs/StatusGoQt/CMakeLists.txt b/libs/StatusGoQt/CMakeLists.txt index 89efbd78e..5cf6ebf52 100644 --- a/libs/StatusGoQt/CMakeLists.txt +++ b/libs/StatusGoQt/CMakeLists.txt @@ -18,7 +18,6 @@ add_library(${PROJECT_NAME} SHARED) # Use by linker only set_property(GLOBAL PROPERTY DEBUG_CONFIGURATIONS Debug) -# TODO: consider adding a private header for parsing and keep json dependency away!? target_link_libraries(${PROJECT_NAME} PUBLIC Status::Helpers @@ -76,10 +75,11 @@ target_sources(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/src/StatusGo/Accounts/Accounts.h ${CMAKE_CURRENT_SOURCE_DIR}/src/StatusGo/Accounts/Accounts.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/StatusGo/Accounts/accounts_types.h ${CMAKE_CURRENT_SOURCE_DIR}/src/StatusGo/Accounts/AccountsAPI.h ${CMAKE_CURRENT_SOURCE_DIR}/src/StatusGo/Accounts/AccountsAPI.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/StatusGo/Accounts/MultiAccount.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/StatusGo/Accounts/MultiAccount.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/StatusGo/Accounts/ChatOrWalletAccount.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/StatusGo/Accounts/ChatOrWalletAccount.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/StatusGo/Messenger/Service.h ${CMAKE_CURRENT_SOURCE_DIR}/src/StatusGo/Messenger/Service.cpp diff --git a/libs/StatusGoQt/src/StatusGo/Accounts/Accounts.cpp b/libs/StatusGoQt/src/StatusGo/Accounts/Accounts.cpp index 8c725fea7..2a133ce9e 100644 --- a/libs/StatusGoQt/src/StatusGo/Accounts/Accounts.cpp +++ b/libs/StatusGoQt/src/StatusGo/Accounts/Accounts.cpp @@ -9,7 +9,7 @@ const int MNEMONIC_PHRASE_LENGTH = 12; namespace Status::StatusGo::Accounts { -RpcResponse generateAddresses(const QVector& paths) +RpcResponse generateAddresses(const std::vector& paths) { QJsonObject payload{ {"n", NUMBER_OF_ADDRESSES_TO_GENERATE}, @@ -64,13 +64,12 @@ RpcResponse generateAlias(const QString& publicKey) } } -RpcResponse storeDerivedAccounts(const QString& id, const QString& hashedPassword, - const QVector& paths) +RpcResponse storeDerivedAccounts(const QString& id, const HashedPassword& password, const std::vector& paths) { QJsonObject payload{ {"accountID", id}, {"paths", Utils::toJsonArray(paths)}, - {"password", hashedPassword} + {"password", password.get()} }; try @@ -101,11 +100,11 @@ RpcResponse storeDerivedAccounts(const QString& id, const QString& } } -RpcResponse storeAccount(const QString& id, const QString& hashedPassword) +RpcResponse storeAccount(const QString& id, const HashedPassword& password) { QJsonObject payload{ {"accountID", id}, - {"password", hashedPassword} + {"password", password.get()} }; try @@ -136,14 +135,14 @@ RpcResponse storeAccount(const QString& id, const QString& hashedPa } } -bool saveAccountAndLogin(const QString& hashedPassword, const QJsonObject& account, +bool saveAccountAndLogin(const HashedPassword& password, const QJsonObject& account, const QJsonArray& subaccounts, const QJsonObject& settings, const QJsonObject& nodeConfig) { try { auto result = SaveAccountAndLogin(Utils::jsonToByteArray(account).data(), - hashedPassword.toUtf8().data(), + password.get().toUtf8().data(), Utils::jsonToByteArray(settings).data(), Utils::jsonToByteArray(nodeConfig).data(), Utils::jsonToByteArray(subaccounts).data()); @@ -193,7 +192,7 @@ RpcResponse openAccounts(const char* dataDirPath) } } -RpcResponse login(const QString& name, const QString& keyUid, const QString& hashedPassword, +RpcResponse login(const QString& name, const QString& keyUid, const HashedPassword& password, const QString& thumbnail, const QString& large) { QJsonObject payload{ @@ -210,7 +209,7 @@ RpcResponse login(const QString& name, const QString& keyUid, const try { auto payloadData = Utils::jsonToByteArray(std::move(payload)); - auto result = Login(payloadData.data(), hashedPassword.toUtf8().data()); + auto result = Login(payloadData.data(), password.get().toUtf8().data()); QJsonObject jsonResult; if(!Utils::checkReceivedResponse(result, jsonResult)) { @@ -234,7 +233,7 @@ RpcResponse login(const QString& name, const QString& keyUid, const } } -RpcResponse loginWithConfig(const QString& name, const QString& keyUid, const QString& hashedPassword, +RpcResponse loginWithConfig(const QString& name, const QString& keyUid, const HashedPassword& password, const QString& thumbnail, const QString& large, const QJsonObject& nodeConfig) { QJsonObject payload{ @@ -252,7 +251,7 @@ RpcResponse loginWithConfig(const QString& name, const QString& key { auto payloadData = Utils::jsonToByteArray(std::move(payload)); auto nodeConfigData = Utils::jsonToByteArray(nodeConfig); - auto result = LoginWithConfig(payloadData.data(), hashedPassword.toUtf8().data(), nodeConfigData.data()); + auto result = LoginWithConfig(payloadData.data(), password.get().toUtf8().data(), nodeConfigData.data()); QJsonObject jsonResult; if(!Utils::checkReceivedResponse(result, jsonResult)) { diff --git a/libs/StatusGoQt/src/StatusGo/Accounts/Accounts.h b/libs/StatusGoQt/src/StatusGo/Accounts/Accounts.h index c4c76ece9..522426b13 100644 --- a/libs/StatusGoQt/src/StatusGo/Accounts/Accounts.h +++ b/libs/StatusGoQt/src/StatusGo/Accounts/Accounts.h @@ -1,31 +1,31 @@ #pragma once #include "Types.h" +#include "accounts_types.h" #include namespace Status::StatusGo::Accounts { - RpcResponse generateAddresses(const QVector& paths); + RpcResponse generateAddresses(const std::vector &paths); RpcResponse generateAlias(const QString& publicKey); - RpcResponse storeDerivedAccounts(const QString& accountId, const QString& hashedPassword, - const QVector& paths); + RpcResponse storeDerivedAccounts(const QString& accountId, const HashedPassword& password, + const std::vector& paths); - RpcResponse storeAccount(const QString& id, const QString& hashedPassword); + RpcResponse storeAccount(const QString& id, const HashedPassword& password); - bool saveAccountAndLogin(const QString& hashedPassword, const QJsonObject& account, - const QJsonArray& subaccounts, const QJsonObject& settings, - const QJsonObject& nodeConfig); + bool saveAccountAndLogin(const StatusGo::HashedPassword& password, const QJsonObject& account, + const QJsonArray& subaccounts, const QJsonObject& settings, + const QJsonObject& nodeConfig); /// opens database and returns accounts list. RpcResponse openAccounts(const char* dataDirPath); - /// TODO harmonise password parameters (hashed or plain)? - RpcResponse login(const QString& name, const QString& keyUid, const QString& hashedPassword, + RpcResponse login(const QString& name, const QString& keyUid, const HashedPassword& password, const QString& thumbnail, const QString& large); - RpcResponse loginWithConfig(const QString& name, const QString& keyUid, const QString& hashedPassword, + RpcResponse loginWithConfig(const QString& name, const QString& keyUid, const HashedPassword& password, const QString& thumbnail, const QString& large, const QJsonObject& nodeConfig); RpcResponse logout(); } diff --git a/libs/StatusGoQt/src/StatusGo/Accounts/AccountsAPI.cpp b/libs/StatusGoQt/src/StatusGo/Accounts/AccountsAPI.cpp index fc4ed76f4..33964fa0f 100644 --- a/libs/StatusGoQt/src/StatusGo/Accounts/AccountsAPI.cpp +++ b/libs/StatusGoQt/src/StatusGo/Accounts/AccountsAPI.cpp @@ -14,7 +14,7 @@ using json = nlohmann::json; namespace Status::StatusGo::Accounts { -Accounts::MultiAccounts getAccounts() { +Accounts::ChatOrWalletAccounts getAccounts() { // or even nicer with a raw string literal json inputJson = { {"jsonrpc", "2.0"}, @@ -29,10 +29,10 @@ Accounts::MultiAccounts getAccounts() { return resultJson.get().result; } -void generateAccountWithDerivedPath(const QString &hashedPassword, const QString &name, const QColor &color, const QString &emoji, - const QString &path, const QString &derivedFrom) +void generateAccountWithDerivedPath(const HashedPassword &password, const QString &name, const QColor &color, const QString &emoji, + const DerivationPath &path, const EOAddress &derivedFrom) { - std::vector params = {hashedPassword, name, color, emoji, path, derivedFrom}; + std::vector params = {password, name, color, emoji, path, derivedFrom}; json inputJson = { {"jsonrpc", "2.0"}, {"method", "accounts_generateAccountWithDerivedPath"}, @@ -44,10 +44,10 @@ void generateAccountWithDerivedPath(const QString &hashedPassword, const QString checkPrivateRpcCallResultAndReportError(resultJson); } -void addAccountWithMnemonicAndPath(const QString &mnemonic, const QString &hashedPassword, const QString &name, - const QColor &color, const QString &emoji, const QString &path) +void addAccountWithMnemonicAndPath(const QString &mnemonic, const HashedPassword &password, const QString &name, + const QColor &color, const QString &emoji, const DerivationPath &path) { - std::vector params = {mnemonic, hashedPassword, name, color, emoji, path}; + std::vector params = {mnemonic, password, name, color, emoji, path}; json inputJson = { {"jsonrpc", "2.0"}, {"method", "accounts_addAccountWithMnemonicAndPath"}, @@ -59,7 +59,7 @@ void addAccountWithMnemonicAndPath(const QString &mnemonic, const QString &hashe checkPrivateRpcCallResultAndReportError(resultJson); } -void addAccountWatch(const QString &address, const QString &name, const QColor &color, const QString &emoji) +void addAccountWatch(const EOAddress &address, const QString &name, const QColor &color, const QString &emoji) { std::vector params = {address, name, color, emoji}; json inputJson = { @@ -73,7 +73,7 @@ void addAccountWatch(const QString &address, const QString &name, const QColor & checkPrivateRpcCallResultAndReportError(resultJson); } -void deleteAccount(const QString &address) +void deleteAccount(const EOAddress &address) { std::vector params = {address}; json inputJson = { diff --git a/libs/StatusGoQt/src/StatusGo/Accounts/AccountsAPI.h b/libs/StatusGoQt/src/StatusGo/Accounts/AccountsAPI.h index 885192705..1686f04d7 100644 --- a/libs/StatusGoQt/src/StatusGo/Accounts/AccountsAPI.h +++ b/libs/StatusGoQt/src/StatusGo/Accounts/AccountsAPI.h @@ -1,7 +1,9 @@ #pragma once +#include "Types.h" -#include "Accounts/MultiAccount.h" +#include "Accounts/ChatOrWalletAccount.h" +#include "Accounts/accounts_types.h" #include #include @@ -16,34 +18,34 @@ namespace Status::StatusGo::Accounts /// \brief Retrieve all available accounts Wallet and Chat /// \note status-go returns accounts in \c CallPrivateRpcResponse.result /// \throws \c CallPrivateRpcError -Accounts::MultiAccounts getAccounts(); +Accounts::ChatOrWalletAccounts getAccounts(); /// \brief Generate a new account /// \note the underlying status-go api, SaveAccounts@accounts.go, returns `nil` for \c CallPrivateRpcResponse.result /// \see \c getAccounts /// \throws \c CallPrivateRpcError -void generateAccountWithDerivedPath(const QString &password, const QString &name, +void generateAccountWithDerivedPath(const HashedPassword &password, const QString &name, const QColor &color, const QString &emoji, - const QString &path, const QString &derivedFrom); + const DerivationPath &path, const Accounts::EOAddress &derivedFrom); /// \brief Add a new account from an existing mnemonic /// \note the underlying status-go api, SaveAccounts@accounts.go, returns `nil` for \c CallPrivateRpcResponse.result /// \see \c getAccounts /// \throws \c CallPrivateRpcError -void addAccountWithMnemonicAndPath(const QString &mnemonic, const QString &hashedPassword, const QString &name, - const QColor &color, const QString &emoji, const QString &path); +void addAccountWithMnemonicAndPath(const QString &mnemonic, const HashedPassword &password, const QString &name, + const QColor &color, const QString &emoji, const DerivationPath &path); /// \brief Add a watch only account /// \note the underlying status-go api, SaveAccounts@accounts.go, returns `nil` for \c CallPrivateRpcResponse.result /// \see \c getAccounts /// \throws \c CallPrivateRpcError -void addAccountWatch(const QString &address, const QString &name, const QColor &color, const QString &emoji); +void addAccountWatch(const EOAddress &address, const QString &name, const QColor &color, const QString &emoji); /// \brief Delete an existing account /// \note the underlying status-go api, DeleteAccount@accounts.go, returns `os.Remove(keyFile)` /// \see \c getAccounts /// \throws \c CallPrivateRpcError -void deleteAccount(const QString &address); +void deleteAccount(const EOAddress &address); /// \brief Delete an existing account /// \note the underlying status-go api, DeleteAccount@accounts.go, returns `os.Remove(keyFile)` diff --git a/libs/StatusGoQt/src/StatusGo/Accounts/MultiAccount.cpp b/libs/StatusGoQt/src/StatusGo/Accounts/ChatOrWalletAccount.cpp similarity index 84% rename from libs/StatusGoQt/src/StatusGo/Accounts/MultiAccount.cpp rename to libs/StatusGoQt/src/StatusGo/Accounts/ChatOrWalletAccount.cpp index dc3c2d15d..a7e032e44 100644 --- a/libs/StatusGoQt/src/StatusGo/Accounts/MultiAccount.cpp +++ b/libs/StatusGoQt/src/StatusGo/Accounts/ChatOrWalletAccount.cpp @@ -1,8 +1,8 @@ -#include "MultiAccount.h" +#include "ChatOrWalletAccount.h" namespace Status::StatusGo::Accounts { -void to_json(json& j, const MultiAccount& d) { +void to_json(json& j, const ChatOrWalletAccount& d) { j = {{"address", d.address}, {"chat", d.isChat}, {"clock", d.clock}, @@ -21,7 +21,7 @@ void to_json(json& j, const MultiAccount& d) { j["derived-from"] = d.derivedFrom.value(); } -void from_json(const json& j, MultiAccount& d) { +void from_json(const json& j, ChatOrWalletAccount& d) { j.at("address").get_to(d.address); j.at("chat").get_to(d.isChat); j.at("clock").get_to(d.clock); @@ -40,7 +40,7 @@ void from_json(const json& j, MultiAccount& d) { if(j.contains(publicKeyKey)) j.at(publicKeyKey).get_to(d.publicKey); if(d.isWallet && !j.at("derived-from").get().empty()) - d.derivedFrom = j.at("derived-from").get(); + d.derivedFrom = j.at("derived-from").get>(); } } diff --git a/libs/StatusGoQt/src/StatusGo/Accounts/ChatOrWalletAccount.h b/libs/StatusGoQt/src/StatusGo/Accounts/ChatOrWalletAccount.h new file mode 100644 index 000000000..8c6fb7335 --- /dev/null +++ b/libs/StatusGoQt/src/StatusGo/Accounts/ChatOrWalletAccount.h @@ -0,0 +1,42 @@ +#pragma once + +#include "accounts_types.h" + +#include + +#include + +#include + +#include + +using json = nlohmann::json; + +namespace Status::StatusGo::Accounts { + + +/// \brief Unique wallet account entity +/// \note equivalent of status-go's accounts.Account@multiaccounts/accounts/database.go +struct ChatOrWalletAccount +{ + EOAddress address; + bool isChat = false; + int clock = -1; + QColor color; + std::optional derivedFrom; + QString emoji; + bool isHidden = false; + QString mixedcaseAddress; + QString name; + DerivationPath path; + QString publicKey; + bool isRemoved = false; + bool isWallet = false; +}; + +using ChatOrWalletAccounts = std::vector; + +void to_json(json& j, const ChatOrWalletAccount& d); +void from_json(const json& j, ChatOrWalletAccount& d); + +} diff --git a/libs/StatusGoQt/src/StatusGo/Accounts/MultiAccount.h b/libs/StatusGoQt/src/StatusGo/Accounts/MultiAccount.h deleted file mode 100644 index 47a0c26bf..000000000 --- a/libs/StatusGoQt/src/StatusGo/Accounts/MultiAccount.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include - -#include - -#include - -#include - -using json = nlohmann::json; - -namespace Status::StatusGo::Accounts { - -// TODO: rename to MixedAccount -// TODO: create custom types or just named types for all. Also fix APIs after this - -/*! \brief Unique wallet account entity - */ -struct MultiAccount -{ - QString address; - bool isChat = false; - int clock = -1; - QColor color; - std::optional derivedFrom; - QString emoji; - bool isHidden = false; - QString mixedcaseAddress; - QString name; - QString path; - QString publicKey; - bool isRemoved = false; - bool isWallet = false; -}; - -using MultiAccounts = std::vector; - -void to_json(json& j, const MultiAccount& d); -void from_json(const json& j, MultiAccount& d); - -} diff --git a/libs/StatusGoQt/src/StatusGo/Accounts/accounts_types.h b/libs/StatusGoQt/src/StatusGo/Accounts/accounts_types.h new file mode 100644 index 000000000..7bcf11caf --- /dev/null +++ b/libs/StatusGoQt/src/StatusGo/Accounts/accounts_types.h @@ -0,0 +1,16 @@ +#include + +#include + +#include + +using json = nlohmann::json; + +/// Defines phantom types for strong typing +namespace Status::StatusGo::Accounts { + +/// The 20 byte address of an Ethereum account prefixed with 0x +using EOAddress = Helpers::NamedType; +using DerivationPath = Helpers::NamedType; + +} diff --git a/libs/StatusGoQt/src/StatusGo/Types.h b/libs/StatusGoQt/src/StatusGo/Types.h index b55bb4f9b..354282413 100644 --- a/libs/StatusGoQt/src/StatusGo/Types.h +++ b/libs/StatusGoQt/src/StatusGo/Types.h @@ -1,10 +1,14 @@ #pragma once +#include + #include namespace Status::StatusGo { +using HashedPassword = Helpers::NamedType; + // Used in calls where we don't have version and id returned from `status-go` struct RpcError diff --git a/libs/StatusGoQt/src/StatusGo/Utils.cpp b/libs/StatusGoQt/src/StatusGo/Utils.cpp index 155e6850c..04a381aee 100644 --- a/libs/StatusGoQt/src/StatusGo/Utils.cpp +++ b/libs/StatusGoQt/src/StatusGo/Utils.cpp @@ -7,11 +7,11 @@ namespace Status::StatusGo::Utils { -QJsonArray toJsonArray(const QVector& value) +QJsonArray toJsonArray(const std::vector& value) { QJsonArray array; for(auto& v : value) - array << v; + array << v.get(); return array; } @@ -20,10 +20,10 @@ const char* statusGoCallPrivateRPC(const char* inputJSON) { return CallPrivateRPC(const_cast(inputJSON)); } -QString hashString(const QString &str) +HashedPassword hashPassword(const QString &str) { - return "0x" + QString::fromUtf8(QCryptographicHash::hash(str.toUtf8(), - QCryptographicHash::Keccak_256).toHex()); + return HashedPassword("0x" + QString::fromUtf8(QCryptographicHash::hash(str.toUtf8(), + QCryptographicHash::Keccak_256).toHex())); } std::optional getRPCErrorInJson(const QJsonObject& json) diff --git a/libs/StatusGoQt/src/StatusGo/Utils.h b/libs/StatusGoQt/src/StatusGo/Utils.h index 75e1810a1..306ac662c 100644 --- a/libs/StatusGoQt/src/StatusGo/Utils.h +++ b/libs/StatusGoQt/src/StatusGo/Utils.h @@ -1,6 +1,7 @@ #pragma once #include "Types.h" +#include "Accounts/accounts_types.h" #include #include @@ -26,7 +27,7 @@ QByteArray jsonToByteArray(const T& json) return QJsonDocument(json).toJson(QJsonDocument::Compact); } -QJsonArray toJsonArray(const QVector& value); +QJsonArray toJsonArray(const std::vector& value); /// Check if json contains a standard status-go error and std::optional getRPCErrorInJson(const QJsonObject& json); @@ -111,6 +112,6 @@ RpcResponse callPrivateRpc(const QByteArray& payload) } } -QString hashString(const QString &str); +HashedPassword hashPassword(const QString &str); } diff --git a/libs/StatusGoQt/src/StatusGo/Wallet/DerivedAddress.h b/libs/StatusGoQt/src/StatusGo/Wallet/DerivedAddress.h index 3e0d1de47..2fb25920d 100644 --- a/libs/StatusGoQt/src/StatusGo/Wallet/DerivedAddress.h +++ b/libs/StatusGoQt/src/StatusGo/Wallet/DerivedAddress.h @@ -1,5 +1,7 @@ #pragma once +#include "Accounts/accounts_types.h" + #include #include @@ -8,6 +10,8 @@ #include +namespace Accounts = Status::StatusGo::Accounts; + using json = nlohmann::json; namespace Status::StatusGo::Wallet { @@ -19,12 +23,10 @@ namespace Status::StatusGo::Wallet { */ struct DerivedAddress { - // TODO create and Address type represents the 20 byte address of an Ethereum account. See https://pkg.go.dev/github.com/ethereum/go-ethereum/common?utm_source=gopls#Address - QString address; - // TODO: create an Path named type - QString path; - bool hasActivity = false; - bool alreadyCreated = false; + Accounts::EOAddress address; + Accounts::DerivationPath path; + bool hasActivity = false; + bool alreadyCreated = false; }; using DerivedAddresses = std::vector; diff --git a/libs/StatusGoQt/src/StatusGo/Wallet/WalletApi.cpp b/libs/StatusGoQt/src/StatusGo/Wallet/WalletApi.cpp index e438ef3b1..5eb5998ec 100644 --- a/libs/StatusGoQt/src/StatusGo/Wallet/WalletApi.cpp +++ b/libs/StatusGoQt/src/StatusGo/Wallet/WalletApi.cpp @@ -3,20 +3,24 @@ #include "Utils.h" #include "Metadata/api_response.h" +#include "Accounts/accounts_types.h" + #include #include #include +namespace Accounts = Status::StatusGo::Accounts; + using json = nlohmann::json; namespace Status::StatusGo::Wallet { -DerivedAddresses getDerivedAddressesForPath(const QString &hashedPassword, const QString &derivedFrom, const QString &path, int pageSize, int pageNumber) +DerivedAddresses getDerivedAddressesForPath(const HashedPassword &password, const Accounts::EOAddress &derivedFrom, const Accounts::DerivationPath &path, int pageSize, int pageNumber) { - std::vector params = {hashedPassword, derivedFrom, path, pageSize, pageNumber}; + std::vector params = {password, derivedFrom, path, pageSize, pageNumber}; json inputJson = { {"jsonrpc", "2.0"}, {"method", "wallet_getDerivedAddressesForPath"}, diff --git a/libs/StatusGoQt/src/StatusGo/Wallet/WalletApi.h b/libs/StatusGoQt/src/StatusGo/Wallet/WalletApi.h index 8fe248c0b..24d260e9c 100644 --- a/libs/StatusGoQt/src/StatusGo/Wallet/WalletApi.h +++ b/libs/StatusGoQt/src/StatusGo/Wallet/WalletApi.h @@ -1,8 +1,9 @@ #pragma once - -#include "Accounts/MultiAccount.h" +#include "Accounts/ChatOrWalletAccount.h" +#include "Accounts/accounts_types.h" #include "DerivedAddress.h" +#include "Types.h" #include @@ -13,6 +14,6 @@ namespace Status::StatusGo::Wallet /// \brief Retrieve a list of derived account addresses /// \see \c generateAccountWithDerivedPath /// \throws \c CallPrivateRpcError -DerivedAddresses getDerivedAddressesForPath(const QString &password, const QString &derivedFrom, const QString &path, int pageSize, int pageNumber); +DerivedAddresses getDerivedAddressesForPath(const HashedPassword &password, const Accounts::EOAddress &derivedFrom, const Accounts::DerivationPath &path, int pageSize, int pageNumber); } // namespaces diff --git a/libs/StatusQ/CMakeLists.txt b/libs/StatusQ/CMakeLists.txt index a14e2df5d..b3aa40a58 100644 --- a/libs/StatusQ/CMakeLists.txt +++ b/libs/StatusQ/CMakeLists.txt @@ -13,7 +13,6 @@ qt6_add_qml_module(${PROJECT_NAME} URI Status VERSION 1.0 - # TODO: temporary until we make qt_target_qml_sources work QML_FILES # Required to suppress "qmllint may not work" warning diff --git a/libs/StatusQ/qml/Status/Containers/CMakeLists.txt b/libs/StatusQ/qml/Status/Containers/CMakeLists.txt index b03f88ed7..77148deba 100644 --- a/libs/StatusQ/qml/Status/Containers/CMakeLists.txt +++ b/libs/StatusQ/qml/Status/Containers/CMakeLists.txt @@ -10,7 +10,6 @@ qt6_add_qml_module(${PROJECT_NAME} URI Status.Containers VERSION 1.0 - # TODO: temporary until we make qt_target_qml_sources work QML_FILES LayoutSpacer.qml diff --git a/libs/StatusQ/qml/Status/Controls/CMakeLists.txt b/libs/StatusQ/qml/Status/Controls/CMakeLists.txt index c58b91bdf..c55103ded 100644 --- a/libs/StatusQ/qml/Status/Controls/CMakeLists.txt +++ b/libs/StatusQ/qml/Status/Controls/CMakeLists.txt @@ -10,7 +10,6 @@ qt6_add_qml_module(${PROJECT_NAME} URI Status.Controls VERSION 1.0 - # TODO: temporary until we make qt_target_qml_sources work QML_FILES StatusBanner.qml diff --git a/libs/StatusQ/qml/Status/Controls/Navigation/CMakeLists.txt b/libs/StatusQ/qml/Status/Controls/Navigation/CMakeLists.txt index dd5ed3c79..b5efdfd88 100644 --- a/libs/StatusQ/qml/Status/Controls/Navigation/CMakeLists.txt +++ b/libs/StatusQ/qml/Status/Controls/Navigation/CMakeLists.txt @@ -14,7 +14,6 @@ qt6_add_qml_module(${PROJECT_NAME} URI Status.Controls.Navigation VERSION 1.0 - # TODO: temporary until we make qt_target_qml_sources work QML_FILES ApplicationContentView.qml ApplicationSection.qml diff --git a/libs/StatusQ/qml/Status/Core/CMakeLists.txt b/libs/StatusQ/qml/Status/Core/CMakeLists.txt index f0dbd1828..54d5a7cc1 100644 --- a/libs/StatusQ/qml/Status/Core/CMakeLists.txt +++ b/libs/StatusQ/qml/Status/Core/CMakeLists.txt @@ -10,7 +10,6 @@ qt6_add_qml_module(${PROJECT_NAME} URI Status.Core VERSION 1.0 - # TODO: temporary until we make qt_target_qml_sources work QML_FILES StatusBaseText.qml diff --git a/libs/StatusQ/qml/Status/Core/Theme/CMakeLists.txt b/libs/StatusQ/qml/Status/Core/Theme/CMakeLists.txt index 91fddd4d5..45fc97597 100644 --- a/libs/StatusQ/qml/Status/Core/Theme/CMakeLists.txt +++ b/libs/StatusQ/qml/Status/Core/Theme/CMakeLists.txt @@ -20,7 +20,6 @@ qt6_add_qml_module(${PROJECT_NAME} URI Status.Core.Theme VERSION 1.0 - # TODO: temporary until we make qt_target_qml_sources work QML_FILES StatusColors.qml StatusDarkPalette.qml diff --git a/libs/StatusQ/tests/CMakeLists.txt b/libs/StatusQ/tests/CMakeLists.txt index 190fa58eb..6091b1264 100644 --- a/libs/StatusQ/tests/CMakeLists.txt +++ b/libs/StatusQ/tests/CMakeLists.txt @@ -12,8 +12,9 @@ qt6_standard_project_setup() qt6_add_qml_module(${PROJECT_NAME} URI Status.TestHelpers VERSION 1.0 - # TODO: temporary until we make qt_target_qml_sources work + QML_FILES + # Required to suppress "qmllint may not work" warning OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Status/TestHelpers diff --git a/test/libs/StatusGoQt/test_accounts.cpp b/test/libs/StatusGoQt/test_accounts.cpp index d3991dd87..0cbae6090 100644 --- a/test/libs/StatusGoQt/test_accounts.cpp +++ b/test/libs/StatusGoQt/test_accounts.cpp @@ -36,14 +36,14 @@ TEST(AccountsAPI, TestGetAccounts) ASSERT_NE(chatIt, accounts.end()); const auto &chatAccount = *chatIt; ASSERT_EQ(chatAccount.name, testAccountName); - ASSERT_FALSE(chatAccount.path.isEmpty()); + ASSERT_FALSE(chatAccount.path.get().isEmpty()); ASSERT_FALSE(chatAccount.derivedFrom.has_value()); const auto walletIt = std::find_if(accounts.begin(), accounts.end(), [](const auto& a) { return a.isWallet; }); ASSERT_NE(walletIt, accounts.end()); const auto &walletAccount = *walletIt; ASSERT_NE(walletAccount.name, testAccountName); - ASSERT_FALSE(walletAccount.path.isEmpty()); + ASSERT_FALSE(walletAccount.path.get().isEmpty()); ASSERT_TRUE(walletAccount.derivedFrom.has_value()); } @@ -53,14 +53,14 @@ TEST(Accounts, TestGenerateAccountWithDerivedPath) constexpr auto testAccountPassword = "password*"; ScopedTestAccount testAccount(test_info_->name(), testRootAccountName, testAccountPassword, true); - auto hashedPassword{Utils::hashString(testAccountPassword)}; + auto password{Utils::hashPassword(testAccountPassword)}; const auto newTestAccountName = u"test_generated_new_account-name"_qs; const auto newTestAccountColor = QColor("fuchsia"); const auto newTestAccountEmoji = u""_qs; const auto newTestAccountPath = Status::Constants::General::PathWalletRoot; const auto chatAccount = testAccount.firstChatAccount(); - Accounts::generateAccountWithDerivedPath(hashedPassword, newTestAccountName, + Accounts::generateAccountWithDerivedPath(password, newTestAccountName, newTestAccountColor, newTestAccountEmoji, newTestAccountPath, chatAccount.address); const auto updatedAccounts = Accounts::getAccounts(); @@ -72,13 +72,13 @@ TEST(Accounts, TestGenerateAccountWithDerivedPath) }); ASSERT_NE(newAccountIt, updatedAccounts.end()); const auto &newAccount = *newAccountIt; - ASSERT_FALSE(newAccount.address.isEmpty()); + ASSERT_FALSE(newAccount.address.get().isEmpty()); ASSERT_FALSE(newAccount.isChat); ASSERT_FALSE(newAccount.isWallet); ASSERT_EQ(newAccount.color, newTestAccountColor); ASSERT_FALSE(newAccount.derivedFrom.has_value()); ASSERT_EQ(newAccount.emoji, newTestAccountEmoji); - ASSERT_EQ(newAccount.mixedcaseAddress.toUpper(), newAccount.address.toUpper()); + ASSERT_EQ(newAccount.mixedcaseAddress.toUpper(), newAccount.address.get().toUpper()); ASSERT_EQ(newAccount.path, newTestAccountPath); ASSERT_FALSE(newAccount.publicKey.isEmpty()); } @@ -91,7 +91,7 @@ TEST(AccountsAPI, TestGenerateAccountWithDerivedPath_WrongPassword) const auto chatAccount = testAccount.firstChatAccount(); try { - Accounts::generateAccountWithDerivedPath(Utils::hashString("WrongPassword"), u"test_wrong_pass-name"_qs, + Accounts::generateAccountWithDerivedPath(Utils::hashPassword("WrongPassword"), u"test_wrong_pass-name"_qs, QColor("fuchsia"), "", Status::Constants::General::PathWalletRoot, chatAccount.address); FAIL(); @@ -111,14 +111,14 @@ TEST(AccountsAPI, TestAddAccountWithMnemonicAndPath) constexpr auto testAccountPassword = "password*"; ScopedTestAccount testAccount(test_info_->name(), testRootAccountName, testAccountPassword, true); - auto hashedPassword{Utils::hashString(testAccountPassword)}; + auto password{Utils::hashPassword(testAccountPassword)}; const auto newTestAccountName = u"test_import_from_mnemonic-name"_qs; const auto newTestAccountColor = QColor("fuchsia"); const auto newTestAccountEmoji = u""_qs; const auto newTestAccountPath = Status::Constants::General::PathWalletRoot; Accounts::addAccountWithMnemonicAndPath("festival october control quarter husband dish throw couch depth stadium cigar whisper", - hashedPassword, newTestAccountName, newTestAccountColor, newTestAccountEmoji, + password, newTestAccountName, newTestAccountColor, newTestAccountEmoji, newTestAccountPath); const auto updatedAccounts = Accounts::getAccounts(); ASSERT_EQ(updatedAccounts.size(), 3); @@ -129,13 +129,13 @@ TEST(AccountsAPI, TestAddAccountWithMnemonicAndPath) }); ASSERT_NE(newAccountIt, updatedAccounts.end()); const auto &newAccount = *newAccountIt; - ASSERT_FALSE(newAccount.address.isEmpty()); + ASSERT_FALSE(newAccount.address.get().isEmpty()); ASSERT_FALSE(newAccount.isChat); ASSERT_FALSE(newAccount.isWallet); ASSERT_EQ(newAccount.color, newTestAccountColor); ASSERT_FALSE(newAccount.derivedFrom.has_value()); ASSERT_EQ(newAccount.emoji, newTestAccountEmoji); - ASSERT_EQ(newAccount.mixedcaseAddress.toUpper(), newAccount.address.toUpper()); + ASSERT_EQ(newAccount.mixedcaseAddress.toUpper(), newAccount.address.get().toUpper()); ASSERT_EQ(newAccount.path, newTestAccountPath); ASSERT_FALSE(newAccount.publicKey.isEmpty()); } @@ -147,7 +147,7 @@ TEST(AccountsAPI, TestAddAccountWithMnemonicAndPath_WrongMnemonicWorks) constexpr auto testAccountPassword = "password*"; ScopedTestAccount testAccount(test_info_->name(), testRootAccountName, testAccountPassword, true); - auto hashedPassword{Utils::hashString(testAccountPassword)}; + auto password{Utils::hashPassword(testAccountPassword)}; const auto newTestAccountName = u"test_import_from_wrong_mnemonic-name"_qs; const auto newTestAccountColor = QColor("fuchsia"); const auto newTestAccountEmoji = u""_qs; @@ -155,7 +155,7 @@ TEST(AccountsAPI, TestAddAccountWithMnemonicAndPath_WrongMnemonicWorks) // Added an inexistent word. The mnemonic is not checked. Accounts::addAccountWithMnemonicAndPath("october control quarter husband dish throw couch depth stadium cigar waku", - hashedPassword, newTestAccountName, newTestAccountColor, newTestAccountEmoji, + password, newTestAccountName, newTestAccountColor, newTestAccountEmoji, newTestAccountPath); const auto updatedAccounts = Accounts::getAccounts(); @@ -168,13 +168,13 @@ TEST(AccountsAPI, TestAddAccountWithMnemonicAndPath_WrongMnemonicWorks) ASSERT_NE(newAccountIt, updatedAccounts.end()); const auto &newAccount = *newAccountIt; - ASSERT_FALSE(newAccount.address.isEmpty()); + ASSERT_FALSE(newAccount.address.get().isEmpty()); ASSERT_FALSE(newAccount.isChat); ASSERT_FALSE(newAccount.isWallet); ASSERT_EQ(newAccount.color, newTestAccountColor); ASSERT_FALSE(newAccount.derivedFrom.has_value()); ASSERT_EQ(newAccount.emoji, newTestAccountEmoji); - ASSERT_EQ(newAccount.mixedcaseAddress.toUpper(), newAccount.address.toUpper()); + ASSERT_EQ(newAccount.mixedcaseAddress.toUpper(), newAccount.address.get().toUpper()); ASSERT_EQ(newAccount.path, newTestAccountPath); ASSERT_FALSE(newAccount.publicKey.isEmpty()); } @@ -189,7 +189,7 @@ TEST(AccountsAPI, TestAddAccountWatch) const auto newTestAccountColor = QColor("fuchsia"); const auto newTestAccountEmoji = u""_qs; - Accounts::addAccountWatch("0x145b6B821523afFC346774b41ACC7b77A171BbA4", newTestAccountName, newTestAccountColor, newTestAccountEmoji); + Accounts::addAccountWatch(Accounts::EOAddress("0x145b6B821523afFC346774b41ACC7b77A171BbA4"), newTestAccountName, newTestAccountColor, newTestAccountEmoji); const auto updatedAccounts = Accounts::getAccounts(); ASSERT_EQ(updatedAccounts.size(), 3); @@ -199,14 +199,14 @@ TEST(AccountsAPI, TestAddAccountWatch) }); ASSERT_NE(newAccountIt, updatedAccounts.end()); const auto &newAccount = *newAccountIt; - ASSERT_FALSE(newAccount.address.isEmpty()); + ASSERT_FALSE(newAccount.address.get().isEmpty()); ASSERT_FALSE(newAccount.isChat); ASSERT_FALSE(newAccount.isWallet); ASSERT_EQ(newAccount.color, newTestAccountColor); ASSERT_FALSE(newAccount.derivedFrom.has_value()); ASSERT_EQ(newAccount.emoji, newTestAccountEmoji); - ASSERT_EQ(newAccount.mixedcaseAddress.toUpper(), newAccount.address.toUpper()); - ASSERT_TRUE(newAccount.path.isEmpty()); + ASSERT_EQ(newAccount.mixedcaseAddress.toUpper(), newAccount.address.get().toUpper()); + ASSERT_TRUE(newAccount.path.get().isEmpty()); ASSERT_TRUE(newAccount.publicKey.isEmpty()); } @@ -220,7 +220,7 @@ TEST(AccountsAPI, TestDeleteAccount) const auto newTestAccountColor = QColor("fuchsia"); const auto newTestAccountEmoji = u""_qs; - Accounts::addAccountWatch("0x145b6B821523afFC346774b41ACC7b77A171BbA4", newTestAccountName, newTestAccountColor, newTestAccountEmoji); + Accounts::addAccountWatch(Accounts::EOAddress("0x145b6B821523afFC346774b41ACC7b77A171BbA4"), newTestAccountName, newTestAccountColor, newTestAccountEmoji); const auto updatedAccounts = Accounts::getAccounts(); ASSERT_EQ(updatedAccounts.size(), 3); diff --git a/test/libs/StatusGoQt/test_wallet.cpp b/test/libs/StatusGoQt/test_wallet.cpp index 0cc4b193b..903355103 100644 --- a/test/libs/StatusGoQt/test_wallet.cpp +++ b/test/libs/StatusGoQt/test_wallet.cpp @@ -32,11 +32,11 @@ TEST(WalletApi, TestGetDerivedAddressesForPath) const auto rootAccount = testAccount.onboardingController()->accountsService()->getLoggedInAccount(); ASSERT_EQ(rootAccount.address, walletAccount.derivedFrom.value()); - const auto hashedPassword{Utils::hashString(testAccountPassword)}; + const auto password{Utils::hashPassword(testAccountPassword)}; const auto testPath = Status::Constants::General::PathWalletRoot; // chatAccount.address - const auto chatDerivedAddresses = Wallet::getDerivedAddressesForPath(hashedPassword, chatAccount.address, testPath, 3, 1); + const auto chatDerivedAddresses = Wallet::getDerivedAddressesForPath(password, chatAccount.address, testPath, 3, 1); // Check that no change is done const auto updatedAccounts = Accounts::getAccounts(); ASSERT_EQ(updatedAccounts.size(), 2); @@ -47,14 +47,14 @@ TEST(WalletApi, TestGetDerivedAddressesForPath) // all hasActivity are false ASSERT_TRUE(std::none_of(chatDerivedAddresses.begin(), chatDerivedAddresses.end(), [](const auto& a) { return a.hasActivity; })); // all address are valid - ASSERT_TRUE(std::none_of(chatDerivedAddresses.begin(), chatDerivedAddresses.end(), [](const auto& a) { return a.address.isEmpty(); })); + ASSERT_TRUE(std::none_of(chatDerivedAddresses.begin(), chatDerivedAddresses.end(), [](const auto& a) { return a.address.get().isEmpty(); })); - const auto walletDerivedAddresses = Wallet::getDerivedAddressesForPath(hashedPassword, walletAccount.address, testPath, 2, 1); + const auto walletDerivedAddresses = Wallet::getDerivedAddressesForPath(password, walletAccount.address, testPath, 2, 1); ASSERT_EQ(walletDerivedAddresses.size(), 2); // all alreadyCreated are false ASSERT_TRUE(std::none_of(walletDerivedAddresses.begin(), walletDerivedAddresses.end(), [](const auto& a) { return a.alreadyCreated; })); - const auto rootDerivedAddresses = Wallet::getDerivedAddressesForPath(hashedPassword, rootAccount.address, testPath, 4, 1); + const auto rootDerivedAddresses = Wallet::getDerivedAddressesForPath(password, rootAccount.address, testPath, 4, 1); ASSERT_EQ(rootDerivedAddresses.size(), 4); ASSERT_EQ(std::count_if(rootDerivedAddresses.begin(), rootDerivedAddresses.end(), [](const auto& a) { return a.alreadyCreated; }), 1); const auto &existingAddress = *std::find_if(rootDerivedAddresses.begin(), rootDerivedAddresses.end(), [](const auto& a) { return a.alreadyCreated; });