Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/interfaces/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,10 @@ class WalletImpl : public Wallet
{
return m_wallet.GetAvailableBalance(&coin_control)[ColorIdentifier()];
}
CAmount getAvailableBalance(const CCoinControl& coin_control, const ColorIdentifier& colorId) override
{
return m_wallet.GetAvailableBalance(&coin_control)[colorId];
}
TokenIssuanceResult issueNewReissuableToken(CAmount value) override
{
TokenIssuanceResult result;
Expand Down
1 change: 1 addition & 0 deletions src/interfaces/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ class Wallet

//! Get available balance.
virtual CAmount getAvailableBalance(const CCoinControl& coin_control) = 0;
virtual CAmount getAvailableBalance(const CCoinControl& coin_control, const ColorIdentifier& colorId) = 0;

//! Issue a new REISSUABLE token; generates address and script internally.
virtual TokenIssuanceResult issueNewReissuableToken(CAmount value) = 0;
Expand Down
75 changes: 75 additions & 0 deletions src/qt/forms/receivecoinsdialog.ui
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,81 @@
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelToken">
<property name="text">
<string>What?</string>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this "What?" mean?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this is receive coins page I meant it as a question "receive what?" Other labels like "Coin type"/ "Asset type" that are long do not align well with the other text inputs in the GUI. We could use just "Colour"/"Type". I was not sure is this is clear enough. Which Lebel would you prefer?

</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>reqToken</cstring>
</property>
</widget>
</item>
<item row="3" column="2">
<layout class="QHBoxLayout" name="tokenSelectionLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QRadioButton" name="radioTPC">
<property name="text">
<string>TPC</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioToken">
<property name="text">
<string>Token</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="reqToken">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Select a token to generate a colored receiving address for</string>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<spacer name="tokenSelectionSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_2">
<property name="toolTip">
Expand Down
60 changes: 54 additions & 6 deletions src/qt/forms/sendcoinsentry.ui
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,55 @@
</property>
</widget>
</item>
<item row="2" column="0">
<item row="2" column="0" colspan="2">
<widget class="QWidget" name="tokenRowSpacer">
<property name="visible">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>8</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>8</height>
</size>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelToken">
<property name="text">
<string>&amp;Token:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>labelTokenName</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="labelTokenName">
<property name="text">
<string>&amp;</string>
</property>
<property name="alignment">
<set>Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>labelToken</cstring>
</property>
<property name="toolTip">
<string>Token type of the address</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="amountLabel">
<property name="text">
<string>A&amp;mount:</string>
Expand All @@ -162,7 +210,7 @@
</property>
</widget>
</item>
<item row="2" column="1">
<item row="4" column="1">
<layout class="QHBoxLayout" name="horizontalLayoutAmount" stretch="0,1,0">
<item>
<widget class="BitcoinAmountField" name="payAmount"/>
Expand All @@ -173,7 +221,7 @@
<string>The fee will be deducted from the amount being sent. The recipient will receive less tpc than you enter in the amount field. If multiple recipients are selected, the fee is split equally.</string>
</property>
<property name="text">
<string>S&amp;ubtract fee from amount</string>
<string>Subtract fee from amount</string>
</property>
</widget>
</item>
Expand All @@ -186,7 +234,7 @@
</item>
</layout>
</item>
<item row="3" column="0">
<item row="5" column="0">
<widget class="QLabel" name="messageLabel">
<property name="text">
<string>Message:</string>
Expand All @@ -196,7 +244,7 @@
</property>
</widget>
</item>
<item row="3" column="1">
<item row="5" column="1">
<widget class="QLabel" name="messageTextLabel">
<property name="toolTip">
<string>A message that was attached to the tapyrus coin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Tapyrus network.</string>
Expand All @@ -206,7 +254,7 @@
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<item row="6" column="0" colspan="2">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
Expand Down
121 changes: 116 additions & 5 deletions src/qt/receivecoinsdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
#include <qt/recentrequeststablemodel.h>
#include <qt/walletmodel.h>

#include <coloridentifier.h>
#include <key_io.h>
#include <utilstrencodings.h>

#include <QAction>
#include <QCursor>
#include <QMessageBox>
Expand Down Expand Up @@ -66,6 +70,41 @@ ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *_platformStyle, QWid
connect(ui->clearButton, &QPushButton::clicked, this, &ReceiveCoinsDialog::clear);
}

