Skip to content

Commit

Permalink
Merge pull request #48 from aivve/feature/coins_tab_k1
Browse files Browse the repository at this point in the history
Feature:  Coins tab
  • Loading branch information
aivve authored May 19, 2021
2 parents 8289a32 + 0dd90f5 commit de604dd
Show file tree
Hide file tree
Showing 41 changed files with 6,571 additions and 1,287 deletions.
8 changes: 8 additions & 0 deletions src/Languages.pro
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ gui/SignMessageDialog.cpp \
gui/OptimizationSettings.cpp \
gui/GetBalanceProofDialog.cpp \
gui/ExportRawTxDialog.cpp \
gui/CoinsFrame.cpp \
gui/OutputsModel.cpp \
gui/OutputDetailsDialog.cpp \


HEADERS = CommandLineParser.h \
Expand Down Expand Up @@ -141,6 +144,9 @@ gui/SignMessageDialog.h \
gui/OptimizationSettings.h \
gui/GetBalanceProofDialog.h \
gui/ExportRawTxDialog.h \
gui/CoinsFrame.h \
gui/OutputsModel.h \
gui/OutputDetailsDialog.h \

FORMS = gui/ui/aboutdialog.ui \
Expand Down Expand Up @@ -183,6 +189,8 @@ gui/ui/signmessagedialog.ui \
gui/ui/optimizationsettingsdialog.ui \
gui/ui/getbalanceproofdialog.ui \
gui/ui/exportrawtxdialog.ui \
gui/ui/coinsframe.ui \
gui/ui/outputdetailsdialog.ui \

TRANSLATIONS = languages/uk.ts \
Expand Down
66 changes: 65 additions & 1 deletion src/WalletAdapter.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright (c) 2011-2016 The Cryptonote developers
// Copyright (c) 2015-2016 XDN developers
// Copyright (c) 2016-2019 The Karbowanec developers
// Copyright (c) 2016-2021 The Karbo developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

Expand Down Expand Up @@ -370,6 +370,42 @@ Crypto::SecretKey WalletAdapter::getTxKey(Crypto::Hash& txid) {
return CryptoNote::NULL_SECRET_KEY;
}

std::vector<CryptoNote::TransactionOutputInformation> WalletAdapter::getOutputs() {
Q_CHECK_PTR(m_wallet);
try {
return m_wallet->getOutputs();
} catch (std::system_error&) {
}
return {};
}

std::vector<CryptoNote::TransactionOutputInformation> WalletAdapter::getLockedOutputs() {
Q_CHECK_PTR(m_wallet);
try {
return m_wallet->getLockedOutputs();
} catch (std::system_error&) {
}
return {};
}

std::vector<CryptoNote::TransactionOutputInformation> WalletAdapter::getUnlockedOutputs() {
Q_CHECK_PTR(m_wallet);
try {
return m_wallet->getLockedOutputs();
} catch (std::system_error&) {
}
return {};
}

std::vector<CryptoNote::TransactionSpentOutputInformation> WalletAdapter::getSpentOutputs() {
Q_CHECK_PTR(m_wallet);
try {
return m_wallet->getSpentOutputs();
} catch (std::system_error&) {
}
return {};
}

