mirror of
https://github.com/status-im/status-desktop.git
synced 2025-01-28 07:15:21 +00:00
7cf0170a8a
Integrate token count in UI Use delete later for QML exposed items to avoid errors Closes #6321
204 lines
7.7 KiB
C++
204 lines
7.7 KiB
C++
#include "Status/Wallet/NewWalletAccountController.h"
|
|
|
|
#include <StatusGo/Wallet/WalletApi.h>
|
|
|
|
#include <StatusGo/Accounts/AccountsAPI.h>
|
|
#include <StatusGo/Accounts/Accounts.h>
|
|
#include <StatusGo/Accounts/accounts_types.h>
|
|
#include <StatusGo/Metadata/api_response.h>
|
|
#include <StatusGo/Utils.h>
|
|
#include <StatusGo/Types.h>
|
|
|
|
#include <Onboarding/Common/Constants.h>
|
|
|
|
#include <QQmlEngine>
|
|
#include <QJSEngine>
|
|
|
|
#include <ranges>
|
|
|
|
namespace GoAccounts = Status::StatusGo::Accounts;
|
|
namespace WalletGo = Status::StatusGo::Wallet;
|
|
namespace UtilsSG = Status::StatusGo::Utils;
|
|
namespace StatusGo = Status::StatusGo;
|
|
|
|
namespace Status::Wallet {
|
|
|
|
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()
|
|
{
|
|
return &m_mainAccounts;
|
|
}
|
|
|
|
QAbstractItemModel *NewWalletAccountController::currentDerivedAddressModel()
|
|
{
|
|
return &m_derivedAddress;
|
|
}
|
|
|
|
QString NewWalletAccountController::derivationPath() const
|
|
{
|
|
return m_derivationPath.get();
|
|
}
|
|
|
|
void NewWalletAccountController::setDerivationPath(const QString &newDerivationPath)
|
|
{
|
|
if (m_derivationPath.get() == newDerivationPath)
|
|
return;
|
|
m_derivationPath = GoAccounts::DerivationPath(newDerivationPath);
|
|
emit derivationPathChanged();
|
|
|
|
auto oldCustom = m_customDerivationPath;
|
|
const auto &[derivedPath, index]= searchDerivationPath(m_derivationPath);
|
|
m_customDerivationPath = derivedPath == nullptr;
|
|
if(!m_customDerivationPath && !derivedPath.get()->alreadyCreated())
|
|
updateSelectedDerivedAddress(index, derivedPath);
|
|
|
|
if(m_customDerivationPath != oldCustom)
|
|
emit customDerivationPathChanged();
|
|
}
|
|
|
|
void NewWalletAccountController::createAccountAsync(const QString &password, const QString &name,
|
|
const QColor &color, const QString &path,
|
|
const WalletAccount *derivedFrom)
|
|
{
|
|
try {
|
|
GoAccounts::generateAccountWithDerivedPath(StatusGo::HashedPassword(UtilsSG::hashPassword(password)),
|
|
name, color, "", GoAccounts::DerivationPath(path),
|
|
derivedFrom->data().derivedFrom.value());
|
|
|
|
addNewlyCreatedAccount(findMissingAccount());
|
|
}
|
|
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)
|
|
{
|
|
try {
|
|
GoAccounts::addAccountWatch(Accounts::EOAddress(address), name, color, u""_qs);
|
|
|
|
addNewlyCreatedAccount(findMissingAccount());
|
|
}
|
|
catch(const StatusGo::CallPrivateRpcError& e) {
|
|
qWarning() << "StatusGoQt.generateAccountWithDerivedPath error: " << e.errorResponse().error.message.c_str();
|
|
|
|
emit accountCreatedStatus(false);
|
|
}
|
|
}
|
|
|
|
bool NewWalletAccountController::retrieveAndUpdateDerivedAddresses(const QString &password,
|
|
const WalletAccount *derivedFrom)
|
|
{
|
|
assert(derivedFrom->data().derivedFrom.has_value());
|
|
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)));
|
|
std::shared_ptr<DerivedWalletAddress> foundEntry;
|
|
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);
|
|
if((currentIndex + all.size()) > m_derivedAddress.size())
|
|
m_derivedAddress.resize(currentIndex + all.size());
|
|
|
|
for(auto newDerived : all) {
|
|
auto newEntry = Helpers::makeSharedQObject<DerivedWalletAddress>(std::move(newDerived));
|
|
m_derivedAddress.set(currentIndex, newEntry);
|
|
if(foundIndex < 0 && !newEntry->data().alreadyCreated) {
|
|
foundIndex = currentIndex;
|
|
foundEntry = newEntry;
|
|
}
|
|
currentIndex++;
|
|
}
|
|
currentPage++;
|
|
}
|
|
if(foundIndex > 0)
|
|
updateSelectedDerivedAddress(foundIndex, foundEntry);
|
|
|
|
return true;
|
|
} catch(const StatusGo::CallPrivateRpcError &e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void NewWalletAccountController::clearDerivedAddresses()
|
|
{
|
|
m_derivedAddress.clear();
|
|
}
|
|
|
|
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 it != accounts.end() ? Helpers::makeSharedQObject<WalletAccount>(*it) : nullptr;
|
|
}
|
|
|
|
NewWalletAccountController::AccountsModel::ObjectContainer
|
|
NewWalletAccountController::filterMainAccounts(const AccountsModel &accounts)
|
|
{
|
|
AccountsModel::ObjectContainer out;
|
|
const auto &c = accounts.objects();
|
|
std::copy_if(c.begin(), c.end(), std::back_inserter(out), [](const auto &a){ return a->data().isWallet; });
|
|
return out;
|
|
}
|
|
|
|
void NewWalletAccountController::addNewlyCreatedAccount(WalletAccountPtr newAccount)
|
|
{
|
|
if(newAccount)
|
|
m_accounts->push_back(newAccount);
|
|
else
|
|
qWarning() << "No new account to add. Creation failed";
|
|
|
|
emit accountCreatedStatus(newAccount != nullptr);
|
|
}
|
|
|
|
DerivedWalletAddress *NewWalletAccountController::selectedDerivedAddress() const
|
|
{
|
|
return m_selectedDerivedAddress.get();
|
|
}
|
|
|
|
void NewWalletAccountController::setSelectedDerivedAddress(DerivedWalletAddress *newSelectedDerivedAddress)
|
|
{
|
|
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; });
|
|
updateSelectedDerivedAddress(std::distance(objs.begin(), foundIt), *foundIt);
|
|
}
|
|
|
|
void NewWalletAccountController::updateSelectedDerivedAddress(int index, std::shared_ptr<DerivedWalletAddress> newEntry) {
|
|
m_derivedAddressIndex = index;
|
|
m_selectedDerivedAddress = newEntry;
|
|
emit selectedDerivedAddressChanged();
|
|
if(m_derivationPath != newEntry->data().path) {
|
|
m_derivationPath = newEntry->data().path;
|
|
emit derivationPathChanged();
|
|
}
|
|
}
|
|
|
|
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)};
|
|
return {nullptr, -1};
|
|
}
|
|
|
|
}
|