diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d1e72b..4200abb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,11 +21,11 @@ cmake_policy(SET CMP0074 NEW) option(STATIC "Link libraries statically, requires static Qt" OFF) option(SELF_CONTAINED "Disable when building Feather for packages" OFF) option(TOR_DIR "Directory containing Tor binaries to embed inside Feather" OFF) -option(CHECK_UPDATES "Enable checking for application updates" ON) +option(CHECK_UPDATES "Enable checking for application updates" OFF) option(PLATFORM_INSTALLER "Built-in updater fetches installer (windows-only)" OFF) -option(USE_DEVICE_TREZOR "Trezor support compilation" OFF) +option(USE_DEVICE_TREZOR "Trezor support compilation" ON) option(DONATE_BEG "Prompt donation window every once in a while" OFF) -option(WITH_SCANNER "Enable webcam QR scanner" OFF) +option(WITH_SCANNER "Enable webcam QR scanner" ON) option(STACK_TRACE "Dump stack trace on crash (Linux only)" OFF) # Plugins diff --git a/contrib/depends/packages/libarchive.mk b/contrib/depends/packages/libarchive.mk index 2508478..352de62 100644 --- a/contrib/depends/packages/libarchive.mk +++ b/contrib/depends/packages/libarchive.mk @@ -5,15 +5,7 @@ $(package)_file_name=$(package)-$($(package)_version).tar.xz $(package)_sha256_hash=f887755c434a736a609cbd28d87ddbfbe9d6a3bb5b703c22c02f6af80a802735 define $(package)_config_cmds - CC="$($(package)_cc)" \ - CXX="$($(package)_cxx)" \ - AR="$($(package)_ar)" \ - RANLIB="$($(package)_ranlib)" \ - LIBTOOL="$($(package)_libtool)" \ - LDLAGS="$($(package)_ldflags)" \ - CFLAGS="-fPIE" \ - CXXFLAGS="-fPIE" \ - ./configure --host=$(host) --enable-static --prefix=$(host_prefix) --without-iconv + $($(package)_autoconf) endef define $(package)_build_cmds diff --git a/contrib/depends/packages/packages.mk b/contrib/depends/packages/packages.mk index 153c051..e5cbd6c 100644 --- a/contrib/depends/packages/packages.mk +++ b/contrib/depends/packages/packages.mk @@ -18,3 +18,4 @@ qt_mingw32_packages := qt tor_linux_packages := libevent tor_linux tor_darwin_packages := tor_darwin +tor_mingw32_packages := tor_mingw32 diff --git a/contrib/guix/manifest.scm b/contrib/guix/manifest.scm index 2f0edf6..5e46a67 100644 --- a/contrib/guix/manifest.scm +++ b/contrib/guix/manifest.scm @@ -304,8 +304,6 @@ chain for " target " development.")) python-minimal ;; Git git-minimal - ;; Libarchive - libarchive ;; Xcb xcb-util xcb-util-cursor diff --git a/external/feather-docs b/external/feather-docs deleted file mode 100644 index e69de29..0000000 diff --git a/external/feather-docs b/external/feather-docs new file mode 160000 index 0000000..c816c53 --- /dev/null +++ b/external/feather-docs @@ -0,0 +1 @@ +Subproject commit c816c53f3a8a65fe0e823faa064bc11f025fd0de diff --git a/src/plugins/PluginRegistry.h b/src/plugins/PluginRegistry.h index e63aef4..9a6d785 100644 --- a/src/plugins/PluginRegistry.h +++ b/src/plugins/PluginRegistry.h @@ -36,7 +36,7 @@ public: } bool isPluginEnabled(const QString &id) { - if (!pluginMap.contains(id) or (QString::compare(id,"atomic")==0 && constants::networkType==NetworkType::TESTNET)) { + if (!pluginMap.contains(id) || (QString::compare(id,"atomic")==0 && constants::networkType==NetworkType::TESTNET)) { return false; } diff --git a/src/plugins/atomic/AtomicConfigDialog.cpp b/src/plugins/atomic/AtomicConfigDialog.cpp index 5eb3a3a..f47e89e 100644 --- a/src/plugins/atomic/AtomicConfigDialog.cpp +++ b/src/plugins/atomic/AtomicConfigDialog.cpp @@ -5,18 +5,30 @@ #include "ui_AtomicConfigDialog.h" #include -#include #include +#include +#include "utils/config.h" +#include "utils/Networking.h" + #ifdef Q_OS_WIN #include +#define OS 1 // "WINDOWS" #else #include #include +#ifdef Q_PROCESSOR_X86_64 +#define ARCH 1 // "x86_64" +#elifdef Q_PROCESSOR_ARM_V7 +#define ARCH 2 // "armv7") +#else +#define ARCH 3 // "assumes aarch64 or unsupported" +#endif +#ifdef Q_OS_DARWIN +#define OS 2 // "MAC" +#else +#define OS 3 // "LINUX" +#endif #endif -#include - -#include "utils/config.h" -#include "utils/Networking.h" AtomicConfigDialog::AtomicConfigDialog(QWidget *parent) : WindowModalDialog(parent) @@ -40,7 +52,7 @@ AtomicConfigDialog::AtomicConfigDialog(QWidget *parent) QString path = QFileDialog::getOpenFileName(this, "Select swap binary file", Config::defaultConfigDir().absolutePath(), "Binary Executable (*)"); - Config::instance()->set(Config::swapPath, path); + saveSwapPath(path); if(path.isEmpty()){ return; } @@ -53,21 +65,50 @@ AtomicConfigDialog::AtomicConfigDialog(QWidget *parent) this->adjustSize(); } +QString AtomicConfigDialog::getPath() { + QFile* pathFile = new QFile(Config::defaultConfigDir().absolutePath() +"/swapPath.conf"); + pathFile->open(QIODevice::ReadOnly); + QString toolPath = pathFile->readAll(); + pathFile->close(); + return toolPath; +} + +void AtomicConfigDialog::saveSwapPath(QString path) { + QFile* pathFile = new QFile(Config::defaultConfigDir().absolutePath() +"/swapPath.conf"); + pathFile->open(QIODevice::WriteOnly); + pathFile->resize(0); + pathFile->write(path.toStdString().c_str()); + pathFile->close(); +} void AtomicConfigDialog::downloadBinary() { auto* network = new Networking(this); download = new QTemporaryFile(this); download->open(); tempFile = download->fileName(); QString url; - auto operatingSystem = Config::instance()->get(Config::operatingSystem).toString().toStdString(); - QString firstPart = "https://github.com/comit-network/xmr-btc-swap/releases/download/" + conf()->get(Config::swapVersion).toString(); - if(strcmp("WIN",operatingSystem.c_str()) == 0) { + QString swapVersion = "0.13.4"; + QString firstPart = "https://github.com/UnstoppableSwap/core/releases/download/" + swapVersion; + if(OS == 1) { // HARD CODED DOWNload URL CHANGE IF PROBLEMS - url = QString(firstPart+"/swap_"+conf()->get(Config::swapVersion).toString()+"_Windows_x86_64.zip"); - } else if (strcmp("LINUX",operatingSystem.c_str())==0){ - url = QString(firstPart+"/swap_"+conf()->get(Config::swapVersion).toString()+"_Linux_x86_64.tar"); + url = QString(firstPart+"/swap_"+ swapVersion + "_Windows_x86_64.zip"); + } else if (OS == 3){ + if (ARCH == 1) { + url = QString(firstPart+"/swap_"+ swapVersion + "_Linux_x86_64.tar"); + } else if (ARCH == 2) { + url = QString(firstPart+"/swap_"+ swapVersion + "_Linux_armv7.tar"); + } else { + qDebug() << "Unsupported architecture"; + throw std::runtime_error("Unsupported architecture"); + } } else { - url = QString(firstPart + "/swap_" + conf()->get(Config::swapVersion).toString() + "_Darwin_x86_64.tar"); + if (ARCH == 1) { + url = QString(firstPart + "/swap_"+ swapVersion + "_Darwin_x86_64.tar"); + } else if (ARCH == 3) { + url = QString(firstPart + "/swap_"+ swapVersion + "_Darwin_aarch64.tar"); + } else { + qDebug() << "Unsupported architecture"; + throw std::runtime_error("Unsupported architecture"); + } } archive = network->get(this, url); @@ -88,7 +129,7 @@ void AtomicConfigDialog::extract() { archive->deleteLater(); auto swapPath = Config::defaultConfigDir().absolutePath(); - swapPath.append("/swapTool"); + swapPath.append("/swap"); QFile binaryFile(swapPath); binaryFile.open(QIODevice::WriteOnly); //auto operatingSystem = conf()->get(Config::operatingSystem).toString().toStdString(); @@ -116,7 +157,7 @@ void AtomicConfigDialog::extract() { zip_fclose(f); //And close the archive zip_close(z); - conf()->set(Config::swapPath,swapPath); + saveSwapPath(swapPath+".exe"); #else //} else { @@ -147,7 +188,7 @@ void AtomicConfigDialog::extract() { archive_write_close(ext); archive_write_free(ext); - conf()->set(Config::swapPath, QString(savePath.c_str())); + saveSwapPath(swapPath); #endif //} qDebug() << "Finished"; diff --git a/src/plugins/atomic/AtomicConfigDialog.h b/src/plugins/atomic/AtomicConfigDialog.h index 6902367..6ac7a85 100644 --- a/src/plugins/atomic/AtomicConfigDialog.h +++ b/src/plugins/atomic/AtomicConfigDialog.h @@ -23,6 +23,7 @@ Q_OBJECT public: explicit AtomicConfigDialog(QWidget *parent = nullptr); ~AtomicConfigDialog() override; + static QString getPath(); public slots: void extract(); @@ -30,14 +31,11 @@ public slots: private: void downloadBinary(); int copy_data(struct archive *ar, struct archive *aw); - + void saveSwapPath(QString path); QScopedPointer ui; - - QNetworkReply* archive; + QNetworkReply* archive = nullptr; QString tempFile; - QTemporaryFile* download; - - + QTemporaryFile* download = nullptr; }; diff --git a/src/plugins/atomic/AtomicFundDialog.h b/src/plugins/atomic/AtomicFundDialog.h index f9dee47..53684d5 100644 --- a/src/plugins/atomic/AtomicFundDialog.h +++ b/src/plugins/atomic/AtomicFundDialog.h @@ -1,6 +1,5 @@ -// -// Created by dev on 7/8/24. -// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileCopyrightText: 2020-2024 The Monero Project #ifndef FEATHER_ATOMICFUNDDIALOG_H #define FEATHER_ATOMICFUNDDIALOG_H diff --git a/src/plugins/atomic/AtomicRecoverDialog.cpp b/src/plugins/atomic/AtomicRecoverDialog.cpp index 8f89404..f661383 100644 --- a/src/plugins/atomic/AtomicRecoverDialog.cpp +++ b/src/plugins/atomic/AtomicRecoverDialog.cpp @@ -1,6 +1,5 @@ -// -// Created by dev on 7/29/24. -// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileCopyrightText: 2020-2024 The Monero Project // You may need to build the project (run Qt uic code generator) to get "ui_AtomicRecoverDialog.h" resolved @@ -40,11 +39,11 @@ AtomicRecoverDialog::AtomicRecoverDialog(QWidget *parent) : QDateTime timestamp = QDateTime::fromString(entry[1],"dd.MM.yyyy.hh.mm.ss"); qint64 difference = timestamp.secsTo(QDateTime::currentDateTime()); - if (difference < 86400) { + if (difference < 86400) { // 86400 is number of seconds in a day (if a swap is older it is punished) rowData.clear(); rowData << new QStandardItem(id); rowData << new QStandardItem(timestamp.toString("MM-dd-yyyy hh:mm")); - if (difference > 43200){ + if (difference > 43200){ // 43200 is number of seconds in 12 hours rowData << new QStandardItem("Refundable"); } else rowData << new QStandardItem("Recoverable/Pending Refund Timelock"); @@ -73,7 +72,7 @@ AtomicRecoverDialog::AtomicRecoverDialog(QWidget *parent) : arguments << "--swap-id"; auto row = ui->swap_history->selectionModel()->selectedRows().at(0); arguments << row.sibling(row.row(),0).data().toString(); - if(conf()->get(Config::proxy).toInt() != Config::Proxy::None) { + if(conf()->get(Config::proxy).toInt() == Config::Proxy::Tor) { arguments << "--tor-socks5-port"; arguments << conf()->get(Config::socks5Port).toString(); } diff --git a/src/plugins/atomic/AtomicRecoverDialog.h b/src/plugins/atomic/AtomicRecoverDialog.h index 29c871f..447d07b 100644 --- a/src/plugins/atomic/AtomicRecoverDialog.h +++ b/src/plugins/atomic/AtomicRecoverDialog.h @@ -1,6 +1,5 @@ -// -// Created by dev on 7/29/24. -// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileCopyrightText: 2020-2024 The Monero Project #ifndef FEATHER_ATOMICRECOVERDIALOG_H #define FEATHER_ATOMICRECOVERDIALOG_H @@ -25,8 +24,8 @@ public: private slots: void updateBtn(const QModelIndex &index); private: - Ui::AtomicRecoverDialog *ui; - AtomicSwap *swapDialog; + Ui::AtomicRecoverDialog *ui = nullptr; + AtomicSwap *swapDialog = nullptr; }; diff --git a/src/plugins/atomic/AtomicSwap.cpp b/src/plugins/atomic/AtomicSwap.cpp index 72faeb2..3d517d7 100644 --- a/src/plugins/atomic/AtomicSwap.cpp +++ b/src/plugins/atomic/AtomicSwap.cpp @@ -1,6 +1,5 @@ -// -// Created by dev on 6/11/24. -// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileCopyrightText: 2020-2024 The Monero Project // You may need to build the project (run Qt uic code generator) to get "ui_AtomicSwap.h" resolved @@ -8,11 +7,17 @@ #include #include + +#include "AtomicConfigDialog.h" #include "ui_AtomicSwap.h" #include "AtomicWidget.h" #include "constants.h" #include "networktype.h" - +#ifdef QT_OS_WIN +#define WINDOWS 1 +#else +#define WINDOWS 0 +#endif AtomicSwap::AtomicSwap(QWidget *parent) : WindowModalDialog(parent), ui(new Ui::AtomicSwap), fundDialog( new AtomicFundDialog(this)), procList(new QList>()) { @@ -38,6 +43,13 @@ void AtomicSwap::runSwap(QStringList arguments){ QJsonParseError err; const QByteArray& rawline = swap->readLine(); QJsonDocument line = QJsonDocument::fromJson(rawline, &err); + if (err.error != QJsonParseError::NoError) { + qDebug()<close(); + this->close(); + return; + } qDebug() << rawline; bool check; QString message = line["fields"]["message"].toString(); @@ -99,8 +111,7 @@ void AtomicSwap::runSwap(QStringList arguments){ QString err = line["fields"]["err"].toString().split("\n")[0].split(":")[1]; QMessageBox::warning(this, "Cancel and Refund", "Time lock hasn't expired yet so cancel failed. Try again in " + err + "blocks"); } else if (QString latest_version = line["fields"]["latest_version"].toString(); !latest_version.isEmpty()){ - QMessageBox::warning(this, "Outdated swap version","A newer version of COMIT xmr-btc swap tool is available, delete current binary and re auto install to upgrade"); - conf()->set(Config::swapVersion,latest_version); + QMessageBox::warning(this, "Outdated swap version","A newer version of COMIT xmr-btc swap tool is available"); } else if (message.startsWith("Acquiring swap lock") && QString::compare("Resume",line["span"]["method_name"].toString())==0){ updateStatus("Beginning resumption of previous swap"); this->show(); @@ -110,14 +121,14 @@ void AtomicSwap::runSwap(QStringList arguments){ } }); - swap->start(conf()->get(Config::swapPath).toString(),arguments); + swap->start(AtomicConfigDialog::getPath(),arguments); qDebug() << "process started"; } AtomicSwap::~AtomicSwap() { for (const auto& proc : *procList){ proc->kill(); } - if(conf()->get(Config::operatingSystem)=="WINDOWS"){ + if(WINDOWS){ (new QProcess)->start("tskill", QStringList{"monero-wallet-rpc"}); }else { if (constants::networkType==NetworkType::STAGENET){ diff --git a/src/plugins/atomic/AtomicSwap.h b/src/plugins/atomic/AtomicSwap.h index d6792e9..553c8ea 100644 --- a/src/plugins/atomic/AtomicSwap.h +++ b/src/plugins/atomic/AtomicSwap.h @@ -1,6 +1,5 @@ -// -// Created by dev on 6/11/24. -// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileCopyrightText: 2020-2024 The Monero Project #ifndef FEATHER_ATOMICSWAP_H #define FEATHER_ATOMICSWAP_H @@ -32,11 +31,11 @@ public slots: signals: void cleanProcs(); private: - Ui::AtomicSwap *ui; + Ui::AtomicSwap *ui = nullptr; QString id; QString min; AtomicFundDialog* fundDialog; - QList>* procList; + QList>* procList = nullptr; int btc_confs; void cancel(); diff --git a/src/plugins/atomic/AtomicWidget.cpp b/src/plugins/atomic/AtomicWidget.cpp index addd6c4..d0fee96 100644 --- a/src/plugins/atomic/AtomicWidget.cpp +++ b/src/plugins/atomic/AtomicWidget.cpp @@ -9,13 +9,19 @@ #include #include #include - #include "AtomicConfigDialog.h" #include "OfferModel.h" #include "utils/AppData.h" #include "utils/ColorScheme.h" #include "utils/WebsocketNotifier.h" #include "AtomicFundDialog.h" +#include "WalletManager.h" + +#ifdef QT_OS_WIN +#define WINDOWS 1 +#else +#define WINDOWS 0 +#endif AtomicWidget::AtomicWidget(QWidget *parent) : QWidget(parent) @@ -76,14 +82,12 @@ AtomicWidget::AtomicWidget(QWidget *parent) QMessageBox::warning(this, "Warning", "XMR receive address is required to start swap"); return; } - QRegularExpression xmrMain("^[48][0-9AB][1-9A-HJ-NP-Za-km-z]{93}"); - QRegularExpression xmrStage("^[57][0-9AB][1-9A-HJ-NP-Za-km-z]{93}"); if (constants::networkType==NetworkType::STAGENET){ if(!btcChange.isEmpty() && !btcTest.match(btcChange).hasMatch()){ QMessageBox::warning(this, "Warning","BTC change address is wrong, not a bech32 segwit address, or on wrong network"); return; } - if(!xmrStage.match(xmrReceive).hasMatch()){ + if(WalletManager::addressValid(xmrReceive,NetworkType::STAGENET)){ QMessageBox::warning(this, "Warning","XMR receive address is improperly formated or on wrong network"); return; } @@ -92,7 +96,7 @@ AtomicWidget::AtomicWidget(QWidget *parent) QMessageBox::warning(this, "Warning","BTC change address is wrong, not a bech32 segwit address,or on wrong network"); return; } - if(!xmrMain.match(xmrReceive).hasMatch()){ + if(WalletManager::addressValid(xmrReceive,NetworkType::MAINNET)){ QMessageBox::warning(this, "Warning","XMR receive address is improperly formated or on wrong network"); return; } @@ -164,7 +168,7 @@ void AtomicWidget::runSwap(const QString& seller, const QString& btcChange, cons */ arguments << "--seller"; arguments << seller; - if(conf()->get(Config::proxy).toInt() != Config::Proxy::None) { + if(conf()->get(Config::proxy).toInt() == Config::Proxy::Tor) { arguments << "--tor-socks5-port"; arguments << conf()->get(Config::socks5Port).toString(); } @@ -183,7 +187,7 @@ void AtomicWidget::list(const QString& rendezvous) { arguments << "-j"; arguments << "list-sellers"; //Temporary fix till comit xmr btc updates libp2p to work with modern rendezvous points - if(!ui->btn_clearnet->isChecked() && conf()->get(Config::proxy).toInt() != Config::Proxy::None) { + if(!ui->btn_clearnet->isChecked() && conf()->get(Config::proxy).toInt() == Config::Proxy::Tor) { arguments << "--tor-socks5-port"; arguments << conf()->get(Config::socks5Port).toString(); } else if (ui->btn_clearnet->isChecked()) { @@ -229,7 +233,7 @@ void AtomicWidget::list(const QString& rendezvous) { o_model->updateOffers(*offerList); return list; }); - swap->start(conf()->get(Config::swapPath).toString(), arguments); + swap->start(AtomicConfigDialog::getPath(), arguments); @@ -250,7 +254,7 @@ void AtomicWidget::clean() { } auto cleanWallet = new QProcess; auto cleanSwap = new QProcess; - if(conf()->get(Config::operatingSystem)=="WINDOWS"){ + if(WINDOWS){ (cleanWallet)->start("tskill", QStringList{"monero-wallet-rpc"}); (cleanWallet)->start("tskill", QStringList{"swap"}); }else { diff --git a/src/plugins/atomic/AtomicWidget.h b/src/plugins/atomic/AtomicWidget.h index c465ced..32b27da 100644 --- a/src/plugins/atomic/AtomicWidget.h +++ b/src/plugins/atomic/AtomicWidget.h @@ -41,13 +41,13 @@ private: QScopedPointer ui; bool m_comboBoxInit = false; QTimer m_statusTimer; - OfferModel *o_model; - QList> *offerList; - AtomicSwap *swapDialog; - AtomicFundDialog *fundDialog; - AtomicRecoverDialog *recoverDialog; + OfferModel *o_model = nullptr; + QList> *offerList = nullptr; + AtomicSwap *swapDialog = nullptr; + AtomicFundDialog *fundDialog = nullptr; + AtomicRecoverDialog *recoverDialog = nullptr; - QList> *procList; + QList> *procList = nullptr; }; #endif // FEATHER_ATOMICWIDGET_H diff --git a/src/plugins/atomic/Offer.h b/src/plugins/atomic/Offer.h index 0940041..804ccd6 100644 --- a/src/plugins/atomic/Offer.h +++ b/src/plugins/atomic/Offer.h @@ -1,6 +1,5 @@ -// -// Created by dev on 5/23/24. -// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileCopyrightText: 2020-2024 The Monero Project #ifndef FEATHER_OFFER_H #define FEATHER_OFFER_H diff --git a/src/plugins/atomic/OfferModel.cpp b/src/plugins/atomic/OfferModel.cpp index 013a080..1197d43 100644 --- a/src/plugins/atomic/OfferModel.cpp +++ b/src/plugins/atomic/OfferModel.cpp @@ -1,6 +1,5 @@ -// -// Created by dev on 5/23/24. -// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileCopyrightText: 2020-2024 The Monero Project #include "OfferModel.h" diff --git a/src/plugins/atomic/OfferModel.h b/src/plugins/atomic/OfferModel.h index d6aded3..0062631 100644 --- a/src/plugins/atomic/OfferModel.h +++ b/src/plugins/atomic/OfferModel.h @@ -1,6 +1,5 @@ -// -// Created by dev on 5/23/24. -// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileCopyrightText: 2020-2024 The Monero Project #ifndef FEATHER_OFFERMODEL_H #define FEATHER_OFFERMODEL_H diff --git a/src/utils/config.cpp b/src/utils/config.cpp index d3dae22..0a976c1 100644 --- a/src/utils/config.cpp +++ b/src/utils/config.cpp @@ -12,13 +12,7 @@ #include "utils/os/tails.h" #define QS QStringLiteral -#if defined(Q_OS_WIN64) -#define OS "WINDOWS" -#elif defined(Q_OS_DARWIN) -#define OS "MAC" -#else -#define OS "LINUX" -#endif + struct ConfigDirective { QString name; @@ -150,10 +144,7 @@ static const QHash configStrings = { {Config::rendezVous, {QS("rendezVous"), QStringList{"/dns4/atomicswaps.majesticbank.at/tcp/8888/p2p/12D3KooWKJUwP45K7fLbwGY1VM5V3U7LseU8EwJiAozUFrq5ihoF", "/dns4/discover.unstoppableswap.net/tcp/8888/p2p/12D3KooWA6cnqJpVnreBVnoro8midDL9Lpzmg8oJPoAGi7YYaamE", "/dns4/eratosthen.es/tcp/7798/p2p/12D3KooWAh7EXXa2ZyegzLGdjvj1W4G3EXrTGrf6trraoT1MEobs"}}}, - {Config::swapPath, {QS("swapPath"), ""}}, - {Config::operatingSystem, {QS("operatingSystem"), OS}}, {Config::pendingSwap, {QS("pendingSwap"), QStringList{}}}, - {Config::swapVersion, {QS("swapVersion"), "0.13.4"}}, };