diff --git a/src/qt/forms/sendcoinsentry.ui b/src/qt/forms/sendcoinsentry.ui
index 965657edb9..11a74f1155 100644
--- a/src/qt/forms/sendcoinsentry.ui
+++ b/src/qt/forms/sendcoinsentry.ui
@@ -238,6 +238,48 @@
+ -
+
+
+ 0
+
+
-
+
+
+
+
+
+
+
+
+ 5
+
+
+ 5
+
+
+ 10
+
+
+ 10
+
+
+ margin-left:-30px;margin-right:-10px;margin-top:2px;
+
+
+
+ -
+
+
+
+
+
+ color: #FFA800; margin-left:-10px;
+
+
+
+
+
-
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index e9706fd9fc..fd3d658217 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -533,11 +533,16 @@ void SendCoinsDialog::on_sendButton_clicked()
QString questionString = tr("Are you sure you want to send?");
questionString.append(warningMessage);
questionString.append("
%1");
- questionString.append("\n\nMessage: ");
- for (auto rec : recipients)
- {
- questionString.append(rec.message);
- questionString.append(".\t");
+ bool firstMessage = true;
+ for (const auto& rec : recipients) {
+ if (!rec.message.isEmpty()) {
+ if (firstMessage) {
+ questionString.append("
" + tr("Messages") + ":
");
+ firstMessage = false;
+ }
+ QString sanitizedMsg = GUIUtil::HtmlEscape(rec.message, true);
+ questionString.append("• " + sanitizedMsg + "
");
+ }
}
double txSize;
diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp
index c762262041..4697423868 100644
--- a/src/qt/sendcoinsentry.cpp
+++ b/src/qt/sendcoinsentry.cpp
@@ -29,6 +29,7 @@ SendCoinsEntry::SendCoinsEntry(const PlatformStyle *_platformStyle, QWidget *par
QIcon icon_;
icon_.addFile(QString::fromUtf8(":/icons/ic_warning"), QSize(), QIcon::Normal, QIcon::On);
ui->iconWarning->setPixmap(icon_.pixmap(18, 18));
+ ui->iconMessageWarning->setPixmap(icon_.pixmap(18, 18));
ui->addressBookButton->setIcon(platformStyle->SingleColorIcon(":/icons/address-book"));
ui->pasteButton->setIcon(platformStyle->SingleColorIcon(":/icons/editpaste"));
@@ -55,9 +56,11 @@ SendCoinsEntry::SendCoinsEntry(const PlatformStyle *_platformStyle, QWidget *par
connect(ui->deleteButton, &QToolButton::clicked, this, &SendCoinsEntry::deleteClicked);
connect(ui->deleteButton_is, &QToolButton::clicked, this, &SendCoinsEntry::deleteClicked);
connect(ui->deleteButton_s, &QToolButton::clicked, this, &SendCoinsEntry::deleteClicked);
+ connect(ui->messageTextLabel, &QLineEdit::textChanged, this, &SendCoinsEntry::on_MemoTextChanged);
ui->messageLabel->setVisible(false);
ui->messageTextLabel->setVisible(false);
+ ui->iconMessageWarning->setVisible(false);
}
SendCoinsEntry::~SendCoinsEntry()
@@ -65,6 +68,24 @@ SendCoinsEntry::~SendCoinsEntry()
delete ui;
}
+void SendCoinsEntry::on_MemoTextChanged(const QString &text)
+{
+ int maxLength = 256;
+ bool isOverLimit = text.length() > maxLength;
+
+ if (isOverLimit) {
+ ui->messageWarning->setText("Message exceeds character 256 character limit");
+ ui->messageWarning->setVisible(true);
+ ui->messageTextLabel->setStyleSheet("border: 1px solid red;");
+ ui->iconMessageWarning->setVisible(true);
+ } else {
+ ui->messageWarning->clear();
+ ui->messageWarning->setVisible(false);
+ ui->messageTextLabel->setStyleSheet("");
+ ui->iconMessageWarning->setVisible(false);
+ }
+}
+
void SendCoinsEntry::on_pasteButton_clicked()
{
// Paste text from clipboard into recipient field
@@ -89,7 +110,10 @@ void SendCoinsEntry::on_payTo_textChanged(const QString &address)
updateLabel(address);
setWarning(fAnonymousMode);
- bool isSparkAddress = model && model->validateSparkAddress(address);
+ bool isSparkAddress = false;
+ if (model) {
+ isSparkAddress = model->validateSparkAddress(address);
+ }
ui->messageLabel->setVisible(isSparkAddress);
ui->messageTextLabel->setVisible(isSparkAddress);
}
diff --git a/src/qt/sendcoinsentry.h b/src/qt/sendcoinsentry.h
index 2e89f0fd5e..4611bd0027 100644
--- a/src/qt/sendcoinsentry.h
+++ b/src/qt/sendcoinsentry.h
@@ -63,6 +63,7 @@ public Q_SLOTS:
private Q_SLOTS:
void deleteClicked();
void on_payTo_textChanged(const QString &address);
+ void on_MemoTextChanged(const QString &text);
void on_addressBookButton_clicked();
void on_pasteButton_clicked();
void updateDisplayUnit();
diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp
index 85d04babc4..deaabaf85f 100644
--- a/src/qt/transactiondesc.cpp
+++ b/src/qt/transactiondesc.cpp
@@ -311,12 +311,42 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
strHTML += "" + tr("Transaction total size") + ": " + QString::number(wtx.tx->GetTotalSize()) + " bytes
";
strHTML += "" + tr("Output index") + ": " + QString::number(rec->getOutputIndex()) + "
";
- uint256 selectedTxID = rec->hash;
- std::unordered_map coins = wallet->sparkWallet->getMintMap();
+ isminetype fAllFromMe = ISMINE_SPENDABLE;
+ bool foundSparkOutput = false;
- for (const auto& [id, meta] : coins) {
- if (meta.txid == selectedTxID && !meta.memo.empty()) {
- strHTML += "" + tr("Message") + ": " + GUIUtil::HtmlEscape(meta.memo, true) + "
\n";
+ for (const CTxIn& txin : wtx.tx->vin) {
+ isminetype mine = wallet->IsMine(txin, *wtx.tx);
+ fAllFromMe = std::min(fAllFromMe, mine);
+ }
+
+ bool firstMessage = true;
+ if (fAllFromMe) {
+ for (const CTxOut& txout : wtx.tx->vout) {
+ if (wtx.IsChange(txout)) continue;
+
+ CSparkOutputTx sparkOutput;
+ if (wallet->GetSparkOutputTx(txout.scriptPubKey, sparkOutput)) {
+ if (!sparkOutput.memo.empty()) {
+ foundSparkOutput = true;
+ if (firstMessage) {
+ strHTML += "
" + tr("Messages") + ":
";
+ firstMessage = false;
+ }
+ strHTML += "• " + GUIUtil::HtmlEscape(sparkOutput.memo, true) + "
";
+ }
+ }
+ }
+ }
+
+ if (!foundSparkOutput && wallet->sparkWallet) {
+ for (const auto& [id, meta] : wallet->sparkWallet->getMintMap()) {
+ if (meta.txid == rec->hash && !meta.memo.empty()) {
+ if (firstMessage) {
+ strHTML += "
" + tr("Messages") + ":
";
+ firstMessage = false;
+ }
+ strHTML += "• " + GUIUtil::HtmlEscape(meta.memo, true) + "
";
+ }
}
}
diff --git a/src/spark/primitives.h b/src/spark/primitives.h
index 7929e73b80..09de4550eb 100644
--- a/src/spark/primitives.h
+++ b/src/spark/primitives.h
@@ -87,6 +87,7 @@ class CSparkOutputTx
{
public:
std::string address;
+ std::string memo;
int64_t amount;
CSparkOutputTx()
@@ -97,6 +98,7 @@ class CSparkOutputTx
void SetNull()
{
address = "";
+ memo = "";
amount = 0;
}
@@ -105,6 +107,7 @@ class CSparkOutputTx
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(address);
READWRITE(amount);
+ READWRITE(memo);
}
};
diff --git a/src/spark/sparkwallet.cpp b/src/spark/sparkwallet.cpp
index 382cb6c62d..d99a3f4810 100644
--- a/src/spark/sparkwallet.cpp
+++ b/src/spark/sparkwallet.cpp
@@ -742,7 +742,8 @@ std::vector CSparkWallet::CreateSparkMintRecipients(
script.insert(script.end(), serializedCoins[i].begin(), serializedCoins[i].end());
unsigned char network = spark::GetNetworkType();
std::string addr = outputs[i].address.encode(network);
- CRecipient recipient = {script, CAmount(outputs[i].v), false, addr};
+ std::string memo = outputs[i].memo;
+ CRecipient recipient = {script, CAmount(outputs[i].v), false, addr, memo};
results.emplace_back(recipient);
}
@@ -1093,6 +1094,7 @@ bool CSparkWallet::CreateSparkMintTransactions(
CSparkOutputTx output;
output.address = recipient.address;
output.amount = recipient.nAmount;
+ output.memo = recipient.memo;
walletdb.WriteSparkOutputTx(recipient.scriptPubKey, output);
break;
}
@@ -1530,6 +1532,7 @@ CWalletTx CSparkWallet::CreateSparkSpendTransaction(
CSparkOutputTx output;
output.address = privOutputs[i].address.encode(network);
output.amount = privOutputs[i].v;
+ output.memo = privOutputs[i].memo;
walletdb.WriteSparkOutputTx(script, output);
tx.vout.push_back(CTxOut(0, script));
i++;
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index f9397f5150..f1f1d0c6a9 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -190,6 +190,7 @@ struct CRecipient
CAmount nAmount;
bool fSubtractFeeFromAmount;
std::string address;
+ std::string memo;
};
typedef std::map mapValue_t;