From 8c312960cbc8103a7dac416801145b6fb3726b4b Mon Sep 17 00:00:00 2001 From: MishkaRogachev Date: Wed, 7 Sep 2022 15:33:37 +0400 Subject: [PATCH] feat(CPP): Backend for saved addresses section --- libs/Helpers/src/Helpers/QObjectVectorModel.h | 12 +++-- libs/StatusGoQt/CMakeLists.txt | 1 + .../src/StatusGo/Wallet/SavedAddress.h | 31 +++++++++++++ .../src/StatusGo/Wallet/WalletApi.cpp | 29 ++++++++++++ .../src/StatusGo/Wallet/WalletApi.h | 16 ++++++- .../include/Status/Wallet/SavedAddress.h | 4 ++ .../Status/Wallet/SavedAddressesController.h | 6 +-- .../SavedAddresses/AddSavedAddressesView.qml | 22 +++++++-- .../SavedAddresses/SavedAddressesView.qml | 22 ++++++++- libs/Wallet/src/SavedAddressesController.cpp | 45 +++++++++++++++---- 10 files changed, 166 insertions(+), 22 deletions(-) create mode 100644 libs/StatusGoQt/src/StatusGo/Wallet/SavedAddress.h diff --git a/libs/Helpers/src/Helpers/QObjectVectorModel.h b/libs/Helpers/src/Helpers/QObjectVectorModel.h index 72dbc5f5a6..af281a20cf 100644 --- a/libs/Helpers/src/Helpers/QObjectVectorModel.h +++ b/libs/Helpers/src/Helpers/QObjectVectorModel.h @@ -57,13 +57,17 @@ public: return m_objects.size(); }; - void clear() { + void reset(const ObjectContainer& objects) { beginResetModel(); - m_objects.clear(); + m_objects = objects; endResetModel(); }; - void push_back(const std::shared_ptr newValue) { + void clear() { + reset({}); + }; + + void push_back(const std::shared_ptr& newValue) { beginInsertRows(QModelIndex(), m_objects.size(), m_objects.size()); m_objects.push_back(newValue); endInsertRows(); @@ -82,7 +86,7 @@ public: } }; - void set(size_t row, const std::shared_ptr newVal) { + void set(size_t row, const std::shared_ptr& newVal) { m_objects.at(row) = newVal; emit dataChanged(index(row), index(row), {}); }; diff --git a/libs/StatusGoQt/CMakeLists.txt b/libs/StatusGoQt/CMakeLists.txt index 6ac567314a..fd82f0e572 100644 --- a/libs/StatusGoQt/CMakeLists.txt +++ b/libs/StatusGoQt/CMakeLists.txt @@ -125,6 +125,7 @@ target_sources(${PROJECT_NAME} src/StatusGo/Wallet/DerivedAddress.h src/StatusGo/Wallet/NetworkConfiguration.h src/StatusGo/Wallet/Token.h + src/StatusGo/Wallet/SavedAddress.h src/StatusGo/Wallet/wallet_types.h src/StatusGo/Wallet/WalletApi.h src/StatusGo/Wallet/WalletApi.cpp diff --git a/libs/StatusGoQt/src/StatusGo/Wallet/SavedAddress.h b/libs/StatusGoQt/src/StatusGo/Wallet/SavedAddress.h new file mode 100644 index 0000000000..cd7d6667ad --- /dev/null +++ b/libs/StatusGoQt/src/StatusGo/Wallet/SavedAddress.h @@ -0,0 +1,31 @@ +#pragma once + +#include "wallet_types.h" +#include "Accounts/accounts_types.h" + +#include + +#include + +#include + +namespace Accounts = Status::StatusGo::Accounts; + +using json = nlohmann::json; + +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 +/// \see \c getSavedAddresses +struct SavedAddress +{ + Accounts::EOAddress address; + QString name; +}; + +using SavedAddresses = std::vector; + +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SavedAddress, address, name); + +} diff --git a/libs/StatusGoQt/src/StatusGo/Wallet/WalletApi.cpp b/libs/StatusGoQt/src/StatusGo/Wallet/WalletApi.cpp index 356adcade9..35f18fb72b 100644 --- a/libs/StatusGoQt/src/StatusGo/Wallet/WalletApi.cpp +++ b/libs/StatusGoQt/src/StatusGo/Wallet/WalletApi.cpp @@ -34,6 +34,35 @@ DerivedAddresses getDerivedAddressesForPath(const HashedPassword &password, cons return resultJson.get().result; } +SavedAddresses getSavedAddresses() +{ + json inputJson = { + {"jsonrpc", "2.0"}, + {"method", "wallet_getSavedAddresses"} + }; + + auto result = Utils::statusGoCallPrivateRPC(inputJson.dump().c_str()); + const auto resultJson = json::parse(result); + checkPrivateRpcCallResultAndReportError(resultJson); + + const auto &data = resultJson.get().result; + return data.is_null() ? nlohmann::json() : data; +} + +void saveAddress(const Accounts::EOAddress &address, const QString &name) +{ + std::vector params = { SavedAddress({ address, name }) }; + json inputJson = { + {"jsonrpc", "2.0"}, + {"method", "wallet_addSavedAddress"}, + {"params", params} + }; + + auto result = Utils::statusGoCallPrivateRPC(inputJson.dump().c_str()); + auto resultJson = json::parse(result); + checkPrivateRpcCallResultAndReportError(resultJson); +} + NetworkConfigurations getEthereumChains(bool onlyEnabled) { std::vector params = {onlyEnabled}; diff --git a/libs/StatusGoQt/src/StatusGo/Wallet/WalletApi.h b/libs/StatusGoQt/src/StatusGo/Wallet/WalletApi.h index afab60ba8e..1cc1ad6ded 100644 --- a/libs/StatusGoQt/src/StatusGo/Wallet/WalletApi.h +++ b/libs/StatusGoQt/src/StatusGo/Wallet/WalletApi.h @@ -7,6 +7,7 @@ #include "DerivedAddress.h" #include "NetworkConfiguration.h" #include "Token.h" +#include "SavedAddress.h" #include "Types.h" @@ -19,7 +20,20 @@ namespace Status::StatusGo::Wallet /// \brief Retrieve a list of derived account addresses /// \see \c generateAccountWithDerivedPath /// \throws \c CallPrivateRpcError -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); + +/// \brief Retrieve a list of saved wallet addresses +/// \see \c getSavedAddresses +/// \throws \c CallPrivateRpcError +SavedAddresses getSavedAddresses(); + +/// \brief Add a new or update existing saved wallet address +/// \see \c addSavedAddress +/// \throws \c CallPrivateRpcError +void saveAddress(const Accounts::EOAddress& address, const QString& name); /// \note status-go's GetEthereumChains@api.go which calls /// NetworkManager@client.go -> network.Manager.get() diff --git a/libs/Wallet/include/Status/Wallet/SavedAddress.h b/libs/Wallet/include/Status/Wallet/SavedAddress.h index 3c4d8d9504..cb2d81fd83 100644 --- a/libs/Wallet/include/Status/Wallet/SavedAddress.h +++ b/libs/Wallet/include/Status/Wallet/SavedAddress.h @@ -1,5 +1,7 @@ #pragma once +#include + #include namespace Status::Wallet @@ -23,4 +25,6 @@ private: const QString m_address; const QString m_name; }; + +using SavedAddressPtr = std::shared_ptr; } diff --git a/libs/Wallet/include/Status/Wallet/SavedAddressesController.h b/libs/Wallet/include/Status/Wallet/SavedAddressesController.h index 408c4c3d7e..0e899d212e 100644 --- a/libs/Wallet/include/Status/Wallet/SavedAddressesController.h +++ b/libs/Wallet/include/Status/Wallet/SavedAddressesController.h @@ -21,8 +21,8 @@ public: enum Error { NoneError, - UnknownAddressError, - AddressAlreadyPresentError + SaveAddressError, + RetrieveSavedAddressesError }; Q_ENUM(Error) @@ -31,7 +31,7 @@ public: QAbstractListModel* savedAddresses() const; Q_INVOKABLE void saveAddress(const QString& address, const QString& name); - // Q_INVOKABLE void removeAddress(const QString& address); + Q_INVOKABLE void refresh(); signals: void error(Status::Wallet::SavedAddressesController::Error error); diff --git a/libs/Wallet/qml/Status/Wallet/SavedAddresses/AddSavedAddressesView.qml b/libs/Wallet/qml/Status/Wallet/SavedAddresses/AddSavedAddressesView.qml index 4f4971629a..9840552870 100644 --- a/libs/Wallet/qml/Status/Wallet/SavedAddresses/AddSavedAddressesView.qml +++ b/libs/Wallet/qml/Status/Wallet/SavedAddresses/AddSavedAddressesView.qml @@ -10,18 +10,30 @@ Popup { required property SavedAddressesController savedAddressesController + width: 300 + GridLayout { anchors.fill: parent columns: 2 - Label { text: qsTr("Address") ; Layout.fillWidth: true } - TextField { - id: addressFiled + Label { + text: qsTr("Address") + Layout.fillWidth: true + } + + TextField { + id: addressFiled + Layout.fillWidth: true + } + + Label { + text: qsTr("Name") + Layout.fillWidth: true } - Label { text: qsTr("Name") ; Layout.fillWidth: true } TextField { id: nameFiled + Layout.fillWidth: true } Button { @@ -29,6 +41,8 @@ Popup { enabled: addressFiled.text.length && nameFiled.text.length onClicked: { savedAddressesController.saveAddress(addressFiled.text, nameFiled.text); + addressFiled.clear(); + nameFiled.clear(); root.close(); } GridLayout.columnSpan: 2 diff --git a/libs/Wallet/qml/Status/Wallet/SavedAddresses/SavedAddressesView.qml b/libs/Wallet/qml/Status/Wallet/SavedAddresses/SavedAddressesView.qml index 27829c3d2c..ae85b0d470 100644 --- a/libs/Wallet/qml/Status/Wallet/SavedAddresses/SavedAddressesView.qml +++ b/libs/Wallet/qml/Status/Wallet/SavedAddresses/SavedAddressesView.qml @@ -10,10 +10,29 @@ Item { required property SavedAddressesController savedAddressesController + Component.onCompleted: savedAddressesController.refresh() + ListView { id: list anchors.fill: parent - model: SavedAddressesController.savedAddresses + model: savedAddressesController.savedAddresses + + header: RowLayout { + width: list.width + spacing: 0 + + Label { + text: qsTr("Address") + font.bold: true + Layout.fillWidth: true + } + + Label { + text: qsTr("Name") + font.bold: true + Layout.fillWidth: true + } + } delegate: RowLayout { width: list.width @@ -39,6 +58,7 @@ Item { AddSavedAddressesView { id: addView + x: (parent.width - width) / 2 y: parent.height - height savedAddressesController: root.savedAddressesController } diff --git a/libs/Wallet/src/SavedAddressesController.cpp b/libs/Wallet/src/SavedAddressesController.cpp index c09806bfe1..25a04a62a9 100644 --- a/libs/Wallet/src/SavedAddressesController.cpp +++ b/libs/Wallet/src/SavedAddressesController.cpp @@ -1,13 +1,15 @@ #include "Status/Wallet/SavedAddressesController.h" #include "Helpers/helpers.h" +#include "Metadata/api_response.h" + +#include namespace Status::Wallet { SavedAddressesController::SavedAddressesController(QObject* parent) : QObject(parent) - , m_savedAddresses(Helpers::makeSharedQObject( - /* TODO: std::move(getWalletAccounts()), */"savedAddress")) + , m_savedAddresses(Helpers::makeSharedQObject("savedAddress")) { } @@ -18,14 +20,39 @@ QAbstractListModel* SavedAddressesController::savedAddresses() const void SavedAddressesController::saveAddress(const QString &address, const QString &name) { -// TODO: check present addresses -// { -// emit error(AddressAlreadyPresentError); -// return; -// } + try + { + StatusGo::Wallet::saveAddress(StatusGo::Accounts::EOAddress(address), name); + } + catch(const StatusGo::CallPrivateRpcError& rpcError) + { + qWarning() << "StatusGoQt.saveAddress error: " << + rpcError.errorResponse().error.message.c_str(); + emit error(SaveAddressError); + } - auto item = Helpers::makeSharedQObject(address, name); - m_savedAddresses->push_back(item); + // TODO: signal from wallet data_source + this->refresh(); +} + +void SavedAddressesController::refresh() +{ + std::vector savedAddresses; + + try + { + for (const StatusGo::Wallet::SavedAddress& address: StatusGo::Wallet::getSavedAddresses()) + { + savedAddresses.push_back(std::make_shared(address.address.get(), address.name)); + } + } + catch(const StatusGo::CallPrivateRpcError& rpcError) + { + qWarning() << "StatusGoQt.getSavedAddresses error: " << + rpcError.errorResponse().error.message.c_str(); + emit error(RetrieveSavedAddressesError); + } + m_savedAddresses->reset(savedAddresses); } } // namespace Status::Wallet