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
This commit is contained in:
parent
a130681dd5
commit
16b866ccbd
|
@ -8,6 +8,7 @@ noBackup/
|
||||||
*.log
|
*.log
|
||||||
.update.timestamp
|
.update.timestamp
|
||||||
.vscode
|
.vscode
|
||||||
|
*.code-workspace
|
||||||
.tours
|
.tours
|
||||||
bin/
|
bin/
|
||||||
/bottles/
|
/bottles/
|
||||||
|
|
|
@ -27,9 +27,18 @@ endif()
|
||||||
|
|
||||||
# status-desktop application
|
# status-desktop application
|
||||||
add_subdirectory(vendor)
|
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(app)
|
||||||
|
|
||||||
add_subdirectory(test/libs/StatusGoQt)
|
add_subdirectory(test/libs/StatusGoQt)
|
||||||
|
|
||||||
# TODO: temporary not to duplicate resources until we switch to c++ app then it can be refactored
|
# TODO: temporary not to duplicate resources until we switch to c++ app then it can be refactored
|
||||||
add_subdirectory(resources)
|
add_subdirectory(resources)
|
||||||
add_subdirectory(ui/imports/assets)
|
add_subdirectory(ui/imports/assets)
|
||||||
|
|
|
@ -32,6 +32,9 @@ qt6_add_qml_module(${PROJECT_NAME}
|
||||||
qml/Status/Application/MainShortcuts.qml
|
qml/Status/Application/MainShortcuts.qml
|
||||||
qml/Status/Application/StatusWindow.qml
|
qml/Status/Application/StatusWindow.qml
|
||||||
|
|
||||||
|
SOURCES
|
||||||
|
res/app.qrc
|
||||||
|
|
||||||
OUTPUT_DIRECTORY
|
OUTPUT_DIRECTORY
|
||||||
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Status/Application
|
${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(qml/Status/Application/Navigation)
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
add_subdirectory(res)
|
|
||||||
|
|
||||||
include(${CMAKE_SOURCE_DIR}/cmake/platform_specific.cmake)
|
include(${CMAKE_SOURCE_DIR}/cmake/platform_specific.cmake)
|
||||||
string(TOLOWER ${PROJECT_ORGANIZATION_NAME} URL_ORGANIZATION_NAME)
|
string(TOLOWER ${PROJECT_ORGANIZATION_NAME} URL_ORGANIZATION_NAME)
|
||||||
|
|
|
@ -14,7 +14,6 @@ qt6_add_qml_module(${PROJECT_NAME}
|
||||||
URI Status.Application.Navigation
|
URI Status.Application.Navigation
|
||||||
VERSION 1.0
|
VERSION 1.0
|
||||||
|
|
||||||
# TODO: temporary until we make qt_target_qml_sources work
|
|
||||||
QML_FILES
|
QML_FILES
|
||||||
StatusNavigationBar.qml
|
StatusNavigationBar.qml
|
||||||
StatusNavigationButton.qml
|
StatusNavigationButton.qml
|
||||||
|
|
|
@ -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 ""
|
|
||||||
#)
|
|
|
@ -20,7 +20,6 @@ qt6_add_qml_module(Assets
|
||||||
URI Status.Assets
|
URI Status.Assets
|
||||||
VERSION 1.0
|
VERSION 1.0
|
||||||
|
|
||||||
# TODO: temporary until we make qt_target_qml_sources work
|
|
||||||
QML_FILES
|
QML_FILES
|
||||||
qml/Status/Assets/Resources.qml
|
qml/Status/Assets/Resources.qml
|
||||||
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
add_subdirectory(ApplicationCore)
|
|
||||||
add_subdirectory(Assets)
|
|
||||||
add_subdirectory(Helpers)
|
|
||||||
add_subdirectory(Onboarding)
|
|
||||||
add_subdirectory(StatusGoQt)
|
|
||||||
add_subdirectory(StatusQ)
|
|
|
@ -71,5 +71,6 @@ target_sources(Helpers
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Helpers/helpers.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/Helpers/helpers.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Helpers/logs.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/Helpers/logs.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Helpers/logs.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/Helpers/logs.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/Helpers/NamedType.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Helpers/Singleton.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/Helpers/Singleton.h
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
namespace Status::Helpers {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using IsNotReference = typename std::enable_if<!std::is_reference<T>::value, void>::type;
|
||||||
|
|
||||||
|
/// Featureless version of https://github.com/joboccara/NamedType that works with nlohmann::json
|
||||||
|
template <typename T, typename Parameter>
|
||||||
|
class NamedType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using UnderlyingType = T;
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
explicit constexpr NamedType(T const& value) : m_value(value) {}
|
||||||
|
template<typename T_ = T, typename = IsNotReference<T_>>
|
||||||
|
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<T> const& get() const {return m_value; }
|
||||||
|
|
||||||
|
bool operator<(const NamedType<T, Parameter> &) const = default;
|
||||||
|
bool operator>(const NamedType<T, Parameter> &) const = default;
|
||||||
|
bool operator<=(const NamedType<T, Parameter> &) const = default;
|
||||||
|
bool operator>=(const NamedType<T, Parameter> &) const = default;
|
||||||
|
bool operator==(const NamedType<T, Parameter> &) const = default;
|
||||||
|
bool operator!=(const NamedType<T, Parameter> &) const = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
T m_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename P>
|
||||||
|
void to_json(json& j, const NamedType<T, P>& p) {
|
||||||
|
j = p.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename P>
|
||||||
|
void from_json(const json& j, NamedType<T, P>& p) {
|
||||||
|
p = NamedType<T, P>{j.get<T>()};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T, typename Parameter>
|
||||||
|
struct hash<Status::Helpers::NamedType<T, Parameter>>
|
||||||
|
{
|
||||||
|
using NamedType = Status::Helpers::NamedType<T, Parameter>;
|
||||||
|
using checkIfHashable = typename std::enable_if<NamedType::is_hashable, void>::type;
|
||||||
|
|
||||||
|
size_t operator()(NamedType const& x) const
|
||||||
|
{
|
||||||
|
return std::hash<T>()(x.get());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -4,13 +4,8 @@ namespace fs = std::filesystem;
|
||||||
|
|
||||||
namespace Status {
|
namespace Status {
|
||||||
|
|
||||||
QString toQString(const std::string &str)
|
|
||||||
{
|
|
||||||
return QString::fromStdString(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString toQString(const fs::path &path) {
|
QString toQString(const fs::path &path) {
|
||||||
return toQString(path.string());
|
return QString::fromStdString(path.string());
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path toPath(const QString &pathStr) {
|
fs::path toPath(const QString &pathStr) {
|
||||||
|
|
|
@ -12,8 +12,8 @@ using json = nlohmann::json;
|
||||||
|
|
||||||
namespace Status {
|
namespace Status {
|
||||||
|
|
||||||
QString toQString(const std::string& str);
|
|
||||||
QString toQString(const std::filesystem::path& path);
|
QString toQString(const std::filesystem::path& path);
|
||||||
|
|
||||||
std::filesystem::path toPath(const QString& pathStr);
|
std::filesystem::path toPath(const QString& pathStr);
|
||||||
|
|
||||||
} // namespace Status
|
} // namespace Status
|
||||||
|
@ -42,4 +42,15 @@ struct adl_serializer<QColor> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct adl_serializer<std::optional<T>> {
|
||||||
|
static void to_json(json& j, const std::optional<T>& opt) {
|
||||||
|
j = opt.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void from_json(const json& j, std::optional<T>& opt) {
|
||||||
|
opt.emplace(j.get<T>());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace nlohmann
|
} // namespace nlohmann
|
||||||
|
|
|
@ -37,6 +37,9 @@ add_subdirectory(src)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
|
|
||||||
target_link_libraries(Onboarding
|
target_link_libraries(Onboarding
|
||||||
|
PUBLIC
|
||||||
|
Status::StatusGoQt
|
||||||
|
|
||||||
PRIVATE
|
PRIVATE
|
||||||
Qt6::Quick
|
Qt6::Quick
|
||||||
Qt6::Qml
|
Qt6::Qml
|
||||||
|
@ -45,7 +48,6 @@ target_link_libraries(Onboarding
|
||||||
Status::ApplicationCore
|
Status::ApplicationCore
|
||||||
Status::Helpers
|
Status::Helpers
|
||||||
|
|
||||||
Status::StatusGoQt
|
|
||||||
Status::StatusGoConfig
|
Status::StatusGoConfig
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,6 @@ SetupNewProfilePageBase {
|
||||||
TempTextInput {
|
TempTextInput {
|
||||||
id: confirmPasswordInput
|
id: confirmPasswordInput
|
||||||
|
|
||||||
// TODO: remove this developer helper
|
|
||||||
text: qsTr("1234567890")
|
|
||||||
|
|
||||||
width: 416
|
width: 416
|
||||||
height: 44
|
height: 44
|
||||||
|
|
||||||
|
|
|
@ -26,12 +26,12 @@ getDataFromFile(const fs::path &path)
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Status::Onboarding
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace StatusGo = Status::StatusGo;
|
namespace StatusGo = Status::StatusGo;
|
||||||
namespace Utils = Status::StatusGo::Utils;
|
namespace Utils = Status::StatusGo::Utils;
|
||||||
|
|
||||||
|
namespace Status::Onboarding
|
||||||
|
{
|
||||||
|
|
||||||
AccountsService::AccountsService()
|
AccountsService::AccountsService()
|
||||||
: m_isFirstTimeAccountLogin(false)
|
: m_isFirstTimeAccountLogin(false)
|
||||||
{
|
{
|
||||||
|
@ -49,32 +49,32 @@ bool AccountsService::init(const fs::path& statusgoDataDir)
|
||||||
|
|
||||||
for(const auto &genAddressObj : response.result)
|
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);
|
gAcc.alias = generateAlias(gAcc.derivedAccounts.whisper.publicKey);
|
||||||
m_generatedAccounts.push_back(std::move(gAcc));
|
m_generatedAccounts.push_back(std::move(gAcc));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<AccountDto> AccountsService::openAndListAccounts()
|
std::vector<MultiAccount> AccountsService::openAndListAccounts()
|
||||||
{
|
{
|
||||||
auto response = StatusGo::Accounts::openAccounts(m_statusgoDataDir.c_str());
|
auto response = StatusGo::Accounts::openAccounts(m_statusgoDataDir.c_str());
|
||||||
if(response.containsError())
|
if(response.containsError())
|
||||||
{
|
{
|
||||||
qWarning() << response.error.message;
|
qWarning() << response.error.message;
|
||||||
return std::vector<AccountDto>();
|
return std::vector<MultiAccount>();
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto multiAccounts = response.result;
|
const auto multiAccounts = response.result;
|
||||||
std::vector<AccountDto> result;
|
std::vector<MultiAccount> result;
|
||||||
for(const auto &value : multiAccounts)
|
for(const auto &value : multiAccounts)
|
||||||
{
|
{
|
||||||
result.push_back(AccountDto::toAccountDto(value.toObject()));
|
result.push_back(MultiAccount::toMultiAccount(value.toObject()));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<GeneratedAccountDto>& AccountsService::generatedAccounts() const
|
const std::vector<GeneratedMultiAccount>& AccountsService::generatedAccounts() const
|
||||||
{
|
{
|
||||||
return m_generatedAccounts;
|
return m_generatedAccounts;
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ bool AccountsService::setupAccountAndLogin(const QString &accountId, const QStri
|
||||||
QJsonObject settings(getAccountSettings(accountId, installationId, displayName));
|
QJsonObject settings(getAccountSettings(accountId, installationId, displayName));
|
||||||
QJsonObject nodeConfig(getDefaultNodeConfig(installationId));
|
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
|
// This initialize the DB if first time running. Required for storing accounts
|
||||||
if(StatusGo::Accounts::openAccounts(m_statusgoDataDir.c_str()).containsError())
|
if(StatusGo::Accounts::openAccounts(m_statusgoDataDir.c_str()).containsError())
|
||||||
|
@ -105,12 +105,12 @@ bool AccountsService::setupAccountAndLogin(const QString &accountId, const QStri
|
||||||
return getLoggedInAccount().isValid();
|
return getLoggedInAccount().isValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
const AccountDto& AccountsService::getLoggedInAccount() const
|
const MultiAccount& AccountsService::getLoggedInAccount() const
|
||||||
{
|
{
|
||||||
return m_loggedInAccount;
|
return m_loggedInAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
const GeneratedAccountDto& AccountsService::getImportedAccount() const
|
const GeneratedMultiAccount& AccountsService::getImportedAccount() const
|
||||||
{
|
{
|
||||||
return m_importedAccount;
|
return m_importedAccount;
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ bool AccountsService::setKeyStoreDir(const QString &key)
|
||||||
return !response.containsError();
|
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
|
// This is a requirement. Make it more explicit into the status go module
|
||||||
if(!setKeyStoreDir(account.keyUid))
|
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())
|
if(StatusGo::Accounts::openAccounts(m_statusgoDataDir.c_str()).containsError())
|
||||||
return QString("Failed to open accounts before logging in");
|
return QString("Failed to open accounts before logging in");
|
||||||
|
|
||||||
QString hashedPassword(Utils::hashString(password));
|
auto hashedPassword(Utils::hashPassword(password));
|
||||||
|
|
||||||
QString thumbnailImage;
|
QString thumbnailImage;
|
||||||
QString largeImage;
|
QString largeImage;
|
||||||
|
@ -157,8 +157,8 @@ QString AccountsService::login(AccountDto account, const QString& password)
|
||||||
void AccountsService::clear()
|
void AccountsService::clear()
|
||||||
{
|
{
|
||||||
m_generatedAccounts.clear();
|
m_generatedAccounts.clear();
|
||||||
m_loggedInAccount = AccountDto();
|
m_loggedInAccount = MultiAccount();
|
||||||
m_importedAccount = GeneratedAccountDto();
|
m_importedAccount = GeneratedMultiAccount();
|
||||||
m_isFirstTimeAccountLogin = false;
|
m_isFirstTimeAccountLogin = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,15 +174,15 @@ QString AccountsService::generateAlias(const QString& publicKey)
|
||||||
return response.result;
|
return response.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountsService::deleteMultiAccount(const AccountDto &account)
|
void AccountsService::deleteMultiAccount(const MultiAccount &account)
|
||||||
{
|
{
|
||||||
StatusGo::Accounts::deleteMultiaccount(account.keyUid, m_keyStoreDir);
|
StatusGo::Accounts::deleteMultiaccount(account.keyUid, m_keyStoreDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
DerivedAccounts AccountsService::storeDerivedAccounts(const QString& accountId, const QString& hashedPassword,
|
DerivedAccounts AccountsService::storeDerivedAccounts(const QString& accountId, const StatusGo::HashedPassword& password,
|
||||||
const QVector<QString>& paths)
|
const std::vector<Accounts::DerivationPath> &paths)
|
||||||
{
|
{
|
||||||
auto response = StatusGo::Accounts::storeDerivedAccounts(accountId, hashedPassword, paths);
|
auto response = StatusGo::Accounts::storeDerivedAccounts(accountId, password, paths);
|
||||||
if(response.containsError())
|
if(response.containsError())
|
||||||
{
|
{
|
||||||
qWarning() << response.error.message;
|
qWarning() << response.error.message;
|
||||||
|
@ -191,31 +191,31 @@ DerivedAccounts AccountsService::storeDerivedAccounts(const QString& accountId,
|
||||||
return DerivedAccounts::toDerivedAccounts(response.result);
|
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())
|
if(response.containsError())
|
||||||
{
|
{
|
||||||
qWarning() << response.error.message;
|
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 QJsonArray& subaccounts, const QJsonObject& settings,
|
||||||
const QJsonObject& config)
|
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");
|
qWarning() << "Failed saving acccount" << account.value("name");
|
||||||
return AccountDto();
|
return MultiAccount();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_isFirstTimeAccountLogin = true;
|
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},
|
return QJsonObject{{"name", displayName.isEmpty() ? account.alias : displayName},
|
||||||
{"address", account.address},
|
{"address", account.address},
|
||||||
|
@ -225,7 +225,7 @@ QJsonObject AccountsService::prepareAccountJsonObject(const GeneratedAccountDto&
|
||||||
|
|
||||||
QJsonObject AccountsService::getAccountDataForAccountId(const QString &accountId, const QString &displayName) const
|
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)
|
if(acc.id == accountId)
|
||||||
{
|
{
|
||||||
|
@ -245,7 +245,7 @@ QJsonObject AccountsService::getAccountDataForAccountId(const QString &accountId
|
||||||
return QJsonObject();
|
return QJsonObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonArray AccountsService::prepareSubaccountJsonObject(const GeneratedAccountDto& account, const QString &displayName) const
|
QJsonArray AccountsService::prepareSubaccountJsonObject(const GeneratedMultiAccount& account, const QString &displayName) const
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
QJsonObject{
|
QJsonObject{
|
||||||
|
@ -253,7 +253,7 @@ QJsonArray AccountsService::prepareSubaccountJsonObject(const GeneratedAccountDt
|
||||||
{"address", account.derivedAccounts.defaultWallet.address},
|
{"address", account.derivedAccounts.defaultWallet.address},
|
||||||
{"color", "#4360df"},
|
{"color", "#4360df"},
|
||||||
{"wallet", true},
|
{"wallet", true},
|
||||||
{"path", Constants::General::PathDefaultWallet},
|
{"path", Constants::General::PathDefaultWallet.get()},
|
||||||
{"name", "Status account"},
|
{"name", "Status account"},
|
||||||
{"derived-from", account.address}
|
{"derived-from", account.address}
|
||||||
},
|
},
|
||||||
|
@ -261,7 +261,7 @@ QJsonArray AccountsService::prepareSubaccountJsonObject(const GeneratedAccountDt
|
||||||
{"public-key", account.derivedAccounts.whisper.publicKey},
|
{"public-key", account.derivedAccounts.whisper.publicKey},
|
||||||
{"address", account.derivedAccounts.whisper.address},
|
{"address", account.derivedAccounts.whisper.address},
|
||||||
{"name", displayName.isEmpty() ? account.alias : displayName},
|
{"name", displayName.isEmpty() ? account.alias : displayName},
|
||||||
{"path", Constants::General::PathWhisper},
|
{"path", Constants::General::PathWhisper.get()},
|
||||||
{"chat", true},
|
{"chat", true},
|
||||||
{"derived-from", ""}
|
{"derived-from", ""}
|
||||||
}
|
}
|
||||||
|
@ -271,7 +271,7 @@ QJsonArray AccountsService::prepareSubaccountJsonObject(const GeneratedAccountDt
|
||||||
QJsonArray AccountsService::getSubaccountDataForAccountId(const QString& accountId, const QString &displayName) const
|
QJsonArray AccountsService::getSubaccountDataForAccountId(const QString& accountId, const QString &displayName) const
|
||||||
{
|
{
|
||||||
// "All these for loops with a nested if cry for a std::find_if :)"
|
// "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)
|
if(acc.id == accountId)
|
||||||
{
|
{
|
||||||
|
@ -302,7 +302,7 @@ QString AccountsService::generateSigningPhrase(int count) const
|
||||||
return words.join(" ");
|
return words.join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject AccountsService::prepareAccountSettingsJsonObject(const GeneratedAccountDto& account,
|
QJsonObject AccountsService::prepareAccountSettingsJsonObject(const GeneratedMultiAccount& account,
|
||||||
const QString& installationId,
|
const QString& installationId,
|
||||||
const QString& displayName) const
|
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
|
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)
|
if(acc.id == accountId)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <StatusGo/Types.h>
|
||||||
|
|
||||||
#include "AccountsServiceInterface.h"
|
#include "AccountsServiceInterface.h"
|
||||||
|
|
||||||
namespace Status::Onboarding
|
namespace Status::Onboarding
|
||||||
|
@ -25,18 +27,18 @@ public:
|
||||||
bool init(const fs::path& statusgoDataDir) override;
|
bool init(const fs::path& statusgoDataDir) override;
|
||||||
|
|
||||||
/// \see ServiceInterface
|
/// \see ServiceInterface
|
||||||
[[nodiscard]] std::vector<AccountDto> openAndListAccounts() override;
|
[[nodiscard]] std::vector<MultiAccount> openAndListAccounts() override;
|
||||||
|
|
||||||
/// \see ServiceInterface
|
/// \see ServiceInterface
|
||||||
[[nodiscard]] const std::vector<GeneratedAccountDto>& generatedAccounts() const override;
|
[[nodiscard]] const std::vector<GeneratedMultiAccount>& generatedAccounts() const override;
|
||||||
|
|
||||||
/// \see ServiceInterface
|
/// \see ServiceInterface
|
||||||
bool setupAccountAndLogin(const QString& accountId, const QString& password, const QString& displayName) override;
|
bool setupAccountAndLogin(const QString& accountId, const QString& password, const QString& displayName) override;
|
||||||
|
|
||||||
/// \see ServiceInterface
|
/// \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
|
/// \see ServiceInterface
|
||||||
[[nodiscard]] bool isFirstTimeAccountLogin() const override;
|
[[nodiscard]] bool isFirstTimeAccountLogin() const override;
|
||||||
|
@ -44,34 +46,34 @@ public:
|
||||||
/// \see ServiceInterface
|
/// \see ServiceInterface
|
||||||
bool setKeyStoreDir(const QString &key) override;
|
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;
|
void clear() override;
|
||||||
|
|
||||||
QString generateAlias(const QString& publicKey) override;
|
QString generateAlias(const QString& publicKey) override;
|
||||||
|
|
||||||
void deleteMultiAccount(const AccountDto &account) override;
|
void deleteMultiAccount(const MultiAccount &account) override;
|
||||||
|
|
||||||
private:
|
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,
|
DerivedAccounts storeDerivedAccounts(const QString& accountId, const StatusGo::HashedPassword& password,
|
||||||
const QVector<QString>& paths);
|
const std::vector<Accounts::DerivationPath>& paths);
|
||||||
StoredAccountDto storeAccount(const QString& accountId, const QString& hashedPassword);
|
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 QJsonArray& subaccounts, const QJsonObject& settings,
|
||||||
const QJsonObject& config);
|
const QJsonObject& config);
|
||||||
|
|
||||||
QJsonObject getAccountDataForAccountId(const QString& accountId, const QString& displayName) const;
|
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;
|
QJsonArray getSubaccountDataForAccountId(const QString& accountId, const QString& displayName) const;
|
||||||
|
|
||||||
QString generateSigningPhrase(int count) const;
|
QString generateSigningPhrase(int count) const;
|
||||||
|
|
||||||
QJsonObject prepareAccountSettingsJsonObject(const GeneratedAccountDto& account,
|
QJsonObject prepareAccountSettingsJsonObject(const GeneratedMultiAccount& account,
|
||||||
const QString& installationId,
|
const QString& installationId,
|
||||||
const QString& displayName) const;
|
const QString& displayName) const;
|
||||||
|
|
||||||
|
@ -80,14 +82,14 @@ private:
|
||||||
QJsonObject getDefaultNodeConfig(const QString& installationId) const;
|
QJsonObject getDefaultNodeConfig(const QString& installationId) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<GeneratedAccountDto> m_generatedAccounts;
|
std::vector<GeneratedMultiAccount> m_generatedAccounts;
|
||||||
|
|
||||||
fs::path m_statusgoDataDir;
|
fs::path m_statusgoDataDir;
|
||||||
fs::path m_keyStoreDir;
|
fs::path m_keyStoreDir;
|
||||||
bool m_isFirstTimeAccountLogin;
|
bool m_isFirstTimeAccountLogin;
|
||||||
// TODO: don't see the need for this state here
|
// TODO: don't see the need for this state here
|
||||||
AccountDto m_loggedInAccount;
|
MultiAccount m_loggedInAccount;
|
||||||
GeneratedAccountDto m_importedAccount;
|
GeneratedMultiAccount m_importedAccount;
|
||||||
|
|
||||||
// Here for now. Extract them if used by other services
|
// Here for now. Extract them if used by other services
|
||||||
static constexpr auto m_keyStoreDirName = "keystore";
|
static constexpr auto m_keyStoreDirName = "keystore";
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "AccountDto.h"
|
#include "MultiAccount.h"
|
||||||
#include "GeneratedAccountDto.h"
|
#include "GeneratedMultiAccount.h"
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
|
@ -20,18 +20,18 @@ public:
|
||||||
virtual bool init(const fs::path& statusgoDataDir) = 0;
|
virtual bool init(const fs::path& statusgoDataDir) = 0;
|
||||||
|
|
||||||
/// opens database and returns accounts list.
|
/// opens database and returns accounts list.
|
||||||
[[nodiscard]] virtual std::vector<AccountDto> openAndListAccounts() = 0;
|
[[nodiscard]] virtual std::vector<MultiAccount> openAndListAccounts() = 0;
|
||||||
|
|
||||||
/// Retrieve cached accounts generated in \c init
|
/// Retrieve cached accounts generated in \c init
|
||||||
[[nodiscard]] virtual const std::vector<GeneratedAccountDto>& generatedAccounts() const = 0;
|
[[nodiscard]] virtual const std::vector<GeneratedMultiAccount>& generatedAccounts() const = 0;
|
||||||
|
|
||||||
/// Configure an generated account. \a accountID must be sourced from \c generatedAccounts
|
/// 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;
|
virtual bool setupAccountAndLogin(const QString& accountID, const QString& password, const QString& displayName) = 0;
|
||||||
|
|
||||||
/// Account that is currently logged-in
|
/// 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
|
/// Check if the login was never done in the current \c data directory
|
||||||
[[nodiscard]] virtual bool isFirstTimeAccountLogin() const = 0;
|
[[nodiscard]] virtual bool isFirstTimeAccountLogin() const = 0;
|
||||||
|
@ -39,13 +39,13 @@ public:
|
||||||
/// Set and initializes the keystore directory. \see StatusGo::General::initKeystore
|
/// Set and initializes the keystore directory. \see StatusGo::General::initKeystore
|
||||||
virtual bool setKeyStoreDir(const QString &key) = 0;
|
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 void clear() = 0;
|
||||||
|
|
||||||
virtual QString generateAlias(const QString& publicKey) = 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<AccountsServiceInterface>;
|
using AccountsServiceInterfacePtr = std::shared_ptr<AccountsServiceInterface>;
|
||||||
|
|
|
@ -50,19 +50,19 @@ struct DerivedAccounts
|
||||||
for(const auto &derivationPath : jsonObj.keys())
|
for(const auto &derivationPath : jsonObj.keys())
|
||||||
{
|
{
|
||||||
auto derivedObj = jsonObj.value(derivationPath).toObject();
|
auto derivedObj = jsonObj.value(derivationPath).toObject();
|
||||||
if(derivationPath == Constants::General::PathWhisper)
|
if(derivationPath == Constants::General::PathWhisper.get())
|
||||||
{
|
{
|
||||||
result.whisper = DerivedAccountDetails::toDerivedAccountDetails(derivedObj, derivationPath);
|
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);
|
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);
|
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);
|
result.eip1581 = DerivedAccountDetails::toDerivedAccountDetails(derivedObj, derivationPath);
|
||||||
}
|
}
|
||||||
|
@ -72,28 +72,28 @@ struct DerivedAccounts
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StoredAccountDto
|
struct StoredMultiAccount
|
||||||
{
|
{
|
||||||
QString publicKey;
|
QString publicKey;
|
||||||
QString address;
|
QString address;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static StoredAccountDto toStoredAccountDto(const QJsonObject& jsonObj)
|
static StoredMultiAccount toStoredMultiAccount(const QJsonObject& jsonObj)
|
||||||
{
|
{
|
||||||
auto result = StoredAccountDto();
|
auto result = StoredMultiAccount();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
result.address = Json::getMandatoryProp(jsonObj, "address")->toString();
|
result.address = Json::getMandatoryProp(jsonObj, "address")->toString();
|
||||||
result.publicKey = Json::getMandatoryProp(jsonObj, "publicKey")->toString();
|
result.publicKey = Json::getMandatoryProp(jsonObj, "publicKey")->toString();
|
||||||
} catch (std::exception e) {
|
} catch (std::exception e) {
|
||||||
qWarning() << QString("Mapping StoredAccountDto failed: %1").arg(e.what());
|
qWarning() << QString("Mapping StoredMultiAccount failed: %1").arg(e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GeneratedAccountDto
|
struct GeneratedMultiAccount
|
||||||
{
|
{
|
||||||
QString id;
|
QString id;
|
||||||
QString publicKey;
|
QString publicKey;
|
||||||
|
@ -110,9 +110,9 @@ struct GeneratedAccountDto
|
||||||
return !(id.isEmpty() || publicKey.isEmpty() || address.isEmpty() || keyUid.isEmpty());
|
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
|
try
|
||||||
{
|
{
|
||||||
|
@ -130,7 +130,7 @@ struct GeneratedAccountDto
|
||||||
}
|
}
|
||||||
catch (std::exception e)
|
catch (std::exception e)
|
||||||
{
|
{
|
||||||
qWarning() << QString("Mapping GeneratedAccountDto failed: %1").arg(e.what());
|
qWarning() << QString("Mapping GeneratedMultiAccount failed: %1").arg(e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
|
@ -4,14 +4,18 @@
|
||||||
#include "Common/SigningPhrases.h"
|
#include "Common/SigningPhrases.h"
|
||||||
#include "Common/Json.h"
|
#include "Common/Json.h"
|
||||||
|
|
||||||
|
#include <StatusGo/Accounts/accounts_types.h>
|
||||||
|
|
||||||
#include <QtCore>
|
#include <QtCore>
|
||||||
|
|
||||||
|
namespace Accounts = Status::StatusGo::Accounts;
|
||||||
|
|
||||||
// TODO: Move to StatusGo library
|
// TODO: Move to StatusGo library
|
||||||
namespace Status::Onboarding
|
namespace Status::Onboarding
|
||||||
{
|
{
|
||||||
|
|
||||||
// TODO: refactor it to MultiAccount
|
/// \note equivalent of status-go's multiaccounts.Account@multiaccounts/database.go
|
||||||
struct AccountDto
|
struct MultiAccount
|
||||||
{
|
{
|
||||||
QString name;
|
QString name;
|
||||||
long timestamp;
|
long timestamp;
|
||||||
|
@ -20,16 +24,16 @@ struct AccountDto
|
||||||
// TODO images
|
// TODO images
|
||||||
// TODO colorHash
|
// TODO colorHash
|
||||||
// TODO colorId
|
// TODO colorId
|
||||||
QString address;
|
Accounts::EOAddress address;
|
||||||
|
|
||||||
bool isValid() const
|
bool isValid() const
|
||||||
{
|
{
|
||||||
return !(name.isEmpty() || keyUid.isEmpty());
|
return !(name.isEmpty() || keyUid.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
static AccountDto toAccountDto(const QJsonObject& jsonObj)
|
static MultiAccount toMultiAccount(const QJsonObject& jsonObj)
|
||||||
{
|
{
|
||||||
auto result = AccountDto();
|
auto result = MultiAccount();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -43,13 +47,13 @@ struct AccountDto
|
||||||
}
|
}
|
||||||
result.keycardPairing = Json::getMandatoryProp(jsonObj, "keycard-pairing")->toString();
|
result.keycardPairing = Json::getMandatoryProp(jsonObj, "keycard-pairing")->toString();
|
||||||
result.keyUid = Json::getMandatoryProp(jsonObj, "key-uid")->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
|
/// TODO: investigate unhandled `photo-path` value
|
||||||
}
|
}
|
||||||
catch (std::exception e)
|
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;
|
return result;
|
|
@ -6,8 +6,8 @@ target_sources(${PROJECT_NAME}
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/UserAccount.h
|
${CMAKE_CURRENT_SOURCE_DIR}/UserAccount.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/UserAccountsModel.h
|
${CMAKE_CURRENT_SOURCE_DIR}/UserAccountsModel.h
|
||||||
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/Accounts/AccountDto.h
|
${CMAKE_CURRENT_SOURCE_DIR}/Accounts/MultiAccount.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/Accounts/GeneratedAccountDto.h
|
${CMAKE_CURRENT_SOURCE_DIR}/Accounts/GeneratedMultiAccount.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/Accounts/AccountsService.h
|
${CMAKE_CURRENT_SOURCE_DIR}/Accounts/AccountsService.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/Accounts/AccountsServiceInterface.h
|
${CMAKE_CURRENT_SOURCE_DIR}/Accounts/AccountsServiceInterface.h
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <StatusGo/Accounts/accounts_types.h>
|
||||||
|
|
||||||
#include <QtCore>
|
#include <QtCore>
|
||||||
#include <QStringLiteral>
|
#include <QStringLiteral>
|
||||||
|
|
||||||
|
namespace Accounts = Status::StatusGo::Accounts;
|
||||||
|
|
||||||
namespace Status::Constants
|
namespace Status::Constants
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -34,15 +38,15 @@ namespace General
|
||||||
|
|
||||||
inline const auto ZeroAddress = u"0x0000000000000000000000000000000000000000"_qs;
|
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
|
// 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
|
// 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
|
// 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<QString> AccountDefaultPaths {PathWalletRoot, PathEIP1581, PathWhisper, PathDefaultWallet};
|
inline const std::vector<Accounts::DerivationPath> AccountDefaultPaths {PathWalletRoot, PathEIP1581, PathWhisper, PathDefaultWallet};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "UserAccountsModel.h"
|
#include "UserAccountsModel.h"
|
||||||
|
|
||||||
#include "Accounts/AccountsServiceInterface.h"
|
#include "Accounts/AccountsServiceInterface.h"
|
||||||
#include "Accounts/AccountDto.h"
|
#include "Accounts/MultiAccount.h"
|
||||||
|
|
||||||
#include <QtQmlIntegration>
|
#include <QtQmlIntegration>
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ OnboardingController::OnboardingController(AccountsServiceInterfacePtr accountsS
|
||||||
{ // Init accounts
|
{ // Init accounts
|
||||||
std::vector<std::shared_ptr<UserAccount>> accounts;
|
std::vector<std::shared_ptr<UserAccount>> accounts;
|
||||||
for(auto &account : getOpenedAccounts()) {
|
for(auto &account : getOpenedAccounts()) {
|
||||||
accounts.push_back(std::make_shared<UserAccount>(std::make_unique<AccountDto>(std::move(account))));
|
accounts.push_back(std::make_shared<UserAccount>(std::make_unique<MultiAccount>(std::move(account))));
|
||||||
}
|
}
|
||||||
m_accounts = std::make_shared<UserAccountsModel>(std::move(accounts));
|
m_accounts = std::make_shared<UserAccountsModel>(std::move(accounts));
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ void OnboardingController::onLogin(const QString& error)
|
||||||
emit accountLoginError(error);
|
emit accountLoginError(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<AccountDto> OnboardingController::getOpenedAccounts() const
|
std::vector<MultiAccount> OnboardingController::getOpenedAccounts() const
|
||||||
{
|
{
|
||||||
return m_accountsService->openAndListAccounts();
|
return m_accountsService->openAndListAccounts();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include "UserAccountsModel.h"
|
#include "UserAccountsModel.h"
|
||||||
|
|
||||||
#include "Accounts/AccountDto.h"
|
#include "Accounts/MultiAccount.h"
|
||||||
|
|
||||||
#include <QQmlEngine>
|
#include <QQmlEngine>
|
||||||
#include <QtQmlIntegration>
|
#include <QtQmlIntegration>
|
||||||
|
@ -38,7 +38,7 @@ public:
|
||||||
~OnboardingController();
|
~OnboardingController();
|
||||||
|
|
||||||
/// Retrieve available accounts
|
/// Retrieve available accounts
|
||||||
std::vector<AccountDto> getOpenedAccounts() const;
|
std::vector<MultiAccount> getOpenedAccounts() const;
|
||||||
|
|
||||||
/// Login user account
|
/// 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
|
/// TODO: \a user should be of type \c UserAccount but this doesn't work with Qt6 CMake API. Investigate and fix later on
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
#include "UserAccount.h"
|
#include "UserAccount.h"
|
||||||
|
|
||||||
#include "Accounts/AccountDto.h"
|
#include "Accounts/MultiAccount.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Status::Onboarding
|
namespace Status::Onboarding
|
||||||
{
|
{
|
||||||
|
|
||||||
UserAccount::UserAccount(std::unique_ptr<AccountDto> data)
|
UserAccount::UserAccount(std::unique_ptr<MultiAccount> data)
|
||||||
: QObject()
|
: QObject()
|
||||||
, m_data(std::move(data))
|
, m_data(std::move(data))
|
||||||
{
|
{
|
||||||
|
@ -18,12 +17,12 @@ const QString &UserAccount::name() const
|
||||||
return m_data->name;
|
return m_data->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AccountDto &UserAccount::accountData() const
|
const MultiAccount &UserAccount::accountData() const
|
||||||
{
|
{
|
||||||
return *m_data;
|
return *m_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserAccount::updateAccountData(const AccountDto& newData)
|
void UserAccount::updateAccountData(const MultiAccount& newData)
|
||||||
{
|
{
|
||||||
std::vector<std::function<void()>> notifyUpdates;
|
std::vector<std::function<void()>> notifyUpdates;
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
namespace Status::Onboarding
|
namespace Status::Onboarding
|
||||||
{
|
{
|
||||||
|
|
||||||
class AccountDto;
|
class MultiAccount;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Represents a user account in Onboarding Presentation Layer
|
* \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)
|
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
|
||||||
public:
|
public:
|
||||||
explicit UserAccount(std::unique_ptr<AccountDto> data);
|
explicit UserAccount(std::unique_ptr<MultiAccount> data);
|
||||||
|
|
||||||
const QString &name() const;
|
const QString &name() const;
|
||||||
|
|
||||||
const AccountDto& accountData() const;
|
const MultiAccount& accountData() const;
|
||||||
void updateAccountData(const AccountDto& newData);
|
void updateAccountData(const MultiAccount& newData);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void nameChanged();
|
void nameChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<AccountDto> m_data;
|
std::unique_ptr<MultiAccount> m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,12 +41,8 @@ target_link_libraries(${PROJECT_NAME}
|
||||||
|
|
||||||
Status::OnboardingTestHelpers
|
Status::OnboardingTestHelpers
|
||||||
Status::Onboarding
|
Status::Onboarding
|
||||||
|
|
||||||
# TODO tmp
|
|
||||||
Status::StatusGoQt
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
include(GoogleTest)
|
include(GoogleTest)
|
||||||
gtest_add_tests(
|
gtest_add_tests(
|
||||||
TARGET ${PROJECT_NAME}
|
TARGET ${PROJECT_NAME}
|
||||||
|
|
|
@ -110,7 +110,7 @@ void ScopedTestAccount::logOut()
|
||||||
throw std::runtime_error("ScopedTestAccount - failed logging out");
|
throw std::runtime_error("ScopedTestAccount - failed logging out");
|
||||||
}
|
}
|
||||||
|
|
||||||
Accounts::MultiAccount ScopedTestAccount::firstChatAccount()
|
Accounts::ChatOrWalletAccount ScopedTestAccount::firstChatAccount()
|
||||||
{
|
{
|
||||||
auto accounts = Accounts::getAccounts();
|
auto accounts = Accounts::getAccounts();
|
||||||
auto chatIt = std::find_if(accounts.begin(), accounts.end(), [](const auto& a) {
|
auto chatIt = std::find_if(accounts.begin(), accounts.end(), [](const auto& a) {
|
||||||
|
@ -121,7 +121,7 @@ Accounts::MultiAccount ScopedTestAccount::firstChatAccount()
|
||||||
return *chatIt;
|
return *chatIt;
|
||||||
}
|
}
|
||||||
|
|
||||||
Accounts::MultiAccount ScopedTestAccount::firstWalletAccount()
|
Accounts::ChatOrWalletAccount ScopedTestAccount::firstWalletAccount()
|
||||||
{
|
{
|
||||||
auto accounts = Accounts::getAccounts();
|
auto accounts = Accounts::getAccounts();
|
||||||
auto walletIt = std::find_if(accounts.begin(), accounts.end(), [](const auto& a) {
|
auto walletIt = std::find_if(accounts.begin(), accounts.end(), [](const auto& a) {
|
||||||
|
|
|
@ -36,8 +36,8 @@ public:
|
||||||
void processMessages(size_t millis, std::function<bool()> shouldWaitUntilTimeout);
|
void processMessages(size_t millis, std::function<bool()> shouldWaitUntilTimeout);
|
||||||
void logOut();
|
void logOut();
|
||||||
|
|
||||||
static Accounts::MultiAccount firstChatAccount();
|
static Accounts::ChatOrWalletAccount firstChatAccount();
|
||||||
static Accounts::MultiAccount firstWalletAccount();
|
static Accounts::ChatOrWalletAccount firstWalletAccount();
|
||||||
|
|
||||||
QString password() const { return m_accountPassword; };
|
QString password() const { return m_accountPassword; };
|
||||||
|
|
||||||
|
|
|
@ -21,17 +21,17 @@ public:
|
||||||
virtual ~AccountsServiceMock() override {};
|
virtual ~AccountsServiceMock() override {};
|
||||||
|
|
||||||
MOCK_METHOD(bool, init, (const fs::path&), (override));
|
MOCK_METHOD(bool, init, (const fs::path&), (override));
|
||||||
MOCK_METHOD(std::vector<Onboarding::AccountDto>, openAndListAccounts, (), (override));
|
MOCK_METHOD(std::vector<Onboarding::MultiAccount>, openAndListAccounts, (), (override));
|
||||||
MOCK_METHOD(const std::vector<Onboarding::GeneratedAccountDto>&, generatedAccounts, (), (const, override));
|
MOCK_METHOD(const std::vector<Onboarding::GeneratedMultiAccount>&, generatedAccounts, (), (const, override));
|
||||||
MOCK_METHOD(bool, setupAccountAndLogin, (const QString&, const QString&, const QString&), (override));
|
MOCK_METHOD(bool, setupAccountAndLogin, (const QString&, const QString&, const QString&), (override));
|
||||||
MOCK_METHOD(const Onboarding::AccountDto&, getLoggedInAccount, (), (const, override));
|
MOCK_METHOD(const Onboarding::MultiAccount&, getLoggedInAccount, (), (const, override));
|
||||||
MOCK_METHOD(const Onboarding::GeneratedAccountDto&, getImportedAccount, (), (const, override));
|
MOCK_METHOD(const Onboarding::GeneratedMultiAccount&, getImportedAccount, (), (const, override));
|
||||||
MOCK_METHOD(bool, isFirstTimeAccountLogin, (), (const, override));
|
MOCK_METHOD(bool, isFirstTimeAccountLogin, (), (const, override));
|
||||||
MOCK_METHOD(bool, setKeyStoreDir, (const QString&), (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(void, clear, (), (override));
|
||||||
MOCK_METHOD(QString, generateAlias, (const QString&), (override));
|
MOCK_METHOD(QString, generateAlias, (const QString&), (override));
|
||||||
MOCK_METHOD(void, deleteMultiAccount, (const Onboarding::AccountDto&), (override));
|
MOCK_METHOD(void, deleteMultiAccount, (const Onboarding::MultiAccount&), (override));
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ add_library(${PROJECT_NAME} SHARED)
|
||||||
# Use by linker only
|
# Use by linker only
|
||||||
set_property(GLOBAL PROPERTY DEBUG_CONFIGURATIONS Debug)
|
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}
|
target_link_libraries(${PROJECT_NAME}
|
||||||
PUBLIC
|
PUBLIC
|
||||||
Status::Helpers
|
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.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/StatusGo/Accounts/Accounts.cpp
|
${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.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/StatusGo/Accounts/AccountsAPI.cpp
|
${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/ChatOrWalletAccount.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/StatusGo/Accounts/MultiAccount.cpp
|
${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.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/StatusGo/Messenger/Service.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/StatusGo/Messenger/Service.cpp
|
||||||
|
|
|
@ -9,7 +9,7 @@ const int MNEMONIC_PHRASE_LENGTH = 12;
|
||||||
|
|
||||||
namespace Status::StatusGo::Accounts {
|
namespace Status::StatusGo::Accounts {
|
||||||
|
|
||||||
RpcResponse<QJsonArray> generateAddresses(const QVector<QString>& paths)
|
RpcResponse<QJsonArray> generateAddresses(const std::vector<Accounts::DerivationPath>& paths)
|
||||||
{
|
{
|
||||||
QJsonObject payload{
|
QJsonObject payload{
|
||||||
{"n", NUMBER_OF_ADDRESSES_TO_GENERATE},
|
{"n", NUMBER_OF_ADDRESSES_TO_GENERATE},
|
||||||
|
@ -64,13 +64,12 @@ RpcResponse<QString> generateAlias(const QString& publicKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RpcResponse<QJsonObject> storeDerivedAccounts(const QString& id, const QString& hashedPassword,
|
RpcResponse<QJsonObject> storeDerivedAccounts(const QString& id, const HashedPassword& password, const std::vector<Accounts::DerivationPath>& paths)
|
||||||
const QVector<QString>& paths)
|
|
||||||
{
|
{
|
||||||
QJsonObject payload{
|
QJsonObject payload{
|
||||||
{"accountID", id},
|
{"accountID", id},
|
||||||
{"paths", Utils::toJsonArray(paths)},
|
{"paths", Utils::toJsonArray(paths)},
|
||||||
{"password", hashedPassword}
|
{"password", password.get()}
|
||||||
};
|
};
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -101,11 +100,11 @@ RpcResponse<QJsonObject> storeDerivedAccounts(const QString& id, const QString&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RpcResponse<QJsonObject> storeAccount(const QString& id, const QString& hashedPassword)
|
RpcResponse<QJsonObject> storeAccount(const QString& id, const HashedPassword& password)
|
||||||
{
|
{
|
||||||
QJsonObject payload{
|
QJsonObject payload{
|
||||||
{"accountID", id},
|
{"accountID", id},
|
||||||
{"password", hashedPassword}
|
{"password", password.get()}
|
||||||
};
|
};
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -136,14 +135,14 @@ RpcResponse<QJsonObject> 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 QJsonArray& subaccounts, const QJsonObject& settings,
|
||||||
const QJsonObject& nodeConfig)
|
const QJsonObject& nodeConfig)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto result = SaveAccountAndLogin(Utils::jsonToByteArray(account).data(),
|
auto result = SaveAccountAndLogin(Utils::jsonToByteArray(account).data(),
|
||||||
hashedPassword.toUtf8().data(),
|
password.get().toUtf8().data(),
|
||||||
Utils::jsonToByteArray(settings).data(),
|
Utils::jsonToByteArray(settings).data(),
|
||||||
Utils::jsonToByteArray(nodeConfig).data(),
|
Utils::jsonToByteArray(nodeConfig).data(),
|
||||||
Utils::jsonToByteArray(subaccounts).data());
|
Utils::jsonToByteArray(subaccounts).data());
|
||||||
|
@ -193,7 +192,7 @@ RpcResponse<QJsonArray> openAccounts(const char* dataDirPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RpcResponse<QJsonObject> login(const QString& name, const QString& keyUid, const QString& hashedPassword,
|
RpcResponse<QJsonObject> login(const QString& name, const QString& keyUid, const HashedPassword& password,
|
||||||
const QString& thumbnail, const QString& large)
|
const QString& thumbnail, const QString& large)
|
||||||
{
|
{
|
||||||
QJsonObject payload{
|
QJsonObject payload{
|
||||||
|
@ -210,7 +209,7 @@ RpcResponse<QJsonObject> login(const QString& name, const QString& keyUid, const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto payloadData = Utils::jsonToByteArray(std::move(payload));
|
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;
|
QJsonObject jsonResult;
|
||||||
if(!Utils::checkReceivedResponse(result, jsonResult))
|
if(!Utils::checkReceivedResponse(result, jsonResult))
|
||||||
{
|
{
|
||||||
|
@ -234,7 +233,7 @@ RpcResponse<QJsonObject> login(const QString& name, const QString& keyUid, const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RpcResponse<QJsonObject> loginWithConfig(const QString& name, const QString& keyUid, const QString& hashedPassword,
|
RpcResponse<QJsonObject> loginWithConfig(const QString& name, const QString& keyUid, const HashedPassword& password,
|
||||||
const QString& thumbnail, const QString& large, const QJsonObject& nodeConfig)
|
const QString& thumbnail, const QString& large, const QJsonObject& nodeConfig)
|
||||||
{
|
{
|
||||||
QJsonObject payload{
|
QJsonObject payload{
|
||||||
|
@ -252,7 +251,7 @@ RpcResponse<QJsonObject> loginWithConfig(const QString& name, const QString& key
|
||||||
{
|
{
|
||||||
auto payloadData = Utils::jsonToByteArray(std::move(payload));
|
auto payloadData = Utils::jsonToByteArray(std::move(payload));
|
||||||
auto nodeConfigData = Utils::jsonToByteArray(nodeConfig);
|
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;
|
QJsonObject jsonResult;
|
||||||
if(!Utils::checkReceivedResponse(result, jsonResult))
|
if(!Utils::checkReceivedResponse(result, jsonResult))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,31 +1,31 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
#include "accounts_types.h"
|
||||||
|
|
||||||
#include <QtCore>
|
#include <QtCore>
|
||||||
|
|
||||||
namespace Status::StatusGo::Accounts
|
namespace Status::StatusGo::Accounts
|
||||||
{
|
{
|
||||||
RpcResponse<QJsonArray> generateAddresses(const QVector<QString>& paths);
|
RpcResponse<QJsonArray> generateAddresses(const std::vector<Accounts::DerivationPath> &paths);
|
||||||
|
|
||||||
RpcResponse<QString> generateAlias(const QString& publicKey);
|
RpcResponse<QString> generateAlias(const QString& publicKey);
|
||||||
|
|
||||||
RpcResponse<QJsonObject> storeDerivedAccounts(const QString& accountId, const QString& hashedPassword,
|
RpcResponse<QJsonObject> storeDerivedAccounts(const QString& accountId, const HashedPassword& password,
|
||||||
const QVector<QString>& paths);
|
const std::vector<Accounts::DerivationPath>& paths);
|
||||||
|
|
||||||
RpcResponse<QJsonObject> storeAccount(const QString& id, const QString& hashedPassword);
|
RpcResponse<QJsonObject> storeAccount(const QString& id, const HashedPassword& password);
|
||||||
|
|
||||||
bool saveAccountAndLogin(const QString& hashedPassword, const QJsonObject& account,
|
bool saveAccountAndLogin(const StatusGo::HashedPassword& password, const QJsonObject& account,
|
||||||
const QJsonArray& subaccounts, const QJsonObject& settings,
|
const QJsonArray& subaccounts, const QJsonObject& settings,
|
||||||
const QJsonObject& nodeConfig);
|
const QJsonObject& nodeConfig);
|
||||||
|
|
||||||
/// opens database and returns accounts list.
|
/// opens database and returns accounts list.
|
||||||
RpcResponse<QJsonArray> openAccounts(const char* dataDirPath);
|
RpcResponse<QJsonArray> openAccounts(const char* dataDirPath);
|
||||||
|
|
||||||
/// TODO harmonise password parameters (hashed or plain)?
|
RpcResponse<QJsonObject> login(const QString& name, const QString& keyUid, const HashedPassword& password,
|
||||||
RpcResponse<QJsonObject> login(const QString& name, const QString& keyUid, const QString& hashedPassword,
|
|
||||||
const QString& thumbnail, const QString& large);
|
const QString& thumbnail, const QString& large);
|
||||||
RpcResponse<QJsonObject> loginWithConfig(const QString& name, const QString& keyUid, const QString& hashedPassword,
|
RpcResponse<QJsonObject> loginWithConfig(const QString& name, const QString& keyUid, const HashedPassword& password,
|
||||||
const QString& thumbnail, const QString& large, const QJsonObject& nodeConfig);
|
const QString& thumbnail, const QString& large, const QJsonObject& nodeConfig);
|
||||||
RpcResponse<QJsonObject> logout();
|
RpcResponse<QJsonObject> logout();
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ using json = nlohmann::json;
|
||||||
namespace Status::StatusGo::Accounts
|
namespace Status::StatusGo::Accounts
|
||||||
{
|
{
|
||||||
|
|
||||||
Accounts::MultiAccounts getAccounts() {
|
Accounts::ChatOrWalletAccounts getAccounts() {
|
||||||
// or even nicer with a raw string literal
|
// or even nicer with a raw string literal
|
||||||
json inputJson = {
|
json inputJson = {
|
||||||
{"jsonrpc", "2.0"},
|
{"jsonrpc", "2.0"},
|
||||||
|
@ -29,10 +29,10 @@ Accounts::MultiAccounts getAccounts() {
|
||||||
return resultJson.get<CallPrivateRpcResponse>().result;
|
return resultJson.get<CallPrivateRpcResponse>().result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void generateAccountWithDerivedPath(const QString &hashedPassword, const QString &name, const QColor &color, const QString &emoji,
|
void generateAccountWithDerivedPath(const HashedPassword &password, const QString &name, const QColor &color, const QString &emoji,
|
||||||
const QString &path, const QString &derivedFrom)
|
const DerivationPath &path, const EOAddress &derivedFrom)
|
||||||
{
|
{
|
||||||
std::vector<json> params = {hashedPassword, name, color, emoji, path, derivedFrom};
|
std::vector<json> params = {password, name, color, emoji, path, derivedFrom};
|
||||||
json inputJson = {
|
json inputJson = {
|
||||||
{"jsonrpc", "2.0"},
|
{"jsonrpc", "2.0"},
|
||||||
{"method", "accounts_generateAccountWithDerivedPath"},
|
{"method", "accounts_generateAccountWithDerivedPath"},
|
||||||
|
@ -44,10 +44,10 @@ void generateAccountWithDerivedPath(const QString &hashedPassword, const QString
|
||||||
checkPrivateRpcCallResultAndReportError(resultJson);
|
checkPrivateRpcCallResultAndReportError(resultJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addAccountWithMnemonicAndPath(const QString &mnemonic, const QString &hashedPassword, const QString &name,
|
void addAccountWithMnemonicAndPath(const QString &mnemonic, const HashedPassword &password, const QString &name,
|
||||||
const QColor &color, const QString &emoji, const QString &path)
|
const QColor &color, const QString &emoji, const DerivationPath &path)
|
||||||
{
|
{
|
||||||
std::vector<json> params = {mnemonic, hashedPassword, name, color, emoji, path};
|
std::vector<json> params = {mnemonic, password, name, color, emoji, path};
|
||||||
json inputJson = {
|
json inputJson = {
|
||||||
{"jsonrpc", "2.0"},
|
{"jsonrpc", "2.0"},
|
||||||
{"method", "accounts_addAccountWithMnemonicAndPath"},
|
{"method", "accounts_addAccountWithMnemonicAndPath"},
|
||||||
|
@ -59,7 +59,7 @@ void addAccountWithMnemonicAndPath(const QString &mnemonic, const QString &hashe
|
||||||
checkPrivateRpcCallResultAndReportError(resultJson);
|
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<json> params = {address, name, color, emoji};
|
std::vector<json> params = {address, name, color, emoji};
|
||||||
json inputJson = {
|
json inputJson = {
|
||||||
|
@ -73,7 +73,7 @@ void addAccountWatch(const QString &address, const QString &name, const QColor &
|
||||||
checkPrivateRpcCallResultAndReportError(resultJson);
|
checkPrivateRpcCallResultAndReportError(resultJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
void deleteAccount(const QString &address)
|
void deleteAccount(const EOAddress &address)
|
||||||
{
|
{
|
||||||
std::vector<json> params = {address};
|
std::vector<json> params = {address};
|
||||||
json inputJson = {
|
json inputJson = {
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Types.h"
|
||||||
|
|
||||||
#include "Accounts/MultiAccount.h"
|
#include "Accounts/ChatOrWalletAccount.h"
|
||||||
|
#include "Accounts/accounts_types.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
@ -16,34 +18,34 @@ namespace Status::StatusGo::Accounts
|
||||||
/// \brief Retrieve all available accounts Wallet and Chat
|
/// \brief Retrieve all available accounts Wallet and Chat
|
||||||
/// \note status-go returns accounts in \c CallPrivateRpcResponse.result
|
/// \note status-go returns accounts in \c CallPrivateRpcResponse.result
|
||||||
/// \throws \c CallPrivateRpcError
|
/// \throws \c CallPrivateRpcError
|
||||||
Accounts::MultiAccounts getAccounts();
|
Accounts::ChatOrWalletAccounts getAccounts();
|
||||||
|
|
||||||
/// \brief Generate a new account
|
/// \brief Generate a new account
|
||||||
/// \note the underlying status-go api, SaveAccounts@accounts.go, returns `nil` for \c CallPrivateRpcResponse.result
|
/// \note the underlying status-go api, SaveAccounts@accounts.go, returns `nil` for \c CallPrivateRpcResponse.result
|
||||||
/// \see \c getAccounts
|
/// \see \c getAccounts
|
||||||
/// \throws \c CallPrivateRpcError
|
/// \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 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
|
/// \brief Add a new account from an existing mnemonic
|
||||||
/// \note the underlying status-go api, SaveAccounts@accounts.go, returns `nil` for \c CallPrivateRpcResponse.result
|
/// \note the underlying status-go api, SaveAccounts@accounts.go, returns `nil` for \c CallPrivateRpcResponse.result
|
||||||
/// \see \c getAccounts
|
/// \see \c getAccounts
|
||||||
/// \throws \c CallPrivateRpcError
|
/// \throws \c CallPrivateRpcError
|
||||||
void addAccountWithMnemonicAndPath(const QString &mnemonic, const QString &hashedPassword, const QString &name,
|
void addAccountWithMnemonicAndPath(const QString &mnemonic, const HashedPassword &password, const QString &name,
|
||||||
const QColor &color, const QString &emoji, const QString &path);
|
const QColor &color, const QString &emoji, const DerivationPath &path);
|
||||||
|
|
||||||
/// \brief Add a watch only account
|
/// \brief Add a watch only account
|
||||||
/// \note the underlying status-go api, SaveAccounts@accounts.go, returns `nil` for \c CallPrivateRpcResponse.result
|
/// \note the underlying status-go api, SaveAccounts@accounts.go, returns `nil` for \c CallPrivateRpcResponse.result
|
||||||
/// \see \c getAccounts
|
/// \see \c getAccounts
|
||||||
/// \throws \c CallPrivateRpcError
|
/// \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
|
/// \brief Delete an existing account
|
||||||
/// \note the underlying status-go api, DeleteAccount@accounts.go, returns `os.Remove(keyFile)`
|
/// \note the underlying status-go api, DeleteAccount@accounts.go, returns `os.Remove(keyFile)`
|
||||||
/// \see \c getAccounts
|
/// \see \c getAccounts
|
||||||
/// \throws \c CallPrivateRpcError
|
/// \throws \c CallPrivateRpcError
|
||||||
void deleteAccount(const QString &address);
|
void deleteAccount(const EOAddress &address);
|
||||||
|
|
||||||
/// \brief Delete an existing account
|
/// \brief Delete an existing account
|
||||||
/// \note the underlying status-go api, DeleteAccount@accounts.go, returns `os.Remove(keyFile)`
|
/// \note the underlying status-go api, DeleteAccount@accounts.go, returns `os.Remove(keyFile)`
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include "MultiAccount.h"
|
#include "ChatOrWalletAccount.h"
|
||||||
|
|
||||||
namespace Status::StatusGo::Accounts {
|
namespace Status::StatusGo::Accounts {
|
||||||
|
|
||||||
void to_json(json& j, const MultiAccount& d) {
|
void to_json(json& j, const ChatOrWalletAccount& d) {
|
||||||
j = {{"address", d.address},
|
j = {{"address", d.address},
|
||||||
{"chat", d.isChat},
|
{"chat", d.isChat},
|
||||||
{"clock", d.clock},
|
{"clock", d.clock},
|
||||||
|
@ -21,7 +21,7 @@ void to_json(json& j, const MultiAccount& d) {
|
||||||
j["derived-from"] = d.derivedFrom.value();
|
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("address").get_to(d.address);
|
||||||
j.at("chat").get_to(d.isChat);
|
j.at("chat").get_to(d.isChat);
|
||||||
j.at("clock").get_to(d.clock);
|
j.at("clock").get_to(d.clock);
|
||||||
|
@ -40,7 +40,7 @@ void from_json(const json& j, MultiAccount& d) {
|
||||||
if(j.contains(publicKeyKey))
|
if(j.contains(publicKeyKey))
|
||||||
j.at(publicKeyKey).get_to(d.publicKey);
|
j.at(publicKeyKey).get_to(d.publicKey);
|
||||||
if(d.isWallet && !j.at("derived-from").get<std::string>().empty())
|
if(d.isWallet && !j.at("derived-from").get<std::string>().empty())
|
||||||
d.derivedFrom = j.at("derived-from").get<QString>();
|
d.derivedFrom = j.at("derived-from").get<std::optional<EOAddress>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "accounts_types.h"
|
||||||
|
|
||||||
|
#include <Helpers/conversions.h>
|
||||||
|
|
||||||
|
#include <QColor>
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
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<EOAddress> derivedFrom;
|
||||||
|
QString emoji;
|
||||||
|
bool isHidden = false;
|
||||||
|
QString mixedcaseAddress;
|
||||||
|
QString name;
|
||||||
|
DerivationPath path;
|
||||||
|
QString publicKey;
|
||||||
|
bool isRemoved = false;
|
||||||
|
bool isWallet = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
using ChatOrWalletAccounts = std::vector<ChatOrWalletAccount>;
|
||||||
|
|
||||||
|
void to_json(json& j, const ChatOrWalletAccount& d);
|
||||||
|
void from_json(const json& j, ChatOrWalletAccount& d);
|
||||||
|
|
||||||
|
}
|
|
@ -1,42 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Helpers/conversions.h>
|
|
||||||
|
|
||||||
#include <QColor>
|
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
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<QString> derivedFrom;
|
|
||||||
QString emoji;
|
|
||||||
bool isHidden = false;
|
|
||||||
QString mixedcaseAddress;
|
|
||||||
QString name;
|
|
||||||
QString path;
|
|
||||||
QString publicKey;
|
|
||||||
bool isRemoved = false;
|
|
||||||
bool isWallet = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
using MultiAccounts = std::vector<MultiAccount>;
|
|
||||||
|
|
||||||
void to_json(json& j, const MultiAccount& d);
|
|
||||||
void from_json(const json& j, MultiAccount& d);
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
#include <Helpers/NamedType.h>
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
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<QString, struct EOAddressTag>;
|
||||||
|
using DerivationPath = Helpers::NamedType<QString, struct DerivationPathTag>;
|
||||||
|
|
||||||
|
}
|
|
@ -1,10 +1,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Helpers/NamedType.h>
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
namespace Status::StatusGo
|
namespace Status::StatusGo
|
||||||
{
|
{
|
||||||
|
|
||||||
|
using HashedPassword = Helpers::NamedType<QString, struct HashedPasswordTag>;
|
||||||
|
|
||||||
// Used in calls where we don't have version and id returned from `status-go`
|
// Used in calls where we don't have version and id returned from `status-go`
|
||||||
|
|
||||||
struct RpcError
|
struct RpcError
|
||||||
|
|
|
@ -7,11 +7,11 @@
|
||||||
namespace Status::StatusGo::Utils
|
namespace Status::StatusGo::Utils
|
||||||
{
|
{
|
||||||
|
|
||||||
QJsonArray toJsonArray(const QVector<QString>& value)
|
QJsonArray toJsonArray(const std::vector<Accounts::DerivationPath>& value)
|
||||||
{
|
{
|
||||||
QJsonArray array;
|
QJsonArray array;
|
||||||
for(auto& v : value)
|
for(auto& v : value)
|
||||||
array << v;
|
array << v.get();
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,10 +20,10 @@ const char* statusGoCallPrivateRPC(const char* inputJSON) {
|
||||||
return CallPrivateRPC(const_cast<char*>(inputJSON));
|
return CallPrivateRPC(const_cast<char*>(inputJSON));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString hashString(const QString &str)
|
HashedPassword hashPassword(const QString &str)
|
||||||
{
|
{
|
||||||
return "0x" + QString::fromUtf8(QCryptographicHash::hash(str.toUtf8(),
|
return HashedPassword("0x" + QString::fromUtf8(QCryptographicHash::hash(str.toUtf8(),
|
||||||
QCryptographicHash::Keccak_256).toHex());
|
QCryptographicHash::Keccak_256).toHex()));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<RpcError> getRPCErrorInJson(const QJsonObject& json)
|
std::optional<RpcError> getRPCErrorInJson(const QJsonObject& json)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
#include "Accounts/accounts_types.h"
|
||||||
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
@ -26,7 +27,7 @@ QByteArray jsonToByteArray(const T& json)
|
||||||
return QJsonDocument(json).toJson(QJsonDocument::Compact);
|
return QJsonDocument(json).toJson(QJsonDocument::Compact);
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonArray toJsonArray(const QVector<QString>& value);
|
QJsonArray toJsonArray(const std::vector<Accounts::DerivationPath>& value);
|
||||||
|
|
||||||
/// Check if json contains a standard status-go error and
|
/// Check if json contains a standard status-go error and
|
||||||
std::optional<RpcError> getRPCErrorInJson(const QJsonObject& json);
|
std::optional<RpcError> getRPCErrorInJson(const QJsonObject& json);
|
||||||
|
@ -111,6 +112,6 @@ RpcResponse<T> callPrivateRpc(const QByteArray& payload)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString hashString(const QString &str);
|
HashedPassword hashPassword(const QString &str);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Accounts/accounts_types.h"
|
||||||
|
|
||||||
#include <Helpers/conversions.h>
|
#include <Helpers/conversions.h>
|
||||||
|
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
|
@ -8,6 +10,8 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Accounts = Status::StatusGo::Accounts;
|
||||||
|
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
|
||||||
namespace Status::StatusGo::Wallet {
|
namespace Status::StatusGo::Wallet {
|
||||||
|
@ -19,12 +23,10 @@ namespace Status::StatusGo::Wallet {
|
||||||
*/
|
*/
|
||||||
struct DerivedAddress
|
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
|
Accounts::EOAddress address;
|
||||||
QString address;
|
Accounts::DerivationPath path;
|
||||||
// TODO: create an Path named type
|
bool hasActivity = false;
|
||||||
QString path;
|
bool alreadyCreated = false;
|
||||||
bool hasActivity = false;
|
|
||||||
bool alreadyCreated = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using DerivedAddresses = std::vector<DerivedAddress>;
|
using DerivedAddresses = std::vector<DerivedAddress>;
|
||||||
|
|
|
@ -3,20 +3,24 @@
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
#include "Metadata/api_response.h"
|
#include "Metadata/api_response.h"
|
||||||
|
|
||||||
|
#include "Accounts/accounts_types.h"
|
||||||
|
|
||||||
#include <libstatus.h>
|
#include <libstatus.h>
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace Accounts = Status::StatusGo::Accounts;
|
||||||
|
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
|
||||||
namespace Status::StatusGo::Wallet
|
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<json> params = {hashedPassword, derivedFrom, path, pageSize, pageNumber};
|
std::vector<json> params = {password, derivedFrom, path, pageSize, pageNumber};
|
||||||
json inputJson = {
|
json inputJson = {
|
||||||
{"jsonrpc", "2.0"},
|
{"jsonrpc", "2.0"},
|
||||||
{"method", "wallet_getDerivedAddressesForPath"},
|
{"method", "wallet_getDerivedAddressesForPath"},
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Accounts/ChatOrWalletAccount.h"
|
||||||
#include "Accounts/MultiAccount.h"
|
#include "Accounts/accounts_types.h"
|
||||||
#include "DerivedAddress.h"
|
#include "DerivedAddress.h"
|
||||||
|
#include "Types.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -13,6 +14,6 @@ namespace Status::StatusGo::Wallet
|
||||||
/// \brief Retrieve a list of derived account addresses
|
/// \brief Retrieve a list of derived account addresses
|
||||||
/// \see \c generateAccountWithDerivedPath
|
/// \see \c generateAccountWithDerivedPath
|
||||||
/// \throws \c CallPrivateRpcError
|
/// \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
|
} // namespaces
|
||||||
|
|
|
@ -13,7 +13,6 @@ qt6_add_qml_module(${PROJECT_NAME}
|
||||||
URI Status
|
URI Status
|
||||||
VERSION 1.0
|
VERSION 1.0
|
||||||
|
|
||||||
# TODO: temporary until we make qt_target_qml_sources work
|
|
||||||
QML_FILES
|
QML_FILES
|
||||||
|
|
||||||
# Required to suppress "qmllint may not work" warning
|
# Required to suppress "qmllint may not work" warning
|
||||||
|
|
|
@ -10,7 +10,6 @@ qt6_add_qml_module(${PROJECT_NAME}
|
||||||
URI Status.Containers
|
URI Status.Containers
|
||||||
VERSION 1.0
|
VERSION 1.0
|
||||||
|
|
||||||
# TODO: temporary until we make qt_target_qml_sources work
|
|
||||||
QML_FILES
|
QML_FILES
|
||||||
LayoutSpacer.qml
|
LayoutSpacer.qml
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ qt6_add_qml_module(${PROJECT_NAME}
|
||||||
URI Status.Controls
|
URI Status.Controls
|
||||||
VERSION 1.0
|
VERSION 1.0
|
||||||
|
|
||||||
# TODO: temporary until we make qt_target_qml_sources work
|
|
||||||
QML_FILES
|
QML_FILES
|
||||||
StatusBanner.qml
|
StatusBanner.qml
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ qt6_add_qml_module(${PROJECT_NAME}
|
||||||
URI Status.Controls.Navigation
|
URI Status.Controls.Navigation
|
||||||
VERSION 1.0
|
VERSION 1.0
|
||||||
|
|
||||||
# TODO: temporary until we make qt_target_qml_sources work
|
|
||||||
QML_FILES
|
QML_FILES
|
||||||
ApplicationContentView.qml
|
ApplicationContentView.qml
|
||||||
ApplicationSection.qml
|
ApplicationSection.qml
|
||||||
|
|
|
@ -10,7 +10,6 @@ qt6_add_qml_module(${PROJECT_NAME}
|
||||||
URI Status.Core
|
URI Status.Core
|
||||||
VERSION 1.0
|
VERSION 1.0
|
||||||
|
|
||||||
# TODO: temporary until we make qt_target_qml_sources work
|
|
||||||
QML_FILES
|
QML_FILES
|
||||||
StatusBaseText.qml
|
StatusBaseText.qml
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@ qt6_add_qml_module(${PROJECT_NAME}
|
||||||
URI Status.Core.Theme
|
URI Status.Core.Theme
|
||||||
VERSION 1.0
|
VERSION 1.0
|
||||||
|
|
||||||
# TODO: temporary until we make qt_target_qml_sources work
|
|
||||||
QML_FILES
|
QML_FILES
|
||||||
StatusColors.qml
|
StatusColors.qml
|
||||||
StatusDarkPalette.qml
|
StatusDarkPalette.qml
|
||||||
|
|
|
@ -12,8 +12,9 @@ qt6_standard_project_setup()
|
||||||
qt6_add_qml_module(${PROJECT_NAME}
|
qt6_add_qml_module(${PROJECT_NAME}
|
||||||
URI Status.TestHelpers
|
URI Status.TestHelpers
|
||||||
VERSION 1.0
|
VERSION 1.0
|
||||||
# TODO: temporary until we make qt_target_qml_sources work
|
|
||||||
QML_FILES
|
QML_FILES
|
||||||
|
|
||||||
# Required to suppress "qmllint may not work" warning
|
# Required to suppress "qmllint may not work" warning
|
||||||
OUTPUT_DIRECTORY
|
OUTPUT_DIRECTORY
|
||||||
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Status/TestHelpers
|
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Status/TestHelpers
|
||||||
|
|
|
@ -36,14 +36,14 @@ TEST(AccountsAPI, TestGetAccounts)
|
||||||
ASSERT_NE(chatIt, accounts.end());
|
ASSERT_NE(chatIt, accounts.end());
|
||||||
const auto &chatAccount = *chatIt;
|
const auto &chatAccount = *chatIt;
|
||||||
ASSERT_EQ(chatAccount.name, testAccountName);
|
ASSERT_EQ(chatAccount.name, testAccountName);
|
||||||
ASSERT_FALSE(chatAccount.path.isEmpty());
|
ASSERT_FALSE(chatAccount.path.get().isEmpty());
|
||||||
ASSERT_FALSE(chatAccount.derivedFrom.has_value());
|
ASSERT_FALSE(chatAccount.derivedFrom.has_value());
|
||||||
|
|
||||||
const auto walletIt = std::find_if(accounts.begin(), accounts.end(), [](const auto& a) { return a.isWallet; });
|
const auto walletIt = std::find_if(accounts.begin(), accounts.end(), [](const auto& a) { return a.isWallet; });
|
||||||
ASSERT_NE(walletIt, accounts.end());
|
ASSERT_NE(walletIt, accounts.end());
|
||||||
const auto &walletAccount = *walletIt;
|
const auto &walletAccount = *walletIt;
|
||||||
ASSERT_NE(walletAccount.name, testAccountName);
|
ASSERT_NE(walletAccount.name, testAccountName);
|
||||||
ASSERT_FALSE(walletAccount.path.isEmpty());
|
ASSERT_FALSE(walletAccount.path.get().isEmpty());
|
||||||
ASSERT_TRUE(walletAccount.derivedFrom.has_value());
|
ASSERT_TRUE(walletAccount.derivedFrom.has_value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,14 +53,14 @@ TEST(Accounts, TestGenerateAccountWithDerivedPath)
|
||||||
constexpr auto testAccountPassword = "password*";
|
constexpr auto testAccountPassword = "password*";
|
||||||
ScopedTestAccount testAccount(test_info_->name(), testRootAccountName, testAccountPassword, true);
|
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 newTestAccountName = u"test_generated_new_account-name"_qs;
|
||||||
const auto newTestAccountColor = QColor("fuchsia");
|
const auto newTestAccountColor = QColor("fuchsia");
|
||||||
const auto newTestAccountEmoji = u""_qs;
|
const auto newTestAccountEmoji = u""_qs;
|
||||||
const auto newTestAccountPath = Status::Constants::General::PathWalletRoot;
|
const auto newTestAccountPath = Status::Constants::General::PathWalletRoot;
|
||||||
|
|
||||||
const auto chatAccount = testAccount.firstChatAccount();
|
const auto chatAccount = testAccount.firstChatAccount();
|
||||||
Accounts::generateAccountWithDerivedPath(hashedPassword, newTestAccountName,
|
Accounts::generateAccountWithDerivedPath(password, newTestAccountName,
|
||||||
newTestAccountColor, newTestAccountEmoji,
|
newTestAccountColor, newTestAccountEmoji,
|
||||||
newTestAccountPath, chatAccount.address);
|
newTestAccountPath, chatAccount.address);
|
||||||
const auto updatedAccounts = Accounts::getAccounts();
|
const auto updatedAccounts = Accounts::getAccounts();
|
||||||
|
@ -72,13 +72,13 @@ TEST(Accounts, TestGenerateAccountWithDerivedPath)
|
||||||
});
|
});
|
||||||
ASSERT_NE(newAccountIt, updatedAccounts.end());
|
ASSERT_NE(newAccountIt, updatedAccounts.end());
|
||||||
const auto &newAccount = *newAccountIt;
|
const auto &newAccount = *newAccountIt;
|
||||||
ASSERT_FALSE(newAccount.address.isEmpty());
|
ASSERT_FALSE(newAccount.address.get().isEmpty());
|
||||||
ASSERT_FALSE(newAccount.isChat);
|
ASSERT_FALSE(newAccount.isChat);
|
||||||
ASSERT_FALSE(newAccount.isWallet);
|
ASSERT_FALSE(newAccount.isWallet);
|
||||||
ASSERT_EQ(newAccount.color, newTestAccountColor);
|
ASSERT_EQ(newAccount.color, newTestAccountColor);
|
||||||
ASSERT_FALSE(newAccount.derivedFrom.has_value());
|
ASSERT_FALSE(newAccount.derivedFrom.has_value());
|
||||||
ASSERT_EQ(newAccount.emoji, newTestAccountEmoji);
|
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_EQ(newAccount.path, newTestAccountPath);
|
||||||
ASSERT_FALSE(newAccount.publicKey.isEmpty());
|
ASSERT_FALSE(newAccount.publicKey.isEmpty());
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ TEST(AccountsAPI, TestGenerateAccountWithDerivedPath_WrongPassword)
|
||||||
|
|
||||||
const auto chatAccount = testAccount.firstChatAccount();
|
const auto chatAccount = testAccount.firstChatAccount();
|
||||||
try {
|
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,
|
QColor("fuchsia"), "", Status::Constants::General::PathWalletRoot,
|
||||||
chatAccount.address);
|
chatAccount.address);
|
||||||
FAIL();
|
FAIL();
|
||||||
|
@ -111,14 +111,14 @@ TEST(AccountsAPI, TestAddAccountWithMnemonicAndPath)
|
||||||
constexpr auto testAccountPassword = "password*";
|
constexpr auto testAccountPassword = "password*";
|
||||||
ScopedTestAccount testAccount(test_info_->name(), testRootAccountName, testAccountPassword, true);
|
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 newTestAccountName = u"test_import_from_mnemonic-name"_qs;
|
||||||
const auto newTestAccountColor = QColor("fuchsia");
|
const auto newTestAccountColor = QColor("fuchsia");
|
||||||
const auto newTestAccountEmoji = u""_qs;
|
const auto newTestAccountEmoji = u""_qs;
|
||||||
const auto newTestAccountPath = Status::Constants::General::PathWalletRoot;
|
const auto newTestAccountPath = Status::Constants::General::PathWalletRoot;
|
||||||
|
|
||||||
Accounts::addAccountWithMnemonicAndPath("festival october control quarter husband dish throw couch depth stadium cigar whisper",
|
Accounts::addAccountWithMnemonicAndPath("festival october control quarter husband dish throw couch depth stadium cigar whisper",
|
||||||
hashedPassword, newTestAccountName, newTestAccountColor, newTestAccountEmoji,
|
password, newTestAccountName, newTestAccountColor, newTestAccountEmoji,
|
||||||
newTestAccountPath);
|
newTestAccountPath);
|
||||||
const auto updatedAccounts = Accounts::getAccounts();
|
const auto updatedAccounts = Accounts::getAccounts();
|
||||||
ASSERT_EQ(updatedAccounts.size(), 3);
|
ASSERT_EQ(updatedAccounts.size(), 3);
|
||||||
|
@ -129,13 +129,13 @@ TEST(AccountsAPI, TestAddAccountWithMnemonicAndPath)
|
||||||
});
|
});
|
||||||
ASSERT_NE(newAccountIt, updatedAccounts.end());
|
ASSERT_NE(newAccountIt, updatedAccounts.end());
|
||||||
const auto &newAccount = *newAccountIt;
|
const auto &newAccount = *newAccountIt;
|
||||||
ASSERT_FALSE(newAccount.address.isEmpty());
|
ASSERT_FALSE(newAccount.address.get().isEmpty());
|
||||||
ASSERT_FALSE(newAccount.isChat);
|
ASSERT_FALSE(newAccount.isChat);
|
||||||
ASSERT_FALSE(newAccount.isWallet);
|
ASSERT_FALSE(newAccount.isWallet);
|
||||||
ASSERT_EQ(newAccount.color, newTestAccountColor);
|
ASSERT_EQ(newAccount.color, newTestAccountColor);
|
||||||
ASSERT_FALSE(newAccount.derivedFrom.has_value());
|
ASSERT_FALSE(newAccount.derivedFrom.has_value());
|
||||||
ASSERT_EQ(newAccount.emoji, newTestAccountEmoji);
|
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_EQ(newAccount.path, newTestAccountPath);
|
||||||
ASSERT_FALSE(newAccount.publicKey.isEmpty());
|
ASSERT_FALSE(newAccount.publicKey.isEmpty());
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,7 @@ TEST(AccountsAPI, TestAddAccountWithMnemonicAndPath_WrongMnemonicWorks)
|
||||||
constexpr auto testAccountPassword = "password*";
|
constexpr auto testAccountPassword = "password*";
|
||||||
ScopedTestAccount testAccount(test_info_->name(), testRootAccountName, testAccountPassword, true);
|
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 newTestAccountName = u"test_import_from_wrong_mnemonic-name"_qs;
|
||||||
const auto newTestAccountColor = QColor("fuchsia");
|
const auto newTestAccountColor = QColor("fuchsia");
|
||||||
const auto newTestAccountEmoji = u""_qs;
|
const auto newTestAccountEmoji = u""_qs;
|
||||||
|
@ -155,7 +155,7 @@ TEST(AccountsAPI, TestAddAccountWithMnemonicAndPath_WrongMnemonicWorks)
|
||||||
|
|
||||||
// Added an inexistent word. The mnemonic is not checked.
|
// Added an inexistent word. The mnemonic is not checked.
|
||||||
Accounts::addAccountWithMnemonicAndPath("october control quarter husband dish throw couch depth stadium cigar waku",
|
Accounts::addAccountWithMnemonicAndPath("october control quarter husband dish throw couch depth stadium cigar waku",
|
||||||
hashedPassword, newTestAccountName, newTestAccountColor, newTestAccountEmoji,
|
password, newTestAccountName, newTestAccountColor, newTestAccountEmoji,
|
||||||
newTestAccountPath);
|
newTestAccountPath);
|
||||||
|
|
||||||
const auto updatedAccounts = Accounts::getAccounts();
|
const auto updatedAccounts = Accounts::getAccounts();
|
||||||
|
@ -168,13 +168,13 @@ TEST(AccountsAPI, TestAddAccountWithMnemonicAndPath_WrongMnemonicWorks)
|
||||||
|
|
||||||
ASSERT_NE(newAccountIt, updatedAccounts.end());
|
ASSERT_NE(newAccountIt, updatedAccounts.end());
|
||||||
const auto &newAccount = *newAccountIt;
|
const auto &newAccount = *newAccountIt;
|
||||||
ASSERT_FALSE(newAccount.address.isEmpty());
|
ASSERT_FALSE(newAccount.address.get().isEmpty());
|
||||||
ASSERT_FALSE(newAccount.isChat);
|
ASSERT_FALSE(newAccount.isChat);
|
||||||
ASSERT_FALSE(newAccount.isWallet);
|
ASSERT_FALSE(newAccount.isWallet);
|
||||||
ASSERT_EQ(newAccount.color, newTestAccountColor);
|
ASSERT_EQ(newAccount.color, newTestAccountColor);
|
||||||
ASSERT_FALSE(newAccount.derivedFrom.has_value());
|
ASSERT_FALSE(newAccount.derivedFrom.has_value());
|
||||||
ASSERT_EQ(newAccount.emoji, newTestAccountEmoji);
|
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_EQ(newAccount.path, newTestAccountPath);
|
||||||
ASSERT_FALSE(newAccount.publicKey.isEmpty());
|
ASSERT_FALSE(newAccount.publicKey.isEmpty());
|
||||||
}
|
}
|
||||||
|
@ -189,7 +189,7 @@ TEST(AccountsAPI, TestAddAccountWatch)
|
||||||
const auto newTestAccountColor = QColor("fuchsia");
|
const auto newTestAccountColor = QColor("fuchsia");
|
||||||
const auto newTestAccountEmoji = u""_qs;
|
const auto newTestAccountEmoji = u""_qs;
|
||||||
|
|
||||||
Accounts::addAccountWatch("0x145b6B821523afFC346774b41ACC7b77A171BbA4", newTestAccountName, newTestAccountColor, newTestAccountEmoji);
|
Accounts::addAccountWatch(Accounts::EOAddress("0x145b6B821523afFC346774b41ACC7b77A171BbA4"), newTestAccountName, newTestAccountColor, newTestAccountEmoji);
|
||||||
const auto updatedAccounts = Accounts::getAccounts();
|
const auto updatedAccounts = Accounts::getAccounts();
|
||||||
ASSERT_EQ(updatedAccounts.size(), 3);
|
ASSERT_EQ(updatedAccounts.size(), 3);
|
||||||
|
|
||||||
|
@ -199,14 +199,14 @@ TEST(AccountsAPI, TestAddAccountWatch)
|
||||||
});
|
});
|
||||||
ASSERT_NE(newAccountIt, updatedAccounts.end());
|
ASSERT_NE(newAccountIt, updatedAccounts.end());
|
||||||
const auto &newAccount = *newAccountIt;
|
const auto &newAccount = *newAccountIt;
|
||||||
ASSERT_FALSE(newAccount.address.isEmpty());
|
ASSERT_FALSE(newAccount.address.get().isEmpty());
|
||||||
ASSERT_FALSE(newAccount.isChat);
|
ASSERT_FALSE(newAccount.isChat);
|
||||||
ASSERT_FALSE(newAccount.isWallet);
|
ASSERT_FALSE(newAccount.isWallet);
|
||||||
ASSERT_EQ(newAccount.color, newTestAccountColor);
|
ASSERT_EQ(newAccount.color, newTestAccountColor);
|
||||||
ASSERT_FALSE(newAccount.derivedFrom.has_value());
|
ASSERT_FALSE(newAccount.derivedFrom.has_value());
|
||||||
ASSERT_EQ(newAccount.emoji, newTestAccountEmoji);
|
ASSERT_EQ(newAccount.emoji, newTestAccountEmoji);
|
||||||
ASSERT_EQ(newAccount.mixedcaseAddress.toUpper(), newAccount.address.toUpper());
|
ASSERT_EQ(newAccount.mixedcaseAddress.toUpper(), newAccount.address.get().toUpper());
|
||||||
ASSERT_TRUE(newAccount.path.isEmpty());
|
ASSERT_TRUE(newAccount.path.get().isEmpty());
|
||||||
ASSERT_TRUE(newAccount.publicKey.isEmpty());
|
ASSERT_TRUE(newAccount.publicKey.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ TEST(AccountsAPI, TestDeleteAccount)
|
||||||
const auto newTestAccountColor = QColor("fuchsia");
|
const auto newTestAccountColor = QColor("fuchsia");
|
||||||
const auto newTestAccountEmoji = u""_qs;
|
const auto newTestAccountEmoji = u""_qs;
|
||||||
|
|
||||||
Accounts::addAccountWatch("0x145b6B821523afFC346774b41ACC7b77A171BbA4", newTestAccountName, newTestAccountColor, newTestAccountEmoji);
|
Accounts::addAccountWatch(Accounts::EOAddress("0x145b6B821523afFC346774b41ACC7b77A171BbA4"), newTestAccountName, newTestAccountColor, newTestAccountEmoji);
|
||||||
const auto updatedAccounts = Accounts::getAccounts();
|
const auto updatedAccounts = Accounts::getAccounts();
|
||||||
ASSERT_EQ(updatedAccounts.size(), 3);
|
ASSERT_EQ(updatedAccounts.size(), 3);
|
||||||
|
|
||||||
|
|
|
@ -32,11 +32,11 @@ TEST(WalletApi, TestGetDerivedAddressesForPath)
|
||||||
const auto rootAccount = testAccount.onboardingController()->accountsService()->getLoggedInAccount();
|
const auto rootAccount = testAccount.onboardingController()->accountsService()->getLoggedInAccount();
|
||||||
ASSERT_EQ(rootAccount.address, walletAccount.derivedFrom.value());
|
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;
|
const auto testPath = Status::Constants::General::PathWalletRoot;
|
||||||
|
|
||||||
// chatAccount.address
|
// 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
|
// Check that no change is done
|
||||||
const auto updatedAccounts = Accounts::getAccounts();
|
const auto updatedAccounts = Accounts::getAccounts();
|
||||||
ASSERT_EQ(updatedAccounts.size(), 2);
|
ASSERT_EQ(updatedAccounts.size(), 2);
|
||||||
|
@ -47,14 +47,14 @@ TEST(WalletApi, TestGetDerivedAddressesForPath)
|
||||||
// all hasActivity are false
|
// all hasActivity are false
|
||||||
ASSERT_TRUE(std::none_of(chatDerivedAddresses.begin(), chatDerivedAddresses.end(), [](const auto& a) { return a.hasActivity; }));
|
ASSERT_TRUE(std::none_of(chatDerivedAddresses.begin(), chatDerivedAddresses.end(), [](const auto& a) { return a.hasActivity; }));
|
||||||
// all address are valid
|
// 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);
|
ASSERT_EQ(walletDerivedAddresses.size(), 2);
|
||||||
// all alreadyCreated are false
|
// all alreadyCreated are false
|
||||||
ASSERT_TRUE(std::none_of(walletDerivedAddresses.begin(), walletDerivedAddresses.end(), [](const auto& a) { return a.alreadyCreated; }));
|
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(rootDerivedAddresses.size(), 4);
|
||||||
ASSERT_EQ(std::count_if(rootDerivedAddresses.begin(), rootDerivedAddresses.end(), [](const auto& a) { return a.alreadyCreated; }), 1);
|
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; });
|
const auto &existingAddress = *std::find_if(rootDerivedAddresses.begin(), rootDerivedAddresses.end(), [](const auto& a) { return a.alreadyCreated; });
|
||||||
|
|
Loading…
Reference in New Issue