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 = [&currentList, &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 = [&currentList, &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> &params
+                                  , 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> &params
+                        , 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 &parameterInfo = 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 \