From 0640751c474ccaec7feb0608972fb63e8e4631e9 Mon Sep 17 00:00:00 2001 From: johnny9 <985648+johnny9@users.noreply.github.com> Date: Sun, 1 Jun 2025 01:06:56 -0400 Subject: [PATCH 1/9] qml: Add alert icon --- src/Makefile.qt.include | 1 + src/qml/bitcoin_qml.qrc | 1 + src/qml/res/icons/alert-filled.png | Bin 0 -> 531 bytes src/qml/res/src/alert-filled.svg | 3 +++ 4 files changed, 5 insertions(+) create mode 100644 src/qml/res/icons/alert-filled.png create mode 100644 src/qml/res/src/alert-filled.svg diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index f3cbb813cf..7a29f7b3e2 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -357,6 +357,7 @@ QML_RES_FONTS = \ QML_RES_ICONS = \ qml/res/icons/add-wallet-dark.png \ + qml/res/icons/alert-filled.png \ qml/res/icons/arrow-down.png \ qml/res/icons/arrow-up.png \ qml/res/icons/bitcoin-circle.png \ diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index edeede29e3..52cff573e2 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -101,6 +101,7 @@ res/icons/add-wallet-dark.png + res/icons/alert-filled.png res/icons/arrow-down.png res/icons/arrow-up.png res/icons/bitcoin-circle.png diff --git a/src/qml/res/icons/alert-filled.png b/src/qml/res/icons/alert-filled.png new file mode 100644 index 0000000000000000000000000000000000000000..a097bea42c3ef90d31cb4eac664331c5cc7e7778 GIT binary patch literal 531 zcmV+u0_^>XP)pRXg5Gi08EfFLAyc92Hl|8G^kM&A$*pmB$wrOmRp4r+gC`e_~;$P@6 zu8ph=U0e VJ+u^Tw50$5002ovPDHLkV1gYO;+Fsb literal 0 HcmV?d00001 diff --git a/src/qml/res/src/alert-filled.svg b/src/qml/res/src/alert-filled.svg new file mode 100644 index 0000000000..f556ef71ca --- /dev/null +++ b/src/qml/res/src/alert-filled.svg @@ -0,0 +1,3 @@ + + + From 7a0d18691c76e7437d3ae9304af3190045017988 Mon Sep 17 00:00:00 2001 From: johnny9 <985648+johnny9@users.noreply.github.com> Date: Sun, 1 Jun 2025 01:13:02 -0400 Subject: [PATCH 2/9] qml: Add validation to Send form address and amount --- src/qml/models/sendrecipient.cpp | 68 +++++++- src/qml/models/sendrecipient.h | 23 ++- src/qml/models/sendrecipientslistmodel.cpp | 8 +- src/qml/models/sendrecipientslistmodel.h | 8 +- src/qml/models/walletqmlmodel.cpp | 8 + src/qml/models/walletqmlmodel.h | 11 +- src/qml/models/walletqmlmodeltransaction.cpp | 3 + src/qml/pages/wallet/Send.qml | 161 ++++++++++++------- test/lint/lint-circular-dependencies.py | 4 + 9 files changed, 223 insertions(+), 71 deletions(-) diff --git a/src/qml/models/sendrecipient.cpp b/src/qml/models/sendrecipient.cpp index ce4943d099..f9b028c59f 100644 --- a/src/qml/models/sendrecipient.cpp +++ b/src/qml/models/sendrecipient.cpp @@ -5,10 +5,14 @@ #include #include +#include -SendRecipient::SendRecipient(QObject* parent) - : QObject(parent), m_amount(new BitcoinAmount(this)) +#include + +SendRecipient::SendRecipient(WalletQmlModel* wallet, QObject* parent) + : QObject(parent), m_wallet(wallet), m_amount(new BitcoinAmount(this)) { + connect(m_amount, &BitcoinAmount::amountChanged, this, &SendRecipient::validateAmount); } QString SendRecipient::address() const @@ -21,6 +25,20 @@ void SendRecipient::setAddress(const QString& address) if (m_address != address) { m_address = address; Q_EMIT addressChanged(); + validateAddress(); + } +} + +QString SendRecipient::addressError() const +{ + return m_addressError; +} + +void SendRecipient::setAddressError(const QString& error) +{ + if (m_addressError != error) { + m_addressError = error; + Q_EMIT addressErrorChanged(); } } @@ -42,6 +60,19 @@ BitcoinAmount* SendRecipient::amount() const return m_amount; } +QString SendRecipient::amountError() const +{ + return m_amountError; +} + +void SendRecipient::setAmountError(const QString& error) +{ + if (m_amountError != error) { + m_amountError = error; + Q_EMIT amountErrorChanged(); + } +} + QString SendRecipient::message() const { return m_message; @@ -77,3 +108,36 @@ void SendRecipient::clear() Q_EMIT messageChanged(); Q_EMIT amount()->amountChanged(); } + +void SendRecipient::validateAddress() +{ + setAddressError(""); + + if (!m_address.isEmpty() && !IsValidDestinationString(m_address.toStdString())) { + setAddressError(tr("Invalid address")); + } + + Q_EMIT isValidChanged(); +} + +void SendRecipient::validateAmount() +{ + setAmountError(""); + + if (m_amount->isSet()) { + if (m_amount->satoshi() <= 0) { + setAmountError(tr("Amount must be greater than zero")); + } else if (m_amount->satoshi() > MAX_MONEY) { + setAmountError(tr("Amount exceeds maximum limit")); + } else if (m_amount->satoshi() > m_wallet->balanceSatoshi()) { + setAmountError(tr("Amount exceeds available balance")); + } + } + + Q_EMIT isValidChanged(); +} + +bool SendRecipient::isValid() const +{ + return m_addressError.isEmpty() && m_amountError.isEmpty() && m_amount->satoshi() > 0 && !m_address.isEmpty(); +} diff --git a/src/qml/models/sendrecipient.h b/src/qml/models/sendrecipient.h index 80af868a1c..965483c854 100644 --- a/src/qml/models/sendrecipient.h +++ b/src/qml/models/sendrecipient.h @@ -10,6 +10,8 @@ #include #include +class WalletQmlModel; + class SendRecipient : public QObject { Q_OBJECT @@ -18,17 +20,25 @@ class SendRecipient : public QObject Q_PROPERTY(QString message READ message WRITE setMessage NOTIFY messageChanged) Q_PROPERTY(BitcoinAmount* amount READ amount CONSTANT) + Q_PROPERTY(QString addressError READ addressError NOTIFY addressErrorChanged) + Q_PROPERTY(QString amountError READ amountError NOTIFY amountErrorChanged) + Q_PROPERTY(bool isValid READ isValid NOTIFY isValidChanged) + public: - explicit SendRecipient(QObject* parent = nullptr); + explicit SendRecipient(WalletQmlModel* wallet, QObject* parent = nullptr); QString address() const; void setAddress(const QString& address); + QString addressError() const; + void setAddressError(const QString& error); QString label() const; void setLabel(const QString& label); BitcoinAmount* amount() const; void setAmount(const QString& amount); + QString amountError() const; + void setAmountError(const QString& error); QString message() const; void setMessage(const QString& message); @@ -37,18 +47,29 @@ class SendRecipient : public QObject bool subtractFeeFromAmount() const; + bool isValid() const; + Q_INVOKABLE void clear(); Q_SIGNALS: void addressChanged(); + void addressErrorChanged(); + void amountErrorChanged(); void labelChanged(); void messageChanged(); + void isValidChanged(); private: + void validateAddress(); + void validateAmount(); + + WalletQmlModel* m_wallet; QString m_address{""}; + QString m_addressError{""}; QString m_label{""}; QString m_message{""}; BitcoinAmount* m_amount; + QString m_amountError{""}; bool m_subtractFeeFromAmount{false}; }; diff --git a/src/qml/models/sendrecipientslistmodel.cpp b/src/qml/models/sendrecipientslistmodel.cpp index c4c4d0a683..eea97bc60e 100644 --- a/src/qml/models/sendrecipientslistmodel.cpp +++ b/src/qml/models/sendrecipientslistmodel.cpp @@ -3,13 +3,15 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include +#include #include SendRecipientsListModel::SendRecipientsListModel(QObject* parent) : QAbstractListModel(parent) { - auto* recipient = new SendRecipient(this); + m_wallet = qobject_cast(parent); + auto* recipient = new SendRecipient(m_wallet, this); connect(recipient->amount(), &BitcoinAmount::amountChanged, this, &SendRecipientsListModel::updateTotalAmount); m_recipients.append(recipient); @@ -50,7 +52,7 @@ void SendRecipientsListModel::add() { const int row = m_recipients.size(); beginInsertRows(QModelIndex(), row, row); - auto* recipient = new SendRecipient(this); + auto* recipient = new SendRecipient(m_wallet, this); connect(recipient->amount(), &BitcoinAmount::amountChanged, this, &SendRecipientsListModel::updateTotalAmount); if (m_recipients.size() > 0) { @@ -137,7 +139,7 @@ void SendRecipientsListModel::clear() m_current = 0; m_totalAmount = 0; - auto* recipient = new SendRecipient(this); + auto* recipient = new SendRecipient(m_wallet, this); connect(recipient->amount(), &BitcoinAmount::amountChanged, this, &SendRecipientsListModel::updateTotalAmount); m_recipients.append(recipient); diff --git a/src/qml/models/sendrecipientslistmodel.h b/src/qml/models/sendrecipientslistmodel.h index 0e9b77d4b7..1919626b51 100644 --- a/src/qml/models/sendrecipientslistmodel.h +++ b/src/qml/models/sendrecipientslistmodel.h @@ -5,11 +5,10 @@ #ifndef BITCOIN_QML_MODELS_SENDRECIPIENTSLISTMODEL_H #define BITCOIN_QML_MODELS_SENDRECIPIENTSLISTMODEL_H -#include - #include -#include -#include + +class SendRecipient; +class WalletQmlModel; class SendRecipientsListModel : public QAbstractListModel { @@ -58,6 +57,7 @@ class SendRecipientsListModel : public QAbstractListModel private: void updateTotalAmount(); + WalletQmlModel* m_wallet; QList m_recipients; int m_current{0}; qint64 m_totalAmount{0}; diff --git a/src/qml/models/walletqmlmodel.cpp b/src/qml/models/walletqmlmodel.cpp index f05b2b38bb..e54d0a0e4d 100644 --- a/src/qml/models/walletqmlmodel.cpp +++ b/src/qml/models/walletqmlmodel.cpp @@ -55,6 +55,14 @@ QString WalletQmlModel::balance() const return BitcoinUnits::format(BitcoinUnits::Unit::BTC, m_wallet->getBalance()); } +CAmount WalletQmlModel::balanceSatoshi() const +{ + if (!m_wallet) { + return 0; + } + return m_wallet->getBalance(); +} + QString WalletQmlModel::name() const { if (!m_wallet) { diff --git a/src/qml/models/walletqmlmodel.h b/src/qml/models/walletqmlmodel.h index 35b86d643a..061464cf11 100644 --- a/src/qml/models/walletqmlmodel.h +++ b/src/qml/models/walletqmlmodel.h @@ -5,20 +5,21 @@ #ifndef BITCOIN_QML_MODELS_WALLETQMLMODEL_H #define BITCOIN_QML_MODELS_WALLETQMLMODEL_H -#include -#include #include #include #include #include #include + +#include +#include +#include #include -#include #include #include -class ActivityListModel; +#include class WalletQmlModel : public QObject { @@ -39,6 +40,8 @@ class WalletQmlModel : public QObject QString name() const; QString balance() const; + CAmount balanceSatoshi() const; + ActivityListModel* activityListModel() const { return m_activity_list_model; } CoinsListModel* coinsListModel() const { return m_coins_list_model; } SendRecipientsListModel* sendRecipientList() const { return m_send_recipients; } diff --git a/src/qml/models/walletqmlmodeltransaction.cpp b/src/qml/models/walletqmlmodeltransaction.cpp index 2303606a0e..11cc34d08c 100644 --- a/src/qml/models/walletqmlmodeltransaction.cpp +++ b/src/qml/models/walletqmlmodeltransaction.cpp @@ -4,6 +4,9 @@ #include +#include +#include + #include WalletQmlModelTransaction::WalletQmlModelTransaction(const SendRecipientsListModel* recipient, QObject* parent) diff --git a/src/qml/pages/wallet/Send.qml b/src/qml/pages/wallet/Send.qml index 65b3b86cdf..3943d550a7 100644 --- a/src/qml/pages/wallet/Send.qml +++ b/src/qml/pages/wallet/Send.qml @@ -127,7 +127,6 @@ PageStack { enabled: wallet.recipients.currentIndex - 1 > 0 onClicked: { wallet.recipients.prev() - } } @@ -170,78 +169,125 @@ PageStack { Layout.fillWidth: true } - LabeledTextInput { - id: address + ColumnLayout { Layout.fillWidth: true - labelText: qsTr("Send to") - placeholderText: qsTr("Enter address...") - text: root.recipient.address - onTextEdited: root.recipient.address = address.text + + LabeledTextInput { + id: address + Layout.fillWidth: true + labelText: qsTr("Send to") + placeholderText: qsTr("Enter address...") + text: root.recipient.address + onTextEdited: root.recipient.address = address.text + } + + RowLayout { + id: addressIssue + Layout.fillWidth: true + visible: root.recipient.addressError.length > 0 + + Icon { + source: "image://images/alert-filled" + size: 22 + color: Theme.color.red + } + + CoreText { + id: warningText + text: root.recipient.addressError + font.pixelSize: 15 + color: Theme.color.red + horizontalAlignment: Text.AlignLeft + Layout.fillWidth: true + } + } } Separator { Layout.fillWidth: true } - Item { - height: amountInput.height + ColumnLayout { Layout.fillWidth: true - CoreText { - id: amountLabel - width: 110 - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - horizontalAlignment: Text.AlignLeft - text: qsTr("Amount") - font.pixelSize: 18 - } - TextField { - id: amountInput - anchors.left: amountLabel.right - anchors.verticalCenter: parent.verticalCenter - leftPadding: 0 - font.family: "Inter" - font.styleName: "Regular" - font.pixelSize: 18 - color: Theme.color.neutral9 - placeholderTextColor: enabled ? Theme.color.neutral7 : Theme.color.neutral4 - background: Item {} - placeholderText: "0.00000000" - selectByMouse: true - text: root.recipient.amount.display - onTextEdited: root.recipient.amount.display = text - onEditingFinished: root.recipient.amount.format() - onActiveFocusChanged: { - if (!activeFocus) { - root.recipient.amount.display = text - } - } - } Item { - width: unitLabel.width + flipIcon.width - height: Math.max(unitLabel.height, flipIcon.height) - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - MouseArea { - anchors.fill: parent - onClicked: root.recipient.amount.flipUnit() - } + height: amountInput.height + Layout.fillWidth: true CoreText { - id: unitLabel - anchors.right: flipIcon.left + id: amountLabel + width: 110 + anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter - text: root.recipient.amount.unitLabel + horizontalAlignment: Text.AlignLeft + text: qsTr("Amount") font.pixelSize: 18 - color: enabled ? Theme.color.neutral7 : Theme.color.neutral4 } - Icon { - id: flipIcon + + TextField { + id: amountInput + anchors.left: amountLabel.right + anchors.verticalCenter: parent.verticalCenter + leftPadding: 0 + font.family: "Inter" + font.styleName: "Regular" + font.pixelSize: 18 + color: Theme.color.neutral9 + placeholderTextColor: enabled ? Theme.color.neutral7 : Theme.color.neutral4 + background: Item {} + placeholderText: "0.00000000" + selectByMouse: true + text: root.recipient.amount.display + onEditingFinished: root.recipient.amount.display = text + onActiveFocusChanged: { + if (!activeFocus) { + root.recipient.amount.display = text + } + } + } + Item { + width: unitLabel.width + flipIcon.width + height: Math.max(unitLabel.height, flipIcon.height) anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter - source: "image://images/flip-vertical" - icon.color: unitLabel.enabled ? Theme.color.neutral8 : Theme.color.neutral4 - size: 30 + MouseArea { + anchors.fill: parent + onClicked: root.recipient.amount.flipUnit() + } + CoreText { + id: unitLabel + anchors.right: flipIcon.left + anchors.verticalCenter: parent.verticalCenter + text: root.recipient.amount.unitLabel + font.pixelSize: 18 + color: enabled ? Theme.color.neutral7 : Theme.color.neutral4 + } + Icon { + id: flipIcon + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + source: "image://images/flip-vertical" + icon.color: unitLabel.enabled ? Theme.color.neutral8 : Theme.color.neutral4 + size: 30 + } + } + } + + RowLayout { + Layout.fillWidth: true + visible: root.recipient.amountError.length > 0 + + Icon { + source: "image://images/alert-filled" + size: 22 + color: Theme.color.red + } + + CoreText { + text: root.recipient.amountError + font.pixelSize: 15 + color: Theme.color.red + horizontalAlignment: Text.AlignLeft + Layout.fillWidth: true } } } @@ -293,6 +339,7 @@ PageStack { Layout.fillWidth: true Layout.topMargin: 30 text: qsTr("Review") + enabled: root.recipient.isValid onClicked: { if (root.wallet.prepareTransaction()) { root.transactionPrepared(settings.multipleRecipientsEnabled); diff --git a/test/lint/lint-circular-dependencies.py b/test/lint/lint-circular-dependencies.py index fa98b6fd69..b2b7540d97 100755 --- a/test/lint/lint-circular-dependencies.py +++ b/test/lint/lint-circular-dependencies.py @@ -17,6 +17,10 @@ "node/utxo_snapshot -> validation -> node/utxo_snapshot", "qml/models/activitylistmodel -> qml/models/walletqmlmodel -> qml/models/activitylistmodel", "qml/models/coinslistmodel -> qml/models/walletqmlmodel -> qml/models/coinslistmodel", + "qml/models/sendrecipient -> qml/models/walletqmlmodel -> qml/models/sendrecipient", + "qml/models/sendrecipient -> qml/models/walletqmlmodel -> qml/models/walletqmlmodeltransaction -> qml/models/sendrecipient", + "qml/models/sendrecipientslistmodel -> qml/models/walletqmlmodel -> qml/models/sendrecipientslistmodel", + "qml/models/sendrecipientslistmodel -> qml/models/walletqmlmodel -> qml/models/walletqmlmodeltransaction -> qml/models/sendrecipientslistmodel", "qt/addresstablemodel -> qt/walletmodel -> qt/addresstablemodel", "qt/recentrequeststablemodel -> qt/walletmodel -> qt/recentrequeststablemodel", "qt/sendcoinsdialog -> qt/walletmodel -> qt/sendcoinsdialog", From aa927c522177841e8d23fa9e23210320b0ca64fa Mon Sep 17 00:00:00 2001 From: johnny9 <985648+johnny9@users.noreply.github.com> Date: Wed, 4 Jun 2025 01:11:06 -0400 Subject: [PATCH 3/9] qml: Split amount and display updating for Bitcoin amount input --- src/qml/pages/wallet/Send.qml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/qml/pages/wallet/Send.qml b/src/qml/pages/wallet/Send.qml index 3943d550a7..2c332f6906 100644 --- a/src/qml/pages/wallet/Send.qml +++ b/src/qml/pages/wallet/Send.qml @@ -237,10 +237,11 @@ PageStack { placeholderText: "0.00000000" selectByMouse: true text: root.recipient.amount.display - onEditingFinished: root.recipient.amount.display = text + onTextEdited: root.recipient.amount.display = text + onEditingFinished: root.recipient.amount.format() onActiveFocusChanged: { if (!activeFocus) { - root.recipient.amount.display = text + root.recipient.amount.format() } } } From e65e7bf0f12785ff137d5634d72bc798b31471db Mon Sep 17 00:00:00 2001 From: johnny9 <985648+johnny9@users.noreply.github.com> Date: Wed, 4 Jun 2025 01:11:57 -0400 Subject: [PATCH 4/9] qml: Add validators to address and amount inputs to limit characters --- src/qml/controls/LabeledTextInput.qml | 1 + src/qml/pages/wallet/Send.qml | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/src/qml/controls/LabeledTextInput.qml b/src/qml/controls/LabeledTextInput.qml index c257ec9a7d..cad703a467 100644 --- a/src/qml/controls/LabeledTextInput.qml +++ b/src/qml/controls/LabeledTextInput.qml @@ -13,6 +13,7 @@ Item { property alias iconSource: icon.source property alias customIcon: iconContainer.data property alias enabled: input.enabled + property alias validator: input.validator signal iconClicked signal textEdited diff --git a/src/qml/pages/wallet/Send.qml b/src/qml/pages/wallet/Send.qml index 2c332f6906..7e0e3568e6 100644 --- a/src/qml/pages/wallet/Send.qml +++ b/src/qml/pages/wallet/Send.qml @@ -179,6 +179,9 @@ PageStack { placeholderText: qsTr("Enter address...") text: root.recipient.address onTextEdited: root.recipient.address = address.text + validator: RegExpValidator { + regExp: /^[1-9A-HJ-NP-Za-km-zac-hj-np-z02-9]+$/ + } } RowLayout { @@ -244,6 +247,10 @@ PageStack { root.recipient.amount.format() } } + validator: RegExpValidator { + regExp: /^(0|[1-9]\d*)(\.\d{0,8})?$/ + } + maximumLength: 17 } Item { width: unitLabel.width + flipIcon.width From 001f4de22430fcdb78ccd1fa15e35652e7077de2 Mon Sep 17 00:00:00 2001 From: johnny9 <985648+johnny9@users.noreply.github.com> Date: Wed, 4 Jun 2025 01:20:54 -0400 Subject: [PATCH 5/9] qml: Add maximum length for address input --- src/qml/controls/LabeledTextInput.qml | 1 + src/qml/pages/wallet/Send.qml | 1 + 2 files changed, 2 insertions(+) diff --git a/src/qml/controls/LabeledTextInput.qml b/src/qml/controls/LabeledTextInput.qml index cad703a467..419c98d422 100644 --- a/src/qml/controls/LabeledTextInput.qml +++ b/src/qml/controls/LabeledTextInput.qml @@ -14,6 +14,7 @@ Item { property alias customIcon: iconContainer.data property alias enabled: input.enabled property alias validator: input.validator + property alias maximumLength: input.maximumLength signal iconClicked signal textEdited diff --git a/src/qml/pages/wallet/Send.qml b/src/qml/pages/wallet/Send.qml index 7e0e3568e6..ab66e67779 100644 --- a/src/qml/pages/wallet/Send.qml +++ b/src/qml/pages/wallet/Send.qml @@ -182,6 +182,7 @@ PageStack { validator: RegExpValidator { regExp: /^[1-9A-HJ-NP-Za-km-zac-hj-np-z02-9]+$/ } + maximumLength: 62 } RowLayout { From 5845f682315bde457682a31df1e6a4127ceda23f Mon Sep 17 00:00:00 2001 From: johnny9 <985648+johnny9@users.noreply.github.com> Date: Wed, 4 Jun 2025 01:24:33 -0400 Subject: [PATCH 6/9] qml: Specify maximum BTC amount in error string --- src/qml/models/sendrecipient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/models/sendrecipient.cpp b/src/qml/models/sendrecipient.cpp index f9b028c59f..0874c85631 100644 --- a/src/qml/models/sendrecipient.cpp +++ b/src/qml/models/sendrecipient.cpp @@ -128,7 +128,7 @@ void SendRecipient::validateAmount() if (m_amount->satoshi() <= 0) { setAmountError(tr("Amount must be greater than zero")); } else if (m_amount->satoshi() > MAX_MONEY) { - setAmountError(tr("Amount exceeds maximum limit")); + setAmountError(tr("Amount exceeds maximum limit of 21,000,000 BTC")); } else if (m_amount->satoshi() > m_wallet->balanceSatoshi()) { setAmountError(tr("Amount exceeds available balance")); } From 204fa383c752fe980e01722abc598051a05e383f Mon Sep 17 00:00:00 2001 From: johnny9 <985648+johnny9@users.noreply.github.com> Date: Wed, 4 Jun 2025 01:25:15 -0400 Subject: [PATCH 7/9] qml: Don't set/clear error string unless needed --- src/qml/models/sendrecipient.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/qml/models/sendrecipient.cpp b/src/qml/models/sendrecipient.cpp index 0874c85631..b5a51ccf56 100644 --- a/src/qml/models/sendrecipient.cpp +++ b/src/qml/models/sendrecipient.cpp @@ -111,10 +111,10 @@ void SendRecipient::clear() void SendRecipient::validateAddress() { - setAddressError(""); - if (!m_address.isEmpty() && !IsValidDestinationString(m_address.toStdString())) { setAddressError(tr("Invalid address")); + } else { + setAddressError(""); } Q_EMIT isValidChanged(); @@ -122,8 +122,6 @@ void SendRecipient::validateAddress() void SendRecipient::validateAmount() { - setAmountError(""); - if (m_amount->isSet()) { if (m_amount->satoshi() <= 0) { setAmountError(tr("Amount must be greater than zero")); @@ -131,6 +129,8 @@ void SendRecipient::validateAmount() setAmountError(tr("Amount exceeds maximum limit of 21,000,000 BTC")); } else if (m_amount->satoshi() > m_wallet->balanceSatoshi()) { setAmountError(tr("Amount exceeds available balance")); + } else { + setAmountError(""); } } From cc15afda62226e76da21d20abe8e10794a0b1ea2 Mon Sep 17 00:00:00 2001 From: johnny9 <985648+johnny9@users.noreply.github.com> Date: Wed, 4 Jun 2025 01:28:26 -0400 Subject: [PATCH 8/9] qml: Add const to sendrecipient's m_wallet --- src/qml/models/sendrecipient.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/models/sendrecipient.h b/src/qml/models/sendrecipient.h index 965483c854..972914a354 100644 --- a/src/qml/models/sendrecipient.h +++ b/src/qml/models/sendrecipient.h @@ -63,7 +63,7 @@ class SendRecipient : public QObject void validateAddress(); void validateAmount(); - WalletQmlModel* m_wallet; + const WalletQmlModel* m_wallet; QString m_address{""}; QString m_addressError{""}; QString m_label{""}; From 29e568cc1dbf0fada047481b7b650090acc392ba Mon Sep 17 00:00:00 2001 From: johnny9 <985648+johnny9@users.noreply.github.com> Date: Wed, 4 Jun 2025 01:53:47 -0400 Subject: [PATCH 9/9] qml: Provide information if the supplied addres is valid for another network --- src/qml/models/sendrecipient.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/qml/models/sendrecipient.cpp b/src/qml/models/sendrecipient.cpp index b5a51ccf56..e98c9b9aff 100644 --- a/src/qml/models/sendrecipient.cpp +++ b/src/qml/models/sendrecipient.cpp @@ -112,7 +112,13 @@ void SendRecipient::clear() void SendRecipient::validateAddress() { if (!m_address.isEmpty() && !IsValidDestinationString(m_address.toStdString())) { - setAddressError(tr("Invalid address")); + if (IsValidDestinationString(m_address.toStdString(), *CChainParams::Main())) { + setAddressError(tr("Address is valid for mainnet, not the current network")); + } else if (IsValidDestinationString(m_address.toStdString(), *CChainParams::TestNet())) { + setAddressError(tr("Address is valid for testnet, not the current network")); + } else { + setAddressError(tr("Invalid address format")); + } } else { setAddressError(""); }