diff --git a/chain/wallet/autocomplete/HelpDictionaryController.cpp b/chain/wallet/autocomplete/HelpDictionaryController.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7047768a54bb30d103cc3bbd682e3d7ea63161ee --- /dev/null +++ b/chain/wallet/autocomplete/HelpDictionaryController.cpp @@ -0,0 +1,522 @@ +#include "HelpDictionaryController.h" +#include <QDebug> +#include <QJsonDocument> +#include <QJsonObject> +#include <QJsonArray> +#include <QSet> + +HelpDictionaryController::HelpDictionaryController() + :m_treeDictionary(new TreeDictionaryBase) +{} + +HelpDictionaryController::~HelpDictionaryController() +{ + delete m_treeDictionary; +} + +void HelpDictionaryController::setDictionary(const QJsonObject &tree) +{ + m_treeDictionary->dictionaryFromJSON(tree); +} + +bool HelpDictionaryController::isDictionary() +{ + return m_treeDictionary->isTree(); +} + +QStringList HelpDictionaryController::getHelpList(const QString& text, int cursorPosition) +{ + return getListVariants(text); +} + +QStringList HelpDictionaryController::getListVariants(const QString& text) +{ + if(text.isEmpty()) + { + return {}; + } + + QStringList resultList; + QStringList list = text.split(' '); + if(!m_treeDictionary->isTree()) + { + return {}; + } + TreeNode* resultNode = m_treeDictionary->getTree(); + + int size = list.size(); + int maxIndex = size - 1; + QVector<const QStringList *> variants; + QMap<QString, int> *mainOrList = nullptr; + QStringList currentList; + + QString wallet; + QString network; + + auto addToCurrListAndFilterVariants = [¤tList, &variants](const QString& name) + { + currentList.append(name); + int size = variants.size(); + for(int index = size - 1; index >= 0; --index) + { + auto& var = variants[index]; + if(!var->contains(name)) + { + variants.remove(index); + } + } + }; + + auto updateResulNode = [¤tList, &resultNode, this]() + { + QString mainName; + for(const QString& name: currentList) + { + if(!name.contains('-')) + { + mainName = name; + } + else + { + break; + } + } + + if(!m_treeDictionary) + { + return; + } + + TreeNode* minNode = m_treeDictionary->getTree(); + while(resultNode->previousNode != minNode) + { + resultNode = resultNode->previousNode; + + if((!resultNode->variantList.isEmpty() && resultNode->name == mainName)) + { + return; + } + } + }; + + bool isParametrLast = false; + + for(int i = 0; i < size; i++) + { + if(variants.isEmpty() && !resultNode->variantList.isEmpty()) + { + for(const auto& item: qAsConst(resultNode->variantList)) + { + variants.append(&item); + } + } + + if(!resultNode->orList.isEmpty() && !mainOrList) + { + mainOrList = &resultNode->orList; + } + + if(i < maxIndex) + { + if(i > 1) + { + if(list[i - 1] == "-w") + { + wallet = list[i]; + } + else if(list[i - 1] == "-net") + { + network = list[i]; + } + } + + if(resultNode->children.contains(list[i])) + { + resultNode = resultNode->children[list[i]]; + addToCurrListAndFilterVariants(resultNode->name); + continue; + } + else if(!resultNode->data.isEmpty() && resultNode->children.isEmpty()) + { + isParametrLast = false; + updateResulNode(); + continue; + } + else if(!resultNode->data.isEmpty() && !resultNode->children.isEmpty()) + { + if(!list[i].isEmpty()) + { + if(resultNode->children.contains(list[i])) + { + resultNode = resultNode->children[list[i]]; + addToCurrListAndFilterVariants(resultNode->name); + } + else + { + isParametrLast = true; + } + } + continue; + } + else if(resultNode->data.isEmpty() && resultNode->children.isEmpty() + && resultNode->previousNode != m_treeDictionary->getTree()) + { + updateResulNode(); + resultNode = resultNode->children[list[i]]; + addToCurrListAndFilterVariants(resultNode->name); + continue; + } + else if(resultNode->data.isEmpty() && resultNode->children.isEmpty() + && resultNode->previousNode == m_treeDictionary->getTree()) + { + continue; + } + } + else if(i == maxIndex) + { + bool isFilter = true; + if (list[i].isEmpty()) + { + int testIndex = i - 1; + if(testIndex >= 0 && list[testIndex] == resultNode->name + && resultNode->data.isEmpty() && resultNode->children.isEmpty()) + { + updateResulNode(); + } + else if(testIndex >= 0 && !list[testIndex].isEmpty() && + !resultNode->data.isEmpty() && !resultNode->children.isEmpty()) + { + //You don't have to do anything + } + else if(--testIndex >= 0 && list[testIndex] == resultNode->name && !resultNode->data.isEmpty()) + { + updateResulNode(); + } + } + if(resultNode->data.isEmpty() && !resultNode->children.isEmpty()) + { + QList<QString> tmpListKeys = resultNode->children.keys(); + for(const QString& key: qAsConst(tmpListKeys)) + { + if(key.contains(list[i])) + { + resultList.append(key); + } + } + } + else if (isParametrLast && !resultNode->data.isEmpty() && !resultNode->children.isEmpty()) + { + QList<QString> tmpListKeys = resultNode->children.keys(); + for(const QString& key: qAsConst(tmpListKeys)) + { + if(key.contains(list[i])) + { + resultList.append(key); + } + } + } + else if(!resultNode->data.isEmpty()) + { + isFilter = false; + QStringList tmpList; + tmpList.append(getListParamrtrs(wallet, network, resultNode->data)); + if(tmpList.isEmpty()) + { + qDebug()<< "problems with parameter data"; + return {}; + } + for(const QString& item: tmpList) + { + if(item.contains(list[i])) + { + resultList.append(item); + } + } + } + else if(resultNode->name == "help" && list.size() == 2) + { + isFilter = false; + resultList.append(resultNode->previousNode->children.keys()); + } + + if(!variants.isEmpty() && isFilter) + { + for(int index = resultList.size() - 1 ; index >= 0; index--) + { + bool isContain = false; + if(resultList[index].contains('<')) + { + continue; + } + + for(int var = 0; var < variants.size(); var++) + { + if(variants[var] && variants[var]->contains(resultList[index])) + { + isContain = true; + } + } + if(!isContain) + { + resultList.removeAt(index); + } + } + } + + for(const auto& item: qAsConst(list)) + { + if(resultList.contains(item)) + { + resultList.removeOne(item); + } + + if(mainOrList && !mainOrList->isEmpty() && mainOrList->contains(item)) + { + int number = mainOrList->value(item); + for(const QString& key: mainOrList->keys()) + { + if(key == item || key.isEmpty()) + { + continue; + } + + if(mainOrList->value(key) == number) + { + resultList.removeOne(key); + } + } + } + } + } + } + return resultList; +} + +void HelpDictionaryController::variantList(const QStringList& currentList, QVector<const QStringList *>& currentVariants) +{ + int size = currentVariants.size(); + for(int index = size - 1; index >= 0; --index) + { + if(!isHasCorrList(currentList, currentVariants[index])) + { + currentVariants.remove(index); + } + } +} + +bool HelpDictionaryController::isHasCorrList(const QStringList& currentList, const QStringList *testList) const +{ + for(const QString& item: currentList) + { + if(!testList->contains(item)) + { + return false; + } + } + return true; +} + +void HelpDictionaryController::setData(const QJsonObject &jData) +{ + if(jData.isEmpty()) + { + return; + } + + auto arrayToStringList = [](const QJsonArray& list) -> QStringList + { + QStringList result; + for(const auto& str: list) + { + result.append(str.toString()); + } + return result; + }; + + if(jData.contains("wallets")) + { + m_wallets = arrayToStringList(jData["wallets"].toArray()); + } + if(jData.contains("networks")) + { + m_networks = arrayToStringList(jData["networks"].toArray()); + } + if(jData.contains("pubCertName")) + { + m_pubCertName = arrayToStringList(jData["pubCertName"].toArray()); + } + if(jData.contains("privCertName")) + { + m_privCertName = arrayToStringList(jData["privCertName"].toArray()); + } + + auto jsonToMapStrL = [&arrayToStringList](const QJsonArray& list) -> QMap<QString, QStringList> + { + QMap<QString, QStringList> result; + for(const QJsonValue& item: list) + { + QJsonObject tmpItem = item.toObject(); + QString key = tmpItem["key"].toString(); + QStringList data = arrayToStringList(tmpItem["data"].toArray()); + result.insert(key, data); + } + return result; + }; + + if(jData.contains("chains")) + { + m_chains = jsonToMapStrL(jData["chains"].toArray()); + } + + if(jData.contains("mempoolTokensTicker")) + { + m_mempoolTokensTicker = jsonToMapStrL(jData["mempoolTokensTicker"].toArray()); + } + + auto jsonToTokenStruct = [&arrayToStringList](const QJsonArray& list) -> QMap<QPair<QString, QString>, QStringList> + { + QMap<QPair<QString, QString>, QStringList> result; + for(const auto& item: list) + { + QJsonObject tmpItem = item.toObject(); + QPair<QString, QString> key(tmpItem["wallet"].toString(), tmpItem["network"].toString()); + QStringList data = arrayToStringList(tmpItem["data"].toArray()); + result.insert(key, data); + } + return result; + }; + + if(jData.contains("tokensTicker")) + { + m_tokensTicker = jsonToTokenStruct(jData["tokensTicker"].toArray()); + } +} + +QStringList HelpDictionaryController::getListParamrtrs(const QString& wallet, const QString& net, const QStringList& curData) +{ + if(curData.size() == 1) + { + QSet<QString> result; + auto addToResult = [&result](const QStringList& list) + { + for(const QString& item: list) + { + result.insert(item); + } + }; + const QString& data = curData[0]; + if(data == "<priv_cert_name>") + { + return m_privCertName; + } + else if(data == "<pub_cert_name>") + { + return m_pubCertName; + } + else if(data == "<net_name>" || data == "<chain_net_name>") + { + return m_networks; + } + else if(data == "<wallet_name>") + { + return m_wallets; + } + else if(data == "<token_ticker>") + { + if(wallet.isEmpty() && net.isEmpty()) + { + for(const QStringList& tickers: qAsConst(m_tokensTicker)) + { + addToResult(tickers); + } + } + else if(!wallet.isEmpty() && net.isEmpty()) + { + for(const QString& item: qAsConst(m_networks)) + { + QPair<QString,QString> key({wallet, item}); + if(m_tokensTicker.contains(key)) + { + addToResult(m_tokensTicker[key]); + } + } + } + else if(wallet.isEmpty() && !net.isEmpty()) + { + for(const QString& item: qAsConst(m_wallets)) + { + QPair<QString,QString> key({item, net}); + if(m_tokensTicker.contains(key)) + { + addToResult(m_tokensTicker[key]); + } + } + } + else + { + QPair<QString,QString> key({wallet, net}); + if(m_tokensTicker.contains(key)) + { + addToResult(m_tokensTicker[key]); + } + } + return result.values(); + } + else if(data == "<mempool_token_ticker>") + { + if(net.isEmpty()) + { + for(const QStringList& item: qAsConst(m_mempoolTokensTicker)) + { + if(!item.isEmpty()) + { + addToResult(item); + } + } + } + else + { + if(m_mempoolTokensTicker.contains(net)) + { + if(!m_mempoolTokensTicker[net].isEmpty()) + { + addToResult(m_mempoolTokensTicker[net]); + } + } + } + return result.values(); + } + else if(data == "<chain_name>") + { + if(net.isEmpty()) + { + for(const QStringList& item: qAsConst(m_chains)) + { + if(!item.isEmpty()) + { + addToResult(item); + } + } + } + else + { + if(m_chains.contains(net)) + { + if(!m_chains[net].isEmpty()) + { + addToResult(m_chains[net]); + } + } + } + return result.values(); + } + else + { + return QStringList(curData); + } + } + else + { + return curData; + } +} diff --git a/chain/wallet/autocomplete/HelpDictionaryController.h b/chain/wallet/autocomplete/HelpDictionaryController.h new file mode 100644 index 0000000000000000000000000000000000000000..9cebcc9398d19e1a221cb3b02d42ec3e04d6c282 --- /dev/null +++ b/chain/wallet/autocomplete/HelpDictionaryController.h @@ -0,0 +1,49 @@ +#ifndef HELPDICTIONARYCONTROLLER_H +#define HELPDICTIONARYCONTROLLER_H + +#include <QString> +#include <QStringList> +#include "TreeDictionaryBase.h" + + +class HelpDictionaryController +{ +public: + HelpDictionaryController(); + ~HelpDictionaryController(); + + void setDictionary(const QJsonObject &tree); + bool isDictionary(); + + void setData(const QJsonObject &jData); + void setNodeVersion(const QString& version){m_nodeVersion = version;} + const QString& getNodeVersion() {return m_nodeVersion;} + + QStringList getHelpList(const QString& text, int cursorPosition); +private: + void getDictionary(); + + QStringList getListVariants(const QString &text); + QStringList getListParamrtrs(const QString& wallet, const QString& net, const QStringList &curData); + + inline bool isHasCorrList(const QStringList& currentList, const QStringList *testList) const; + inline void variantList(const QStringList& currentList, QVector<const QStringList *>& currentVariants); + +private: + TreeDictionaryBase* m_treeDictionary = nullptr; + + QString m_nodeVersion = ""; + + QStringList m_wallets; + QStringList m_networks; + QStringList m_pubCertName; + QStringList m_privCertName; + // network chains + QMap<QString, QStringList> m_chains; + // <wallet, network>, tickers + QMap<QPair<QString, QString>, QStringList> m_tokensTicker; + // net, tickers + QMap<QString, QStringList> m_mempoolTokensTicker; +}; + +#endif // HELPDICTIONARYCONTROLLER_H diff --git a/chain/wallet/autocomplete/HelpDictionaryServiceController.cpp b/chain/wallet/autocomplete/HelpDictionaryServiceController.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f22f4e900fc2e49ed7187f062c8412fa84ceadaa --- /dev/null +++ b/chain/wallet/autocomplete/HelpDictionaryServiceController.cpp @@ -0,0 +1,802 @@ +#include "HelpDictionaryServiceController.h" +#include <QJsonDocument> +#include <QJsonObject> +#include <QStack> +#include <QHash> +#include <QJsonArray> +#include "../handlers/DapCommandList.h" + +HelpDictionaryServiceController::HelpDictionaryServiceController(QString cliPath, QObject *parent) + : QObject{parent} + , m_sCliPath(cliPath) + , m_treeDictionary(new TreeDictionaryBase()) +{ + onInit(); +} + +HelpDictionaryServiceController::~HelpDictionaryServiceController() +{ + delete m_treeDictionary; +} + +void HelpDictionaryServiceController::setNodeVersion(const QString& version, bool isUpdate) +{ + m_nodeVersion = version; + if(isUpdate) + { + tryTestVersions(); + } +} + +void HelpDictionaryServiceController::tryTestVersions() +{ + if(!m_nodeVersion.isEmpty() && m_nodeVersion != m_nodeVersionFromFile) + { + newDictionary(); + } +} + +QJsonDocument HelpDictionaryServiceController::getJsonDictionary() +{ + if(m_treeDictionary->isTree()) + { + return QJsonDocument(m_treeDictionary->getJSONTree()); + } + + if(loadDictionary()) + { + return QJsonDocument(m_treeDictionary->getJSONTree()); + } + else + { + return getNewJsonDictionary(); + } + return {}; +} + +bool HelpDictionaryServiceController::newDictionary() +{ + if(m_nodeVersion.isEmpty()) + { + return false; + } + + if(auto* node = creatDictionary()) + { + m_treeDictionary->setTree(node); + if(!saveDictionary()) + { + qWarning() << "Dictionory is not saved"; + } + m_nodeVersionFromFile = m_nodeVersion; + return true; + } + else + { + qWarning() << "couldn't create a dictionary"; + } + return false; +} + +QJsonDocument HelpDictionaryServiceController::getNewJsonDictionary() +{ + return newDictionary() ? QJsonDocument(m_treeDictionary->getJSONTree()) : QJsonDocument(); +} + +void HelpDictionaryServiceController::onInit() +{ + // TODO: For tests, if you need to forcibly get a new tree + //newDictionary(); + if(!m_treeDictionary->isTree()) + { + if(!loadDictionary()) + { + newDictionary(); + } + else + { + m_nodeVersion = m_nodeVersionFromFile; + } + } +} + +bool HelpDictionaryServiceController::saveDictionary() +{ + QJsonObject resultObject; + QJsonObject treeJson = m_treeDictionary->getJSONTree(); + resultObject["data"] = std::move(treeJson); + resultObject["version"] = m_nodeVersion; + QJsonDocument jsonDocument(resultObject); + QFile file(FILE_NAME); + if (!file.open(QIODevice::WriteOnly)) + { + qDebug() << "File is not created"; + return false; + } + qint64 result = file.write(jsonDocument.toBinaryData()); + file.close(); + return result > -1; +} + +bool HelpDictionaryServiceController::loadDictionary() +{ + QFile file(FILE_NAME); + if (!file.open(QIODevice::ReadOnly)) + { + qDebug() << "File not opened"; + return false; + } + QByteArray jsonData = file.readAll(); + file.close(); + QJsonDocument jsonDocument = QJsonDocument::fromBinaryData(jsonData); + if (jsonDocument.isNull()) + { + qDebug() << "Error when reading a JSON document from a file"; + return false; + } + else if (!jsonDocument.isObject()) + { + qDebug() << "A JSON document is not an object"; + return false; + } + QJsonObject resultObject = jsonDocument.object(); + if(!resultObject.contains("data") || !resultObject.contains("version")) + { + qWarning() << "Data is broken"; + } + m_nodeVersionFromFile = resultObject["version"].toString(); + m_treeDictionary->dictionaryFromJSON(resultObject["data"].toObject()); + return true; +} + +QVector<QPair<QString, int>> HelpDictionaryServiceController::findSubstrings(QString &input, const char openCurl, const char closeCurl) +{ + QStack<int> stack; + QVector<QPair<QString, int>> substrings; + QStack<QPair<int,int>> stackForDelete; + QString substring; + int open = input.count(openCurl); + int close = input.count(closeCurl); + if(open != close) + { + qWarning() << "Incorrect number of brackets, input data error. String: " << input; + } + + for (int i = 0; i < input.length(); i++) + { + QChar currentChar = input[i]; + + if (currentChar == openCurl) + { + stack.push(i); + } + + else if (currentChar == closeCurl && !stack.isEmpty()) + { + int startIndex = stack.pop(); + int stopIndex = i - startIndex; + int stackSize = stack.size(); + substring = input.mid(startIndex + 1, stopIndex - 1); + if(stackSize == 0) + { + stackForDelete.push_back({startIndex, stopIndex + 1}); + } + + // If there are problems with brackets, + // then we output an empty container, + // but we delete everything in brackets anyway. + if(open == close) + { + substrings.append({substring, stackSize}); + } + } + } + + // Delete the extra lines + while(!stackForDelete.isEmpty()) + { + QPair<int, int> pair = stackForDelete.pop(); + input.remove(pair.first, pair.second); + } + + return substrings; +} + +TreeNode *HelpDictionaryServiceController::creatDictionary() +{ + QMap<QString, QString> rawData = getRawData(); + + int counterIsLists = 0; + + TreeNode* resultNode = new TreeNode(); + + for(const QString &key: rawData.keys()) + { + TreeNode commandNode; + //TODO: if you need to check the output of a specific command + //key = "global_db"; + + QStringList list = rawData[key].split(QString("\n")); + + for(int i = 1; i < list.size(); i++) + { + QString& str = list[i]; + if(!str.startsWith(key)) + { + continue; + } + TreeNode* tmpLastNode = resultNode; + + QStringList mainLineList; + QVector<TmpDataStruct> mainMondatoryParam; + mainParamParce(str, mainLineList, mainMondatoryParam); + + QVector<QPair<QString, int>> unnecessExpress = findSubstrings(str); + QVector<QPair<QString, int>> necessExpress = findSubstrings(str, '{', '}'); + + int currLayerNode = 0; + int zeroLayerNode = 0; + + auto addToNode = [&tmpLastNode, &currLayerNode] + (QPair<QString, TreeNode*> itemNode, int layer, bool toOptional = false, int curVariantCount = 0) + { + itemNode.second->name = itemNode.first.trimmed(); + TreeNode *parentNode = nullptr; + if(currLayerNode == layer) + { + itemNode.second->previousNode = tmpLastNode->previousNode; + tmpLastNode->previousNode->children.insert(itemNode.first.trimmed(), itemNode.second); + parentNode = tmpLastNode->previousNode; + tmpLastNode = itemNode.second; + } + else if(currLayerNode < layer) + { + currLayerNode = layer; + itemNode.second->previousNode = tmpLastNode; + tmpLastNode->children.insert(itemNode.first.trimmed(), itemNode.second); + parentNode = tmpLastNode; + tmpLastNode = itemNode.second; + } + else if(currLayerNode > layer) + { + int dif = currLayerNode - layer; + currLayerNode = layer; + while(dif) + { + if(tmpLastNode->previousNode){ + tmpLastNode = tmpLastNode->previousNode; + --dif; + } + else + { + qWarning()<< "Probably an attempt to access a non-existent value"; + break; + } + } + itemNode.second->previousNode = tmpLastNode->previousNode; + tmpLastNode->previousNode->children.insert(itemNode.first.trimmed(), itemNode.second); + parentNode = tmpLastNode->previousNode; + tmpLastNode = itemNode.second; + } + + if(parentNode) + { + if(toOptional) + { + parentNode->optionalList.append(itemNode.first); + } + if(curVariantCount != 0) + { + parentNode->orList.insert(itemNode.first, curVariantCount); + } + } + }; + + for(auto& item: mainLineList) + { + if(tmpLastNode->children.contains(item)) + { + tmpLastNode = tmpLastNode->children[item]; + continue; + } + TreeNode* nodeNew = new TreeNode(); + QPair<QString, TreeNode *> tmpData = {item, nodeNew}; + addToNode(tmpData, ++zeroLayerNode); + } + TreeNode* lastMainNode = tmpLastNode; + QStringList listParam; + + auto appendToMainLineList = [&mainLineList](const QString& str) + { + QString tmpStr = str.trimmed(); + if(!tmpStr.isEmpty()) + { + mainLineList.append(tmpStr); + } + }; + + zeroLayerNode++; + for(auto& item: mainMondatoryParam) + { + addToNode({item.paramName, item.node}, zeroLayerNode); + appendToMainLineList(item.paramName); + } + + for(int u = unnecessExpress.size() - 1; u >= 0 ; --u) + { + QVector<TmpDataStruct> unmondatoryParam; + mainParamParce(unnecessExpress[u].first, mainLineList, unmondatoryParam, false); + for(auto& item: unmondatoryParam) + { + int layer = zeroLayerNode + unnecessExpress[u].second; + addToNode({item.paramName,item.node}, layer, true); + if(layer == zeroLayerNode) + { + appendToMainLineList(item.paramName); + } + } + } + + for(int n = necessExpress.size() - 1; n >= 0 ; --n) + { + QVector<TmpDataStruct> mondatoryParam; + + if(necessExpress[n].first.contains('{')) + { + + int nextCount = n - 1; + if(nextCount >= 0 && necessExpress[n].first.contains(necessExpress[nextCount].first)) + { + int index = necessExpress[n].first.indexOf(necessExpress[nextCount].first); + necessExpress[n].first.remove(index, necessExpress[nextCount].first.size()); + } + else + { + qWarning() << "Has a probem in help for " << key; + } + } + + QStringList orParam = necessExpress[n].first.split('|'); + int localCounterIsLists = ++counterIsLists; + for(int orCount = 0; orCount < orParam.size(); orCount++) + { + if(orParam[orCount].contains('{')) + { + mainParamParce(orParam[orCount], mainLineList, mondatoryParam, false, 0, localCounterIsLists); + + if(n - 1 >= 0) + { + n--; + if(necessExpress[n].first.contains('|')) + { + QStringList orParamChild = necessExpress[n].first.split('|'); + ++counterIsLists; + for(auto& item: orParamChild) + { + mainParamParce(item, mainLineList, mondatoryParam, false, 1, counterIsLists); + } + } + else + { + mainParamParce(necessExpress[n].first, mainLineList, mondatoryParam, false, 1, localCounterIsLists); + } + } + } + else + { + mainParamParce(orParam[orCount], mainLineList, mondatoryParam, false, 0, localCounterIsLists); + } + } + + for(auto& item: mondatoryParam) + { + int layer = zeroLayerNode + item.layer; + addToNode({item.paramName, item.node}, layer, false, item.countOrList); + mainLineList.append(item.paramName); + } + } + TreeNode* tmpMain = lastMainNode; + while(tmpMain->name != key) + { + tmpMain = tmpMain->previousNode; + } + if(tmpMain != lastMainNode) + { + tmpMain->variantList.append(mainLineList); + } + lastMainNode->variantList.append(std::move(mainLineList)); + } + } + return std::move(resultNode); +} + +QMap<QString, QString> HelpDictionaryServiceController::getRawData() +{ + QMap<QString, QString> result; + QString helpCmd = QString(m_sCliPath + " " + CMD_HELP); + QString dataList = requestToNode(helpCmd); + QStringList list = dataList.split('\n'); + QRegularExpression regularHelp(R"(^(\w+):)"); + for(const auto &str: list) + { + QRegularExpressionMatch command = regularHelp.match(str); + auto lst = command.capturedTexts(); + if(command.hasMatch() && !command.captured(1).isEmpty()) + { + QString tmpResult = requestToNode(m_sCliPath + " " + CMD_HELP + " " + command.captured(1)); + result.insert(command.captured(1), std::move(tmpResult)); + } + } + return result; +} + +QString HelpDictionaryServiceController::requestToNode(QString cmd) +{ + QProcess process; + process.start(cmd); + + if(process.waitForFinished(10000)) + return QString::fromLatin1(process.readAll()); + else{ + qWarning()<<QString("Timeout request: %1").arg(cmd); + return QString(); + } +} + +HelpDictionaryServiceController::TmpDataStruct::TmpDataStruct(const QString& name, TreeNode* node, const int layer, const int countOrList) + : paramName(name) + , node(node) + , layer(layer) + , countOrList(countOrList) +{} + +void HelpDictionaryServiceController::mainParamParce(QString& str, QStringList& mainList, + QVector<TmpDataStruct> ¶ms + , bool isNeedMain + , int layer + , int orCount) +{ + if(str.count('<') != str.count('>') + || str.count('[') != str.count(']') + || str.count('{') != str.count('}')) + { + qWarning() << "String: " << str << " has problem"; + } + + QVector<QString> list; + QString tmpStr; + QStack<int> triangl; + QStack<int> rect; + QStack<int> fig; + int startSq = -1; + QStack<QPair<int,int>> indexesForDel; + QVector<QString> nonDelList; + QVector<char> keySymbols = {' ', '<', '>', '[', ']', '{', '}'}; + + auto addStrToList = [&tmpStr, &list](){ + if(!tmpStr.isEmpty() && tmpStr != ' ') + { + list.append(tmpStr); + tmpStr.clear(); + } + }; + + for(int i = 0; i < str.size(); i++) + { + bool isSpace = str[i] == keySymbols[0]; + bool isTriangeOpen = str[i] == keySymbols[1]; + bool isTriangeClose = str[i] == keySymbols[2]; + bool isRectOpen = str[i] == keySymbols[3]; + bool isRectClose = str[i] == keySymbols[4]; + bool isBraceOpen = str[i] == keySymbols[5]; + bool isBraceClose = str[i] == keySymbols[6]; + + if(!keySymbols.contains(str[i].toLatin1())) + { + if(rect.isEmpty()) + { + tmpStr +=str[i]; + } + + } + else if(isRectOpen) + { + rect.push_back(i); + addStrToList(); + if(rect.size() == 1) + { + startSq = i; + tmpStr = "[]"; + addStrToList(); + } + } + else if(isRectClose) + { + rect.pop(); + indexesForDel.append({startSq, i-startSq + 1}); + startSq = -1; + } + else if(!rect.empty()) + { + continue; + } + else if(isSpace) + { + if(triangl.isEmpty() && fig.isEmpty() && rect.isEmpty()) + { + addStrToList(); + } + else if(!triangl.isEmpty() || !fig.isEmpty()) + { + tmpStr +=str[i]; + } + } + else if(isTriangeOpen && !fig.empty()) + { + tmpStr +=str[i]; + } + else if(isTriangeClose && !fig.empty()) + { + tmpStr +=str[i]; + } + else if(isTriangeOpen && fig.empty()) + { + if(triangl.isEmpty()) + { + addStrToList(); + } + triangl.push_back(i); + tmpStr +=str[i]; + } + else if(isTriangeClose && fig.empty()) + { + tmpStr +=str[i]; + triangl.pop(); + if(triangl.empty()) + { + addStrToList(); + } + } + else if(isBraceOpen) + { + if(fig.isEmpty()) + { + addStrToList(); + } + fig.push_back(i); + tmpStr +=str[i]; + } + else if(isBraceClose) + { + tmpStr +=str[i]; + fig.pop(); + if(fig.isEmpty()) + { + addStrToList(); + } + } + + if(str.size() == i + 1) + { + addStrToList(); + } + } + + auto addNondelList = [&indexesForDel, &str, &nonDelList](){ + if(!indexesForDel.isEmpty()) + { + while(!indexesForDel.isEmpty()) + { + auto item = indexesForDel.pop(); + nonDelList.append(str.mid(item.first, item.second)); + str.remove(item.first, item.second); + } + } + }; + + addNondelList(); + + int sizeList = list.size(); + bool isMainEnd = isNeedMain ? false : true; + QVector<int> blackList; + + for(int i = 0; i < sizeList; i++) + { + if(i == 0 && !isMainEnd) + { + mainList.append(list[i]); + continue; + } + + bool isDashCur = list[i].contains('-'); + bool isTrienglCur = list[i].contains('<'); + bool isCurlyCur = list[i].contains('{'); + bool isOrCur = list[i].contains('|'); + bool isRectCur = list[i].contains('['); + + // {-cert <cert name> | -hash <cert hash>} current value + if(isCurlyCur && (isDashCur || isOrCur || isTrienglCur)) + { + blackList.append(i); + int index = str.indexOf(list[i]); + indexesForDel.append({index, index + list[i].size()}); + continue; + } + else if(isRectCur) + { + continue; + } + if(i + 1 >= sizeList) + { + if(!isRectCur && !isCurlyCur && !isTrienglCur) + { + + params.append({list[i], new TreeNode(), layer, orCount}); + } + continue; + } + + bool isDashNext = list[i + 1].contains('-'); + bool isTrienglNext = list[i + 1].contains('<'); + bool isCurlyNext = list[i + 1].contains('{'); + bool isOrNext = list[i + 1].contains('|'); + bool isRectNext = list[i + 1].contains('['); + bool isPointTrienglNext = list[i + 1].contains(".<"); + + if(!isRectNext && i + 1 >= sizeList) + { + params.append(TmpDataStruct(list[i], new TreeNode(), layer, orCount)); + } + + if((!isOrCur && !isCurlyCur && !isTrienglCur) && + isRectNext && !isMainEnd) + { + mainList.append(list[i]); + isMainEnd = true; + continue; + } + if(!isMainEnd && !isOrNext && !isTrienglNext && (!isOrCur && !isCurlyCur && !isTrienglCur)) + { + mainList.append(list[i]); + continue; + } + else if(!isMainEnd && (!isOrCur && !isCurlyCur && !isTrienglCur) && isDashNext) + { + mainList.append(list[i]); + isMainEnd = true; + continue; + } + else if(!isMainEnd && isTrienglNext) + { + isMainEnd = true; + } + + //ca del -hash + if((!isOrCur && !isCurlyCur && !isTrienglCur) && + (!isOrNext && !isCurlyNext && !isTrienglNext && !isRectNext)) + { + if(i + 2 < sizeList) + { + if(!list[i + 2].contains('<') && !list[i + 2].contains('{')) + { + if(!isMainEnd) + { + mainList.append(list[i]); + i++; + mainList.append(list[i]); + } + else + { + params.append(TmpDataStruct(list[i], new TreeNode(), layer, orCount)); + i++; + params.append(TmpDataStruct(list[i], new TreeNode(), layer, orCount)); + } + } + else + { + params.append(TmpDataStruct(list[i], new TreeNode(), layer, orCount)); + } + } + else + { + if(!isMainEnd) + { + mainList.append(list[i]); + } + else + { + params.append(TmpDataStruct(list[i], new TreeNode(), layer, orCount)); + params.append(TmpDataStruct(list[i + 1], new TreeNode(), layer, orCount)); + i++; + } + } + continue; + } + else + { + if(!isMainEnd) + { + isMainEnd = true; + } + } + + // -mode {update | all}, go {online | offline | sync} + // -from {events | events_lasts | threshold | round.new | round.<Round id in hex>} + if((!isOrCur && !isCurlyCur && !isTrienglCur) + && ((isOrNext && isCurlyNext && !isTrienglNext && !isDashNext && !isRectNext) + || (isOrNext && isCurlyNext && isPointTrienglNext && !isDashNext && !isRectNext))) + { + TreeNode* tmpNode = new TreeNode(); + QString& secondParam = list[i+1]; + QStringList paramsList = secondParam.split('|'); + for(QString& strList: paramsList) + { + strList.remove('{'); + strList.remove('}'); + tmpNode->data.append(strList.trimmed()); + } + params.append(TmpDataStruct(list[i], std::move(tmpNode), layer, orCount)); + i++; + continue; + } + + // {-cert <cert name> | -hash <cert hash>} next value + if((!isOrCur && !isCurlyCur && !isTrienglCur) && isCurlyNext + && (isDashNext || isOrNext || isTrienglNext) && !isPointTrienglNext) + { + if(!isMainEnd) + { + mainList.append(list[i]); + isMainEnd = true; + } + else + { + params.append(TmpDataStruct(list[i], new TreeNode(), layer, orCount)); + } + continue; + } + + // list [-from_hash <block_hash>] + if((!isOrCur && !isCurlyCur && !isTrienglCur) && isRectNext) + { + if(!isMainEnd) + { + mainList.append(list[i]); + isMainEnd = true; + } + else + { + params.append(TmpDataStruct(list[i], new TreeNode(), layer, orCount)); + } + continue; + } + + // -n <chain net name> + if((!isOrCur && !isCurlyCur && !isTrienglCur) && + (!isOrNext && !isCurlyNext && isTrienglNext && !isDashNext && !isRectNext)) + { + TreeNode* tmpNode = new TreeNode(); + tmpNode->data.append(list[i+1]); + params.append(TmpDataStruct(list[i], std::move(tmpNode), layer, orCount)); + i++; + continue; + } + } + + addNondelList(); + + for(int i = 0; i < sizeList; i++ ) + { + if (!blackList.contains(i) && !list[i].contains('[')) + { + int index = str.indexOf(list[i]); + str.remove(index, list[i].size()); + } + } + str = str.trimmed(); + for(auto& item: nonDelList) + { + str += item; + } +} + diff --git a/chain/wallet/autocomplete/HelpDictionaryServiceController.h b/chain/wallet/autocomplete/HelpDictionaryServiceController.h new file mode 100644 index 0000000000000000000000000000000000000000..0cbd0f8ef20333717e3d0d91b985a04662de72ee --- /dev/null +++ b/chain/wallet/autocomplete/HelpDictionaryServiceController.h @@ -0,0 +1,68 @@ +#pragma once +#include <QObject> +#include <QProcess> +#include <QString> +#include <QStringList> +#include <QMap> +#include <QDir> +#include <QFile> +#include <QDebug> +#include <QRegularExpression> +#include <QRegularExpressionMatch> +#include <QRegularExpressionMatchIterator> + +#include "TreeDictionaryBase.h" + +class HelpDictionaryServiceController : public QObject +{ + Q_OBJECT + + struct TmpDataStruct + { + QString paramName = ""; + TreeNode* node = nullptr; + int layer = 0; + int countOrList = 0; + + TmpDataStruct(const QString& name, TreeNode* node, const int layer, const int countOrList = 0); + }; + +public: + explicit HelpDictionaryServiceController(QString cliPath, QObject *parent = nullptr); + ~HelpDictionaryServiceController(); + + QJsonDocument getJsonDictionary(); + QJsonDocument getNewJsonDictionary(); + + void setNodeVersion(const QString& version, bool isUpdate = true); + const QString& getNodeVersion() {return m_nodeVersion;} +private: + void tryTestVersions(); + + bool newDictionary(); + void onInit(); + TreeNode* creatDictionary(); + bool saveDictionary(); + bool loadDictionary(); + + QMap<QString, QString> getRawData(); + + QString requestToNode(QString cmd); + QVector<QPair<QString, int>> findSubstrings(QString& input, const char openCurl = '[', const char closeCurl = ']'); + + void mainParamParce(QString& str, QStringList &mainList + , QVector<TmpDataStruct> ¶ms + , bool isNeedMain = true, int layer = 0, int orCount = 0); + +private: + QString m_sCliPath; + + TreeDictionaryBase* m_treeDictionary = nullptr; + QString m_nodeVersion = ""; + QString m_nodeVersionFromFile = ""; + +private: //const property + const QString CMD_HELP = "help"; + const QString FILE_NAME = "HelpDictionary.bin"; +}; + diff --git a/chain/wallet/autocomplete/TreeDictionaryBase.cpp b/chain/wallet/autocomplete/TreeDictionaryBase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..62ff9c9b8290d389411c8fb2bcecb16cf13aeaf7 --- /dev/null +++ b/chain/wallet/autocomplete/TreeDictionaryBase.cpp @@ -0,0 +1,190 @@ +#include "TreeDictionaryBase.h" +#include <QJsonObject> +#include <QJsonArray> + +TreeNode::~TreeNode() +{ + for(TreeNode* item: qAsConst(children)) + { + delete item; + } +} + +TreeDictionaryBase::TreeDictionaryBase() +{} + +TreeDictionaryBase::~TreeDictionaryBase() +{ + if(m_tree) + { + delete m_tree; + } +} + +QJsonObject TreeDictionaryBase::intMapToJson(const QMap<QString, int>& map) +{ + QJsonObject json; + for (auto it = map.begin(); it != map.end(); ++it) { + json[it.key()] = it.value(); + } + return json; +} + +QMap<QString, int> TreeDictionaryBase::intMapFromJson(const QJsonObject& json) +{ + QMap<QString, int> map; + for (auto it = json.begin(); it != json.end(); ++it) { + map[it.key()] = it.value().toInt(); + } + return map; +} + +QJsonArray TreeDictionaryBase::stringListToJson(const QStringList& list) +{ + QJsonArray json; + for (const auto& str : list) { + json.append(str); + } + return json; +} + +QStringList TreeDictionaryBase::stringListFromJson(const QJsonArray& json) +{ + QStringList list; + for (const auto& val : json) { + list.append(val.toString()); + } + return list; +} + +QJsonArray TreeDictionaryBase::vectorStringListToJson(const QVector<QStringList>& vec) +{ + QJsonArray json; + for (const auto& list : vec) { + json.append(stringListToJson(list)); + } + return json; +} + +QVector<QStringList> TreeDictionaryBase::vectorStringListFromJson(const QJsonArray& json) +{ + QVector<QStringList> vec; + for (const auto& val : json) { + vec.append(stringListFromJson(val.toArray())); + } + return vec; +} + +QJsonObject TreeDictionaryBase::getJSONTree() +{ + if(!m_tree) + { + qDebug() << "it is not possible to convert to json because a tree has not been created"; + return {}; + } + QJsonObject result; + for(auto& key: m_tree->children.keys()) + { + result.insert(key, recursiveGetJSONTree(m_tree->children.value(key))); + } + return result; +} + +QJsonObject TreeDictionaryBase::recursiveGetJSONTree(TreeNode* node) +{ + QJsonObject result; + result.insert("name", node->name); + + if(!node->orList.isEmpty()) + { + result.insert("orList", intMapToJson(node->orList)); + } + if(!node->optionalList.isEmpty()) + { + result.insert("optionalList", QJsonArray::fromStringList(node->optionalList)); + } + if(!node->data.isEmpty()) + { + result.insert("data", QJsonArray::fromStringList(node->data)); + } + if(!node->variantList.isEmpty()) + { + result.insert("variantList", vectorStringListToJson(node->variantList)); + } + if(!node->children.isEmpty()) + { + QJsonObject children; + for(auto& key: node->children.keys()) + { + children.insert(key, recursiveGetJSONTree(node->children.value(key))); + } + result.insert("children", children); + } + return result; +} + +void TreeDictionaryBase::dictionaryFromJSON(const QJsonObject& tree) +{ + if(tree.isEmpty()) + { + return; + } + + TreeNode* node = new TreeNode(); + + auto keys = tree.keys(); + for(auto key: keys) + { + TreeNode* tmpNode = new TreeNode(); + recursiveTreeNodeFromJson(tmpNode, tree[key].toObject()); + tmpNode->previousNode = node; + node->children.insert(key, tmpNode); + } + + if(m_tree) + { + delete m_tree; + } + + m_tree = std::move(node); +} + +void TreeDictionaryBase::recursiveTreeNodeFromJson(TreeNode* node, const QJsonObject& tree) +{ + if(tree.contains("name")) + { + node->name = tree["name"].toString(); + + } + if(tree.contains("orList")) + { + node->orList.insert(intMapFromJson(tree["orList"].toObject())); + } + if(tree.contains("optionalList")) + { + QStringList list = stringListFromJson(tree["optionalList"].toArray()); + node->optionalList.append(list); + } + if(tree.contains("data")) + { + QStringList list = stringListFromJson(tree["data"].toArray()); + node->data.append(list); + } + if(tree.contains("variantList")) + { + QVector<QStringList> list = vectorStringListFromJson(tree["variantList"].toArray()); + node->variantList.append(list); + } + + if(tree.contains("children")) + { + auto keys = tree["children"].toObject().keys(); + for(auto key: keys) + { + TreeNode* tmpNode = new TreeNode(); + recursiveTreeNodeFromJson(tmpNode, tree["children"][key].toObject()); + tmpNode->previousNode = node; + node->children.insert(key, tmpNode); + } + } +} diff --git a/chain/wallet/autocomplete/TreeDictionaryBase.h b/chain/wallet/autocomplete/TreeDictionaryBase.h new file mode 100644 index 0000000000000000000000000000000000000000..de3abfb74437b4d59c1fe329f4d876df05e3cacd --- /dev/null +++ b/chain/wallet/autocomplete/TreeDictionaryBase.h @@ -0,0 +1,61 @@ +#ifndef TREEDICTIONARYBASE_H +#define TREEDICTIONARYBASE_H + +#include <QObject> +#include <QMap> +#include <QHash> +#include <QString> +#include <QStringList> +#include <QVector> + +/// The structure of the tree node. +/// children - Branching is carried out. here are the main parameters. +/// data - data for the specified parameter. +/// variantList - the branches of variants are recorded. +/// To filter out the data in the list. +/// orList - to filter out the list of parameters that should not be together. +/// optionalLast - parameters that are not required to execute the command. +/// previousNode - is the address of the previous note for maneuvering through the list. +/// Creates a bidirectional graph. +/// name - the name of the node to clarify the position. +struct TreeNode +{ + QString name = ""; + QHash<QString, TreeNode*> children; + TreeNode* previousNode = nullptr; + QMap<QString, int> orList; + QStringList optionalList; + QStringList data; + QVector<QStringList> variantList; + + ~TreeNode(); +}; + +class TreeDictionaryBase +{ +public: + TreeDictionaryBase(); + ~TreeDictionaryBase(); + + TreeNode* getTree() const {return m_tree;} + void setTree(TreeNode* tree) { m_tree = tree;} + + bool isTree() {return m_tree != nullptr;} + + QJsonObject getJSONTree(); + void dictionaryFromJSON(const QJsonObject &tree); +private: + void recursiveTreeNodeFromJson(TreeNode* node, const QJsonObject &tree); + QJsonObject recursiveGetJSONTree(TreeNode* node); + QVector<QStringList> vectorStringListFromJson(const QJsonArray& json); + QJsonArray vectorStringListToJson(const QVector<QStringList>& vec); + QStringList stringListFromJson(const QJsonArray& json); + QJsonArray stringListToJson(const QStringList& list); + QMap<QString, int> intMapFromJson(const QJsonObject& json); + QJsonObject intMapToJson(const QMap<QString, int>& map); + +private: + TreeNode* m_tree = nullptr; +}; + +#endif // TREEDICTIONARYBASE_H diff --git a/chain/wallet/dapRPCProtocol/DapRpcLocalServer.cpp b/chain/wallet/dapRPCProtocol/DapRpcLocalServer.cpp index 63b7e0e1e97f54f627052494260ffc918047093f..f36b28b93bdf55f923c5721bee52c9f5449f4cb5 100644 --- a/chain/wallet/dapRPCProtocol/DapRpcLocalServer.cpp +++ b/chain/wallet/dapRPCProtocol/DapRpcLocalServer.cpp @@ -80,7 +80,7 @@ void DapRpcLocalServer::messageProcessing(const DapRpcMessage &asMessage) return; } - processMessage(socket, asMessage); + processMessage(socket, asMessage, false); } DapRpcServiceReply *DapRpcLocalServer::notifyConnectedClients(const DapRpcMessage &message) @@ -106,8 +106,18 @@ void DapRpcLocalServer::incomingConnection(quintptr aSocketDescriptor) DapRpcSocket *socket = new DapRpcSocket(device, this); connect(socket, SIGNAL(messageReceived(DapRpcMessage)), this, SLOT(messageProcessing(DapRpcMessage))); + connect(this, SIGNAL(errorSignal(DapRpcMessage)), socket, SLOT(preNotify(DapRpcMessage))); + for(auto& item: m_services) + { + connect(item, SIGNAL(respondMessage(DapRpcMessage)), socket, SLOT(preNotify(DapRpcMessage))); + } m_clients.append(socket); connect(localSocket, SIGNAL(disconnected()), this, SLOT(clientDisconnected())); m_socketLookup.insert(localSocket, socket); emit onClientConnected(); } + +void DapRpcLocalServer::sendError(const DapRpcMessage& message) +{ + emit errorSignal(message); +} diff --git a/chain/wallet/dapRPCProtocol/DapRpcLocalServer.h b/chain/wallet/dapRPCProtocol/DapRpcLocalServer.h index e72bf9225b30a37295b2fd8d7cbe2098f92e98da..86a28fef230978c7f3ab3a6c9cfa7926175bd33e 100644 --- a/chain/wallet/dapRPCProtocol/DapRpcLocalServer.h +++ b/chain/wallet/dapRPCProtocol/DapRpcLocalServer.h @@ -23,11 +23,6 @@ class DapRpcLocalServer : public QLocalServer, public DapRpcAbstractServer /// Hash map socket lookups. LocalSocket according to RPC socket QHash<QLocalSocket*, DapRpcSocket*> m_socketLookup; -protected: - /// Call when new connection is available - /// @param aSocketDescriptor SocketDescriptor is the native socket descriptor for the accepted connection - virtual void incomingConnection(quintptr aSocketDescriptor); - public: /// Standard constructor explicit DapRpcLocalServer(QObject *apParent = nullptr); @@ -51,12 +46,21 @@ public: DapRpcService* findService(const QString& asServiceName); + +protected: + /// Call when new connection is available + /// @param aSocketDescriptor SocketDescriptor is the native socket descriptor for the accepted connection + virtual void incomingConnection(quintptr aSocketDescriptor); + + void sendError(const DapRpcMessage& message) override; + signals: /// The signal is emitted when client was connected void onClientConnected(); /// The signal is emitted when client was disconnected void onClientDisconnected(); + void errorSignal(const DapRpcMessage& message); private slots: /// Calls when client disconnected void clientDisconnected(); diff --git a/chain/wallet/dapRPCProtocol/DapRpcService.cpp b/chain/wallet/dapRPCProtocol/DapRpcService.cpp index c69cf2d83a79995b8b5228a7b5c82fa812017274..8829e660071a179dc34e5902c17d5ec2e7a9b0ca 100644 --- a/chain/wallet/dapRPCProtocol/DapRpcService.cpp +++ b/chain/wallet/dapRPCProtocol/DapRpcService.cpp @@ -68,12 +68,18 @@ QString DapRpcService::getName() const DapRpcService::DapRpcService(const QString &asName, QObject *apParent) : QObject(apParent), m_sName(asName) { + connect(this, &DapRpcService::startDataProcessing, this, &DapRpcService::dispatch); } DapRpcService::~DapRpcService() { } +void DapRpcService::sendDataToProcessing(const DapRpcMessage &aRequest) +{ + emit startDataProcessing(aRequest); +} + DapRpcServiceRequest DapRpcService::currentRequest() const { return m_currentRequest; @@ -257,13 +263,19 @@ static inline QByteArray methodName(const DapRpcMessage &request) DapRpcMessage DapRpcService::dispatch(const DapRpcMessage &aRequest) { if (aRequest.type() != DapRpcMessage::Request && - aRequest.type() != DapRpcMessage::Notification) { - return aRequest.createErrorResponse(DapErrorCode::InvalidRequest, "invalid request"); + aRequest.type() != DapRpcMessage::Notification) + { + auto messageResult = aRequest.createErrorResponse(DapErrorCode::InvalidRequest, "invalid request"); + emit respondMessage(messageResult); + return messageResult; } const QByteArray &method(methodName(aRequest)); - if (!m_invokableMethodHash.contains(method)) { - return aRequest.createErrorResponse(DapErrorCode::MethodNotFound, "invalid method called"); + if (!m_invokableMethodHash.contains(method)) + { + auto messageResult = aRequest.createErrorResponse(DapErrorCode::MethodNotFound, "invalid method called"); + emit respondMessage(messageResult); + return messageResult; } int idx = -1; @@ -275,13 +287,15 @@ DapRpcMessage DapRpcService::dispatch(const DapRpcMessage &aRequest) QMetaType::Type returnType = QMetaType::Void; bool usingNamedParameters = params.isObject(); - foreach (int methodIndex, indexes) { + foreach (int methodIndex, indexes) + { MethodInfo &info = m_methodInfoHash[methodIndex]; bool methodMatch = usingNamedParameters ? jsParameterCompare(params.toObject(), info) : jsParameterCompare(params.toArray(), info); - if (methodMatch) { + if (methodMatch) + { idx = methodIndex; arguments.reserve(info.parameters.size()); returnType = static_cast<QMetaType::Type>(info.returnType); @@ -292,7 +306,8 @@ DapRpcMessage DapRpcService::dispatch(const DapRpcMessage &aRequest) else parameters.append(returnValue.data()); - for (int i = 0; i < info.parameters.size(); ++i) { + for (int i = 0; i < info.parameters.size(); ++i) + { const ParameterInfo ¶meterInfo = info.parameters.at(i); QJsonValue incomingArgument = usingNamedParameters ? params.toObject().value(parameterInfo.name) : @@ -303,7 +318,9 @@ DapRpcMessage DapRpcService::dispatch(const DapRpcMessage &aRequest) QString message = incomingArgument.isUndefined() ? QString("failed to construct default object for '%1'").arg(parameterInfo.name) : QString("failed to convert from JSON for '%1'").arg(parameterInfo.name); - return aRequest.createErrorResponse(DapErrorCode::InvalidParams, message); + auto messageResult = aRequest.createErrorResponse(DapErrorCode::InvalidParams, message); + emit respondMessage(messageResult); + return messageResult; } arguments.push_back(argument); @@ -316,17 +333,23 @@ DapRpcMessage DapRpcService::dispatch(const DapRpcMessage &aRequest) } } - if (idx == -1) { - return aRequest.createErrorResponse(DapErrorCode::InvalidParams, "invalid parameters"); + if (idx == -1) + { + auto messageResult = aRequest.createErrorResponse(DapErrorCode::InvalidParams, "invalid parameters"); + emit respondMessage(messageResult); + return messageResult; } MethodInfo &info = m_methodInfoHash[idx]; bool success = const_cast<DapRpcService*>(this)->qt_metacall(QMetaObject::InvokeMetaMethod, idx, parameters.data()) < 0; - if (!success) { + if (!success) + { QString message = QString("dispatch for method '%1' failed").arg(method.constData()); - return aRequest.createErrorResponse(DapErrorCode::InvalidRequest, message); + auto messageResult = aRequest.createErrorResponse(DapErrorCode::InvalidRequest, message); + emit respondMessage(messageResult); + return messageResult; } if (m_delayedResponse) { @@ -342,9 +365,16 @@ DapRpcMessage DapRpcService::dispatch(const DapRpcMessage &aRequest) if (info.parameters.at(i).out) ret.append(convertReturnValue(arguments[i])); if (ret.size() > 1) - return aRequest.createResponse(ret); - return aRequest.createResponse(ret.first()); + { + auto messageResult = aRequest.createResponse(ret); + emit respondMessage(messageResult); + return messageResult; + } + auto messageResult = aRequest.createResponse(ret.first()); + emit respondMessage(messageResult); + return messageResult; } - - return aRequest.createResponse(convertReturnValue(returnValue)); + auto messageResult = aRequest.createResponse(convertReturnValue(returnValue)); + emit respondMessage(messageResult); + return messageResult; } diff --git a/chain/wallet/dapRPCProtocol/DapRpcService.h b/chain/wallet/dapRPCProtocol/DapRpcService.h index 6e348b96658456681ece13ed7d12e31bcb2027c9..47643cac524c62ccd76502186e9270b47541de40 100644 --- a/chain/wallet/dapRPCProtocol/DapRpcService.h +++ b/chain/wallet/dapRPCProtocol/DapRpcService.h @@ -62,11 +62,15 @@ public: QString getName() const; + void sendDataToProcessing(const DapRpcMessage &aRequest); + signals: void result(const DapRpcMessage &aDapRpcMessage); void notifyConnectedClients(const DapRpcMessage &aDapRpcMessage); void notifyConnectedClients(const QString &asMethod, const QJsonArray &aParams = QJsonArray()); + void startDataProcessing(const DapRpcMessage &aRequest); + void respondMessage(const DapRpcMessage& message); public slots: DapRpcMessage dispatch(const DapRpcMessage &aRequest); }; diff --git a/chain/wallet/dapRPCProtocol/DapRpcServiceProvider.cpp b/chain/wallet/dapRPCProtocol/DapRpcServiceProvider.cpp index 54ac4b794dfafe5024bc68103e5309b62e88a4f5..c9f94236aa2d3eed2df8bb8bc63d80d8a0d94a1a 100644 --- a/chain/wallet/dapRPCProtocol/DapRpcServiceProvider.cpp +++ b/chain/wallet/dapRPCProtocol/DapRpcServiceProvider.cpp @@ -65,7 +65,7 @@ DapRpcService* DapRpcServiceProvider::findService(const QString &asServiceName) return m_services.value(QByteArray::fromStdString(asServiceName.toStdString())); } -void DapRpcServiceProvider::processMessage(DapRpcSocket *apSocket, const DapRpcMessage &aMessage) +void DapRpcServiceProvider::processMessage(DapRpcSocket *apSocket, const DapRpcMessage &aMessage, bool isWaitMessage) { if(!apSocket || !apSocket->isValid()) { @@ -78,25 +78,43 @@ void DapRpcServiceProvider::processMessage(DapRpcSocket *apSocket, const DapRpcM case DapRpcMessage::Request: case DapRpcMessage::Notification: { QByteArray serviceName = aMessage.method().section(".", 0, -2).toLatin1(); - bool b = m_services.contains(serviceName); + if (serviceName.isEmpty() || !m_services.contains(serviceName)) { if (aMessage.type() == DapRpcMessage::Request) { DapRpcMessage error = aMessage.createErrorResponse(DapErrorCode::MethodNotFound, - QString("service '%1' not found").arg(serviceName.constData())); - apSocket->notify(error); + QString("service '%1' not found").arg(serviceName.constData())); + if(isWaitMessage) + { + apSocket->notify(error); + } + else + { + sendError(error); + } } - } else { + } + else + { DapRpcService *service = m_services.value(serviceName); + service->setCurrentRequest(DapRpcServiceRequest(aMessage, apSocket)); if (aMessage.type() == DapRpcMessage::Request) - QObject::connect(service, SIGNAL(result(DapRpcMessage)), + QObject::connect(service, SIGNAL(respondMessage(DapRpcMessage)), apSocket, SLOT(notify(DapRpcMessage)), Qt::UniqueConnection); - DapRpcMessage response = service->dispatch(aMessage); - if (response.isValid()) - apSocket->notify(response); + + if(isWaitMessage) + { + DapRpcMessage response = service->dispatch(aMessage); + if (response.isValid()) + apSocket->notify(response); + } + else + { + service->sendDataToProcessing(aMessage); + } } } break; @@ -107,7 +125,14 @@ void DapRpcServiceProvider::processMessage(DapRpcSocket *apSocket, const DapRpcM default: { DapRpcMessage error = aMessage.createErrorResponse(DapErrorCode::InvalidRequest, QString("invalid request")); - apSocket->notify(error); + if(isWaitMessage) + { + apSocket->notify(error); + } + else + { + sendError(error); + } break; } } diff --git a/chain/wallet/dapRPCProtocol/DapRpcServiceProvider.h b/chain/wallet/dapRPCProtocol/DapRpcServiceProvider.h index 6377d1bf3e8fb06ffea963d1373872eb511e69c0..025a6af2d5d590a0feddd8cc2988e3b292a1d0fb 100644 --- a/chain/wallet/dapRPCProtocol/DapRpcServiceProvider.h +++ b/chain/wallet/dapRPCProtocol/DapRpcServiceProvider.h @@ -16,18 +16,6 @@ */ class DapRpcServiceProvider { - /// Store pointers to service by the name - QHash<QByteArray, DapRpcService*> m_services; - /// Handle service to cleanup - QObjectCleanupHandler m_cleanupHandler; - -protected: - /// Standard constructor - DapRpcServiceProvider(); - /// Process message to send by socket interface - /// @param apSocket Remote socket - /// aMessage Rpc message - void processMessage(DapRpcSocket *apSocket, const DapRpcMessage &aMessage); public: /// Virtual destructor @@ -46,6 +34,21 @@ public: /// @param apService Service /// @return Serilization name of service QByteArray getServiceName(DapRpcService *apService); + +protected: + /// Standard constructor + DapRpcServiceProvider(); + /// Process message to send by socket interface + /// @param apSocket Remote socket + /// aMessage Rpc message + void processMessage(DapRpcSocket *apSocket, const DapRpcMessage &aMessage, bool isWaitMessage = true); + + virtual void sendError(const DapRpcMessage& message){} +protected: + /// Store pointers to service by the name + QHash<QByteArray, DapRpcService*> m_services; + /// Handle service to cleanup + QObjectCleanupHandler m_cleanupHandler; }; #endif // DapRPCSERVICEPROVIDER_H diff --git a/chain/wallet/dapRPCProtocol/DapRpcSocket.cpp b/chain/wallet/dapRPCProtocol/DapRpcSocket.cpp index 3c3e4de07caa6e541a286fd0e325a8ccb352b1d7..7d3723200e5066b7992191eed6578fef8d61c2a3 100644 --- a/chain/wallet/dapRPCProtocol/DapRpcSocket.cpp +++ b/chain/wallet/dapRPCProtocol/DapRpcSocket.cpp @@ -1,10 +1,9 @@ #include "DapRpcSocket.h" #include "DapRpcService.h" - +#include <QDebug> DapRpcSocket::DapRpcSocket(QObject *apParent) : QObject(apParent) { - } DapRpcSocket::DapRpcSocket(QIODevice *apDevice, QObject *apParent) @@ -137,6 +136,14 @@ DapRpcServiceReply *DapRpcSocket::sendMessage(const DapRpcMessage &asMessage) return reply; } +void DapRpcSocket::preNotify(const DapRpcMessage &asMessage) +{ + if(asMessage.isValid()) + { + notify(asMessage); + } +} + void DapRpcSocket::notify(const DapRpcMessage &asMessage) { if (!m_pDevice) { @@ -275,5 +282,5 @@ void DapRpcSocket::setIODevice(QIODevice *pDevice) void DapRpcSocket::processRequestMessage(const DapRpcMessage &asMessage) { - processMessage(this, asMessage); + processMessage(this, asMessage, false); } diff --git a/chain/wallet/dapRPCProtocol/DapRpcSocket.h b/chain/wallet/dapRPCProtocol/DapRpcSocket.h index 8dfb2b4e582ff5a1bc829367fa678d95e69f5663..25ad335607e1b4267e6b2e4b449d578ec294afd1 100644 --- a/chain/wallet/dapRPCProtocol/DapRpcSocket.h +++ b/chain/wallet/dapRPCProtocol/DapRpcSocket.h @@ -28,20 +28,6 @@ class DapRpcSocket : public QObject, public DapRpcServiceProvider Q_OBJECT Q_DISABLE_COPY(DapRpcSocket) - /// Pointer to IO device - QPointer<QIODevice> m_pDevice; - /// Buffer - QByteArray m_aBuffer; - /// Storage to replies by id - QHash<int, QPointer<DapRpcServiceReply>> m_replies; - /// Default request timeout - int m_defaultRequestTimeout; - -protected: - /// TODO: not implement - /// @param asMessage Request message - virtual void processRequestMessage(const DapRpcMessage &asMessage); - public: /// Standard constructor explicit DapRpcSocket(QObject *apParent = nullptr); @@ -85,6 +71,8 @@ public slots: /// Notify to new request message and try to send to device /// @param asMessage Request message virtual void notify(const DapRpcMessage &asMessage); + void preNotify(const DapRpcMessage &asMessage); + /// Send message with delay for sending message /// @param asMessage Request message /// @param aMsecs Delay request timeout. If not pass parameter uses default value @@ -153,6 +141,21 @@ public slots: const QVariant &arg8 = QVariant(), const QVariant &arg9 = QVariant(), const QVariant &arg10 = QVariant()); DapRpcServiceReply *invokeRemoteMethod(const DapRpcMessage &message); + +protected: + /// TODO: not implement + /// @param asMessage Request message + virtual void processRequestMessage(const DapRpcMessage &asMessage); + +private: + /// Pointer to IO device + QPointer<QIODevice> m_pDevice; + /// Buffer + QByteArray m_aBuffer; + /// Storage to replies by id + QHash<int, QPointer<DapRpcServiceReply>> m_replies; + /// Default request timeout + int m_defaultRequestTimeout; }; #endif // DapRPCSOCKET_H diff --git a/chain/wallet/dapRPCProtocol/DapRpcTCPServer.cpp b/chain/wallet/dapRPCProtocol/DapRpcTCPServer.cpp index ad70badf24abf81a1512c99f3f8d7e5b632c1591..98a766a8ef5b7bcc9ca3dcc21fa3814fe2acc34d 100644 --- a/chain/wallet/dapRPCProtocol/DapRpcTCPServer.cpp +++ b/chain/wallet/dapRPCProtocol/DapRpcTCPServer.cpp @@ -86,7 +86,7 @@ void DapRpcTCPServer::messageProcessing(const DapRpcMessage &asMessage) return; } - processMessage(socket, asMessage); + processMessage(socket, asMessage, false); } void DapRpcTCPServer::incomingConnection(qintptr aSocketDescriptor) diff --git a/chain/wallet/handlers/CertificateManager/DapCertificateOperation.cpp b/chain/wallet/handlers/CertificateManager/DapCertificateOperation.cpp index 9e15b454e244e6f46dd43846e26e680716d58e57..8d94f43a7b672c28ef183309114d5179f57975ea 100644 --- a/chain/wallet/handlers/CertificateManager/DapCertificateOperation.cpp +++ b/chain/wallet/handlers/CertificateManager/DapCertificateOperation.cpp @@ -106,6 +106,7 @@ QJsonObject DapCertificateOperation::createCertificate(const QString &certName, , { "picnic", DAP_ENC_KEY_TYPE_SIG_PICNIC } , { "bliss", DAP_ENC_KEY_TYPE_SIG_BLISS } , { "tesla", DAP_ENC_KEY_TYPE_SIG_TESLA } + , { "falcon", DAP_ENC_KEY_TYPE_SIG_FALCON } }); qDebug() << "DapCertificateOperation::createCertificate"; diff --git a/chain/wallet/handlers/DapAbstractCommand.cpp b/chain/wallet/handlers/DapAbstractCommand.cpp index cd218178ce372d438152e9c746c44cfa259740b3..d0594b6e42a4262e04e8e5084211655e7176d304 100644 --- a/chain/wallet/handlers/DapAbstractCommand.cpp +++ b/chain/wallet/handlers/DapAbstractCommand.cpp @@ -120,8 +120,8 @@ void DapAbstractCommand::requestToService(const QVariant &args) /// @return Reply to client. QVariant DapAbstractCommand::respondToClient(const QVariant &args) { - Q_UNUSED(args) - qDebug() << "[" << this->getName() << "] [respondToClient]"; + //Q_UNUSED(args) + qDebug() << "[" << this->getName() << "] [respondToClient] " << args.toStringList(); return QVariant(); } diff --git a/chain/wallet/handlers/DapAddWalletCommand.cpp b/chain/wallet/handlers/DapAddWalletCommand.cpp index b97d9e9029c117022dd0944fef0bcc2b49452af2..db14464e47e925d7041cdf7d5ab2e056b73abe14 100644 --- a/chain/wallet/handlers/DapAddWalletCommand.cpp +++ b/chain/wallet/handlers/DapAddWalletCommand.cpp @@ -28,16 +28,8 @@ QVariant DapAddWalletCommand::respondToClient(const QVariant &args) DapAbstractCommand::respondToClient(args); QJsonObject resultObj; - QVariant v_res = cmdList->addWallet(args); + QString result = cmdList->addWallet(args); - // if json : - if(v_res.type() == QMetaType::QJsonDocument) { - qWarning() << "NEED JSON PARSING"; - return resultObj; - } - - // if string : - QString result = v_res.toString(); if(result.contains("successfully created")) { QString walletName = args.toStringList().first(); diff --git a/chain/wallet/handlers/DapCommandList.cpp b/chain/wallet/handlers/DapCommandList.cpp index 0ab48aa0c74d8955860278aa5b642142517ecd07..523155a1edc91fdd213d75e062175ea94f5bad0c 100644 --- a/chain/wallet/handlers/DapCommandList.cpp +++ b/chain/wallet/handlers/DapCommandList.cpp @@ -1,4 +1,5 @@ #include "DapCommandList.h" +#include <QRegExp> #include <QRegularExpression> DapCommandList::DapCommandList(QObject *parent) @@ -74,7 +75,6 @@ QString DapCommandList::getFee(const QString &net) return requestToNode(command).remove("\r"); } -// Ðе проверено /// Orders list QString DapCommandList::getListOrders(const QString &net) { @@ -83,7 +83,6 @@ QString DapCommandList::getListOrders(const QString &net) return requestToNode(command).remove("\r"); } -// Ðе проверено /// Ledger information QString DapCommandList::getListTokens(const QString &net) { @@ -92,12 +91,33 @@ QString DapCommandList::getListTokens(const QString &net) return requestToNode(command); } +/// Get request list of wallets +QString DapCommandList::getRequestListWallets() { + + QString command = QString("%1 wallet list").arg(CLI_PATH); + + return requestToNode(std::move(command)); +} + /// Get list of wallets -QString DapCommandList::getListWallets() +QStringList DapCommandList::getListWallets() { - auto command = QString("%1 wallet list").arg(CLI_PATH); + QString request = getRequestListWallets(); - return requestToNode(command); + const QString BACKUP = "Backup"; + const QString REGULAR_WALLET_ACTIVE = R"(^Wallet: (\S+)( \((\S+)\))?)"; + + QRegularExpression rx(REGULAR_WALLET_ACTIVE, QRegularExpression::MultilineOption); + QRegularExpressionMatchIterator itr = rx.globalMatch(request); + QStringList resultList; + while (itr.hasNext()) + { + QRegularExpressionMatch match = itr.next(); + QString walletName = match.captured(1); + if(BACKUP == match.captured(3)) continue; + resultList.append(walletName); + } + return resultList; } /// Make transaction @@ -120,6 +140,11 @@ QString DapCommandList::createTransaction(const QVariant &args) /// Displays the current net status QString DapCommandList::getNetworkState(const QString &net) { + if(net.isEmpty()) + { + qWarning() << "getNetworkState() net name is empty"; + return QString(); + } auto command = QString("%1 net -net %2 get status").arg(CLI_PATH).arg(net); return requestToNode(command); @@ -128,6 +153,17 @@ QString DapCommandList::getNetworkState(const QString &net) /// Display information of wallet QString DapCommandList::getWalletInfo(const QString &net, const QString &wallet) { + if(wallet.isEmpty()) + { + qWarning() << "getWalletInfo() wallet is empty"; + return QString(); + } + else if(net.isEmpty()) + { + qWarning() << "getWalletInfo() net name is empty"; + return QString(); + } + auto command = QString("%1 wallet info -w %2 -net %3").arg(CLI_PATH).arg(wallet).arg(net); return requestToNode(command); @@ -136,6 +172,16 @@ QString DapCommandList::getWalletInfo(const QString &net, const QString &wallet) /// Transaction history by wallet name QString DapCommandList::getTXHistory(const QString &net, const QString &wallet) { + if(wallet.isEmpty()) + { + qWarning() << "getTXHistory() wallet is empty"; + return QString(); + } + else if(net.isEmpty()) + { + qWarning() << "getTXHistory() net name is empty"; + return QString(); + } auto command = QString("%1 tx_history -net %2 -w %3").arg(CLI_PATH).arg(net).arg(wallet); return requestToNode(command); @@ -144,6 +190,11 @@ QString DapCommandList::getTXHistory(const QString &net, const QString &wallet) /// Get the exchange orders list within specified net name QString DapCommandList::getXchangeOrdersList(const QString &net) { + if(net.isEmpty()) + { + qWarning() << "getXchangeOrdersList() net name is empty"; + return QString(); + } auto command = QString("%1 srv_xchange orders -net %2").arg(CLI_PATH).arg(net); return requestToNode(command); @@ -152,6 +203,11 @@ QString DapCommandList::getXchangeOrdersList(const QString &net) /// List of all token pairs QString DapCommandList::getXchangeTokenPairsList(const QString &net) { + if(net.isEmpty()) + { + qWarning() << "getXchangeTokenPairsList() net name is empty"; + return QString(); + } auto command = QString("%1 srv_xchange token_pair -net %2 list all") .arg(CLI_PATH).arg(net); @@ -357,7 +413,24 @@ QString DapCommandList::getVersion() { QString command = QString("%1 version").arg(CLI_PATH); - return requestToNode(command); +// return requestToNode(command); + + QString request = requestToNode(command); + request = request.trimmed(); + QRegularExpression regex(R"(version (\S+))"); + QRegularExpressionMatch match = regex.match(request); + if(!match.hasMatch()) + { + qWarning() << "The output of the node version information has changed"; + return {}; + } + QString version = match.captured(1); + if(version.isEmpty()) + { + qWarning() << "Couldn't find out the node version"; + return {}; + } + return version; } /// Activate or deactivate wallet @@ -436,7 +509,7 @@ QString DapCommandList::xchangeOrderRemove(const QVariant &args) /// List mempool (entries or transaction) for (selected chain network or wallet) QString DapCommandList::getListMempool(const QString &net) { - auto command = QString("%1 mempool_list -net %2") + auto command = QString("%1 mempool list -net %2") .arg(CLI_PATH) .arg(net); @@ -501,13 +574,20 @@ QString DapCommandList::createStakeOrder(const QVariant &args) return requestToNode(command); } +QString DapCommandList::getListChains() +{ + auto command = QString("%1 net list chains").arg(CLI_PATH); + + return requestToNode(command); +} + QString DapCommandList::requestToNode(QString cmd) { QProcess process; process.start(cmd); /// TODO: if you need a list of output commands, then uncomment. /// In the usual case, it is better to avoid this because it causes logging redundancy. - //qQDebug() << "command:" << cmd; + qDebug() << "command:" << cmd; if(process.waitForFinished(10000)) { auto result = QString::fromLatin1(process.readAll()); diff --git a/chain/wallet/handlers/DapCommandList.h b/chain/wallet/handlers/DapCommandList.h index 25111f062ca62ce8d9b87a31a2871f4982665cbe..9bddf30412f2d73d3cf154eca19dd87280466793 100644 --- a/chain/wallet/handlers/DapCommandList.h +++ b/chain/wallet/handlers/DapCommandList.h @@ -16,7 +16,8 @@ public: QString getFee(const QString &net); QString getListOrders(const QString &net); QString getListTokens(const QString &net); - QString getListWallets(); + QString getRequestListWallets(); + QStringList getListWallets(); QString getNetworkState(const QString &net); QString getWalletInfo(const QString &net, const QString &wallet); QString getTXHistory(const QString &net, const QString &wallet); @@ -42,6 +43,7 @@ public: QString getWalletAddress(const QString &net, const QString &wallet); QString createVPNOrder(const QVariant &args); QString createStakeOrder(const QVariant &args); + QString getListChains(); void restartNode(); diff --git a/chain/wallet/handlers/DapCreatePassForWallet.cpp b/chain/wallet/handlers/DapCreatePassForWallet.cpp index f4cfdb7297a033542a52726480229fcea2e6baa7..3dd6f0fa7edafbdbc4d07390798d4a9c478e6397 100644 --- a/chain/wallet/handlers/DapCreatePassForWallet.cpp +++ b/chain/wallet/handlers/DapCreatePassForWallet.cpp @@ -12,7 +12,7 @@ DapCreatePassForWallet::DapCreatePassForWallet(const QString &asServicename, QOb /// @return Reply to client. QVariant DapCreatePassForWallet::respondToClient(const QVariant &args) { - DapAbstractCommand::respondToClient(args); + qDebug() << "[" << this->getName() << "] [respondToClient]"; QStringList params = args.toStringList(); diff --git a/chain/wallet/handlers/DapDictionaryCommand.cpp b/chain/wallet/handlers/DapDictionaryCommand.cpp new file mode 100644 index 0000000000000000000000000000000000000000..141c98e85fc27ce31dab9b1571d67aa2e628662f --- /dev/null +++ b/chain/wallet/handlers/DapDictionaryCommand.cpp @@ -0,0 +1,281 @@ +#include "DapDictionaryCommand.h" +#include <QDataStream> +#include <QByteArray> + +DapDictionaryCommand::DapDictionaryCommand(const QString &asServiceName, QObject *parent, const QString &asCliPath) + : DapAbstractCommand{asServiceName, parent, asCliPath} + , m_dictionary(new HelpDictionaryServiceController(asCliPath)) +{ + updateVersionNode(); + updateData(); +} + +void DapDictionaryCommand::updateVersionNode(bool isUpdate) +{ + QString version = cmdList->getVersion(); + if(!version.isEmpty() && version != m_dictionary->getNodeVersion()) + { + m_dictionary->setNodeVersion(std::move(version), isUpdate); + } +} + +void DapDictionaryCommand::updateData() +{ + m_wallets = cmdList->getListWallets(); + updateCerts(); + m_networks = cmdList->getListNetworks(); + updateTokens(); + updateMempoolTokens(); + updateChains(); +} + +DapDictionaryCommand::~DapDictionaryCommand() +{ + delete m_dictionary; +} + +/// Send a response to the client. +/// @details Performed on the service side. +/// @param arg1...arg10 Parameters. +/// @return Reply to client. +QVariant DapDictionaryCommand::respondToClient(const QVariant &args) +{ + if(!m_dictionary) + { + return {}; + } + QJsonDocument result; + QStringList params = args.toStringList(); + + auto getJsonWithHeader = [](const QString& head, const QJsonDocument& doc, const QString& versionNode = "") -> QJsonDocument + { + QJsonObject result; + result["head"] = head; + result["data"] = doc.object(); + if(!versionNode.isEmpty()) + { + result["version"] = versionNode; + } + + return QJsonDocument(result); + }; + + if(params[0] == "getNewDictionary") + { + updateVersionNode(false); + result = getJsonWithHeader("dictionary", m_dictionary->getNewJsonDictionary(), m_dictionary->getNodeVersion()); + } + else if (params[0] == "getDictionary") + { + updateVersionNode(false); + result = getJsonWithHeader("dictionary", m_dictionary->getJsonDictionary(), m_dictionary->getNodeVersion()); + } + else if(params[0] == "getData") + { + result = getJsonWithHeader("data", getData()); + } + else if(params[0] == "updateData") + { + updateData(); + result = getJsonWithHeader("data", getData()); + } + + QByteArray resByte; + QDataStream streamer(&resByte, QIODevice::WriteOnly); + streamer << result; + + return resByte.toHex(); +} + +QJsonDocument DapDictionaryCommand::getData() +{ + auto stringListToJson = [](const QStringList& list) -> QJsonArray + { + QJsonArray jsonArray; + for(const QString& str: list) + { + jsonArray.append(str); + } + return jsonArray; + }; + + QJsonObject data; + data["wallets"] = stringListToJson(m_wallets); + data["networks"] = stringListToJson(m_networks); + data["pubCertName"] = stringListToJson(m_pubCertName); + data["privCertName"] = stringListToJson(m_privCertName); + + auto mapStrLToJson = [&stringListToJson](const QMap<QString, QStringList>& chains) -> QJsonArray + { + QJsonArray jsonArray; + QMapIterator<QString, QStringList> it(chains); + while(it.hasNext()) + { + it.next(); + QString key = it.key(); + QStringList list = it.value(); + QJsonArray jsonList = stringListToJson(list); + QJsonObject tmpObject; + tmpObject["key"] = key; + tmpObject["data"] = jsonList; + jsonArray.append(std::move(tmpObject)); + } + return jsonArray; + }; + + data["chains"] = mapStrLToJson(m_chains); + data["mempoolTokensTicker"] = mapStrLToJson(m_mempoolTokensTicker); + + auto mapTokenToJson = [&stringListToJson](const QMap<QPair<QString, QString>, QStringList>& tokensTicker) -> QJsonArray + { + QJsonArray jsonArray; + QMapIterator<QPair<QString, QString>, QStringList> it(tokensTicker); + while(it.hasNext()) + { + it.next(); + QPair<QString, QString> key = it.key(); + QStringList list = it.value(); + QJsonArray jsonList = stringListToJson(list); + QJsonObject tmpObject; + tmpObject["wallet"] = key.first; + tmpObject["network"] = key.second; + tmpObject["data"] = jsonList; + jsonArray.append(std::move(tmpObject)); + } + return jsonArray; + }; + + data["tokensTicker"] = mapTokenToJson(m_tokensTicker); + return QJsonDocument(data); +} + +void DapDictionaryCommand::updateCerts() +{ + m_pubCertName.clear(); + m_privCertName.clear(); + QDir pubDir(PUB_CERT_PATH); + pubDir.setFilter(QDir::Files | QDir::Hidden); + QStringList files = pubDir.entryList(); + for (int i = 0; i < files.length(); ++i) + { + QString s = files[i].remove(".dcert"); + if (s != "." && s != "..") + m_pubCertName.append(s); + } + + QDir privDir(PRIV_CERT_PATH); + privDir.setFilter(QDir::Files | QDir::Hidden); + files = privDir.entryList(); + for (int i = 0; i < files.length(); ++i) + { + QString s = files[i].remove(".dcert"); + if (s != "." && s != "..") + m_privCertName.append(s); + } +} + +void DapDictionaryCommand::updateTokens() +{ + QMap<QPair<QString, QString>, QStringList> result; + for(const QString& wallet: qAsConst(m_wallets)) + { + for(const QString& net: qAsConst(m_networks)) + { + QString resultRequest = cmdList->getWalletInfo(net,wallet); + QRegularExpression tickerRegex(R"((\w+) \((\w+)\) (\w+))"); + QRegularExpressionMatchIterator matchTicker = tickerRegex.globalMatch(resultRequest); + QStringList listTicker; + while (matchTicker.hasNext()) + { + QRegularExpressionMatch match = matchTicker.next(); + listTicker.append(match.captured(3)); + } + if(!listTicker.isEmpty()) + { + result.insert({wallet, net}, listTicker); + } + } + } + if(!result.isEmpty()) + { + m_tokensTicker = std::move(result); + } +} + +void DapDictionaryCommand::updateMempoolTokens() +{ + QMap<QString, QStringList> result; + + for(const QString& net: m_networks) + { + QString resultRequest = cmdList->getListTokens(net); + + QRegularExpression tickerRegex(R"(Token name \'(\w+)\')"); + QRegularExpressionMatchIterator matchTicker = tickerRegex.globalMatch(resultRequest); + QStringList listTicker; + while (matchTicker.hasNext()) + { + QRegularExpressionMatch match = matchTicker.next(); + listTicker.append(match.captured(1)); + } + if(!listTicker.isEmpty()) + { + result.insert(net, listTicker); + } + } + if(!result.isEmpty()) + { + m_mempoolTokensTicker = std::move(result); + } + else + { + qWarning() << "The search for Tickers in the mempool yielded no results"; + } +} + +void DapDictionaryCommand::updateChains() +{ + QMap<QString, QStringList> result; + QString resultRequest = cmdList->getListChains(); + + resultRequest = resultRequest.remove("Networks:\n\t"); + resultRequest = resultRequest.remove(":"); + resultRequest = resultRequest.remove("\n"); + resultRequest = resultRequest.remove("\r"); + QStringList list = resultRequest.split("\t"); + list.removeAll(""); + + if (list.isEmpty()) + return; + + QString net; + QStringList tmpList; + auto addToResult = [&result, &net, &tmpList]() + { + if(!net.isEmpty() && !tmpList.isEmpty()) + { + result.insert(net, tmpList); + net.clear(); + tmpList.clear(); + } + }; + + for (int i = 0; i < list.length(); ++i) + { + if(m_networks.contains(list[i])) + { + addToResult(); + net = list[i]; + } + else if(!list[i].contains('|')) + { + tmpList.append(list[i]); + } + } + addToResult(); + + if(!result.isEmpty()) + { + m_chains = std::move(result); + } +} diff --git a/chain/wallet/handlers/DapDictionaryCommand.h b/chain/wallet/handlers/DapDictionaryCommand.h new file mode 100644 index 0000000000000000000000000000000000000000..79926adabe5902087f13bb3fffe54c4c05a34f2c --- /dev/null +++ b/chain/wallet/handlers/DapDictionaryCommand.h @@ -0,0 +1,67 @@ +#ifndef DAPDICTIONARYCOMMAND_H +#define DAPDICTIONARYCOMMAND_H + +#include "DapAbstractCommand.h" +#include "../autocomplete/HelpDictionaryServiceController.h" + +#ifdef Q_OS_WIN +#include "registry.h" +#define PRIV_CERT_PATH QString("%1/cellframe-node/var/lib/ca/").arg(regGetUsrPath()) +#define PUB_CERT_PATH QString("%1/cellframe-node/share/ca/").arg(regGetUsrPath()) +#define NETWORKS_PATH QString("%1/cellframe-node/etc/network/").arg(regGetUsrPath()) +#endif + +#ifdef Q_OS_MAC +#include <sys/stat.h> +#define PUB_CERT_PATH QString("/Users/%1/Applications/Cellframe.app/Contents/Resources/share/ca/").arg(getenv("USER")) +#define PRIV_CERT_PATH QString("/Users/%1/Applications/Cellframe.app/Contents/Resources/var/lib/ca/").arg(getenv("USER")) +#define NETWORKS_PATH QString("/Users/%1/Applications/Cellframe.app/Contents/Resources/etc/network/").arg(getenv("USER")) +#endif + +#ifdef Q_OS_LINUX +#include <sys/stat.h> +#define PUB_CERT_PATH QString("/opt/cellframe-node/share/ca") +#define PRIV_CERT_PATH QString("/opt/cellframe-node/var/lib/ca") +#define NETWORKS_PATH QString("/opt/cellframe-node/etc/network/") +#endif + +class DapDictionaryCommand : public DapAbstractCommand +{ + Q_OBJECT +public: + explicit DapDictionaryCommand(const QString &asServiceName, QObject *parent = nullptr, const QString &asCliPath = QString()); + + ~DapDictionaryCommand(); +public slots: + /// Send a response to the client. + /// @details Performed on the service side. + /// @param arg1...arg10 Parameters. + /// @return Reply to client. + QVariant respondToClient(const QVariant &args = QVariant()) override; + +private: + QJsonDocument getData(); + + void updateCerts(); + void updateTokens(); + void updateMempoolTokens(); + void updateChains(); + + void updateData(); + void updateVersionNode(bool isUpdate = true); +private: + HelpDictionaryServiceController* m_dictionary = nullptr; + + QStringList m_wallets; + QStringList m_networks; + QStringList m_pubCertName; + QStringList m_privCertName; + // network chains + QMap<QString, QStringList> m_chains; + // <wallet, network>, tickers + QMap<QPair<QString, QString>, QStringList> m_tokensTicker; + // net, tickers + QMap<QString, QStringList> m_mempoolTokensTicker; +}; + +#endif // DAPDICTIONARYCOMMAND_H diff --git a/chain/wallet/handlers/DapGetAllWalletHistoryCommand.cpp b/chain/wallet/handlers/DapGetAllWalletHistoryCommand.cpp index 306a7c07c9955ad88b261a386322b55ee0c0082b..ad274df13cedc3f502833d60202f93a986ed2382 100644 --- a/chain/wallet/handlers/DapGetAllWalletHistoryCommand.cpp +++ b/chain/wallet/handlers/DapGetAllWalletHistoryCommand.cpp @@ -45,7 +45,7 @@ QVariant DapGetAllWalletHistoryCommand::respondToClient(const QVariant &args) if(!result.isEmpty()) { - QRegularExpression regularAddr(R"(History for addr (\S+):)"); + QRegularExpression regularAddr(R"(address: (\S+))"); QRegularExpressionMatch matchAddr = regularAddr.match(result); if (!matchAddr.hasMatch()) { @@ -73,7 +73,7 @@ QVariant DapGetAllWalletHistoryCommand::respondToClient(const QVariant &args) QMap<typeHistoryData, HistoryData> dataTransaction; - auto setData = [&txHeader, &dataTransaction, getStatus, this](){ + auto setData = [&txHeader, &dataTransaction, &txHistory, getStatus, this](){ // Using these keys, we set options for filling in the history bool isStateLock = dataTransaction.contains(typeHistoryData::STATE_LOCK); @@ -174,43 +174,134 @@ QVariant DapGetAllWalletHistoryCommand::respondToClient(const QVariant &args) } dataTransaction.clear(); + + if(txHeader.contains(TX_HASH_KEY) && !txHeader[TX_HASH_KEY].toString().isEmpty()) + { + txHistory.append(txHeader); + } }; - for(int i = 0; i < size; i++) + enum MainTypeHistoryData + { + HASH = 0, + ATOM_HASH, + TX_CREATED, + NULL_MAIN_DATA + }; + + QVector<QPair<QRegularExpression, MainTypeHistoryData>> mainResultToData = {{QRegularExpression(R"(^hash: (\S+))"), MainTypeHistoryData::HASH} + ,{QRegularExpression(R"(^atom_hash: (\S+))"), MainTypeHistoryData::ATOM_HASH} + ,{QRegularExpression(R"(^tx_created: (.+))"), MainTypeHistoryData::TX_CREATED}}; + + + auto getMainData = [&mainResultToData](const QString& str) -> QPair<MainTypeHistoryData, QString> { - historyList[i] = historyList[i].trimmed(); - if(historyList[i].contains(REGULAR_HISTORY_BEGIN)) + for(const auto& regular: mainResultToData) { - if(!txHeader.isEmpty()) + if(str.contains(regular.first)) { - setData(); - txHistory.append(txHeader); - txHeader = QJsonObject(); + QRegularExpressionMatch match = regular.first.match(str); + return {regular.second, match.captured(1)}; } - QRegularExpressionMatch match = REGULAR_HISTORY_BEGIN.match(historyList[i]); + } + return {MainTypeHistoryData::NULL_MAIN_DATA, QString()}; + }; - if(hashSet.contains(match.captured(2))) + enum TypeHistoryData + { + TX_TYPE = 0, + COINS, + TOKEN, + ADDRESS, + NULL_DATA + }; + + QVector<QPair<QRegularExpression, TypeHistoryData>> resultToData = {{QRegularExpression(R"(tx_type: (\S+))"), TypeHistoryData::TX_TYPE} + ,{QRegularExpression(R"(coins: (\S+))"), TypeHistoryData::COINS} + ,{QRegularExpression(R"(token: (\S+))"), TypeHistoryData::TOKEN} + ,{QRegularExpression(R"(address: (\S+))"), TypeHistoryData::ADDRESS}}; + + + auto getData = [&resultToData](const QString& str) -> QPair<TypeHistoryData, QString> + { + for(const auto& regular: resultToData) + { + if(str.contains(regular.first)) { - isHashDouble = true; - continue; + QRegularExpressionMatch match = regular.first.match(str); + return {regular.second, match.captured(1)}; } - else + } + return {TypeHistoryData::NULL_DATA, QString()}; + }; + + auto getHistoryData = [&](const QStringList& list, int& currentIndex) -> HistoryData + { + bool isStart = false; + int size = list.size(); + + HistoryData result; + while(size > currentIndex) + { + QString currStr = list[currentIndex].trimmed(); + if(currStr.isEmpty() && isStart) { - hashSet.insert(match.captured(2)); - isHashDouble = false; + return result; } - if("0x2819BE1267689EACDC3CC60CBACF6FBFCAC085F35F8955AD5D438A6F681901D5" == match.captured(2)) + auto data = getData(currStr); + switch (data.first) { - QString str = historyList[i]; - bool a=0; + case TypeHistoryData::TX_TYPE: + { + result.status = data.second; + result.direction = data.second == "send" ? "to" : "from"; + isStart = true; + } + break; + case TypeHistoryData::ADDRESS: + result.address = data.second; + break; + case TypeHistoryData::COINS: + result.value = data.second; + break; + case TypeHistoryData::TOKEN: + result.token = data.second; + break; + default: + break; } + + currentIndex++; + } + + return result; + }; + + + bool isMainDataGetting = true; + bool isStart = false; + for(int i = 0; i < size; i++) + { + QString currentStr = historyList[i].trimmed(); + + if(currentStr.isEmpty()) + { + continue; + } + else if(currentStr.contains(REGULAR_HISTORY_BEGIN)) + { + isMainDataGetting = true; + isStart = true; + if(!txHeader.isEmpty()) + { + setData(); + txHeader = QJsonObject(); + } + QRegularExpressionMatch match = REGULAR_HISTORY_BEGIN.match(historyList[i]); + txHeader.insert(TX_STATUS_KEY, match.captured(1)); - txHeader.insert(TX_HASH_KEY, match.captured(2)); - txHeader.insert(ATOM_KEY, match.captured(3)); txHeader.insert(NETWORK_KEY, net); txHeader.insert(WALLET_NAME_KEY, walletName); - txHeader.insert("emission_token", ""); - txHeader.insert("emission_value", ""); txHeader.insert(VALUE_KEY, "0.0"); txHeader.insert(TOKEN_KEY, netInfo.tokenName); txHeader.insert(FEE_TOKEN_KEY, netInfo.tokenName); @@ -218,37 +309,66 @@ QVariant DapGetAllWalletHistoryCommand::respondToClient(const QVariant &args) txHeader.insert(FEE_NET_KEY, "0.0"); txHeader.insert(M_VALUE_KEY, "0.0"); - // The next line contains the date, so we immediately go there - QDateTime date = QDateTime::fromString(historyList[++i]); - qint64 dateToSecs = date.toSecsSinceEpoch(); - txHeader.insert(DATA_KEY, date.toString("yyyy-MM-dd")); - txHeader.insert(DATE_TO_SECS_KEY, QString::number(dateToSecs)); - continue; } - if(historyList[i].contains(REGULAR_HISTORY_INFO_TR) && !isHashDouble) + else if(isMainDataGetting && isStart) { - QRegularExpressionMatch match = REGULAR_HISTORY_INFO_TR.match(historyList[i]); - if(!match.hasMatch()) + if(currentStr.contains("data:") ) { + isMainDataGetting = false; continue; } - HistoryData data(match.captured(1), match.captured(2), match.captured(4), match.captured(5), match.captured(6)); - // Validator commission - if(match.captured(6).contains(REWARD_HISTORY)) + auto currentParam = getMainData(currentStr); + + switch (currentParam.first) + { + case MainTypeHistoryData::HASH: + { + txHeader.insert(TX_HASH_KEY, currentParam.second); + if(hashSet.contains(currentParam.second)) + { + isHashDouble = true; + continue; + } + else + { + hashSet.insert(currentParam.second); + isHashDouble = false; + } + } + break; + case MainTypeHistoryData::ATOM_HASH: + txHeader.insert(ATOM_KEY, currentParam.second); + break; + case MainTypeHistoryData::TX_CREATED: + { + QDateTime date = QDateTime::fromString(currentParam.second); + qint64 dateToSecs = date.toSecsSinceEpoch(); + txHeader.insert(DATA_KEY, date.toString("yyyy-MM-dd")); + txHeader.insert(DATE_TO_SECS_KEY, QString::number(dateToSecs)); + } + break; + default: + break; + } + } + else if(!isMainDataGetting && isStart) + { + HistoryData data = getHistoryData(historyList, i); + if(data.address == REWARD_HISTORY) { if(!dataTransaction.contains(typeHistoryData::REWARD)) { dataTransaction.insert(typeHistoryData::REWARD, data); } } - else if(match.captured(6).contains(TYPE_COMMISSION)) + else if(data.address == TYPE_COMMISSION) { if(!dataTransaction.contains(typeHistoryData::VALIDATOR)) { dataTransaction.insert(typeHistoryData::VALIDATOR, data); } } - else if (match.captured(6).contains(TYPE_M_TRANSACTION)) + else if (data.address == TYPE_M_TRANSACTION) { if(!dataTransaction.contains(typeHistoryData::STATE_LOCK)) { @@ -256,10 +376,10 @@ QVariant DapGetAllWalletHistoryCommand::respondToClient(const QVariant &args) dataTransaction.insert(typeHistoryData::STATE_LOCK, data); } } - else if (match.captured(6).contains(REGULAR_WALLET_ADDRESS)) + else if (data.address.contains(REGULAR_WALLET_ADDRESS)) { // Network commission - if(match.captured(6) == netInfo.address) + if(data.address == netInfo.address) { if(!dataTransaction.contains(typeHistoryData::NET)) { @@ -274,14 +394,14 @@ QVariant DapGetAllWalletHistoryCommand::respondToClient(const QVariant &args) } } } - else if (match.captured(6) == "null") + else if (data.address == "null") { if(!dataTransaction.contains(typeHistoryData::NULL_ADDR)) { dataTransaction.insert(typeHistoryData::NULL_ADDR, data); } } - else if (match.captured(6) == "emission") + else if (data.address == "emission") { if(!dataTransaction.contains(typeHistoryData::EMISSION)) { @@ -292,7 +412,7 @@ QVariant DapGetAllWalletHistoryCommand::respondToClient(const QVariant &args) { for(const QString& key: TYPES_SERVICE_TRANSACTION.keys()) { - if(match.captured(6) == key) + if(data.address == key) { if(!dataTransaction.contains(typeHistoryData::SOME_SERVICE_PAY)) { @@ -302,23 +422,8 @@ QVariant DapGetAllWalletHistoryCommand::respondToClient(const QVariant &args) } } } - else if(historyList[i].contains(REGULAR_HISTORY_PAY) && !isHashDouble) - { - QRegularExpressionMatch match = REGULAR_HISTORY_PAY.match(historyList[i]); - if(!match.hasMatch()) - { - continue; - } - HistoryData data("", match.captured(2), "", "", ""); - dataTransaction.insert(typeHistoryData::FEE_REWARD, data); - } - - if(i == size - 1) - { - setData(); - txHistory.append(txHeader); - } } + setData(); } } @@ -327,187 +432,282 @@ QVariant DapGetAllWalletHistoryCommand::respondToClient(const QVariant &args) // GET MEMPOOL QString mempoolStr = cmdList->getListMempool(net); //QString - QStringList stringsMempool = mempoolStr.split("\n"); + QStringList stringsMempool = mempoolStr.split("\n"); + + bool isStartParce = false; + + + bool hasAddressSelf = false; + + bool isAnstake = false; + bool isStartData = false; + QString addressWalletFrom, tx_hash, timeStamp, time; + QMap<MemoolTypes, QList<MempoolItem>> typesInfo; auto getTicker = [](const QString& tiker) -> QString { - return tiker.contains("null") ? "UNKNOWN" : tiker; + return tiker.contains("null") ? "UNKNOWN" : tiker; }; - QJsonObject txHeader; - bool hasAddressSelf = false; - // false = from - bool direction = false; - bool isAnstake = false; - for(auto& str: stringsMempool) + auto setMempoolData = [&]() { - str = str.trimmed(); - auto memBeginMatch = REGULAR_MEMPOOL_BEGIN.match(str); - if(memBeginMatch.hasMatch()) + QJsonObject txHeader; + + txHeader.insert(DATA_KEY, time); + txHeader.insert(DATE_TO_SECS_KEY, timeStamp); + txHeader.insert(TX_HASH_KEY, tx_hash); + txHeader.insert(TX_STATUS_KEY, "PROCESSING"); + txHeader.insert(STATUS_KEY, "Pending"); + txHeader.insert(NETWORK_KEY, net); + txHeader.insert(WALLET_NAME_KEY, walletName); + txHeader.insert(ATOM_KEY, ""); + txHeader.insert(FEE_KEY, "0.0"); + txHeader.insert(FEE_NET_KEY, "0.0"); + txHeader.insert(TOKEN_KEY, getTicker(netInfo.tokenName)); + txHeader.insert(FEE_TOKEN_KEY, getTicker(netInfo.tokenName)); + txHeader.insert(M_VALUE_KEY, "0.0"); + txHeader.insert(VALUE_KEY, "0.0"); + + bool direction = walletAddr == addressWalletFrom; + txHeader.insert(DIRECTION_KEY, !direction ? "from" : "to"); + + if(typesInfo[MemoolTypes::SECTION_TO].size() == 1 && typesInfo[MemoolTypes::SECTION_TO][0].coins.isEmpty()) { - // 1 - hash - // 3 - time DDMMYY HHmmSS - QStringList list = memBeginMatch.capturedTexts(); + typesInfo[MemoolTypes::SECTION_TO].clear(); + } - if(txHeader.contains(TX_HASH_KEY)) + for(const auto& item: typesInfo[MemoolTypes::SECTION_TO]) + { + if(netInfo.address == item.addr) { - if(hasAddressSelf) + if(direction) { - direction = false; - isAnstake = false; - txHistory.append(txHeader); + txHeader.insert(FEE_NET_KEY, item.coins); } - txHeader = QJsonObject(); - hasAddressSelf = false; + if(typesInfo[MemoolTypes::SECTION_TO].size() == 1) + { + typesInfo[MemoolTypes::SECTION_TO].clear(); + } + } - auto memTime = REGULAR_MEMPOOL_TIME.match(list[3]); - if(!memTime.hasMatch()) + else { - qWarning() << "The time output from the node has been changed."; - continue; + txHeader.insert(VALUE_KEY, item.coins); + txHeader.insert(TOKEN_KEY, item.token); + + txHeader.insert(WALLET_NAME_KEY, !direction ? walletName : item.addr); + txHeader.insert(ADDRESS_KEY, !direction ? item.addr : walletName); } + } - if(hashSet.contains(list[1])) + if(typesInfo[MemoolTypes::SECTION_TO].isEmpty() && typesInfo[MemoolTypes::SECTION_CHANGE].size() > 1) + { + QMap<QString, int> testMap; + for(const auto& item: typesInfo[MemoolTypes::SECTION_CHANGE]) { - continue; + if(testMap.contains(item.token)) + { + testMap[item.token]++; + } + else + { + testMap.insert(item.token, 1); + } } - - int month = 0; - for(int index = 0; index < MONTH_LIST.count();index++) + QString maxKeyStr = ""; + int max = 0; + for(const QString& key: testMap.keys()) { - if(memTime.captured(2) == MONTH_LIST.at(index)) + if(testMap[key] > max) { - month = index+1; - break; + max = testMap[key]; + maxKeyStr = key; } } - - auto memTimeList = memTime.capturedTexts(); - QDate date(memTimeList[3].toInt() + 2000 ,month, memTimeList[1].toInt()); - QTime time = QTime::fromString(QString("%1").arg(memTime.captured(4)),"hh:mm:ss"); - - QDateTime resultTime = QDateTime(date, time); - qint64 date_to_secs = resultTime.toSecsSinceEpoch(); - - txHeader.insert(DATA_KEY, resultTime.toString("yyyy-MM-dd")); - txHeader.insert(DATE_TO_SECS_KEY, QString::number(date_to_secs)); - txHeader.insert(TX_HASH_KEY, list[1]); - txHeader.insert(TX_STATUS_KEY, "PROCESSING"); - txHeader.insert(STATUS_KEY, "Pending"); - txHeader.insert(NETWORK_KEY, net); - txHeader.insert(WALLET_NAME_KEY, walletName); - txHeader.insert(ATOM_KEY, ""); - txHeader.insert(FEE_KEY, "0.0"); - txHeader.insert(FEE_NET_KEY, "0.0"); - txHeader.insert(TOKEN_KEY, getTicker(netInfo.tokenName)); - txHeader.insert(FEE_TOKEN_KEY, getTicker(netInfo.tokenName)); - txHeader.insert(M_VALUE_KEY, "0.0"); - txHeader.insert(VALUE_KEY, "0.0"); - continue; + txHeader.insert(TOKEN_KEY, maxKeyStr.isEmpty() ? getTicker(netInfo.tokenName) : maxKeyStr); + txHeader.insert(DIRECTION_KEY, "from"); + txHeader.insert(ADDRESS_KEY, walletName); } - if(!txHeader.contains(TX_HASH_KEY)) + if(!typesInfo[MemoolTypes::SECTION_FEE].isEmpty()) { - continue; + if(direction) + { + const auto& item = typesInfo[MemoolTypes::SECTION_FEE][0]; + txHeader.insert(FEE_KEY, item.coins); + txHeader.insert(FEE_TOKEN_KEY, item.token); + } + } - auto fromMatch = REGULAR_MEMPOOL_FROM.match(str); - if(fromMatch.hasMatch()) + if(!typesInfo[MemoolTypes::SECTION_SRV_XCHANGE].isEmpty()) { - // 1 - address - direction = walletAddr != fromMatch.captured(1); - txHeader.insert(DIRECTION_KEY, direction ? "from" : "to"); - - if(walletAddr == fromMatch.captured(1)) + if(typesInfo[MemoolTypes::SECTION_TO].isEmpty()) { - hasAddressSelf = true; - txHeader.insert(ADDRESS_KEY, walletName); - txHeader.insert(WALLET_NAME_KEY, ""); + auto& item = typesInfo[MemoolTypes::SECTION_SRV_XCHANGE][0]; + txHeader.insert(VALUE_KEY, item.coins); + txHeader.insert(TOKEN_KEY, item.token); } - else + } + + if(!typesInfo[MemoolTypes::SECTION_SRV_STAKE_LOCK].isEmpty()) + { + + } + + if(!typesInfo[MemoolTypes::SECTION_FROM_EMMISSION].isEmpty()) + { + auto& item = typesInfo[MemoolTypes::SECTION_FROM_EMMISSION][0]; + if(item.token[0] == "m") { - txHeader.insert(ADDRESS_KEY, fromMatch.captured(1)); + txHeader.insert(M_VALUE_KEY, item.coins); + txHeader.insert(M_TOKEN, item.token); + txHeader.insert(M_DIRECTION_KEY, "from"); } - continue; } + txHistory.append(std::move(txHeader)); - auto toMatch = REGULAR_MEMPOOL_TO.match(str); - if(toMatch.hasMatch()) - { - // 1 -coins - // 3 - ticker - // 4 - address or unknown + hasAddressSelf = false; - QString tiker = toMatch.captured(3); - if(!tiker.isEmpty() && tiker[0] == "m") + isAnstake = false; + isStartData = false; + addressWalletFrom.clear(); + tx_hash.clear(); + timeStamp.clear(); + time.clear();; + typesInfo.clear(); + }; + + auto getTypeInfo = [this, &stringsMempool, &hasAddressSelf, &walletAddr](int& currentIndex) -> QList<MempoolItem> + { + QList<MempoolItem> result; + MempoolItem itemResult; + + for(int i = currentIndex; i < stringsMempool.size(); i++) + { + QString currantStr = stringsMempool[i].trimmed(); + if(currantStr.isEmpty()) + { + continue; + } + else if(currantStr.contains(MONEY_MEMPOOL)) { - isAnstake = true; - txHeader.insert(M_VALUE_KEY, toMatch.captured(1)); - txHeader.insert(M_TOKEN, tiker); - txHeader.insert(M_DIRECTION_KEY, "to"); - txHeader.insert(DIRECTION_KEY, "from"); - txHeader.insert(WALLET_NAME_KEY, walletName); + if(!itemResult.value.isEmpty()) + { + result.append(itemResult); + itemResult = MempoolItem(); + } + continue; } - else if(netInfo.address == toMatch.captured(4)) + else if(currantStr.contains(VALUE_MEMPOOL)) { - txHeader.insert(FEE_NET_KEY, !direction ? toMatch.captured(1) : "0.0" ); + QRegularExpressionMatch match = REGULAR_VALUE_MEMPOOL.match(currantStr); + itemResult.value = match.captured(1); + continue; } - else if(toMatch.captured(4) == walletAddr) + else if(currantStr.contains(COINS_MEMPOOL)) { - txHeader.insert(WALLET_NAME_KEY, walletName); - txHeader.insert(VALUE_KEY, toMatch.captured(1)); - txHeader.insert(TOKEN_KEY, getTicker(tiker)); - hasAddressSelf = true; + QRegularExpressionMatch match = REGULAR_COINS_MEMPOOL.match(currantStr); + itemResult.coins = match.captured(1); + continue; } - else + else if(currantStr.contains(TOKEN_MEMPOOL)) { - txHeader.insert(WALLET_NAME_KEY, toMatch.captured(4)); - txHeader.insert(VALUE_KEY, toMatch.captured(1)); - txHeader.insert(TOKEN_KEY, getTicker(tiker)); + QRegularExpressionMatch match = REGULAR_TOKEN_MEMPOOL.match(currantStr); + itemResult.token = match.captured(1); + continue; + } + else if(currantStr.contains(ADDR_MEMPOOL)) + { + QRegularExpressionMatch match = REGULAR_ADDR_MEMPOOL.match(currantStr); + itemResult.addr = match.captured(1); + if(itemResult.addr == walletAddr) + { + hasAddressSelf = true; + } + continue; } - continue; + result.append(itemResult); + itemResult = MempoolItem(); + currentIndex = i - 1; + break; } + return result; + }; - auto feeMatch = REGULAR_MEMPOOL_FEE.match(str); - if(feeMatch.hasMatch()) + for(int i = 0; i < stringsMempool.size(); i++) + { + if(!isStartParce) { - // 1 - conins - // 3 - ticker - if(feeMatch.captured(3) != "(null)") + if(stringsMempool[i].contains("name: main")) { - txHeader.insert(FEE_KEY, !direction ? feeMatch.captured(1) : "0.0"); - txHeader.insert(FEE_TOKEN_KEY, feeMatch.captured(3)); + isStartParce = true; } - continue; } - - auto changeMatch = REGULAR_MEMPOOL_CHANGE.match(str); - if(changeMatch.hasMatch()) + else { - QString tiker = changeMatch.captured(3); - if(tiker.isEmpty() || isAnstake) + QString currentString = stringsMempool[i].trimmed(); + if(currentString.contains(REGULAR_MEMPOOL_BEGIN)) { - continue; + if(isStartData) + { + if(hasAddressSelf) + { + setMempoolData(); + } + hasAddressSelf = false; + } + QRegularExpressionMatch match = REGULAR_MEMPOOL_BEGIN.match(currentString); + QString hash = match.captured(1); + isStartData = hashSet.contains(hash) ? false : true; + if(isStartData) + { + tx_hash = hash; + hashSet.insert(hash); + } } - if(tiker[0] == "m") + else if(isStartData) { - txHeader.insert(M_VALUE_KEY, changeMatch.captured(1)); - txHeader.insert(M_TOKEN, tiker); - txHeader.insert(M_DIRECTION_KEY, "from"); + if(currentString.contains(REGULAR_MEMPOOL_TYPE)) + { + QRegularExpressionMatch match = REGULAR_MEMPOOL_TYPE.match(currentString); + if(match.captured(1) != "DATUM_TX") + { + isStartData = false; + } + + } + else if(currentString.contains(REGULAR_MEMPOOL_TIME)) + { + QRegularExpressionMatch match = REGULAR_MEMPOOL_TIME.match(currentString); + qint64 timestamp = match.captured(1).toLongLong(); + QDateTime datetime = QDateTime::fromSecsSinceEpoch(timestamp); + + qint64 date_to_secs = datetime.toSecsSinceEpoch(); + + timeStamp = QString::number(date_to_secs); + time = datetime.toString("yyyy-MM-dd"); + } + else if(currentString.contains(REGULAR_MEMPOOL_FROM)) + { + QRegularExpressionMatch match = REGULAR_MEMPOOL_FROM.match(currentString); + addressWalletFrom = match.captured(1); + if(addressWalletFrom == walletAddr) + { + hasAddressSelf = true; + } + } + else if(MATCHING_TYPE_MEMPOOL.contains(currentString)) + { + i++; + typesInfo.insert(MATCHING_TYPE_MEMPOOL[currentString], getTypeInfo(i)); + } } -// else if(!txHeader.contains(VALUE_KEY)) -// { -// txHeader.insert(ADDRESS_KEY, walletName); -// txHeader.insert(VALUE_KEY, changeMatch.captured(1)); -// txHeader.insert(TOKEN_KEY, tiker); -// } - continue; } } - - if(hasAddressSelf) + if(isStartData && hasAddressSelf) { - txHistory.append(txHeader); + setMempoolData(); } } } @@ -551,30 +751,3 @@ DapGetAllWalletHistoryCommand::NetCommissionInfo DapGetAllWalletHistoryCommand:: DapGetAllWalletHistoryCommand::HistoryData::HistoryData(const QString& status, const QString& value, const QString& token, const QString& direction, const QString& address) : status(status), value(value), token(token), direction(direction), address(address) {} - -QDateTime DapGetAllWalletHistoryCommand::convertTimeFromHistory(const QString& a_string) -{ - QRegExp rxTime("([0-9\\s]+) ([A-Za-z]{3}) ([0-9\\:]{8}) ([0-9]{4})"); - rxTime.indexIn(a_string); - - if(!rxTime.cap(0).isEmpty()) - { - int month = 0; - for(int index = 0; index < MONTH_LIST.count();index++) - { - if(rxTime.cap(2) == MONTH_LIST.at(index)) - { - month = index+1; - } - } - QDate date(rxTime.cap(5).toInt(),month,rxTime.cap(3).toInt()); - QTime time = QTime::fromString(QString("%1").arg(rxTime.cap(4)),"hh:mm:ss"); - - return QDateTime(date,time); - } - else - { - return QDateTime(); - } - -} diff --git a/chain/wallet/handlers/DapGetAllWalletHistoryCommand.h b/chain/wallet/handlers/DapGetAllWalletHistoryCommand.h index 00a70a857f5652c4be879e052f6dd4ef98d07a64..12750e3f9459b73d9539c93ebd5912f2d5c16585 100644 --- a/chain/wallet/handlers/DapGetAllWalletHistoryCommand.h +++ b/chain/wallet/handlers/DapGetAllWalletHistoryCommand.h @@ -64,31 +64,64 @@ private: QString address = ""; }; + struct MempoolItem + { + QString value = QString(); + QString coins = QString(); + QString token = QString(); + QString addr = QString(); + }; + + enum MemoolTypes + { + SECTION_TO = 0, + SECTION_CHANGE, + SECTION_FEE, + SECTION_SRV_XCHANGE, + SECTION_SRV_STAKE_LOCK, + SECTION_FROM_EMMISSION + }; + NetCommissionInfo parseNetCommissionInfo(const QString& str); - QDateTime convertTimeFromHistory(const QString& a_string); + private: QString _lastResult; QSet<QString> _lastHashSet; - const QVector<QString> _itemLookingFor = {"OUT", "OUT COND", "OUT EXT", "Signature"}; - const QVector<QString> _itemIgnoredLookingFor = {"Header"}; - const QRegularExpression REGULAR_HISTORY_BEGIN = QRegularExpression(R"(^(\S+) TX hash (\S+) with atom (.+))"); - const QRegularExpression REGULAR_HISTORY_INFO_TR = QRegularExpression(R"((recv|send) (\S+) \((\S+)\) (\S+) (\S+) (.+))"); - const QRegularExpression REGULAR_HISTORY_PAY = QRegularExpression(R"(pay (\S+) \((\S+)\) fee)"); + const QRegularExpression REGULAR_HISTORY_BEGIN = QRegularExpression(R"(status: (\S+))"); const QRegularExpression REGULAR_WALLET_ADDRESS = QRegularExpression(R"([a-zA-Z0-9]{64})"); - const QRegularExpression REGULAR_SPLIT= QRegularExpression(R"(^0x[a-fA-F0-9]{64})"); - const QRegularExpression REGULAR_TX_CREATED = QRegularExpression(R"(^TS Created: (.+))"); const QRegularExpression REGULAR_NETWORK = QRegularExpression(R"(Network: (\S+) \((\S+)\) (\S+) Addr: (\S+))"); - const QRegularExpression REGULAR_MEMPOOL_BEGIN = QRegularExpression(R"(DATUM_TX hash (0x[a-fA-F0-9]{64}) (.\S+), (.+) +(.\S+))"); - const QRegularExpression REGULAR_MEMPOOL_FROM = QRegularExpression(R"(From: (\S+))"); - const QRegularExpression REGULAR_MEMPOOL_TO = QRegularExpression(R"(To: (.\S+) \((.\S+)\) (.\S+) (.\S+))"); - const QRegularExpression REGULAR_MEMPOOL_FEE = QRegularExpression(R"(Fee: (.\S+) \((.+)\) (.+))"); - const QRegularExpression REGULAR_MEMPOOL_CHANGE = QRegularExpression(R"(hange: (.\S+) \((.\S+)\) (.\S+))"); - const QRegularExpression REGULAR_MEMPOOL_TIME = QRegularExpression(R"((\w{2}) (\w{3}) (\w{2}) (.+))"); - - const QString HEADER_ADDRESS_FOR_NET = "Addr:"; - const QString HEADER_ADDRESS_MEMPOOL = "address"; - const QString HEADER_ADDRESS_MEMPOOL_ALT = "addr"; + const QRegularExpression REGULAR_MEMPOOL_BEGIN = QRegularExpression(R"(hash: (\S+))"); + const QRegularExpression REGULAR_MEMPOOL_TYPE = QRegularExpression(R"(type: (\S+))"); + const QRegularExpression REGULAR_MEMPOOL_TIME = QRegularExpression(R"(time_stamp: (\S+))"); + const QRegularExpression REGULAR_MEMPOOL_FROM = QRegularExpression(R"(from: (\S+))"); + + const QRegularExpression REGULAR_VALUE_MEMPOOL = QRegularExpression(R"(value: (\S+))"); + const QRegularExpression REGULAR_COINS_MEMPOOL = QRegularExpression(R"(coins: (\S+))"); + const QRegularExpression REGULAR_TOKEN_MEMPOOL = QRegularExpression(R"(token: (\S+))"); + const QRegularExpression REGULAR_ADDR_MEMPOOL = QRegularExpression(R"(addr: (\S+))"); + + const QString VALUE_MEMPOOL = "value:"; + const QString COINS_MEMPOOL = "coins:"; + const QString TOKEN_MEMPOOL = "token:"; + const QString ADDR_MEMPOOL = "addr:"; + const QString MONEY_MEMPOOL = "money:"; + + const QString SECTION_TO_MEMPOOL = "to:"; + const QString SECTION_CHANGE_MEMPOOL = "change:"; + const QString SECTION_FEE_MEMPOOL = "fee:"; + const QString SECTION_SRV_XCHANGE_MEMPOOL = "srv_xchange:"; + const QString SECTION_SRV_STAKE_LOCK_MEMPOOL = "srv_stake_lock:"; + const QString SECTION_FROM_EMMISSION_MEMPOOL = "from_emission:"; + + const QMap<QString, MemoolTypes> MATCHING_TYPE_MEMPOOL = {{SECTION_TO_MEMPOOL, MemoolTypes::SECTION_TO} + ,{SECTION_CHANGE_MEMPOOL, MemoolTypes::SECTION_CHANGE} + ,{SECTION_FEE_MEMPOOL, MemoolTypes::SECTION_FEE} + ,{SECTION_SRV_XCHANGE_MEMPOOL, MemoolTypes::SECTION_SRV_XCHANGE} + ,{SECTION_SRV_STAKE_LOCK_MEMPOOL, MemoolTypes::SECTION_SRV_STAKE_LOCK} + ,{SECTION_FROM_EMMISSION_MEMPOOL, MemoolTypes::SECTION_FROM_EMMISSION}}; + + const QString TOKEN = "token"; const QString TICKER = "ticker"; const QString SUBTYPE = "subtype"; @@ -122,7 +155,6 @@ private: const QString SENDER_ADDR = "sender addr"; - const QStringList MONTH_LIST {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; enum typeHistoryData { STATE_LOCK = 0, diff --git a/chain/wallet/handlers/DapGetListWalletsCommand.cpp b/chain/wallet/handlers/DapGetListWalletsCommand.cpp index 2076b06c204bb47225a7e9a20a4269fe00673e8a..b61fe93fae90e504b2475d2e4321300bc01c35ea 100644 --- a/chain/wallet/handlers/DapGetListWalletsCommand.cpp +++ b/chain/wallet/handlers/DapGetListWalletsCommand.cpp @@ -22,16 +22,8 @@ QVariant DapGetListWalletsCommand::respondToClient(const QVariant &args) QJsonDocument walletsDoc; QJsonArray walletsArray; - QVariant v_resources = cmdList->getListWallets(); + QString resources = cmdList->getRequestListWallets(); - // if json : - if(v_resources.type() == QMetaType::QJsonDocument) { - qWarning() << "NEED JSON PARSING"; - return walletsDoc; - } - - // if string : - QString resources = v_resources.toString(); QRegularExpression rx(REGULAR_WALLET_ACTIVE, QRegularExpression::MultilineOption); QRegularExpressionMatchIterator itr = rx.globalMatch(resources); while (itr.hasNext()) diff --git a/chain/wallet/handlers/DapGetWalletInfoCommand.cpp b/chain/wallet/handlers/DapGetWalletInfoCommand.cpp index 23ac7f7214cbbb7f0ef93405cbb8aa29b4d515d9..8530b06262ad1a5aa12016372d0a86b63f3bbd15 100755 --- a/chain/wallet/handlers/DapGetWalletInfoCommand.cpp +++ b/chain/wallet/handlers/DapGetWalletInfoCommand.cpp @@ -39,7 +39,7 @@ QVariant DapGetWalletInfoCommand::respondToClient(const QVariant &args) QStringList netlist = cmdList->getListNetworks(); // get list wallets - QString res = cmdList->getListWallets(); + QString res = cmdList->getRequestListWallets(); res.remove("\r"); // check status wallet diff --git a/chain/wallet/handlers/DapGetWalletsInfoCommand.cpp b/chain/wallet/handlers/DapGetWalletsInfoCommand.cpp index fad48a0687af60d2e57b0c5c5bde619e5ea5f90e..2d329adfacb9472af6f2bf1efc39b4590cc5b5cd 100644 --- a/chain/wallet/handlers/DapGetWalletsInfoCommand.cpp +++ b/chain/wallet/handlers/DapGetWalletsInfoCommand.cpp @@ -31,7 +31,7 @@ QVariant DapGetWalletsInfoCommand::respondToClient(const QVariant &args) QStringList netlist = cmdList->getListNetworks(); // get list wallets - QString res = cmdList->getListWallets(); + QString res = cmdList->getRequestListWallets(); res.remove("\r"); QRegularExpression rx(REGULAR_WALLET_ACTIVE, QRegularExpression::MultilineOption); diff --git a/chain/wallet/handlers/DapGetWordBook.cpp b/chain/wallet/handlers/DapGetWordBook.cpp deleted file mode 100644 index 77d8b9deb0084c72745c9d24c8d04ec33da5b9bb..0000000000000000000000000000000000000000 --- a/chain/wallet/handlers/DapGetWordBook.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "DapGetWordBook.h" - -#ifdef Q_OS_WIN -#include "registry.h" -#endif - -DapGetWordBook::DapGetWordBook(const QString &asServicename, QObject *parent, const QString &asCliPath) - : DapAbstractCommand(asServicename, parent, asCliPath) -{ - s_thrBook = new QThread(); - s_wordsBook = new WordsBook(asCliPath); - s_wordsBook->moveToThread(s_thrBook); - s_thrBook->start(); - - connect(this, &DapGetWordBook::sigInit, s_wordsBook, &WordsBook::initBook, - Qt::QueuedConnection); - connect(this, &DapGetWordBook::sigUpdateValues, s_wordsBook, &WordsBook::updateValues, - Qt::QueuedConnection); -} - -DapGetWordBook::~DapGetWordBook() -{ - s_thrBook->quit(); - s_thrBook->wait(); - - delete s_thrBook, s_wordsBook; -} - -/// Send a response to the client. -/// @details Performed on the service side. -/// @param arg1...arg10 Parameters. -/// @return Reply to client. -QVariant DapGetWordBook::respondToClient(const QVariant &args) -{ - DapAbstractCommand::respondToClient(args); - - QStringList params = args.toStringList(); - - QVariantList res; - - if(params[0] == "init") - emit sigInit(); - else if (params[0] == "updateValues") - emit sigUpdateValues(); - else - res = s_wordsBook->getTreeWords(params[0]); - - QByteArray resByte; - QDataStream streamer(&resByte, QIODevice::WriteOnly); - streamer << res; - - return resByte.toHex(); -} - - diff --git a/chain/wallet/handlers/DapGetWordBook.h b/chain/wallet/handlers/DapGetWordBook.h deleted file mode 100644 index f5660c6b4f46f51f7345a04b4e6bb9649ef8044b..0000000000000000000000000000000000000000 --- a/chain/wallet/handlers/DapGetWordBook.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef DAPGETWORDBOOK_H -#define DAPGETWORDBOOK_H - -#include "DapAbstractCommand.h" -#include "WordsBookManager/WordsBook.h" -#include <QThread> - - -class DapGetWordBook : public DapAbstractCommand -{ - Q_OBJECT -public: - /// Overloaded constructor. - /// @param asServiceName Service name. - /// @param parent Parent. - /// @details The parent must be either DapRPCSocket or DapRPCLocalServer. - explicit DapGetWordBook(const QString &asServicename, QObject *parent = nullptr, const QString &asCliPath = QString()); - ~DapGetWordBook(); - -private: - WordsBook * s_wordsBook; - QThread *s_thrBook; -signals: - void sigInit(); - void sigUpdateValues(); - -public slots: - /// Send a response to the client. - /// @details Performed on the service side. - /// @param arg1...arg10 Parameters. - /// @return Reply to client. - QVariant respondToClient(const QVariant &args = QVariant()) override; -}; -#endif // DAPGETWORDBOOK_H diff --git a/chain/wallet/handlers/DapSaveHistoryExecutedCmdCommand.cpp b/chain/wallet/handlers/DapSaveHistoryExecutedCmdCommand.cpp index e958828280ac546e3458cb0ca114d651aa499dab..15db469c6118fd48072d73da2ae99ec21afacf4f 100644 --- a/chain/wallet/handlers/DapSaveHistoryExecutedCmdCommand.cpp +++ b/chain/wallet/handlers/DapSaveHistoryExecutedCmdCommand.cpp @@ -1,4 +1,5 @@ #include "DapSaveHistoryExecutedCmdCommand.h" +#include <QDateTime> /// Overloaded constructor. /// @param asServiceName Service name. @@ -24,6 +25,9 @@ void DapSaveHistoryExecutedCmdCommand::notifedFromClient(const QVariant &args) if (!m_File->open(QIODevice::Append | QIODevice::ReadWrite)) return; - m_File->write(arr.at(0).toString().toUtf8() + '\n'); + QDateTime currentDateTime = QDateTime::currentDateTime(); + QString formattedDateTime = currentDateTime.toString("dd.MM.yy - hh:mm:ss"); + + m_File->write('[' + formattedDateTime.toUtf8() + "] " + arr.at(0).toString().toUtf8() + '\n'); m_File->close(); } diff --git a/chain/wallet/handlers/DapVersionController.cpp b/chain/wallet/handlers/DapVersionController.cpp index b94ca8ea8a4e6dc0844f30f81dd06d523f55ea76..e7d0dd59f121253cde9fb2436af7729a946da435 100644 --- a/chain/wallet/handlers/DapVersionController.cpp +++ b/chain/wallet/handlers/DapVersionController.cpp @@ -98,15 +98,15 @@ QVariant DapVersionController::respondToClient(const QVariant &args) else if(params.first() == "version node") { QString result = cmdList->getVersion(); - if(result.contains("cellframe-node version")) + if(result.isEmpty()) + { + resultObj.insert(MESSAGE,QJsonValue("Error. " + result)); + } + else { - result = result.split("version")[1]; - result = result.split('\n', QString::SkipEmptyParts).first().trimmed(); resultObj.insert(LAST_VERSION,QJsonValue(result)); resultObj.insert(MESSAGE,QJsonValue("Reply node version")); } - else - resultObj.insert(MESSAGE,QJsonValue("Error. " + result)); } return resultObj; diff --git a/chain/wallet/handlers/DapWalletActivateOrDeactivateCommand.cpp b/chain/wallet/handlers/DapWalletActivateOrDeactivateCommand.cpp index 44e1e75bd456572c2f1ae58d7324aac69603e593..79f5a5eb2741fd347e8fa61327a9d290c7dce111 100644 --- a/chain/wallet/handlers/DapWalletActivateOrDeactivateCommand.cpp +++ b/chain/wallet/handlers/DapWalletActivateOrDeactivateCommand.cpp @@ -16,7 +16,7 @@ DapWalletActivateOrDeactivateCommand::DapWalletActivateOrDeactivateCommand(const /// @return Reply to client. QVariant DapWalletActivateOrDeactivateCommand::respondToClient(const QVariant &args) { - DapAbstractCommand::respondToClient(args); + qDebug() << "[" << this->getName() << "] [respondToClient]"; QStringList params = args.toStringList(); QJsonObject resultObj; diff --git a/chain/wallet/handlers/WordsBookManager/WordsBook.cpp b/chain/wallet/handlers/WordsBookManager/WordsBook.cpp deleted file mode 100644 index b9c5f3400ccff53095b770fac7ce2cf17411d1b7..0000000000000000000000000000000000000000 --- a/chain/wallet/handlers/WordsBookManager/WordsBook.cpp +++ /dev/null @@ -1,800 +0,0 @@ -#include "WordsBook.h" - - -WordsBook::WordsBook(QString cliPath, QObject *parent) - : QObject{parent} - , m_sCliPath(cliPath) -{ - -#ifdef Q_OS_LINUX - m_pathWords = QString("/opt/%1/data/wordsBook.ini").arg(DAP_BRAND_LO); -#elif defined Q_OS_MACOS - mkdir("/tmp/Cellframe-Dashboard_data",0777); - m_pathWords = QString("/tmp/Cellframe-Dashboard_data/wordsBook.ini"); -#elif defined Q_OS_WIN - m_pathWords = QString("%1/%2/data/wordsBook.ini").arg(regGetUsrPath()).arg(DAP_BRAND); -#endif - isInit = false; - -} - -void WordsBook::updateValues() -{ - _getWallets(); - _getCerts(); - _getChains(); - _getMempoolTokens(); -} - -void WordsBook::initBook() -{ - updateValues(); - - if(!isInit) - { - cliDataPreparation(); - - if(words.count() > 0) - { - isInit = true; - } - } - -} - -void WordsBook::cliDataPreparation() -{ - QFile file(m_pathWords); - - if(file.exists()) - { - if(file.open(QIODevice::ReadOnly)) - { - QDataStream in(&file); - in.setVersion(QDataStream::Qt_5_15); - in >> cliData; - file.close(); - } - - if(!cliData.length()) - { - file.remove(); - QString result = cmdCommand("help")[1]; - parseAllCommands(result); - } - } - else - { - QString result = cmdCommand("help")[1]; - parseAllCommands(result); - - if(file.open(QIODevice::WriteOnly)) - { - QDataStream out(&file); - out.setVersion(QDataStream::Qt_5_15); - out << cliData; - file.close(); - } - } - - for(auto command : cliData) - parseAllCommandsParams(command); -} - -QString WordsBook::rightOrCommand(QString command, int i) -{ - int count = 0; - int k = i; - while (true) - { - if (i - 1 < 0) - return ""; - if (command[i] == ']' || command[i] == '}') - ++count; - - if (command[i] == '[' || command[i] == '{') - { - if (count == 0) - break; - --count; - } - --i; - } - command = command.remove(i + 1, k - i); - return command; -} - -QString WordsBook::leftOrCommand(QString command, int i) -{ - int count = 0; - int k = i; - int j = 0; - while (true) - { - if (i+1 > command.length()) - return ""; - if (command[i] == ']' || command[i] == '}') - { - if (count == 0) - break; - --count; - } - - if (command[i] == '[' || command[i] == '{') - ++count; - ++i; - } - - command = command.remove(k, i - k); - return command; -} - -void WordsBook::parseAllCommands(const QString &asAnswer) -{ - QString str = asAnswer; - str = str.right(str.size() - 21); - - QStringList _commands = str.split("\n"); - - for (int i = 0; i < _commands.length(); ++i) - { - QStringList tmp = _commands[i].split(":"); - if (!tmp.empty() && tmp[0] != "" && tmp[0] != "\r") - { - commands.append(tmp[0]); - QStringList result = cmdCommand("help " + tmp[0]); - - cliData.append(result); - } - } -} - -void WordsBook::parseAllCommandsParams(const QStringList &asAnswer) -{ - QString command = asAnswer[0]; - command = command.right(command.length() - 5); - - QString str = asAnswer[1]; - - str = str.right(str.size()); - - QStringList _commands = str.split("\n"); - - for (int i = 1; i < _commands.length(); ++i) - { - if (!_commands[i].startsWith("\t") && _commands[i] != "" && _commands[i] != "\r" && _commands[i][0].isLower() && _commands[i] != "s" && _commands[i] != "g" && _commands[i] != "n") - { - if (_commands[i].contains("\t")) - _commands[i] = _commands[i].split('\t')[0]; - - if (_commands[i].contains("\r")) - _commands[i] = _commands[i].split('\r')[0]; - { - parsedCommands.clear(); - parseTree(_commands[i]); - parsedCommands.removeDuplicates(); - for (int j = 0; j < parsedCommands.length(); ++j) - { - QStringList s = parsedCommands[j].split(" "); - s.removeAll(""); - words[command].append(s); - } - } - } - } -} - -void WordsBook::parseTree(QString command) -{ - bool containsValue = command.contains("<mempool_token_ticker>") || command.contains("<chain_name>") || command.contains("<priv_cert_name>") || command.contains("<pub_cert_name>") || command.contains("<net_name>") || command.contains("<wallet_name>") || command.contains("<token_ticker>"); - if (!command.contains("[") && !command.contains("|") && !containsValue) - { - command = command.remove('{'); - command = command.remove('}'); - - if (!(!command.contains(" ") || (command.count(" ") == 1 && command.endsWith(" ")))) - { - for (int i = 0; i < command.length(); ++i) - if (command[i] == ' ' && command[i - 1] == ' ') - { - command.remove(i, 1); - if(i - 1 < 0) - break; - --i; - } - - parsedCommands.append(command); - } - return; - } - else - if (command.contains("|")) - { - for (int i = 0; i < command.length(); ++i) - { - if (command[i] == '|'/* && count == 0*/) - { - parseTree(leftOrCommand(command, i)); - parseTree(rightOrCommand(command, i)); - } - } - } - else - if (command.contains("[") || command.contains("]")) - { - int count = 0; - int leftIndex = 0; - for (int i = 0; i < command.length(); ++i) - { - if (command[i] == '[' && count == 0) - leftIndex = i; - - if (command[i] == ']' && count == 1) - { - QString delCommand = command; - delCommand = delCommand.remove(leftIndex, i - leftIndex + 1); - parseTree(delCommand); - - QString isCommand = command.remove(i, 1); - isCommand = isCommand.remove(leftIndex, 1); - parseTree(isCommand); - - if(i > command.length()-1) - break; - } - - if (command[i] == '[') - ++count; - - if (command[i] == ']') - --count; - } - } - else - if (command.contains("<") || command.contains(">")) - { - if (command.contains("<priv_cert_name>")) - { - QStringList certsList = getPrivCerts(); - - QString sCommand = command; - int idx = sCommand.indexOf("<priv_cert_name>"); - QString s = sCommand.remove(idx, 16); - if(!certsList.isEmpty()) - { - for (int i = 0; i < certsList.length(); ++i) - { - QString rS = s; - rS = rS.insert(idx, certsList[i]); - parseTree(rS); - } - } - QString rS = s; - rS = rS.insert(idx, "<empty>"); - parseTree(rS); - } - else - if (command.contains("<pub_cert_name>")) - { - QStringList certsList = getPubCerts(); - - QString sCommand = command; - int idx = sCommand.indexOf("<pub_cert_name>"); - QString s = sCommand.remove(idx, 15); - if(!certsList.isEmpty()) - { - for (int i = 0; i < certsList.length(); ++i) - { - QString rS = s; - rS = rS.insert(idx, certsList[i]); - parseTree(rS); - } - } - QString rS = s; - rS = rS.insert(idx, "<empty>"); - parseTree(rS); - } - else - if (command.contains("<net_name>")) - { - QStringList netList = getNetworks(); - QString sCommand = command; - int idx = sCommand.indexOf("<net_name>"); - QString s = sCommand.remove(idx, 10); - if(!netList.isEmpty()) - { - for (int i = 0; i < netList.length(); ++i) - { - QString rS = s; - rS = rS.insert(idx, netList[i]); - parseTree(rS); - } - } - QString rS = s; - rS = rS.insert(idx, "<empty>"); - parseTree(rS); - } - else - if (command.contains("<wallet_name>")) - { - QStringList walletList = getWallets(); - QString sCommand = command; - int idx = sCommand.indexOf("<wallet_name>"); - QString s = sCommand.remove(idx, 13); - if(!walletList.isEmpty()) - { - for (int i = 0; i < walletList.length(); ++i) - { - QString rS = s; - rS = rS.insert(idx, walletList[i]); - parseTree(rS); - } - } - QString rS = s; - rS = rS.insert(idx, "<empty>"); - parseTree(rS); - } - else - if (command.contains("<token_ticker>")) - { - QStringList tokenList = getTokens(); - QString sCommand = command; - int idx = sCommand.indexOf("<token_ticker>"); - QString s = sCommand.remove(idx, 14); - if(!tokenList.isEmpty()) - { - for (int i = 0; i < tokenList.length(); ++i) - { - QString rS = s; - rS = rS.insert(idx, tokenList[i]); - parseTree(rS); - } - } - QString rS = s; - rS = rS.insert(idx, "<empty>"); - parseTree(rS); - } - else - if (command.contains("<mempool_token_ticker>")) - { - QStringList tokenList = getAllMempoolTokens(); - QString sCommand = command; - int idx = sCommand.indexOf("<mempool_token_ticker>"); - QString s = sCommand.remove(idx, 22); - if(!tokenList.isEmpty()) - { - for (int i = 0; i < tokenList.length(); ++i) - { - QString rS = s; - rS = rS.insert(idx, tokenList[i]); - parseTree(rS); - } - } - QString rS = s; - rS = rS.insert(idx, "<empty>"); - parseTree(rS); - } - else - if (command.contains("<chain_name>")) - { - QStringList chaintList = getAllChains(); - QString sCommand = command; - int idx = sCommand.indexOf("<chain_name>"); - QString s = sCommand.remove(idx, 12); - if(!chaintList.isEmpty()) - { - for (int i = 0; i < chaintList.length(); ++i) - { - QString rS = s; - rS = rS.insert(idx, chaintList[i]); - parseTree(rS); - } - } - QString rS = s; - rS = rS.insert(idx, "<empty>"); - parseTree(rS); - } - else return; - } - else - return; -} - -QVariantList WordsBook::getTreeWords(QString value) -{ - - QStringList list = value.split(" "); - - QVariantList res; - - if (value == "") - return res; - - QVariantMap map; - - QStringList checkChainList; - - if (list.length() == 1) - { - for (int i = 0; i < commands.length(); ++i) - if (commands[i].startsWith(value)) - { - map["word"] = QVariant::fromValue(commands[i]); - checkChainList.append(commands[i]); - map["str"] = QVariant::fromValue(commands[i] + " "); - res.append(map); - } - return res; - } - - - QString key = list[0]; - commandTree *tree = &words[key]; - - for (int i = 1; i < list.length(); ++i) - { - for (int j = 0; j < tree->children.length(); ++j) - if (tree->children[j]->data == list[i]) - { - tree = tree->children[j]; - break; - } - } - - if (!value.endsWith(tree->data)) - { - int k = value.length() - 1; - while (value[k] != " ") - --k; - value = value.left(k); - } - - bool isAllWord = false; - - for (int i = 0; i < tree->children.length(); ++i) - { - QString str = tree->children[i]->data; - if (str.startsWith(" ")) - str.remove(0, 1); - - if (str != "" && str != " " && (str.startsWith(list[list.length() - 1]) || tree->data == list[list.length() - 1])) - { - if (str == list[list.length() - 1]) - isAllWord = true; - map["word"] = QVariant::fromValue(str); - checkChainList.append(str); - if (!value.endsWith(" ")) - value += " "; - map["str"] = QVariant::fromValue(value + str); - res.append(map); - } - } - - - // QStringList chainsList = getAllChains(); - // bool isEqual = false; - - // if (checkChainList.length() == chainsList.length() && checkChainList.length() != 0 && value.contains("-net")) - // { - // isEqual = true; - // for (int k = 0; k < checkChainList.length(); ++k) - // if (!checkChainList.contains(chainsList[k])) - // isEqual = false; - // } - - // if (isEqual) - // { - // int idx = value.indexOf("-net") + 5; - // while (value[idx] == " ") - // ++idx; - - // QString netName = ""; - // while (value[idx] != " ") - // { - // netName.push_back(value[idx]); - // ++idx; - // } - - // QStringList netChains = getChainsByNetwork(netName); - // QVariantList chainsRes; - - // for (int k = 0; k < res.length(); ++k) - // { - // if (netChains.contains(res[k].toMap()["word"].toString())) - // chainsRes.append(res[k]); - // } - - // return chainsRes; - // } - - // QStringList netsList = getNetworks(); - // bool isNetEqual = false; - - // if (checkChainList.length() == netsList.length() && checkChainList.length() != 0 && value.contains("-chain")) - // { - // isNetEqual = true; - // for (int k = 0; k < checkChainList.length(); ++k) - // if (!checkChainList.contains(netsList[k])) - // isNetEqual = false; - // } - - // if (isNetEqual) - // { - // int idx = value.indexOf("-chain") + 7; - // while (value[idx] == " ") - // ++idx; - - // QString chainName = ""; - // while (value[idx] != " ") - // { - // chainName.push_back(value[idx]); - // ++idx; - // } - - // QStringList chainNets = getNetworkByChain(chainName); - // QVariantList netsRes; - - // for (int k = 0; k < res.length(); ++k) - // { - // if (chainNets.contains(res[k].toMap()["word"].toString())) - // netsRes.append(res[k]); - // } - - // return netsRes; - // } - - return res; -} - -void WordsBook::_getCerts() -{ - pubCerts.clear(); - privCerts.clear(); - QDir pubDir(PUB_CERT_PATH); - pubDir.setFilter(QDir::Files | QDir::Hidden); - QStringList files = pubDir.entryList(); - for (int i = 0; i < files.length(); ++i) - { - QString s = files[i].remove(".dcert"); - if (s != "." && s != "..") - pubCerts.append(s); - } - - QDir privDir(PRIV_CERT_PATH); - privDir.setFilter(QDir::Files | QDir::Hidden); - files = privDir.entryList(); - for (int i = 0; i < files.length(); ++i) - { - QString s = files[i].remove(".dcert"); - if (s != "." && s != "..") - privCerts.append(s); - } -} - -void WordsBook::_getChains() -{ - chains.clear(); - chainNets.clear(); - - QString command = QString("%1 net list chains").arg(CLI_PATH); - QString result = cmdCommand(command)[1]; - - result = result.remove("Networks:\n\t"); - result = result.remove(":"); - result = result.remove("\n"); - result = result.remove("\r"); - QStringList list = result.split("\t"); - list.removeAll(""); - - if (list.isEmpty()) - return; - - QString netKey = list[0]; - QStringList chainList; - - for (int i = 1; i < list.length(); ++i) - { - if (!networks.contains(list[i])) - { - chainList.append(list[i]); - chains.append(list[i]); - if (chainNets.keys().contains(list[i])) - chainNets[list[i]].append(netKey); - else - chainNets.insert(list[i], {netKey}); - } - else - { - netChains.insert(netKey, chainList); - chainList.clear(); - netKey = list[i]; - } - } - netChains.insert(netKey, chainList); - chains.removeDuplicates(); - for (int i = 0; i < chainNets.keys().length(); ++i) - { - chainNets[chainNets.keys()[i]].removeDuplicates(); - } -} - -void WordsBook::_getMempoolTokens() -{ - mempoolTokens.clear(); - for (int i = 0; i < networks.length(); ++i) - { - QString command = QString("%1 ledger list coins -net %2").arg(CLI_PATH).arg(networks[i]); - QString result = cmdCommand(command)[1]; - - QStringList list = result.split("\n"); - QStringList resList; - - for (int j = 0; j < list.length(); ++j) - if (list[j].contains("Token name")) - resList.append(list[j]); - - for (int j = 0; j < resList.length(); ++j) - { - int k = 12; - QString tokenName = ""; - while (resList[j][k] != '\'') - { - tokenName += resList[j][k]; - ++k; - } - resList[j] = tokenName; - } - mempoolTokens.insert(networks[i], resList); - } -} - -void WordsBook::_getWallets() -{ - wallets.clear(); - QStringList netlist; - - QString result = cmdCommand(QString("net list"))[1]; - - if (!result.contains("Socket connection err") && - result.contains("Networks:")) - { - result.remove(' '); - result.remove('\r'); - result.remove('\t'); - result.remove("Networks:"); - if(!(result.isEmpty() || result.isNull() || result.contains('\''))) - netlist = result.split('\n', QString::SkipEmptyParts); - } - else - qWarning() << "Net list ERROR! Result:" << result; - - networks = netlist; - - QString res = cmdCommand(QString("wallet list"))[1]; - res.remove("\r"); - QRegularExpression rx(REGULAR_WALLET_ACTIVE, QRegularExpression::MultilineOption); - QRegularExpressionMatchIterator itr = rx.globalMatch(res); - while (itr.hasNext()) - { - QRegularExpressionMatch match = itr.next(); - if(BACKUP == match.captured(3)) continue; - QString walletName = match.captured(1); - - wallets.append(walletName); - - for (QString net: netlist) - { - QByteArray result_tokens = cmdCommand(QString("wallet info -w %1 -net %2") - .arg(walletName) - .arg(net))[1].toStdString().data(); -#ifdef Q_OS_WIN - QRegularExpression regex(R"(wallet: (\S+)\r\naddr: (\S+)\r\nnetwork: (\S+)\r\nbalance:)"); -#else - QRegularExpression regex(R"(wallet: (\S+)\naddr: (\S+)\nnetwork: (\S+)\nbalance:)"); -#endif - QRegularExpressionMatch match = regex.match(result_tokens); - if (!match.hasMatch()) - qWarning() << "Wallet: " << walletName << "Can't parse result" << result_tokens; - else - { - QString network = match.captured(3); - if (network != net) - continue; - - QRegularExpression balanceRegex1(R"((\d+.\d+) \((\d+)\) (\w+))"); - QRegularExpression balanceRegex2(R"((\d+.) \((\d+)\) (\w+))"); - QRegularExpressionMatchIterator matchIt1 = balanceRegex1.globalMatch(result_tokens); - QRegularExpressionMatchIterator matchIt2 = balanceRegex2.globalMatch(result_tokens); - QRegularExpressionMatchIterator matchIt = matchIt1.hasNext() ? matchIt1 : matchIt2; - - while (matchIt.hasNext()) - { - QRegularExpressionMatch match = matchIt.next(); - tokens.append(match.captured(3)); - } - } - } - } -} - -QStringList WordsBook::getAllMempoolTokens() -{ - QStringList res = {}; - for (int i = 0; i < mempoolTokens.keys().length(); ++i) - { - res += mempoolTokens[mempoolTokens.keys()[i]]; - } - return res; -} - -WordsBook::commandTree WordsBook::commandTree::append(QStringList command) -{ - int i = 1; - if (this->data == "") - { - this->data = command[0]; - } - - commandTree *tree = this; - bool flag = true; - - while (flag) - { - if (tree->children.length() == 0 || i == command.length()) - break; - for (int j = 0; j < tree->children.length(); ++j) - if (tree->children[j]->data == command[i]) - { - tree = tree->children[j]; - ++i; - break; - } - else - if (j == tree->children.length() - 1) - flag = false; - } - - for (int j = i; j < command.length(); ++j) - { - commandTree *tmp = new commandTree; - tmp->data = command[j]; - tree->children.append(tmp); - tree = tmp; - } - - return *this; -} - -void WordsBook::commandTree::debugTree(commandTree *tree) -{ - qDebug() << "papa" << tree->data; - - if (tree->children.length() == 0) - { - return; - } - - for (int i = 0; i < tree->children.length(); ++i) - { - qDebug() << "chichi" << tree->children[i]->data; - } - - for (int i = 0; i < tree->children.length(); ++i) - { - debugTree(tree->children[i]); - } -} - -QStringList WordsBook::cmdCommand(QString cmd) -{ - QProcess process; - QString command = QString("%1 %2").arg(m_sCliPath).arg(cmd); - process.start(command); - process.waitForFinished(10000); - // QStringList result = QString::fromLatin1(process.readAll()); - QStringList result; - result.append(cmd); - result.append(QString::fromLatin1(process.readAll())); - - return result; -} diff --git a/chain/wallet/handlers/WordsBookManager/WordsBook.h b/chain/wallet/handlers/WordsBookManager/WordsBook.h deleted file mode 100644 index 03902c6190d1fc9941cfdb6f3dd74e6d4daf067f..0000000000000000000000000000000000000000 --- a/chain/wallet/handlers/WordsBookManager/WordsBook.h +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef WORDSBOOK_H -#define WORDSBOOK_H - -#include <QObject> -#include <QProcess> -#include <QString> -#include <QStringList> -#include <QMap> -#include <QDir> -#include <QFile> -#include <QDebug> -#include <QRegularExpression> -#include <QRegularExpressionMatch> -#include <QRegularExpressionMatchIterator> -#include <DapWallet.h> -#include <QDataStream> -#include <QIODevice> -#include <QEventLoop> -#include <QDataStream> - -#ifdef Q_OS_WIN -#include "registry.h" -#define PRIV_CERT_PATH QString("%1/cellframe-node/var/lib/ca/").arg(regGetUsrPath()) -#define PUB_CERT_PATH QString("%1/cellframe-node/share/ca/").arg(regGetUsrPath()) -#define NETWORKS_PATH QString("%1/cellframe-node/etc/network/").arg(regGetUsrPath()) -#endif - -#ifdef Q_OS_MAC -#include <sys/stat.h> -#define PUB_CERT_PATH QString("/Users/%1/Applications/Cellframe.app/Contents/Resources/share/ca/").arg(getenv("USER")) -#define PRIV_CERT_PATH QString("/Users/%1/Applications/Cellframe.app/Contents/Resources/var/lib/ca/").arg(getenv("USER")) -#define NETWORKS_PATH QString("/Users/%1/Applications/Cellframe.app/Contents/Resources/etc/network/").arg(getenv("USER")) -#endif - -#ifdef Q_OS_LINUX -#include <sys/stat.h> -#define PUB_CERT_PATH QString("/opt/cellframe-node/share/ca") -#define PRIV_CERT_PATH QString("/opt/cellframe-node/var/lib/ca") -#define NETWORKS_PATH QString("/opt/cellframe-node/etc/network/") -#endif - -class WordsBook : public QObject -{ - Q_OBJECT -public: - explicit WordsBook(QString cliPath, QObject *parent = nullptr); - - QVariantList getTreeWords(QString value); - -public: - - QString m_sCliPath; - bool isInit; - - struct commandTree - { - QString data; - QList<commandTree*> children; - - commandTree append(QStringList command); - void debugTree(commandTree *tree); - }; - - QMap<QString, commandTree> words; - - QStringList commands; - QStringList parsedCommands; - QVariantMap commandsParams; - - QStringList pubCerts; - QStringList privCerts; - QStringList networks; - QStringList wallets; - QStringList tokens; - QStringList chains; - QMap<QString, QStringList> netChains; - QMap<QString, QStringList> chainNets; - QMap<QString, QStringList> mempoolTokens; - - QList <QStringList> cliData; - - - QString m_pathWords; - - - -private: - - void cliDataPreparation(); - - - QStringList cmdCommand(QString command); - void parseTree(QString command); - - QString leftOrCommand(QString command, int i); - QString rightOrCommand(QString command, int i); - - void parseAllCommands(const QString& asAnswer); - void parseAllCommandsParams(const QStringList& asAnswer); - - - int maxLengthText(QVariantList list); - - void _getCerts(); - void _getChains(); - void _getMempoolTokens(); - void _getWallets(); - - QStringList getPubCerts(){return pubCerts;}; - QStringList getPrivCerts(){return privCerts;}; - QStringList getNetworks(){return networks;}; - QStringList getWallets(){return wallets;}; - QStringList getTokens(){return tokens;}; - QStringList getAllChains(){return chains;}; - QStringList getChainsByNetwork(const QString &netName){return netChains[netName];}; - QStringList getNetworkByChain(const QString &chainName){return chainNets[chainName];}; - QStringList getAllMempoolTokens(); - QStringList getMempoolTokensByNetwork(const QString &netName){return mempoolTokens[netName];}; - - - - -public slots: - void initBook(); - void updateValues(); - -private: - const QString BACKUP = "Backup"; - const QString REGULAR_WALLET_ACTIVE = R"(^Wallet: (\S+)( \((\S+)\))?)"; -}; - -#endif // WORDSBOOK_H diff --git a/chain/wallet/libdap-qt-chain-wallet.pri b/chain/wallet/libdap-qt-chain-wallet.pri index 6f3cdccf2302ff092743e510deb1811b3b13e3a7..af6957b87b760363528c820177f30a81d4e2ab13 100644 --- a/chain/wallet/libdap-qt-chain-wallet.pri +++ b/chain/wallet/libdap-qt-chain-wallet.pri @@ -27,6 +27,8 @@ HEADERS += \ $$PWD/DapWalletHistoryEvent.h \ $$PWD/DapWalletToken.h \ $$PWD/VpnOrder.h \ + $$PWD/autocomplete/HelpDictionaryServiceController.h \ + $$PWD/autocomplete/HelpDictionaryController.h \ $$PWD/dapconfigreader.h \ $$PWD/handlers/CertificateManager/DapCertificateCommands.h \ $$PWD/handlers/CertificateManager/DapCertificateOperation.h \ @@ -42,6 +44,7 @@ HEADERS += \ $$PWD/handlers/DapCreateTransactionCommand.h \ $$PWD/handlers/DapCreateVPNOrder.h \ $$PWD/handlers/DapGetOnceWalletInfoCommand.h \ + $$PWD/handlers/DapDictionaryCommand.h \ $$PWD/handlers/DapExportLogCommand.h \ $$PWD/handlers/DapGetAllWalletHistoryCommand.h \ $$PWD/handlers/DapGetFeeCommand.h \ @@ -84,8 +87,7 @@ HEADERS += \ $$PWD/handlers/DapXchangeOrderCreate.h \ $$PWD/handlers/DapXchangeOrderPurchase.h \ $$PWD/handlers/DapXchangeOrderRemove.h \ - $$PWD/handlers/WordsBookManager/WordsBook.h \ - $$PWD/handlers/DapGetWordBook.h \ + $$PWD/autocomplete/TreeDictionaryBase.h \ $$PWD/models/DapBalanceModel.h \ $$PWD/models/DapNetworksModel.h \ $$PWD/models/DapTransactionsProxyModel.h \ @@ -118,6 +120,8 @@ SOURCES += \ $$PWD/DapWalletHistoryEvent.cpp \ $$PWD/DapWalletToken.cpp \ $$PWD/VpnOrder.cpp \ + $$PWD/autocomplete/HelpDictionaryServiceController.cpp \ + $$PWD/autocomplete/HelpDictionaryController.cpp \ $$PWD/dapconfigreader.cpp \ $$PWD/handlers/CertificateManager/DapCertificateCommands.cpp \ $$PWD/handlers/CertificateManager/DapCertificateOperation.cpp \ @@ -131,6 +135,7 @@ SOURCES += \ $$PWD/handlers/DapCreateTransactionCommand.cpp \ $$PWD/handlers/DapCreateVPNOrder.cpp \ $$PWD/handlers/DapGetOnceWalletInfoCommand.cpp \ + $$PWD/handlers/DapDictionaryCommand.cpp \ $$PWD/handlers/DapExportLogCommand.cpp \ $$PWD/handlers/DapGetAllWalletHistoryCommand.cpp \ $$PWD/handlers/DapGetFeeCommand.cpp \ @@ -173,8 +178,7 @@ SOURCES += \ $$PWD/handlers/DapXchangeOrderCreate.cpp \ $$PWD/handlers/DapXchangeOrderPurchase.cpp \ $$PWD/handlers/DapXchangeOrderRemove.cpp \ - $$PWD/handlers/WordsBookManager/WordsBook.cpp \ - $$PWD/handlers/DapGetWordBook.cpp \ + $$PWD/autocomplete/TreeDictionaryBase.cpp \ $$PWD/models/DapBalanceModel.cpp \ $$PWD/models/DapNetworksModel.cpp \ $$PWD/models/DapTransactionsProxyModel.cpp \