void WalletAdapter::sendTransaction(const std::vector<CryptoNote::WalletLegacyTransfer>& _transfers, quint64 _fee, const QString& _payment_id, quint64 _mixin) {
Q_CHECK_PTR(m_wallet);
try {
Expand All @@ -381,6 +417,21 @@ void WalletAdapter::sendTransaction(const std::vector<CryptoNote::WalletLegacyTr
}
}

// Prerequisites: deduce fee from transfers, selected outs amount and tansfers amount + fee should match
void WalletAdapter::sendTransaction(const std::vector<CryptoNote::WalletLegacyTransfer>& _transfers, const std::list<CryptoNote::TransactionOutputInformation>& _selectedOuts, quint64 _fee, const QString& _payment_id, quint64 _mixin) {
Q_CHECK_PTR(m_wallet);

// can validate here that transfer amount + fee = selected outs amounts

try {
lock();
Q_EMIT walletStateChangedSignal(tr("Sending transaction"));
m_wallet->sendTransaction(_transfers, _selectedOuts, _fee, NodeAdapter::instance().convertPaymentId(_payment_id), _mixin, 0);
} catch (std::system_error&) {
unlock();
}
}

QString WalletAdapter::prepareRawTransaction(const std::vector<CryptoNote::WalletLegacyTransfer>& _transfers, quint64 _fee, const QString& _payment_id, quint64 _mixin) {
Q_CHECK_PTR(m_wallet);
try {
Expand All @@ -394,6 +445,19 @@ QString WalletAdapter::prepareRawTransaction(const std::vector<CryptoNote::Walle
return QString();
}

QString WalletAdapter::prepareRawTransaction(const std::vector<CryptoNote::WalletLegacyTransfer>& _transfers, const std::list<CryptoNote::TransactionOutputInformation>& _selectedOuts, quint64 _fee, const QString& _payment_id, quint64 _mixin) {
Q_CHECK_PTR(m_wallet);
try {
lock();
Q_EMIT walletStateChangedSignal(tr("Preparing transaction"));
CryptoNote::TransactionId transactionId;
return QString::fromStdString(m_wallet->prepareRawTransaction(transactionId, _transfers, _selectedOuts, _fee, NodeAdapter::instance().convertPaymentId(_payment_id), _mixin, 0));
} catch (std::system_error&) {
unlock();
}
return QString();
}

quint64 WalletAdapter::estimateFusion(quint64 _threshold) {
Q_CHECK_PTR(m_wallet);
try {
Expand Down
9 changes: 8 additions & 1 deletion src/WalletAdapter.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright (c) 2011-2016 The Cryptonote developers
// Copyright (c) 2015-2016 XDN developers
// Copyright (c) 2016-2019 The Karbowanec developers
// Copyright (c) 2016-2021 The Karbo developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

Expand Down Expand Up @@ -55,9 +55,16 @@ class WalletAdapter : public QObject, public CryptoNote::IWalletLegacyObserver {
Crypto::SecretKey getTxKey(Crypto::Hash& txid);
size_t getUnlockedOutputsCount();

std::vector<CryptoNote::TransactionOutputInformation> getOutputs();
std::vector<CryptoNote::TransactionOutputInformation> getLockedOutputs();
std::vector<CryptoNote::TransactionOutputInformation> getUnlockedOutputs();
std::vector<CryptoNote::TransactionSpentOutputInformation> getSpentOutputs();

void sendTransaction(const std::vector<CryptoNote::WalletLegacyTransfer>& _transfers, quint64 _fee, const QString& _payment_id, quint64 _mixin);
void sendTransaction(const std::vector<CryptoNote::WalletLegacyTransfer>& _transfers, const std::list<CryptoNote::TransactionOutputInformation>& _selectedOuts, quint64 _fee, const QString& _payment_id, quint64 _mixin);

QString prepareRawTransaction(const std::vector<CryptoNote::WalletLegacyTransfer>& _transfers, quint64 _fee, const QString& _payment_id, quint64 _mixin);
QString prepareRawTransaction(const std::vector<CryptoNote::WalletLegacyTransfer>& _transfers, const std::list<CryptoNote::TransactionOutputInformation>& _selectedOuts, quint64 _fee, const QString& _payment_id, quint64 _mixin);

quint64 estimateFusion(quint64 _threshold);
std::list<CryptoNote::TransactionOutputInformation> getFusionTransfersToSend(quint64 _threshold, size_t _min_input_count, size_t _max_input_count);
Expand Down
197 changes: 197 additions & 0 deletions src/gui/CoinsFrame.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
// Copyright (c) 2011-2016 The Cryptonote developers
// Copyright (c) 2015-2016 XDN developers
// Copyright (c) 2016-2021 Karbo developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <QApplication>
#include <QClipboard>
#include <QDateTime>

#include "Common/FormatTools.h"
#include "CoinsFrame.h"
#include "MainWindow.h"
#include "OutputDetailsDialog.h"
#include "OutputsModel.h"
#include "SortedOutputsModel.h"
#include "VisibleOutputsModel.h"
#include "CurrencyAdapter.h"
#include "NodeAdapter.h"
#include "WalletAdapter.h"
#include "WalletEvents.h"
#include "IWalletLegacy.h"

#include "ui_coinsframe.h"

namespace WalletGui {

CoinsFrame::CoinsFrame(QWidget* _parent) : QFrame(_parent), m_ui(new Ui::CoinsFrame),
m_visibleOutputsModel(new VisibleOutputsModel)
{
m_ui->setupUi(this);
m_visibleOutputsModel->setDynamicSortFilter(true);
m_ui->m_outputsView->setModel(m_visibleOutputsModel.data());
m_ui->m_outputsView->header()->setSectionResizeMode(QHeaderView::Interactive);
m_ui->m_outputsView->header()->setSectionResizeMode(0, QHeaderView::Fixed);
m_ui->m_outputsView->header()->resizeSection(0, 30);
m_ui->m_outputsView->header()->resizeSection(1, 40);
m_ui->m_outputsView->header()->resizeSection(2, 200);
m_ui->m_outputsView->header()->resizeSection(3, 200);
m_ui->m_outputsView->header()->resizeSection(6, 50);
m_ui->m_outputsView->header()->resizeSection(7, 50);

connect(m_ui->m_outputsView->selectionModel(), &QItemSelectionModel::currentChanged, this, &CoinsFrame::currentOutputChanged);
connect(m_ui->m_outputsView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &CoinsFrame::computeSelected);

m_ui->m_outputsView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_ui->m_outputsView, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onCustomContextMenu(const QPoint &)));
connect(&WalletAdapter::instance(), &WalletAdapter::walletCloseCompletedSignal, this, &CoinsFrame::resetTotalAmountLabel);

resetTotalAmountLabel();

contextMenu = new QMenu();
contextMenu->addAction(QString(tr("Copy transaction &hash")), this, SLOT(copyHash()));
contextMenu->addAction(QString(tr("Copy &key")), this, SLOT(copyKey()));
contextMenu->addAction(QString(tr("Copy &global index")), this, SLOT(copyGindex()));
contextMenu->addAction(QString(tr("Show &details")), this, SLOT(showDetails()));

m_ui->m_typeSelect->addItem(tr("All types"), AllTypes);
m_ui->m_typeSelect->addItem(tr("Spent"), Spent);
m_ui->m_typeSelect->addItem(tr("Unspent"), Unspent);

connect(m_ui->m_typeSelect, SIGNAL(activated(int)), this, SLOT(chooseType(int)));
connect(m_ui->m_searchFor, SIGNAL(textChanged(QString)), this, SLOT(changedSearchFor(QString)));

// set sorting to include all types of transactions
SortedOutputsModel::instance().setState(-1);
}

CoinsFrame::~CoinsFrame() {
}

void CoinsFrame::currentOutputChanged(const QModelIndex& _currentIndex) {

}

void CoinsFrame::outputDoubleClicked(const QModelIndex& _index) {
if (!_index.isValid()) {
return;
}

OutputDetailsDialog dlg(_index, &MainWindow::instance());
if (dlg.exec() == QDialog::Accepted) {
// do nothing
}
}

void CoinsFrame::onCustomContextMenu(const QPoint &point)
{
m_index = m_ui->m_outputsView->indexAt(point);
contextMenu->exec(m_ui->m_outputsView->mapToGlobal(point));
}

void CoinsFrame::showDetails()
{
outputDoubleClicked(m_index);
}

void CoinsFrame::copyHash()
{
QApplication::clipboard()->setText(m_index.sibling(m_index.row(), 3).data().toString());
}

void CoinsFrame::copyKey()
{
QApplication::clipboard()->setText(m_index.sibling(m_index.row(), 2).data().toString());
}

void CoinsFrame::copyGindex()
{
QApplication::clipboard()->setText(m_index.sibling(m_index.row(), 5).data().toString());
}

void CoinsFrame::chooseType(int idx)
{
if(!m_visibleOutputsModel)
return;

switch(m_ui->m_typeSelect->itemData(idx).toInt())
{
case AllTypes:
SortedOutputsModel::instance().setState(-1);
break;
case Spent:
SortedOutputsModel::instance().setState(0);
break;
case Unspent:
SortedOutputsModel::instance().setState(1);
break;
}
}

void CoinsFrame::changedSearchFor(const QString &searchstring)
{
if(!m_visibleOutputsModel)
return;
SortedOutputsModel::instance().setSearchFor(searchstring);
}

void CoinsFrame::resetFilterClicked() {
m_ui->m_searchFor->clear();
m_ui->m_typeSelect->setCurrentIndex(0);
SortedOutputsModel::instance().setState(-1);
m_ui->m_outputsView->clearSelection();

}

void CoinsFrame::resetTotalAmountLabel() {
QString amountText = QString::number(0, 'f', 12) + " " + CurrencyAdapter::instance().getCurrencyTicker().toUpper();
m_ui->m_selectedAmount->setText(amountText);
}

void CoinsFrame::computeSelected() {
double amount = 0;
if(!m_ui->m_outputsView->selectionModel())
return;

QModelIndexList selection = m_ui->m_outputsView->selectionModel()->selectedRows();

foreach (QModelIndex index, selection) {
QString amountstring = index.sibling(index.row(), OutputsModel::COLUMN_AMOUNT).data().toString().remove(',');
amount += amountstring.toDouble();
}
QString amountText = QString::number(amount, 'f', 12) + " " + CurrencyAdapter::instance().getCurrencyTicker().toUpper();
m_ui->m_selectedAmount->show();
m_ui->m_selectedAmount->setText(amountText);
}

void CoinsFrame::sendClicked() {
if(!m_ui->m_outputsView->selectionModel())
return;

QModelIndexList selection = m_ui->m_outputsView->selectionModel()->selectedRows();
QList<CryptoNote::TransactionOutputInformation> selectedOutputs;

foreach (QModelIndex index, selection) {
CryptoNote::TransactionOutputInformation o;
o.amount = index.data(OutputsModel::ROLE_AMOUNT).value<quint64>();
o.type = static_cast<CryptoNote::TransactionTypes::OutputType>(index.data(OutputsModel::ROLE_TYPE).value<quint8>());
o.globalOutputIndex = index.data(OutputsModel::ROLE_GLOBAL_OUTPUT_INDEX).value<quint32>();
o.outputInTransaction = index.data(OutputsModel::ROLE_OUTPUT_IN_TRANSACTION).value<quint32>();
o.transactionHash = *reinterpret_cast<const Crypto::Hash*>(index.data(OutputsModel::ROLE_TX_HASH).value<QByteArray>().data());
o.transactionPublicKey = *reinterpret_cast<const Crypto::PublicKey*>(index.data(OutputsModel::ROLE_TX_PUBLIC_KEY).value<QByteArray>().data());

if (o.type == CryptoNote::TransactionTypes::OutputType::Key)
o.outputKey = *reinterpret_cast<const Crypto::PublicKey*>(index.data(OutputsModel::ROLE_OUTPUT_KEY).value<QByteArray>().data());
else if (o.type == CryptoNote::TransactionTypes::OutputType::Multisignature)
o.requiredSignatures = index.data(OutputsModel::ROLE_REQ_SIG).value<quint32>();

if (index.data(OutputsModel::ROLE_STATE).value<quint8>() != static_cast<quint8>(OutputsModel::OutputState::SPENT)) {
selectedOutputs.push_back(o);
}
}

Q_EMIT sendOutputsSignal(selectedOutputs);
}

}
Loading

0 comments on commit de604dd

Please sign in to comment.