2018-07-23 15:21:31 +00:00
|
|
|
/**
|
|
|
|
* Copyright (c) 2017-present, Status Research and Development GmbH.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the BSD-style license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "rctstatus.h"
|
|
|
|
#include "bridge.h"
|
|
|
|
#include "eventdispatcher.h"
|
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
#include <QByteArray>
|
2018-07-23 15:21:31 +00:00
|
|
|
#include <QDebug>
|
2019-10-01 17:52:20 +00:00
|
|
|
#include <QDir>
|
|
|
|
#include <QJsonDocument>
|
2018-12-15 18:57:00 +00:00
|
|
|
#include <QMessageBox>
|
2019-10-01 17:52:20 +00:00
|
|
|
#include <QStandardPaths>
|
2018-12-15 18:57:00 +00:00
|
|
|
#include <QStorageInfo>
|
2018-07-23 15:21:31 +00:00
|
|
|
#include <QVariantMap>
|
2018-09-07 09:53:43 +00:00
|
|
|
#include <QtConcurrent>
|
2018-07-23 15:21:31 +00:00
|
|
|
|
|
|
|
#include "libstatus.h"
|
|
|
|
|
2018-12-15 18:57:00 +00:00
|
|
|
extern QString getDataStoragePath();
|
|
|
|
extern QString getLogFilePath();
|
|
|
|
|
2018-07-23 15:21:31 +00:00
|
|
|
namespace {
|
|
|
|
struct RegisterQMLMetaType {
|
2019-10-01 17:52:20 +00:00
|
|
|
RegisterQMLMetaType() { qRegisterMetaType<RCTStatus *>(); }
|
2018-07-23 15:21:31 +00:00
|
|
|
} registerMetaType;
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
class RCTStatusPrivate {
|
|
|
|
public:
|
2019-10-01 17:52:20 +00:00
|
|
|
static Bridge *bridge;
|
|
|
|
static RCTStatus *rctStatus;
|
2018-07-23 15:21:31 +00:00
|
|
|
};
|
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
Bridge *RCTStatusPrivate::bridge = nullptr;
|
|
|
|
RCTStatus *RCTStatusPrivate::rctStatus = nullptr;
|
2018-11-06 16:01:43 +00:00
|
|
|
|
|
|
|
Q_LOGGING_CATEGORY(RCTSTATUS, "RCTStatus")
|
2018-07-23 15:21:31 +00:00
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
RCTStatus::RCTStatus(QObject *parent)
|
|
|
|
: QObject(parent), d_ptr(new RCTStatusPrivate) {
|
|
|
|
RCTStatusPrivate::rctStatus = this;
|
|
|
|
SetSignalEventCallback((void *)&RCTStatus::statusGoEventCallback);
|
|
|
|
connect(this, &RCTStatus::statusGoEvent, this, &RCTStatus::onStatusGoEvent);
|
2018-07-23 15:21:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
RCTStatus::~RCTStatus() {}
|
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
void RCTStatus::setBridge(Bridge *bridge) {
|
|
|
|
Q_D(RCTStatus);
|
|
|
|
d->bridge = bridge;
|
2018-07-23 15:21:31 +00:00
|
|
|
}
|
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
QString RCTStatus::moduleName() { return "Status"; }
|
2018-07-23 15:21:31 +00:00
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
QList<ModuleMethod *> RCTStatus::methodsToExport() {
|
|
|
|
return QList<ModuleMethod *>{};
|
2018-07-23 15:21:31 +00:00
|
|
|
}
|
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
QVariantMap RCTStatus::constantsToExport() { return QVariantMap(); }
|
2018-07-23 15:21:31 +00:00
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
void RCTStatus::shouldMoveToInternalStorage(double callbackId) {
|
|
|
|
Q_D(RCTStatus);
|
|
|
|
qCDebug(RCTSTATUS) << "::shouldMoveToInternalStorage call";
|
2018-07-23 15:21:31 +00:00
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{QVariant()});
|
|
|
|
}
|
2019-02-21 14:51:00 +00:00
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
void RCTStatus::moveToInternalStorage(double callbackId) {
|
|
|
|
Q_D(RCTStatus);
|
|
|
|
qCDebug(RCTSTATUS) << "::moveToInternalStorage call";
|
2019-01-17 22:46:48 +00:00
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{QVariant()});
|
2018-07-23 15:21:31 +00:00
|
|
|
}
|
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
QString RCTStatus::prepareDirAndUpdateConfig(QString configString) {
|
|
|
|
Q_D(RCTStatus);
|
|
|
|
qCDebug(RCTSTATUS) << "::prepareDirAndUpdateConfig call - configString:"
|
|
|
|
<< configString;
|
|
|
|
|
|
|
|
QJsonParseError jsonError;
|
|
|
|
const QJsonDocument &jsonDoc =
|
|
|
|
QJsonDocument::fromJson(configString.toUtf8(), &jsonError);
|
|
|
|
if (jsonError.error != QJsonParseError::NoError) {
|
|
|
|
qCWarning(RCTSTATUS) << jsonError.errorString();
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariantMap configJSON = jsonDoc.toVariant().toMap();
|
|
|
|
QVariantMap shhextConfig = configJSON["ShhextConfig"].toMap();
|
|
|
|
qCDebug(RCTSTATUS) << "::startNode configString: " << configJSON;
|
|
|
|
|
|
|
|
int networkId = configJSON["NetworkId"].toInt();
|
|
|
|
QString relativeDataDirPath = configJSON["DataDir"].toString();
|
|
|
|
if (!relativeDataDirPath.startsWith("/"))
|
|
|
|
relativeDataDirPath.prepend("/");
|
|
|
|
|
|
|
|
QString rootDirPath = getDataStoragePath();
|
|
|
|
QDir rootDir(rootDirPath);
|
|
|
|
QString absDataDirPath = rootDirPath + relativeDataDirPath;
|
|
|
|
QDir dataDir(absDataDirPath);
|
|
|
|
if (!dataDir.exists()) {
|
|
|
|
dataDir.mkpath(".");
|
|
|
|
}
|
|
|
|
|
|
|
|
d_gethLogFilePath = dataDir.absoluteFilePath("geth.log");
|
|
|
|
configJSON["DataDir"] = absDataDirPath;
|
|
|
|
configJSON["KeyStoreDir"] = rootDir.absoluteFilePath("keystore");
|
|
|
|
configJSON["LogFile"] = d_gethLogFilePath;
|
|
|
|
|
|
|
|
shhextConfig["BackupDisabledDataDir"] = rootDirPath;
|
|
|
|
|
|
|
|
configJSON["ShhExtConfig"] = shhextConfig;
|
|
|
|
|
|
|
|
const QJsonDocument &updatedJsonDoc = QJsonDocument::fromVariant(configJSON);
|
|
|
|
qCInfo(RCTSTATUS) << "::startNode updated configString: "
|
|
|
|
<< updatedJsonDoc.toVariant().toMap();
|
|
|
|
return QString(updatedJsonDoc.toJson(QJsonDocument::Compact));
|
|
|
|
}
|
|
|
|
|
|
|
|
void RCTStatus::prepareDirAndUpdateConfig(QString configString,
|
|
|
|
double callbackId) {
|
|
|
|
Q_D(RCTStatus);
|
|
|
|
qCInfo(RCTSTATUS) << "::prepareDirAndUpdateConfig call - callbackId:"
|
|
|
|
<< callbackId;
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](QString configString, double callbackId) {
|
|
|
|
QString updatedConfig = prepareDirAndUpdateConfig(configString);
|
|
|
|
d->bridge->invokePromiseCallback(
|
|
|
|
callbackId, QVariantList{updatedConfig.toUtf8().data()});
|
|
|
|
},
|
|
|
|
configString, callbackId);
|
2018-07-23 15:21:31 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 16:10:38 +00:00
|
|
|
void RCTStatus::initKeystore() {
|
2019-10-01 17:52:20 +00:00
|
|
|
qCInfo(RCTSTATUS) << "::initKeystore call";
|
|
|
|
QString rootDir = getDataStoragePath();
|
|
|
|
const char *result = InitKeystore(rootDir.toUtf8().data());
|
|
|
|
logStatusGoResult("::initKeystore InitKeystore", result);
|
|
|
|
}
|
|
|
|
|
2018-12-15 18:57:00 +00:00
|
|
|
#include <QApplication>
|
2019-10-01 17:52:20 +00:00
|
|
|
#include <QMessageBox>
|
2018-12-15 18:57:00 +00:00
|
|
|
#include <QProcess>
|
|
|
|
#include <QStandardPaths>
|
|
|
|
#include <QtGui/private/qzipwriter_p.h>
|
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
void showFileInGraphicalShell(QWidget *parent, const QFileInfo &fileInfo) {
|
|
|
|
// Mac, Windows support folder or file.
|
2018-12-15 18:57:00 +00:00
|
|
|
#ifdef Q_OS_WIN
|
2019-10-01 17:52:20 +00:00
|
|
|
const QString explorer =
|
|
|
|
QStandardPaths::findExecutable(QLatin1String("explorer.exe"));
|
|
|
|
if (explorer.isEmpty()) {
|
|
|
|
QMessageBox::warning(
|
|
|
|
parent, QApplication::translate("Core::Internal",
|
|
|
|
"Launching Windows Explorer Failed"),
|
|
|
|
QApplication::translate(
|
|
|
|
"Core::Internal",
|
|
|
|
"Could not find explorer.exe in path to launch Windows Explorer."));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
QStringList param;
|
|
|
|
if (!fileInfo.isDir())
|
|
|
|
param += QLatin1String("/select,");
|
|
|
|
param += QDir::toNativeSeparators(fileInfo.canonicalFilePath());
|
|
|
|
QProcess::startDetached(explorer, param);
|
2018-12-15 18:57:00 +00:00
|
|
|
#elif defined(Q_OS_MAC)
|
2019-10-01 17:52:20 +00:00
|
|
|
QStringList scriptArgs;
|
|
|
|
scriptArgs << QLatin1String("-e")
|
|
|
|
<< QString::fromLatin1(
|
|
|
|
"tell application \"Finder\" to reveal POSIX file \"%1\"")
|
|
|
|
.arg(fileInfo.canonicalFilePath());
|
|
|
|
QProcess::execute(QLatin1String("/usr/bin/osascript"), scriptArgs);
|
|
|
|
scriptArgs.clear();
|
|
|
|
scriptArgs << QLatin1String("-e")
|
|
|
|
<< QLatin1String("tell application \"Finder\" to activate");
|
|
|
|
QProcess::execute(QLatin1String("/usr/bin/osascript"), scriptArgs);
|
2018-12-15 18:57:00 +00:00
|
|
|
#else
|
2019-10-01 17:52:20 +00:00
|
|
|
// we cannot select a file here, because no file browser really supports it...
|
|
|
|
const QString folder = fileInfo.isDir() ? fileInfo.absoluteFilePath()
|
|
|
|
: fileInfo.dir().absolutePath();
|
|
|
|
QProcess browserProc;
|
|
|
|
browserProc.setProgram("xdg-open");
|
|
|
|
browserProc.setArguments(QStringList(folder));
|
|
|
|
bool success = browserProc.startDetached();
|
|
|
|
const QString error =
|
|
|
|
QString::fromLocal8Bit(browserProc.readAllStandardError());
|
|
|
|
success = success && error.isEmpty();
|
|
|
|
if (!success) {
|
|
|
|
QMessageBox::warning(parent, "Launching Explorer Failed", error);
|
|
|
|
return;
|
|
|
|
}
|
2018-12-15 18:57:00 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-04-30 11:49:45 +00:00
|
|
|
void RCTStatus::sendLogs(QString dbJSON, QString jsLogs, double callbackId) {
|
2019-10-01 17:52:20 +00:00
|
|
|
Q_D(RCTStatus);
|
|
|
|
|
|
|
|
qCDebug(RCTSTATUS) << "::sendLogs call - logFilePath:" << getLogFilePath()
|
|
|
|
<< "d_gethLogFilePath:" << d_gethLogFilePath
|
|
|
|
<< "dbJSON:" << dbJSON;
|
|
|
|
|
|
|
|
QString tmpDirName("Status.im");
|
|
|
|
QDir tmpDir(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
|
|
|
|
if (!tmpDir.mkpath(tmpDirName)) {
|
|
|
|
qCWarning(RCTSTATUS) << "::sendLogs could not create temp dir:"
|
|
|
|
<< tmpDirName;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check that at least 20MB are available for log generation
|
|
|
|
QStorageInfo storage(tmpDir);
|
|
|
|
if (storage.bytesAvailable() < 20 * 1024 * 1024) {
|
|
|
|
QMessageBox dlg;
|
|
|
|
dlg.warning(QApplication::activeWindow(), "Error",
|
|
|
|
QString("Insufficient storage space available in %1 for log "
|
|
|
|
"generation. Please free up some space.")
|
|
|
|
.arg(storage.rootPath()),
|
|
|
|
QMessageBox::Close);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QFile zipFile(tmpDir.absoluteFilePath(tmpDirName + QDir::separator() +
|
|
|
|
"Status-debug-logs.zip"));
|
|
|
|
QZipWriter zipWriter(&zipFile);
|
|
|
|
QFile gethLogFile(d_gethLogFilePath);
|
|
|
|
QFile logFile(getLogFilePath());
|
|
|
|
zipWriter.addFile("db.json", dbJSON.toUtf8());
|
|
|
|
zipWriter.addFile("js_logs.log", jsLogs.toUtf8());
|
|
|
|
if (gethLogFile.exists()) {
|
|
|
|
zipWriter.addFile(QFileInfo(gethLogFile).fileName(), &gethLogFile);
|
|
|
|
}
|
|
|
|
if (logFile.exists()) {
|
|
|
|
zipWriter.addFile(QFileInfo(logFile).fileName(), &logFile);
|
|
|
|
}
|
|
|
|
zipWriter.close();
|
|
|
|
|
|
|
|
showFileInGraphicalShell(QApplication::activeWindow(), QFileInfo(zipFile));
|
|
|
|
}
|
|
|
|
|
|
|
|
void RCTStatus::exportLogs(double callbackId) {
|
|
|
|
Q_D(RCTStatus);
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](double callbackId) {
|
|
|
|
const char *result = ExportNodeLogs();
|
|
|
|
logStatusGoResult("::exportLogs", result);
|
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{result});
|
|
|
|
},
|
|
|
|
callbackId);
|
2018-12-15 18:57:00 +00:00
|
|
|
}
|
|
|
|
|
2018-07-23 15:21:31 +00:00
|
|
|
void RCTStatus::addPeer(QString enode, double callbackId) {
|
2019-10-01 17:52:20 +00:00
|
|
|
Q_D(RCTStatus);
|
|
|
|
qCDebug(RCTSTATUS) << "::addPeer call - callbackId:" << callbackId;
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](QString enode, double callbackId) {
|
|
|
|
const char *result = AddPeer(enode.toUtf8().data());
|
|
|
|
logStatusGoResult("::addPeer AddPeer", result);
|
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{result});
|
|
|
|
},
|
|
|
|
enode, callbackId);
|
2018-07-23 15:21:31 +00:00
|
|
|
}
|
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
void RCTStatus::saveAccountAndLogin(QString accountData, QString password,
|
|
|
|
QString config, QString subAccountsData) {
|
2019-08-01 20:11:59 +00:00
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
Q_D(RCTStatus);
|
|
|
|
QString finalConfig = prepareDirAndUpdateConfig(config);
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](QString accountData, QString password, QString finalConfig,
|
|
|
|
QString subAccountsData) {
|
|
|
|
const char *result = SaveAccountAndLogin(
|
|
|
|
accountData.toUtf8().data(), password.toUtf8().data(),
|
|
|
|
finalConfig.toUtf8().data(), subAccountsData.toUtf8().data());
|
2019-08-01 20:11:59 +00:00
|
|
|
logStatusGoResult("::saveAccountAndLogin", result);
|
2019-10-01 17:52:20 +00:00
|
|
|
},
|
|
|
|
accountData, password, finalConfig, subAccountsData);
|
|
|
|
}
|
|
|
|
|
|
|
|
// void RCTStatus::saveAccountAndLoginWithKeycard(QString accountData,
|
|
|
|
// QString password, QString
|
|
|
|
// config,
|
|
|
|
// QString chatKey) {
|
|
|
|
// Q_D(RCTStatus);
|
|
|
|
// QString finalConfig = prepareDirAndUpdateConfig(config);
|
|
|
|
// QtConcurrent::run(
|
|
|
|
// [&](QString accountData, QString password, QString finalConfig,
|
|
|
|
// QString chatKey) {
|
|
|
|
// const char *result = SaveAccountAndLoginWithKeycard(
|
|
|
|
// accountData.toUtf8().data(), password.toUtf8().data(),
|
|
|
|
// finalConfig.toUtf8().data(), chatKey.toUtf8().data());
|
|
|
|
// logStatusGoResult("::saveAccountAndLoginWithKeycard", result);
|
|
|
|
// },
|
|
|
|
// accountData, password, finalConfig, chatKey);
|
|
|
|
//}
|
2018-07-23 15:21:31 +00:00
|
|
|
|
2019-08-01 20:11:59 +00:00
|
|
|
void RCTStatus::login(QString accountData, QString password) {
|
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
Q_D(RCTStatus);
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](QString accountData, QString password) {
|
|
|
|
const char *result =
|
|
|
|
Login(accountData.toUtf8().data(), password.toUtf8().data());
|
2019-08-01 20:11:59 +00:00
|
|
|
logStatusGoResult("::login", result);
|
2019-10-01 17:52:20 +00:00
|
|
|
},
|
|
|
|
accountData, password);
|
|
|
|
}
|
|
|
|
|
|
|
|
// void RCTStatus::loginWithKeycard(QString accountData, QString password,
|
|
|
|
// QString chatKey) {
|
|
|
|
//
|
|
|
|
// Q_D(RCTStatus);
|
|
|
|
// QtConcurrent::run(
|
|
|
|
// [&](QString accountData, QString password, QString chatKey) {
|
|
|
|
// const char *result =
|
|
|
|
// LoginWithKeycard(accountData.toUtf8().data(),
|
|
|
|
// password.toUtf8().data(),
|
|
|
|
// chatKey.toUtf8().data());
|
|
|
|
// logStatusGoResult("::loginWithKeycard", result);
|
|
|
|
// },
|
|
|
|
// accountData, password, chatKey);
|
|
|
|
//}
|
2019-08-01 20:11:59 +00:00
|
|
|
|
|
|
|
void RCTStatus::logout() {
|
2019-10-01 17:52:20 +00:00
|
|
|
Q_D(RCTStatus);
|
|
|
|
QtConcurrent::run([&]() {
|
|
|
|
const char *result = Logout();
|
|
|
|
logStatusGoResult("::logout", result);
|
|
|
|
});
|
2019-08-01 20:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void RCTStatus::openAccounts(double callbackId) {
|
2019-10-01 17:52:20 +00:00
|
|
|
Q_D(RCTStatus);
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](double callbackId) {
|
2019-08-01 20:11:59 +00:00
|
|
|
QString rootDir = getDataStoragePath();
|
2019-10-01 17:52:20 +00:00
|
|
|
const char *result = OpenAccounts(rootDir.toUtf8().data());
|
2019-08-01 20:11:59 +00:00
|
|
|
logStatusGoResult("::openAccounts", result);
|
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{result});
|
2019-10-01 17:52:20 +00:00
|
|
|
},
|
|
|
|
callbackId);
|
2019-08-01 20:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void RCTStatus::multiAccountStoreAccount(QString json, double callbackId) {
|
2019-10-01 17:52:20 +00:00
|
|
|
Q_D(RCTStatus);
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](QString json, double callbackId) {
|
|
|
|
const char *result = MultiAccountStoreAccount(json.toUtf8().data());
|
2019-08-01 20:11:59 +00:00
|
|
|
logStatusGoResult("::multiAccountStoreAccount", result);
|
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{result});
|
2019-10-01 17:52:20 +00:00
|
|
|
},
|
|
|
|
json, callbackId);
|
2019-08-01 20:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void RCTStatus::multiAccountLoadAccount(QString json, double callbackId) {
|
2019-10-01 17:52:20 +00:00
|
|
|
Q_D(RCTStatus);
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](QString json, double callbackId) {
|
|
|
|
const char *result = MultiAccountLoadAccount(json.toUtf8().data());
|
2019-08-01 20:11:59 +00:00
|
|
|
logStatusGoResult("::multiAccountLoadAccount", result);
|
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{result});
|
2019-10-01 17:52:20 +00:00
|
|
|
},
|
|
|
|
json, callbackId);
|
2019-08-01 20:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void RCTStatus::multiAccountReset(double callbackId) {
|
2019-10-01 17:52:20 +00:00
|
|
|
Q_D(RCTStatus);
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](double callbackId) {
|
|
|
|
const char *result = MultiAccountReset();
|
2019-08-01 20:11:59 +00:00
|
|
|
logStatusGoResult("::multiAccountReset", result);
|
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{result});
|
2019-10-01 17:52:20 +00:00
|
|
|
},
|
|
|
|
callbackId);
|
2019-08-01 20:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void RCTStatus::multiAccountDeriveAddresses(QString json, double callbackId) {
|
2019-10-01 17:52:20 +00:00
|
|
|
Q_D(RCTStatus);
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](QString json, double callbackId) {
|
|
|
|
const char *result = MultiAccountDeriveAddresses(json.toUtf8().data());
|
2019-08-01 20:11:59 +00:00
|
|
|
logStatusGoResult("::multiAccountDeriveAddresses", result);
|
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{result});
|
2019-10-01 17:52:20 +00:00
|
|
|
},
|
|
|
|
json, callbackId);
|
2019-08-01 20:11:59 +00:00
|
|
|
}
|
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
void RCTStatus::multiAccountStoreDerived(QString json, double callbackId) {
|
|
|
|
Q_D(RCTStatus);
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](QString json, double callbackId) {
|
|
|
|
const char *result =
|
|
|
|
MultiAccountStoreDerivedAccounts(json.toUtf8().data());
|
|
|
|
logStatusGoResult("::multiAccountStoreDerived", result);
|
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{result});
|
|
|
|
},
|
|
|
|
json, callbackId);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RCTStatus::multiAccountGenerateAndDeriveAddresses(QString json,
|
|
|
|
double callbackId) {
|
|
|
|
Q_D(RCTStatus);
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](QString json, double callbackId) {
|
|
|
|
const char *result =
|
|
|
|
MultiAccountGenerateAndDeriveAddresses(json.toUtf8().data());
|
|
|
|
logStatusGoResult("::multiAccountGenerateAndDeriveAddresses", result);
|
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{result});
|
|
|
|
},
|
|
|
|
json, callbackId);
|
2018-12-03 19:19:56 +00:00
|
|
|
}
|
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
void RCTStatus::multiAccountImportMnemonic(QString json, double callbackId) {
|
|
|
|
Q_D(RCTStatus);
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](QString json, double callbackId) {
|
|
|
|
const char *result = MultiAccountImportMnemonic(json.toUtf8().data());
|
|
|
|
logStatusGoResult("::multiAccountImportMnemonic", result);
|
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{result});
|
|
|
|
},
|
|
|
|
json, callbackId);
|
2018-07-23 15:21:31 +00:00
|
|
|
}
|
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
void RCTStatus::verify(QString address, QString password, double callbackId) {
|
|
|
|
Q_D(RCTStatus);
|
|
|
|
qCInfo(RCTSTATUS) << "::verify call - callbackId:" << callbackId;
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](QString address, QString password, double callbackId) {
|
|
|
|
QDir rootDir(getDataStoragePath());
|
|
|
|
QString keystorePath = rootDir.absoluteFilePath("keystore");
|
|
|
|
const char *result = VerifyAccountPassword(keystorePath.toUtf8().data(),
|
|
|
|
address.toUtf8().data(),
|
|
|
|
password.toUtf8().data());
|
|
|
|
logStatusGoResult("::verify VerifyAccountPassword", result);
|
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{result});
|
|
|
|
},
|
|
|
|
address, password, callbackId);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RCTStatus::sendTransaction(QString txArgsJSON, QString password,
|
|
|
|
double callbackId) {
|
|
|
|
Q_D(RCTStatus);
|
|
|
|
qCDebug(RCTSTATUS) << "::sendTransaction call - callbackId:" << callbackId;
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](QString txArgsJSON, QString password, double callbackId) {
|
|
|
|
const char *result = SendTransaction(txArgsJSON.toUtf8().data(),
|
|
|
|
password.toUtf8().data());
|
|
|
|
logStatusGoResult("::sendTransaction SendTransaction", result);
|
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{result});
|
|
|
|
},
|
|
|
|
txArgsJSON, password, callbackId);
|
|
|
|
}
|
2018-08-20 11:05:51 +00:00
|
|
|
|
|
|
|
void RCTStatus::signMessage(QString rpcParams, double callbackId) {
|
2019-10-01 17:52:20 +00:00
|
|
|
Q_D(RCTStatus);
|
|
|
|
qCDebug(RCTSTATUS) << "::signMessage call - callbackId:" << callbackId;
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](QString rpcParams, double callbackId) {
|
|
|
|
const char *result = SignMessage(rpcParams.toUtf8().data());
|
|
|
|
logStatusGoResult("::signMessage SignMessage", result);
|
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{result});
|
|
|
|
},
|
|
|
|
rpcParams, callbackId);
|
2018-07-23 15:21:31 +00:00
|
|
|
}
|
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
void RCTStatus::signTypedData(QString data, QString account, QString password,
|
|
|
|
double callbackId) {
|
2018-07-19 15:51:06 +00:00
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
Q_D(RCTStatus);
|
|
|
|
qCDebug(RCTSTATUS) << "::signMessage call - callbackId:" << callbackId;
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](QString data, QString account, QString password, double callbackId) {
|
|
|
|
const char *result =
|
|
|
|
SignTypedData(data.toUtf8().data(), account.toUtf8().data(),
|
|
|
|
password.toUtf8().data());
|
|
|
|
logStatusGoResult("::signTypedData signTypedData", result);
|
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{result});
|
|
|
|
},
|
|
|
|
data, account, password, callbackId);
|
2018-07-19 15:51:06 +00:00
|
|
|
}
|
2019-10-01 17:52:20 +00:00
|
|
|
void RCTStatus::signGroupMembership(QString content, double callbackId) {
|
|
|
|
Q_D(RCTStatus);
|
|
|
|
qCDebug(RCTSTATUS) << "::signGroupMembership - callbackId:" << callbackId;
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](QString content, double callbackId) {
|
|
|
|
const char *result = SignGroupMembership(content.toUtf8().data());
|
|
|
|
logStatusGoResult("::signGroupMembership SignGroupMembership", result);
|
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{result});
|
|
|
|
},
|
|
|
|
content, callbackId);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RCTStatus::extractGroupMembershipSignatures(QString signatures,
|
|
|
|
double callbackId) {
|
|
|
|
Q_D(RCTStatus);
|
|
|
|
qCDebug(RCTSTATUS) << "::extractGroupMembershipSignatures - callbackId:"
|
|
|
|
<< callbackId;
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](QString signatures, double callbackId) {
|
|
|
|
const char *result =
|
|
|
|
ExtractGroupMembershipSignatures(signatures.toUtf8().data());
|
|
|
|
logStatusGoResult("::extractGroupMembershipSignatures "
|
|
|
|
"ExtractGroupMembershipSignatures",
|
|
|
|
result);
|
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{result});
|
|
|
|
},
|
|
|
|
signatures, callbackId);
|
2018-07-23 15:21:31 +00:00
|
|
|
}
|
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
void RCTStatus::setAdjustResize() {}
|
2018-07-23 15:21:31 +00:00
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
void RCTStatus::setAdjustPan() {}
|
2018-07-23 15:21:31 +00:00
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
void RCTStatus::setSoftInputMode(int i) {}
|
2018-07-23 15:21:31 +00:00
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
void RCTStatus::clearCookies() {}
|
2018-07-23 15:21:31 +00:00
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
void RCTStatus::clearStorageAPIs() {}
|
2018-07-23 15:21:31 +00:00
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
void RCTStatus::callRPC(QString payload, double callbackId) {
|
|
|
|
Q_D(RCTStatus);
|
|
|
|
qCDebug(RCTSTATUS) << "::callRPC call - payload:" << payload.left(128)
|
|
|
|
<< "callbackId:" << callbackId;
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](QString payload, double callbackId) {
|
|
|
|
const char *result = CallRPC(payload.toUtf8().data());
|
|
|
|
logStatusGoResult("::callRPC CallRPC", result);
|
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{result});
|
|
|
|
},
|
|
|
|
payload, callbackId);
|
2018-07-23 15:21:31 +00:00
|
|
|
}
|
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
void RCTStatus::callPrivateRPC(QString payload, double callbackId) {
|
|
|
|
Q_D(RCTStatus);
|
|
|
|
qCDebug(RCTSTATUS) << "::callPrivateRPC call - payload:" << payload.left(128)
|
|
|
|
<< "callbackId:" << callbackId;
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](QString payload, double callbackId) {
|
|
|
|
const char *result = CallPrivateRPC(payload.toUtf8().data());
|
|
|
|
logStatusGoResult("::callPrivateRPC CallPrivateRPC", result);
|
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{result});
|
|
|
|
},
|
|
|
|
payload, callbackId);
|
2018-07-23 15:21:31 +00:00
|
|
|
}
|
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
void RCTStatus::closeApplication() {}
|
2018-07-23 15:21:31 +00:00
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
void RCTStatus::connectionChange(QString type, bool isExpensive) {
|
|
|
|
Q_D(RCTStatus);
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](QString type, bool isExpensive) {
|
|
|
|
ConnectionChange(type.toUtf8().data(), isExpensive ? 1 : 0);
|
|
|
|
qCWarning(RCTSTATUS) << "::connectionChange";
|
|
|
|
},
|
|
|
|
type, isExpensive);
|
2018-07-23 15:21:31 +00:00
|
|
|
}
|
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
void RCTStatus::appStateChange(QString type) {
|
|
|
|
Q_D(RCTStatus);
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](QString type) {
|
|
|
|
AppStateChange(type.toUtf8().data());
|
|
|
|
qCWarning(RCTSTATUS) << "::appStateChange";
|
|
|
|
},
|
|
|
|
type);
|
2018-07-23 15:21:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool RCTStatus::JSCEnabled() {
|
2019-10-01 17:52:20 +00:00
|
|
|
qCDebug(RCTSTATUS) << "::JSCEnabled call";
|
|
|
|
return false;
|
2018-07-23 15:21:31 +00:00
|
|
|
}
|
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
void RCTStatus::statusGoEventCallback(const char *event) {
|
|
|
|
qCDebug(RCTSTATUS) << "::statusGoEventCallback call - event: " << event;
|
|
|
|
RCTStatusPrivate::rctStatus->emitStatusGoEvent(event);
|
2018-07-23 15:21:31 +00:00
|
|
|
}
|
|
|
|
|
2018-08-16 19:51:48 +00:00
|
|
|
void RCTStatus::emitStatusGoEvent(QString event) {
|
2019-10-01 17:52:20 +00:00
|
|
|
qCDebug(RCTSTATUS) << "::emitStatusGoEvent call - event: " << event;
|
|
|
|
Q_EMIT statusGoEvent(event);
|
2018-07-23 15:21:31 +00:00
|
|
|
}
|
|
|
|
|
2018-08-16 19:51:48 +00:00
|
|
|
void RCTStatus::onStatusGoEvent(QString event) {
|
2019-10-01 17:52:20 +00:00
|
|
|
qCDebug(RCTSTATUS) << "::onStatusGoEvent call - event: "
|
|
|
|
<< event.toUtf8().data();
|
|
|
|
RCTStatusPrivate::bridge->eventDispatcher()->sendDeviceEvent(
|
|
|
|
"gethEvent", QVariantMap{{"jsonEvent", event.toUtf8().data()}});
|
2018-07-23 15:21:31 +00:00
|
|
|
}
|
2018-09-14 16:52:14 +00:00
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
void RCTStatus::logStatusGoResult(const char *methodName, const char *result) {
|
|
|
|
QJsonParseError jsonError;
|
|
|
|
QJsonDocument jsonDoc =
|
|
|
|
QJsonDocument::fromJson(QString(result).toUtf8(), &jsonError);
|
|
|
|
if (jsonError.error != QJsonParseError::NoError) {
|
|
|
|
qCWarning(RCTSTATUS) << qUtf8Printable(jsonError.errorString());
|
|
|
|
return;
|
|
|
|
}
|
2018-09-14 16:52:14 +00:00
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
QString error = jsonDoc.toVariant().toMap().value("error").toString();
|
|
|
|
if (error.isEmpty()) {
|
|
|
|
qCDebug(RCTSTATUS) << methodName << "succeeded";
|
|
|
|
} else {
|
|
|
|
qCWarning(RCTSTATUS) << methodName << "- error:" << qUtf8Printable(error);
|
|
|
|
}
|
2018-09-14 16:52:14 +00:00
|
|
|
}
|
Add mailservers confirmations & use peer count for online status
We now check that we are only connected to some `peers` instead of using `NetInfo` from `react-native`.
This is because it has been reported to be quite flaky at times, not reporting online status after sleeping, and for privacy concerns (on ios it pings `apple.com`, on desktop `google.com`).
Adds a new banner `Wallet Offline` and change `Connecting to peers` to `Chat offline`.
A message will be marked as `Sent` only if it made it to the mailserver you are connected to, which will increase the guarantees that we can make about a message (if you see it as sent, it has reached at least a mailserver), this has the consequence that:
- If you are not connected to any mailserver or the mailserver is non responsive/down, and you send a message, it will be marked as `Not sent`, although it might have been actually made it in the network.
Probably this is something that we would like to communicate to the user through UX (i.e. tick if made it to at least a peer, double tick if it made to a mailserver )
Currently I have only enabled this feature in nightlies & devs, I would give it a run and see how we feel about it.
2018-12-06 10:53:45 +00:00
|
|
|
|
2019-10-01 17:52:20 +00:00
|
|
|
void RCTStatus::getNodesFromContract(QString url, QString address,
|
|
|
|
double callbackId) {
|
|
|
|
Q_D(RCTStatus);
|
|
|
|
qCDebug(RCTSTATUS) << "::getNodesFromContract call - callbackId:"
|
|
|
|
<< callbackId;
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](QString url, QString address, double callbackId) {
|
|
|
|
const char *result =
|
|
|
|
GetNodesFromContract(url.toUtf8().data(), address.toUtf8().data());
|
|
|
|
logStatusGoResult("::getNodesFromContract GetNodesFromContract",
|
|
|
|
result);
|
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{result});
|
|
|
|
},
|
|
|
|
url, address, callbackId);
|
2019-03-29 18:00:12 +00:00
|
|
|
}
|
|
|
|
|
2019-03-22 13:57:27 +00:00
|
|
|
void RCTStatus::chaosModeUpdate(bool on, double callbackId) {
|
2019-10-01 17:52:20 +00:00
|
|
|
Q_D(RCTStatus);
|
|
|
|
qCDebug(RCTSTATUS) << "::chaosModeUpdate call - callbackId:" << callbackId;
|
|
|
|
QtConcurrent::run(
|
|
|
|
[&](bool on, double callbackId) {
|
|
|
|
const char *result = ChaosModeUpdate(on);
|
|
|
|
logStatusGoResult("::chaosModeUpdate ChaosModeUpdate", result);
|
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{result});
|
|
|
|
},
|
|
|
|
on, callbackId);
|
2019-03-22 13:57:27 +00:00
|
|
|
}
|
2019-09-12 09:41:25 +00:00
|
|
|
|
|
|
|
QString RCTStatus::generateAlias(QString publicKey) {
|
2019-10-01 17:52:20 +00:00
|
|
|
Q_D(RCTStatus);
|
|
|
|
qCDebug(RCTSTATUS) << "::generateAlias call";
|
2019-11-28 10:00:29 +00:00
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
void RCTStatus::generateAliasAsync(QString publicKey, double callbackId) {
|
|
|
|
Q_D(RCTStatus);
|
|
|
|
qCDebug(RCTSTATUS) << "::generateAliasAsync call";
|
|
|
|
QByteArray b = publicKey.toUtf8();
|
|
|
|
const char *result = GenerateAlias({b.data(), b.length()});
|
|
|
|
qCDebug(RCTSTATUS) << "::generateAliasAsync call result"<<result;
|
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{result});
|
2019-09-12 09:41:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QString RCTStatus::identicon(QString publicKey) {
|
2019-10-01 17:52:20 +00:00
|
|
|
Q_D(RCTStatus);
|
|
|
|
qCDebug(RCTSTATUS) << "::identicon call";
|
2019-11-28 10:00:29 +00:00
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
void RCTStatus::identiconAsync(QString publicKey, double callbackId) {
|
|
|
|
Q_D(RCTStatus);
|
|
|
|
qCDebug(RCTSTATUS) << "::identiconAsync call";
|
|
|
|
QByteArray b = publicKey.toUtf8();
|
|
|
|
const char *result = Identicon({b.data(), b.length()});
|
|
|
|
qCDebug(RCTSTATUS) << "::identiconAsync call result"<<result;
|
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{result});
|
2019-09-12 09:41:25 +00:00
|
|
|
}
|
2019-11-28 10:00:29 +00:00
|
|
|
|
|
|
|
void RCTStatus::generateAliasAndIdenticonAsync(QString publicKey, double callbackId) {
|
|
|
|
Q_D(RCTStatus);
|
|
|
|
qCDebug(RCTSTATUS) << "::generateAliasAndIdenticonAsync call";
|
|
|
|
QByteArray pubKey = publicKey.toUtf8();
|
|
|
|
const char *alias = GenerateAlias({pubKey.data(), pubKey.length()});
|
|
|
|
const char *identicon = Identicon({pubKey.data(), pubKey.length()});
|
|
|
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{alias, identicon});
|
2020-01-08 14:41:07 +00:00
|
|
|
}
|