void ReceiveCoinsDialog::refreshTokenCombo()
{
if (!model) return;

ui->reqToken->blockSignals(true);
int prevIndex = ui->reqToken->currentIndex();
QString prevColorId;
if (prevIndex >= 0 && prevIndex < m_tokenRecords.size())
prevColorId = m_tokenRecords[prevIndex].colorId;

ui->reqToken->clear();

static const QMap<QString, QString> typeIcons = {
{"REISSUABLE", ":/icons/token_reissuable"},
{"NON_REISSUABLE", ":/icons/token_nonreissuable"},
{"NFT", ":/icons/token_nft"},
};

m_tokenRecords = model->getIssuedTokens();
for (const WalletModel::IssuedTokenRecord& rec : m_tokenRecords) {
QIcon icon(typeIcons.value(rec.tokenType));
ui->reqToken->addItem(icon, rec.colorId, rec.colorId);
}

ui->reqToken->blockSignals(false);

// Restore previous selection if possible
int restoreIndex = 0;
if (!prevColorId.isEmpty()) {
int found = ui->reqToken->findData(prevColorId);
if (found >= 0) restoreIndex = found;
}
ui->reqToken->setCurrentIndex(restoreIndex);
}

void ReceiveCoinsDialog::setModel(WalletModel *_model)
{
this->model = _model;
Expand All @@ -74,6 +113,11 @@ void ReceiveCoinsDialog::setModel(WalletModel *_model)
{
_model->getRecentRequestsTableModel()->sort(RecentRequestsTableModel::Date, Qt::DescendingOrder);
connect(_model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &ReceiveCoinsDialog::updateDisplayUnit);
connect(_model, &WalletModel::tokenAddressBookChanged, this, &ReceiveCoinsDialog::refreshTokenCombo);
connect(ui->radioToken, &QRadioButton::toggled, this, &ReceiveCoinsDialog::on_radioToken_toggled);
connect(ui->reqToken, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &ReceiveCoinsDialog::on_reqToken_currentIndexChanged);
refreshTokenCombo();
updateDisplayUnit();

QTableView* tableView = ui->recentRequestsView;
Expand All @@ -86,6 +130,7 @@ void ReceiveCoinsDialog::setModel(WalletModel *_model)
tableView->setSelectionMode(QAbstractItemView::ContiguousSelection);
tableView->setColumnWidth(RecentRequestsTableModel::Date, DATE_COLUMN_WIDTH);
tableView->setColumnWidth(RecentRequestsTableModel::Label, LABEL_COLUMN_WIDTH);
tableView->setColumnWidth(RecentRequestsTableModel::Token, TOKEN_COLUMN_WIDTH);
tableView->setColumnWidth(RecentRequestsTableModel::Amount, AMOUNT_MINIMUM_COLUMN_WIDTH);

connect(tableView->selectionModel(),
Expand All @@ -107,9 +152,17 @@ ReceiveCoinsDialog::~ReceiveCoinsDialog()

void ReceiveCoinsDialog::clear()
{
ui->radioTPC->setChecked(true);
ui->reqToken->setCurrentIndex(0);
ui->reqToken->setEnabled(false);
ui->reqAmount->setTokenMode(false);
ui->reqAmount->setEnabled(true);
ui->reqAmount->clear();
ui->reqLabel->setText("");
ui->reqMessage->setText("");
if (model)
ui->receiveButton->setEnabled(!model->privateKeysDisabled());
ui->receiveButton->setToolTip(QString());
updateDisplayUnit();
}

Expand All @@ -123,12 +176,47 @@ void ReceiveCoinsDialog::accept()
clear();
}

void ReceiveCoinsDialog::on_radioToken_toggled(bool checked)
{
ui->reqToken->setEnabled(checked);
ui->reqAmount->setTokenMode(checked);
if (!checked) {
ui->reqToken->setCurrentIndex(0);
ui->reqAmount->setEnabled(true);
ui->receiveButton->setEnabled(!model->privateKeysDisabled());
ui->receiveButton->setToolTip(QString());
} else {
on_reqToken_currentIndexChanged(ui->reqToken->currentIndex());
}
}

void ReceiveCoinsDialog::on_reqToken_currentIndexChanged(int index)
{
if (!ui->radioToken->isChecked() || index < 0 || index >= m_tokenRecords.size())
return;

const WalletModel::IssuedTokenRecord& rec = m_tokenRecords[index];
if (rec.tokenType == "NFT") {
// NFT: fixed amount of 1, no more requests if already holding 1
ui->reqAmount->setValue(1);
ui->reqAmount->setEnabled(false);
bool alreadyOwned = (rec.balance + rec.unconfirmedBalance) >= 1;
bool canRequest = !alreadyOwned && !model->privateKeysDisabled();
ui->receiveButton->setEnabled(canRequest);
ui->receiveButton->setToolTip(alreadyOwned
? tr("This NFT token is already in your wallet. Only one can exist in the network.")
: QString());
} else {
ui->reqAmount->setEnabled(true);
ui->receiveButton->setEnabled(!model->privateKeysDisabled());
ui->receiveButton->setToolTip(QString());
}
}

void ReceiveCoinsDialog::updateDisplayUnit()
{
if(model && model->getOptionsModel())
{
ui->reqAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
}
}

void ReceiveCoinsDialog::on_receiveButton_clicked()
Expand All @@ -138,12 +226,35 @@ void ReceiveCoinsDialog::on_receiveButton_clicked()

QString address;
QString label = ui->reqLabel->text();
/* Generate new receiving address */
OutputType address_type = model->wallet().getDefaultAddressType();
int tokenIndex = ui->reqToken->currentIndex();

if (ui->radioToken->isChecked() && tokenIndex >= 0 && tokenIndex < m_tokenRecords.size()) {
// Generate a colored receiving address
const WalletModel::IssuedTokenRecord& rec = m_tokenRecords[tokenIndex];
const std::vector<unsigned char> vColorId(ParseHex(rec.colorId.toStdString()));
ColorIdentifier colorId(vColorId.data(), vColorId.data() + vColorId.size());

CPubKey newKey;
if (!model->wallet().getKeyFromPool(false /* internal */, newKey)) {
WalletModel::UnlockContext ctx(model->requestUnlock());
if (!ctx.isValid()) return;
if (!model->wallet().getKeyFromPool(false, newKey)) return;
}
CColorKeyID colorKeyId(newKey.GetID(), colorId);
address = QString::fromStdString(EncodeDestination(colorKeyId));
model->wallet().setAddressBook(colorKeyId, label.toStdString(), "receive");
} else {
// Generate a standard TPC receiving address
OutputType address_type = model->wallet().getDefaultAddressType();
address = model->getAddressTableModel()->addRow(AddressTableModel::Receive, label, "", address_type);
}

address = model->getAddressTableModel()->addRow(AddressTableModel::Receive, label, "", address_type);
SendCoinsRecipient info(address, label,
ui->reqAmount->value(), ui->reqMessage->text());
if (ui->radioToken->isChecked() && tokenIndex >= 0 && tokenIndex < m_tokenRecords.size()) {
const std::vector<unsigned char> vColorId(ParseHex(m_tokenRecords[tokenIndex].colorId.toStdString()));
info.colorid = ColorIdentifier(vColorId.data(), vColorId.data() + vColorId.size());
}
ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setModel(model);
Expand Down
Loading
Loading