chore(cpp): apply clang-format
This commit is contained in:
parent
1dcc3a1f2f
commit
c53264b124
|
@ -2,14 +2,13 @@
|
|||
|
||||
#include <QtQml/QQmlEngine>
|
||||
|
||||
namespace Status::Application {
|
||||
namespace Status::Application
|
||||
{
|
||||
|
||||
ApplicationController::ApplicationController(QObject* parent)
|
||||
: QObject{parent}
|
||||
, m_dataProvider(std::make_unique<DataProvider>())
|
||||
{
|
||||
|
||||
}
|
||||
{ }
|
||||
|
||||
void ApplicationController::initOnLogin()
|
||||
{
|
||||
|
@ -30,10 +29,9 @@ QObject *ApplicationController::statusAccount() const
|
|||
|
||||
void ApplicationController::setStatusAccount(QObject* newStatusAccount)
|
||||
{
|
||||
if (m_statusAccount == newStatusAccount)
|
||||
return;
|
||||
if(m_statusAccount == newStatusAccount) return;
|
||||
m_statusAccount = newStatusAccount;
|
||||
emit statusAccountChanged();
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status::Application
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "DbSettingsObj.h"
|
||||
#include "DataProvider.h"
|
||||
#include "DbSettingsObj.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QtQml/qqmlregistration.h>
|
||||
|
@ -9,7 +9,8 @@
|
|||
// TODO: investigate. This line breaks qobject_cast in OnboardingController::login
|
||||
//#include <Onboarding/UserAccount.h>
|
||||
|
||||
namespace Status::Application {
|
||||
namespace Status::Application
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Responsible for providing general information and utility components
|
||||
|
@ -41,4 +42,4 @@ private:
|
|||
std::shared_ptr<DbSettingsObj> m_dbSettings;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Status::Application
|
||||
|
|
|
@ -6,18 +6,20 @@ namespace StatusGo = Status::StatusGo;
|
|||
|
||||
DataProvider::DataProvider()
|
||||
: QObject(nullptr)
|
||||
{
|
||||
}
|
||||
{ }
|
||||
|
||||
StatusGo::Settings::SettingsDto DataProvider::getSettings() const
|
||||
{
|
||||
try {
|
||||
try
|
||||
{
|
||||
return StatusGo::Settings::getSettings();
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
catch(std::exception& e)
|
||||
{
|
||||
qWarning() << "DataProvider::getSettings, error: " << e.what();
|
||||
}
|
||||
catch (...) {
|
||||
catch(...)
|
||||
{
|
||||
qWarning() << "DataProvider::getSettings, unknown error";
|
||||
}
|
||||
return StatusGo::Settings::SettingsDto{};
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <StatusGo/SettingsAPI>
|
||||
#include <QtCore/QtCore>
|
||||
#include <StatusGo/SettingsAPI>
|
||||
|
||||
namespace Status::Application {
|
||||
namespace Status::Application
|
||||
{
|
||||
|
||||
class DataProvider : public QObject
|
||||
{
|
||||
|
@ -14,4 +15,4 @@ namespace Status::Application {
|
|||
|
||||
StatusGo::Settings::SettingsDto getSettings() const;
|
||||
};
|
||||
}
|
||||
} // namespace Status::Application
|
||||
|
|
|
@ -5,8 +5,7 @@ using namespace Status::Application;
|
|||
DbSettingsObj::DbSettingsObj(StatusGo::Settings::SettingsDto rawData)
|
||||
: QObject(nullptr)
|
||||
, m_data(std::move(rawData))
|
||||
{
|
||||
}
|
||||
{ }
|
||||
|
||||
QString DbSettingsObj::address() const
|
||||
{
|
||||
|
@ -15,8 +14,7 @@ QString DbSettingsObj::address() const
|
|||
|
||||
void DbSettingsObj::setAddress(const QString& value)
|
||||
{
|
||||
if (m_data.address == value)
|
||||
return;
|
||||
if(m_data.address == value) return;
|
||||
m_data.address = value;
|
||||
emit addressChanged();
|
||||
}
|
||||
|
@ -28,8 +26,7 @@ QString DbSettingsObj::displayName() const
|
|||
|
||||
void DbSettingsObj::setDisplayName(const QString& value)
|
||||
{
|
||||
if (m_data.displayName == value)
|
||||
return;
|
||||
if(m_data.displayName == value) return;
|
||||
m_data.displayName = value;
|
||||
emit displayNameChanged();
|
||||
}
|
||||
|
@ -41,8 +38,7 @@ QString DbSettingsObj::preferredName() const
|
|||
|
||||
void DbSettingsObj::setPreferredName(const QString& value)
|
||||
{
|
||||
if (m_data.preferredName == value)
|
||||
return;
|
||||
if(m_data.preferredName == value) return;
|
||||
m_data.preferredName = value;
|
||||
emit preferredNameChanged();
|
||||
}
|
||||
|
@ -54,8 +50,7 @@ QString DbSettingsObj::keyUid() const
|
|||
|
||||
void DbSettingsObj::setKeyUid(const QString& value)
|
||||
{
|
||||
if (m_data.keyUid == value)
|
||||
return;
|
||||
if(m_data.keyUid == value) return;
|
||||
m_data.keyUid = value;
|
||||
emit keyUidChanged();
|
||||
}
|
||||
|
@ -67,8 +62,7 @@ QString DbSettingsObj::publicKey() const
|
|||
|
||||
void DbSettingsObj::setPublicKey(const QString& value)
|
||||
{
|
||||
if (m_data.publicKey == value)
|
||||
return;
|
||||
if(m_data.publicKey == value) return;
|
||||
m_data.publicKey = value;
|
||||
emit publicKeyChanged();
|
||||
}
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
#include <QtCore/QtCore>
|
||||
|
||||
namespace Status::Application {
|
||||
namespace Status::Application
|
||||
{
|
||||
|
||||
class DbSettingsObj : public QObject
|
||||
{
|
||||
|
@ -16,7 +17,6 @@ namespace Status::Application {
|
|||
Q_PROPERTY(QString keyUid READ keyUid NOTIFY keyUidChanged)
|
||||
Q_PROPERTY(QString publicKey READ publicKey NOTIFY publicKeyChanged)
|
||||
|
||||
|
||||
public:
|
||||
explicit DbSettingsObj(StatusGo::Settings::SettingsDto rawData);
|
||||
|
||||
|
@ -35,7 +35,6 @@ namespace Status::Application {
|
|||
[[nodiscard]] QString publicKey() const;
|
||||
void setPublicKey(const QString& value);
|
||||
|
||||
|
||||
signals:
|
||||
void addressChanged();
|
||||
void displayNameChanged();
|
||||
|
@ -46,4 +45,4 @@ namespace Status::Application {
|
|||
private:
|
||||
StatusGo::Settings::SettingsDto m_data;
|
||||
};
|
||||
}
|
||||
} // namespace Status::Application
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
#include <Helpers/helpers.h>
|
||||
#include <Helpers/logs.h>
|
||||
|
||||
#include <QDir>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
|
||||
using namespace Status;
|
||||
|
||||
|
@ -24,9 +24,11 @@ int main(int argc, char *argv[])
|
|||
|
||||
QTranslator translator;
|
||||
const QStringList uiLanguages = QLocale::system().uiLanguages();
|
||||
for (const QString &locale : uiLanguages) {
|
||||
for(const QString& locale : uiLanguages)
|
||||
{
|
||||
const QString baseName = BUILD_PROJECT_NAME + QLocale(locale).name();
|
||||
if (translator.load(":/i18n/" + baseName)) {
|
||||
if(translator.load(":/i18n/" + baseName))
|
||||
{
|
||||
app.installTranslator(&translator);
|
||||
break;
|
||||
}
|
||||
|
@ -35,17 +37,21 @@ int main(int argc, char *argv[])
|
|||
QQmlApplicationEngine engine;
|
||||
|
||||
const QUrl url(u"qrc:/Status/Application/qml/main.qml"_qs);
|
||||
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
|
||||
&app, [url](QObject *obj, const QUrl &objUrl) {
|
||||
if (!obj && url == objUrl)
|
||||
QCoreApplication::exit(-1);
|
||||
}, Qt::QueuedConnection);
|
||||
QObject::connect(
|
||||
&engine,
|
||||
&QQmlApplicationEngine::objectCreated,
|
||||
&app,
|
||||
[url](QObject* obj, const QUrl& objUrl) {
|
||||
if(!obj && url == objUrl) QCoreApplication::exit(-1);
|
||||
},
|
||||
Qt::QueuedConnection);
|
||||
engine.load(url);
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
||||
void setApplicationInformation(QGuiApplication& app) {
|
||||
void setApplicationInformation(QGuiApplication& app)
|
||||
{
|
||||
#if !defined BUILD_PROJECT_ORGANIZATION_NAME
|
||||
static_assert(false, "Compile-time define missing: BUILD_PROJECT_ORGANIZATION_NAME")
|
||||
#endif
|
||||
|
|
|
@ -8,12 +8,14 @@
|
|||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace Status::ApplicationCore {
|
||||
namespace Status::ApplicationCore
|
||||
{
|
||||
|
||||
namespace {
|
||||
namespace
|
||||
{
|
||||
constexpr auto statusFolder = "Status";
|
||||
constexpr auto dataSubfolder = "data";
|
||||
}
|
||||
} // namespace
|
||||
|
||||
UserConfiguration::UserConfiguration(QObject* parent)
|
||||
: QObject{parent}
|
||||
|
@ -34,8 +36,7 @@ const fs::path &UserConfiguration::userDataFolder() const
|
|||
void UserConfiguration::setUserDataFolder(const QString& newUserDataFolder)
|
||||
{
|
||||
auto newVal = Status::toPath(newUserDataFolder);
|
||||
if (m_userDataFolder.compare(newVal) == 0)
|
||||
return;
|
||||
if(m_userDataFolder.compare(newVal) == 0) return;
|
||||
m_userDataFolder = newVal;
|
||||
emit userDataFolderChanged();
|
||||
}
|
||||
|
@ -43,7 +44,8 @@ void UserConfiguration::setUserDataFolder(const QString &newUserDataFolder)
|
|||
void UserConfiguration::generateReleaseConfiguration()
|
||||
{
|
||||
if(!parseFromCommandLineAndReturnTrueIfSet())
|
||||
m_userDataFolder = toPath(QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation))/statusFolder/dataSubfolder;
|
||||
m_userDataFolder =
|
||||
toPath(QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation)) / statusFolder / dataSubfolder;
|
||||
emit userDataFolderChanged();
|
||||
}
|
||||
|
||||
|
@ -55,7 +57,8 @@ bool UserConfiguration::parseFromCommandLineAndReturnTrueIfSet()
|
|||
parser.addPositionalArgument("dataDir", "Data folder");
|
||||
parser.process(*QCoreApplication::instance());
|
||||
auto args = parser.positionalArguments();
|
||||
if (args.size() > 0) {
|
||||
if(args.size() > 0)
|
||||
{
|
||||
m_userDataFolder = toPath(args[0]);
|
||||
emit userDataFolderChanged();
|
||||
return true;
|
||||
|
@ -63,4 +66,4 @@ bool UserConfiguration::parseFromCommandLineAndReturnTrueIfSet()
|
|||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status::ApplicationCore
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
|
||||
#include <filesystem>
|
||||
|
||||
namespace Status::ApplicationCore {
|
||||
namespace Status::ApplicationCore
|
||||
{
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
|
@ -35,4 +36,4 @@ private:
|
|||
fs::path m_userDataFolder;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Status::ApplicationCore
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <StatusGo/ChatAPI>
|
||||
#include <QtCore/QtCore>
|
||||
#include <StatusGo/ChatAPI>
|
||||
|
||||
namespace Status::ChatSection {
|
||||
namespace Status::ChatSection
|
||||
{
|
||||
|
||||
class ChatDataProvider : public QObject
|
||||
{
|
||||
|
@ -14,4 +15,4 @@ namespace Status::ChatSection {
|
|||
|
||||
StatusGo::Chats::ChannelGroupDto getSectionData(const QString& sectionId) const;
|
||||
};
|
||||
}
|
||||
} // namespace Status::ChatSection
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
#include <QtCore/QtCore>
|
||||
|
||||
namespace Status::ChatSection {
|
||||
namespace Status::ChatSection
|
||||
{
|
||||
|
||||
class ChatItem : public QObject
|
||||
{
|
||||
|
@ -49,4 +50,4 @@ namespace Status::ChatSection {
|
|||
};
|
||||
|
||||
using ChatItemPtr = std::shared_ptr<ChatItem>;
|
||||
}
|
||||
} // namespace Status::ChatSection
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include "ChatItem.h"
|
||||
#include "ChatDataProvider.h"
|
||||
#include "ChatItem.h"
|
||||
|
||||
#include <Helpers/QObjectVectorModel.h>
|
||||
|
||||
namespace Status::ChatSection {
|
||||
namespace Status::ChatSection
|
||||
{
|
||||
|
||||
class ChatSectionController : public QObject
|
||||
{
|
||||
|
@ -34,4 +35,4 @@ namespace Status::ChatSection {
|
|||
std::unique_ptr<ChatDataProvider> m_dataProvider;
|
||||
ChatItemPtr m_currentChat;
|
||||
};
|
||||
}
|
||||
} // namespace Status::ChatSection
|
||||
|
|
|
@ -6,22 +6,24 @@ namespace StatusGo = Status::StatusGo;
|
|||
|
||||
ChatDataProvider::ChatDataProvider()
|
||||
: QObject(nullptr)
|
||||
{
|
||||
}
|
||||
{ }
|
||||
|
||||
StatusGo::Chats::ChannelGroupDto ChatDataProvider::getSectionData(const QString& sectionId) const
|
||||
{
|
||||
try {
|
||||
try
|
||||
{
|
||||
auto result = StatusGo::Chats::getChats();
|
||||
for(auto chGroup : result.allChannelGroups) {
|
||||
if (chGroup.id == sectionId)
|
||||
return chGroup;
|
||||
for(auto chGroup : result.allChannelGroups)
|
||||
{
|
||||
if(chGroup.id == sectionId) return chGroup;
|
||||
}
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
catch(std::exception& e)
|
||||
{
|
||||
qWarning() << "ChatDataProvider::getSectionData, error: " << e.what();
|
||||
}
|
||||
catch (...) {
|
||||
catch(...)
|
||||
{
|
||||
qWarning() << "ChatDataProvider::getSectionData, unknown error";
|
||||
}
|
||||
return StatusGo::Chats::ChannelGroupDto{};
|
||||
|
|
|
@ -5,8 +5,7 @@ using namespace Status::ChatSection;
|
|||
ChatItem::ChatItem(StatusGo::Chats::ChatDto rawData)
|
||||
: QObject(nullptr)
|
||||
, m_data(std::move(rawData))
|
||||
{
|
||||
}
|
||||
{ }
|
||||
|
||||
QString ChatItem::id() const
|
||||
{
|
||||
|
@ -20,8 +19,7 @@ QString ChatItem::name() const
|
|||
|
||||
void ChatItem::setName(const QString& value)
|
||||
{
|
||||
if (m_data.name == value)
|
||||
return;
|
||||
if(m_data.name == value) return;
|
||||
m_data.name = value;
|
||||
emit nameChanged();
|
||||
}
|
||||
|
@ -33,8 +31,7 @@ QString ChatItem::description() const
|
|||
|
||||
void ChatItem::setDescription(const QString& value)
|
||||
{
|
||||
if (m_data.description == value)
|
||||
return;
|
||||
if(m_data.description == value) return;
|
||||
m_data.description = value;
|
||||
emit descriptionChanged();
|
||||
}
|
||||
|
@ -46,8 +43,7 @@ QColor ChatItem::color() const
|
|||
|
||||
void ChatItem::setColor(const QColor& value)
|
||||
{
|
||||
if (m_data.color == value)
|
||||
return;
|
||||
if(m_data.color == value) return;
|
||||
m_data.color = value;
|
||||
emit colorChanged();
|
||||
}
|
||||
|
@ -59,8 +55,7 @@ bool ChatItem::muted() const
|
|||
|
||||
void ChatItem::setMuted(bool value)
|
||||
{
|
||||
if (m_data.muted == value)
|
||||
return;
|
||||
if(m_data.muted == value) return;
|
||||
m_data.muted = value;
|
||||
emit mutedChanged();
|
||||
}
|
||||
|
@ -72,8 +67,7 @@ bool ChatItem::active() const
|
|||
|
||||
void ChatItem::setActive(bool value)
|
||||
{
|
||||
if (m_data.active == value)
|
||||
return;
|
||||
if(m_data.active == value) return;
|
||||
m_data.active = value;
|
||||
emit activeChanged();
|
||||
}
|
||||
|
|
|
@ -5,15 +5,15 @@ using namespace Status::ChatSection;
|
|||
ChatSectionController::ChatSectionController()
|
||||
: QObject(nullptr)
|
||||
, m_dataProvider(std::make_unique<ChatDataProvider>())
|
||||
{
|
||||
}
|
||||
{ }
|
||||
|
||||
void ChatSectionController::init(const QString& sectionId)
|
||||
{
|
||||
auto chatSectionData = m_dataProvider->getSectionData(sectionId);
|
||||
assert(chatSectionData.chats.size() > 0);
|
||||
std::vector<ChatItemPtr> model;
|
||||
for (auto c : chatSectionData.chats) {
|
||||
for(auto c : chatSectionData.chats)
|
||||
{
|
||||
model.push_back(std::make_shared<ChatItem>(std::move(c)));
|
||||
}
|
||||
m_chats = std::make_shared<ChatsModel>(std::move(model), "chat");
|
||||
|
@ -34,8 +34,7 @@ ChatItem* ChatSectionController::currentChat() const
|
|||
void ChatSectionController::setCurrentChatIndex(int index)
|
||||
{
|
||||
auto chat = index >= 0 && index < m_chats->size() ? m_chats->get(index) : ChatItemPtr();
|
||||
if (m_currentChat == chat)
|
||||
return;
|
||||
if(m_currentChat == chat) return;
|
||||
|
||||
m_currentChat = chat;
|
||||
emit currentChatChanged();
|
||||
|
|
|
@ -6,13 +6,12 @@
|
|||
if(REQUIRED) \
|
||||
j.at(NAME).get_to(d.FIELD); \
|
||||
else if(j.contains(NAME)) \
|
||||
j.at(NAME).get_to(d.FIELD); \
|
||||
j.at(NAME).get_to(d.FIELD);
|
||||
|
||||
#define STATUS_READ_NLOHMAN_JSON_PROPERTY_2_ARGS(FIELD, NAME) \
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY_3_ARGS(FIELD, NAME, true)
|
||||
|
||||
#define STATUS_READ_NLOHMAN_JSON_PROPERTY_1_ARGS(FIELD) \
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY_2_ARGS(FIELD, #FIELD)
|
||||
#define STATUS_READ_NLOHMAN_JSON_PROPERTY_1_ARGS(FIELD) STATUS_READ_NLOHMAN_JSON_PROPERTY_2_ARGS(FIELD, #FIELD)
|
||||
|
||||
// This macro reads prop from the nlohman json object. It implies that nlohman json object is named `j` and the struct
|
||||
// instance that json object should be mapped to is named `d`.
|
||||
|
@ -28,11 +27,7 @@ STATUS_READ_NLOHMAN_JSON_PROPERTY_2_ARGS(FIELD, #FIELD)
|
|||
// STATUS_READ_NLOHMAN_JSON_PROPERTY(field, "realFieldName", false)
|
||||
//
|
||||
#define STATUS_READ_NLOHMAN_JSON_PROPERTY(...) \
|
||||
STATUS_EXPAND( \
|
||||
STATUS_MACRO_SELECTOR_3_ARGS( \
|
||||
__VA_ARGS__, \
|
||||
STATUS_EXPAND(STATUS_MACRO_SELECTOR_3_ARGS(__VA_ARGS__, \
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY_3_ARGS, \
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY_2_ARGS, \
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY_1_ARGS \
|
||||
)(__VA_ARGS__) \
|
||||
)
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY_1_ARGS)(__VA_ARGS__))
|
||||
|
|
|
@ -4,9 +4,7 @@
|
|||
#define STATUS_EXPAND(x) x
|
||||
|
||||
// 2 arguments macro selector.
|
||||
#define STATUS_MACRO_SELECTOR_2_ARGS(_1, _2, selected, ...) \
|
||||
selected
|
||||
#define STATUS_MACRO_SELECTOR_2_ARGS(_1, _2, selected, ...) selected
|
||||
|
||||
// 3 arguments macro selector.
|
||||
#define STATUS_MACRO_SELECTOR_3_ARGS(_1, _2, _3, selected, ...) \
|
||||
selected
|
||||
#define STATUS_MACRO_SELECTOR_3_ARGS(_1, _2, _3, selected, ...) selected
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Status::Helpers {
|
||||
namespace Status::Helpers
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
using IsNotReference = typename std::enable_if<!std::is_reference<T>::value, void>::type;
|
||||
|
@ -19,27 +20,52 @@ class NamedType
|
|||
public:
|
||||
using UnderlyingType = T;
|
||||
|
||||
explicit constexpr NamedType(T const& value) : m_value(value) {}
|
||||
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(T&& value)
|
||||
: m_value(std::move(value))
|
||||
{ }
|
||||
explicit constexpr NamedType() = default;
|
||||
|
||||
constexpr T& get() {
|
||||
constexpr T& get()
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
constexpr std::remove_reference_t<T> const& get() const {
|
||||
constexpr std::remove_reference_t<T> const& get() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
bool operator<(const NamedType<T, Parameter> &other) const { return m_value < other.m_value; };
|
||||
bool operator>(const NamedType<T, Parameter> &other) const { return m_value > other.m_value; };
|
||||
bool operator<=(const NamedType<T, Parameter> &other) const { return m_value <= other.m_value; };
|
||||
bool operator>=(const NamedType<T, Parameter> &other) const { return m_value >= other.m_value; };
|
||||
bool operator==(const NamedType<T, Parameter> &other) const { return m_value == other.m_value; };
|
||||
bool operator!=(const NamedType<T, Parameter> &other) const { return m_value != other.m_value; };
|
||||
bool operator<(const NamedType<T, Parameter>& other) const
|
||||
{
|
||||
return m_value < other.m_value;
|
||||
};
|
||||
bool operator>(const NamedType<T, Parameter>& other) const
|
||||
{
|
||||
return m_value > other.m_value;
|
||||
};
|
||||
bool operator<=(const NamedType<T, Parameter>& other) const
|
||||
{
|
||||
return m_value <= other.m_value;
|
||||
};
|
||||
bool operator>=(const NamedType<T, Parameter>& other) const
|
||||
{
|
||||
return m_value >= other.m_value;
|
||||
};
|
||||
bool operator==(const NamedType<T, Parameter>& other) const
|
||||
{
|
||||
return m_value == other.m_value;
|
||||
};
|
||||
bool operator!=(const NamedType<T, Parameter>& other) const
|
||||
{
|
||||
return m_value != other.m_value;
|
||||
};
|
||||
|
||||
T &operator=(NamedType<T, Parameter> const& rhs) {
|
||||
T& operator=(NamedType<T, Parameter> const& rhs)
|
||||
{
|
||||
return m_value = rhs.m_value;
|
||||
};
|
||||
|
||||
|
@ -48,16 +74,18 @@ private:
|
|||
};
|
||||
|
||||
template <typename T, typename P>
|
||||
void to_json(json& j, const NamedType<T, P>& 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) {
|
||||
void from_json(const json& j, NamedType<T, P>& p)
|
||||
{
|
||||
p = NamedType<T, P>{j.get<T>()};
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status::Helpers
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
#include <QAbstractListModel>
|
||||
#include <QQmlEngine>
|
||||
|
||||
namespace Status::Helpers {
|
||||
namespace Status::Helpers
|
||||
{
|
||||
|
||||
/// Generic typed QObject provider model
|
||||
///
|
||||
|
@ -15,83 +16,96 @@ class QObjectVectorModel final : public QAbstractListModel
|
|||
static_assert(std::is_base_of<QObject, T>::value, "Template parameter (T) not a QObject");
|
||||
|
||||
public:
|
||||
|
||||
using ObjectContainer = std::vector<std::shared_ptr<T>>;
|
||||
|
||||
explicit QObjectVectorModel(ObjectContainer initialObjects, const char* objectRoleName, QObject* parent = nullptr)
|
||||
: QAbstractListModel(parent)
|
||||
, m_objects(std::move(initialObjects))
|
||||
, m_roleName(objectRoleName)
|
||||
{
|
||||
}
|
||||
{ }
|
||||
explicit QObjectVectorModel(const char* objectRoleName, QObject* parent = nullptr)
|
||||
: QObjectVectorModel(ObjectContainer{}, objectRoleName, parent)
|
||||
{ }
|
||||
~QObjectVectorModel(){};
|
||||
|
||||
QHash<int, QByteArray> roleNames() const override {
|
||||
QHash<int, QByteArray> roleNames() const override
|
||||
{
|
||||
return {{ObjectRole, m_roleName}};
|
||||
};
|
||||
|
||||
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override {
|
||||
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return m_objects.size();
|
||||
}
|
||||
|
||||
virtual QVariant data(const QModelIndex& index, int role) const override {
|
||||
if(!QAbstractItemModel::checkIndex(index) || role != ObjectRole)
|
||||
return QVariant();
|
||||
virtual QVariant data(const QModelIndex& index, int role) const override
|
||||
{
|
||||
if(!QAbstractItemModel::checkIndex(index) || role != ObjectRole) return QVariant();
|
||||
|
||||
return QVariant::fromValue<QObject*>(m_objects[index.row()].get());
|
||||
}
|
||||
|
||||
const T* at(size_t pos) const {
|
||||
const T* at(size_t pos) const
|
||||
{
|
||||
return m_objects.at(pos).get();
|
||||
};
|
||||
|
||||
std::shared_ptr<T> get(size_t pos) {
|
||||
std::shared_ptr<T> get(size_t pos)
|
||||
{
|
||||
return m_objects.at(pos);
|
||||
};
|
||||
|
||||
size_t size() const {
|
||||
size_t size() const
|
||||
{
|
||||
return m_objects.size();
|
||||
};
|
||||
|
||||
void reset(const ObjectContainer& objects) {
|
||||
void reset(const ObjectContainer& objects)
|
||||
{
|
||||
beginResetModel();
|
||||
m_objects = objects;
|
||||
endResetModel();
|
||||
};
|
||||
|
||||
void clear() {
|
||||
void clear()
|
||||
{
|
||||
reset({});
|
||||
};
|
||||
|
||||
void push_back(const std::shared_ptr<T>& newValue) {
|
||||
void push_back(const std::shared_ptr<T>& newValue)
|
||||
{
|
||||
beginInsertRows(QModelIndex(), m_objects.size(), m_objects.size());
|
||||
m_objects.push_back(newValue);
|
||||
endInsertRows();
|
||||
};
|
||||
|
||||
void resize(size_t count) {
|
||||
if(count > m_objects.size()) {
|
||||
void resize(size_t count)
|
||||
{
|
||||
if(count > m_objects.size())
|
||||
{
|
||||
beginInsertRows(QModelIndex(), m_objects.size(), count - 1);
|
||||
m_objects.resize(count);
|
||||
endInsertRows();
|
||||
}
|
||||
else if(count < m_objects.size()) {
|
||||
else if(count < m_objects.size())
|
||||
{
|
||||
beginRemoveRows(QModelIndex(), count, m_objects.size() - 1);
|
||||
m_objects.resize(count);
|
||||
endRemoveRows();
|
||||
}
|
||||
};
|
||||
|
||||
void set(size_t row, const std::shared_ptr<T>& newVal) {
|
||||
void set(size_t row, const std::shared_ptr<T>& newVal)
|
||||
{
|
||||
m_objects.at(row) = newVal;
|
||||
emit dataChanged(index(row), index(row), {});
|
||||
};
|
||||
|
||||
const ObjectContainer &objects() const { return m_objects; };
|
||||
const ObjectContainer& objects() const
|
||||
{
|
||||
return m_objects;
|
||||
};
|
||||
|
||||
private:
|
||||
ObjectContainer m_objects;
|
||||
|
@ -101,4 +115,4 @@ private:
|
|||
constexpr static auto ObjectRole = Qt::UserRole + 1;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Status::Helpers
|
||||
|
|
|
@ -19,9 +19,9 @@ public:
|
|||
|
||||
Singleton<T>(const Singleton<T>&) = delete;
|
||||
Singleton<T>& operator=(const Singleton<T>&) = delete;
|
||||
private:
|
||||
|
||||
private:
|
||||
Singleton<T>() = default;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Status::Helpers
|
||||
|
|
|
@ -2,14 +2,17 @@
|
|||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace Status {
|
||||
namespace Status
|
||||
{
|
||||
|
||||
QString toQString(const fs::path &path) {
|
||||
QString toQString(const fs::path& path)
|
||||
{
|
||||
return QString::fromStdString(path.string());
|
||||
}
|
||||
|
||||
fs::path toPath(const QString &pathStr) {
|
||||
fs::path toPath(const QString& pathStr)
|
||||
{
|
||||
return fs::path(pathStr.toStdString());
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
#include "helpers.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
#include <QColor>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
|
||||
#include <filesystem>
|
||||
|
@ -13,7 +13,8 @@
|
|||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Status {
|
||||
namespace Status
|
||||
{
|
||||
|
||||
QString toQString(const std::filesystem::path& path);
|
||||
|
||||
|
@ -21,15 +22,19 @@ std::filesystem::path toPath(const QString& pathStr);
|
|||
|
||||
} // namespace Status
|
||||
|
||||
namespace nlohmann {
|
||||
namespace nlohmann
|
||||
{
|
||||
|
||||
template <>
|
||||
struct adl_serializer<QString> {
|
||||
static void to_json(json& j, const QString& str) {
|
||||
struct adl_serializer<QString>
|
||||
{
|
||||
static void to_json(json& j, const QString& str)
|
||||
{
|
||||
j = str.toStdString();
|
||||
}
|
||||
|
||||
static void from_json(const json& j, QString& str) {
|
||||
static void from_json(const json& j, QString& str)
|
||||
{
|
||||
str = QString::fromStdString(j.get<std::string>());
|
||||
}
|
||||
};
|
||||
|
@ -37,12 +42,15 @@ struct adl_serializer<QString> {
|
|||
using namespace std::string_literals;
|
||||
|
||||
template <>
|
||||
struct adl_serializer<QByteArray> {
|
||||
static void to_json(json& j, const QByteArray& data) {
|
||||
struct adl_serializer<QByteArray>
|
||||
{
|
||||
static void to_json(json& j, const QByteArray& data)
|
||||
{
|
||||
j = data.toStdString();
|
||||
}
|
||||
|
||||
static void from_json(const json& j, QByteArray& data) {
|
||||
static void from_json(const json& j, QByteArray& data)
|
||||
{
|
||||
auto str = j.get<std::string>();
|
||||
if(str.size() >= 2 && Status::Helpers::iequals(str, "0x"s, 2))
|
||||
data = QByteArray::fromHex(QByteArray::fromRawData(str.c_str() + 2 * sizeof(str[0]), str.size() - 2));
|
||||
|
@ -52,34 +60,43 @@ struct adl_serializer<QByteArray> {
|
|||
};
|
||||
|
||||
template <>
|
||||
struct adl_serializer<QColor> {
|
||||
static void to_json(json& j, const QColor& color) {
|
||||
struct adl_serializer<QColor>
|
||||
{
|
||||
static void to_json(json& j, const QColor& color)
|
||||
{
|
||||
j = color.name();
|
||||
}
|
||||
|
||||
static void from_json(const json& j, QColor& color) {
|
||||
static void from_json(const json& j, QColor& color)
|
||||
{
|
||||
color = QColor(QString::fromStdString(j.get<std::string>()));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct adl_serializer<QUrl> {
|
||||
static void to_json(json& j, const QUrl& url) {
|
||||
struct adl_serializer<QUrl>
|
||||
{
|
||||
static void to_json(json& j, const QUrl& url)
|
||||
{
|
||||
j = url.toString();
|
||||
}
|
||||
|
||||
static void from_json(const json& j, QUrl& url) {
|
||||
static void from_json(const json& j, QUrl& url)
|
||||
{
|
||||
url = QUrl(QString::fromStdString(j.get<std::string>()));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct adl_serializer<std::optional<T>> {
|
||||
static void to_json(json& j, const std::optional<T>& opt) {
|
||||
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) {
|
||||
static void from_json(const json& j, std::optional<T>& opt)
|
||||
{
|
||||
opt.emplace(j.get<T>());
|
||||
}
|
||||
};
|
||||
|
|
|
@ -4,11 +4,12 @@
|
|||
|
||||
#include <QObject>
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <memory.h>
|
||||
#include <string>
|
||||
|
||||
namespace Status::Helpers {
|
||||
namespace Status::Helpers
|
||||
{
|
||||
|
||||
constexpr bool isDebugBuild()
|
||||
{
|
||||
|
@ -26,11 +27,11 @@ template<typename T>
|
|||
bool iequals(const T& a, const T& b, size_t len = -1)
|
||||
{
|
||||
return len < a.size() && len < b.size() &&
|
||||
std::equal(a.begin(), len >= 0 ? a.end() : a.begin() + len,
|
||||
b.begin(), len >= 0 ? b.end() : b.begin() + len,
|
||||
[](auto a, auto b) {
|
||||
return tolower(a) == tolower(b);
|
||||
});
|
||||
std::equal(a.begin(),
|
||||
len >= 0 ? a.end() : a.begin() + len,
|
||||
b.begin(),
|
||||
len >= 0 ? b.end() : b.begin() + len,
|
||||
[](auto a, auto b) { return tolower(a) == tolower(b); });
|
||||
}
|
||||
|
||||
template <typename KeyType, typename ValT>
|
||||
|
@ -43,14 +44,16 @@ std::vector<KeyType> getKeys(const std::map<KeyType, ValT>& map)
|
|||
return keys;
|
||||
}
|
||||
|
||||
static void doDeleteLater(QObject *obj) {
|
||||
static void doDeleteLater(QObject* obj)
|
||||
{
|
||||
obj->deleteLater();
|
||||
}
|
||||
|
||||
// TODO: use https://en.cppreference.com/w/cpp/memory/shared_ptr/allocate_shared
|
||||
template <typename T, typename... Args>
|
||||
std::shared_ptr<T> makeSharedQObject(Args&& ...args) {
|
||||
std::shared_ptr<T> makeSharedQObject(Args&&... args)
|
||||
{
|
||||
return std::shared_ptr<T>(new T(std::forward<Args>(args)...), doDeleteLater);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status::Helpers
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
|
||||
#include "BuildConfiguration.h"
|
||||
|
||||
namespace Status::Helpers {
|
||||
namespace Status::Helpers
|
||||
{
|
||||
|
||||
void logFormatter(QtMsgType type, const QMessageLogContext& context, const QString& msg)
|
||||
{
|
||||
|
@ -37,7 +38,12 @@ void logFormatter(QtMsgType type, const QMessageLogContext& context, const QStri
|
|||
case QtFatalMsg: log = "\033[0;31m!!! \033[0m%s \033[1m%s \033[0;33mfile=\033[94m%s:%u %s\n"; break;
|
||||
}
|
||||
fprintf(type == QtCriticalMsg || type == QtFatalMsg ? stderr : stdout,
|
||||
log, timestamp.constData(), localMsg.constData(), file, context.line, function.constData());
|
||||
log,
|
||||
timestamp.constData(),
|
||||
localMsg.constData(),
|
||||
file,
|
||||
context.line,
|
||||
function.constData());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace Status::Helpers
|
||||
|
|
|
@ -4,9 +4,10 @@
|
|||
#include <QDebug>
|
||||
#include <QString>
|
||||
|
||||
namespace Status::Helpers {
|
||||
namespace Status::Helpers
|
||||
{
|
||||
|
||||
/// Formats with colloring output if not a development build
|
||||
void logFormatter(QtMsgType type, const QMessageLogContext& context, const QString& msg);
|
||||
|
||||
}
|
||||
} // namespace Status::Helpers
|
||||
|
|
|
@ -3,16 +3,14 @@
|
|||
#include <StatusGo/Accounts/Accounts.h>
|
||||
#include <StatusGo/Accounts/AccountsAPI.h>
|
||||
#include <StatusGo/General.h>
|
||||
#include <StatusGo/Utils.h>
|
||||
#include <StatusGo/Messenger/Service.h>
|
||||
#include <StatusGo/Utils.h>
|
||||
|
||||
#include <Helpers/conversions.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
|
||||
std::optional<QString>
|
||||
getDataFromFile(const fs::path &path)
|
||||
std::optional<QString> getDataFromFile(const fs::path& path)
|
||||
{
|
||||
QFile jsonFile{Status::toQString(path)};
|
||||
if(!jsonFile.open(QIODevice::ReadOnly))
|
||||
|
@ -34,8 +32,7 @@ namespace Status::Onboarding
|
|||
|
||||
AccountsService::AccountsService()
|
||||
: m_isFirstTimeAccountLogin(false)
|
||||
{
|
||||
}
|
||||
{ }
|
||||
|
||||
bool AccountsService::init(const fs::path& statusgoDataDir)
|
||||
{
|
||||
|
@ -79,13 +76,14 @@ const std::vector<GeneratedMultiAccount>& AccountsService::generatedAccounts() c
|
|||
return m_generatedAccounts;
|
||||
}
|
||||
|
||||
bool AccountsService::setupAccountAndLogin(const QString &accountId, const QString &password, const QString &displayName)
|
||||
bool AccountsService::setupAccountAndLogin(const QString& accountId,
|
||||
const QString& password,
|
||||
const QString& displayName)
|
||||
{
|
||||
const QString installationId(QUuid::createUuid().toString(QUuid::WithoutBraces));
|
||||
const QJsonObject accountData(getAccountDataForAccountId(accountId, displayName));
|
||||
|
||||
if(!setKeyStoreDir(accountData.value("key-uid").toString()))
|
||||
return false;
|
||||
if(!setKeyStoreDir(accountData.value("key-uid").toString())) return false;
|
||||
|
||||
QJsonArray subAccountData(getSubaccountDataForAccountId(accountId, displayName));
|
||||
QJsonObject settings(getAccountSettings(accountId, installationId, displayName));
|
||||
|
@ -94,8 +92,7 @@ bool AccountsService::setupAccountAndLogin(const QString &accountId, const QStri
|
|||
auto hashedPassword(Utils::hashPassword(password));
|
||||
|
||||
// This initialize the DB if first time running. Required for storing accounts
|
||||
if(StatusGo::Accounts::openAccounts(m_statusgoDataDir.c_str()).containsError())
|
||||
return false;
|
||||
if(StatusGo::Accounts::openAccounts(m_statusgoDataDir.c_str()).containsError()) return false;
|
||||
|
||||
AccountsService::storeAccount(accountId, hashedPassword);
|
||||
AccountsService::storeDerivedAccounts(accountId, hashedPassword, Constants::General::AccountDefaultPaths);
|
||||
|
@ -130,8 +127,7 @@ bool AccountsService::setKeyStoreDir(const QString &key)
|
|||
QString AccountsService::login(MultiAccount account, const QString& password)
|
||||
{
|
||||
// This is a requirement. Make it more explicit into the status go module
|
||||
if(!setKeyStoreDir(account.keyUid))
|
||||
return QString("Failed to initialize keystore before logging in");
|
||||
if(!setKeyStoreDir(account.keyUid)) return QString("Failed to initialize keystore before logging in");
|
||||
|
||||
// This initialize the DB if first time running. Required before logging in
|
||||
if(StatusGo::Accounts::openAccounts(m_statusgoDataDir.c_str()).containsError())
|
||||
|
@ -141,8 +137,8 @@ QString AccountsService::login(MultiAccount account, const QString& password)
|
|||
|
||||
const QString thumbnailImage;
|
||||
const QString largeImage;
|
||||
const auto response = StatusGo::Accounts::login(account.name, account.keyUid, hashedPassword,
|
||||
thumbnailImage, largeImage);
|
||||
const auto response =
|
||||
StatusGo::Accounts::login(account.name, account.keyUid, hashedPassword, thumbnailImage, largeImage);
|
||||
if(response.containsError())
|
||||
{
|
||||
qWarning() << response.error.message;
|
||||
|
@ -179,7 +175,8 @@ void AccountsService::deleteMultiAccount(const MultiAccount &account)
|
|||
StatusGo::Accounts::deleteMultiaccount(account.keyUid, m_keyStoreDir);
|
||||
}
|
||||
|
||||
DerivedAccounts AccountsService::storeDerivedAccounts(const QString& accountId, const StatusGo::HashedPassword& password,
|
||||
DerivedAccounts AccountsService::storeDerivedAccounts(const QString& accountId,
|
||||
const StatusGo::HashedPassword& password,
|
||||
const std::vector<Accounts::DerivationPath>& paths)
|
||||
{
|
||||
const auto response = StatusGo::Accounts::storeDerivedAccounts(accountId, password, paths);
|
||||
|
@ -202,11 +199,14 @@ StoredMultiAccount AccountsService::storeAccount(const QString& accountId, const
|
|||
return toStoredMultiAccount(response.result);
|
||||
}
|
||||
|
||||
MultiAccount AccountsService::saveAccountAndLogin(const StatusGo::HashedPassword& password, const QJsonObject& account,
|
||||
const QJsonArray& subaccounts, const QJsonObject& settings,
|
||||
MultiAccount AccountsService::saveAccountAndLogin(const StatusGo::HashedPassword& password,
|
||||
const QJsonObject& account,
|
||||
const QJsonArray& subaccounts,
|
||||
const QJsonObject& settings,
|
||||
const QJsonObject& config)
|
||||
{
|
||||
if(!StatusGo::Accounts::saveAccountAndLogin(password, account, subaccounts, settings, config)) {
|
||||
if(!StatusGo::Accounts::saveAccountAndLogin(password, account, subaccounts, settings, config))
|
||||
{
|
||||
qWarning() << "Failed saving acccount" << account.value("name");
|
||||
return MultiAccount();
|
||||
}
|
||||
|
@ -215,7 +215,8 @@ MultiAccount AccountsService::saveAccountAndLogin(const StatusGo::HashedPassword
|
|||
return MultiAccount::toMultiAccount(account);
|
||||
}
|
||||
|
||||
QJsonObject AccountsService::prepareAccountJsonObject(const GeneratedMultiAccount& account, const QString &displayName) const
|
||||
QJsonObject AccountsService::prepareAccountJsonObject(const GeneratedMultiAccount& account,
|
||||
const QString& displayName) const
|
||||
{
|
||||
return QJsonObject{{"name", displayName.isEmpty() ? account.alias : displayName},
|
||||
{"address", account.address},
|
||||
|
@ -245,27 +246,22 @@ QJsonObject AccountsService::getAccountDataForAccountId(const QString &accountId
|
|||
return QJsonObject();
|
||||
}
|
||||
|
||||
QJsonArray AccountsService::prepareSubaccountJsonObject(const GeneratedMultiAccount& account, const QString &displayName) const
|
||||
QJsonArray AccountsService::prepareSubaccountJsonObject(const GeneratedMultiAccount& account,
|
||||
const QString& displayName) const
|
||||
{
|
||||
return {
|
||||
QJsonObject{
|
||||
{"public-key", account.derivedAccounts.defaultWallet.publicKey},
|
||||
return {QJsonObject{{"public-key", account.derivedAccounts.defaultWallet.publicKey},
|
||||
{"address", account.derivedAccounts.defaultWallet.address},
|
||||
{"color", "#4360df"},
|
||||
{"wallet", true},
|
||||
{"path", Constants::General::PathDefaultWallet.get()},
|
||||
{"name", "Status account"},
|
||||
{"derived-from", account.address}
|
||||
},
|
||||
QJsonObject{
|
||||
{"public-key", account.derivedAccounts.whisper.publicKey},
|
||||
{"derived-from", account.address}},
|
||||
QJsonObject{{"public-key", account.derivedAccounts.whisper.publicKey},
|
||||
{"address", account.derivedAccounts.whisper.address},
|
||||
{"name", displayName.isEmpty() ? account.alias : displayName},
|
||||
{"path", Constants::General::PathWhisper.get()},
|
||||
{"chat", true},
|
||||
{"derived-from", ""}
|
||||
}
|
||||
};
|
||||
{"derived-from", ""}}};
|
||||
}
|
||||
|
||||
QJsonArray AccountsService::getSubaccountDataForAccountId(const QString& accountId, const QString& displayName) const
|
||||
|
@ -306,8 +302,7 @@ QJsonObject AccountsService::prepareAccountSettingsJsonObject(const GeneratedMul
|
|||
const QString& installationId,
|
||||
const QString& displayName) const
|
||||
{
|
||||
return QJsonObject{
|
||||
{"key-uid", account.keyUid},
|
||||
return QJsonObject{{"key-uid", account.keyUid},
|
||||
{"mnemonic", account.mnemonic},
|
||||
{"public-key", account.derivedAccounts.whisper.publicKey},
|
||||
{"name", account.alias},
|
||||
|
@ -326,11 +321,12 @@ QJsonObject AccountsService::prepareAccountSettingsJsonObject(const GeneratedMul
|
|||
{"wallet/visible-tokens", QJsonObject()},
|
||||
{"waku-enabled", true},
|
||||
{"appearance", 0},
|
||||
{"installation-id", installationId}
|
||||
};
|
||||
{"installation-id", installationId}};
|
||||
}
|
||||
|
||||
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 GeneratedMultiAccount& acc : m_generatedAccounts)
|
||||
|
||||
|
@ -363,7 +359,8 @@ QJsonArray getNodes(const QJsonObject& fleet, const QString& nodeType)
|
|||
|
||||
QJsonObject AccountsService::getDefaultNodeConfig(const QString& installationId) const
|
||||
{
|
||||
try {
|
||||
try
|
||||
{
|
||||
auto templateNodeConfigJsonStr = getDataFromFile(":/Status/StaticConfig/node-config.json").value();
|
||||
auto fleetJson = getDataFromFile(":/Status/StaticConfig/fleets.json").value();
|
||||
auto infuraKey = getDataFromFile(":/Status/StaticConfig/infura_key").value();
|
||||
|
@ -376,8 +373,8 @@ QJsonObject AccountsService::getDefaultNodeConfig(const QString& installationId)
|
|||
auto DEFAULT_TORRENT_CONFIG_DATADIR = m_statusgoDataDir / "archivedata";
|
||||
auto DEFAULT_TORRENT_CONFIG_TORRENTDIR = m_statusgoDataDir / "torrents";
|
||||
|
||||
auto nodeConfigJsonStr = templateNodeConfigJsonStr
|
||||
.replace("%INSTALLATIONID%", installationId)
|
||||
auto nodeConfigJsonStr =
|
||||
templateNodeConfigJsonStr.replace("%INSTALLATIONID%", installationId)
|
||||
.replace("%INFURA_TOKEN_RESOLVED%", infuraKey)
|
||||
.replace("%DEFAULT_TORRENT_CONFIG_PORT%", QString::number(DEFAULT_TORRENT_CONFIG_PORT))
|
||||
.replace("%DEFAULT_TORRENT_CONFIG_DATADIR%", DEFAULT_TORRENT_CONFIG_DATADIR.c_str())
|
||||
|
@ -413,9 +410,11 @@ QJsonObject AccountsService::getDefaultNodeConfig(const QString& installationId)
|
|||
|
||||
nodeConfigJson["KeyStoreDir"] = toQString(fs::relative(m_keyStoreDir, m_statusgoDataDir));
|
||||
return nodeConfigJson;
|
||||
} catch (std::bad_optional_access) {
|
||||
}
|
||||
catch(std::bad_optional_access)
|
||||
{
|
||||
return QJsonObject();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status::Onboarding
|
||||
|
|
|
@ -59,12 +59,15 @@ public:
|
|||
private:
|
||||
QJsonObject prepareAccountJsonObject(const GeneratedMultiAccount& account, const QString& displayName) const;
|
||||
|
||||
DerivedAccounts storeDerivedAccounts(const QString& accountId, const StatusGo::HashedPassword& password,
|
||||
DerivedAccounts storeDerivedAccounts(const QString& accountId,
|
||||
const StatusGo::HashedPassword& password,
|
||||
const std::vector<Accounts::DerivationPath>& paths);
|
||||
StoredMultiAccount storeAccount(const QString& accountId, const StatusGo::HashedPassword& password);
|
||||
|
||||
MultiAccount saveAccountAndLogin(const StatusGo::HashedPassword& password, const QJsonObject& account,
|
||||
const QJsonArray& subaccounts, const QJsonObject& settings,
|
||||
MultiAccount saveAccountAndLogin(const StatusGo::HashedPassword& password,
|
||||
const QJsonObject& account,
|
||||
const QJsonArray& subaccounts,
|
||||
const QJsonObject& settings,
|
||||
const QJsonObject& config);
|
||||
|
||||
QJsonObject getAccountDataForAccountId(const QString& accountId, const QString& displayName) const;
|
||||
|
@ -79,7 +82,8 @@ private:
|
|||
const QString& installationId,
|
||||
const QString& displayName) const;
|
||||
|
||||
QJsonObject getAccountSettings(const QString& accountId, const QString& installationId, const QString& displayName) const;
|
||||
QJsonObject
|
||||
getAccountSettings(const QString& accountId, const QString& installationId, const QString& displayName) const;
|
||||
|
||||
QJsonObject getDefaultNodeConfig(const QString& installationId) const;
|
||||
|
||||
|
@ -97,4 +101,4 @@ private:
|
|||
static constexpr auto m_keyStoreDirName = "keystore";
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Status::Onboarding
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "MultiAccount.h"
|
||||
#include "GeneratedMultiAccount.h"
|
||||
#include "MultiAccount.h"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
|
@ -13,7 +13,6 @@ namespace Status::Onboarding
|
|||
class AccountsServiceInterface
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~AccountsServiceInterface() = default;
|
||||
|
||||
/// Generates and cache addresses accessible by \c generatedAccounts
|
||||
|
@ -26,7 +25,8 @@ public:
|
|||
[[nodiscard]] virtual const std::vector<GeneratedMultiAccount>& generatedAccounts() const = 0;
|
||||
|
||||
/// Configure an generated account. \a accountID must be sourced from \c generatedAccounts
|
||||
virtual bool setupAccountAndLogin(const QString& accountID, const QString& password, const QString& displayName) = 0;
|
||||
virtual bool
|
||||
setupAccountAndLogin(const QString& accountID, const QString& password, const QString& displayName) = 0;
|
||||
|
||||
/// Account that is currently logged-in
|
||||
[[nodiscard]] virtual const MultiAccount& getLoggedInAccount() const = 0;
|
||||
|
@ -50,4 +50,4 @@ public:
|
|||
|
||||
using AccountsServiceInterfacePtr = std::shared_ptr<AccountsServiceInterface>;
|
||||
|
||||
}
|
||||
} // namespace Status::Onboarding
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "Common/Constants.h"
|
||||
#include "Common/SigningPhrases.h"
|
||||
#include "Common/Json.h"
|
||||
#include "Common/SigningPhrases.h"
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
|
@ -76,17 +76,19 @@ struct StoredMultiAccount
|
|||
{
|
||||
QString publicKey;
|
||||
QString address;
|
||||
|
||||
};
|
||||
|
||||
static StoredMultiAccount toStoredMultiAccount(const QJsonObject& jsonObj)
|
||||
{
|
||||
auto result = StoredMultiAccount();
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
result.address = Json::getMandatoryProp(jsonObj, "address")->toString();
|
||||
result.publicKey = Json::getMandatoryProp(jsonObj, "publicKey")->toString();
|
||||
} catch (std::exception e) {
|
||||
}
|
||||
catch(std::exception e)
|
||||
{
|
||||
qWarning() << QString("Mapping StoredMultiAccount failed: %1").arg(e.what());
|
||||
}
|
||||
|
||||
|
@ -137,4 +139,4 @@ struct GeneratedMultiAccount
|
|||
}
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Status::Onboarding
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "Common/Constants.h"
|
||||
#include "Common/SigningPhrases.h"
|
||||
#include "Common/Json.h"
|
||||
#include "Common/SigningPhrases.h"
|
||||
|
||||
#include <StatusGo/Accounts/accounts_types.h>
|
||||
|
||||
|
@ -39,11 +39,11 @@ struct MultiAccount
|
|||
{
|
||||
result.name = Json::getMandatoryProp(jsonObj, "name")->toString();
|
||||
auto timestampIt = Json::getProp(jsonObj, "timestamp");
|
||||
if(timestampIt != jsonObj.constEnd()) {
|
||||
if(timestampIt != jsonObj.constEnd())
|
||||
{
|
||||
bool ok = false;
|
||||
auto t = timestampIt->toString().toLong(&ok);
|
||||
if(ok)
|
||||
result.timestamp = t;
|
||||
if(ok) result.timestamp = t;
|
||||
}
|
||||
result.keycardPairing = Json::getMandatoryProp(jsonObj, "keycard-pairing")->toString();
|
||||
result.keyUid = Json::getMandatoryProp(jsonObj, "key-uid")->toString();
|
||||
|
@ -60,4 +60,4 @@ struct MultiAccount
|
|||
}
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Status::Onboarding
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
#include <StatusGo/Accounts/accounts_types.h>
|
||||
|
||||
#include <QtCore>
|
||||
#include <QStringLiteral>
|
||||
#include <QtCore>
|
||||
|
||||
namespace GoAccounts = Status::StatusGo::Accounts;
|
||||
|
||||
|
@ -18,7 +18,7 @@ namespace Fleet
|
|||
inline const auto WakuV2Prod = u"wakuv2.prod"_qs;
|
||||
inline const auto WakuV2Test = u"wakuv2.test"_qs;
|
||||
inline const auto GoWakuTest = u"go-waku.test"_qs;
|
||||
}
|
||||
} // namespace Fleet
|
||||
|
||||
namespace FleetNodes
|
||||
{
|
||||
|
@ -29,7 +29,7 @@ namespace FleetNodes
|
|||
inline const auto Waku = u"waku"_qs;
|
||||
inline const auto LibP2P = u"libp2p"_qs;
|
||||
inline const auto Websocket = u"websocket"_qs;
|
||||
}
|
||||
} // namespace FleetNodes
|
||||
|
||||
namespace General
|
||||
{
|
||||
|
@ -46,7 +46,8 @@ namespace General
|
|||
// EIP1581 Chat Key 0, the default whisper key
|
||||
inline const GoAccounts::DerivationPath PathWhisper{PathEIP1581.get() + u"/0'/0"_qs};
|
||||
|
||||
inline const std::vector<GoAccounts::DerivationPath> AccountDefaultPaths {PathWalletRoot, PathEIP1581, PathWhisper, PathDefaultWallet};
|
||||
}
|
||||
inline const std::vector<GoAccounts::DerivationPath> AccountDefaultPaths{
|
||||
PathWalletRoot, PathEIP1581, PathWhisper, PathDefaultWallet};
|
||||
} // namespace General
|
||||
|
||||
}
|
||||
} // namespace Status::Constants
|
||||
|
|
|
@ -29,4 +29,4 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Status
|
||||
|
|
|
@ -50,7 +50,6 @@ constexpr std::array SigningPhrases {
|
|||
"veal", "veil", "vein", "vest", "vibe", "view", "vise", "wait", "wake", "walk", "wall", "wash", "wasp", "wave",
|
||||
"wear", "weed", "week", "well", "west", "whip", "wife", "will", "wind", "wine", "wing", "wire", "wish", "wolf",
|
||||
"wood", "wool", "word", "work", "worm", "wrap", "wren", "yard", "yarn", "yawl", "year", "yoga", "yoke", "yurt",
|
||||
"zinc", "zone"
|
||||
};
|
||||
"zinc", "zone"};
|
||||
|
||||
}
|
||||
|
|
|
@ -15,33 +15,36 @@ NewAccountController::NewAccountController(AccountsServiceInterfacePtr accountsS
|
|||
: m_accountsService(accountsService)
|
||||
{
|
||||
connect(this, &NewAccountController::passwordChanged, this, &NewAccountController::checkAndUpdateDataValidity);
|
||||
connect(this, &NewAccountController::confirmationPasswordChanged, this, &NewAccountController::checkAndUpdateDataValidity);
|
||||
connect(this,
|
||||
&NewAccountController::confirmationPasswordChanged,
|
||||
this,
|
||||
&NewAccountController::checkAndUpdateDataValidity);
|
||||
connect(this, &NewAccountController::nameChanged, this, &NewAccountController::checkAndUpdateDataValidity);
|
||||
}
|
||||
|
||||
void NewAccountController::createAccount()
|
||||
{
|
||||
// TODO: fix this after moving SingalManager to StatusGo wrapper lib
|
||||
QObject::connect(StatusGo::SignalsManager::instance(), &StatusGo::SignalsManager::nodeLogin, this, &NewAccountController::onNodeLogin);
|
||||
QObject::connect(StatusGo::SignalsManager::instance(),
|
||||
&StatusGo::SignalsManager::nodeLogin,
|
||||
this,
|
||||
&NewAccountController::onNodeLogin);
|
||||
|
||||
auto setupAccountFn = [this]() {
|
||||
if(m_nameIsValid && m_passwordIsValid && m_confirmationPasswordIsValid) {
|
||||
if(m_nameIsValid && m_passwordIsValid && m_confirmationPasswordIsValid)
|
||||
{
|
||||
auto genAccounts = m_accountsService->generatedAccounts();
|
||||
if(genAccounts.size() > 0) {
|
||||
if(m_accountsService->setupAccountAndLogin(genAccounts[0].id, m_password, m_name))
|
||||
return;
|
||||
if(genAccounts.size() > 0)
|
||||
{
|
||||
if(m_accountsService->setupAccountAndLogin(genAccounts[0].id, m_password, m_name)) return;
|
||||
}
|
||||
}
|
||||
};
|
||||
// TODO: refactor StatusGo wrapper to work with futures instead of SignalManager
|
||||
m_createAccountFuture = QtConcurrent::run(setupAccountFn)
|
||||
.then([] { /*Nothing, we expect status-go events*/ })
|
||||
.onFailed([this] {
|
||||
emit accountCreationError();
|
||||
})
|
||||
.onCanceled([this] {
|
||||
emit accountCreationError();
|
||||
});
|
||||
.onFailed([this] { emit accountCreationError(); })
|
||||
.onCanceled([this] { emit accountCreationError(); });
|
||||
}
|
||||
|
||||
const QString& NewAccountController::password() const
|
||||
|
@ -51,8 +54,7 @@ const QString &NewAccountController::password() const
|
|||
|
||||
void NewAccountController::setPassword(const QString& newPassword)
|
||||
{
|
||||
if (m_password == newPassword)
|
||||
return;
|
||||
if(m_password == newPassword) return;
|
||||
m_password = newPassword;
|
||||
emit passwordChanged();
|
||||
}
|
||||
|
@ -64,8 +66,7 @@ const QString &NewAccountController::confirmationPassword() const
|
|||
|
||||
void NewAccountController::setConfirmationPassword(const QString& newConfirmationPassword)
|
||||
{
|
||||
if (m_confirmationPassword == newConfirmationPassword)
|
||||
return;
|
||||
if(m_confirmationPassword == newConfirmationPassword) return;
|
||||
m_confirmationPassword = newConfirmationPassword;
|
||||
emit confirmationPasswordChanged();
|
||||
}
|
||||
|
@ -77,8 +78,7 @@ const QString &NewAccountController::name() const
|
|||
|
||||
void NewAccountController::setName(const QString& newName)
|
||||
{
|
||||
if (m_name == newName)
|
||||
return;
|
||||
if(m_name == newName) return;
|
||||
m_name = newName;
|
||||
emit nameChanged();
|
||||
}
|
||||
|
@ -109,19 +109,22 @@ void NewAccountController::onNodeLogin(const QString& error)
|
|||
void NewAccountController::checkAndUpdateDataValidity()
|
||||
{
|
||||
auto passwordValid = m_password.length() >= 6;
|
||||
if(passwordValid != m_passwordIsValid) {
|
||||
if(passwordValid != m_passwordIsValid)
|
||||
{
|
||||
m_passwordIsValid = passwordValid;
|
||||
emit passwordIsValidChanged();
|
||||
}
|
||||
|
||||
auto confirmationPasswordValid = m_password == m_confirmationPassword;
|
||||
if(confirmationPasswordValid != m_confirmationPasswordIsValid) {
|
||||
if(confirmationPasswordValid != m_confirmationPasswordIsValid)
|
||||
{
|
||||
m_confirmationPasswordIsValid = confirmationPasswordValid;
|
||||
emit confirmationPasswordIsValidChanged();
|
||||
}
|
||||
|
||||
auto nameValid = m_name.length() >= 10;
|
||||
if(nameValid != m_nameIsValid) {
|
||||
if(nameValid != m_nameIsValid)
|
||||
{
|
||||
m_nameIsValid = nameValid;
|
||||
emit nameIsValidChanged();
|
||||
}
|
||||
|
|
|
@ -28,10 +28,12 @@ class NewAccountController: public QObject
|
|||
QML_UNCREATABLE("Created and owned externally")
|
||||
|
||||
Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY passwordChanged)
|
||||
Q_PROPERTY(QString confirmationPassword READ confirmationPassword WRITE setConfirmationPassword NOTIFY confirmationPasswordChanged)
|
||||
Q_PROPERTY(QString confirmationPassword READ confirmationPassword WRITE setConfirmationPassword NOTIFY
|
||||
confirmationPasswordChanged)
|
||||
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
|
||||
Q_PROPERTY(bool passwordIsValid READ passwordIsValid NOTIFY passwordIsValidChanged)
|
||||
Q_PROPERTY(bool confirmationPasswordIsValid READ confirmationPasswordIsValid NOTIFY confirmationPasswordIsValidChanged)
|
||||
Q_PROPERTY(
|
||||
bool confirmationPasswordIsValid READ confirmationPasswordIsValid NOTIFY confirmationPasswordIsValidChanged)
|
||||
Q_PROPERTY(bool nameIsValid READ nameIsValid NOTIFY nameIsValidChanged)
|
||||
|
||||
public:
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
|
||||
#include <Helpers/helpers.h>
|
||||
|
||||
namespace Status::Onboarding {
|
||||
namespace Status::Onboarding
|
||||
{
|
||||
|
||||
namespace StatusGo = Status::StatusGo;
|
||||
|
||||
|
@ -18,13 +19,18 @@ OnboardingController::OnboardingController(AccountsServiceInterfacePtr accountsS
|
|||
{
|
||||
{ // Init accounts
|
||||
std::vector<std::shared_ptr<UserAccount>> accounts;
|
||||
for(auto &account : getOpenedAccounts()) {
|
||||
accounts.push_back(Helpers::makeSharedQObject<UserAccount>(std::make_unique<MultiAccount>(std::move(account))));
|
||||
for(auto& account : getOpenedAccounts())
|
||||
{
|
||||
accounts.push_back(
|
||||
Helpers::makeSharedQObject<UserAccount>(std::make_unique<MultiAccount>(std::move(account))));
|
||||
}
|
||||
m_accounts = Helpers::makeSharedQObject<UserAccountsModel>(std::move(accounts));
|
||||
}
|
||||
|
||||
connect(StatusGo::SignalsManager::instance(), &StatusGo::SignalsManager::nodeLogin, this, &OnboardingController::onLogin);
|
||||
connect(StatusGo::SignalsManager::instance(),
|
||||
&StatusGo::SignalsManager::nodeLogin,
|
||||
this,
|
||||
&OnboardingController::onLogin);
|
||||
}
|
||||
|
||||
OnboardingController::~OnboardingController()
|
||||
|
@ -50,8 +56,7 @@ void OnboardingController::login(QObject* user, const QString& password)
|
|||
auto account = qobject_cast<UserAccount*>(user);
|
||||
assert(account != nullptr);
|
||||
auto error = m_accountsService->login(account->accountData(), password);
|
||||
if(!error.isEmpty())
|
||||
emit accountLoginError(error);
|
||||
if(!error.isEmpty()) emit accountLoginError(error);
|
||||
}
|
||||
|
||||
UserAccountsModel* OnboardingController::accounts() const
|
||||
|
@ -82,4 +87,4 @@ AccountsServiceInterfacePtr OnboardingController::accountsService() const
|
|||
return m_accountsService;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status::Onboarding
|
||||
|
|
|
@ -22,8 +22,7 @@ class NewAccountController;
|
|||
* \todo don't use DTOs in controllers, use QObjects directly
|
||||
* \todo make dependency on SignalManager explicit. Now it is hidden.
|
||||
*/
|
||||
class OnboardingController final : public QObject
|
||||
, public std::enable_shared_from_this<OnboardingController>
|
||||
class OnboardingController final : public QObject, public std::enable_shared_from_this<OnboardingController>
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -72,4 +71,4 @@ private:
|
|||
std::unique_ptr<NewAccountController> m_newAccountController;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Status::Onboarding
|
||||
|
|
|
@ -10,7 +10,8 @@ namespace AppCore = Status::ApplicationCore;
|
|||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace Status::Onboarding {
|
||||
namespace Status::Onboarding
|
||||
{
|
||||
|
||||
OnboardingModule::OnboardingModule(const fs::path& userDataPath, QObject* parent)
|
||||
: OnboardingModule{parent}
|
||||
|
@ -22,8 +23,7 @@ OnboardingModule::OnboardingModule(const fs::path& userDataPath, QObject *parent
|
|||
OnboardingModule::OnboardingModule(QObject* parent)
|
||||
: QObject{parent}
|
||||
, m_accountsService(std::make_shared<AccountsService>())
|
||||
{
|
||||
}
|
||||
{ }
|
||||
|
||||
OnboardingController* OnboardingModule::controller() const
|
||||
{
|
||||
|
@ -32,9 +32,12 @@ OnboardingController* OnboardingModule::controller() const
|
|||
|
||||
void OnboardingModule::componentComplete()
|
||||
{
|
||||
try {
|
||||
try
|
||||
{
|
||||
initWithUserDataPath(m_userDataPath);
|
||||
} catch(const std::exception &e) {
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
qCritical() << "OnboardingModule: failed to initialize";
|
||||
}
|
||||
}
|
||||
|
@ -42,10 +45,8 @@ void OnboardingModule::componentComplete()
|
|||
void OnboardingModule::initWithUserDataPath(const fs::path& path)
|
||||
{
|
||||
auto result = m_accountsService->init(path);
|
||||
if(!result)
|
||||
throw std::runtime_error(std::string("Failed to initialize OnboadingService") + path.string());
|
||||
m_controller = Helpers::makeSharedQObject<OnboardingController>(
|
||||
m_accountsService);
|
||||
if(!result) throw std::runtime_error(std::string("Failed to initialize OnboadingService") + path.string());
|
||||
m_controller = Helpers::makeSharedQObject<OnboardingController>(m_accountsService);
|
||||
emit controllerChanged();
|
||||
}
|
||||
|
||||
|
@ -57,10 +58,9 @@ const QString OnboardingModule::userDataPath() const
|
|||
void OnboardingModule::setUserDataPath(const QString& newUserDataPath)
|
||||
{
|
||||
auto newVal = newUserDataPath.toStdString();
|
||||
if (m_userDataPath.compare(newVal) == 0)
|
||||
return;
|
||||
if(m_userDataPath.compare(newVal) == 0) return;
|
||||
m_userDataPath = newVal;
|
||||
emit userDataPathChanged();
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status::Onboarding
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace Status::Onboarding {
|
||||
namespace Status::Onboarding
|
||||
{
|
||||
|
||||
class AccountsService;
|
||||
|
||||
|
@ -48,7 +49,6 @@ signals:
|
|||
void userDataPathChanged();
|
||||
|
||||
private:
|
||||
|
||||
/// Throws exceptions
|
||||
void initWithUserDataPath(const fs::path& path);
|
||||
|
||||
|
@ -59,4 +59,4 @@ private:
|
|||
fs::path m_userDataPath;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Status::Onboarding
|
||||
|
|
|
@ -8,8 +8,7 @@ namespace Status::Onboarding
|
|||
UserAccount::UserAccount(std::unique_ptr<MultiAccount> data)
|
||||
: QObject()
|
||||
, m_data(std::move(data))
|
||||
{
|
||||
}
|
||||
{ }
|
||||
|
||||
const QString& UserAccount::name() const
|
||||
{
|
||||
|
@ -27,9 +26,7 @@ void UserAccount::updateAccountData(const MultiAccount& newData)
|
|||
|
||||
*m_data = newData;
|
||||
|
||||
if(newData.name != m_data->name)
|
||||
notifyUpdates.push_back([this]() { emit nameChanged(); });
|
||||
|
||||
if(newData.name != m_data->name) notifyUpdates.push_back([this]() { emit nameChanged(); });
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status::Onboarding
|
||||
|
|
|
@ -35,4 +35,4 @@ private:
|
|||
std::unique_ptr<MultiAccount> m_data;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Status::Onboarding
|
||||
|
|
|
@ -2,25 +2,19 @@
|
|||
|
||||
#include <QObject>
|
||||
|
||||
namespace Status::Onboarding {
|
||||
|
||||
namespace Status::Onboarding
|
||||
{
|
||||
|
||||
UserAccountsModel::UserAccountsModel(const std::vector<std::shared_ptr<UserAccount>> accounts, QObject* parent)
|
||||
: QAbstractListModel(parent)
|
||||
, m_accounts(std::move(accounts))
|
||||
{
|
||||
}
|
||||
{ }
|
||||
|
||||
UserAccountsModel::~UserAccountsModel()
|
||||
{
|
||||
}
|
||||
UserAccountsModel::~UserAccountsModel() { }
|
||||
|
||||
QHash<int, QByteArray> UserAccountsModel::roleNames() const
|
||||
{
|
||||
static QHash<int, QByteArray> roles{
|
||||
{Name, "name"},
|
||||
{Account, "account"}
|
||||
};
|
||||
static QHash<int, QByteArray> roles{{Name, "name"}, {Account, "account"}};
|
||||
return roles;
|
||||
}
|
||||
|
||||
|
@ -32,14 +26,14 @@ int UserAccountsModel::rowCount(const QModelIndex& parent) const
|
|||
|
||||
QVariant UserAccountsModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if(!QAbstractItemModel::checkIndex(index))
|
||||
return QVariant();
|
||||
if(!QAbstractItemModel::checkIndex(index)) return QVariant();
|
||||
|
||||
switch(static_cast<ModelRole>(role)) {
|
||||
switch(static_cast<ModelRole>(role))
|
||||
{
|
||||
case Name: return QVariant::fromValue(m_accounts[index.row()].get()->name());
|
||||
case Account: return QVariant::fromValue<QObject*>(m_accounts[index.row()].get());
|
||||
default: return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status::Onboarding
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
namespace Status::Onboarding {
|
||||
namespace Status::Onboarding
|
||||
{
|
||||
|
||||
/// \todo Replace it with \c QObjectVectorModel
|
||||
class UserAccountsModel : public QAbstractListModel
|
||||
|
@ -14,12 +15,13 @@ class UserAccountsModel : public QAbstractListModel
|
|||
QML_ELEMENT
|
||||
QML_UNCREATABLE("Created by OnboardingController")
|
||||
|
||||
enum ModelRole {
|
||||
enum ModelRole
|
||||
{
|
||||
Name = Qt::UserRole + 1,
|
||||
Account
|
||||
};
|
||||
public:
|
||||
|
||||
public:
|
||||
explicit UserAccountsModel(const std::vector<std::shared_ptr<UserAccount>> accounts, QObject* parent = nullptr);
|
||||
~UserAccountsModel();
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
@ -30,4 +32,4 @@ private:
|
|||
const std::vector<std::shared_ptr<UserAccount>> m_accounts;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Status::Onboarding
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
namespace Status::Testing::Constants {
|
||||
namespace Status::Testing::Constants
|
||||
{
|
||||
|
||||
inline constexpr auto userDataDirName = "StatusTest";
|
||||
inline constexpr auto statusGoDataDirName = "data";
|
||||
|
@ -12,4 +13,4 @@ inline constexpr auto qtDataDirName = "qt";
|
|||
inline constexpr auto keystoreDataDirName = "keystore";
|
||||
inline constexpr auto globalSettingsFileName = "global";
|
||||
|
||||
}
|
||||
} // namespace Status::Testing::Constants
|
||||
|
|
|
@ -20,7 +20,8 @@ namespace Accounts = Status::StatusGo::Accounts;
|
|||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace Status::Testing {
|
||||
namespace Status::Testing
|
||||
{
|
||||
|
||||
ScopedTestAccount::ScopedTestAccount(const std::string& tempTestSubfolderName,
|
||||
const QString& accountName,
|
||||
|
@ -41,7 +42,9 @@ ScopedTestAccount::ScopedTestAccount(const std::string &tempTestSubfolderName,
|
|||
auto accountsService = std::make_shared<Onboarding::AccountsService>();
|
||||
auto result = accountsService->init(m_testFolderPath);
|
||||
if(!result)
|
||||
{
|
||||
throw std::runtime_error("ScopedTestAccount - Failed to create temporary test account");
|
||||
}
|
||||
|
||||
// TODO refactor and merge account creation events with login into Onboarding controller
|
||||
//
|
||||
|
@ -51,42 +54,60 @@ ScopedTestAccount::ScopedTestAccount(const std::string &tempTestSubfolderName,
|
|||
// Beware, smartpointer is a requirement
|
||||
m_onboarding = Helpers::makeSharedQObject<Onboarding::OnboardingController>(accountsService);
|
||||
if(m_onboarding->getOpenedAccounts().size() != 0)
|
||||
{
|
||||
throw std::runtime_error("ScopedTestAccount - already have opened account");
|
||||
}
|
||||
|
||||
int accountLoggedInCount = 0;
|
||||
QObject::connect(m_onboarding.get(), &Onboarding::OnboardingController::accountLoggedIn, [&accountLoggedInCount]() {
|
||||
accountLoggedInCount++;
|
||||
});
|
||||
bool accountLoggedInError = false;
|
||||
QObject::connect(m_onboarding.get(), &Onboarding::OnboardingController::accountLoginError, [&accountLoggedInError]() {
|
||||
accountLoggedInError = true;
|
||||
});
|
||||
QObject::connect(m_onboarding.get(),
|
||||
&Onboarding::OnboardingController::accountLoginError,
|
||||
[&accountLoggedInError]() { accountLoggedInError = true; });
|
||||
|
||||
// Create Accounts
|
||||
auto genAccounts = accountsService->generatedAccounts();
|
||||
if(genAccounts.size() == 0)
|
||||
{
|
||||
throw std::runtime_error("ScopedTestAccount - missing generated accounts");
|
||||
}
|
||||
|
||||
if(accountsService->isFirstTimeAccountLogin())
|
||||
{
|
||||
throw std::runtime_error("ScopedTestAccount - Service::isFirstTimeAccountLogin returned true");
|
||||
}
|
||||
|
||||
if(!accountsService->setupAccountAndLogin(genAccounts[0].id, m_accountPassword, m_accountName))
|
||||
{
|
||||
throw std::runtime_error("ScopedTestAccount - Service::setupAccountAndLogin failed");
|
||||
}
|
||||
|
||||
if(!accountsService->isFirstTimeAccountLogin())
|
||||
{
|
||||
throw std::runtime_error("ScopedTestAccount - Service::isFirstTimeAccountLogin returned false");
|
||||
}
|
||||
if(!accountsService->getLoggedInAccount().isValid())
|
||||
{
|
||||
throw std::runtime_error("ScopedTestAccount - newly created account is not valid");
|
||||
}
|
||||
if(accountsService->getLoggedInAccount().name != accountName)
|
||||
{
|
||||
throw std::runtime_error("ScopedTestAccount - newly created account has a wrong name");
|
||||
processMessages(2000, [accountLoggedInCount]() {
|
||||
return accountLoggedInCount == 0;
|
||||
});
|
||||
}
|
||||
|
||||
processMessages(2000, [accountLoggedInCount]() { return accountLoggedInCount == 0; });
|
||||
|
||||
if(accountLoggedInCount != 1)
|
||||
{
|
||||
throw std::runtime_error("ScopedTestAccount - missing confirmation of account creation");
|
||||
}
|
||||
if(accountLoggedInError)
|
||||
{
|
||||
throw std::runtime_error("ScopedTestAccount - account loggedin error");
|
||||
}
|
||||
}
|
||||
|
||||
ScopedTestAccount::~ScopedTestAccount()
|
||||
{
|
||||
|
@ -94,12 +115,14 @@ ScopedTestAccount::~ScopedTestAccount()
|
|||
m_onboarding->accountsService()->deleteMultiAccount(rootAccount);
|
||||
}
|
||||
|
||||
void ScopedTestAccount::processMessages(size_t maxWaitTimeMillis, std::function<bool()> shouldWaitUntilTimeout) {
|
||||
void ScopedTestAccount::processMessages(size_t maxWaitTimeMillis, std::function<bool()> shouldWaitUntilTimeout)
|
||||
{
|
||||
using namespace std::chrono_literals;
|
||||
std::chrono::milliseconds maxWaitTime{maxWaitTimeMillis};
|
||||
auto iterationSleepTime = 2ms;
|
||||
auto remainingIterations = maxWaitTime / iterationSleepTime;
|
||||
while (remainingIterations-- > 0 && shouldWaitUntilTimeout()) {
|
||||
while(remainingIterations-- > 0 && shouldWaitUntilTimeout())
|
||||
{
|
||||
std::this_thread::sleep_for(iterationSleepTime);
|
||||
|
||||
QCoreApplication::sendPostedEvents();
|
||||
|
@ -109,28 +132,30 @@ void ScopedTestAccount::processMessages(size_t maxWaitTimeMillis, std::function<
|
|||
void ScopedTestAccount::logOut()
|
||||
{
|
||||
if(Status::StatusGo::Accounts::logout().containsError())
|
||||
{
|
||||
throw std::runtime_error("ScopedTestAccount - failed logging out");
|
||||
}
|
||||
}
|
||||
|
||||
Accounts::ChatOrWalletAccount ScopedTestAccount::firstChatAccount()
|
||||
{
|
||||
auto accounts = Accounts::getAccounts();
|
||||
auto chatIt = std::find_if(accounts.begin(), accounts.end(), [](const auto& a) {
|
||||
return a.isChat;
|
||||
});
|
||||
auto chatIt = std::find_if(accounts.begin(), accounts.end(), [](const auto& a) { return a.isChat; });
|
||||
if(chatIt == accounts.end())
|
||||
{
|
||||
throw std::runtime_error("ScopedTestAccount::chatAccount: account not found");
|
||||
}
|
||||
return *chatIt;
|
||||
}
|
||||
|
||||
Accounts::ChatOrWalletAccount ScopedTestAccount::firstWalletAccount()
|
||||
{
|
||||
auto accounts = Accounts::getAccounts();
|
||||
auto walletIt = std::find_if(accounts.begin(), accounts.end(), [](const auto& a) {
|
||||
return a.isWallet;
|
||||
});
|
||||
auto walletIt = std::find_if(accounts.begin(), accounts.end(), [](const auto& a) { return a.isWallet; });
|
||||
if(walletIt == accounts.end())
|
||||
{
|
||||
throw std::runtime_error("ScopedTestAccount::firstWalletAccount: account not found");
|
||||
}
|
||||
return *walletIt;
|
||||
}
|
||||
|
||||
|
@ -149,4 +174,4 @@ const std::filesystem::path &ScopedTestAccount::fusedTestFolder() const
|
|||
return m_testFolderPath;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status::Testing
|
||||
|
|
|
@ -4,27 +4,30 @@
|
|||
|
||||
#include <StatusGo/Utils.h>
|
||||
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
|
||||
#include <QString>
|
||||
|
||||
class QCoreApplication;
|
||||
|
||||
namespace Status::Onboarding {
|
||||
namespace Status::Onboarding
|
||||
{
|
||||
class OnboardingController;
|
||||
class MultiAccount;
|
||||
}
|
||||
} // namespace Status::Onboarding
|
||||
|
||||
namespace Wallet = Status::StatusGo::Wallet;
|
||||
namespace Accounts = Status::StatusGo::Accounts;
|
||||
namespace GoUtils = Status::StatusGo::Utils;
|
||||
|
||||
namespace Status::Testing {
|
||||
namespace Status::Testing
|
||||
{
|
||||
|
||||
class AutoCleanTempTestDir;
|
||||
|
||||
class ScopedTestAccount final {
|
||||
class ScopedTestAccount final
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* \brief Create and logs in a new test account
|
||||
|
@ -44,8 +47,14 @@ public:
|
|||
/// Root account
|
||||
const Status::Onboarding::MultiAccount& loggedInAccount() const;
|
||||
|
||||
QString password() const { return m_accountPassword; };
|
||||
StatusGo::HashedPassword hashedPassword() const { return GoUtils::hashPassword(m_accountPassword); };
|
||||
QString password() const
|
||||
{
|
||||
return m_accountPassword;
|
||||
};
|
||||
StatusGo::HashedPassword hashedPassword() const
|
||||
{
|
||||
return GoUtils::hashPassword(m_accountPassword);
|
||||
};
|
||||
|
||||
Status::Onboarding::OnboardingController* onboardingController() const;
|
||||
|
||||
|
@ -65,4 +74,4 @@ private:
|
|||
static constexpr auto defaultAccountPassword = "test_pwd*";
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Status::Testing
|
||||
|
|
|
@ -34,4 +34,4 @@ public:
|
|||
MOCK_METHOD(void, deleteMultiAccount, (const Onboarding::MultiAccount&), (override));
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Status::Testing
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "ServiceMock.h"
|
||||
|
||||
#include <IOTestHelpers.h>
|
||||
#include <Constants.h>
|
||||
#include <IOTestHelpers.h>
|
||||
|
||||
#include <StatusGo/Accounts/Accounts.h>
|
||||
|
||||
|
@ -15,7 +15,8 @@ namespace Onboarding = Status::Onboarding;
|
|||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace Status::Testing {
|
||||
namespace Status::Testing
|
||||
{
|
||||
|
||||
class AccountsService : public ::testing::Test
|
||||
{
|
||||
|
@ -23,19 +24,20 @@ protected:
|
|||
std::unique_ptr<Onboarding::AccountsService> m_accountsService;
|
||||
std::unique_ptr<Testing::AutoCleanTempTestDir> m_fusedTestFolder;
|
||||
|
||||
void SetUp() override {
|
||||
void SetUp() override
|
||||
{
|
||||
m_fusedTestFolder = std::make_unique<Testing::AutoCleanTempTestDir>("TestAccountsService");
|
||||
m_accountsService = std::make_unique<Onboarding::AccountsService>();
|
||||
m_accountsService->init(m_fusedTestFolder->tempFolder() / Constants::statusGoDataDirName);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
void TearDown() override
|
||||
{
|
||||
m_fusedTestFolder.reset();
|
||||
m_accountsService.reset();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TEST_F(AccountsService, GeneratedAccounts)
|
||||
{
|
||||
auto genAccounts = m_accountsService->generatedAccounts();
|
||||
|
@ -51,13 +53,16 @@ TEST_F(AccountsService, GeneratedAccounts)
|
|||
}
|
||||
}
|
||||
|
||||
TEST_F(AccountsService, DISABLED_GenerateAlias) // temporary disabled till we see what's happening on the status-go side since it doesn't return aliases for any pk
|
||||
TEST_F(
|
||||
AccountsService,
|
||||
DISABLED_GenerateAlias) // temporary disabled till we see what's happening on the status-go side since it doesn't return aliases for any pk
|
||||
{
|
||||
QString testPubKey = "0x04487f44bac3e90825bfa9720148308cb64835bebb7e888f519cebc127223187067629f8b70d0661a35d4af6516b225286";
|
||||
QString testPubKey =
|
||||
"0x04487f44bac3e90825bfa9720148308cb64835bebb7e888f519cebc127223187067629f8b70d0661a35d4af6516b225286";
|
||||
|
||||
auto alias = m_accountsService->generateAlias(testPubKey);
|
||||
|
||||
ASSERT_NE(alias, QString(""));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace Status::Testing
|
||||
|
|
|
@ -17,7 +17,8 @@ namespace Onboarding = Status::Onboarding;
|
|||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace Status::Testing {
|
||||
namespace Status::Testing
|
||||
{
|
||||
|
||||
class LoginTest : public ::testing::Test
|
||||
{
|
||||
|
@ -27,20 +28,24 @@ protected:
|
|||
std::unique_ptr<Onboarding::AccountsService> m_accountsService;
|
||||
std::unique_ptr<Testing::AutoCleanTempTestDir> m_fusedTestFolder;
|
||||
|
||||
static void SetUpTestSuite() {
|
||||
static void SetUpTestSuite()
|
||||
{
|
||||
m_accountsServiceMock = std::make_shared<AccountsServiceMock>();
|
||||
}
|
||||
static void TearDownTestSuite() {
|
||||
static void TearDownTestSuite()
|
||||
{
|
||||
m_accountsServiceMock.reset();
|
||||
}
|
||||
|
||||
void SetUp() override {
|
||||
void SetUp() override
|
||||
{
|
||||
m_fusedTestFolder = std::make_unique<Testing::AutoCleanTempTestDir>("LoginTest");
|
||||
m_accountsService = std::make_unique<Onboarding::AccountsService>();
|
||||
m_accountsService->init(m_fusedTestFolder->tempFolder() / Constants::statusGoDataDirName);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
void TearDown() override
|
||||
{
|
||||
m_fusedTestFolder.release();
|
||||
m_accountsService.release();
|
||||
}
|
||||
|
@ -54,4 +59,4 @@ TEST_F(LoginTest, DISABLED_TestLoginController)
|
|||
auto controller = Helpers::makeSharedQObject<Onboarding::OnboardingController>(m_accountsServiceMock);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace Status::Testing
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
#include <Onboarding/Accounts/AccountsService.h>
|
||||
#include <Onboarding/OnboardingController.h>
|
||||
|
||||
#include <StatusGo/SignalsManager.h>
|
||||
#include <StatusGo/Accounts/Accounts.h>
|
||||
#include <StatusGo/SignalsManager.h>
|
||||
|
||||
#include <ScopedTestAccount.h>
|
||||
|
||||
|
@ -21,7 +21,8 @@ namespace Onboarding = Status::Onboarding;
|
|||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace Status::Testing {
|
||||
namespace Status::Testing
|
||||
{
|
||||
|
||||
static std::unique_ptr<Onboarding::AccountsService> m_accountsServiceMock;
|
||||
|
||||
|
@ -90,7 +91,8 @@ TEST(OnboardingModule, TestCreateAndLoginAccountEndToEnd)
|
|||
auto maxWaitTime = 2000ms;
|
||||
auto iterationSleepTime = 2ms;
|
||||
auto remainingIterations = maxWaitTime / iterationSleepTime;
|
||||
while (remainingIterations-- > 0 && accountLoggedInCount == 0) {
|
||||
while(remainingIterations-- > 0 && accountLoggedInCount == 0)
|
||||
{
|
||||
std::this_thread::sleep_for(iterationSleepTime);
|
||||
|
||||
QCoreApplication::sendPostedEvents();
|
||||
|
@ -110,20 +112,23 @@ TEST(OnboardingModule, TestLoginEndToEnd)
|
|||
// Create test account and login
|
||||
//
|
||||
bool createAndLogin = false;
|
||||
QObject::connect(StatusGo::SignalsManager::instance(), &StatusGo::SignalsManager::nodeLogin, [&createAndLogin](const QString& error) {
|
||||
if(error.isEmpty()) {
|
||||
if(createAndLogin) {
|
||||
QObject::connect(StatusGo::SignalsManager::instance(),
|
||||
&StatusGo::SignalsManager::nodeLogin,
|
||||
[&createAndLogin](const QString& error) {
|
||||
if(error.isEmpty())
|
||||
{
|
||||
if(createAndLogin)
|
||||
{
|
||||
createAndLogin = false;
|
||||
} else
|
||||
}
|
||||
else
|
||||
createAndLogin = true;
|
||||
}
|
||||
});
|
||||
|
||||
constexpr auto accountName = "TestLoginAccountName";
|
||||
ScopedTestAccount testAccount(test_info_->name(), accountName);
|
||||
testAccount.processMessages(1000, [createAndLogin]() {
|
||||
return !createAndLogin;
|
||||
});
|
||||
testAccount.processMessages(1000, [createAndLogin]() { return !createAndLogin; });
|
||||
ASSERT_TRUE(createAndLogin);
|
||||
|
||||
testAccount.logOut();
|
||||
|
@ -148,14 +153,15 @@ TEST(OnboardingModule, TestLoginEndToEnd)
|
|||
accountLoggedInCount++;
|
||||
});
|
||||
bool accountLoggedInError = false;
|
||||
QObject::connect(onboarding.get(), &Onboarding::OnboardingController::accountLoginError,
|
||||
QObject::connect(onboarding.get(),
|
||||
&Onboarding::OnboardingController::accountLoginError,
|
||||
[&accountLoggedInError](const QString& error) {
|
||||
accountLoggedInError = true;
|
||||
qDebug() << "Failed logging in in test" << test_info_->name() << "with error:" << error;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
auto ourAccountRes = std::find_if(accounts.begin(), accounts.end(), [accountName](const auto &a) { return a.name == accountName; });
|
||||
auto ourAccountRes =
|
||||
std::find_if(accounts.begin(), accounts.end(), [accountName](const auto& a) { return a.name == accountName; });
|
||||
auto errorString = accountsService->login(*ourAccountRes, testAccount.password());
|
||||
ASSERT_EQ(errorString.length(), 0);
|
||||
|
||||
|
@ -186,13 +192,16 @@ TEST(OnboardingModule, TestLoginEndToEnd_WrongPassword)
|
|||
});
|
||||
bool accountLoggedInError = false;
|
||||
QString loginErrorMessage;
|
||||
QObject::connect(onboarding.get(), &Onboarding::OnboardingController::accountLoginError,
|
||||
QObject::connect(onboarding.get(),
|
||||
&Onboarding::OnboardingController::accountLoginError,
|
||||
[&loginErrorMessage, &accountLoggedInError](const QString& error) {
|
||||
accountLoggedInError = true;
|
||||
loginErrorMessage = error;
|
||||
});
|
||||
|
||||
auto ourAccountRes = std::find_if(accounts.begin(), accounts.end(), [testRootAccountName](const auto &a) { return a.name == testRootAccountName; });
|
||||
auto ourAccountRes = std::find_if(accounts.begin(), accounts.end(), [testRootAccountName](const auto& a) {
|
||||
return a.name == testRootAccountName;
|
||||
});
|
||||
auto errorString = accountsService->login(*ourAccountRes, testAccount.password() + "extra");
|
||||
ASSERT_EQ(errorString.length(), 0);
|
||||
|
||||
|
@ -204,4 +213,4 @@ TEST(OnboardingModule, TestLoginEndToEnd_WrongPassword)
|
|||
ASSERT_EQ(loginErrorMessage, "file is not a database");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace Status::Testing
|
||||
|
|
|
@ -7,16 +7,15 @@
|
|||
const int NUMBER_OF_ADDRESSES_TO_GENERATE = 5;
|
||||
const int MNEMONIC_PHRASE_LENGTH = 12;
|
||||
|
||||
namespace Status::StatusGo::Accounts {
|
||||
namespace Status::StatusGo::Accounts
|
||||
{
|
||||
|
||||
RpcResponse<QJsonArray> generateAddresses(const std::vector<Accounts::DerivationPath>& paths)
|
||||
{
|
||||
QJsonObject payload{
|
||||
{"n", NUMBER_OF_ADDRESSES_TO_GENERATE},
|
||||
QJsonObject payload{{"n", NUMBER_OF_ADDRESSES_TO_GENERATE},
|
||||
{"mnemonicPhraseLength", MNEMONIC_PHRASE_LENGTH},
|
||||
{"bip32Passphrase", ""},
|
||||
{"paths", Utils::toJsonArray(paths)}
|
||||
};
|
||||
{"paths", Utils::toJsonArray(paths)}};
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -64,13 +63,11 @@ RpcResponse<QString> generateAlias(const QString& publicKey)
|
|||
}
|
||||
}
|
||||
|
||||
RpcResponse<QJsonObject> storeDerivedAccounts(const QString& id, const HashedPassword& password, const std::vector<Accounts::DerivationPath>& paths)
|
||||
RpcResponse<QJsonObject> storeDerivedAccounts(const QString& id,
|
||||
const HashedPassword& password,
|
||||
const std::vector<Accounts::DerivationPath>& paths)
|
||||
{
|
||||
QJsonObject payload{
|
||||
{"accountID", id},
|
||||
{"paths", Utils::toJsonArray(paths)},
|
||||
{"password", password.get()}
|
||||
};
|
||||
QJsonObject payload{{"accountID", id}, {"paths", Utils::toJsonArray(paths)}, {"password", password.get()}};
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -102,10 +99,7 @@ RpcResponse<QJsonObject> storeDerivedAccounts(const QString& id, const HashedPas
|
|||
|
||||
RpcResponse<QJsonObject> storeAccount(const QString& id, const HashedPassword& password)
|
||||
{
|
||||
QJsonObject payload{
|
||||
{"accountID", id},
|
||||
{"password", password.get()}
|
||||
};
|
||||
QJsonObject payload{{"accountID", id}, {"password", password.get()}};
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -135,8 +129,10 @@ RpcResponse<QJsonObject> storeAccount(const QString& id, const HashedPassword& p
|
|||
}
|
||||
}
|
||||
|
||||
bool saveAccountAndLogin(const HashedPassword& password, const QJsonObject& account,
|
||||
const QJsonArray& subaccounts, const QJsonObject& settings,
|
||||
bool saveAccountAndLogin(const HashedPassword& password,
|
||||
const QJsonObject& account,
|
||||
const QJsonArray& subaccounts,
|
||||
const QJsonObject& settings,
|
||||
const QJsonObject& nodeConfig)
|
||||
{
|
||||
try
|
||||
|
@ -154,9 +150,13 @@ bool saveAccountAndLogin(const HashedPassword& password, const QJsonObject& acco
|
|||
}
|
||||
|
||||
return !Utils::getRPCErrorInJson(jsonResult).has_value();
|
||||
} catch (std::exception& e) {
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
qWarning() << QString("an error saving account and login occurred, msg: %1").arg(e.what());
|
||||
} catch (...) {
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
qWarning() << "an error saving account and login occurred";
|
||||
}
|
||||
return false;
|
||||
|
@ -167,11 +167,11 @@ RpcResponse<QJsonArray> openAccounts(const char* dataDirPath)
|
|||
try
|
||||
{
|
||||
auto result = QString(OpenAccounts(const_cast<char*>(dataDirPath)));
|
||||
if(result == "null")
|
||||
return RpcResponse<QJsonArray>(QJsonArray());
|
||||
if(result == "null") return RpcResponse<QJsonArray>(QJsonArray());
|
||||
|
||||
QJsonArray jsonResult;
|
||||
if(!Utils::checkReceivedResponse(result, jsonResult)) {
|
||||
if(!Utils::checkReceivedResponse(result, jsonResult))
|
||||
{
|
||||
throw std::domain_error("parsing response failed");
|
||||
}
|
||||
|
||||
|
@ -192,14 +192,13 @@ RpcResponse<QJsonArray> openAccounts(const char* dataDirPath)
|
|||
}
|
||||
}
|
||||
|
||||
RpcResponse<QJsonObject> login(const QString& name, const QString& keyUid, const HashedPassword& password,
|
||||
const QString& thumbnail, const QString& large)
|
||||
RpcResponse<QJsonObject> login(const QString& name,
|
||||
const QString& keyUid,
|
||||
const HashedPassword& password,
|
||||
const QString& thumbnail,
|
||||
const QString& large)
|
||||
{
|
||||
QJsonObject payload{
|
||||
{"name", name},
|
||||
{"key-uid", keyUid},
|
||||
{"identityImage", QJsonValue()}
|
||||
};
|
||||
QJsonObject payload{{"name", name}, {"key-uid", keyUid}, {"identityImage", QJsonValue()}};
|
||||
|
||||
if(!thumbnail.isEmpty() && !large.isEmpty())
|
||||
{
|
||||
|
@ -233,8 +232,12 @@ RpcResponse<QJsonObject> login(const QString& name, const QString& keyUid, const
|
|||
}
|
||||
}
|
||||
|
||||
RpcResponse<QJsonObject> loginWithConfig(const QString& name, const QString& keyUid, const HashedPassword& password,
|
||||
const QString& thumbnail, const QString& large, const QJsonObject& nodeConfig)
|
||||
RpcResponse<QJsonObject> loginWithConfig(const QString& name,
|
||||
const QString& keyUid,
|
||||
const HashedPassword& password,
|
||||
const QString& thumbnail,
|
||||
const QString& large,
|
||||
const QJsonObject& nodeConfig)
|
||||
{
|
||||
QJsonObject payload{
|
||||
{"name", name},
|
||||
|
@ -305,4 +308,4 @@ RpcResponse<QJsonObject> logout()
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status::StatusGo::Accounts
|
||||
|
|
|
@ -11,21 +11,31 @@ namespace Status::StatusGo::Accounts
|
|||
|
||||
RpcResponse<QString> generateAlias(const QString& publicKey);
|
||||
|
||||
RpcResponse<QJsonObject> storeDerivedAccounts(const QString& accountId, const HashedPassword& password,
|
||||
RpcResponse<QJsonObject> storeDerivedAccounts(const QString& accountId,
|
||||
const HashedPassword& password,
|
||||
const std::vector<Accounts::DerivationPath>& paths);
|
||||
|
||||
RpcResponse<QJsonObject> storeAccount(const QString& id, const HashedPassword& password);
|
||||
|
||||
bool saveAccountAndLogin(const StatusGo::HashedPassword& password, const QJsonObject& account,
|
||||
const QJsonArray& subaccounts, const QJsonObject& settings,
|
||||
bool saveAccountAndLogin(const StatusGo::HashedPassword& password,
|
||||
const QJsonObject& account,
|
||||
const QJsonArray& subaccounts,
|
||||
const QJsonObject& settings,
|
||||
const QJsonObject& nodeConfig);
|
||||
|
||||
/// opens database and returns accounts list.
|
||||
RpcResponse<QJsonArray> openAccounts(const char* dataDirPath);
|
||||
|
||||
RpcResponse<QJsonObject> login(const QString& name, const QString& keyUid, const HashedPassword& password,
|
||||
const QString& thumbnail, const QString& large);
|
||||
RpcResponse<QJsonObject> loginWithConfig(const QString& name, const QString& keyUid, const HashedPassword& password,
|
||||
const QString& thumbnail, const QString& large, const QJsonObject& nodeConfig);
|
||||
RpcResponse<QJsonObject> login(const QString& name,
|
||||
const QString& keyUid,
|
||||
const HashedPassword& password,
|
||||
const QString& thumbnail,
|
||||
const QString& large);
|
||||
RpcResponse<QJsonObject> loginWithConfig(const QString& name,
|
||||
const QString& keyUid,
|
||||
const HashedPassword& password,
|
||||
const QString& thumbnail,
|
||||
const QString& large,
|
||||
const QJsonObject& nodeConfig);
|
||||
RpcResponse<QJsonObject> logout();
|
||||
}
|
||||
} // namespace Status::StatusGo::Accounts
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "AccountsAPI.h"
|
||||
|
||||
#include "Utils.h"
|
||||
#include "Metadata/api_response.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#include <libstatus.h>
|
||||
|
||||
|
@ -14,13 +14,10 @@ using json = nlohmann::json;
|
|||
namespace Status::StatusGo::Accounts
|
||||
{
|
||||
|
||||
Accounts::ChatOrWalletAccounts getAccounts() {
|
||||
Accounts::ChatOrWalletAccounts getAccounts()
|
||||
{
|
||||
// or even nicer with a raw string literal
|
||||
json inputJson = {
|
||||
{"jsonrpc", "2.0"},
|
||||
{"method", "accounts_getAccounts"},
|
||||
{"params", json::array()}
|
||||
};
|
||||
json inputJson = {{"jsonrpc", "2.0"}, {"method", "accounts_getAccounts"}, {"params", json::array()}};
|
||||
|
||||
auto result = Utils::statusGoCallPrivateRPC(inputJson.dump().c_str());
|
||||
auto resultJson = json::parse(result);
|
||||
|
@ -29,31 +26,30 @@ Accounts::ChatOrWalletAccounts getAccounts() {
|
|||
return resultJson.get<CallPrivateRpcResponse>().result;
|
||||
}
|
||||
|
||||
void generateAccountWithDerivedPath(const HashedPassword &password, const QString &name, const QColor &color, const QString &emoji,
|
||||
const DerivationPath &path, const EOAddress &derivedFrom)
|
||||
void generateAccountWithDerivedPath(const HashedPassword& password,
|
||||
const QString& name,
|
||||
const QColor& color,
|
||||
const QString& emoji,
|
||||
const DerivationPath& path,
|
||||
const EOAddress& derivedFrom)
|
||||
{
|
||||
std::vector<json> params = {password, name, color, emoji, path, derivedFrom};
|
||||
json inputJson = {
|
||||
{"jsonrpc", "2.0"},
|
||||
{"method", "accounts_generateAccountWithDerivedPath"},
|
||||
{"params", params}
|
||||
};
|
||||
json inputJson = {{"jsonrpc", "2.0"}, {"method", "accounts_generateAccountWithDerivedPath"}, {"params", params}};
|
||||
|
||||
auto result = Utils::statusGoCallPrivateRPC(inputJson.dump().c_str());
|
||||
auto resultJson = json::parse(result);
|
||||
checkPrivateRpcCallResultAndReportError(resultJson);
|
||||
|
||||
}
|
||||
|
||||
void addAccountWithMnemonicAndPath(const QString &mnemonic, const HashedPassword &password, const QString &name,
|
||||
const QColor &color, const QString &emoji, const DerivationPath &path)
|
||||
void addAccountWithMnemonicAndPath(const QString& mnemonic,
|
||||
const HashedPassword& password,
|
||||
const QString& name,
|
||||
const QColor& color,
|
||||
const QString& emoji,
|
||||
const DerivationPath& path)
|
||||
{
|
||||
std::vector<json> params = {mnemonic, password, name, color, emoji, path};
|
||||
json inputJson = {
|
||||
{"jsonrpc", "2.0"},
|
||||
{"method", "accounts_addAccountWithMnemonicAndPath"},
|
||||
{"params", params}
|
||||
};
|
||||
json inputJson = {{"jsonrpc", "2.0"}, {"method", "accounts_addAccountWithMnemonicAndPath"}, {"params", params}};
|
||||
|
||||
auto result = Utils::statusGoCallPrivateRPC(inputJson.dump().c_str());
|
||||
auto resultJson = json::parse(result);
|
||||
|
@ -63,11 +59,7 @@ void addAccountWithMnemonicAndPath(const QString &mnemonic, const HashedPassword
|
|||
void addAccountWatch(const EOAddress& address, const QString& name, const QColor& color, const QString& emoji)
|
||||
{
|
||||
std::vector<json> params = {address, name, color, emoji};
|
||||
json inputJson = {
|
||||
{"jsonrpc", "2.0"},
|
||||
{"method", "accounts_addAccountWatch"},
|
||||
{"params", params}
|
||||
};
|
||||
json inputJson = {{"jsonrpc", "2.0"}, {"method", "accounts_addAccountWatch"}, {"params", params}};
|
||||
|
||||
auto result = Utils::statusGoCallPrivateRPC(inputJson.dump().c_str());
|
||||
auto resultJson = json::parse(result);
|
||||
|
@ -77,11 +69,7 @@ void addAccountWatch(const EOAddress &address, const QString &name, const QColor
|
|||
void deleteAccount(const EOAddress& address)
|
||||
{
|
||||
std::vector<json> params = {address};
|
||||
json inputJson = {
|
||||
{"jsonrpc", "2.0"},
|
||||
{"method", "accounts_deleteAccount"},
|
||||
{"params", params}
|
||||
};
|
||||
json inputJson = {{"jsonrpc", "2.0"}, {"method", "accounts_deleteAccount"}, {"params", params}};
|
||||
|
||||
auto result = Utils::statusGoCallPrivateRPC(inputJson.dump().c_str());
|
||||
auto resultJson = json::parse(result);
|
||||
|
@ -91,9 +79,10 @@ void deleteAccount(const EOAddress &address)
|
|||
void deleteMultiaccount(const QString& keyUID, const fs::path& keyStoreDir)
|
||||
{
|
||||
// We know go bridge won't misbehave with the input arguments
|
||||
auto result = DeleteMultiaccount(const_cast<char*>(keyUID.toStdString().c_str()), const_cast<char*>(keyStoreDir.string().c_str()));
|
||||
auto result = DeleteMultiaccount(const_cast<char*>(keyUID.toStdString().c_str()),
|
||||
const_cast<char*>(keyStoreDir.string().c_str()));
|
||||
auto resultJson = json::parse(result);
|
||||
checkApiError(resultJson);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status::StatusGo::Accounts
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
#include "Accounts/ChatOrWalletAccount.h"
|
||||
#include "Accounts/accounts_types.h"
|
||||
|
||||
#include <vector>
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
|
||||
namespace Accounts = Status::StatusGo::Accounts;
|
||||
|
||||
|
@ -28,16 +28,23 @@ Accounts::ChatOrWalletAccounts getAccounts();
|
|||
/// \note the underlying status-go API, SaveAccounts@accounts.go, returns `nil` for \c CallPrivateRpcResponse.result
|
||||
/// \see \c getAccounts
|
||||
/// \throws \c CallPrivateRpcError
|
||||
void generateAccountWithDerivedPath(const HashedPassword &password, const QString &name,
|
||||
const QColor &color, const QString &emoji,
|
||||
const DerivationPath &path, const Accounts::EOAddress &derivedFrom);
|
||||
void generateAccountWithDerivedPath(const HashedPassword& password,
|
||||
const QString& name,
|
||||
const QColor& color,
|
||||
const QString& emoji,
|
||||
const DerivationPath& path,
|
||||
const Accounts::EOAddress& derivedFrom);
|
||||
|
||||
/// \brief Add a new account from an existing mnemonic
|
||||
/// \note the underlying status-go api, SaveAccounts@accounts.go, returns `nil` for \c CallPrivateRpcResponse.result
|
||||
/// \see \c getAccounts
|
||||
/// \throws \c CallPrivateRpcError
|
||||
void addAccountWithMnemonicAndPath(const QString &mnemonic, const HashedPassword &password, const QString &name,
|
||||
const QColor &color, const QString &emoji, const DerivationPath &path);
|
||||
void addAccountWithMnemonicAndPath(const QString& mnemonic,
|
||||
const HashedPassword& password,
|
||||
const QString& name,
|
||||
const QColor& color,
|
||||
const QString& emoji,
|
||||
const DerivationPath& path);
|
||||
|
||||
/// \brief Add a watch only account
|
||||
/// \note the underlying status-go api, SaveAccounts@accounts.go, returns `nil` for \c CallPrivateRpcResponse.result
|
||||
|
@ -57,4 +64,4 @@ void deleteAccount(const EOAddress &address);
|
|||
/// \throws \c CallPrivateRpcError
|
||||
void deleteMultiaccount(const QString& keyUID, const fs::path& keyStoreDir);
|
||||
|
||||
} // namespaces
|
||||
} // namespace Status::StatusGo::Accounts
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
#include "ChatOrWalletAccount.h"
|
||||
|
||||
namespace Status::StatusGo::Accounts {
|
||||
namespace Status::StatusGo::Accounts
|
||||
{
|
||||
|
||||
void to_json(json& j, const ChatOrWalletAccount& d) {
|
||||
j = {{"address", d.address},
|
||||
void to_json(json& j, const ChatOrWalletAccount& d)
|
||||
{
|
||||
j = {
|
||||
{"address", d.address},
|
||||
{"chat", d.isChat},
|
||||
{"clock", d.clock},
|
||||
{"color", d.color},
|
||||
|
@ -17,11 +20,11 @@ void to_json(json& j, const ChatOrWalletAccount& d) {
|
|||
{"wallet", d.isWallet},
|
||||
};
|
||||
|
||||
if(d.derivedFrom != std::nullopt)
|
||||
j["derived-from"] = d.derivedFrom.value();
|
||||
if(d.derivedFrom != std::nullopt) j["derived-from"] = d.derivedFrom.value();
|
||||
}
|
||||
|
||||
void from_json(const json& j, ChatOrWalletAccount& d) {
|
||||
void from_json(const json& j, ChatOrWalletAccount& d)
|
||||
{
|
||||
j.at("address").get_to(d.address);
|
||||
j.at("chat").get_to(d.isChat);
|
||||
j.at("clock").get_to(d.clock);
|
||||
|
@ -34,13 +37,11 @@ void from_json(const json& j, ChatOrWalletAccount& d) {
|
|||
j.at("wallet").get_to(d.isWallet);
|
||||
|
||||
constexpr auto pathKey = "path";
|
||||
if(j.contains(pathKey))
|
||||
j.at(pathKey).get_to(d.path);
|
||||
if(j.contains(pathKey)) j.at(pathKey).get_to(d.path);
|
||||
constexpr auto publicKeyKey = "public-key";
|
||||
if(j.contains(publicKeyKey))
|
||||
j.at(publicKeyKey).get_to(d.publicKey);
|
||||
if(j.contains(publicKeyKey)) j.at(publicKeyKey).get_to(d.publicKey);
|
||||
if(d.isWallet && !j.at("derived-from").get<std::string>().empty())
|
||||
d.derivedFrom = j.at("derived-from").get<std::optional<EOAddress>>();
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status::StatusGo::Accounts
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Status::StatusGo::Accounts {
|
||||
|
||||
namespace Status::StatusGo::Accounts
|
||||
{
|
||||
|
||||
/// \brief Unique wallet account entity
|
||||
/// \note equivalent of status-go's accounts.Account@multiaccounts/accounts/database.go
|
||||
|
@ -39,4 +39,4 @@ using ChatOrWalletAccounts = std::vector<ChatOrWalletAccount>;
|
|||
void to_json(json& j, const ChatOrWalletAccount& d);
|
||||
void from_json(const json& j, ChatOrWalletAccount& d);
|
||||
|
||||
}
|
||||
} // namespace Status::StatusGo::Accounts
|
||||
|
|
|
@ -7,10 +7,11 @@
|
|||
using json = nlohmann::json;
|
||||
|
||||
/// Defines phantom types for strong typing
|
||||
namespace Status::StatusGo::Accounts {
|
||||
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>;
|
||||
|
||||
}
|
||||
} // namespace Status::StatusGo::Accounts
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "ChatAPI.h"
|
||||
|
||||
#include "Utils.h"
|
||||
#include "Metadata/api_response.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#include <libstatus.h>
|
||||
|
||||
|
@ -13,11 +13,7 @@ using namespace Status::StatusGo;
|
|||
|
||||
Chats::AllChannelGroupsDto Chats::getChats()
|
||||
{
|
||||
json inputJson = {
|
||||
{"jsonrpc", "2.0"},
|
||||
{"method", "chat_getChats"},
|
||||
{"params", json::array()}
|
||||
};
|
||||
json inputJson = {{"jsonrpc", "2.0"}, {"method", "chat_getChats"}, {"params", json::array()}};
|
||||
|
||||
auto result = Utils::statusGoCallPrivateRPC(inputJson.dump().c_str());
|
||||
const auto resultJson = json::parse(result);
|
||||
|
|
|
@ -6,4 +6,4 @@ namespace Status::StatusGo::Chats
|
|||
{
|
||||
/// \brief Retrieve all available channel groups
|
||||
AllChannelGroupsDto getChats();
|
||||
}
|
||||
} // namespace Status::StatusGo::Chats
|
||||
|
|
|
@ -1,75 +1,87 @@
|
|||
#include "ChatDto.h"
|
||||
|
||||
#include <Helpers/conversions.h>
|
||||
#include <Helpers/JsonMacros.h>
|
||||
#include <Helpers/conversions.h>
|
||||
|
||||
using namespace Status::StatusGo;
|
||||
|
||||
void Chats::to_json(json& j, const Category& d) {
|
||||
j = {{"id", d.id},
|
||||
void Chats::to_json(json& j, const Category& d)
|
||||
{
|
||||
j = {
|
||||
{"id", d.id},
|
||||
{"name", d.name},
|
||||
{"position", d.position},
|
||||
};
|
||||
}
|
||||
|
||||
void Chats::from_json(const json& j, Category& d) {
|
||||
void Chats::from_json(const json& j, Category& d)
|
||||
{
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY(name)
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY(position)
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY(id, "category_id", false)
|
||||
if (!j.contains("category_id")){
|
||||
if(!j.contains("category_id"))
|
||||
{
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY(id, "id", false)
|
||||
}
|
||||
}
|
||||
|
||||
void Chats::to_json(json& j, const Permission& d) {
|
||||
j = {{"access", d.access},
|
||||
void Chats::to_json(json& j, const Permission& d)
|
||||
{
|
||||
j = {
|
||||
{"access", d.access},
|
||||
{"ens_only", d.ensOnly},
|
||||
};
|
||||
}
|
||||
|
||||
void Chats::from_json(const json& j, Permission& d) {
|
||||
void Chats::from_json(const json& j, Permission& d)
|
||||
{
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY(access, "access", false)
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY(ensOnly, "ens_only", false)
|
||||
}
|
||||
|
||||
void Chats::to_json(json& j, const Images& d) {
|
||||
j = {{"large", d.large},
|
||||
void Chats::to_json(json& j, const Images& d)
|
||||
{
|
||||
j = {
|
||||
{"large", d.large},
|
||||
{"thumbnail", d.thumbnail},
|
||||
{"banner", d.banner},
|
||||
};
|
||||
}
|
||||
|
||||
void Chats::from_json(const json& j, Images& d) {
|
||||
void Chats::from_json(const json& j, Images& d)
|
||||
{
|
||||
constexpr auto large = "large";
|
||||
if(j.contains(large))
|
||||
j[large].at("uri").get_to(d.large);
|
||||
if(j.contains(large)) j[large].at("uri").get_to(d.large);
|
||||
|
||||
constexpr auto thumbnail = "thumbnail";
|
||||
if(j.contains(thumbnail))
|
||||
j[thumbnail].at("uri").get_to(d.thumbnail);
|
||||
if(j.contains(thumbnail)) j[thumbnail].at("uri").get_to(d.thumbnail);
|
||||
|
||||
constexpr auto banner = "banner";
|
||||
if(j.contains(banner))
|
||||
j[banner].at("uri").get_to(d.banner);
|
||||
if(j.contains(banner)) j[banner].at("uri").get_to(d.banner);
|
||||
}
|
||||
|
||||
void Chats::to_json(json& j, const ChatMember& d) {
|
||||
j = {{"id", d.id},
|
||||
void Chats::to_json(json& j, const ChatMember& d)
|
||||
{
|
||||
j = {
|
||||
{"id", d.id},
|
||||
{"admin", d.admin},
|
||||
{"joined", d.joined},
|
||||
{"roles", d.roles},
|
||||
};
|
||||
}
|
||||
|
||||
void Chats::from_json(const json& j, ChatMember& d) {
|
||||
void Chats::from_json(const json& j, ChatMember& d)
|
||||
{
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY(id)
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY(joined)
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY(roles)
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY(admin, "admin", false)
|
||||
}
|
||||
|
||||
void Chats::to_json(json& j, const ChatDto& d) {
|
||||
j = {{"id", d.id},
|
||||
void Chats::to_json(json& j, const ChatDto& d)
|
||||
{
|
||||
j = {
|
||||
{"id", d.id},
|
||||
{"name", d.name},
|
||||
{"description", d.description},
|
||||
{"color", d.color},
|
||||
|
@ -99,7 +111,8 @@ void Chats::to_json(json& j, const ChatDto& d) {
|
|||
};
|
||||
}
|
||||
|
||||
void Chats::from_json(const json& j, ChatDto& d) {
|
||||
void Chats::from_json(const json& j, ChatDto& d)
|
||||
{
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY(id)
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY(name)
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY(description)
|
||||
|
@ -127,25 +140,31 @@ void Chats::from_json(const json& j, ChatDto& d) {
|
|||
STATUS_READ_NLOHMAN_JSON_PROPERTY(chatType)
|
||||
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY(categoryId, "categoryId", false)
|
||||
if (!j.contains("categoryId")) {
|
||||
if(!j.contains("categoryId"))
|
||||
{
|
||||
// Communities have `categoryID` and chats have `categoryId`
|
||||
// This should be fixed in status-go, but would be a breaking change
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY(categoryId, "categoryID", false)
|
||||
}
|
||||
|
||||
// Add community ID if needed
|
||||
if (!d.communityId.isEmpty() && !d.id.contains(d.communityId)) {
|
||||
if(!d.communityId.isEmpty() && !d.id.contains(d.communityId))
|
||||
{
|
||||
d.id = d.communityId + d.id;
|
||||
}
|
||||
|
||||
constexpr auto membersKey = "members";
|
||||
if (j.contains(membersKey)) {
|
||||
if (j[membersKey].is_array()) {
|
||||
if(j.contains(membersKey))
|
||||
{
|
||||
if(j[membersKey].is_array())
|
||||
{
|
||||
j.at(membersKey).get_to(d.members);
|
||||
}
|
||||
else if (j[membersKey].is_object()) {
|
||||
else if(j[membersKey].is_object())
|
||||
{
|
||||
auto obj = j[membersKey];
|
||||
for (json::const_iterator it = obj.cbegin(); it != obj.cend(); ++it) {
|
||||
for(json::const_iterator it = obj.cbegin(); it != obj.cend(); ++it)
|
||||
{
|
||||
ChatMember chatMember;
|
||||
it.value().get_to(chatMember);
|
||||
chatMember.id = it.key().c_str();
|
||||
|
@ -155,8 +174,10 @@ void Chats::from_json(const json& j, ChatDto& d) {
|
|||
}
|
||||
}
|
||||
|
||||
void Chats::to_json(json& j, const ChannelGroupDto& d) {
|
||||
j = {{"id", d.id},
|
||||
void Chats::to_json(json& j, const ChannelGroupDto& d)
|
||||
{
|
||||
j = {
|
||||
{"id", d.id},
|
||||
{"admin", d.admin},
|
||||
{"verified", d.verified},
|
||||
{"name", d.name},
|
||||
|
@ -175,7 +196,8 @@ void Chats::to_json(json& j, const ChannelGroupDto& d) {
|
|||
};
|
||||
}
|
||||
|
||||
void Chats::from_json(const json& j, ChannelGroupDto& d) {
|
||||
void Chats::from_json(const json& j, ChannelGroupDto& d)
|
||||
{
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY(admin)
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY(verified)
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY(name)
|
||||
|
@ -189,13 +211,14 @@ void Chats::from_json(const json& j, ChannelGroupDto& d) {
|
|||
STATUS_READ_NLOHMAN_JSON_PROPERTY(permissions, "permissions", false)
|
||||
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY(channelGroupType)
|
||||
if (d.channelGroupType.isEmpty())
|
||||
d.channelGroupType = ChannelGroupTypeUnknown;
|
||||
if(d.channelGroupType.isEmpty()) d.channelGroupType = ChannelGroupTypeUnknown;
|
||||
|
||||
constexpr auto chats = "chats";
|
||||
if (j.contains(chats)) {
|
||||
if(j.contains(chats))
|
||||
{
|
||||
auto obj = j[chats];
|
||||
for (json::const_iterator it = obj.cbegin(); it != obj.cend(); ++it) {
|
||||
for(json::const_iterator it = obj.cbegin(); it != obj.cend(); ++it)
|
||||
{
|
||||
ChatDto chatDto;
|
||||
it.value().get_to(chatDto);
|
||||
d.chats.emplace_back(std::move(chatDto));
|
||||
|
@ -203,9 +226,11 @@ void Chats::from_json(const json& j, ChannelGroupDto& d) {
|
|||
}
|
||||
|
||||
constexpr auto categories = "categories";
|
||||
if (j.contains(categories)) {
|
||||
if(j.contains(categories))
|
||||
{
|
||||
auto obj = j[categories];
|
||||
for (json::const_iterator it = obj.cbegin(); it != obj.cend(); ++it) {
|
||||
for(json::const_iterator it = obj.cbegin(); it != obj.cend(); ++it)
|
||||
{
|
||||
Category category;
|
||||
it.value().get_to(category);
|
||||
d.categories.emplace_back(std::move(category));
|
||||
|
@ -213,10 +238,13 @@ void Chats::from_json(const json& j, ChannelGroupDto& d) {
|
|||
}
|
||||
|
||||
constexpr auto membersKey = "members";
|
||||
if (j.contains(membersKey)) {
|
||||
if (j[membersKey].is_object()) {
|
||||
if(j.contains(membersKey))
|
||||
{
|
||||
if(j[membersKey].is_object())
|
||||
{
|
||||
auto obj = j[membersKey];
|
||||
for (json::const_iterator it = obj.cbegin(); it != obj.cend(); ++it) {
|
||||
for(json::const_iterator it = obj.cbegin(); it != obj.cend(); ++it)
|
||||
{
|
||||
ChatMember chatMember;
|
||||
it.value().get_to(chatMember);
|
||||
chatMember.id = it.key().c_str();
|
||||
|
@ -226,16 +254,18 @@ void Chats::from_json(const json& j, ChannelGroupDto& d) {
|
|||
}
|
||||
}
|
||||
|
||||
void Chats::to_json(json& j, const AllChannelGroupsDto& d) {
|
||||
void Chats::to_json(json& j, const AllChannelGroupsDto& d)
|
||||
{
|
||||
j = {{"id", d.allChannelGroups}};
|
||||
}
|
||||
|
||||
void Chats::from_json(const json& j, AllChannelGroupsDto& d) {
|
||||
for (json::const_iterator it = j.cbegin(); it != j.cend(); ++it) {
|
||||
void Chats::from_json(const json& j, AllChannelGroupsDto& d)
|
||||
{
|
||||
for(json::const_iterator it = j.cbegin(); it != j.cend(); ++it)
|
||||
{
|
||||
ChannelGroupDto channelGroupDto;
|
||||
it.value().get_to(channelGroupDto);
|
||||
channelGroupDto.id = it.key().c_str();
|
||||
d.allChannelGroups.emplace_back(std::move(channelGroupDto));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Status::StatusGo::Chats {
|
||||
namespace Status::StatusGo::Chats
|
||||
{
|
||||
|
||||
constexpr auto ChannelGroupTypeUnknown = "unknown";
|
||||
constexpr auto ChannelGroupTypePersonal = "personal";
|
||||
|
@ -24,31 +25,36 @@ namespace Status::StatusGo::Chats {
|
|||
CommunityChat = 6
|
||||
};
|
||||
|
||||
struct Category {
|
||||
struct Category
|
||||
{
|
||||
QString id;
|
||||
QString name;
|
||||
int position;
|
||||
};
|
||||
|
||||
struct Permission {
|
||||
struct Permission
|
||||
{
|
||||
int access;
|
||||
bool ensOnly;
|
||||
};
|
||||
|
||||
struct Images {
|
||||
struct Images
|
||||
{
|
||||
QString thumbnail;
|
||||
QString large;
|
||||
QString banner;
|
||||
};
|
||||
|
||||
struct ChatMember {
|
||||
struct ChatMember
|
||||
{
|
||||
QString id;
|
||||
bool admin;
|
||||
bool joined;
|
||||
std::vector<int> roles;
|
||||
};
|
||||
|
||||
struct ChatDto {
|
||||
struct ChatDto
|
||||
{
|
||||
QString id; // ID is the id of the chat, for public chats it is the name e.g. status,
|
||||
// for one-to-one is the hex encoded public key and for group chats is a random
|
||||
// uuid appended with the hex encoded pk of the creator of the chat
|
||||
|
@ -60,7 +66,8 @@ namespace Status::StatusGo::Chats {
|
|||
ChatType chatType;
|
||||
quint64 timestamp; // indicates the last time this chat has received/sent a message
|
||||
quint64 lastClockValue; // indicates the last clock value to be used when sending messages
|
||||
quint64 deletedAtClockValue; // indicates the clock value at time of deletion, messages with lower clock value of this should be discarded
|
||||
quint64
|
||||
deletedAtClockValue; // indicates the clock value at time of deletion, messages with lower clock value of this should be discarded
|
||||
quint64 readMessagesAtClockValue;
|
||||
int unviewedMessagesCount;
|
||||
int unviewedMentionsCount;
|
||||
|
@ -80,7 +87,8 @@ namespace Status::StatusGo::Chats {
|
|||
Permission permissions;
|
||||
};
|
||||
|
||||
struct ChannelGroupDto {
|
||||
struct ChannelGroupDto
|
||||
{
|
||||
QString id;
|
||||
QString channelGroupType;
|
||||
bool admin;
|
||||
|
@ -102,11 +110,13 @@ namespace Status::StatusGo::Chats {
|
|||
bool pinMessageAllMembersEnabled;
|
||||
};
|
||||
|
||||
struct AllChannelGroupsDto {
|
||||
struct AllChannelGroupsDto
|
||||
{
|
||||
std::vector<ChannelGroupDto> allChannelGroups;
|
||||
};
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(ChatType, {
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(ChatType,
|
||||
{
|
||||
{Unknown, "Unknown"},
|
||||
{OneToOne, "OneToOne"},
|
||||
{Public, "Public"},
|
||||
|
@ -129,4 +139,4 @@ namespace Status::StatusGo::Chats {
|
|||
void from_json(const json& j, ChannelGroupDto& d);
|
||||
void to_json(json& j, const AllChannelGroupsDto& d);
|
||||
void from_json(const json& j, AllChannelGroupsDto& d);
|
||||
}
|
||||
} // namespace Status::StatusGo::Chats
|
||||
|
|
|
@ -13,7 +13,8 @@ RpcResponse<QJsonObject> initKeystore(const char* keystoreDir)
|
|||
{
|
||||
auto result = InitKeystore(const_cast<char*>(keystoreDir));
|
||||
QJsonObject jsonResult;
|
||||
if(!Utils::checkReceivedResponse(result, jsonResult)) {
|
||||
if(!Utils::checkReceivedResponse(result, jsonResult))
|
||||
{
|
||||
throw std::domain_error("parsing response failed");
|
||||
}
|
||||
|
||||
|
@ -35,4 +36,4 @@ RpcResponse<QJsonObject> initKeystore(const char* keystoreDir)
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status::StatusGo::General
|
||||
|
|
|
@ -7,11 +7,7 @@ namespace Status::StatusGo::Messenger
|
|||
|
||||
bool startMessenger()
|
||||
{
|
||||
QJsonObject payload{
|
||||
{"jsonrpc", "2.0"},
|
||||
{"method", "wakuext_startMessenger"},
|
||||
{"params", QJsonArray()}
|
||||
};
|
||||
QJsonObject payload{{"jsonrpc", "2.0"}, {"method", "wakuext_startMessenger"}, {"params", QJsonArray()}};
|
||||
|
||||
auto callResult = Utils::callPrivateRpc<QJsonObject>(Utils::jsonToByteArray(payload));
|
||||
if(callResult.containsError())
|
||||
|
@ -19,4 +15,4 @@ bool startMessenger()
|
|||
return !callResult.containsError();
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status::StatusGo::Messenger
|
||||
|
|
|
@ -1,25 +1,28 @@
|
|||
#include "api_response.h"
|
||||
|
||||
namespace Status::StatusGo {
|
||||
namespace Status::StatusGo
|
||||
{
|
||||
|
||||
void checkApiError(const json &response) {
|
||||
if(response.contains("error")) {
|
||||
void checkApiError(const json& response)
|
||||
{
|
||||
if(response.contains("error"))
|
||||
{
|
||||
const auto& error = response["error"];
|
||||
if(error.is_object()) {
|
||||
if(error.is_object())
|
||||
{
|
||||
const auto apiErr = response["error"].get<ApiErrorResponseWithCode>();
|
||||
throw CallGenericPrepareJsonError(apiErr);
|
||||
}
|
||||
assert(error.is_string());
|
||||
const auto apiError = response.get<ApiErrorResponse>();
|
||||
if(!apiError.error.empty())
|
||||
throw CallGenericMakeJsonError(response.get<ApiErrorResponse>());
|
||||
if(!apiError.error.empty()) throw CallGenericMakeJsonError(response.get<ApiErrorResponse>());
|
||||
}
|
||||
}
|
||||
|
||||
/// \throws \c CallPrivateRpcError, \c nlohmann::exception
|
||||
void checkPrivateRpcCallResultAndReportError(const json &response) {
|
||||
if(response.contains("error"))
|
||||
throw CallPrivateRpcError(response.get<CallPrivateRpcErrorResponse>());
|
||||
void checkPrivateRpcCallResultAndReportError(const json& response)
|
||||
{
|
||||
if(response.contains("error")) throw CallPrivateRpcError(response.get<CallPrivateRpcErrorResponse>());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace Status::StatusGo
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Status::StatusGo {
|
||||
namespace Status::StatusGo
|
||||
{
|
||||
|
||||
/*!
|
||||
* \brief General API response if an internal status-go error occured
|
||||
|
@ -18,7 +19,8 @@ namespace Status::StatusGo {
|
|||
*
|
||||
* \note update NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE when changing structure's content
|
||||
*/
|
||||
struct ApiErrorResponse {
|
||||
struct ApiErrorResponse
|
||||
{
|
||||
std::string error;
|
||||
};
|
||||
|
||||
|
@ -31,7 +33,8 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(ApiErrorResponse, error)
|
|||
*
|
||||
* \note update NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE when changing structure's content
|
||||
*/
|
||||
struct JsonError {
|
||||
struct JsonError
|
||||
{
|
||||
int code{0};
|
||||
std::string message;
|
||||
};
|
||||
|
@ -45,7 +48,8 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonError, code, message)
|
|||
* \see jsonrpcSuccessfulResponse@response.go
|
||||
* \note update NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE when changing structure's content
|
||||
*/
|
||||
struct ApiErrorResponseWithCode {
|
||||
struct ApiErrorResponseWithCode
|
||||
{
|
||||
JsonError error;
|
||||
};
|
||||
|
||||
|
@ -60,7 +64,8 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(ApiErrorResponseWithCode, error)
|
|||
*
|
||||
* \note update NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE when changing structure's content
|
||||
*/
|
||||
struct ApiResponse {
|
||||
struct ApiResponse
|
||||
{
|
||||
json result;
|
||||
};
|
||||
|
||||
|
@ -116,38 +121,53 @@ void checkApiError(const json& response);
|
|||
|
||||
constexpr int defaultErrorCode = -32000;
|
||||
|
||||
class CallGenericMakeJsonError: public std::runtime_error {
|
||||
class CallGenericMakeJsonError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
CallGenericMakeJsonError(const ApiErrorResponse error)
|
||||
: std::runtime_error("CallGenericMakeJsonError@status-go failed")
|
||||
, m_error(std::move(error))
|
||||
{ }
|
||||
|
||||
const ApiErrorResponse &errorResponse() const { return m_error; };
|
||||
const ApiErrorResponse& errorResponse() const
|
||||
{
|
||||
return m_error;
|
||||
};
|
||||
|
||||
private:
|
||||
const ApiErrorResponse m_error;
|
||||
};
|
||||
|
||||
class CallGenericPrepareJsonError: public std::runtime_error {
|
||||
class CallGenericPrepareJsonError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
CallGenericPrepareJsonError(const ApiErrorResponseWithCode error)
|
||||
: std::runtime_error("CallGenericPrepareJsonError@status-go failed")
|
||||
, m_error(std::move(error))
|
||||
{ }
|
||||
|
||||
const ApiErrorResponseWithCode &errorResponse() const { return m_error; };
|
||||
const ApiErrorResponseWithCode& errorResponse() const
|
||||
{
|
||||
return m_error;
|
||||
};
|
||||
|
||||
private:
|
||||
const ApiErrorResponseWithCode m_error;
|
||||
};
|
||||
|
||||
class CallPrivateRpcError: public std::runtime_error {
|
||||
class CallPrivateRpcError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
CallPrivateRpcError(const CallPrivateRpcErrorResponse error)
|
||||
: std::runtime_error("CallPrivateRPC@status-go failed")
|
||||
, m_error(std::move(error))
|
||||
{ }
|
||||
|
||||
const CallPrivateRpcErrorResponse &errorResponse() const { return m_error; };
|
||||
const CallPrivateRpcErrorResponse& errorResponse() const
|
||||
{
|
||||
return m_error;
|
||||
};
|
||||
|
||||
private:
|
||||
const CallPrivateRpcErrorResponse m_error;
|
||||
};
|
||||
|
@ -160,4 +180,4 @@ private:
|
|||
*/
|
||||
void checkPrivateRpcCallResultAndReportError(const json& response);
|
||||
|
||||
}
|
||||
} // namespace Status::StatusGo
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "SettingsAPI.h"
|
||||
|
||||
#include "Utils.h"
|
||||
#include "Metadata/api_response.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#include <libstatus.h>
|
||||
|
||||
|
@ -13,11 +13,7 @@ using namespace Status::StatusGo;
|
|||
|
||||
Settings::SettingsDto Settings::getSettings()
|
||||
{
|
||||
json inputJson = {
|
||||
{"jsonrpc", "2.0"},
|
||||
{"method", "settings_getSettings"},
|
||||
{"params", json::array()}
|
||||
};
|
||||
json inputJson = {{"jsonrpc", "2.0"}, {"method", "settings_getSettings"}, {"params", json::array()}};
|
||||
|
||||
auto result = Utils::statusGoCallPrivateRPC(inputJson.dump().c_str());
|
||||
const auto resultJson = json::parse(result);
|
||||
|
|
|
@ -6,4 +6,4 @@ namespace Status::StatusGo::Settings
|
|||
{
|
||||
/// \brief Retrieve settings
|
||||
SettingsDto getSettings();
|
||||
}
|
||||
} // namespace Status::StatusGo::Settings
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
#include "SettingsDto.h"
|
||||
|
||||
#include <Helpers/conversions.h>
|
||||
#include <Helpers/JsonMacros.h>
|
||||
#include <Helpers/conversions.h>
|
||||
|
||||
using namespace Status::StatusGo;
|
||||
|
||||
void Settings::to_json(json& j, const SettingsDto& d) {
|
||||
j = {{"address", d.address},
|
||||
void Settings::to_json(json& j, const SettingsDto& d)
|
||||
{
|
||||
j = {
|
||||
{"address", d.address},
|
||||
{"display-name", d.displayName},
|
||||
{"preferred-name", d.preferredName},
|
||||
{"key-uid", d.keyUid},
|
||||
|
@ -14,7 +16,8 @@ void Settings::to_json(json& j, const SettingsDto& d) {
|
|||
};
|
||||
}
|
||||
|
||||
void Settings::from_json(const json& j, SettingsDto& d) {
|
||||
void Settings::from_json(const json& j, SettingsDto& d)
|
||||
{
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY(address)
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY(displayName, "display-name")
|
||||
STATUS_READ_NLOHMAN_JSON_PROPERTY(preferredName, "preferred-name", false)
|
||||
|
|
|
@ -8,9 +8,11 @@
|
|||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Status::StatusGo::Settings {
|
||||
namespace Status::StatusGo::Settings
|
||||
{
|
||||
|
||||
struct SettingsDto {
|
||||
struct SettingsDto
|
||||
{
|
||||
QString address;
|
||||
QString displayName;
|
||||
QString preferredName;
|
||||
|
@ -20,4 +22,4 @@ namespace Status::StatusGo::Settings {
|
|||
|
||||
void to_json(json& j, const SettingsDto& d);
|
||||
void from_json(const json& j, SettingsDto& d);
|
||||
}
|
||||
} // namespace Status::StatusGo::Settings
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
|
||||
using namespace std::string_literals;
|
||||
|
||||
namespace Status::StatusGo {
|
||||
namespace Status::StatusGo
|
||||
{
|
||||
|
||||
std::map<std::string, SignalType> SignalsManager::signalMap;
|
||||
|
||||
|
@ -22,8 +23,7 @@ SignalsManager::SignalsManager()
|
|||
{
|
||||
SetSignalEventCallback((void*)&SignalsManager::signalCallback);
|
||||
|
||||
signalMap = {
|
||||
{"node.ready"s, SignalType::NodeReady},
|
||||
signalMap = {{"node.ready"s, SignalType::NodeReady},
|
||||
{"node.started"s, SignalType::NodeStarted},
|
||||
{"node.stopped"s, SignalType::NodeStopped},
|
||||
{"node.login"s, SignalType::NodeLogin},
|
||||
|
@ -38,13 +38,10 @@ SignalsManager::SignalsManager()
|
|||
|
||||
{"history.request.started"s, SignalType::HistoryRequestStarted},
|
||||
{"history.request.batch.processed"s, SignalType::HistoryRequestBatchProcessed},
|
||||
{"history.request.completed"s, SignalType::HistoryRequestCompleted}
|
||||
};
|
||||
{"history.request.completed"s, SignalType::HistoryRequestCompleted}};
|
||||
}
|
||||
|
||||
SignalsManager::~SignalsManager()
|
||||
{
|
||||
}
|
||||
SignalsManager::~SignalsManager() { }
|
||||
|
||||
void SignalsManager::processSignal(const QString& statusSignal)
|
||||
{
|
||||
|
@ -82,46 +79,22 @@ void SignalsManager::decode(const QJsonObject& signalEvent)
|
|||
switch(signalType)
|
||||
{
|
||||
// TODO: create extractor functions like in nim
|
||||
case NodeLogin:
|
||||
emit nodeLogin(signalError);
|
||||
break;
|
||||
case NodeReady:
|
||||
emit nodeReady(signalError);
|
||||
break;
|
||||
case NodeStarted:
|
||||
emit nodeStarted(signalError);
|
||||
break;
|
||||
case NodeStopped:
|
||||
emit nodeStopped(signalError);
|
||||
break;
|
||||
case NodeLogin: emit nodeLogin(signalError); break;
|
||||
case NodeReady: emit nodeReady(signalError); break;
|
||||
case NodeStarted: emit nodeStarted(signalError); break;
|
||||
case NodeStopped: emit nodeStopped(signalError); break;
|
||||
case NodeCrashed:
|
||||
qWarning() << "node.crashed, error: " << signalError;
|
||||
emit nodeCrashed(signalError);
|
||||
break;
|
||||
case DiscoveryStarted:
|
||||
emit discoveryStarted(signalError);
|
||||
break;
|
||||
case DiscoveryStopped:
|
||||
emit discoveryStopped(signalError);
|
||||
break;
|
||||
case DiscoverySummary:
|
||||
emit discoverySummary(signalEvent["event"].toArray().count(), signalError);
|
||||
break;
|
||||
case MailserverChanged:
|
||||
emit mailserverChanged(signalError);
|
||||
break;
|
||||
case MailserverAvailable:
|
||||
emit mailserverAvailable(signalError);
|
||||
break;
|
||||
case HistoryRequestStarted:
|
||||
emit historyRequestStarted(signalError);
|
||||
break;
|
||||
case HistoryRequestBatchProcessed:
|
||||
emit historyRequestBatchProcessed(signalError);
|
||||
break;
|
||||
case HistoryRequestCompleted:
|
||||
emit historyRequestCompleted(signalError);
|
||||
break;
|
||||
case DiscoveryStarted: emit discoveryStarted(signalError); break;
|
||||
case DiscoveryStopped: emit discoveryStopped(signalError); break;
|
||||
case DiscoverySummary: emit discoverySummary(signalEvent["event"].toArray().count(), signalError); break;
|
||||
case MailserverChanged: emit mailserverChanged(signalError); break;
|
||||
case MailserverAvailable: emit mailserverAvailable(signalError); break;
|
||||
case HistoryRequestStarted: emit historyRequestStarted(signalError); break;
|
||||
case HistoryRequestBatchProcessed: emit historyRequestBatchProcessed(signalError); break;
|
||||
case HistoryRequestCompleted: emit historyRequestCompleted(signalError); break;
|
||||
case Unknown: assert(false); break;
|
||||
}
|
||||
}
|
||||
|
@ -130,9 +103,8 @@ void SignalsManager::signalCallback(const char* data)
|
|||
{
|
||||
// TODO: overkill, use some kind of message broker
|
||||
auto dataStrPtr = std::make_shared<QString>(data);
|
||||
QFuture<void> future = QtConcurrent::run([dataStrPtr](){
|
||||
SignalsManager::instance()->processSignal(*dataStrPtr);
|
||||
});
|
||||
QFuture<void> future =
|
||||
QtConcurrent::run([dataStrPtr]() { SignalsManager::instance()->processSignal(*dataStrPtr); });
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status::StatusGo
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
#include <QObject>
|
||||
|
||||
namespace Status::StatusGo {
|
||||
namespace Status::StatusGo
|
||||
{
|
||||
|
||||
enum SignalType
|
||||
{
|
||||
|
@ -35,7 +36,6 @@ class SignalsManager final : public QObject
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
static SignalsManager* instance();
|
||||
|
||||
void processSignal(const QString& ev);
|
||||
|
@ -57,6 +57,7 @@ signals:
|
|||
void historyRequestStarted(const QString& error);
|
||||
void historyRequestBatchProcessed(const QString& error);
|
||||
void historyRequestCompleted(const QString& error);
|
||||
|
||||
private:
|
||||
explicit SignalsManager();
|
||||
~SignalsManager();
|
||||
|
@ -67,4 +68,4 @@ private:
|
|||
void decode(const QJsonObject& signalEvent);
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Status::StatusGo
|
||||
|
|
|
@ -30,8 +30,9 @@ struct RpcResponse
|
|||
int id;
|
||||
RpcError error;
|
||||
|
||||
explicit
|
||||
RpcResponse(T result, QString version = RpcError::UnknownVersion, int id = RpcError::UnknownId,
|
||||
explicit RpcResponse(T result,
|
||||
QString version = RpcError::UnknownVersion,
|
||||
int id = RpcError::UnknownId,
|
||||
RpcError error = RpcError())
|
||||
: result(std::move(result))
|
||||
, jsonRpcVersion(std::move(version))
|
||||
|
@ -39,9 +40,10 @@ struct RpcResponse
|
|||
, error(std::move(error))
|
||||
{ }
|
||||
|
||||
bool containsError() const {
|
||||
bool containsError() const
|
||||
{
|
||||
return !error.message.isEmpty() || error.code != RpcError::NoError;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Status::StatusGo
|
||||
|
|
|
@ -15,7 +15,8 @@ QJsonArray toJsonArray(const std::vector<Accounts::DerivationPath>& value)
|
|||
return array;
|
||||
}
|
||||
|
||||
const char* statusGoCallPrivateRPC(const char* inputJSON) {
|
||||
const char* statusGoCallPrivateRPC(const char* inputJSON)
|
||||
{
|
||||
// Evil done here! status-go API doesn't follow the proper const conventions
|
||||
return CallPrivateRPC(const_cast<char*>(inputJSON));
|
||||
}
|
||||
|
@ -23,17 +24,16 @@ const char* statusGoCallPrivateRPC(const char* inputJSON) {
|
|||
HashedPassword hashPassword(const QString& str)
|
||||
{
|
||||
// TODO: is utf8 the standard used by NIM also? Will it unlock DBs encrypted with NIM password hashing?
|
||||
return HashedPassword("0x" + QString::fromUtf8(QCryptographicHash::hash(str.toUtf8(),
|
||||
QCryptographicHash::Keccak_256).toHex().toUpper()));
|
||||
return HashedPassword(
|
||||
"0x" +
|
||||
QString::fromUtf8(QCryptographicHash::hash(str.toUtf8(), QCryptographicHash::Keccak_256).toHex().toUpper()));
|
||||
}
|
||||
|
||||
std::optional<RpcError> getRPCErrorInJson(const QJsonObject& json)
|
||||
{
|
||||
auto errVal = json[Param::Error];
|
||||
if (errVal.isNull() || errVal.isUndefined())
|
||||
return std::nullopt;
|
||||
if(errVal.isString() && errVal.toString().length() == 0)
|
||||
return std::nullopt;
|
||||
if(errVal.isNull() || errVal.isUndefined()) return std::nullopt;
|
||||
if(errVal.isString() && errVal.toString().length() == 0) return std::nullopt;
|
||||
|
||||
RpcError response;
|
||||
auto errObj = json[Param::Id].toObject();
|
||||
|
@ -46,4 +46,4 @@ std::optional<RpcError> getRPCErrorInJson(const QJsonObject& json)
|
|||
return response;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status::StatusGo::Utils
|
||||
|
|
|
@ -1,29 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
#include "Types.h"
|
||||
#include "Accounts/accounts_types.h"
|
||||
#include "Types.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
|
||||
namespace Status::StatusGo::Utils
|
||||
{
|
||||
|
||||
namespace Param {
|
||||
namespace Param
|
||||
{
|
||||
static constexpr auto Id{"id"};
|
||||
static constexpr auto JsonRpc{"jsonrpc"};
|
||||
static constexpr auto Result{"result"};
|
||||
static constexpr auto Error{"error"};
|
||||
static constexpr auto ErrorMessage{"message"};
|
||||
static constexpr auto ErrorCode{"code"};
|
||||
}
|
||||
} // namespace Param
|
||||
|
||||
template <class T>
|
||||
QByteArray jsonToByteArray(const T& json)
|
||||
{
|
||||
static_assert(std::is_same_v<T, QJsonObject> ||
|
||||
std::is_same_v<T, QJsonArray>, "Wrong Json type. Supported: Object, Array");
|
||||
static_assert(std::is_same_v<T, QJsonObject> || std::is_same_v<T, QJsonArray>,
|
||||
"Wrong Json type. Supported: Object, Array");
|
||||
return QJsonDocument(json).toJson(QJsonDocument::Compact);
|
||||
}
|
||||
|
||||
|
@ -37,8 +38,7 @@ bool checkReceivedResponse(const QString& response, T& json)
|
|||
{
|
||||
QJsonParseError error;
|
||||
auto jsonDocument = QJsonDocument::fromJson(response.toUtf8(), &error);
|
||||
if (error.error != QJsonParseError::NoError)
|
||||
return false;
|
||||
if(error.error != QJsonParseError::NoError) return false;
|
||||
|
||||
if constexpr(std::is_same_v<T, QJsonObject>)
|
||||
{
|
||||
|
@ -62,8 +62,7 @@ RpcResponse<T> buildPrivateRPCResponse(const T& json)
|
|||
|
||||
if constexpr(std::is_same_v<T, QJsonObject>)
|
||||
{
|
||||
if (!json[Param::Id].isNull() && !json[Param::Id].isUndefined())
|
||||
response.id = json[Param::Id].toInt();
|
||||
if(!json[Param::Id].isNull() && !json[Param::Id].isUndefined()) response.id = json[Param::Id].toInt();
|
||||
|
||||
if(!json[Param::JsonRpc].isNull() && !json[Param::JsonRpc].isUndefined())
|
||||
response.jsonRpcVersion = json[Param::JsonRpc].toString();
|
||||
|
@ -114,4 +113,4 @@ RpcResponse<T> callPrivateRpc(const QByteArray& payload)
|
|||
|
||||
HashedPassword hashPassword(const QString& str);
|
||||
|
||||
}
|
||||
} // namespace Status::StatusGo::Utils
|
||||
|
|
|
@ -1,36 +1,36 @@
|
|||
#include "BigInt.h"
|
||||
|
||||
#include <locale>
|
||||
#include <iostream>
|
||||
#include <locale>
|
||||
|
||||
#include <Helpers/helpers.h>
|
||||
|
||||
namespace Status {
|
||||
namespace StatusGo::Wallet {
|
||||
namespace Status
|
||||
{
|
||||
namespace StatusGo::Wallet
|
||||
{
|
||||
|
||||
std::string toHexData(const BigInt& num, bool uppercase)
|
||||
{
|
||||
return num.str(0, std::ios_base::showbase | std::ios_base::hex | (uppercase ? std::ios_base::uppercase : std::ios_base::fmtflags(0)));
|
||||
return num.str(0,
|
||||
std::ios_base::showbase | std::ios_base::hex |
|
||||
(uppercase ? std::ios_base::uppercase : std::ios_base::fmtflags(0)));
|
||||
}
|
||||
|
||||
|
||||
using namespace QtLiterals;
|
||||
|
||||
bool has0xPrefix(const QByteArray &in) {
|
||||
bool has0xPrefix(const QByteArray& in)
|
||||
{
|
||||
return in.size() >= 2 && Helpers::iequals(in.first(2), "0x"_qba);
|
||||
}
|
||||
|
||||
BigInt parseHex(const std::string& value)
|
||||
{
|
||||
auto data = QByteArray::fromRawData(value.c_str(), value.size());
|
||||
if (!has0xPrefix(data))
|
||||
throw std::runtime_error("BigInt::parseHex missing 0x prefix");
|
||||
if (data.size() == 2)
|
||||
throw std::runtime_error("BigInt::parseHex empty number");
|
||||
if (data.size() > 3 && data[2] == '0')
|
||||
throw std::runtime_error("BigInt::parseHex leading zero");
|
||||
if (data.size() > 66)
|
||||
throw std::runtime_error("BigInt::parseHex more than 256 bits");
|
||||
if(!has0xPrefix(data)) throw std::runtime_error("BigInt::parseHex missing 0x prefix");
|
||||
if(data.size() == 2) throw std::runtime_error("BigInt::parseHex empty number");
|
||||
if(data.size() > 3 && data[2] == '0') throw std::runtime_error("BigInt::parseHex leading zero");
|
||||
if(data.size() > 66) throw std::runtime_error("BigInt::parseHex more than 256 bits");
|
||||
return BigInt{data.data()};
|
||||
}
|
||||
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Status {
|
||||
namespace StatusGo::Wallet {
|
||||
namespace Status
|
||||
{
|
||||
namespace StatusGo::Wallet
|
||||
{
|
||||
|
||||
using BigInt = boost::multiprecision::uint256_t;
|
||||
|
||||
|
@ -24,24 +26,28 @@ std::string toHexData(const BigInt &num, bool uppercase = false);
|
|||
/// \see toHexData
|
||||
BigInt parseHex(const std::string& value);
|
||||
|
||||
}
|
||||
} // namespace StatusGo::Wallet
|
||||
|
||||
/// Human readable form
|
||||
QString toQString(const StatusGo::Wallet::BigInt& num);
|
||||
|
||||
} // Status::StatusGo::Wallet
|
||||
} // namespace Status
|
||||
|
||||
namespace nlohmann {
|
||||
namespace nlohmann
|
||||
{
|
||||
|
||||
namespace GoWallet = Status::StatusGo::Wallet;
|
||||
|
||||
template <>
|
||||
struct adl_serializer<GoWallet::BigInt> {
|
||||
static void to_json(json& j, const GoWallet::BigInt& num) {
|
||||
struct adl_serializer<GoWallet::BigInt>
|
||||
{
|
||||
static void to_json(json& j, const GoWallet::BigInt& num)
|
||||
{
|
||||
j = GoWallet::toHexData(num);
|
||||
}
|
||||
|
||||
static void from_json(const json& j, GoWallet::BigInt& num) {
|
||||
static void from_json(const json& j, GoWallet::BigInt& num)
|
||||
{
|
||||
num = GoWallet::BigInt(j.get<std::string>());
|
||||
}
|
||||
};
|
||||
|
|
|
@ -14,7 +14,8 @@ namespace Accounts = Status::StatusGo::Accounts;
|
|||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Status::StatusGo::Wallet {
|
||||
namespace Status::StatusGo::Wallet
|
||||
{
|
||||
|
||||
/// \brief Define a derived address as returned by the corresponding API
|
||||
/// \note equivalent of status-go's DerivedAddress@api.go
|
||||
|
@ -31,4 +32,4 @@ using DerivedAddresses = std::vector<DerivedAddress>;
|
|||
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(DerivedAddress, address, path, hasActivity, alreadyCreated);
|
||||
|
||||
}
|
||||
} // namespace Status::StatusGo::Wallet
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
using json = nlohmann::json;
|
||||
|
||||
/// \note not sure if this is the best namespace, ok for now
|
||||
namespace Status::StatusGo::Wallet {
|
||||
namespace Status::StatusGo::Wallet
|
||||
{
|
||||
|
||||
/// \note equivalent of status-go's Network@config.go (params package)
|
||||
struct NetworkConfiguration
|
||||
|
@ -34,9 +35,19 @@ struct NetworkConfiguration
|
|||
|
||||
using NetworkConfigurations = std::vector<NetworkConfiguration>;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(NetworkConfiguration, chainId, chainName, rpcUrl, blockExplorerUrl,
|
||||
iconUrl, nativeCurrencyName, nativeCurrencySymbol,
|
||||
nativeCurrencyDecimals, isTest, layer, enabled, chainColor,
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(NetworkConfiguration,
|
||||
chainId,
|
||||
chainName,
|
||||
rpcUrl,
|
||||
blockExplorerUrl,
|
||||
iconUrl,
|
||||
nativeCurrencyName,
|
||||
nativeCurrencySymbol,
|
||||
nativeCurrencyDecimals,
|
||||
isTest,
|
||||
layer,
|
||||
enabled,
|
||||
chainColor,
|
||||
shortName);
|
||||
|
||||
}
|
||||
} // namespace Status::StatusGo::Wallet
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "wallet_types.h"
|
||||
#include "Accounts/accounts_types.h"
|
||||
#include "wallet_types.h"
|
||||
|
||||
#include <Helpers/conversions.h>
|
||||
|
||||
|
@ -11,7 +11,8 @@
|
|||
|
||||
namespace Accounts = Status::StatusGo::Accounts;
|
||||
|
||||
namespace Status::StatusGo::Wallet {
|
||||
namespace Status::StatusGo::Wallet
|
||||
{
|
||||
|
||||
/// \brief Define a saved wallet address as returned by the corresponding API
|
||||
/// \note equivalent of status-go's SavedAddress@api.go
|
||||
|
@ -28,4 +29,4 @@ using SavedAddresses = std::vector<SavedAddress>;
|
|||
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SavedAddress, address, name, favourite, chainId);
|
||||
|
||||
}
|
||||
} // namespace Status::StatusGo::Wallet
|
||||
|
|
|
@ -14,7 +14,8 @@ namespace Accounts = Status::StatusGo::Accounts;
|
|||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Status::StatusGo::Wallet {
|
||||
namespace Status::StatusGo::Wallet
|
||||
{
|
||||
|
||||
/// \note equivalent of status-go's Token@token.go
|
||||
/// \see \c getDerivedAddressesForPath
|
||||
|
@ -31,7 +32,6 @@ struct Token
|
|||
using TokenPtr = std::shared_ptr<Token>;
|
||||
using Tokens = std::vector<Token>;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Token, address, name,symbol,
|
||||
color, decimals, chainId);
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Token, address, name, symbol, color, decimals, chainId);
|
||||
|
||||
}
|
||||
} // namespace Status::StatusGo::Wallet
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "WalletApi.h"
|
||||
|
||||
#include "Utils.h"
|
||||
#include "Metadata/api_response.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#include "Accounts/accounts_types.h"
|
||||
|
||||
|
@ -18,14 +18,14 @@ using json = nlohmann::json;
|
|||
namespace Status::StatusGo::Wallet
|
||||
{
|
||||
|
||||
DerivedAddresses getDerivedAddressesForPath(const HashedPassword &password, const Accounts::EOAddress &derivedFrom, const Accounts::DerivationPath &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 = {password, derivedFrom, path, pageSize, pageNumber};
|
||||
json inputJson = {
|
||||
{"jsonrpc", "2.0"},
|
||||
{"method", "wallet_getDerivedAddressesForPath"},
|
||||
{"params", params}
|
||||
};
|
||||
json inputJson = {{"jsonrpc", "2.0"}, {"method", "wallet_getDerivedAddressesForPath"}, {"params", params}};
|
||||
|
||||
auto result = Utils::statusGoCallPrivateRPC(inputJson.dump().c_str());
|
||||
const auto resultJson = json::parse(result);
|
||||
|
@ -36,10 +36,7 @@ DerivedAddresses getDerivedAddressesForPath(const HashedPassword &password, cons
|
|||
|
||||
SavedAddresses getSavedAddresses()
|
||||
{
|
||||
json inputJson = {
|
||||
{"jsonrpc", "2.0"},
|
||||
{"method", "wallet_getSavedAddresses"}
|
||||
};
|
||||
json inputJson = {{"jsonrpc", "2.0"}, {"method", "wallet_getSavedAddresses"}};
|
||||
|
||||
auto result = Utils::statusGoCallPrivateRPC(inputJson.dump().c_str());
|
||||
const auto resultJson = json::parse(result);
|
||||
|
@ -52,11 +49,7 @@ SavedAddresses getSavedAddresses()
|
|||
void saveAddress(const SavedAddress& address)
|
||||
{
|
||||
std::vector<json> params = {address};
|
||||
json inputJson = {
|
||||
{"jsonrpc", "2.0"},
|
||||
{"method", "wakuext_upsertSavedAddress"},
|
||||
{"params", params}
|
||||
};
|
||||
json inputJson = {{"jsonrpc", "2.0"}, {"method", "wakuext_upsertSavedAddress"}, {"params", params}};
|
||||
|
||||
auto result = Utils::statusGoCallPrivateRPC(inputJson.dump().c_str());
|
||||
auto resultJson = json::parse(result);
|
||||
|
@ -66,11 +59,7 @@ void saveAddress(const SavedAddress &address)
|
|||
NetworkConfigurations getEthereumChains(bool onlyEnabled)
|
||||
{
|
||||
std::vector<json> params = {onlyEnabled};
|
||||
json inputJson = {
|
||||
{"jsonrpc", "2.0"},
|
||||
{"method", "wallet_getEthereumChains"},
|
||||
{"params", params}
|
||||
};
|
||||
json inputJson = {{"jsonrpc", "2.0"}, {"method", "wallet_getEthereumChains"}, {"params", params}};
|
||||
|
||||
auto result = Utils::statusGoCallPrivateRPC(inputJson.dump().c_str());
|
||||
const auto resultJson = json::parse(result);
|
||||
|
@ -83,11 +72,7 @@ NetworkConfigurations getEthereumChains(bool onlyEnabled)
|
|||
Tokens getTokens(const ChainID& chainId)
|
||||
{
|
||||
std::vector<json> params = {chainId};
|
||||
json inputJson = {
|
||||
{"jsonrpc", "2.0"},
|
||||
{"method", "wallet_getTokens"},
|
||||
{"params", params}
|
||||
};
|
||||
json inputJson = {{"jsonrpc", "2.0"}, {"method", "wallet_getTokens"}, {"params", params}};
|
||||
|
||||
auto result = Utils::statusGoCallPrivateRPC(inputJson.dump().c_str());
|
||||
const auto resultJson = json::parse(result);
|
||||
|
@ -102,11 +87,7 @@ TokenBalances getTokensBalancesForChainIDs(const std::vector<ChainID> &chainIds,
|
|||
const std::vector<Accounts::EOAddress> tokens)
|
||||
{
|
||||
std::vector<json> params = {chainIds, accounts, tokens};
|
||||
json inputJson = {
|
||||
{"jsonrpc", "2.0"},
|
||||
{"method", "wallet_getTokensBalancesForChainIDs"},
|
||||
{"params", params}
|
||||
};
|
||||
json inputJson = {{"jsonrpc", "2.0"}, {"method", "wallet_getTokensBalancesForChainIDs"}, {"params", params}};
|
||||
|
||||
auto result = Utils::statusGoCallPrivateRPC(inputJson.dump().c_str());
|
||||
const auto resultJson = json::parse(result);
|
||||
|
@ -117,7 +98,8 @@ TokenBalances getTokensBalancesForChainIDs(const std::vector<ChainID> &chainIds,
|
|||
// Workaround to exception "type must be array, but is object" for custom key-types
|
||||
// TODO: find out why
|
||||
std::map<std::string, std::map<std::string, BigInt>> dataMap = data.is_null() ? nlohmann::json() : data;
|
||||
for(const auto &keyIt : dataMap) {
|
||||
for(const auto& keyIt : dataMap)
|
||||
{
|
||||
std::map<Accounts::EOAddress, BigInt> val;
|
||||
for(const auto& valIt : keyIt.second)
|
||||
val.emplace(QString::fromStdString(valIt.first), valIt.second);
|
||||
|
@ -126,4 +108,4 @@ TokenBalances getTokensBalancesForChainIDs(const std::vector<ChainID> &chainIds,
|
|||
return resultData;
|
||||
}
|
||||
|
||||
} // namespaces
|
||||
} // namespace Status::StatusGo::Wallet
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
#include "DerivedAddress.h"
|
||||
#include "NetworkConfiguration.h"
|
||||
#include "Token.h"
|
||||
#include "SavedAddress.h"
|
||||
#include "Token.h"
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
|
@ -23,7 +23,8 @@ namespace Status::StatusGo::Wallet
|
|||
DerivedAddresses getDerivedAddressesForPath(const HashedPassword& password,
|
||||
const Accounts::EOAddress& derivedFrom,
|
||||
const Accounts::DerivationPath& path,
|
||||
int pageSize, int pageNumber);
|
||||
int pageSize,
|
||||
int pageNumber);
|
||||
|
||||
/// \brief Retrieve a list of saved wallet addresses
|
||||
/// \see \c getSavedAddresses
|
||||
|
@ -46,7 +47,6 @@ NetworkConfigurations getEthereumChains(bool onlyEnabled);
|
|||
/// \throws \c CallPrivateRpcError for general RPC call failure
|
||||
NetworkConfigurations getEthereumChains(bool onlyEnabled);
|
||||
|
||||
|
||||
/// \note status-go's GetTokens@api.go -> TokenManager.getTokens@token.go
|
||||
/// \throws \c CallPrivateRpcError with
|
||||
Tokens getTokens(const ChainID& chainId);
|
||||
|
@ -57,4 +57,4 @@ using TokenBalances = std::map<Accounts::EOAddress, std::map<Accounts::EOAddress
|
|||
TokenBalances getTokensBalancesForChainIDs(const std::vector<ChainID>& chainIds,
|
||||
const std::vector<Accounts::EOAddress> accounts,
|
||||
const std::vector<Accounts::EOAddress> tokens);
|
||||
} // namespaces
|
||||
} // namespace Status::StatusGo::Wallet
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
|
||||
#include <QString>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
/// Defines phantom types for strong typing
|
||||
namespace Status::StatusGo::Wallet {
|
||||
namespace Status::StatusGo::Wallet
|
||||
{
|
||||
|
||||
using ChainID = Helpers::NamedType<unsigned long long int, struct ChainIDTag>;
|
||||
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
|
||||
using json = nlohmann::json;
|
||||
namespace StatusGo = Status::StatusGo;
|
||||
namespace Status::Testing {
|
||||
namespace Status::Testing
|
||||
{
|
||||
|
||||
TEST(StatusGoQt, TestJsonParsing)
|
||||
{
|
||||
|
@ -19,13 +20,15 @@ TEST(StatusGoQt, TestJsonParsing)
|
|||
ASSERT_EQ(callRawRPCJson.error.message, expectedJsonError.message);
|
||||
|
||||
auto callRawRPCBadJsonKeyStr = R"({"unknown":"2.0","id":42,"error":{"code":-32601,"message":"Method not found"}})";
|
||||
ASSERT_THROW(json::parse(callRawRPCBadJsonKeyStr).get<StatusGo::CallPrivateRpcErrorResponse>(), nlohmann::detail::out_of_range);
|
||||
ASSERT_THROW(json::parse(callRawRPCBadJsonKeyStr).get<StatusGo::CallPrivateRpcErrorResponse>(),
|
||||
nlohmann::detail::out_of_range);
|
||||
auto callRawRPCBadJsonValStr = R"({"jsonrpc":"2.0","id":42,"error":23})";
|
||||
ASSERT_THROW(json::parse(callRawRPCBadJsonValStr).get<StatusGo::CallPrivateRpcErrorResponse>(), nlohmann::detail::type_error);
|
||||
ASSERT_THROW(json::parse(callRawRPCBadJsonValStr).get<StatusGo::CallPrivateRpcErrorResponse>(),
|
||||
nlohmann::detail::type_error);
|
||||
|
||||
auto statusGoWithResultJsonStr = R"({"result":"0x123"})";
|
||||
auto statusGoWithResultJson = json::parse(statusGoWithResultJsonStr).get<StatusGo::ApiResponse>();
|
||||
ASSERT_EQ(statusGoWithResultJson.result, "0x123");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace Status::Testing
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace Status::Testing {
|
||||
namespace Status::Testing
|
||||
{
|
||||
|
||||
fs::path createTestFolder(const std::string& testName)
|
||||
{
|
||||
|
@ -18,8 +19,7 @@ fs::path createTestFolder(const std::string& testName)
|
|||
AutoCleanTempTestDir::AutoCleanTempTestDir(const std::string& testName, bool createDir)
|
||||
: m_testFolder(createTestFolder(testName))
|
||||
{
|
||||
if(createDir)
|
||||
fs::create_directories(m_testFolder);
|
||||
if(createDir) fs::create_directories(m_testFolder);
|
||||
}
|
||||
|
||||
AutoCleanTempTestDir::~AutoCleanTempTestDir()
|
||||
|
@ -33,4 +33,4 @@ const std::filesystem::path& AutoCleanTempTestDir::tempFolder()
|
|||
return m_testFolder;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status::Testing
|
||||
|
|
|
@ -4,9 +4,11 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
namespace Status::Testing {
|
||||
namespace Status::Testing
|
||||
{
|
||||
|
||||
class AutoCleanTempTestDir {
|
||||
class AutoCleanTempTestDir
|
||||
{
|
||||
public:
|
||||
/// Creates a temporary folder to be used in tests. The folder content's will
|
||||
/// be removed when out of scope
|
||||
|
@ -19,4 +21,4 @@ private:
|
|||
const std::filesystem::path m_testFolder;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Status::Testing
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace Status::Testing {
|
||||
namespace Status::Testing
|
||||
{
|
||||
|
||||
std::weak_ptr<QString> MonitorQtOutput::m_qtMessageOutputForSharing;
|
||||
std::mutex MonitorQtOutput::m_mutex;
|
||||
QtMessageHandler MonitorQtOutput::m_previousHandler = nullptr;
|
||||
|
||||
|
||||
MonitorQtOutput::MonitorQtOutput()
|
||||
{
|
||||
// Ensure only one instance registers a handler
|
||||
|
@ -17,13 +17,14 @@ MonitorQtOutput::MonitorQtOutput()
|
|||
std::unique_lock<std::mutex> localLock(m_mutex);
|
||||
auto globalMsgOut = m_qtMessageOutputForSharing.lock();
|
||||
auto prev = qInstallMessageHandler(qtMessageOutput);
|
||||
if(prev != qtMessageOutput)
|
||||
m_previousHandler = prev;
|
||||
if(!globalMsgOut) {
|
||||
if(prev != qtMessageOutput) m_previousHandler = prev;
|
||||
if(!globalMsgOut)
|
||||
{
|
||||
m_thisMessageOutput = std::make_shared<QString>();
|
||||
m_qtMessageOutputForSharing = m_thisMessageOutput;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
m_thisMessageOutput = globalMsgOut;
|
||||
m_start = m_thisMessageOutput->length();
|
||||
}
|
||||
|
@ -32,15 +33,15 @@ MonitorQtOutput::MonitorQtOutput()
|
|||
MonitorQtOutput::~MonitorQtOutput()
|
||||
{
|
||||
std::unique_lock<std::mutex> localLock(m_mutex);
|
||||
if(m_thisMessageOutput.use_count() == 1) {
|
||||
if(m_thisMessageOutput.use_count() == 1)
|
||||
{
|
||||
// Last instance, deregister the handler
|
||||
qInstallMessageHandler(0);
|
||||
m_thisMessageOutput.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MonitorQtOutput::qtMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
|
||||
void MonitorQtOutput::qtMessageOutput(QtMsgType type, const QMessageLogContext& context, const QString& msg)
|
||||
{
|
||||
std::unique_lock<std::mutex> localLock(m_mutex);
|
||||
auto globalMsgOut = m_qtMessageOutputForSharing.lock();
|
||||
|
@ -50,23 +51,20 @@ MonitorQtOutput::qtMessageOutput(QtMsgType type, const QMessageLogContext &conte
|
|||
m_previousHandler(type, context, msg);
|
||||
}
|
||||
|
||||
QString
|
||||
MonitorQtOutput::qtOuput()
|
||||
QString MonitorQtOutput::qtOuput()
|
||||
{
|
||||
std::unique_lock<std::mutex> localLock(m_mutex);
|
||||
assert(m_thisMessageOutput->length() >= m_start);
|
||||
return m_thisMessageOutput->right(m_thisMessageOutput->length() - m_start);
|
||||
}
|
||||
|
||||
void
|
||||
MonitorQtOutput::restartCapturing()
|
||||
void MonitorQtOutput::restartCapturing()
|
||||
{
|
||||
std::unique_lock<std::mutex> localLock(m_mutex);
|
||||
// Ensure the messageHandler is installed. Foun to be reset at test initializaiton
|
||||
auto prev = qInstallMessageHandler(qtMessageOutput);
|
||||
if(prev != qtMessageOutput)
|
||||
m_previousHandler = prev;
|
||||
if(prev != qtMessageOutput) m_previousHandler = prev;
|
||||
m_start = m_thisMessageOutput->length();
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status::Testing
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
namespace Status::Testing {
|
||||
namespace Status::Testing
|
||||
{
|
||||
|
||||
///
|
||||
/// \brief Monitor output for tests and declaratively control message handler availability
|
||||
|
@ -46,4 +47,4 @@ private:
|
|||
int m_start = 0;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Status::Testing
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
|
||||
#include <QtQmlIntegration>
|
||||
|
||||
namespace Status::Wallet {
|
||||
namespace Status::Wallet
|
||||
{
|
||||
|
||||
/// Controlls asset for an account using hardcoded network and token lists
|
||||
///
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
|
||||
namespace WalletGo = Status::StatusGo::Wallet;
|
||||
|
||||
namespace Status::Wallet {
|
||||
namespace Status::Wallet
|
||||
{
|
||||
|
||||
class DerivedWalletAddress : public QObject
|
||||
{
|
||||
|
@ -22,7 +23,10 @@ public:
|
|||
|
||||
QString address() const;
|
||||
|
||||
const WalletGo::DerivedAddress &data() const { return m_derivedAddress; };
|
||||
const WalletGo::DerivedAddress& data() const
|
||||
{
|
||||
return m_derivedAddress;
|
||||
};
|
||||
|
||||
bool alreadyCreated() const;
|
||||
|
||||
|
@ -32,4 +36,4 @@ private:
|
|||
|
||||
using DerivedWalletAddressPtr = std::shared_ptr<DerivedWalletAddress>;
|
||||
|
||||
}
|
||||
} // namespace Status::Wallet
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include "Status/Wallet/WalletAccount.h"
|
||||
#include "Status/Wallet/DerivedWalletAddress.h"
|
||||
#include "Status/Wallet/WalletAccount.h"
|
||||
|
||||
#include <Helpers/QObjectVectorModel.h>
|
||||
|
||||
#include <QtQmlIntegration>
|
||||
|
||||
namespace Status::Wallet {
|
||||
namespace Status::Wallet
|
||||
{
|
||||
|
||||
/// \note the following values are kept in sync \c selectedDerivedAddress, \c derivedAddressIndex and \c derivationPath
|
||||
/// and \c customDerivationPath; \see connascence.io/value
|
||||
|
@ -20,7 +21,8 @@ class NewWalletAccountController: public QObject
|
|||
Q_PROPERTY(QAbstractListModel* mainAccountsModel READ mainAccountsModel CONSTANT)
|
||||
|
||||
Q_PROPERTY(QAbstractItemModel* currentDerivedAddressModel READ currentDerivedAddressModel CONSTANT)
|
||||
Q_PROPERTY(DerivedWalletAddress* selectedDerivedAddress READ selectedDerivedAddress WRITE setSelectedDerivedAddress NOTIFY selectedDerivedAddressChanged)
|
||||
Q_PROPERTY(DerivedWalletAddress* selectedDerivedAddress READ selectedDerivedAddress WRITE setSelectedDerivedAddress
|
||||
NOTIFY selectedDerivedAddressChanged)
|
||||
Q_PROPERTY(int derivedAddressIndex MEMBER m_derivedAddressIndex NOTIFY selectedDerivedAddressChanged)
|
||||
|
||||
Q_PROPERTY(QString derivationPath READ derivationPath WRITE setDerivationPath NOTIFY derivationPathChanged)
|
||||
|
@ -39,14 +41,14 @@ public:
|
|||
void setDerivationPath(const QString& newDerivationPath);
|
||||
|
||||
/// \see \c accountCreatedStatus for async result
|
||||
Q_INVOKABLE void createAccountAsync(const QString &password, const QString &name,
|
||||
const QColor &color, const QString &path,
|
||||
Q_INVOKABLE void createAccountAsync(const QString& password,
|
||||
const QString& name,
|
||||
const QColor& color,
|
||||
const QString& path,
|
||||
const Status::Wallet::WalletAccount* derivedFrom);
|
||||
|
||||
/// \see \c accountCreatedStatus for async result
|
||||
Q_INVOKABLE void addWatchOnlyAccountAsync(const QString &address, const QString &name,
|
||||
const QColor &color);
|
||||
|
||||
Q_INVOKABLE void addWatchOnlyAccountAsync(const QString& address, const QString& name, const QColor& color);
|
||||
|
||||
/// \returns \c false if fails (due to incomplete user input)
|
||||
Q_INVOKABLE bool retrieveAndUpdateDerivedAddresses(const QString& password,
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
#include <QtQmlIntegration>
|
||||
|
||||
namespace Status::Wallet {
|
||||
namespace Status::Wallet
|
||||
{
|
||||
|
||||
class SavedAddress : public QObject
|
||||
{
|
||||
|
@ -16,8 +17,7 @@ class SavedAddress : public QObject
|
|||
Q_PROPERTY(QString name READ name CONSTANT)
|
||||
|
||||
public:
|
||||
SavedAddress(const QString &address = QString(), const QString &name = QString(),
|
||||
QObject *parent = nullptr);
|
||||
SavedAddress(const QString& address = QString(), const QString& name = QString(), QObject* parent = nullptr);
|
||||
|
||||
const QString& address() const;
|
||||
const QString& name() const;
|
||||
|
@ -28,4 +28,4 @@ private:
|
|||
};
|
||||
|
||||
using SavedAddressPtr = std::shared_ptr<SavedAddress>;
|
||||
}
|
||||
} // namespace Status::Wallet
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
|
||||
namespace GoAccounts = Status::StatusGo::Accounts;
|
||||
|
||||
namespace Status::Wallet {
|
||||
namespace Status::Wallet
|
||||
{
|
||||
|
||||
class WalletAccount : public QObject
|
||||
{
|
||||
|
@ -27,7 +28,10 @@ public:
|
|||
|
||||
QColor color() const;
|
||||
|
||||
const GoAccounts::ChatOrWalletAccount &data() const { return m_data; };
|
||||
const GoAccounts::ChatOrWalletAccount& data() const
|
||||
{
|
||||
return m_data;
|
||||
};
|
||||
|
||||
private:
|
||||
const GoAccounts::ChatOrWalletAccount m_data;
|
||||
|
@ -36,4 +40,4 @@ private:
|
|||
using WalletAccountPtr = std::shared_ptr<WalletAccount>;
|
||||
using WalletAccounts = std::vector<WalletAccount>;
|
||||
|
||||
}
|
||||
} // namespace Status::Wallet
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include <StatusGo/Wallet/Token.h>
|
||||
#include <StatusGo/Wallet/BigInt.h>
|
||||
#include <StatusGo/Wallet/Token.h>
|
||||
|
||||
#include <QtQmlIntegration>
|
||||
|
||||
namespace WalletGo = Status::StatusGo::Wallet;
|
||||
|
||||
namespace Status::Wallet {
|
||||
namespace Status::Wallet
|
||||
{
|
||||
|
||||
class WalletAsset : public QObject
|
||||
{
|
||||
|
@ -42,4 +43,4 @@ private:
|
|||
int m_count;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Status::Wallet
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
class QQmlEngine;
|
||||
class QJSEngine;
|
||||
|
||||
namespace Status::Wallet {
|
||||
namespace Status::Wallet
|
||||
{
|
||||
|
||||
class NewWalletAccountController;
|
||||
class AccountAssetsController;
|
||||
|
@ -50,7 +51,8 @@ public:
|
|||
Q_INVOKABLE void setCurrentAccountIndex(int index);
|
||||
|
||||
/// \note caller (QML) takes ownership of the returned instance
|
||||
Q_INVOKABLE Status::Wallet::AccountAssetsController* createAccountAssetsController(Status::Wallet::WalletAccount* account);
|
||||
Q_INVOKABLE Status::Wallet::AccountAssetsController*
|
||||
createAccountAssetsController(Status::Wallet::WalletAccount* account);
|
||||
|
||||
signals:
|
||||
void currentAccountChanged();
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#include "Status/Wallet/AccountAssetsController.h"
|
||||
|
||||
#include <StatusGo/Wallet/WalletApi.h>
|
||||
#include <StatusGo/Wallet/BigInt.h>
|
||||
#include <StatusGo/Metadata/api_response.h>
|
||||
#include <StatusGo/Wallet/BigInt.h>
|
||||
#include <StatusGo/Wallet/WalletApi.h>
|
||||
|
||||
#include <Helpers/helpers.h>
|
||||
|
||||
|
@ -10,7 +10,8 @@
|
|||
|
||||
namespace WalletGo = Status::StatusGo::Wallet;
|
||||
|
||||
namespace Status::Wallet {
|
||||
namespace Status::Wallet
|
||||
{
|
||||
|
||||
AccountAssetsController::AccountAssetsController(WalletAccount* address, QObject* parent)
|
||||
: QObject(parent)
|
||||
|
@ -30,49 +31,61 @@ AccountAssetsController::AccountAssetsController(WalletAccount* address, QObject
|
|||
})
|
||||
.onFailed([this] {
|
||||
emit assetsReadyChanged();
|
||||
qWarning() << "Unexpected failure while executing updateBalances for account" << m_address->data().address.get();
|
||||
qWarning() << "Unexpected failure while executing updateBalances for account"
|
||||
<< m_address->data().address.get();
|
||||
});
|
||||
}
|
||||
|
||||
void AccountAssetsController::updateBalances()
|
||||
{
|
||||
const StatusGo::Accounts::EOAddress& address = m_address->data().address;
|
||||
if(m_assets->size() > 0)
|
||||
m_assets->clear();
|
||||
if(m_assets->size() > 0) m_assets->clear();
|
||||
// TODO: this should be moved to status-go and exposed as "get balances for account and tokens with currency"
|
||||
std::map<Accounts::EOAddress, StatusGo::Wallet::Token> tokens;
|
||||
std::vector<WalletGo::ChainID> chainIds;
|
||||
auto allNets = WalletGo::getEthereumChains(false);
|
||||
for(const auto &net : allNets) {
|
||||
if(net.enabled && !net.isTest) {
|
||||
try {
|
||||
for(const auto& net : allNets)
|
||||
{
|
||||
if(net.enabled && !net.isTest)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto allTokens = WalletGo::getTokens(net.chainId);
|
||||
for(const auto& tokenToMove : allTokens) {
|
||||
if(isTokenEnabled(tokenToMove)) {
|
||||
for(const auto& tokenToMove : allTokens)
|
||||
{
|
||||
if(isTokenEnabled(tokenToMove))
|
||||
{
|
||||
auto address = tokenToMove.address;
|
||||
tokens.emplace(std::move(address), std::move(tokenToMove));
|
||||
}
|
||||
}
|
||||
chainIds.push_back(net.chainId);
|
||||
}
|
||||
catch (const StatusGo::CallPrivateRpcError& e) {
|
||||
catch(const StatusGo::CallPrivateRpcError& e)
|
||||
{
|
||||
// Most probably "no tokens for this network"
|
||||
if(e.errorResponse().error.message.compare("no tokens for this network") != 0)
|
||||
qWarning() << "Failed retrieving tokens for network" << net.chainId.get() << "; error" << e.errorResponse().error.message.c_str();
|
||||
qWarning() << "Failed retrieving tokens for network" << net.chainId.get() << "; error"
|
||||
<< e.errorResponse().error.message.c_str();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto accountBalances = WalletGo::getTokensBalancesForChainIDs(chainIds, { address }, std::move(Helpers::getKeys(tokens)));
|
||||
if(accountBalances.size() == 1) {
|
||||
for(const auto& accountAndBalance : accountBalances.begin()->second) {
|
||||
auto asset = Helpers::makeSharedQObject<WalletAsset>(std::make_shared<WalletGo::Token>(tokens.at(accountAndBalance.first)), accountAndBalance.second);
|
||||
auto accountBalances =
|
||||
WalletGo::getTokensBalancesForChainIDs(chainIds, {address}, std::move(Helpers::getKeys(tokens)));
|
||||
if(accountBalances.size() == 1)
|
||||
{
|
||||
for(const auto& accountAndBalance : accountBalances.begin()->second)
|
||||
{
|
||||
auto asset = Helpers::makeSharedQObject<WalletAsset>(
|
||||
std::make_shared<WalletGo::Token>(tokens.at(accountAndBalance.first)), accountAndBalance.second);
|
||||
m_assets->push_back(asset);
|
||||
}
|
||||
}
|
||||
else
|
||||
qWarning() << "Failed fetching balances for account" << address.get() << "; balances count" << accountBalances.size();
|
||||
qWarning() << "Failed fetching balances for account" << address.get() << "; balances count"
|
||||
<< accountBalances.size();
|
||||
}
|
||||
|
||||
bool AccountAssetsController::isTokenEnabled(const StatusGo::Wallet::Token& token) const
|
||||
|
@ -97,4 +110,4 @@ bool AccountAssetsController::assetsReady() const
|
|||
return m_assetsReady;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status::Wallet
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
#include "DerivedWalletAddress.h"
|
||||
|
||||
namespace Status::Wallet {
|
||||
namespace Status::Wallet
|
||||
{
|
||||
|
||||
DerivedWalletAddress::DerivedWalletAddress(WalletGo::DerivedAddress address, QObject* parent)
|
||||
: QObject{parent}
|
||||
, m_derivedAddress{std::move(address)}
|
||||
{
|
||||
}
|
||||
{ }
|
||||
|
||||
QString DerivedWalletAddress::address() const
|
||||
{
|
||||
|
@ -18,4 +18,4 @@ bool DerivedWalletAddress::alreadyCreated() const
|
|||
return m_derivedAddress.alreadyCreated;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status::Wallet
|
||||
|
|
|
@ -2,17 +2,17 @@
|
|||
|
||||
#include <StatusGo/Wallet/WalletApi.h>
|
||||
|
||||
#include <StatusGo/Accounts/AccountsAPI.h>
|
||||
#include <StatusGo/Accounts/Accounts.h>
|
||||
#include <StatusGo/Accounts/AccountsAPI.h>
|
||||
#include <StatusGo/Accounts/accounts_types.h>
|
||||
#include <StatusGo/Metadata/api_response.h>
|
||||
#include <StatusGo/Utils.h>
|
||||
#include <StatusGo/Types.h>
|
||||
#include <StatusGo/Utils.h>
|
||||
|
||||
#include <Onboarding/Common/Constants.h>
|
||||
|
||||
#include <QQmlEngine>
|
||||
#include <QJSEngine>
|
||||
#include <QQmlEngine>
|
||||
|
||||
#include <ranges>
|
||||
|
||||
|
@ -21,15 +21,16 @@ namespace WalletGo = Status::StatusGo::Wallet;
|
|||
namespace UtilsSG = Status::StatusGo::Utils;
|
||||
namespace StatusGo = Status::StatusGo;
|
||||
|
||||
namespace Status::Wallet {
|
||||
namespace Status::Wallet
|
||||
{
|
||||
|
||||
NewWalletAccountController::NewWalletAccountController(std::shared_ptr<Helpers::QObjectVectorModel<WalletAccount>> accounts)
|
||||
NewWalletAccountController::NewWalletAccountController(
|
||||
std::shared_ptr<Helpers::QObjectVectorModel<WalletAccount>> accounts)
|
||||
: m_accounts(accounts)
|
||||
, m_mainAccounts(std::move(filterMainAccounts(*accounts)), "account")
|
||||
, m_derivedAddress("derivedAddress")
|
||||
, m_derivationPath(Status::Constants::General::PathWalletRoot)
|
||||
{
|
||||
}
|
||||
{ }
|
||||
|
||||
QAbstractListModel* NewWalletAccountController::mainAccountsModel()
|
||||
{
|
||||
|
@ -48,8 +49,7 @@ QString NewWalletAccountController::derivationPath() const
|
|||
|
||||
void NewWalletAccountController::setDerivationPath(const QString& newDerivationPath)
|
||||
{
|
||||
if (m_derivationPath.get() == newDerivationPath)
|
||||
return;
|
||||
if(m_derivationPath.get() == newDerivationPath) return;
|
||||
m_derivationPath = GoAccounts::DerivationPath(newDerivationPath);
|
||||
emit derivationPathChanged();
|
||||
|
||||
|
@ -59,36 +59,46 @@ void NewWalletAccountController::setDerivationPath(const QString &newDerivationP
|
|||
if(!m_customDerivationPath && !derivedPath.get()->alreadyCreated())
|
||||
updateSelectedDerivedAddress(index, derivedPath);
|
||||
|
||||
if(m_customDerivationPath != oldCustom)
|
||||
emit customDerivationPathChanged();
|
||||
if(m_customDerivationPath != oldCustom) emit customDerivationPathChanged();
|
||||
}
|
||||
|
||||
void NewWalletAccountController::createAccountAsync(const QString &password, const QString &name,
|
||||
const QColor &color, const QString &path,
|
||||
void NewWalletAccountController::createAccountAsync(const QString& password,
|
||||
const QString& name,
|
||||
const QColor& color,
|
||||
const QString& path,
|
||||
const WalletAccount* derivedFrom)
|
||||
{
|
||||
try {
|
||||
try
|
||||
{
|
||||
GoAccounts::generateAccountWithDerivedPath(StatusGo::HashedPassword(UtilsSG::hashPassword(password)),
|
||||
name, color, "", GoAccounts::DerivationPath(path),
|
||||
name,
|
||||
color,
|
||||
"",
|
||||
GoAccounts::DerivationPath(path),
|
||||
derivedFrom->data().derivedFrom.value());
|
||||
|
||||
addNewlyCreatedAccount(findMissingAccount());
|
||||
}
|
||||
catch(const StatusGo::CallPrivateRpcError& e) {
|
||||
catch(const StatusGo::CallPrivateRpcError& e)
|
||||
{
|
||||
qWarning() << "StatusGoQt.generateAccountWithDerivedPath error: " << e.errorResponse().error.message.c_str();
|
||||
|
||||
emit accountCreatedStatus(false);
|
||||
}
|
||||
}
|
||||
|
||||
void NewWalletAccountController::addWatchOnlyAccountAsync(const QString &address, const QString &name, const QColor &color)
|
||||
void NewWalletAccountController::addWatchOnlyAccountAsync(const QString& address,
|
||||
const QString& name,
|
||||
const QColor& color)
|
||||
{
|
||||
try
|
||||
{
|
||||
try {
|
||||
GoAccounts::addAccountWatch(Accounts::EOAddress(address), name, color, u""_qs);
|
||||
|
||||
addNewlyCreatedAccount(findMissingAccount());
|
||||
}
|
||||
catch(const StatusGo::CallPrivateRpcError& e) {
|
||||
catch(const StatusGo::CallPrivateRpcError& e)
|
||||
{
|
||||
qWarning() << "StatusGoQt.generateAccountWithDerivedPath error: " << e.errorResponse().error.message.c_str();
|
||||
|
||||
emit accountCreatedStatus(false);
|
||||
|
@ -99,24 +109,30 @@ bool NewWalletAccountController::retrieveAndUpdateDerivedAddresses(const QString
|
|||
const WalletAccount* derivedFrom)
|
||||
{
|
||||
assert(derivedFrom->data().derivedFrom.has_value());
|
||||
try {
|
||||
try
|
||||
{
|
||||
int currentPage = 1;
|
||||
int foundIndex = -1;
|
||||
int currentIndex = 0;
|
||||
auto maxPageCount = static_cast<int>(std::ceil(static_cast<double>(m_maxDerivedAddresses)/static_cast<double>(m_derivedAddressesPageSize)));
|
||||
auto maxPageCount = static_cast<int>(
|
||||
std::ceil(static_cast<double>(m_maxDerivedAddresses) / static_cast<double>(m_derivedAddressesPageSize)));
|
||||
std::shared_ptr<DerivedWalletAddress> foundEntry;
|
||||
while(currentPage <= maxPageCount && foundIndex < 0) {
|
||||
while(currentPage <= maxPageCount && foundIndex < 0)
|
||||
{
|
||||
auto all = WalletGo::getDerivedAddressesForPath(StatusGo::HashedPassword(UtilsSG::hashPassword(password)),
|
||||
derivedFrom->data().derivedFrom.value(),
|
||||
Status::Constants::General::PathWalletRoot,
|
||||
m_derivedAddressesPageSize, currentPage);
|
||||
m_derivedAddressesPageSize,
|
||||
currentPage);
|
||||
if((currentIndex + all.size()) > m_derivedAddress.size())
|
||||
m_derivedAddress.resize(currentIndex + all.size());
|
||||
|
||||
for(auto newDerived : all) {
|
||||
for(auto newDerived : all)
|
||||
{
|
||||
auto newEntry = Helpers::makeSharedQObject<DerivedWalletAddress>(std::move(newDerived));
|
||||
m_derivedAddress.set(currentIndex, newEntry);
|
||||
if(foundIndex < 0 && !newEntry->data().alreadyCreated) {
|
||||
if(foundIndex < 0 && !newEntry->data().alreadyCreated)
|
||||
{
|
||||
foundIndex = currentIndex;
|
||||
foundEntry = newEntry;
|
||||
}
|
||||
|
@ -124,11 +140,12 @@ bool NewWalletAccountController::retrieveAndUpdateDerivedAddresses(const QString
|
|||
}
|
||||
currentPage++;
|
||||
}
|
||||
if(foundIndex > 0)
|
||||
updateSelectedDerivedAddress(foundIndex, foundEntry);
|
||||
if(foundIndex > 0) updateSelectedDerivedAddress(foundIndex, foundEntry);
|
||||
|
||||
return true;
|
||||
} catch(const StatusGo::CallPrivateRpcError &e) {
|
||||
}
|
||||
catch(const StatusGo::CallPrivateRpcError& e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -143,8 +160,9 @@ WalletAccountPtr NewWalletAccountController::findMissingAccount()
|
|||
auto accounts = GoAccounts::getAccounts();
|
||||
// TODO: consider using a QObjectSetModel and a proxy sort model on top instead
|
||||
auto it = std::find_if(accounts.begin(), accounts.end(), [this](const auto& a) {
|
||||
return std::none_of(m_accounts->objects().begin(), m_accounts->objects().end(),
|
||||
[&a](const auto &eA) { return a.address == eA->data().address; });
|
||||
return std::none_of(m_accounts->objects().begin(), m_accounts->objects().end(), [&a](const auto& eA) {
|
||||
return a.address == eA->data().address;
|
||||
});
|
||||
});
|
||||
return it != accounts.end() ? Helpers::makeSharedQObject<WalletAccount>(*it) : nullptr;
|
||||
}
|
||||
|
@ -175,29 +193,34 @@ DerivedWalletAddress *NewWalletAccountController::selectedDerivedAddress() const
|
|||
|
||||
void NewWalletAccountController::setSelectedDerivedAddress(DerivedWalletAddress* newSelectedDerivedAddress)
|
||||
{
|
||||
if (m_selectedDerivedAddress.get() == newSelectedDerivedAddress)
|
||||
return;
|
||||
if(m_selectedDerivedAddress.get() == newSelectedDerivedAddress) return;
|
||||
auto& objs = m_derivedAddress.objects();
|
||||
auto foundIt = std::find_if(objs.begin(), objs.end(), [newSelectedDerivedAddress](const auto &a) { return a.get() == newSelectedDerivedAddress; });
|
||||
auto foundIt = std::find_if(objs.begin(), objs.end(), [newSelectedDerivedAddress](const auto& a) {
|
||||
return a.get() == newSelectedDerivedAddress;
|
||||
});
|
||||
updateSelectedDerivedAddress(std::distance(objs.begin(), foundIt), *foundIt);
|
||||
}
|
||||
|
||||
void NewWalletAccountController::updateSelectedDerivedAddress(int index, std::shared_ptr<DerivedWalletAddress> newEntry) {
|
||||
void NewWalletAccountController::updateSelectedDerivedAddress(int index, std::shared_ptr<DerivedWalletAddress> newEntry)
|
||||
{
|
||||
m_derivedAddressIndex = index;
|
||||
m_selectedDerivedAddress = newEntry;
|
||||
emit selectedDerivedAddressChanged();
|
||||
if(m_derivationPath != newEntry->data().path) {
|
||||
if(m_derivationPath != newEntry->data().path)
|
||||
{
|
||||
m_derivationPath = newEntry->data().path;
|
||||
emit derivationPathChanged();
|
||||
}
|
||||
}
|
||||
|
||||
std::tuple<DerivedWalletAddressPtr, int> NewWalletAccountController::searchDerivationPath(const GoAccounts::DerivationPath &derivationPath) {
|
||||
std::tuple<DerivedWalletAddressPtr, int>
|
||||
NewWalletAccountController::searchDerivationPath(const GoAccounts::DerivationPath& derivationPath)
|
||||
{
|
||||
const auto& c = m_derivedAddress.objects();
|
||||
auto foundIt = find_if(c.begin(), c.end(), [&derivationPath](const auto &a) { return a->data().path == derivationPath; });
|
||||
if(foundIt != c.end())
|
||||
return {*foundIt, std::distance(c.begin(), foundIt)};
|
||||
auto foundIt =
|
||||
find_if(c.begin(), c.end(), [&derivationPath](const auto& a) { return a->data().path == derivationPath; });
|
||||
if(foundIt != c.end()) return {*foundIt, std::distance(c.begin(), foundIt)};
|
||||
return {nullptr, -1};
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status::Wallet
|
||||
|
|
|
@ -7,8 +7,7 @@ SavedAddress::SavedAddress(const QString &address, const QString &name, QObject
|
|||
: QObject(parent)
|
||||
, m_address(address)
|
||||
, m_name(name)
|
||||
{
|
||||
}
|
||||
{ }
|
||||
|
||||
const QString& SavedAddress::address() const
|
||||
{
|
||||
|
@ -20,4 +19,4 @@ const QString& SavedAddress::name() const
|
|||
return m_name;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Status::Wallet
|
||||
|
|
|
@ -10,8 +10,7 @@ namespace Status::Wallet
|
|||
SavedAddressesController::SavedAddressesController(QObject* parent)
|
||||
: QObject(parent)
|
||||
, m_savedAddresses(Helpers::makeSharedQObject<SavedAddressesModel>("savedAddress"))
|
||||
{
|
||||
}
|
||||
{ }
|
||||
|
||||
QAbstractListModel* SavedAddressesController::savedAddresses() const
|
||||
{
|
||||
|
@ -28,8 +27,7 @@ void SavedAddressesController::saveAddress(const QString &address, const QString
|
|||
}
|
||||
catch(const StatusGo::CallPrivateRpcError& rpcError)
|
||||
{
|
||||
qWarning() << "StatusGoQt.saveAddress error: " <<
|
||||
rpcError.errorResponse().error.message.c_str();
|
||||
qWarning() << "StatusGoQt.saveAddress error: " << rpcError.errorResponse().error.message.c_str();
|
||||
emit error(SaveAddressError);
|
||||
}
|
||||
|
||||
|
@ -50,8 +48,7 @@ void SavedAddressesController::refresh()
|
|||
}
|
||||
catch(const StatusGo::CallPrivateRpcError& rpcError)
|
||||
{
|
||||
qWarning() << "StatusGoQt.getSavedAddresses error: " <<
|
||||
rpcError.errorResponse().error.message.c_str();
|
||||
qWarning() << "StatusGoQt.getSavedAddresses error: " << rpcError.errorResponse().error.message.c_str();
|
||||
emit error(RetrieveSavedAddressesError);
|
||||
}
|
||||
m_savedAddresses->reset(savedAddresses);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue