diff --git a/.gitmodules b/.gitmodules index 745d6be7..35508a8b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "GraftMobileClient/qrcodegenerator"] path = GraftMobileClient/qrcodegenerator url = https://github.com/EDDragonWolf/QR-Code-generator.git +[submodule "GraftMobileClient/libwallet"] + path = GraftMobileClient/libwallet + url = https://gitlab.com/EDDragonWolf/explibwallet.git diff --git a/GraftMobileClient/GraftMobileClient.pro b/GraftMobileClient/GraftMobileClient.pro index 01885e44..e13e8377 100644 --- a/GraftMobileClient/GraftMobileClient.pro +++ b/GraftMobileClient/GraftMobileClient.pro @@ -3,8 +3,8 @@ QT += qml quick network widgets CONFIG += c++11 DEFINES += MAJOR_VERSION=1 -DEFINES += MINOR_VERSION=11 -DEFINES += BUILD_VERSION=1 +DEFINES += MINOR_VERSION=13 +DEFINES += BUILD_VERSION=0 win32|macx|unix { DEFINES += RES_IOS @@ -29,6 +29,10 @@ include(android/android.pri) include(qzxing/QZXing.pri) include(QRCodeGenerator.pri) +include(libwallet/libwallet.pri) +ios|macx { +include(core/api/v2/graftapiv2.pri) +} contains(DEFINES, POS_BUILD) { ios|android { @@ -36,22 +40,28 @@ include(imagepicker/ImagePickerLibrary.pri) } SOURCES += \ - core/api/graftposapi.cpp \ + core/api/v1/graftposapiv1.cpp \ + core/api/v1/graftposhandlerv1.cpp \ core/graftposclient.cpp HEADERS += \ - core/api/graftposapi.h \ + core/api/v1/graftposapiv1.h \ + core/api/v1/graftposhandlerv1.h \ + core/api/graftposhandler.h \ core/graftposclient.h \ core/defines.h } contains(DEFINES, WALLET_BUILD) { SOURCES += \ - core/api/graftwalletapi.cpp \ + core/api/v1/graftwalletapiv1.cpp \ + core/api/v1/graftwallethandlerv1.cpp \ core/graftwalletclient.cpp HEADERS += \ - core/api/graftwalletapi.h \ + core/api/v1/graftwalletapiv1.h \ + core/api/v1/graftwallethandlerv1.h \ + core/api/graftwallethandler.h \ core/graftwalletclient.h } @@ -64,7 +74,7 @@ include(mac/mac.pri) } SOURCES += main.cpp \ - core/api/graftgenericapi.cpp \ + core/api/v1/graftgenericapiv1.cpp \ core/productmodel.cpp \ core/productitem.cpp \ core/productmodelserializator.cpp \ @@ -88,7 +98,8 @@ SOURCES += main.cpp \ HEADERS += \ core/config.h \ - core/api/graftgenericapi.h \ + core/api/v1/graftgenericapiv1.h \ + core/api/graftbasehandler.h \ core/productmodel.h \ core/productitem.h \ core/productmodelserializator.h \ diff --git a/GraftMobileClient/android/pos/AndroidManifest.xml b/GraftMobileClient/android/pos/AndroidManifest.xml index 69147b07..a2883dd0 100644 --- a/GraftMobileClient/android/pos/AndroidManifest.xml +++ b/GraftMobileClient/android/pos/AndroidManifest.xml @@ -1,5 +1,5 @@ - + diff --git a/GraftMobileClient/android/wallet/AndroidManifest.xml b/GraftMobileClient/android/wallet/AndroidManifest.xml index ce6a193f..3a3f6969 100644 --- a/GraftMobileClient/android/wallet/AndroidManifest.xml +++ b/GraftMobileClient/android/wallet/AndroidManifest.xml @@ -1,5 +1,5 @@ - + diff --git a/GraftMobileClient/core/api/graftbasehandler.h b/GraftMobileClient/core/api/graftbasehandler.h new file mode 100644 index 00000000..2179288b --- /dev/null +++ b/GraftMobileClient/core/api/graftbasehandler.h @@ -0,0 +1,40 @@ +#ifndef GRAFTBASEHANDLER_H +#define GRAFTBASEHANDLER_H + +#include + +class GraftBaseHandler : public QObject +{ + Q_OBJECT +public: + explicit GraftBaseHandler(QObject *parent = nullptr) : QObject(parent) {} + + virtual void changeAddresses(const QStringList &addresses, + const QStringList &internalAddresses = QStringList()) = 0; + + virtual void setAccountData(const QByteArray &accountData, const QString &password) = 0; + virtual QByteArray accountData() const = 0; + virtual QString password() const = 0; + + virtual void resetData() = 0; + +public slots: + virtual void createAccount(const QString &password) = 0; + virtual void restoreAccount(const QString &seed, const QString &password) = 0; + virtual void updateBalance() = 0; + virtual void transferFee(const QString &address, const QString &amount) = 0; + virtual void transfer(const QString &address, const QString &amount) = 0; + +signals: + void errorReceived(const QString &message); + void createAccountReceived(const QByteArray &accountData, const QString &password, + const QString &address, const QString &viewKey, const QString &seed); + void restoreAccountReceived(const QByteArray &accountData, const QString &password, + const QString &address, const QString &viewKey, + const QString &seed); + void balanceReceived(double balance, double unlockedBalance); + void transferFeeReceived(int result, double fee); + void transferReceived(int result); +}; + +#endif // GRAFTBASEHANDLER_H diff --git a/GraftMobileClient/core/api/graftposhandler.h b/GraftMobileClient/core/api/graftposhandler.h new file mode 100644 index 00000000..18216de0 --- /dev/null +++ b/GraftMobileClient/core/api/graftposhandler.h @@ -0,0 +1,24 @@ +#ifndef GRAFTPOSHANDLER_H +#define GRAFTPOSHANDLER_H + +#include "graftbasehandler.h" + +class GraftPOSHandler : public GraftBaseHandler +{ + Q_OBJECT +public: + explicit GraftPOSHandler(QObject *parent = nullptr) : GraftBaseHandler(parent) {} + +public slots: + virtual void sale(const QString &address, const QString &viewKey, double amount, + const QString &saleDetails = QString()) = 0; + virtual void rejectSale(const QString &pid) = 0; + virtual void saleStatus(const QString &pid, int blockNumber) = 0; + +signals: + void saleReceived(int result, const QString &pid, int blockNumber); + void rejectSaleReceived(bool result); + void saleStatusReceived(bool result); +}; + +#endif // GRAFTPOSHANDLER_H diff --git a/GraftMobileClient/core/api/graftwallethandler.h b/GraftMobileClient/core/api/graftwallethandler.h new file mode 100644 index 00000000..6a27641c --- /dev/null +++ b/GraftMobileClient/core/api/graftwallethandler.h @@ -0,0 +1,26 @@ +#ifndef GRAFTWALLETHANDLER_H +#define GRAFTWALLETHANDLER_H + +#include "graftbasehandler.h" + +class GraftWalletHandler : public GraftBaseHandler +{ + Q_OBJECT +public: + explicit GraftWalletHandler(QObject *parent = nullptr) : GraftBaseHandler(parent) {} + +public slots: + virtual void saleDetails(const QString &pid, int blockNumber) = 0; + virtual void rejectPay(const QString &pid, int blockNumber) = 0; + virtual void pay(const QString &pid, const QString &address, + double amount, int blockNumber) = 0; + virtual void payStatus(const QString &pid, int blockNumber) = 0; + +signals: + void saleDetailsReceived(int result, const QString &details); + void rejectPayReceived(int result); + void payReceived(int result); + void payStatusReceived(int result, int status); +}; + +#endif // GRAFTWALLETHANDLER_H diff --git a/GraftMobileClient/core/api/graftgenericapi.cpp b/GraftMobileClient/core/api/v1/graftgenericapiv1.cpp similarity index 82% rename from GraftMobileClient/core/api/graftgenericapi.cpp rename to GraftMobileClient/core/api/v1/graftgenericapiv1.cpp index 907279f2..fe18a2f3 100644 --- a/GraftMobileClient/core/api/graftgenericapi.cpp +++ b/GraftMobileClient/core/api/v1/graftgenericapiv1.cpp @@ -1,12 +1,12 @@ -#include "graftgenericapi.h" +#include "graftgenericapiv1.h" #include #include #include #include -#include "../config.h" +#include "../../config.h" -GraftGenericAPI::GraftGenericAPI(const QStringList &addresses, const QString &dapiVersion, - QObject *parent) +GraftGenericAPIv1::GraftGenericAPIv1(const QStringList &addresses, const QString &dapiVersion, + QObject *parent) : QObject(parent) ,mDAPIVersion(dapiVersion) { @@ -18,39 +18,39 @@ GraftGenericAPI::GraftGenericAPI(const QStringList &addresses, const QString &da mRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); } -GraftGenericAPI::~GraftGenericAPI() +GraftGenericAPIv1::~GraftGenericAPIv1() { } -void GraftGenericAPI::changeAddresses(const QStringList &addresses) +void GraftGenericAPIv1::changeAddresses(const QStringList &addresses) { mAddresses = addresses; mCurrentAddress = -1; mRequest.setUrl(nextAddress()); } -void GraftGenericAPI::setDAPIVersion(const QString &version) +void GraftGenericAPIv1::setDAPIVersion(const QString &version) { mDAPIVersion = version; } -void GraftGenericAPI::setAccountData(const QByteArray &accountData, const QString &password) +void GraftGenericAPIv1::setAccountData(const QByteArray &accountData, const QString &password) { mAccountData = accountData; mPassword = password; } -QByteArray GraftGenericAPI::accountData() const +QByteArray GraftGenericAPIv1::accountData() const { return mAccountData; } -QString GraftGenericAPI::password() const +QString GraftGenericAPIv1::password() const { return mPassword; } -void GraftGenericAPI::createAccount(const QString &password) +void GraftGenericAPIv1::createAccount(const QString &password) { mRetries = 0; mPassword = password; @@ -61,10 +61,11 @@ void GraftGenericAPI::createAccount(const QString &password) mTimer.start(); mLastRequest = array; QNetworkReply *reply = mManager->post(mRequest, array); - connect(reply, &QNetworkReply::finished, this, &GraftGenericAPI::receiveCreateAccountResponse); + connect(reply, &QNetworkReply::finished, + this, &GraftGenericAPIv1::receiveCreateAccountResponse); } -void GraftGenericAPI::getBalance() +void GraftGenericAPIv1::getBalance() { mRetries = 0; if (mAccountData.isEmpty()) @@ -81,10 +82,10 @@ void GraftGenericAPI::getBalance() mTimer.start(); mLastRequest = array; QNetworkReply *reply = mManager->post(mRequest, array); - connect(reply, &QNetworkReply::finished, this, &GraftGenericAPI::receiveGetBalanceResponse); + connect(reply, &QNetworkReply::finished, this, &GraftGenericAPIv1::receiveGetBalanceResponse); } -void GraftGenericAPI::getSeed() +void GraftGenericAPIv1::getSeed() { mRetries = 0; if (mAccountData.isEmpty()) @@ -102,10 +103,10 @@ void GraftGenericAPI::getSeed() mTimer.start(); mLastRequest = array; QNetworkReply *reply = mManager->post(mRequest, array); - connect(reply, &QNetworkReply::finished, this, &GraftGenericAPI::receiveGetSeedResponse); + connect(reply, &QNetworkReply::finished, this, &GraftGenericAPIv1::receiveGetSeedResponse); } -void GraftGenericAPI::restoreAccount(const QString &seed, const QString &password) +void GraftGenericAPIv1::restoreAccount(const QString &seed, const QString &password) { mRetries = 0; mPassword = password; @@ -116,10 +117,11 @@ void GraftGenericAPI::restoreAccount(const QString &seed, const QString &passwor mTimer.start(); mLastRequest = array; QNetworkReply *reply = mManager->post(mRequest, array); - connect(reply, &QNetworkReply::finished, this, &GraftGenericAPI::receiveRestoreAccountResponse); + connect(reply, &QNetworkReply::finished, + this, &GraftGenericAPIv1::receiveRestoreAccountResponse); } -void GraftGenericAPI::transferFee(const QString &address, const QString &amount) +void GraftGenericAPIv1::transferFee(const QString &address, const QString &amount) { mRetries = 0; if (mAccountData.isEmpty()) @@ -138,10 +140,10 @@ void GraftGenericAPI::transferFee(const QString &address, const QString &amount) mTimer.start(); mLastRequest = array; QNetworkReply *reply = mManager->post(mRequest, array); - connect(reply, &QNetworkReply::finished, this, &GraftGenericAPI::receiveTransferFeeResponse); + connect(reply, &QNetworkReply::finished, this, &GraftGenericAPIv1::receiveTransferFeeResponse); } -void GraftGenericAPI::transfer(const QString &address, const QString &amount) +void GraftGenericAPIv1::transfer(const QString &address, const QString &amount) { mRetries = 0; if (mAccountData.isEmpty()) @@ -160,32 +162,32 @@ void GraftGenericAPI::transfer(const QString &address, const QString &amount) mTimer.start(); mLastRequest = array; QNetworkReply *reply = mManager->post(mRequest, array); - connect(reply, &QNetworkReply::finished, this, &GraftGenericAPI::receiveTransferResponse); + connect(reply, &QNetworkReply::finished, this, &GraftGenericAPIv1::receiveTransferResponse); } -double GraftGenericAPI::toCoins(double atomic) +double GraftGenericAPIv1::toCoins(double atomic) { return (1.0 * atomic) / 10000000000.0; } -double GraftGenericAPI::toAtomic(double coins) +double GraftGenericAPIv1::toAtomic(double coins) { return coins * 10000000000; } -QString GraftGenericAPI::accountPlaceholder() const +QString GraftGenericAPIv1::accountPlaceholder() const { return QString("????"); } -QByteArray GraftGenericAPI::serializeAmount(double amount) const +QByteArray GraftGenericAPIv1::serializeAmount(double amount) const { QByteArray serializedAmount; serializedAmount.setNum(toAtomic(amount), 'f', 0); return serializedAmount; } -QJsonObject GraftGenericAPI::buildMessage(const QString &key, const QJsonObject ¶ms) const +QJsonObject GraftGenericAPIv1::buildMessage(const QString &key, const QJsonObject ¶ms) const { QJsonObject data; data.insert(QStringLiteral("jsonrpc"), QStringLiteral("2.0")); @@ -199,7 +201,7 @@ QJsonObject GraftGenericAPI::buildMessage(const QString &key, const QJsonObject return data; } -QJsonObject GraftGenericAPI::processReply(QNetworkReply *reply) +QJsonObject GraftGenericAPIv1::processReply(QNetworkReply *reply) { QJsonObject object; if (reply->error() == QNetworkReply::NoError) @@ -233,7 +235,7 @@ QJsonObject GraftGenericAPI::processReply(QNetworkReply *reply) return object; } -QUrl GraftGenericAPI::nextAddress() +QUrl GraftGenericAPIv1::nextAddress() { mCurrentAddress++; if (mCurrentAddress >= mAddresses.count()) @@ -243,7 +245,7 @@ QUrl GraftGenericAPI::nextAddress() return QUrl(scUrl.arg(mAddresses.value(mCurrentAddress))); } -QNetworkReply *GraftGenericAPI::retry() +QNetworkReply *GraftGenericAPIv1::retry() { if (mRetries < mAddresses.count() - 1) { @@ -259,7 +261,7 @@ QNetworkReply *GraftGenericAPI::retry() return nullptr; } -void GraftGenericAPI::receiveCreateAccountResponse() +void GraftGenericAPIv1::receiveCreateAccountResponse() { mLastError.clear(); qDebug() << "CreateAccount Response Received:\nTime: " << mTimer.elapsed(); @@ -316,7 +318,7 @@ void GraftGenericAPI::receiveCreateAccountResponse() if (reply) { connect(reply, &QNetworkReply::finished, - this, &GraftGenericAPI::receiveCreateAccountResponse); + this, &GraftGenericAPIv1::receiveCreateAccountResponse); } else { @@ -325,7 +327,7 @@ void GraftGenericAPI::receiveCreateAccountResponse() } } -void GraftGenericAPI::receiveGetBalanceResponse() +void GraftGenericAPIv1::receiveGetBalanceResponse() { mLastError.clear(); qDebug() << "GetBalance Response Received:\nTime: " << mTimer.elapsed(); @@ -333,8 +335,8 @@ void GraftGenericAPI::receiveGetBalanceResponse() QJsonObject object = processReply(reply); if (!object.isEmpty()) { - emit getBalanceReceived(toCoins(object.value(QLatin1String("Balance")).toDouble()), - toCoins(object.value(QLatin1String("UnlockedBalance")).toDouble())); + emit balanceReceived(toCoins(object.value(QLatin1String("Balance")).toDouble()), + toCoins(object.value(QLatin1String("UnlockedBalance")).toDouble())); } else { @@ -343,7 +345,7 @@ void GraftGenericAPI::receiveGetBalanceResponse() } } -void GraftGenericAPI::receiveGetSeedResponse() +void GraftGenericAPIv1::receiveGetSeedResponse() { mLastError.clear(); qDebug() << "GetSeed Response Received:\nTime: " << mTimer.elapsed(); @@ -359,12 +361,12 @@ void GraftGenericAPI::receiveGetSeedResponse() if (reply) { connect(reply, &QNetworkReply::finished, - this, &GraftGenericAPI::receiveGetSeedResponse); + this, &GraftGenericAPIv1::receiveGetSeedResponse); } } } -void GraftGenericAPI::receiveRestoreAccountResponse() +void GraftGenericAPIv1::receiveRestoreAccountResponse() { mLastError.clear(); qDebug() << "RestoreAccount Response Received:\nTime: " << mTimer.elapsed(); @@ -421,7 +423,7 @@ void GraftGenericAPI::receiveRestoreAccountResponse() if (reply) { connect(reply, &QNetworkReply::finished, - this, &GraftGenericAPI::receiveRestoreAccountResponse); + this, &GraftGenericAPIv1::receiveRestoreAccountResponse); } else { @@ -430,7 +432,7 @@ void GraftGenericAPI::receiveRestoreAccountResponse() } } -void GraftGenericAPI::receiveTransferFeeResponse() +void GraftGenericAPIv1::receiveTransferFeeResponse() { mLastError.clear(); qDebug() << "GetTransferFee Response Received:\nTime: " << mTimer.elapsed(); @@ -447,12 +449,12 @@ void GraftGenericAPI::receiveTransferFeeResponse() if (reply) { connect(reply, &QNetworkReply::finished, - this, &GraftGenericAPI::receiveTransferFeeResponse); + this, &GraftGenericAPIv1::receiveTransferFeeResponse); } } } -void GraftGenericAPI::receiveTransferResponse() +void GraftGenericAPIv1::receiveTransferResponse() { mLastError.clear(); qDebug() << "Transfer Response Received:\nTime: " << mTimer.elapsed(); @@ -468,7 +470,7 @@ void GraftGenericAPI::receiveTransferResponse() if (reply) { connect(reply, &QNetworkReply::finished, - this, &GraftGenericAPI::receiveTransferResponse); + this, &GraftGenericAPIv1::receiveTransferResponse); } } } diff --git a/GraftMobileClient/core/api/graftgenericapi.h b/GraftMobileClient/core/api/v1/graftgenericapiv1.h similarity index 86% rename from GraftMobileClient/core/api/graftgenericapi.h rename to GraftMobileClient/core/api/v1/graftgenericapiv1.h index 5454c2b1..ed026b10 100644 --- a/GraftMobileClient/core/api/graftgenericapi.h +++ b/GraftMobileClient/core/api/v1/graftgenericapiv1.h @@ -1,5 +1,5 @@ -#ifndef GRAFTGENERICAPI_H -#define GRAFTGENERICAPI_H +#ifndef GRAFTGENERICAPIV1_H +#define GRAFTGENERICAPIV1_H #include #include @@ -9,7 +9,7 @@ class QNetworkAccessManager; class QNetworkReply; -class GraftGenericAPI : public QObject +class GraftGenericAPIv1 : public QObject { Q_OBJECT public: @@ -23,9 +23,9 @@ class GraftGenericAPI : public QObject StatusPOSRejected = 5 }; - explicit GraftGenericAPI(const QStringList &addresses, const QString &dapiVersion, - QObject *parent = nullptr); - virtual ~GraftGenericAPI(); + explicit GraftGenericAPIv1(const QStringList &addresses, const QString &dapiVersion, + QObject *parent = nullptr); + virtual ~GraftGenericAPIv1(); void changeAddresses(const QStringList &addresses); void setDAPIVersion(const QString &version); @@ -48,7 +48,7 @@ class GraftGenericAPI : public QObject void error(const QString &message); void createAccountReceived(const QByteArray &accountData, const QString &password, const QString &address, const QString &viewKey, const QString &seed); - void getBalanceReceived(double balance, double unlockedBalance); + void balanceReceived(double balance, double unlockedBalance); void getSeedReceived(const QString &seed); void restoreAccountReceived(const QByteArray &accountData, const QString &password, const QString &address, const QString &viewKey, @@ -89,4 +89,4 @@ private slots: QByteArray mLastRequest; }; -#endif // GRAFTGENERICAPI_H +#endif // GRAFTGENERICAPIV1_H diff --git a/GraftMobileClient/core/api/graftposapi.cpp b/GraftMobileClient/core/api/v1/graftposapiv1.cpp similarity index 74% rename from GraftMobileClient/core/api/graftposapi.cpp rename to GraftMobileClient/core/api/v1/graftposapiv1.cpp index 24cfd64e..8b99a036 100644 --- a/GraftMobileClient/core/api/graftposapi.cpp +++ b/GraftMobileClient/core/api/v1/graftposapiv1.cpp @@ -1,16 +1,17 @@ -#include "graftposapi.h" +#include "graftposapiv1.h" #include #include #include #include #include -GraftPOSAPI::GraftPOSAPI(const QStringList &addresses, const QString &dapiVersion, QObject *parent) - : GraftGenericAPI(addresses, dapiVersion, parent) +GraftPOSAPIv1::GraftPOSAPIv1(const QStringList &addresses, const QString &dapiVersion, + QObject *parent) + : GraftGenericAPIv1(addresses, dapiVersion, parent) { } -void GraftPOSAPI::sale(const QString &address, const QString &viewKey, double amount, +void GraftPOSAPIv1::sale(const QString &address, const QString &viewKey, double amount, const QString &saleDetails) { mRetries = 0; @@ -26,10 +27,10 @@ void GraftPOSAPI::sale(const QString &address, const QString &viewKey, double am qDebug() << array; mLastRequest = array; QNetworkReply *reply = mManager->post(mRequest, array); - connect(reply, &QNetworkReply::finished, this, &GraftPOSAPI::receiveSaleResponse); + connect(reply, &QNetworkReply::finished, this, &GraftPOSAPIv1::receiveSaleResponse); } -void GraftPOSAPI::rejectSale(const QString &pid) +void GraftPOSAPIv1::rejectSale(const QString &pid) { mRetries = 0; QJsonObject params; @@ -39,10 +40,10 @@ void GraftPOSAPI::rejectSale(const QString &pid) mTimer.start(); mLastRequest = array; QNetworkReply *reply = mManager->post(mRequest, array); - connect(reply, &QNetworkReply::finished, this, &GraftPOSAPI::receiveRejectSaleResponse); + connect(reply, &QNetworkReply::finished, this, &GraftPOSAPIv1::receiveRejectSaleResponse); } -void GraftPOSAPI::getSaleStatus(const QString &pid) +void GraftPOSAPIv1::getSaleStatus(const QString &pid) { QJsonObject params; params.insert(QStringLiteral("PaymentID"), pid); @@ -50,10 +51,10 @@ void GraftPOSAPI::getSaleStatus(const QString &pid) QByteArray array = QJsonDocument(data).toJson(); mTimer.start(); QNetworkReply *reply = mManager->post(mRequest, array); - connect(reply, &QNetworkReply::finished, this, &GraftPOSAPI::receiveSaleStatusResponse); + connect(reply, &QNetworkReply::finished, this, &GraftPOSAPIv1::receiveSaleStatusResponse); } -void GraftPOSAPI::receiveSaleResponse() +void GraftPOSAPIv1::receiveSaleResponse() { mLastError.clear(); qDebug() << "Sale Response Received:\nTime: " << mTimer.elapsed(); @@ -70,12 +71,12 @@ void GraftPOSAPI::receiveSaleResponse() QNetworkReply *reply = retry(); if (reply) { - connect(reply, &QNetworkReply::finished, this, &GraftPOSAPI::receiveSaleResponse); + connect(reply, &QNetworkReply::finished, this, &GraftPOSAPIv1::receiveSaleResponse); } } } -void GraftPOSAPI::receiveRejectSaleResponse() +void GraftPOSAPIv1::receiveRejectSaleResponse() { mLastError.clear(); qDebug() << "RejectSale Response Received:\nTime: " << mTimer.elapsed(); @@ -90,12 +91,13 @@ void GraftPOSAPI::receiveRejectSaleResponse() QNetworkReply *reply = retry(); if (reply) { - connect(reply, &QNetworkReply::finished, this, &GraftPOSAPI::receiveRejectSaleResponse); + connect(reply, &QNetworkReply::finished, + this, &GraftPOSAPIv1::receiveRejectSaleResponse); } } } -void GraftPOSAPI::receiveSaleStatusResponse() +void GraftPOSAPIv1::receiveSaleStatusResponse() { qDebug() << "GetSaleStatus Response Received:\nTime: " << mTimer.elapsed(); QNetworkReply *reply = qobject_cast(sender()); diff --git a/GraftMobileClient/core/api/graftposapi.h b/GraftMobileClient/core/api/v1/graftposapiv1.h similarity index 66% rename from GraftMobileClient/core/api/graftposapi.h rename to GraftMobileClient/core/api/v1/graftposapiv1.h index 1580a9c9..fb67d52a 100644 --- a/GraftMobileClient/core/api/graftposapi.h +++ b/GraftMobileClient/core/api/v1/graftposapiv1.h @@ -1,13 +1,14 @@ -#ifndef GRAFTPOSAPI_H -#define GRAFTPOSAPI_H +#ifndef GRAFTPOSAPIV1_H +#define GRAFTPOSAPIV1_H -#include "graftgenericapi.h" +#include "graftgenericapiv1.h" -class GraftPOSAPI : public GraftGenericAPI +class GraftPOSAPIv1 : public GraftGenericAPIv1 { Q_OBJECT public: - explicit GraftPOSAPI(const QStringList &addresses, const QString &dapiVersion, QObject *parent = nullptr); + explicit GraftPOSAPIv1(const QStringList &addresses, const QString &dapiVersion, + QObject *parent = nullptr); void sale(const QString &address, const QString &viewKey, double amount, const QString &saleDetails = QString()); @@ -25,4 +26,4 @@ private slots: void receiveSaleStatusResponse(); }; -#endif // GRAFTPOSAPI_H +#endif // GRAFTPOSAPIV1_H diff --git a/GraftMobileClient/core/api/v1/graftposhandlerv1.cpp b/GraftMobileClient/core/api/v1/graftposhandlerv1.cpp new file mode 100644 index 00000000..afbf2846 --- /dev/null +++ b/GraftMobileClient/core/api/v1/graftposhandlerv1.cpp @@ -0,0 +1,171 @@ +#include "graftposhandlerv1.h" +#include "graftposapiv1.h" + +#include + +GraftPOSHandlerV1::GraftPOSHandlerV1(const QString &dapiVersion, const QStringList addresses, + QObject *parent) + : GraftPOSHandler(parent) +{ + mApi = new GraftPOSAPIv1(addresses, dapiVersion, this); + connect(mApi, &GraftPOSAPIv1::createAccountReceived, + this, &GraftPOSHandlerV1::createAccountReceived); + connect(mApi, &GraftPOSAPIv1::restoreAccountReceived, + this, &GraftPOSHandlerV1::restoreAccountReceived); + connect(mApi, &GraftPOSAPIv1::transferFeeReceived, + this, &GraftPOSHandlerV1::transferFeeReceived); + connect(mApi, &GraftPOSAPIv1::transferReceived, this, &GraftPOSHandlerV1::transferReceived); + connect(mApi, &GraftPOSAPIv1::balanceReceived, this, &GraftPOSHandlerV1::receiveBalance); + + connect(mApi, &GraftPOSAPIv1::saleResponseReceived, this, &GraftPOSHandlerV1::saleReceived); + connect(mApi, &GraftPOSAPIv1::rejectSaleResponseReceived, + this, &GraftPOSHandlerV1::receiveRejectSale); + connect(mApi, &GraftPOSAPIv1::getSaleStatusResponseReceived, + this, &GraftPOSHandlerV1::receiveSaleStatus); + connect(mApi, &GraftPOSAPIv1::error, this, &GraftPOSHandlerV1::errorReceived); +} + +void GraftPOSHandlerV1::changeAddresses(const QStringList &addresses, const QStringList &internalAddresses) +{ + if (mApi) + { + mApi->changeAddresses(addresses); + } +} + +void GraftPOSHandlerV1::setAccountData(const QByteArray &accountData, const QString &password) +{ + if (mApi) + { + mApi->setAccountData(accountData, password); + } +} + +QByteArray GraftPOSHandlerV1::accountData() const +{ + if (mApi) + { + return mApi->accountData(); + } + return QByteArray(); +} + +QString GraftPOSHandlerV1::password() const +{ + if (mApi) + { + return mApi->password(); + } + return QString(); +} + +void GraftPOSHandlerV1::resetData() +{ + +} + +void GraftPOSHandlerV1::createAccount(const QString &password) +{ + if (mApi) + { + mApi->createAccount(password); + } +} + +void GraftPOSHandlerV1::restoreAccount(const QString &seed, const QString &password) +{ + if (mApi) + { + mApi->restoreAccount(seed, password); + } +} + +void GraftPOSHandlerV1::updateBalance() +{ + if (mApi) + { + mApi->getBalance(); + } +} + +void GraftPOSHandlerV1::transferFee(const QString &address, const QString &amount) +{ + if (mApi) + { + mApi->transferFee(address, amount); + } +} + +void GraftPOSHandlerV1::transfer(const QString &address, const QString &amount) +{ + if (mApi) + { + mApi->transfer(address, amount); + } +} + +void GraftPOSHandlerV1::sale(const QString &address, const QString &viewKey, + double amount, const QString &saleDetails) +{ + if (mApi) + { + mApi->sale(address, viewKey, amount, saleDetails); + } +} + +void GraftPOSHandlerV1::rejectSale(const QString &pid) +{ + if (mApi) + { + mApi->rejectSale(pid); + } +} + +void GraftPOSHandlerV1::saleStatus(const QString &pid, int blockNumber) +{ + Q_UNUSED(blockNumber); + if (mApi) + { + mLastPID = pid; + mApi->getSaleStatus(pid); + } +} + +void GraftPOSHandlerV1::receiveRejectSale(int result) +{ + emit rejectSaleReceived(result == 0); +} + +void GraftPOSHandlerV1::receiveSaleStatus(int result, int status) +{ + if (result == 0) + { + switch (status) { + case GraftPOSAPIv1::StatusProcessing: + saleStatus(mLastPID, 0); + break; + case GraftPOSAPIv1::StatusApproved: + mLastPID.clear(); + emit saleStatusReceived(true); + break; + case GraftPOSAPIv1::StatusNone: + case GraftPOSAPIv1::StatusFailed: + case GraftPOSAPIv1::StatusPOSRejected: + case GraftPOSAPIv1::StatusWalletRejected: + default: + mLastPID.clear(); + emit saleStatusReceived(false); + break; + } + } + else + { + emit saleStatusReceived(false); + } +} + +void GraftPOSHandlerV1::receiveBalance(double balance, double unlockedBalance) +{ + QTimer::singleShot(20000, this, &GraftPOSHandlerV1::updateBalance); + emit balanceReceived(balance, unlockedBalance); +} diff --git a/GraftMobileClient/core/api/v1/graftposhandlerv1.h b/GraftMobileClient/core/api/v1/graftposhandlerv1.h new file mode 100644 index 00000000..00673068 --- /dev/null +++ b/GraftMobileClient/core/api/v1/graftposhandlerv1.h @@ -0,0 +1,46 @@ +#ifndef GRAFTPOSHANDLERV1_H +#define GRAFTPOSHANDLERV1_H + +#include "../graftposhandler.h" + +class GraftPOSAPIv1; + +class GraftPOSHandlerV1 : public GraftPOSHandler +{ + Q_OBJECT +public: + explicit GraftPOSHandlerV1(const QString &dapiVersion, const QStringList addresses, + QObject *parent = nullptr); + + void changeAddresses(const QStringList &addresses, + const QStringList &internalAddresses = QStringList()) override; + + void setAccountData(const QByteArray &accountData, const QString &password) override; + QByteArray accountData() const override; + QString password() const override; + + void resetData() override; + +public slots: + void createAccount(const QString &password) override; + void restoreAccount(const QString &seed, const QString &password) override; + void updateBalance() override; + void transferFee(const QString &address, const QString &amount) override; + void transfer(const QString &address, const QString &amount) override; + + void sale(const QString &address, const QString &viewKey, double amount, + const QString &saleDetails = QString()) override; + void rejectSale(const QString &pid) override; + void saleStatus(const QString &pid, int blockNumber) override; + +private slots: + void receiveRejectSale(int result); + void receiveSaleStatus(int result, int status); + void receiveBalance(double balance, double unlockedBalance); + +private: + GraftPOSAPIv1 *mApi; + QString mLastPID; +}; + +#endif // GRAFTPOSHANDLERV1_H diff --git a/GraftMobileClient/core/api/graftwalletapi.cpp b/GraftMobileClient/core/api/v1/graftwalletapiv1.cpp similarity index 80% rename from GraftMobileClient/core/api/graftwalletapi.cpp rename to GraftMobileClient/core/api/v1/graftwalletapiv1.cpp index 04c82786..598c0de7 100644 --- a/GraftMobileClient/core/api/graftwalletapi.cpp +++ b/GraftMobileClient/core/api/v1/graftwalletapiv1.cpp @@ -1,16 +1,16 @@ -#include "graftwalletapi.h" +#include "graftwalletapiv1.h" #include #include #include #include #include -GraftWalletAPI::GraftWalletAPI(const QStringList &addresses, const QString &dapiVersion, QObject *parent) - : GraftGenericAPI(addresses, dapiVersion, parent) +GraftWalletAPIv1::GraftWalletAPIv1(const QStringList &addresses, const QString &dapiVersion, QObject *parent) + : GraftGenericAPIv1(addresses, dapiVersion, parent) { } -void GraftWalletAPI::getPOSData(const QString &pid, int blockNum) +void GraftWalletAPIv1::getPOSData(const QString &pid, int blockNum) { mRetries = 0; QJsonObject params; @@ -21,10 +21,10 @@ void GraftWalletAPI::getPOSData(const QString &pid, int blockNum) mTimer.start(); mLastRequest = array; QNetworkReply *reply = mManager->post(mRequest, array); - connect(reply, &QNetworkReply::finished, this, &GraftWalletAPI::receiveGetPOSDataResponse); + connect(reply, &QNetworkReply::finished, this, &GraftWalletAPIv1::receiveGetPOSDataResponse); } -void GraftWalletAPI::rejectPay(const QString &pid, int blockNum) +void GraftWalletAPIv1::rejectPay(const QString &pid, int blockNum) { mRetries = 0; QJsonObject params; @@ -35,10 +35,10 @@ void GraftWalletAPI::rejectPay(const QString &pid, int blockNum) mTimer.start(); mLastRequest = array; QNetworkReply *reply = mManager->post(mRequest, array); - connect(reply, &QNetworkReply::finished, this, &GraftWalletAPI::receiveRejectPayResponse); + connect(reply, &QNetworkReply::finished, this, &GraftWalletAPIv1::receiveRejectPayResponse); } -void GraftWalletAPI::pay(const QString &pid, const QString &address, double amount, int blockNum) +void GraftWalletAPIv1::pay(const QString &pid, const QString &address, double amount, int blockNum) { mRetries = 0; QJsonObject params; @@ -55,10 +55,10 @@ void GraftWalletAPI::pay(const QString &pid, const QString &address, double amou mTimer.start(); mLastRequest = array; QNetworkReply *reply = mManager->post(mRequest, array); - connect(reply, &QNetworkReply::finished, this, &GraftWalletAPI::receivePayResponse); + connect(reply, &QNetworkReply::finished, this, &GraftWalletAPIv1::receivePayResponse); } -void GraftWalletAPI::getPayStatus(const QString &pid) +void GraftWalletAPIv1::getPayStatus(const QString &pid) { QJsonObject params; params.insert(QStringLiteral("PaymentID"), pid); @@ -66,10 +66,10 @@ void GraftWalletAPI::getPayStatus(const QString &pid) QByteArray array = QJsonDocument(data).toJson(); mTimer.start(); QNetworkReply *reply = mManager->post(mRequest, array); - connect(reply, &QNetworkReply::finished, this, &GraftWalletAPI::receivePayStatusResponse); + connect(reply, &QNetworkReply::finished, this, &GraftWalletAPIv1::receivePayStatusResponse); } -void GraftWalletAPI::receiveGetPOSDataResponse() +void GraftWalletAPIv1::receiveGetPOSDataResponse() { mLastError.clear(); qDebug() << "GetPOSData Response Received:\nTime: " << mTimer.elapsed(); @@ -86,12 +86,12 @@ void GraftWalletAPI::receiveGetPOSDataResponse() if (reply) { connect(reply, &QNetworkReply::finished, this, - &GraftWalletAPI::receiveGetPOSDataResponse); + &GraftWalletAPIv1::receiveGetPOSDataResponse); } } } -void GraftWalletAPI::receiveRejectPayResponse() +void GraftWalletAPIv1::receiveRejectPayResponse() { mLastError.clear(); qDebug() << "RejectPay Response Received:\nTime: " << mTimer.elapsed(); @@ -107,12 +107,12 @@ void GraftWalletAPI::receiveRejectPayResponse() if (reply) { connect(reply, &QNetworkReply::finished, this, - &GraftWalletAPI::receiveRejectPayResponse); + &GraftWalletAPIv1::receiveRejectPayResponse); } } } -void GraftWalletAPI::receivePayResponse() +void GraftWalletAPIv1::receivePayResponse() { mLastError.clear(); qDebug() << "Pay Response Received:\nTime: " << mTimer.elapsed(); @@ -127,12 +127,12 @@ void GraftWalletAPI::receivePayResponse() QNetworkReply *reply = retry(); if (reply) { - connect(reply, &QNetworkReply::finished, this, &GraftWalletAPI::receivePayResponse); + connect(reply, &QNetworkReply::finished, this, &GraftWalletAPIv1::receivePayResponse); } } } -void GraftWalletAPI::receivePayStatusResponse() +void GraftWalletAPIv1::receivePayStatusResponse() { qDebug() << "GetPayStatus Response Received:\nTime: " << mTimer.elapsed(); QNetworkReply *reply = qobject_cast(sender()); diff --git a/GraftMobileClient/core/api/graftwalletapi.h b/GraftMobileClient/core/api/v1/graftwalletapiv1.h similarity index 67% rename from GraftMobileClient/core/api/graftwalletapi.h rename to GraftMobileClient/core/api/v1/graftwalletapiv1.h index f4900de4..59ff981f 100644 --- a/GraftMobileClient/core/api/graftwalletapi.h +++ b/GraftMobileClient/core/api/v1/graftwalletapiv1.h @@ -1,14 +1,14 @@ -#ifndef GRAFTWALLETAPI_H -#define GRAFTWALLETAPI_H +#ifndef GRAFTWALLETAPIV1_H +#define GRAFTWALLETAPIV1_H -#include "graftgenericapi.h" +#include "graftgenericapiv1.h" -class GraftWalletAPI : public GraftGenericAPI +class GraftWalletAPIv1 : public GraftGenericAPIv1 { Q_OBJECT public: - explicit GraftWalletAPI(const QStringList &addresses, const QString &dapiVersion, - QObject *parent = nullptr); + explicit GraftWalletAPIv1(const QStringList &addresses, const QString &dapiVersion, + QObject *parent = nullptr); void getPOSData(const QString &pid, int blockNum); void rejectPay(const QString &pid, int blockNum); @@ -28,4 +28,4 @@ private slots: void receivePayStatusResponse(); }; -#endif // GRAFTWALLETAPI_H +#endif // GRAFTWALLETAPIV1_H diff --git a/GraftMobileClient/core/api/v1/graftwallethandlerv1.cpp b/GraftMobileClient/core/api/v1/graftwallethandlerv1.cpp new file mode 100644 index 00000000..a1e3f94d --- /dev/null +++ b/GraftMobileClient/core/api/v1/graftwallethandlerv1.cpp @@ -0,0 +1,150 @@ +#include "graftwallethandlerv1.h" +#include "graftwalletapiv1.h" + +#include + +GraftWalletHandlerV1::GraftWalletHandlerV1(const QString &dapiVersion, const QStringList addresses, + QObject *parent) + : GraftWalletHandler(parent) +{ + mApi = new GraftWalletAPIv1(addresses, dapiVersion, this); + connect(mApi, &GraftWalletAPIv1::createAccountReceived, + this, &GraftWalletHandlerV1::createAccountReceived); + connect(mApi, &GraftWalletAPIv1::restoreAccountReceived, + this, &GraftWalletHandlerV1::restoreAccountReceived); + connect(mApi, &GraftWalletAPIv1::transferFeeReceived, + this, &GraftWalletHandlerV1::transferFeeReceived); + connect(mApi, &GraftWalletAPIv1::transferReceived, + this, &GraftWalletHandlerV1::transferReceived); + connect(mApi, &GraftWalletAPIv1::balanceReceived, this, &GraftWalletHandlerV1::receiveBalance); + + connect(mApi, &GraftWalletAPIv1::getPOSDataReceived, + this, &GraftWalletHandlerV1::saleDetailsReceived); + connect(mApi, &GraftWalletAPIv1::rejectPayReceived, + this, &GraftWalletHandlerV1::rejectPayReceived); + connect(mApi, &GraftWalletAPIv1::payReceived, this, &GraftWalletHandlerV1::payReceived); + connect(mApi, &GraftWalletAPIv1::getPayStatusReceived, + this, &GraftWalletHandlerV1::payStatusReceived); + connect(mApi, &GraftWalletAPIv1::error, this, &GraftWalletHandlerV1::errorReceived); +} + +void GraftWalletHandlerV1::changeAddresses(const QStringList &addresses, + const QStringList &internalAddresses) +{ + Q_UNUSED(internalAddresses); + if (mApi) + { + mApi->changeAddresses(addresses); + } +} + +void GraftWalletHandlerV1::setAccountData(const QByteArray &accountData, const QString &password) +{ + if (mApi) + { + mApi->setAccountData(accountData, password); + } +} + +QByteArray GraftWalletHandlerV1::accountData() const +{ + if (mApi) + { + return mApi->accountData(); + } + return QByteArray(); +} + +QString GraftWalletHandlerV1::password() const +{ + if (mApi) + { + return mApi->password(); + } + return QString(); +} + +void GraftWalletHandlerV1::resetData() +{ + +} + +void GraftWalletHandlerV1::createAccount(const QString &password) +{ + if (mApi) + { + mApi->createAccount(password); + } +} + +void GraftWalletHandlerV1::restoreAccount(const QString &seed, const QString &password) +{ + if (mApi) + { + mApi->restoreAccount(seed, password); + } +} + +void GraftWalletHandlerV1::updateBalance() +{ + if (mApi) + { + mApi->getBalance(); + } +} + +void GraftWalletHandlerV1::transferFee(const QString &address, const QString &amount) +{ + if (mApi) + { + mApi->transferFee(address, amount); + } +} + +void GraftWalletHandlerV1::transfer(const QString &address, const QString &amount) +{ + if (mApi) + { + mApi->transfer(address, amount); + } +} + +void GraftWalletHandlerV1::saleDetails(const QString &pid, int blockNumber) +{ + if (mApi) + { + mApi->getPOSData(pid, blockNumber); + } +} + +void GraftWalletHandlerV1::rejectPay(const QString &pid, int blockNumber) +{ + if (mApi) + { + mApi->rejectPay(pid, blockNumber); + } +} + +void GraftWalletHandlerV1::pay(const QString &pid, const QString &address, double amount, + int blockNumber) +{ + if (mApi) + { + mApi->pay(pid, address, amount, blockNumber); + } +} + +void GraftWalletHandlerV1::payStatus(const QString &pid, int blockNumber) +{ + Q_UNUSED(blockNumber); + if (mApi) + { + mApi->getPayStatus(pid); + } +} + +void GraftWalletHandlerV1::receiveBalance(double balance, double unlockedBalance) +{ + QTimer::singleShot(20000, this, &GraftWalletHandlerV1::updateBalance); + emit balanceReceived(balance, unlockedBalance); +} diff --git a/GraftMobileClient/core/api/v1/graftwallethandlerv1.h b/GraftMobileClient/core/api/v1/graftwallethandlerv1.h new file mode 100644 index 00000000..1ea9ec28 --- /dev/null +++ b/GraftMobileClient/core/api/v1/graftwallethandlerv1.h @@ -0,0 +1,43 @@ +#ifndef GRAFTWALLETHANDLERV1_H +#define GRAFTWALLETHANDLERV1_H + +#include "../graftwallethandler.h" + +class GraftWalletAPIv1; + +class GraftWalletHandlerV1 : public GraftWalletHandler +{ + Q_OBJECT +public: + explicit GraftWalletHandlerV1(const QString &dapiVersion, const QStringList addresses, + QObject *parent = nullptr); + + void changeAddresses(const QStringList &addresses, + const QStringList &internalAddresses = QStringList()) override; + + void setAccountData(const QByteArray &accountData, const QString &password) override; + QByteArray accountData() const override; + QString password() const override; + + void resetData() override; + +public slots: + void createAccount(const QString &password) override; + void restoreAccount(const QString &seed, const QString &password) override; + void updateBalance() override; + void transferFee(const QString &address, const QString &amount) override; + void transfer(const QString &address, const QString &amount) override; + + void saleDetails(const QString &pid, int blockNumber) override; + void rejectPay(const QString &pid, int blockNumber) override; + void pay(const QString &pid, const QString &address, double amount, int blockNumber) override; + void payStatus(const QString &pid, int blockNumber) override; + +private slots: + void receiveBalance(double balance, double unlockedBalance); + +private: + GraftWalletAPIv1 *mApi; +}; + +#endif // GRAFTWALLETHANDLERV1_H diff --git a/GraftMobileClient/core/api/v2/graftapiv2.pri b/GraftMobileClient/core/api/v2/graftapiv2.pri new file mode 100644 index 00000000..22ce2b70 --- /dev/null +++ b/GraftMobileClient/core/api/v2/graftapiv2.pri @@ -0,0 +1,30 @@ +contains(DEFINES, POS_BUILD) { + +SOURCES += \ + $$PWD/graftposapiv2.cpp \ + $$PWD/graftposhandlerv2.cpp + +HEADERS += \ + $$PWD/graftposapiv2.h \ + $$PWD/graftposhandlerv2.h +} + +contains(DEFINES, WALLET_BUILD) { +SOURCES += \ + $$PWD/graftwalletapiv2.cpp \ + $$PWD/graftwallethandlerv2.cpp + +HEADERS += \ + $$PWD/graftwalletapiv2.h \ + $$PWD/graftwallethandlerv2.h +} + +SOURCES += \ + $$PWD/graftgenericapiv2.cpp \ + $$PWD/graftwallet.cpp \ + $$PWD/graftwalletlistener.cpp + +HEADERS += \ + $$PWD/graftgenericapiv2.h \ + $$PWD/graftwallet.h \ + $$PWD/graftwalletlistener.h diff --git a/GraftMobileClient/core/api/v2/graftgenericapiv2.cpp b/GraftMobileClient/core/api/v2/graftgenericapiv2.cpp new file mode 100644 index 00000000..fb49aa6a --- /dev/null +++ b/GraftMobileClient/core/api/v2/graftgenericapiv2.cpp @@ -0,0 +1,164 @@ +#include "graftgenericapiv2.h" +#include +#include +#include +#include +#include "../../config.h" + +GraftGenericAPIv2::GraftGenericAPIv2(const QStringList &addresses, const QString &dapiVersion, + QObject *parent) + : QObject(parent) + ,mDAPIVersion(dapiVersion) +{ + mRetries = 0; + mCurrentAddress = -1; + mAddresses = addresses; + mManager = new QNetworkAccessManager(this); + mRequest = QNetworkRequest(nextAddress()); + mRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); +} + +GraftGenericAPIv2::~GraftGenericAPIv2() +{ +} + +void GraftGenericAPIv2::changeAddresses(const QStringList &addresses) +{ + mAddresses = addresses; + mCurrentAddress = -1; + mRequest.setUrl(nextAddress()); +} + +void GraftGenericAPIv2::setDAPIVersion(const QString &version) +{ + mDAPIVersion = version; +} + +void GraftGenericAPIv2::setAccountData(const QByteArray &accountData, const QString &password) +{ + mAccountData = accountData; + mPassword = password; +} + +QByteArray GraftGenericAPIv2::accountData() const +{ + return mAccountData; +} + +QString GraftGenericAPIv2::password() const +{ + return mPassword; +} + +double GraftGenericAPIv2::toCoins(double atomic) +{ + return (1.0 * atomic) / 10000000000.0; +} + +double GraftGenericAPIv2::toCoins(uint64_t atomic) +{ + return (1.0 * atomic) / 10000000000.0; +} + +double GraftGenericAPIv2::toAtomic(double coins) +{ + return coins * 10000000000; +} + +uint64_t GraftGenericAPIv2::toAtomic(const QString &coins) +{ + return coins.toDouble() * 10000000000; +} + +QString GraftGenericAPIv2::accountPlaceholder() const +{ + return QString("????"); +} + +QByteArray GraftGenericAPIv2::serializeAmount(double amount) const +{ + QByteArray serializedAmount; + serializedAmount.setNum(toAtomic(amount), 'f', 0); + return serializedAmount; +} + +QJsonObject GraftGenericAPIv2::buildMessage(const QString &key, const QJsonObject ¶ms) const +{ + QJsonObject data; + data.insert(QStringLiteral("jsonrpc"), QStringLiteral("2.0")); + data.insert(QStringLiteral("id"), QStringLiteral("0")); + data.insert(QStringLiteral("method"), key); + data.insert(QStringLiteral("dapi_version"), mDAPIVersion); + if (!params.isEmpty()) + { + data.insert(QStringLiteral("params"), params); + } + return data; +} + +QJsonObject GraftGenericAPIv2::processReply(QNetworkReply *reply) +{ + QJsonObject object; + if (reply->error() == QNetworkReply::NoError) + { + QByteArray rawData = reply->readAll(); + qDebug() << rawData; + if (!rawData.isEmpty()) + { + QJsonObject response = QJsonDocument::fromJson(rawData).object(); + qDebug() << response.toVariantMap(); + if (response.contains(QLatin1String("result"))) + { + object = response.value(QLatin1String("result")).toObject(); + } + else + { + mLastError = QLatin1String("Response error"); + } + } + else + { + mLastError = QLatin1String("Couldn't parse request response."); + } + } + else + { + mLastError = reply->errorString(); + } + reply->deleteLater(); + reply = nullptr; + return object; +} + +QUrl GraftGenericAPIv2::nextAddress(const QString &endpoint) +{ + mCurrentAddress++; + if (mCurrentAddress >= mAddresses.count()) + { + mCurrentAddress = 0; + } + if (endpoint.isEmpty()) + { + return QUrl(scUrl.arg(mAddresses.value(mCurrentAddress))); + } + else + { + return QUrl(scDapiUrl.arg(mAddresses.value(mCurrentAddress)).arg(endpoint)); + } +} + +QNetworkReply *GraftGenericAPIv2::retry() +{ + if (mRetries < mAddresses.count() - 1) + { + mRetries++; + mRequest.setUrl(nextAddress()); + return mManager->post(mRequest, mLastRequest); + } + else + { + mRetries = 0; + emit error(QString("Services cannot process request. Reason: %1").arg(mLastError)); + } + return nullptr; +} diff --git a/GraftMobileClient/core/api/v2/graftgenericapiv2.h b/GraftMobileClient/core/api/v2/graftgenericapiv2.h new file mode 100644 index 00000000..f386e807 --- /dev/null +++ b/GraftMobileClient/core/api/v2/graftgenericapiv2.h @@ -0,0 +1,71 @@ +#ifndef GRAFTGENERICAPIV2_H +#define GRAFTGENERICAPIV2_H + +#include +#include +#include +#include + +class QNetworkAccessManager; +class QNetworkReply; + +class GraftGenericAPIv2 : public QObject +{ + Q_OBJECT +public: + enum OperationStatus + { + StatusNone = 0, + StatusWaiting = 1, + StatusProcessing = 2, + StatusSuccess = 3, + StatusFailed = 4, + StatusWalletRejected = 5, + StatusPOSRejected = 6 + }; + + explicit GraftGenericAPIv2(const QStringList &addresses, const QString &dapiVersion, + QObject *parent = nullptr); + virtual ~GraftGenericAPIv2(); + + void changeAddresses(const QStringList &addresses); + void setDAPIVersion(const QString &version); + + void setAccountData(const QByteArray &accountData, const QString &password); + QByteArray accountData() const; + QString password() const; + + static double toCoins(double atomic); + static double toCoins(uint64_t atomic); + static double toAtomic(double coins); + static uint64_t toAtomic(const QString &coins); + +signals: + void error(const QString &message); + +protected: + QString accountPlaceholder() const; + QByteArray serializeAmount(double amount) const; + QJsonObject buildMessage(const QString &key, const QJsonObject ¶ms = QJsonObject()) const; + QJsonObject processReply(QNetworkReply *reply); + QUrl nextAddress(const QString &endpoint = QString()); + QNetworkReply *retry(); + +protected: + QNetworkAccessManager *mManager; + QNetworkRequest mRequest; + QElapsedTimer mTimer; + QStringList mAddresses; + int mCurrentAddress; + + QByteArray mAccountData; + QString mPassword; + + QString mDAPIVersion; + + QString mLastError; + int mRetries; + QByteArray mLastRequest; +}; + +#endif // GRAFTGENERICAPIV2_H diff --git a/GraftMobileClient/core/api/v2/graftposapiv2.cpp b/GraftMobileClient/core/api/v2/graftposapiv2.cpp new file mode 100644 index 00000000..546b3d18 --- /dev/null +++ b/GraftMobileClient/core/api/v2/graftposapiv2.cpp @@ -0,0 +1,108 @@ +#include "graftposapiv2.h" +#include +#include +#include +#include +#include + +GraftPOSAPIv2::GraftPOSAPIv2(const QStringList &addresses, const QString &dapiVersion, + QObject *parent) + : GraftGenericAPIv2(addresses, dapiVersion, parent) +{ +} + +void GraftPOSAPIv2::sale(const QString &address, double amount, const QString &saleDetails) +{ + mRetries = 0; + mRequest.setUrl(nextAddress(QStringLiteral("sale"))); + QJsonObject params; + params.insert(QStringLiteral("Address"), address); + params.insert(QStringLiteral("SaleDetails"), saleDetails); + params.insert(QStringLiteral("Amount"), -666); + QJsonObject data = buildMessage(QStringLiteral("sale"), params); + QByteArray array = QJsonDocument(data).toJson(); + array.replace("-666", serializeAmount(amount)); + mTimer.start(); + qDebug() << array; + mLastRequest = array; + QNetworkReply *reply = mManager->post(mRequest, array); + connect(reply, &QNetworkReply::finished, this, &GraftPOSAPIv2::receiveSaleResponse); +} + +void GraftPOSAPIv2::rejectSale(const QString &pid) +{ + mRetries = 0; + QJsonObject params; + params.insert(QStringLiteral("PaymentID"), pid); + QJsonObject data = buildMessage(QStringLiteral("PosRejectSale"), params); + QByteArray array = QJsonDocument(data).toJson(); + mTimer.start(); + mLastRequest = array; + QNetworkReply *reply = mManager->post(mRequest, array); + connect(reply, &QNetworkReply::finished, this, &GraftPOSAPIv2::receiveRejectSaleResponse); +} + +void GraftPOSAPIv2::saleStatus(const QString &pid, int blockNumber) +{ + mRequest.setUrl(nextAddress(QStringLiteral("sale_status"))); + QJsonObject params; + params.insert(QStringLiteral("PaymentID"), pid); + params.insert(QStringLiteral("BlockNumber"), blockNumber); + QJsonObject data = buildMessage(QStringLiteral("sale_status"), params); + QByteArray array = QJsonDocument(data).toJson(); + mTimer.start(); + QNetworkReply *reply = mManager->post(mRequest, array); + connect(reply, &QNetworkReply::finished, this, &GraftPOSAPIv2::receiveSaleStatusResponse); +} + +void GraftPOSAPIv2::receiveSaleResponse() +{ + mLastError.clear(); + qDebug() << "Sale Response Received:\nTime: " << mTimer.elapsed(); + QNetworkReply *reply = qobject_cast(sender()); + QJsonObject object = processReply(reply); + if (!object.isEmpty()) + { + emit saleResponseReceived(object.value(QLatin1String("PaymentID")).toString(), + object.value(QLatin1String("BlockNumber")).toInt()); + } + else + { + QNetworkReply *reply = retry(); + if (reply) + { + connect(reply, &QNetworkReply::finished, this, &GraftPOSAPIv2::receiveSaleResponse); + } + } +} + +void GraftPOSAPIv2::receiveRejectSaleResponse() +{ + mLastError.clear(); + qDebug() << "RejectSale Response Received:\nTime: " << mTimer.elapsed(); + QNetworkReply *reply = qobject_cast(sender()); + QJsonObject object = processReply(reply); + if (!object.isEmpty()) + { + emit rejectSaleResponseReceived(object.value(QLatin1String("Result")).toInt()); + } + else + { + QNetworkReply *reply = retry(); + if (reply) + { + connect(reply, &QNetworkReply::finished, this, &GraftPOSAPIv2::receiveRejectSaleResponse); + } + } +} + +void GraftPOSAPIv2::receiveSaleStatusResponse() +{ + qDebug() << "SaleStatus Response Received:\nTime: " << mTimer.elapsed(); + QNetworkReply *reply = qobject_cast(sender()); + QJsonObject object = processReply(reply); + if (!object.isEmpty()) + { + emit saleStatusResponseReceived(object.value(QLatin1String("Status")).toInt()); + } +} diff --git a/GraftMobileClient/core/api/v2/graftposapiv2.h b/GraftMobileClient/core/api/v2/graftposapiv2.h new file mode 100644 index 00000000..b0a5f61c --- /dev/null +++ b/GraftMobileClient/core/api/v2/graftposapiv2.h @@ -0,0 +1,28 @@ +#ifndef GRAFTPOSAPIV2_H +#define GRAFTPOSAPIV2_H + +#include "graftgenericapiv2.h" + +class GraftPOSAPIv2 : public GraftGenericAPIv2 +{ + Q_OBJECT +public: + explicit GraftPOSAPIv2(const QStringList &addresses, const QString &dapiVersion, + QObject *parent = nullptr); + + void sale(const QString &address, double amount, const QString &saleDetails = QString()); + void rejectSale(const QString &pid); + void saleStatus(const QString &pid, int blockNumber); + +signals: + void saleResponseReceived(const QString &pid, int blockNumber); + void rejectSaleResponseReceived(int result); + void saleStatusResponseReceived(int status); + +private slots: + void receiveSaleResponse(); + void receiveRejectSaleResponse(); + void receiveSaleStatusResponse(); +}; + +#endif // GRAFTPOSAPIV2_H diff --git a/GraftMobileClient/core/api/v2/graftposhandlerv2.cpp b/GraftMobileClient/core/api/v2/graftposhandlerv2.cpp new file mode 100644 index 00000000..aeac7e06 --- /dev/null +++ b/GraftMobileClient/core/api/v2/graftposhandlerv2.cpp @@ -0,0 +1,210 @@ +#include "../../graftclienttools.h" +#include "graftposhandlerv2.h" +#include "graftposapiv2.h" +#include "graftwallet.h" + +GraftPOSHandlerV2::GraftPOSHandlerV2(const QString &dapiVersion, const QStringList &addresses, + const QStringList &internalAddresses, bool testnet, + QObject *parent) + : GraftPOSHandler(parent) + ,mBlockNumber(0) + ,tRetryStatus(false) +{ + mApi = new GraftPOSAPIv2(addresses, dapiVersion, this); + connect(mApi, &GraftPOSAPIv2::saleResponseReceived, this, &GraftPOSHandlerV2::receiveSale); + connect(mApi, &GraftPOSAPIv2::rejectSaleResponseReceived, + this, &GraftPOSHandlerV2::receiveRejectSale); + connect(mApi, &GraftPOSAPIv2::saleStatusResponseReceived, + this, &GraftPOSHandlerV2::receiveSaleStatus); + connect(mApi, &GraftPOSAPIv2::error, this, &GraftPOSHandlerV2::errorReceived); + mWallet = new GraftWallet(this); + mWallet->setTestnet(testnet); + mWallet->changeAddresses(internalAddresses); + connect(mWallet, &GraftWallet::refreshed, this, &GraftPOSHandlerV2::receiveBalance); + connect(mWallet, &GraftWallet::transactionPrepared, + this, &GraftPOSHandlerV2::receiveTransaction); +} + +void GraftPOSHandlerV2::changeAddresses(const QStringList &addresses, + const QStringList &internalAddresses) +{ + if (mApi) + { + mApi->changeAddresses(addresses); + } + if (mWallet) + { + mWallet->changeAddresses(internalAddresses); + } +} + +void GraftPOSHandlerV2::setAccountData(const QByteArray &accountData, const QString &password) +{ + if (mApi) + { + mApi->setAccountData(accountData, password); + } + if (mWallet) + { + mWallet->restoreWallet(accountData, password); + } +} + +QByteArray GraftPOSHandlerV2::accountData() const +{ + if (mApi) + { + return mApi->accountData(); + } + return QByteArray(); +} + +QString GraftPOSHandlerV2::password() const +{ + if (mApi) + { + return mApi->password(); + } + return QString(); +} + +void GraftPOSHandlerV2::resetData() +{ + mWallet->closeWallet(); + mWallet->removeCache(); +} + +void GraftPOSHandlerV2::createAccount(const QString &password) +{ + if (mWallet) + { + bool isAccountCreated = mWallet->createWallet(password); + if (isAccountCreated) + { + updateBalance(); + } + emit createAccountReceived(mWallet->accountData(), password, mWallet->publicAddress(), + mWallet->privateViewKey(), mWallet->seed()); + } +} + +void GraftPOSHandlerV2::restoreAccount(const QString &seed, const QString &password) +{ + if (mWallet) + { + bool isAccountRestored = mWallet->restoreWallet(seed.toLower(), password); + if (isAccountRestored) + { + updateBalance(); + } + emit restoreAccountReceived(mWallet->accountData(), password, mWallet->publicAddress(), + mWallet->privateViewKey(), mWallet->seed()); + } +} + +void GraftPOSHandlerV2::updateBalance() +{ + if (mWallet) + { + mWallet->startRefresh(); + } +} + +void GraftPOSHandlerV2::transferFee(const QString &address, const QString &amount) +{ + if (mWallet) + { + mWallet->prepareTransactionAsync(address, GraftGenericAPIv2::toAtomic(amount)); + } +} + +void GraftPOSHandlerV2::transfer(const QString &address, const QString &amount) +{ + if (mWallet) + { + bool status = mWallet->sendCurrentTransaction(); + emit transferReceived(status); + } +} + +void GraftPOSHandlerV2::sale(const QString &address, const QString &viewKey, double amount, + const QString &saleDetails) +{ + if (mApi) + { + mApi->sale(address, amount, saleDetails); + } +} + +void GraftPOSHandlerV2::rejectSale(const QString &pid) +{ +// if (mApi) +// { +// mApi->rejectSale(pid); +// } + tRetryStatus = false; +} + +void GraftPOSHandlerV2::saleStatus(const QString &pid, int blockNumber) +{ + if (mApi && tRetryStatus) + { + mLastPID = pid; + mBlockNumber = blockNumber; + mApi->saleStatus(pid, blockNumber); + } +} + +void GraftPOSHandlerV2::receiveBalance() +{ + if (mWallet) + { + double lockedBalance = GraftGenericAPIv2::toCoins(mWallet->lockedBalance()); + double unlockedBalance = GraftGenericAPIv2::toCoins(mWallet->unlockedBalance()); + emit balanceReceived(lockedBalance + unlockedBalance, unlockedBalance); + } +} + +void GraftPOSHandlerV2::receiveTransaction(bool result) +{ + if (mWallet) + { + double lFee = 0; + if (result) + { + lFee = GraftGenericAPIv2::toCoins(mWallet->currentTransactionFee()); + } + emit transferFeeReceived(result, lFee); + } +} + +void GraftPOSHandlerV2::receiveSale(const QString &pid, int blockNumber) +{ + tRetryStatus = true; + emit saleReceived(0, pid, blockNumber); +} + +void GraftPOSHandlerV2::receiveRejectSale(int result) +{ + emit rejectSaleReceived(result == 0); +} + +void GraftPOSHandlerV2::receiveSaleStatus(int status) +{ + switch (status) { + case GraftPOSAPIv2::StatusWaiting: + case GraftPOSAPIv2::StatusProcessing: + saleStatus(mLastPID, mBlockNumber); + break; + case GraftPOSAPIv2::StatusSuccess: + emit saleStatusReceived(true); + break; + case GraftPOSAPIv2::StatusNone: + case GraftPOSAPIv2::StatusFailed: + case GraftPOSAPIv2::StatusPOSRejected: + case GraftPOSAPIv2::StatusWalletRejected: + default: + emit saleStatusReceived(false); + break; + } +} diff --git a/GraftMobileClient/core/api/v2/graftposhandlerv2.h b/GraftMobileClient/core/api/v2/graftposhandlerv2.h new file mode 100644 index 00000000..c3252c0c --- /dev/null +++ b/GraftMobileClient/core/api/v2/graftposhandlerv2.h @@ -0,0 +1,54 @@ +#ifndef GRAFTPOSHANDLERV2_H +#define GRAFTPOSHANDLERV2_H + +#include "../graftposhandler.h" + +class GraftPOSAPIv2; +class GraftWallet; + +class GraftPOSHandlerV2 : public GraftPOSHandler +{ + Q_OBJECT +public: + explicit GraftPOSHandlerV2(const QString &dapiVersion, const QStringList &addresses, + const QStringList &internalAddresses, bool testnet = false, + QObject *parent = nullptr); + + void changeAddresses(const QStringList &addresses, + const QStringList &internalAddresses = QStringList()) override; + + void setAccountData(const QByteArray &accountData, const QString &password) override; + QByteArray accountData() const override; + QString password() const override; + + void resetData() override; + +public slots: + void createAccount(const QString &password) override; + void restoreAccount(const QString &seed, const QString &password) override; + void updateBalance() override; + void transferFee(const QString &address, const QString &amount) override; + void transfer(const QString &address, const QString &amount) override; + + void sale(const QString &address, const QString &viewKey, double amount, + const QString &saleDetails = QString()) override; + void rejectSale(const QString &pid) override; + void saleStatus(const QString &pid, int blockNumber) override; + +private slots: + void receiveBalance(); + void receiveTransaction(bool result); + void receiveSale(const QString &pid, int blockNumber); + void receiveRejectSale(int result); + void receiveSaleStatus(int status); + +private: + GraftWallet *mWallet; + GraftPOSAPIv2 *mApi; + QString mLastPID; + int mBlockNumber; + //TODO: Temporary + bool tRetryStatus; +}; + +#endif // GRAFTPOSHANDLERV2_H diff --git a/GraftMobileClient/core/api/v2/graftwallet.cpp b/GraftMobileClient/core/api/v2/graftwallet.cpp new file mode 100644 index 00000000..0d9dc3d1 --- /dev/null +++ b/GraftMobileClient/core/api/v2/graftwallet.cpp @@ -0,0 +1,443 @@ +#include "graftwalletlistener.h" +#include "graftwallet.h" +#include +#include +#include +#include +#include +#include + +static const QString scWalletCacheFile("accountCache.dat"); +static const std::string scLanguage("English"); +static const uint64_t scUpperTransLimit(0); + +GraftWallet::GraftWallet(QObject *parent) + : QObject(parent) + ,mTestnet(true) + ,mWallet(nullptr) + ,mListener(new GraftWalletListener(this)) + ,mCurrentTransaction(nullptr) + ,mCurrentAddress(-1) +{ + Monero::WalletManagerFactory::setLogLevel(Monero::WalletManagerFactory::LogLevel_Max); + mManager = Monero::WalletManagerFactory::getWalletManager(); +} + +GraftWallet::~GraftWallet() +{ + closeWallet(); +// delete mManager; + delete mListener; +} + +void GraftWallet::setTestnet(bool t) +{ + mTestnet = t; +} + +bool GraftWallet::isTestnet() const +{ + return mTestnet; +} + +void GraftWallet::changeAddresses(const QStringList &addresses) +{ + mAddresses = addresses; + mCurrentAddress = -1; + if (mWallet) + { + mWallet->init(nextAddress().toStdString(), scUpperTransLimit); + } +} + +bool GraftWallet::createWallet(const QString &password) +{ + if (!mWallet) + { + mWallet = mManager->createNewWallet(password.toStdString(), scLanguage, mTestnet); + if (mWallet) + { + mWallet->setListener(mListener); + mWallet->init(nextAddress().toStdString(), scUpperTransLimit); + saveCache(); + return true; + } + } + return false; +} + +bool GraftWallet::restoreWallet(const QString &seed, const QString &password) +{ + if (!mWallet) + { + mWallet = mManager->restoreWallet(seed.toStdString(), mTestnet); + if (mWallet) + { + mWallet->setListener(mListener); + mWallet->init(nextAddress().toStdString(), scUpperTransLimit); + saveCache(); + return true; + } + } + return false; +} + +bool GraftWallet::restoreWallet(const QByteArray &data, const QString &password) +{ + if (!mWallet) + { + mWallet = mManager->createWalletFromData(data.toStdString(), password.toStdString(), + mTestnet, cacheFilePath().toStdString()); + if (mWallet) + { + mWallet->setListener(mListener); + mWallet->setSeedLanguage(scLanguage); + mWallet->init(nextAddress().toStdString(), scUpperTransLimit); + saveCache(); + return true; + } + } + return false; +} + +QString GraftWallet::seed() const +{ + if (mWallet) + { + return QString::fromStdString(mWallet->seed()); + } + return QString(); +} + +QString GraftWallet::publicAddress() const +{ + if (mWallet) + { + return QString::fromStdString(mWallet->address()); + } + return QString(); +} + +QByteArray GraftWallet::accountData() const +{ + if (mWallet) + { + return QByteArray::fromStdString(mWallet->getWalletData("")); + } + return QByteArray(); +} + +QString GraftWallet::publicViewKey() const +{ + if (mWallet) + { + return QString::fromStdString(mWallet->publicViewKey()); + } + return QString(); +} + +QString GraftWallet::privateViewKey() const +{ + if (mWallet) + { + return QString::fromStdString(mWallet->secretViewKey()); + } + return QString(); +} + +QString GraftWallet::publicSpendKey() const +{ + if (mWallet) + { + return QString::fromStdString(mWallet->publicSpendKey()); + } + return QString(); +} + +QString GraftWallet::privateSpendKey() const +{ + if (mWallet) + { + return QString::fromStdString(mWallet->secretSpendKey()); + } + return QString(); +} + +uint64_t GraftWallet::balance() const +{ + if (mWallet) + { + return mWallet->balance(); + } + return 0; +} + +uint64_t GraftWallet::unlockedBalance() const +{ + if (mWallet) + { + return mWallet->unlockedBalance(); + } + return 0; +} + +uint64_t GraftWallet::lockedBalance() const +{ + if (mWallet) + { + return mWallet->balance() - mWallet->unlockedBalance(); + } + return 0; +} + +bool GraftWallet::prepareTransaction(const QString &address, uint64_t amount) +{ + if (mWallet) + { + closeCurrentTransaction(); + mCurrentTransaction = mWallet->createTransaction(address.toStdString(), std::string(), + amount, 0); + mLastError = QString::fromStdString(mWallet->errorString()); + return mCurrentTransaction->status() == Monero::PendingTransaction::Status_Ok; + } + return false; +} + +bool GraftWallet::prepareTransactionAsync(const QString &address, uint64_t amount) +{ + if (mWallet) + { + closeCurrentTransaction(); + QFuture future = QtConcurrent::run(this, &GraftWallet::prepareTransaction, + address, amount); + QFutureWatcher *watcher = new QFutureWatcher(); + connect(watcher, &QFutureWatcher::finished, this, [this, watcher]() { + QFuture future = watcher->future(); + watcher->deleteLater(); + emit transactionPrepared(future.result()); + }); + watcher->setFuture(future); + return true; + } + return false; +} + +bool GraftWallet::prepareRTATransaction(const QVector > &addresses) +{ + if (mWallet) + { + closeCurrentTransaction(); + std::vector dests; + for (auto address : addresses) + { + Monero::Wallet::TransactionDestination dst; + dst.address = address.first.toStdString(); + dst.amount = address.second; + dests.push_back(dst); + } + mCurrentTransaction = mWallet->createTransaction(dests, 0, true); + mLastError = QString::fromStdString(mWallet->errorString()); + return mCurrentTransaction->status() == Monero::PendingTransaction::Status_Ok; + } + return false; +} + +bool GraftWallet::prepareRTATransactionAsync(const QVector > &addresses) +{ + if (mWallet) + { + closeCurrentTransaction(); + QFuture future = QtConcurrent::run(this, &GraftWallet::prepareRTATransaction, + addresses); + QFutureWatcher *watcher = new QFutureWatcher(); + connect(watcher, &QFutureWatcher::finished, this, [this, watcher]() { + QFuture future = watcher->future(); + watcher->deleteLater(); + emit rtaTransactionPrepared(future.result()); + }); + watcher->setFuture(future); + return true; + } + return false; +} + +uint64_t GraftWallet::currentTransactionFee() const +{ + if (mWallet && mCurrentTransaction) + { + return mCurrentTransaction->fee(); + } + return 0; +} + +bool GraftWallet::sendCurrentTransaction() +{ + if (mWallet && mCurrentTransaction) + { + bool status = mCurrentTransaction->commit(); + if (!status) + { + mLastError = QString::fromStdString(mCurrentTransaction->errorString()); + } + closeCurrentTransaction(); + return status; + } + return false; +} + +void GraftWallet::cacheCurrentTransaction() +{ + if (mWallet && mCurrentTransaction) + { + mCurrentTransaction->updateTransactionCache(); + } +} + +void GraftWallet::closeCurrentTransaction() +{ + if (mWallet && mCurrentTransaction) + { + mWallet->disposeTransaction(mCurrentTransaction); + mCurrentTransaction = nullptr; + } +} + +QByteArrayList GraftWallet::getRawCurrentTransaction() const +{ + QByteArrayList data; + if (mWallet) + { + std::vector tx_data = mCurrentTransaction->getRawTransaction(); + for (auto it = tx_data.cbegin(); it != tx_data.cend(); ++it) + { + data.append(QByteArray::fromStdString(*it)); + } + } + return data; +} + +QByteArrayList GraftWallet::getRawTransaction(const QString &address, uint64_t amount) +{ + QByteArrayList data; + if (mWallet) + { + Monero::PendingTransaction *tx = mWallet->createTransaction(address.toStdString(), std::string(), + amount, 0); + std::vector tx_data = tx->getRawTransaction(); + for (auto it = tx_data.cbegin(); it != tx_data.cend(); ++it) + { + data.append(QByteArray::fromStdString(*it)); + } + mWallet->disposeTransaction(tx); + } + return data; +} + +QByteArrayList GraftWallet::getRawTransaction(const QVector > &addresses) +{ + QByteArrayList data; + if (mWallet) + { + std::vector dests; + for (auto address : addresses) + { + Monero::Wallet::TransactionDestination dst; + dst.address = address.first.toStdString(); + dst.amount = address.second; + dests.push_back(dst); + } + Monero::PendingTransaction *tx = mWallet->createTransaction(dests, 0); + std::vector tx_data = tx->getRawTransaction(); + for (auto it = tx_data.cbegin(); it != tx_data.cend(); ++it) + { + data.append(QByteArray::fromStdString(*it)); + } + mWallet->disposeTransaction(tx); + } + return data; +} + +void GraftWallet::startRefresh() +{ + if (mWallet) + { + mWallet->startRefresh(); + } +} + +void GraftWallet::saveCache() const +{ + if (mWallet) + { + mWallet->saveCache(cacheFilePath().toStdString()); + } +} + +bool GraftWallet::removeCache() const +{ + QFile lFile(cacheFilePath()); + return lFile.remove(); +} + +void GraftWallet::closeWallet() +{ + if (mWallet) + { + mWallet->pauseRefresh(); + mManager->closeWallet(mWallet); + mWallet = nullptr; + } +} + +void GraftWallet::updateWallet() +{ + saveCache(); + emit updated(); +} + +void GraftWallet::refreshWallet() +{ + if (mWallet) + { + saveCache(); + if (mWallet->blockChainHeight() == mWallet->daemonBlockChainHeight()) + { + emit refreshed(); + } + } +} + +QString GraftWallet::lastError() const +{ + if (mLastError.isEmpty() && mWallet) + { + return QString::fromStdString(mWallet->errorString()); + } + return mLastError; +} + +QString GraftWallet::nextAddress() +{ + mCurrentAddress++; + if (mCurrentAddress >= mAddresses.count()) + { + mCurrentAddress = 0; + } + //TODO: Use standard addresses + return QUrl(mAddresses.value(mCurrentAddress)).authority(); +// return QStringLiteral("91.237.240.44:28881"); +// return QStringLiteral("34.239.181.212:28681"); +// return QStringLiteral("54.145.210.249:28681"); +// return QStringLiteral("54.236.111.68:28681"); +} + +QString GraftWallet::cacheFilePath() const +{ + QString dataPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + if (!QFileInfo(dataPath).exists()) + { + QDir().mkpath(dataPath); + } + QDir lDir(dataPath); + return lDir.filePath(scWalletCacheFile); +} diff --git a/GraftMobileClient/core/api/v2/graftwallet.h b/GraftMobileClient/core/api/v2/graftwallet.h new file mode 100644 index 00000000..ca2ebb74 --- /dev/null +++ b/GraftMobileClient/core/api/v2/graftwallet.h @@ -0,0 +1,83 @@ +#ifndef GRAFTWALLET_H +#define GRAFTWALLET_H + +#include + +#include "wallet2_api.h" + +class GraftWallet : public QObject +{ + Q_OBJECT +public: + explicit GraftWallet(QObject *parent = nullptr); + ~GraftWallet(); + + void setTestnet(bool t); + bool isTestnet() const; + + void changeAddresses(const QStringList &addresses); + + bool createWallet(const QString &password); + bool restoreWallet(const QString &seed, const QString &password); + bool restoreWallet(const QByteArray &data, const QString &password); + + QString seed() const; + QString publicAddress() const; + QByteArray accountData() const; + + QString publicViewKey() const; + QString privateViewKey() const; + QString publicSpendKey() const; + QString privateSpendKey() const; + + uint64_t balance() const; + uint64_t unlockedBalance() const; + uint64_t lockedBalance() const; + + bool prepareTransaction(const QString &address, uint64_t amount); + bool prepareTransactionAsync(const QString &address, uint64_t amount); + bool prepareRTATransaction(const QVector > &addresses); + bool prepareRTATransactionAsync(const QVector > &addresses); + uint64_t currentTransactionFee() const; + bool sendCurrentTransaction(); + void cacheCurrentTransaction(); + void closeCurrentTransaction(); + + QByteArrayList getRawCurrentTransaction() const; + QByteArrayList getRawTransaction(const QString &address, uint64_t amount); + QByteArrayList getRawTransaction(const QVector > &addresses); + + void startRefresh(); + + void saveCache() const; + bool removeCache() const; + + void closeWallet(); + + void updateWallet(); + void refreshWallet(); + + QString lastError() const; + +signals: + void updated(); + void refreshed(); + void transactionPrepared(bool result); + void rtaTransactionPrepared(bool result); + +private: + QString nextAddress(); + QString cacheFilePath() const; + + bool mTestnet; + Monero::WalletManager *mManager; + Monero::Wallet *mWallet; + Monero::WalletListener *mListener; + Monero::PendingTransaction *mCurrentTransaction; + + QString mLastError; + QStringList mAddresses; + int mCurrentAddress; +}; + +#endif // GRAFTWALLET_H diff --git a/GraftMobileClient/core/api/v2/graftwalletapiv2.cpp b/GraftMobileClient/core/api/v2/graftwalletapiv2.cpp new file mode 100644 index 00000000..3946a3cc --- /dev/null +++ b/GraftMobileClient/core/api/v2/graftwalletapiv2.cpp @@ -0,0 +1,162 @@ +#include "graftwalletapiv2.h" +#include +#include +#include +#include +#include +#include + +GraftWalletAPIv2::GraftWalletAPIv2(const QStringList &addresses, const QString &dapiVersion, + QObject *parent) + : GraftGenericAPIv2(addresses, dapiVersion, parent) +{ +} + +void GraftWalletAPIv2::saleDetails(const QString &pid, int blockNumber) +{ + mRetries = 0; + mRequest.setUrl(nextAddress(QStringLiteral("sale_details"))); + QJsonObject params; + params.insert(QStringLiteral("PaymentID"), pid); + params.insert(QStringLiteral("BlockNumber"), blockNumber); + QJsonObject data = buildMessage(QStringLiteral("sale_details"), params); + QByteArray array = QJsonDocument(data).toJson(); + mTimer.start(); + mLastRequest = array; + QNetworkReply *reply = mManager->post(mRequest, array); + connect(reply, &QNetworkReply::finished, this, &GraftWalletAPIv2::receiveSaleDetailsResponse); +} + +void GraftWalletAPIv2::rejectPay(const QString &pid, int blockNum) +{ + mRetries = 0; + QJsonObject params; + params.insert(QStringLiteral("PaymentID"), pid); + params.insert(QStringLiteral("BlockNum"), blockNum); + QJsonObject data = buildMessage(QStringLiteral("WalletRejectPay"), params); + QByteArray array = QJsonDocument(data).toJson(); + mTimer.start(); + mLastRequest = array; + QNetworkReply *reply = mManager->post(mRequest, array); + connect(reply, &QNetworkReply::finished, this, &GraftWalletAPIv2::receiveRejectPayResponse); +} + +void GraftWalletAPIv2::pay(const QString &pid, const QString &address, double amount, + int blockNumber, const QByteArrayList &transactions) +{ + mRetries = 0; + mRequest.setUrl(nextAddress(QStringLiteral("pay"))); + QJsonArray trans; + for (QByteArray transaction : transactions) + { + trans.append(QString(transaction)); + } + QJsonObject params; + params.insert(QStringLiteral("Address"), address); + params.insert(QStringLiteral("PaymentID"), pid); + params.insert(QStringLiteral("BlockNumber"), blockNumber); + params.insert(QStringLiteral("Amount"), -666); + params.insert(QStringLiteral("Transactions"), trans); + QJsonObject data = buildMessage(QStringLiteral("pay"), params); + QByteArray array = QJsonDocument(data).toJson(); + array.replace("-666", serializeAmount(amount)); + qDebug() << array; + mTimer.start(); + mLastRequest = array; + QNetworkReply *reply = mManager->post(mRequest, array); + connect(reply, &QNetworkReply::finished, this, &GraftWalletAPIv2::receivePayResponse); +} + +void GraftWalletAPIv2::payStatus(const QString &pid, int blockNumber) +{ + mRequest.setUrl(nextAddress(QStringLiteral("pay_status"))); + QJsonObject params; + params.insert(QStringLiteral("PaymentID"), pid); + params.insert(QStringLiteral("BlockNumber"), blockNumber); + QJsonObject data = buildMessage(QStringLiteral("pay_status"), params); + QByteArray array = QJsonDocument(data).toJson(); + mTimer.start(); + QNetworkReply *reply = mManager->post(mRequest, array); + connect(reply, &QNetworkReply::finished, this, &GraftWalletAPIv2::receivePayStatusResponse); +} + +void GraftWalletAPIv2::receiveSaleDetailsResponse() +{ + mLastError.clear(); + qDebug() << "SaleDetails Response Received:\nTime: " << mTimer.elapsed(); + QNetworkReply *reply = qobject_cast(sender()); + QJsonObject object = processReply(reply); + if (!object.isEmpty()) + { + QVector> authSample; + QJsonArray authSampleArray = object.value(QLatin1String("AuthSample")).toArray(); + for (int i = 0; i < authSampleArray.size(); ++i) + { + QJsonObject authNode = authSampleArray.at(i).toObject(); + authSample.append(qMakePair(authNode.value(QLatin1String("Address")).toString(), + authNode.value(QLatin1String("Fee")).toString())); + } + emit saleDetailsReceived(authSample, object.value(QLatin1String("Details")).toString()); + } + else + { + QNetworkReply *reply = retry(); + if (reply) + { + connect(reply, &QNetworkReply::finished, this, + &GraftWalletAPIv2::receiveSaleDetailsResponse); + } + } +} + +void GraftWalletAPIv2::receiveRejectPayResponse() +{ + mLastError.clear(); + qDebug() << "RejectPay Response Received:\nTime: " << mTimer.elapsed(); + QNetworkReply *reply = qobject_cast(sender()); + QJsonObject object = processReply(reply); + if (!object.isEmpty()) + { + emit rejectPayReceived(object.value(QLatin1String("Result")).toInt()); + } + else + { + QNetworkReply *reply = retry(); + if (reply) + { + connect(reply, &QNetworkReply::finished, this, + &GraftWalletAPIv2::receiveRejectPayResponse); + } + } +} + +void GraftWalletAPIv2::receivePayResponse() +{ + mLastError.clear(); + qDebug() << "Pay Response Received:\nTime: " << mTimer.elapsed(); + QNetworkReply *reply = qobject_cast(sender()); + QJsonObject object = processReply(reply); + if (!object.isEmpty()) + { + emit payReceived(object.value(QLatin1String("Result")).toInt()); + } + else + { + QNetworkReply *reply = retry(); + if (reply) + { + connect(reply, &QNetworkReply::finished, this, &GraftWalletAPIv2::receivePayResponse); + } + } +} + +void GraftWalletAPIv2::receivePayStatusResponse() +{ + qDebug() << "PayStatus Response Received:\nTime: " << mTimer.elapsed(); + QNetworkReply *reply = qobject_cast(sender()); + QJsonObject object = processReply(reply); + if (!object.isEmpty()) + { + emit payStatusReceived(object.value(QLatin1String("Status")).toInt()); + } +} diff --git a/GraftMobileClient/core/api/v2/graftwalletapiv2.h b/GraftMobileClient/core/api/v2/graftwalletapiv2.h new file mode 100644 index 00000000..1e55000a --- /dev/null +++ b/GraftMobileClient/core/api/v2/graftwalletapiv2.h @@ -0,0 +1,33 @@ +#ifndef GRAFTWALLETAPIV2_H +#define GRAFTWALLETAPIV2_H + +#include "graftgenericapiv2.h" + +class GraftWalletAPIv2 : public GraftGenericAPIv2 +{ + Q_OBJECT +public: + explicit GraftWalletAPIv2(const QStringList &addresses, const QString &dapiVersion, + QObject *parent = nullptr); + + void saleDetails(const QString &pid, int blockNumber); + void rejectPay(const QString &pid, int blockNumber); + void pay(const QString &pid, const QString &address, double amount, int blockNumber, + const QByteArrayList &transactions); + void payStatus(const QString &pid, int blockNumber); + +signals: + void saleDetailsReceived(const QVector> &authSample, + const QString &saleDetails); + void rejectPayReceived(int result); + void payReceived(int result); + void payStatusReceived(int status); + +private slots: + void receiveSaleDetailsResponse(); + void receiveRejectPayResponse(); + void receivePayResponse(); + void receivePayStatusResponse(); +}; + +#endif // GRAFTWALLETAPIV2_H diff --git a/GraftMobileClient/core/api/v2/graftwallethandlerv2.cpp b/GraftMobileClient/core/api/v2/graftwallethandlerv2.cpp new file mode 100644 index 00000000..680ae772 --- /dev/null +++ b/GraftMobileClient/core/api/v2/graftwallethandlerv2.cpp @@ -0,0 +1,265 @@ +#include "graftwallethandlerv2.h" +#include "graftwalletapiv2.h" +#include "graftwallet.h" + +GraftWalletHandlerV2::GraftWalletHandlerV2(const QString &dapiVersion, const QStringList &addresses, + const QStringList &internalAddresses, bool testnet, + QObject *parent) + : GraftWalletHandler(parent) +{ + mApi = new GraftWalletAPIv2(addresses, dapiVersion, this); + connect(mApi, &GraftWalletAPIv2::saleDetailsReceived, + this, &GraftWalletHandlerV2::receiveSaleDetails); + connect(mApi, &GraftWalletAPIv2::rejectPayReceived, + this, &GraftWalletHandlerV2::rejectPayReceived); + connect(mApi, &GraftWalletAPIv2::payReceived, this, &GraftWalletHandlerV2::payReceived); + connect(mApi, &GraftWalletAPIv2::payStatusReceived, + this, &GraftWalletHandlerV2::receivePayStatus); + connect(mApi, &GraftWalletAPIv2::error, this, &GraftWalletHandlerV2::errorReceived); + mWallet = new GraftWallet(this); + mWallet->setTestnet(testnet); + mWallet->changeAddresses(internalAddresses); + connect(mWallet, &GraftWallet::refreshed, this, &GraftWalletHandlerV2::receiveBalance); + connect(mWallet, &GraftWallet::transactionPrepared, + this, &GraftWalletHandlerV2::receiveTransaction); + connect(mWallet, &GraftWallet::rtaTransactionPrepared, this, &GraftWalletHandlerV2::sendPay); +} + +void GraftWalletHandlerV2::changeAddresses(const QStringList &addresses, + const QStringList &internalAddresses) +{ + if (mApi) + { + mApi->changeAddresses(addresses); + } + if (mWallet) + { + mWallet->changeAddresses(internalAddresses); + } +} + +void GraftWalletHandlerV2::setAccountData(const QByteArray &accountData, const QString &password) +{ + if (mApi) + { + mApi->setAccountData(accountData, password); + } + if (mWallet) + { + mWallet->restoreWallet(accountData, password); + } +} + +QByteArray GraftWalletHandlerV2::accountData() const +{ + if (mApi) + { + return mApi->accountData(); + } + return QByteArray(); +} + +QString GraftWalletHandlerV2::password() const +{ + if (mApi) + { + return mApi->password(); + } + return QString(); +} + +void GraftWalletHandlerV2::resetData() +{ + mWallet->closeWallet(); + mWallet->removeCache(); +} + +void GraftWalletHandlerV2::createAccount(const QString &password) +{ + if (mWallet) + { + bool isAccountCreated = mWallet->createWallet(password); + if (isAccountCreated) + { + updateBalance(); + } + emit createAccountReceived(mWallet->accountData(), password, mWallet->publicAddress(), + mWallet->privateViewKey(), mWallet->seed()); + } +} + +void GraftWalletHandlerV2::restoreAccount(const QString &seed, const QString &password) +{ + if (mWallet) + { + bool isAccountRestored = mWallet->restoreWallet(seed.toLower(), password); + if (isAccountRestored) + { + updateBalance(); + } + emit restoreAccountReceived(mWallet->accountData(), password, mWallet->publicAddress(), + mWallet->privateViewKey(), mWallet->seed()); + } +} + +void GraftWalletHandlerV2::updateBalance() +{ + if (mWallet) + { + mWallet->startRefresh(); + } +} + +void GraftWalletHandlerV2::transferFee(const QString &address, const QString &amount) +{ + if (mWallet) + { + mWallet->prepareTransactionAsync(address, GraftGenericAPIv2::toAtomic(amount)); + } +} + +void GraftWalletHandlerV2::transfer(const QString &address, const QString &amount) +{ + if (mWallet) + { + bool status = mWallet->sendCurrentTransaction(); + emit transferReceived(status); + } +} + +void GraftWalletHandlerV2::saleDetails(const QString &pid, int blockNumber) +{ + if (mApi) + { + mLastPID = pid; + mBlockNumber = blockNumber; + mApi->saleDetails(pid, blockNumber); + } + else + { + emit saleDetailsReceived(false, QString()); + } +} + +void GraftWalletHandlerV2::rejectPay(const QString &pid, int blockNumber) +{ + //TODO: Fix support of rejectPay, unsupported on supernode side +// mApi->rejectPay(mPID, mBlockNumber); +} + +void GraftWalletHandlerV2::pay(const QString &pid, const QString &address, double amount, + int blockNumber) +{ + if (mWallet) + { + mLastPID = pid; + mBlockNumber = blockNumber; + mPOSAddress = address; + mTotalCost = amount; + QVector> destinations; + uint64_t totalFee = 0; + for (QPair authNode : mAuthSample) + { + uint64_t fee = authNode.second.toULongLong(); + totalFee += fee; + destinations.append(qMakePair(authNode.first, fee)); + } + destinations.prepend(qMakePair(address, mApi->toAtomic(amount) - totalFee)); + mWallet->prepareRTATransactionAsync(destinations); + } +} + +void GraftWalletHandlerV2::payStatus(const QString &pid, int blockNumber) +{ + if (mApi) + { + mApi->payStatus(pid, blockNumber); + } +} + +void GraftWalletHandlerV2::receiveBalance() +{ + if (mWallet) + { + double lockedBalance = GraftGenericAPIv2::toCoins(mWallet->lockedBalance()); + double unlockedBalance = GraftGenericAPIv2::toCoins(mWallet->unlockedBalance()); + emit balanceReceived(lockedBalance + unlockedBalance, unlockedBalance); + } +} + +void GraftWalletHandlerV2::receiveTransaction(bool result) +{ + if (mWallet) + { + double lFee = 0; + if (result) + { + lFee = GraftGenericAPIv2::toCoins(mWallet->currentTransactionFee()); + } + emit transferFeeReceived(result, lFee); + } +} + +void GraftWalletHandlerV2::receiveSaleDetails(const QVector > &authSample, + const QString &saleDetails) +{ + mAuthSample = authSample; + emit saleDetailsReceived(0, saleDetails); +} + +void GraftWalletHandlerV2::sendPay(bool result) +{ + if (mWallet) + { + if (result) + { + QByteArrayList transactions = mWallet->getRawCurrentTransaction(); + mApi->pay(mLastPID, mPOSAddress, mTotalCost, mBlockNumber, transactions); + } + else + { + emit errorReceived(mWallet->lastError()); + } + } + else + { + emit errorReceived(tr("Wallet isn't initialized!")); + } + +} + +void GraftWalletHandlerV2::receivePayStatus(int status) +{ + switch (status) { + case GraftWalletAPIv2::StatusWaiting: + case GraftWalletAPIv2::StatusProcessing: + payStatus(mLastPID, mBlockNumber); + break; + case GraftWalletAPIv2::StatusSuccess: + processPayResult(true); + break; + case GraftWalletAPIv2::StatusNone: + case GraftWalletAPIv2::StatusFailed: + case GraftWalletAPIv2::StatusPOSRejected: + case GraftWalletAPIv2::StatusWalletRejected: + default: + processPayResult(false); + break; + } +} + +void GraftWalletHandlerV2::processPayResult(bool result) +{ + if (mWallet) + { + if (result) + { + mWallet->cacheCurrentTransaction(); + } + mWallet->closeCurrentTransaction(); + mAuthSample.clear(); + mLastPID.clear(); + mBlockNumber = 0; + } + emit payStatusReceived(0, result); +} diff --git a/GraftMobileClient/core/api/v2/graftwallethandlerv2.h b/GraftMobileClient/core/api/v2/graftwallethandlerv2.h new file mode 100644 index 00000000..91388cd3 --- /dev/null +++ b/GraftMobileClient/core/api/v2/graftwallethandlerv2.h @@ -0,0 +1,59 @@ +#ifndef GRAFTWALLETHANDLERV2_H +#define GRAFTWALLETHANDLERV2_H + +#include "../graftwallethandler.h" + +#include + +class GraftWalletAPIv2; +class GraftWallet; + +class GraftWalletHandlerV2 : public GraftWalletHandler +{ + Q_OBJECT +public: + explicit GraftWalletHandlerV2(const QString &dapiVersion, const QStringList &addresses, + const QStringList &internalAddresses, bool testnet = false, + QObject *parent = nullptr); + + void changeAddresses(const QStringList &addresses, + const QStringList &internalAddresses = QStringList()) override; + + void setAccountData(const QByteArray &accountData, const QString &password) override; + QByteArray accountData() const override; + QString password() const override; + + void resetData() override; + +public slots: + void createAccount(const QString &password) override; + void restoreAccount(const QString &seed, const QString &password) override; + void updateBalance() override; + void transferFee(const QString &address, const QString &amount) override; + void transfer(const QString &address, const QString &amount) override; + + void saleDetails(const QString &pid, int blockNumber) override; + void rejectPay(const QString &pid, int blockNumber) override; + void pay(const QString &pid, const QString &address, double amount, int blockNumber) override; + void payStatus(const QString &pid, int blockNumber) override; + +private slots: + void receiveBalance(); + void receiveTransaction(bool result); + void receiveSaleDetails(const QVector> &authSample, + const QString &saleDetails); + void sendPay(bool result); + void receivePayStatus(int status); + void processPayResult(bool result); + +private: + GraftWalletAPIv2 *mApi; + GraftWallet *mWallet; + QString mLastPID; + int mBlockNumber; + QString mPOSAddress; + double mTotalCost; + QVector> mAuthSample; +}; + +#endif // GRAFTWALLETHANDLERV2_H diff --git a/GraftMobileClient/core/api/v2/graftwalletlistener.cpp b/GraftMobileClient/core/api/v2/graftwalletlistener.cpp new file mode 100644 index 00000000..3bfa4bc0 --- /dev/null +++ b/GraftMobileClient/core/api/v2/graftwalletlistener.cpp @@ -0,0 +1,39 @@ +#include "graftwalletlistener.h" +#include "graftwallet.h" +#include + +GraftWalletListener::GraftWalletListener(GraftWallet *wallet) + : mWallet(wallet) +{ + +} + +void GraftWalletListener::moneySpent(const std::string &txId, uint64_t amount) +{ + qDebug() << __FUNCTION__ << QString::fromStdString(txId) << amount; +} + +void GraftWalletListener::moneyReceived(const std::string &txId, uint64_t amount) +{ + qDebug() << __FUNCTION__ << QString::fromStdString(txId) << amount; +} + +void GraftWalletListener::unconfirmedMoneyReceived(const std::string &txId, uint64_t amount) +{ + qDebug() << __FUNCTION__ << QString::fromStdString(txId) << amount; +} + +void GraftWalletListener::newBlock(uint64_t height) +{ + qDebug() << __FUNCTION__ << height; +} + +void GraftWalletListener::updated() +{ + mWallet->updateWallet(); +} + +void GraftWalletListener::refreshed() +{ + mWallet->refreshWallet(); +} diff --git a/GraftMobileClient/core/api/v2/graftwalletlistener.h b/GraftMobileClient/core/api/v2/graftwalletlistener.h new file mode 100644 index 00000000..7e1e8c43 --- /dev/null +++ b/GraftMobileClient/core/api/v2/graftwalletlistener.h @@ -0,0 +1,25 @@ +#ifndef GRAFTWALLETLISTENER_H +#define GRAFTWALLETLISTENER_H + +#include "wallet2_api.h" + +class GraftWallet; + +class GraftWalletListener : public Monero::WalletListener +{ +public: + GraftWalletListener(GraftWallet *wallet); + + void moneySpent(const std::string &txId, uint64_t amount) override; + void moneyReceived(const std::string &txId, uint64_t amount) override; + void unconfirmedMoneyReceived(const std::string &txId, uint64_t amount) override; + void newBlock(uint64_t height) override; + + void updated() override; + void refreshed() override; + +private: + GraftWallet *mWallet; +}; + +#endif // GRAFTWALLETLISTENER_H diff --git a/GraftMobileClient/core/config.h b/GraftMobileClient/core/config.h index 9182d7f1..dca14e70 100644 --- a/GraftMobileClient/core/config.h +++ b/GraftMobileClient/core/config.h @@ -4,6 +4,7 @@ #include static const QString scUrl("%1/dapi"); +static const QString scDapiUrl("%1/dapi/v2.0/%2"); namespace MainnetConfiguration { @@ -37,18 +38,22 @@ static const QString scDAPIVersion("1.0F"); namespace ExperimentalTestnetConfiguration { -static const QString scConfigTitle("Public RTA Testnet"); +static const QString scConfigTitle("Alpha RTA Testnet"); -static const QStringList scHttpSeedSupernodes{"testnet-rta-seed.graft.network:28900" +static const QStringList scHttpSeedSupernodes{ + "testnet-dev-seed.graft.network:28600" + //"testnet-rta-seed.graft.network:28900" //"34.200.186.98:28900", //"34.224.118.182:28900", //"52.206.105.250:28900" }; -static const QStringList scHttpsSeedSupernodes{"testnet-rta-seed.graft.network:28943"}; +static const QStringList scHttpsSeedSupernodes{ + "testnet-dev-seed.graft.network:28643" + //"testnet-rta-seed.graft.network:28943" + }; static const QString scDAPIVersion("1.0R"); } - #endif // CONFIG_H diff --git a/GraftMobileClient/core/graftbaseclient.cpp b/GraftMobileClient/core/graftbaseclient.cpp index edc590d5..5e71d208 100644 --- a/GraftMobileClient/core/graftbaseclient.cpp +++ b/GraftMobileClient/core/graftbaseclient.cpp @@ -1,6 +1,7 @@ #include "accountmodelserializator.h" #include "barcodeimageprovider.h" -#include "api/graftgenericapi.h" +#include "api/graftbasehandler.h" +#include "api/v1/graftgenericapiv1.h" #include "quickexchangemodel.h" #include "graftclienttools.h" #include "graftbaseclient.h" @@ -69,14 +70,14 @@ void GraftBaseClient::setNetworkType(int networkType) { mAccountManager->setNetworkType(networkType); } - graftAPI()->setDAPIVersion(dapiVersion()); - graftAPI()->changeAddresses(getServiceAddresses()); + changeGraftHandler(); emit networkTypeChanged(); } int GraftBaseClient::networkType() const { - switch (mAccountManager->networkType()) { + switch (mAccountManager->networkType()) + { case GraftClientTools::Mainnet: return GraftClientTools::Mainnet; case GraftClientTools::PublicTestnet: @@ -96,6 +97,7 @@ bool GraftBaseClient::isAccountExists() const void GraftBaseClient::resetData() { mAccountManager->clearData(); + graftHandler()->resetData(); mBalances.clear(); saveBalance(); mIsBalanceUpdated = false; @@ -104,56 +106,58 @@ void GraftBaseClient::resetData() void GraftBaseClient::createAccount(const QString &password) { - GraftGenericAPI *api = graftAPI(); - if (api) + GraftBaseHandler *handler = graftHandler(); + if (handler) { if (mAccountManager->account().isEmpty()) { - connect(api, &GraftGenericAPI::createAccountReceived, - this, &GraftBaseClient::receiveAccount, Qt::UniqueConnection); + connect(handler, &GraftBaseHandler::createAccountReceived, + this, &GraftBaseClient::receiveCreateAccount, Qt::UniqueConnection); mAccountManager->setPassword(password); - api->createAccount(password); + handler->createAccount(password); } else { - api->setAccountData(mAccountManager->account(), mAccountManager->password()); + handler->setAccountData(mAccountManager->account(), mAccountManager->password()); } } } void GraftBaseClient::restoreAccount(const QString &seed, const QString &password) { - GraftGenericAPI *api = graftAPI(); - if (api) + GraftBaseHandler *handler = graftHandler(); + if (handler) { - connect(api, &GraftGenericAPI::restoreAccountReceived, + connect(handler, &GraftBaseHandler::restoreAccountReceived, this, &GraftBaseClient::receiveRestoreAccount, Qt::UniqueConnection); mAccountManager->setPassword(password); - api->restoreAccount(seed.toLower(), password); + handler->restoreAccount(seed.toLower(), password); } } void GraftBaseClient::transfer(const QString &address, const QString &amount) { - GraftGenericAPI *api = graftAPI(); - if (api) + GraftBaseHandler *handler = graftHandler(); + if (handler) { - connect(api, &GraftGenericAPI::transferReceived, + connect(handler, &GraftBaseHandler::transferReceived, this, &GraftBaseClient::receiveTransfer, Qt::UniqueConnection); - QString customAmount = QString::number(GraftGenericAPI::toAtomic(amount.toDouble()), 'f', 0); - api->transfer(address, customAmount); + QString customAmount = QString::number(GraftGenericAPIv1::toAtomic(amount.toDouble()), + 'f', 0); + handler->transfer(address, customAmount); } } void GraftBaseClient::transferFee(const QString &address, const QString &amount) { - GraftGenericAPI *api = graftAPI(); - if (api) + GraftBaseHandler *handler = graftHandler(); + if (handler) { - connect(api, &GraftGenericAPI::transferFeeReceived, + connect(handler, &GraftBaseHandler::transferFeeReceived, this, &GraftBaseClient::receiveTransferFee, Qt::UniqueConnection); - QString customAmount = QString::number(GraftGenericAPI::toAtomic(amount.toDouble()), 'f', 0); - api->transferFee(address, customAmount); + QString customAmount = QString::number(GraftGenericAPIv1::toAtomic(amount.toDouble()), + 'f', 0); + handler->transferFee(address, customAmount); } } @@ -228,15 +232,15 @@ void GraftBaseClient::saveAccounts() const void GraftBaseClient::updateBalance() { - if (!mAccountManager->account().isEmpty()) + if (graftHandler() && !mAccountManager->account().isEmpty()) { - graftAPI()->getBalance(); + graftHandler()->updateBalance(); } } void GraftBaseClient::timerEvent(QTimerEvent *event) { - if (event->timerId() == mBalanceTimer && !mAccountManager->account().isEmpty()) + if (event->timerId() == mBalanceTimer) { updateBalance(); } @@ -244,16 +248,15 @@ void GraftBaseClient::timerEvent(QTimerEvent *event) void GraftBaseClient::initAccountSettings() { - if (graftAPI()) + if (graftHandler()) { - connect(graftAPI(), &GraftGenericAPI::getBalanceReceived, this, + connect(graftHandler(), &GraftBaseHandler::balanceReceived, this, &GraftBaseClient::receiveBalance, Qt::UniqueConnection); if (isAccountExists()) { - graftAPI()->setAccountData(mAccountManager->account(), mAccountManager->password()); + graftHandler()->setAccountData(mAccountManager->account(), mAccountManager->password()); updateBalance(); } -// mBalanceTimer = startTimer(20000); } } @@ -297,11 +300,12 @@ QByteArray GraftBaseClient::loadModel(const QString &fileName) const return QByteArray(); } -QStringList GraftBaseClient::getServiceAddresses() const +QStringList GraftBaseClient::getServiceAddresses(bool httpOnly) const { QStringList addressList; QString type; - if (httpsType()) + bool isHttpsType = httpOnly ? false : httpsType(); + if (isHttpsType) { type = "s"; } @@ -317,7 +321,7 @@ QStringList GraftBaseClient::getServiceAddresses() const } else { - QStringList seeds = httpsType() ? httpsSeedSupernodes() : httpSeedSupernodes(); + QStringList seeds = isHttpsType ? httpsSeedSupernodes() : httpSeedSupernodes(); for (int i = 0; i < seeds.size(); ++i) { addressList << QString("http%1://%2").arg(type).arg(seeds.at(i)); @@ -326,9 +330,9 @@ QStringList GraftBaseClient::getServiceAddresses() const return addressList; } -void GraftBaseClient::receiveAccount(const QByteArray &accountData, const QString &password, - const QString &address, const QString &viewKey, - const QString &seed) +void GraftBaseClient::receiveCreateAccount(const QByteArray &accountData, const QString &password, + const QString &address, const QString &viewKey, + const QString &seed) { bool isAccountCreated = false; if (mAccountManager->password() == password && !accountData.isEmpty() && !address.isEmpty()) @@ -372,7 +376,6 @@ void GraftBaseClient::receiveBalance(double balance, double unlockedBalance) saveBalance(); mIsBalanceUpdated = true; emit balanceUpdated(); - QTimer::singleShot(20000, this, &GraftBaseClient::updateBalance); } } @@ -387,7 +390,7 @@ void GraftBaseClient::receiveTransferFee(int result, double fee) double lFee = 0; if (status) { - lFee = GraftGenericAPI::toCoins(fee); + lFee = GraftGenericAPIv1::toCoins(fee); } emit transferFeeReceived(status, lFee); } @@ -472,7 +475,7 @@ void GraftBaseClient::setSettings(const QString &key, const QVariant &value) con void GraftBaseClient::updateSettings() const { - graftAPI()->changeAddresses(getServiceAddresses()); + graftHandler()->changeAddresses(getServiceAddresses(), getServiceAddresses(true)); } bool GraftBaseClient::httpsType() const diff --git a/GraftMobileClient/core/graftbaseclient.h b/GraftMobileClient/core/graftbaseclient.h index 7cc0e115..03b1684a 100644 --- a/GraftMobileClient/core/graftbaseclient.h +++ b/GraftMobileClient/core/graftbaseclient.h @@ -6,7 +6,7 @@ class BarcodeImageProvider; class QuickExchangeModel; -class GraftGenericAPI; +class GraftBaseHandler; class AccountManager; class CurrencyModel; class AccountModel; @@ -94,18 +94,19 @@ public slots: protected: void timerEvent(QTimerEvent *event) override; - virtual GraftGenericAPI *graftAPI() const = 0; + virtual void changeGraftHandler() = 0; + virtual GraftBaseHandler *graftHandler() const = 0; void initAccountSettings(); void registerImageProvider(QQmlEngine *engine); void saveModel(const QString &fileName,const QByteArray &data) const; QByteArray loadModel(const QString &fileName) const; - QStringList getServiceAddresses() const; + QStringList getServiceAddresses(bool httpOnly = false) const; private slots: - void receiveAccount(const QByteArray &accountData, const QString &password, - const QString &address, const QString &viewKey, - const QString &seed); + void receiveCreateAccount(const QByteArray &accountData, const QString &password, + const QString &address, const QString &viewKey, + const QString &seed); void receiveRestoreAccount(const QByteArray &accountData, const QString &password, const QString &address, const QString &viewKey, const QString &seed); diff --git a/GraftMobileClient/core/graftposclient.cpp b/GraftMobileClient/core/graftposclient.cpp index e29922ec..906b8f8a 100644 --- a/GraftMobileClient/core/graftposclient.cpp +++ b/GraftMobileClient/core/graftposclient.cpp @@ -1,11 +1,16 @@ #include "selectedproductproxymodel.h" #include "productmodelserializator.h" +#include "graftclienttools.h" #include "qrcodegenerator.h" -#include "api/graftposapi.h" #include "graftposclient.h" #include "accountmanager.h" #include "keygenerator.h" #include "productmodel.h" +#include "api/v1/graftposhandlerv1.h" +#if defined(Q_OS_IOS) || defined(Q_OS_MACOS) +#include "api/v2/graftposhandlerv2.h" +#endif +#include "api/graftposhandler.h" #include "config.h" #include @@ -16,16 +21,10 @@ static const QString scProductModelDataFile("productList.dat"); GraftPOSClient::GraftPOSClient(QObject *parent) : GraftBaseClient(parent) + ,mClientHandler(nullptr) { - mApi = new GraftPOSAPI(getServiceAddresses(), dapiVersion(), this); - connect(mApi, &GraftPOSAPI::saleResponseReceived, this, &GraftPOSClient::receiveSale); - connect(mApi, &GraftPOSAPI::rejectSaleResponseReceived, - this, &GraftPOSClient::receiveRejectSale); - connect(mApi, &GraftPOSAPI::getSaleStatusResponseReceived, - this, &GraftPOSClient::receiveSaleStatus); - connect(mApi, &GraftPOSAPI::error, this, &GraftPOSClient::errorReceived); + changeGraftHandler(); initProductModels(); - initAccountSettings(); } GraftPOSClient::~GraftPOSClient() @@ -58,8 +57,8 @@ void GraftPOSClient::sale() { updateQuickExchange(mProductModel->totalCost()); QByteArray selectedProducts = ProductModelSerializator::serialize(mProductModel, true); - mApi->sale(mAccountManager->address(), mAccountManager->viewKey(), - mProductModel->totalCost(), selectedProducts.toHex()); + mClientHandler->sale(mAccountManager->address(), mAccountManager->viewKey(), + mProductModel->totalCost(), selectedProducts.toHex()); } else { @@ -69,69 +68,71 @@ void GraftPOSClient::sale() void GraftPOSClient::rejectSale() { - mApi->rejectSale(mPID); + mClientHandler->rejectSale(mPID); } -void GraftPOSClient::getSaleStatus() +void GraftPOSClient::saleStatus() { - mApi->getSaleStatus(mPID); + mClientHandler->saleStatus(mPID, mBlockNumber); } -void GraftPOSClient::receiveSale(int result, const QString &pid, int blockNum) +void GraftPOSClient::receiveSale(int result, const QString &pid, int blockNumber) { const bool isStatusOk = (result == 0); mPID = pid; + mBlockNumber = blockNumber; QString qrText = QString("%1;%2;%3;%4").arg(pid).arg(mAccountManager->address()) - .arg(mProductModel->totalCost()).arg(blockNum); + .arg(mProductModel->totalCost()).arg(blockNumber); setQRCodeImage(QRCodeGenerator::encode(qrText)); emit saleReceived(isStatusOk); if (isStatusOk) { - getSaleStatus(); + saleStatus(); } } -void GraftPOSClient::receiveRejectSale(int result) +void GraftPOSClient::initProductModels() { - emit rejectSaleReceived(result == 0); + mProductModel = new ProductModel(this); + ProductModelSerializator::deserialize(loadModel(scProductModelDataFile), mProductModel); + mSelectedProductModel = new SelectedProductProxyModel(this); + mSelectedProductModel->setSourceModel(mProductModel); } -void GraftPOSClient::receiveSaleStatus(int result, int saleStatus) +void GraftPOSClient::changeGraftHandler() { - if (result == 0) + if (mClientHandler) { - switch (saleStatus) { - case GraftPOSAPI::StatusProcessing: - getSaleStatus(); - break; - case GraftPOSAPI::StatusApproved: - emit saleStatusReceived(true); - break; - case GraftPOSAPI::StatusNone: - case GraftPOSAPI::StatusFailed: - case GraftPOSAPI::StatusPOSRejected: - case GraftPOSAPI::StatusWalletRejected: - default: - emit saleStatusReceived(false); - break; - } + mClientHandler->deleteLater(); } - else + switch (networkType()) { - emit saleStatusReceived(false); + case GraftClientTools::Mainnet: + case GraftClientTools::PublicTestnet: + mClientHandler = new GraftPOSHandlerV1(dapiVersion(), getServiceAddresses(), this); + break; + case GraftClientTools::PublicExperimentalTestnet: +#if defined(Q_OS_IOS) || defined(Q_OS_MACOS) + mClientHandler = new GraftPOSHandlerV2(dapiVersion(), getServiceAddresses(), + getServiceAddresses(true), + networkType() != GraftClientTools::Mainnet, this); +#else + mClientHandler = new GraftPOSHandlerV1(dapiVersion(), getServiceAddresses(), this); +#endif + break; } + connect(mClientHandler, &GraftPOSHandler::saleReceived, this, &GraftPOSClient::receiveSale); + connect(mClientHandler, &GraftPOSHandler::rejectSaleReceived, + this, &GraftPOSClient::rejectSaleReceived); + connect(mClientHandler, &GraftPOSHandler::saleStatusReceived, + this, &GraftPOSClient::saleStatusReceived); + connect(mClientHandler, &GraftPOSHandler::errorReceived, + this, &GraftPOSClient::errorReceived); + initAccountSettings(); } -void GraftPOSClient::initProductModels() -{ - mProductModel = new ProductModel(this); - ProductModelSerializator::deserialize(loadModel(scProductModelDataFile), mProductModel); - mSelectedProductModel = new SelectedProductProxyModel(this); - mSelectedProductModel->setSourceModel(mProductModel); -} - -GraftGenericAPI *GraftPOSClient::graftAPI() const +GraftBaseHandler *GraftPOSClient::graftHandler() const { - Q_ASSERT_X(mApi, "GraftWalletClient", "GraftGenericAPI not initialized!"); - return mApi; + Q_ASSERT_X(mClientHandler, "GraftPOSClient", "GraftPOSHandler not initialized!"); + return mClientHandler; } diff --git a/GraftMobileClient/core/graftposclient.h b/GraftMobileClient/core/graftposclient.h index 2772cb74..dd30cf51 100644 --- a/GraftMobileClient/core/graftposclient.h +++ b/GraftMobileClient/core/graftposclient.h @@ -4,8 +4,8 @@ #include "graftbaseclient.h" class SelectedProductProxyModel; +class GraftPOSHandler; class ProductModel; -class GraftPOSAPI; class GraftPOSClient : public GraftBaseClient { @@ -28,19 +28,19 @@ public slots: void saveProducts() const; void sale(); void rejectSale(); - void getSaleStatus(); + void saleStatus(); private slots: - void receiveSale(int result, const QString &pid, int blockNum); - void receiveRejectSale(int result); - void receiveSaleStatus(int result, int saleStatus); + void receiveSale(int result, const QString &pid, int blockNumber); private: void initProductModels(); - GraftGenericAPI *graftAPI() const override; + void changeGraftHandler() override; + GraftBaseHandler *graftHandler() const override; - GraftPOSAPI *mApi; + GraftPOSHandler *mClientHandler; QString mPID; + int mBlockNumber; ProductModel *mProductModel; SelectedProductProxyModel *mSelectedProductModel; }; diff --git a/GraftMobileClient/core/graftwalletclient.cpp b/GraftMobileClient/core/graftwalletclient.cpp index 786277a6..8eaed0d9 100644 --- a/GraftMobileClient/core/graftwalletclient.cpp +++ b/GraftMobileClient/core/graftwalletclient.cpp @@ -1,6 +1,11 @@ #include "productmodelserializator.h" -#include "api/graftwalletapi.h" +#include "api/v1/graftwalletapiv1.h" +#include "api/v1/graftwallethandlerv1.h" +#if defined(Q_OS_IOS) || defined(Q_OS_MACOS) +#include "api/v2/graftwallethandlerv2.h" +#endif #include "graftwalletclient.h" +#include "graftclienttools.h" #include "accountmanager.h" #include "productmodel.h" #include "keygenerator.h" @@ -8,19 +13,11 @@ GraftWalletClient::GraftWalletClient(QObject *parent) : GraftBaseClient(parent) + ,mClientHandler(nullptr) { - mBlockNum = 0; - mApi = new GraftWalletAPI(getServiceAddresses(), dapiVersion(), this); - connect(mApi, &GraftWalletAPI::getPOSDataReceived, - this, &GraftWalletClient::receiveGetPOSData); - connect(mApi, &GraftWalletAPI::rejectPayReceived, this, &GraftWalletClient::receiveRejectPay); - connect(mApi, &GraftWalletAPI::payReceived, this, &GraftWalletClient::receivePay); - connect(mApi, &GraftWalletAPI::getPayStatusReceived, - this, &GraftWalletClient::receivePayStatus); - connect(mApi, &GraftWalletAPI::error, this, &GraftWalletClient::errorReceived); - + mBlockNumber = 0; + changeGraftHandler(); mPaymentProductModel = new ProductModel(this); - initAccountSettings(); } double GraftWalletClient::totalCost() const @@ -33,7 +30,7 @@ ProductModel *GraftWalletClient::paymentProductModel() const return mPaymentProductModel; } -void GraftWalletClient::getPOSData(const QString &data) +void GraftWalletClient::saleDetails(const QString &data) { if (!data.isEmpty()) { @@ -43,39 +40,48 @@ void GraftWalletClient::getPOSData(const QString &data) mPID = dataList.value(0); mPrivateKey = dataList.value(1); mTotalCost = dataList.value(2).toDouble(); - mBlockNum = dataList.value(3).toInt(); + mBlockNumber = dataList.value(3).toInt(); updateQuickExchange(mTotalCost); - mApi->getPOSData(mPID, mBlockNum); + mClientHandler->saleDetails(mPID, mBlockNumber); } else { - emit getPOSDataReceived(false); + emit saleDetailsReceived(false); } } } void GraftWalletClient::rejectPay() { - mApi->rejectPay(mPID, mBlockNum); + if (mClientHandler) + { + mClientHandler->rejectPay(mPID, mBlockNumber); + } } void GraftWalletClient::pay() { - mApi->pay(mPID, mPrivateKey, mTotalCost, mBlockNum); + if (mClientHandler) + { + mClientHandler->pay(mPID, mPrivateKey, mTotalCost, mBlockNumber); + } } -void GraftWalletClient::getPayStatus() +void GraftWalletClient::payStatus() { - mApi->getPayStatus(mPID); + if (mClientHandler) + { + mClientHandler->payStatus(mPID, mBlockNumber); + } } -void GraftWalletClient::receiveGetPOSData(int result, const QString &payDetails) +void GraftWalletClient::receiveSaleDetails(int result, const QString &payDetails) { const bool isStatusOk = (result == 0); mPaymentProductModel->clear(); QByteArray data = QByteArray::fromHex(payDetails.toLatin1()); ProductModelSerializator::deserialize(data, mPaymentProductModel); - emit getPOSDataReceived(isStatusOk); + emit saleDetailsReceived(isStatusOk); } void GraftWalletClient::receiveRejectPay(int result) @@ -89,25 +95,25 @@ void GraftWalletClient::receivePay(int result) emit payReceived(isStatusOk); if (isStatusOk) { - getPayStatus(); + payStatus(); } } -void GraftWalletClient::receivePayStatus(int result, int payStatus) +void GraftWalletClient::receivePayStatus(int result, int status) { if (result == 0) { - switch (payStatus) { - case GraftWalletAPI::StatusProcessing: - getPayStatus(); + switch (status) { + case GraftWalletAPIv1::StatusProcessing: + payStatus(); break; - case GraftWalletAPI::StatusApproved: + case GraftWalletAPIv1::StatusApproved: emit payStatusReceived(true); break; - case GraftWalletAPI::StatusNone: - case GraftWalletAPI::StatusFailed: - case GraftWalletAPI::StatusPOSRejected: - case GraftWalletAPI::StatusWalletRejected: + case GraftWalletAPIv1::StatusNone: + case GraftWalletAPIv1::StatusFailed: + case GraftWalletAPIv1::StatusPOSRejected: + case GraftWalletAPIv1::StatusWalletRejected: default: emit payStatusReceived(false); break; @@ -119,8 +125,41 @@ void GraftWalletClient::receivePayStatus(int result, int payStatus) } } -GraftGenericAPI *GraftWalletClient::graftAPI() const +void GraftWalletClient::changeGraftHandler() +{ + if (mClientHandler) + { + mClientHandler->deleteLater(); + } + switch (networkType()) + { + case GraftClientTools::Mainnet: + case GraftClientTools::PublicTestnet: + mClientHandler = new GraftWalletHandlerV1(dapiVersion(), getServiceAddresses(), this); + break; + case GraftClientTools::PublicExperimentalTestnet: +#if defined(Q_OS_IOS) || defined(Q_OS_MACOS) + mClientHandler = new GraftWalletHandlerV2(dapiVersion(), getServiceAddresses(), + getServiceAddresses(true), + networkType() != GraftClientTools::Mainnet, this); +#else + mClientHandler = new GraftWalletHandlerV1(dapiVersion(), getServiceAddresses(), this); +#endif + break; + } + connect(mClientHandler, &GraftWalletHandler::saleDetailsReceived, + this, &GraftWalletClient::receiveSaleDetails); + connect(mClientHandler, &GraftWalletHandler::rejectPayReceived, + this, &GraftWalletClient::receiveRejectPay); + connect(mClientHandler, &GraftWalletHandler::payStatusReceived, + this, &GraftWalletClient::payStatusReceived); + connect(mClientHandler, &GraftWalletHandler::errorReceived, + this, &GraftWalletClient::errorReceived); + initAccountSettings(); +} + +GraftBaseHandler *GraftWalletClient::graftHandler() const { - Q_ASSERT_X(mApi, "GraftWalletClient", "GraftGenericAPI not initialized!"); - return mApi; + Q_ASSERT_X(mClientHandler, "GraftWalletClient", "GraftWalletHandler not initialized!"); + return mClientHandler; } diff --git a/GraftMobileClient/core/graftwalletclient.h b/GraftMobileClient/core/graftwalletclient.h index 0ae155e7..11f4f79a 100644 --- a/GraftMobileClient/core/graftwalletclient.h +++ b/GraftMobileClient/core/graftwalletclient.h @@ -3,7 +3,7 @@ #include "graftbaseclient.h" -class GraftWalletAPI; +class GraftWalletHandler; class ProductModel; class GraftWalletClient : public GraftBaseClient @@ -16,30 +16,31 @@ class GraftWalletClient : public GraftBaseClient Q_INVOKABLE ProductModel *paymentProductModel() const; signals: - void getPOSDataReceived(bool result); + void saleDetailsReceived(bool result); void rejectPayReceived(bool result); void payReceived(bool result); void payStatusReceived(bool result); public slots: - void getPOSData(const QString &data); + void saleDetails(const QString &data); void rejectPay(); void pay(); - void getPayStatus(); + void payStatus(); private slots: - void receiveGetPOSData(int result, const QString &payDetails); + void receiveSaleDetails(int result, const QString &payDetails); void receiveRejectPay(int result); void receivePay(int result); - void receivePayStatus(int result, int payStatus); + void receivePayStatus(int result, int status); private: - GraftGenericAPI *graftAPI() const override; + void changeGraftHandler() override; + GraftBaseHandler *graftHandler() const override; - GraftWalletAPI *mApi; + GraftWalletHandler *mClientHandler; QString mPID; QString mPrivateKey; - int mBlockNum; + int mBlockNumber; double mTotalCost; ProductModel *mPaymentProductModel; diff --git a/GraftMobileClient/ios/pos/Info.plist b/GraftMobileClient/ios/pos/Info.plist index 9f6f1646..33a42177 100644 --- a/GraftMobileClient/ios/pos/Info.plist +++ b/GraftMobileClient/ios/pos/Info.plist @@ -17,11 +17,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.11 + 1.13.0 CFBundleSignature ???? CFBundleVersion - 1.11.1 + 1.13.0 LSRequiresIPhoneOS NOTE diff --git a/GraftMobileClient/ios/wallet/Info.plist b/GraftMobileClient/ios/wallet/Info.plist index 3a2fb230..782cb409 100644 --- a/GraftMobileClient/ios/wallet/Info.plist +++ b/GraftMobileClient/ios/wallet/Info.plist @@ -19,11 +19,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.11 + 1.13.0 CFBundleSignature ???? CFBundleVersion - 1.11.1 + 1.13.0 LSRequiresIPhoneOS NOTE diff --git a/GraftMobileClient/libwallet b/GraftMobileClient/libwallet new file mode 160000 index 00000000..c93c9db7 --- /dev/null +++ b/GraftMobileClient/libwallet @@ -0,0 +1 @@ +Subproject commit c93c9db7cda713113fd37a2b70741b26d52b54e2 diff --git a/GraftMobileClient/mac/pos/Info.plist b/GraftMobileClient/mac/pos/Info.plist index 0f6edfc2..6b591673 100644 --- a/GraftMobileClient/mac/pos/Info.plist +++ b/GraftMobileClient/mac/pos/Info.plist @@ -19,11 +19,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.11 + 1.13 CFBundleSignature ???? CFBundleVersion - 1.11.1 + 1.13.0 NOTE This file was generated by Qt/QMake. NSHighResolutionCapable diff --git a/GraftMobileClient/mac/wallet/Info.plist b/GraftMobileClient/mac/wallet/Info.plist index c08a434f..59b88eb1 100644 --- a/GraftMobileClient/mac/wallet/Info.plist +++ b/GraftMobileClient/mac/wallet/Info.plist @@ -19,11 +19,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.11 + 1.13 CFBundleSignature ???? CFBundleVersion - 1.11.1 + 1.13.0 NOTE This file was generated by Qt/QMake. NSHighResolutionCapable diff --git a/GraftMobileClient/resources/SelectNetworkScreen.qml b/GraftMobileClient/resources/SelectNetworkScreen.qml index 1c599bbd..8df66299 100644 --- a/GraftMobileClient/resources/SelectNetworkScreen.qml +++ b/GraftMobileClient/resources/SelectNetworkScreen.qml @@ -83,7 +83,7 @@ BaseScreen { Layout.alignment: Qt.AlignTop Material.accent: ColorFactory.color(DesignFactory.Foreground) Material.foreground: ColorFactory.color(DesignFactory.Foreground) - text: qsTr("Public RTA Testnet") + text: qsTr("Alpha RTA Testnet") font { pixelSize: 16 bold: true @@ -100,7 +100,8 @@ BaseScreen { wrapMode: Label.WordWrap text: qsTr("Blockchain and test network running on the code branch that contains " + "Real Time Authorization and other future features that are not yet " + - "available on mainnet.") + "available on mainnet.\n\nCurrently available only for iOS and MacOS.\n" + + "Other platforms are coming soon.") MouseArea { anchors.fill: parent onClicked: rtaTestNet.checked = true @@ -115,6 +116,8 @@ BaseScreen { WideActionButton { Layout.alignment: Qt.AlignBottom text: qsTr("Confirm") + enabled: Detector.isPlatform(Platform.IOS) || Detector.isPlatform(Platform.MacOS) + ? true : !rtaTestNet.checked onClicked: { disableScreen() setNetworkType() diff --git a/GraftMobileClient/resources/wallet/QRScanningScreen.qml b/GraftMobileClient/resources/wallet/QRScanningScreen.qml index 4147ccd9..b6e8ccbb 100644 --- a/GraftMobileClient/resources/wallet/QRScanningScreen.qml +++ b/GraftMobileClient/resources/wallet/QRScanningScreen.qml @@ -13,7 +13,7 @@ BaseScreen { Connections { target: GraftClient - onGetPOSDataReceived: { + onSaleDetailsReceived: { if (result === true) { pushScreen.openPaymentConfirmationScreen() } else { @@ -31,7 +31,7 @@ BaseScreen { QRScanningView { id: qRScanningView anchors.fill: parent - onQrCodeDetected: GraftClient.getPOSData(message) + onQrCodeDetected: GraftClient.saleDetails(message) } function pop() { diff --git a/GraftMobileClient/windows/pos/install.nsi b/GraftMobileClient/windows/pos/install.nsi index 473e8d2c..a24b1a1f 100644 --- a/GraftMobileClient/windows/pos/install.nsi +++ b/GraftMobileClient/windows/pos/install.nsi @@ -9,9 +9,9 @@ !define COMPANYNAME "GRAFT Payments, LLC" !define DESCRIPTION "Graft Point-of-Sale" !define VERSIONMAJOR 1 - !define VERSIONMINOR 11 - !define VERSIONBUILD 1 - !define VERSION "1.11.1" + !define VERSIONMINOR 13 + !define VERSIONBUILD 0 + !define VERSION "1.13.0" !define APPICON "icon.ico" !define ABOUTURL "https://www.graft.network" ; !define LIC_NAME "license.rtf" diff --git a/GraftMobileClient/windows/pos/resource.rc b/GraftMobileClient/windows/pos/resource.rc index ea87f1f8..54affde1 100644 --- a/GraftMobileClient/windows/pos/resource.rc +++ b/GraftMobileClient/windows/pos/resource.rc @@ -4,8 +4,8 @@ IDI_ICON1 ICON DISCARDABLE "icon.ico" #define VFT_APP 0x00000001L 1 VERSIONINFO -FILEVERSION 1,11,1 -PRODUCTVERSION 1,11,1 +FILEVERSION 1,13,0 +PRODUCTVERSION 1,13,0 FILETYPE VFT_APP { BLOCK "StringFileInfo" @@ -13,13 +13,13 @@ FILETYPE VFT_APP BLOCK "040904E4" { VALUE "CompanyName", "GRAFT Payments, LLC" - VALUE "FileVersion", "1.11.1" + VALUE "FileVersion", "1.13.0" VALUE "FileDescription", "Graft Point-of-Sale" VALUE "InternalName", "Graft POS" VALUE "LegalCopyright", " 2018 GRAFT Payments, LLC" VALUE "OriginalFilename", "GraftPointOfSale.exe" VALUE "ProductName", "Graft Point-of-Sale" - VALUE "ProductVersion", "1.11.1" + VALUE "ProductVersion", "1.13.0" } } diff --git a/GraftMobileClient/windows/wallet/install.nsi b/GraftMobileClient/windows/wallet/install.nsi index 4f39a071..36b1bccf 100644 --- a/GraftMobileClient/windows/wallet/install.nsi +++ b/GraftMobileClient/windows/wallet/install.nsi @@ -9,9 +9,9 @@ !define COMPANYNAME "GRAFT Payments, LLC" !define DESCRIPTION "Graft Wallet" !define VERSIONMAJOR 1 - !define VERSIONMINOR 11 - !define VERSIONBUILD 1 - !define VERSION "1.11.1" + !define VERSIONMINOR 13 + !define VERSIONBUILD 0 + !define VERSION "1.13.0" !define APPICON "icon.ico" !define ABOUTURL "https://www.graft.network" !define LIC_NAME "license.rtf" diff --git a/GraftMobileClient/windows/wallet/resource.rc b/GraftMobileClient/windows/wallet/resource.rc index 5cf084ca..c4061ea5 100644 --- a/GraftMobileClient/windows/wallet/resource.rc +++ b/GraftMobileClient/windows/wallet/resource.rc @@ -4,8 +4,8 @@ IDI_ICON1 ICON DISCARDABLE "icon.ico" #define VFT_APP 0x00000001L 1 VERSIONINFO -FILEVERSION 1,11,1 -PRODUCTVERSION 1,11,1 +FILEVERSION 1,13,0 +PRODUCTVERSION 1,13,0 FILETYPE VFT_APP { BLOCK "StringFileInfo" @@ -13,13 +13,13 @@ FILETYPE VFT_APP BLOCK "040904E4" { VALUE "CompanyName", "GRAFT Payments, LLC" - VALUE "FileVersion", "1.11.1" + VALUE "FileVersion", "1.13.0" VALUE "FileDescription", "Graft Wallet" VALUE "InternalName", "Graft Wallet" VALUE "LegalCopyright", " 2018 GRAFT Payments, LLC" VALUE "OriginalFilename", "GraftWallet.exe" VALUE "ProductName", "Graft Wallet" - VALUE "ProductVersion", "1.11.1" + VALUE "ProductVersion", "1.13.0" } }