From e7d4eda2cf8fa07478340da61a4a355afdd6247c Mon Sep 17 00:00:00 2001 From: June Egbert <102435854+junekomeiji@users.noreply.github.com> Date: Tue, 29 Oct 2024 23:26:34 +0100 Subject: [PATCH] Overhauled the Buy Names Page with the Electrum-NMC version and added error boxes for invalid names. There are still multiple bugs which lead to crashes, so filing a PR as WIP for now. --- src/names/applications.cpp | 13 + src/names/applications.h | 2 + src/qt/buynamespage.cpp | 141 +++++++- src/qt/buynamespage.h | 5 +- src/qt/forms/buynamespage.ui | 472 ++++++++++++++++++++------- src/test/name_applications_tests.cpp | 8 + 6 files changed, 517 insertions(+), 124 deletions(-) diff --git a/src/names/applications.cpp b/src/names/applications.cpp index ad4c82ced9..3e5d7aef23 100644 --- a/src/names/applications.cpp +++ b/src/names/applications.cpp @@ -217,3 +217,16 @@ GetMinimalJSON (const std::string& text){ return v.write(0,0); } + +std::string +ConvertDomainForms (const std::string& domain){ + if(domain.ends_with(".bit")){ + return domain.substr(0, domain.size()-4); + } else if (domain.starts_with("0x")) { + std::string cutdomain = domain.substr(2, domain.size()); + int hexval = std::stoi(cutdomain, 0, 16); + return std::to_string(hexval); + } else { + return domain; + } +} diff --git a/src/names/applications.h b/src/names/applications.h index 525d90f182..83c29634c4 100644 --- a/src/names/applications.h +++ b/src/names/applications.h @@ -29,4 +29,6 @@ bool IsMinimalJSONOrEmptyString (const std::string& text); std::string GetMinimalJSON (const std::string& text); +std::string ConvertDomainForms (const std::string& domain); + #endif // H_BITCOIN_NAMES_APPLICATIONS diff --git a/src/qt/buynamespage.cpp b/src/qt/buynamespage.cpp index 06648861d8..24748cb1c1 100644 --- a/src/qt/buynamespage.cpp +++ b/src/qt/buynamespage.cpp @@ -8,11 +8,18 @@ #include #include #include +#include #include +#include +#include + #include +//ascii -> old domain system +//domain -> domain from scratch (without .bit) +//hex -> hex BuyNamesPage::BuyNamesPage(const PlatformStyle *platformStyle, QWidget *parent) : QWidget(parent), platformStyle(platformStyle), @@ -22,11 +29,13 @@ BuyNamesPage::BuyNamesPage(const PlatformStyle *platformStyle, QWidget *parent) ui->setupUi(this); ui->registerNameButton->hide(); - - connect(ui->registerName, &QLineEdit::textEdited, this, &BuyNamesPage::onNameEdited); + + connect(ui->registerNameDomain, &QLineEdit::textEdited, this, &BuyNamesPage::onDomainNameEdited); + connect(ui->registerNameAscii, &QLineEdit::textEdited, this, &BuyNamesPage::onAsciiNameEdited); + connect(ui->registerNameHex, &QLineEdit::textEdited, this, &BuyNamesPage::onHexNameEdited); connect(ui->registerNameButton, &QPushButton::clicked, this, &BuyNamesPage::onRegisterNameAction); - ui->registerName->installEventFilter(this); + ui->registerNameDomain->installEventFilter(this); } BuyNamesPage::~BuyNamesPage() @@ -43,7 +52,7 @@ bool BuyNamesPage::eventFilter(QObject *object, QEvent *event) { if (event->type() == QEvent::FocusIn) { - if (object == ui->registerName) + if (object == ui->registerNameAscii) { ui->registerNameButton->setDefault(true); } @@ -51,15 +60,76 @@ bool BuyNamesPage::eventFilter(QObject *object, QEvent *event) return QWidget::eventFilter(object, event); } -void BuyNamesPage::onNameEdited(const QString &name) +void BuyNamesPage::onAsciiNameEdited(const QString &name) { if (!walletModel) return; - const QString availableError = name_available(name); + QString availableError = name_available(name); + + if (availableError == "") + { + ui->statusLabel->setText(tr("%1 is available to register!").arg(name)); + ui->registerNameButton->show(); + } + else + { + ui->statusLabel->setText(availableError); + ui->registerNameButton->hide(); + } +} + +void BuyNamesPage::onHexNameEdited(const QString &name) +{ + + if (!walletModel) + return; + + QString availableError; + //check if it's even a valid hexdomain + std::string hex = name.toStdString(); + if(!std::all_of(hex.begin(), hex.end(), ::isxdigit)) + { + ui->statusLabel->setText(tr("%1 is not a valid hexadecimal entry!").arg(name)); + } + else + { + std::string domain = ConvertDomainForms("0x" + hex); + availableError = name_available(QString::fromStdString(domain)); + } + + if (availableError == "") + { + ui->statusLabel->setText(tr("%1 is available to register!").arg(name)); + ui->registerNameButton->show(); + } + else + { + ui->statusLabel->setText(availableError); + ui->registerNameButton->hide(); + } +} + +void BuyNamesPage::onDomainNameEdited(const QString &name){ + + if (!walletModel) + return; + + QString availableError; + std::string domain = name.toStdString(); + //check if it even ends with .bit + if(!name.toStdString().ends_with(".bit")) + { + ui->statusLabel->setText(tr("%1 does not end with .bit!").arg(name)); + } else { + domain = ConvertDomainForms(domain); + availableError = name_available(QString::fromStdString(domain)); + } if (availableError == "") { + + const std::string domain = ConvertDomainForms(name.toStdString()); ui->statusLabel->setText(tr("%1 is available to register!").arg(name)); ui->registerNameButton->show(); } @@ -75,7 +145,60 @@ void BuyNamesPage::onRegisterNameAction() if (!walletModel) return; - QString name = ui->registerName->text(); + //check which tab we're on + int currentTab = ui->tabWidget->currentIndex(); + + QString input, name; + QMessageBox::StandardButton ErrorBox; + + //just do the conversion here... + switch(currentTab) { + case 0: + { + //strip off .bit + input = ui->registerNameDomain->text(); + std::string domain = input.toStdString(); + if(!domain.ends_with(".bit")){ + ErrorBox = QMessageBox::critical(this, tr("Invalid Namecoin Domain"), + tr("The inputted domain does not end with .bit."), QMessageBox::Cancel); + return; + } else { + name = QString::fromStdString(ConvertDomainForms(domain)); + } + } + + break; + + case 1: + { + //no changes needed + input = ui->registerNameAscii->text(); + name = input; + break; + } + case 2: + { + //check if valid hex + input = ui->registerNameHex->text(); + std::string hex = input.toStdString(); + + if(!std::all_of(hex.begin(), hex.end(), ::isxdigit)){ + ErrorBox = QMessageBox::critical(this, tr("Invalid Hex Value"), + tr("The inputted hex value is invalid."), QMessageBox::Cancel); + + return; + } else { + std::string domain = ConvertDomainForms("0x" + input.toStdString()); + name = QString::fromStdString(domain); + } + } + + break; + + default: + //how did we get here? + break; + } WalletModel::UnlockContext ctx(walletModel->requestUnlock()); if (!ctx.isValid()) @@ -98,7 +221,9 @@ void BuyNamesPage::onRegisterNameAction() } // reset UI text - ui->registerName->setText("d/"); + ui->registerNameDomain->setText(""); + ui->registerNameAscii->setText("d/"); + ui->registerNameHex->setText("642f"); ui->registerNameButton->setDefault(true); } diff --git a/src/qt/buynamespage.h b/src/qt/buynamespage.h index 46f37658b0..ff7bc5d4a5 100644 --- a/src/qt/buynamespage.h +++ b/src/qt/buynamespage.h @@ -37,7 +37,10 @@ class BuyNamesPage : public QWidget private Q_SLOTS: bool eventFilter(QObject *object, QEvent *event); - void onNameEdited(const QString &name); + void onDomainNameEdited(const QString &name); + void onHexNameEdited(const QString &name); + void onAsciiNameEdited(const QString &name); + void onRegisterNameAction(); }; diff --git a/src/qt/forms/buynamespage.ui b/src/qt/forms/buynamespage.ui index 82d6a82802..40ee933a70 100644 --- a/src/qt/forms/buynamespage.ui +++ b/src/qt/forms/buynamespage.ui @@ -6,10 +6,11 @@ 0 0 - 776 + 1023 364 + + + + + + + 0 + 140 + + + + + 16777213 + 150 + + + + 0 + + + + Domain + + + + + 0 + 0 + 211 + 16 + + + + + 0 + 0 + + + + New domain name: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + 0 + 50 + 1005 + 41 + + + + + 0 + 0 + + + + <html><head/><body><p>E.g. <span style=" font-weight:600;">mysite.bit</span></p></body></html> + + + Qt::RichText + + + true + + + true + + + + + + 0 + 20 + 621 + 31 + + + + + + + + + + + + + + + + + + + ASCII + + + + + 0 + 0 + 211 + 16 + + + + + 0 + 0 + + + + New ASCII name: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + 0 + 50 + 621 + 61 + + + + + 0 + 0 + + + + Use <strong>d/</strong> prefix for domain names. E.g. <strong>d/mysite</strong> will register <strong>mysite.bit</strong><br>See the <a href="https://github.com/namecoin/proposals/blob/master/ifa-0001.md#keys">Namecoin Domain Names specification</a> for reference. Other prefixes can be used for miscellaneous purposes (not domain names).</p> + + + Qt::RichText + + + true + + + true + + + + + + 0 + 20 + 621 + 31 + + + + + + + d/ + + + + + + + + + + + + Hex + + + + + 0 + 0 + 211 + 16 + + + + + 0 + 0 + + + + New hex name: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + 0 + 50 + 1005 + 41 + + + + + 0 + 0 + + + + <html><head/><body><p>Hex names are only recommended for power users and developers.</p></body></html> + + + Qt::RichText + + + true + + + true + + + + + + 0 + 20 + 621 + 31 + + + + + + + 642f + + + + + + + + + + + + + + + + 0 + 0 + + + + + + + Qt::PlainText + + + true + + + + + + + + 0 + 0 + + + + + 150 + 0 + + + + &Check name availability… + + + + + + + + 0 + 0 + + + + + + + Qt::PlainText + + + true + + + + + + + + 0 + 0 + + + + + 150 + 0 + + + + Register the name. + + + &Register Name… + + + + :/icons/send:/icons/send + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + @@ -153,5 +394,6 @@ + diff --git a/src/test/name_applications_tests.cpp b/src/test/name_applications_tests.cpp index 72cb7bc7d7..d39a128b2e 100644 --- a/src/test/name_applications_tests.cpp +++ b/src/test/name_applications_tests.cpp @@ -141,4 +141,12 @@ BOOST_AUTO_TEST_CASE( minimal_json ) BOOST_CHECK_EQUAL(IsMinimalJSONOrEmptyString("{\"bar\":[1, 2, 3]}"), false); } +BOOST_AUTO_TEST_CASE( domain_conversion ){ + BOOST_CHECK_EQUAL(ConvertDomainForms("namecoin"), "namecoin"); + + BOOST_CHECK_EQUAL(ConvertDomainForms("namecoin.bit"), "namecoin"); + + BOOST_CHECK_EQUAL(ConvertDomainForms("6E616D65636F696E0A"), "namecoin"); +} + BOOST_AUTO_TEST_SUITE_END()