diff --git a/.gitignore b/.gitignore
index c6127b38c1aa25968a88db3940604d41529e4cf5..754c5be8b9ae38f027341294b2737b87b9e227e0 100755
--- a/.gitignore
+++ b/.gitignore
@@ -50,3 +50,6 @@ modules.order
 Module.symvers
 Mkfile.old
 dkms.conf
+/build/
+/.project
+/.cproject
diff --git a/CMakeLists.txt b/CMakeLists.txt
old mode 100755
new mode 100644
diff --git a/LICENSE b/LICENSE
old mode 100755
new mode 100644
diff --git a/README.md b/README.md
old mode 100755
new mode 100644
diff --git a/dap_chain_net.c b/dap_chain_net.c
old mode 100755
new mode 100644
index fc3daced3799f4747e880167e04d77abc286c0a7..fdf4ca9b822a94d897c5671e8e48c329087c499c
--- a/dap_chain_net.c
+++ b/dap_chain_net.c
@@ -44,12 +44,6 @@
 
 #define LOG_TAG "chain_net"
 
-typedef  enum dap_chain_net_state{
-    NET_STATE_BEGIN = 0,
-    NET_STATE_LINKS_CONNECTING,
-    NET_STATE_LINKS_ESTABLISHED,
-} dap_chain_net_state_t;
-
 /**
   * @struct dap_chain_net_pvt
   * @details Private part of chain_net dap object
@@ -61,11 +55,17 @@ typedef struct dap_chain_net_pvt{
     uint8_t padding[4];
 
     dap_chain_node_client_t * clients_by_node_addr;
+    dap_chain_node_client_t * clients_by_ipv4;
+    dap_chain_node_client_t * clients_by_ipv6;
+    size_t clients_count;
+
     dap_chain_net_state_t state;
+    dap_chain_net_state_t state_target;
 } dap_chain_net_pvt_t;
 
 typedef struct dap_chain_net_item{
     char name [DAP_CHAIN_NET_NAME_MAX];
+    dap_chain_net_id_t net_id;
     dap_chain_net_t * chain_net;
     UT_hash_handle hh;
 } dap_chain_net_item_t;
@@ -74,11 +74,81 @@ typedef struct dap_chain_net_item{
 #define PVT_S(a) ( (dap_chain_net_pvt_t *) (void*) a.pvt )
 
 static dap_chain_net_item_t * s_net_items = NULL;
+static dap_chain_net_item_t * s_net_items_ids = NULL;
 
 static size_t            s_net_configs_count = 0;
 static pthread_cond_t    s_net_proc_loop_cond = PTHREAD_COND_INITIALIZER;
 static pthread_mutex_t    s_net_proc_loop_mutex = PTHREAD_MUTEX_INITIALIZER;
 
+int s_net_states_proc(dap_chain_net_t * l_net);
+
+static const char * c_net_states[]={
+    [NET_STATE_BEGIN] = "NET_STATE_BEGIN",
+    [NET_STATE_LINKS_CONNECTING] = "NET_STATE_LINKS_CONNECTING",
+    [NET_STATE_LINKS_ESTABLISHED]= "NET_STATE_LINKS_ESTABLISHED",
+    [NET_STATE_SYNC_GDB]= "NET_STATE_SYNC_GDB",
+    [NET_STATE_SYNC_CHAINS]= "NET_STATE_SYNC_CHAINS",
+    [NET_STATE_STAND_BY]= "NET_STATE_STAND_BY"
+};
+
+/**
+ * @brief s_net_state_to_str
+ * @param l_state
+ * @return
+ */
+inline static const char * s_net_state_to_str(dap_chain_net_state_t l_state)
+{
+    return c_net_states[l_state];
+}
+
+/**
+ * @brief dap_chain_net_state_go_to
+ * @param a_net
+ * @param a_new_state
+ */
+int dap_chain_net_state_go_to(dap_chain_net_t * a_net, dap_chain_net_state_t a_new_state)
+{
+    if (PVT(a_net)->state_target == a_new_state){
+        log_it(L_WARNING,"Already going to state %s",s_net_state_to_str(a_new_state));
+    }
+    PVT(a_net)->state_target = a_new_state;
+    return s_net_states_proc(a_net);
+}
+
+
+/**
+ * @brief s_net_states_proc
+ * @param l_net
+ */
+int s_net_states_proc(dap_chain_net_t * l_net)
+{
+    int ret=0;
+    switch ( PVT(l_net)->state ){
+        case NET_STATE_BEGIN:{
+            if ( PVT(l_net)->state_target != NET_STATE_BEGIN )
+                dap_chain_net_links_establish(l_net);
+        }break;
+        case NET_STATE_LINKS_CONNECTING:{
+
+            log_it(L_DEBUG,"Connected %u/% links", PVT(l_net)->clients_count );
+            ret = 1;
+        }break;
+        case NET_STATE_LINKS_ESTABLISHED:{
+
+        }break;
+        case NET_STATE_SYNC_GDB:{
+
+        }break;
+        case NET_STATE_SYNC_CHAINS:{
+
+        }break;
+        case NET_STATE_STAND_BY:{
+
+        } break;
+    }
+    return ret;
+}
+
 /**
  * @brief s_net_proc_thread
  * @details Brings up and check the Dap Chain Network
@@ -94,6 +164,7 @@ static void * s_net_proc_thread ( void * a_net)
         pthread_cond_wait(&s_net_proc_loop_cond,&s_net_proc_loop_mutex);
         pthread_mutex_unlock(&s_net_proc_loop_mutex);
         log_it( L_DEBUG, "Waked up net proc thread");
+        s_net_states_proc(l_net);
     }
     return NULL;
 }
@@ -102,7 +173,7 @@ static void * s_net_proc_thread ( void * a_net)
  * @brief net_proc_start
  * @param a_cfg
  */
-static void s_net_proc_start( dap_chain_net_t * a_net )
+static void s_net_proc_thread_start( dap_chain_net_t * a_net )
 {
     if ( pthread_create(& PVT(a_net)->proc_tid ,NULL, s_net_proc_thread, a_net) == 0 ){
         log_it (L_NOTICE,"Network processing thread started");
@@ -137,10 +208,39 @@ dap_chain_net_t * dap_chain_net_new(const char * a_id, const char * a_name ,
 {
     dap_chain_net_t * ret = DAP_NEW_Z_SIZE (dap_chain_net_t, sizeof (ret->pub)+ sizeof (dap_chain_net_pvt_t) );
     ret->pub.name = strdup( a_name );
+
     if ( sscanf(a_id,"0x%016lx", &ret->pub.id.uint64 ) == 1 ){
-        if (strcmp (a_node_role, "root")==0){
-            PVT(ret)->node_role.enums = ROOT;
+        if (strcmp (a_node_role, "root_master")==0){
+            PVT(ret)->node_role.enums = NODE_ROLE_ROOT_MASTER;
+            log_it (L_NOTICE, "Node role \"root master\" selected");
+        } else if (strcmp( a_node_role,"root") == 0){
+            PVT(ret)->node_role.enums = NODE_ROLE_ROOT;
             log_it (L_NOTICE, "Node role \"root\" selected");
+
+        } else if (strcmp( a_node_role,"archive") == 0){
+            PVT(ret)->node_role.enums = NODE_ROLE_ARCHIVE;
+            log_it (L_NOTICE, "Node role \"archive\" selected");
+
+        } else if (strcmp( a_node_role,"cell_master") == 0){
+            PVT(ret)->node_role.enums = NODE_ROLE_CELL_MASTER;
+            log_it (L_NOTICE, "Node role \"cell master\" selected");
+
+        }else if (strcmp( a_node_role,"master") == 0){
+            PVT(ret)->node_role.enums = NODE_ROLE_MASTER;
+            log_it (L_NOTICE, "Node role \"master\" selected");
+
+        }else if (strcmp( a_node_role,"full") == 0){
+            PVT(ret)->node_role.enums = NODE_ROLE_FULL;
+            log_it (L_NOTICE, "Node role \"full\" selected");
+
+        }else if (strcmp( a_node_role,"light") == 0){
+            PVT(ret)->node_role.enums = NODE_ROLE_LIGHT;
+            log_it (L_NOTICE, "Node role \"light\" selected");
+
+        }else{
+            log_it(L_ERROR,"Unknown node role \"%s\"",a_node_role);
+            DAP_DELETE(ret);
+            return  NULL;
         }
         else if(strcmp(a_node_role, "master") == 0) {
             PVT(ret)->node_role.enums = MASTER;
@@ -160,6 +260,8 @@ dap_chain_net_t * dap_chain_net_new(const char * a_id, const char * a_name ,
         }
     } else {
         log_it (L_ERROR, "Wrong id format (\"%s\"). Must be like \"0x0123456789ABCDE\"" , a_id );
+        DAP_DELETE(ret);
+        return  NULL;
     }
     return ret;
 
@@ -192,25 +294,25 @@ int dap_chain_net_init()
                                             dap_config_get_item_str(l_cfg , "general" , "node-role" )
                                            );
         l_net->pub.gdb_groups_prefix = dap_strdup (
-                    dap_config_get_item_str_default(l_cfg , "dag" , "gdb_groups_prefix","" ) );
+                    dap_config_get_item_str_default(l_cfg , "general" , "gdb_groups_prefix","" ) );
 
 
         // UTXO model
         uint16_t l_utxo_flags = 0;
         switch ( PVT( l_net )->node_role.enums ) {
-            case ROOT_MASTER:
-            case ROOT:
-            case ARCHIVE:
+            case NODE_ROLE_ROOT_MASTER:
+            case NODE_ROLE_ROOT:
+            case NODE_ROLE_ARCHIVE:
                 l_utxo_flags |= DAP_CHAIN_UTXO_CHECK_TOKEN_EMISSION;
                 break;
-            case MASTER:
+            case NODE_ROLE_MASTER:
                 l_utxo_flags |= DAP_CHAIN_UTXO_CHECK_CELLS_DS;
                 break;
-            case CELL_MASTER:
+            case NODE_ROLE_CELL_MASTER:
                 l_utxo_flags |= DAP_CHAIN_UTXO_CHECK_TOKEN_EMISSION;
                 break;
-            case FULL:
-            case LIGHT:
+            case NODE_ROLE_FULL:
+            case NODE_ROLE_LIGHT:
                 l_utxo_flags |= DAP_CHAIN_UTXO_CHECK_LOCAL_DS;
                 break;
         }
@@ -254,21 +356,21 @@ int dap_chain_net_init()
 
         // Do specific role actions post-chain created
         switch ( PVT( l_net )->node_role.enums ) {
-            case ROOT_MASTER:{
+            case NODE_ROLE_ROOT_MASTER:{
                 // Set to process everything in datum pool
                 dap_chain_t * l_chain = NULL;
                 DL_FOREACH(l_net->pub.chains, l_chain ) l_chain->is_datum_pool_proc = true;
                 log_it(L_INFO,"Root master node role established");
             } break;
-            case ROOT:{
+            case NODE_ROLE_ROOT:{
                 // Set to process only zerochain
                 dap_chain_id_t l_chain_id = {{0}};
                 dap_chain_t * l_chain = dap_chain_find_by_id(l_net->pub.id,l_chain_id);
                 l_chain->is_datum_pool_proc = true;
                 log_it(L_INFO,"Root node role established");
             } break;
-            case CELL_MASTER:
-            case MASTER:{
+            case NODE_ROLE_CELL_MASTER:
+            case NODE_ROLE_MASTER:{
                 // Set to process only plasma chain (id 0x0000000000000001 )
                 dap_chain_id_t l_chain_id = { .raw = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x01} };
                 dap_chain_t * l_chain = dap_chain_find_by_id(l_net->pub.id, l_chain_id );
@@ -276,10 +378,10 @@ int dap_chain_net_init()
 
                 log_it(L_INFO,"Master node role established");
             } break;
-            case FULL:{
+            case NODE_ROLE_FULL:{
                 log_it(L_INFO,"Full node role established");
             } break;
-            case LIGHT:
+            case NODE_ROLE_LIGHT:
             default:
                 log_it(L_INFO,"Light node role established");
 
@@ -287,14 +389,19 @@ int dap_chain_net_init()
 
         // Add network to the list
         dap_chain_net_item_t * l_net_item = DAP_NEW_Z( dap_chain_net_item_t);
+        dap_chain_net_item_t * l_net_item2 = DAP_NEW_Z( dap_chain_net_item_t);
         snprintf(l_net_item->name,sizeof (l_net_item->name),"%s"
                      ,dap_config_get_item_str(l_cfg , "general" , "name" ));
         l_net_item->chain_net = l_net;
+        l_net_item->net_id.uint64 = l_net->pub.id.uint64;
         HASH_ADD_STR(s_net_items,name,l_net_item);
 
+        memcpy( l_net_item2,l_net_item,sizeof (*l_net_item));
+        HASH_ADD(hh,s_net_items_ids,net_id,sizeof ( l_net_item2->net_id),l_net_item2);
+
         // Start the proc thread
-        s_net_proc_start(l_net);
-        log_it(L_NOTICE, "Сhain network initialized");
+        s_net_proc_thread_start(l_net);
+        log_it(L_NOTICE, "Сhain network \"%s\" initialized",l_net_item->name);
         return 0;
     }
 }
@@ -307,30 +414,37 @@ void dap_chain_net_deinit()
 }
 
 /**
- * @brief dap_chain_net_load
+ * @brief dap_chain_net_by_name
  * @param a_name
  * @return
  */
-dap_chain_net_t * dap_chain_net_load (const char * a_name)
+dap_chain_net_t * dap_chain_net_by_name( const char * a_name)
 {
-
+    dap_chain_net_item_t * l_net_item = NULL;
+    HASH_FIND_STR(s_net_items,a_name,l_net_item );
+    if ( l_net_item )
+        return l_net_item->chain_net;
+    else
+        return NULL;
 }
 
 /**
- * @brief dap_chain_net_by_name
- * @param a_name
+ * @brief dap_chain_net_by_id
+ * @param a_id
  * @return
  */
-dap_chain_net_t * dap_chain_net_by_name( const char * a_name)
+dap_chain_net_t * dap_chain_net_by_id( dap_chain_net_id_t a_id)
 {
     dap_chain_net_item_t * l_net_item = NULL;
-    HASH_FIND_STR(s_net_items,a_name,l_net_item );
+    HASH_FIND(hh,s_net_items_ids,&a_id,sizeof (a_id), l_net_item );
     if ( l_net_item )
         return l_net_item->chain_net;
     else
         return NULL;
+
 }
 
+
 /**
  * @brief dap_chain_net_id_by_name
  * @param a_name
@@ -345,6 +459,23 @@ dap_chain_net_id_t dap_chain_net_id_by_name( const char * a_name)
     return l_ret;
 }
 
+/**
+ * @brief dap_chain_net_get_chain_by_name
+ * @param l_net
+ * @param a_name
+ * @return
+ */
+dap_chain_t * dap_chain_net_get_chain_by_name( dap_chain_net_t * l_net, const char * a_name)
+{
+   dap_chain_t * l_chain;
+   DL_FOREACH(l_net->pub.chains, l_chain){
+        if(strcmp(l_chain->name,a_name) == 0)
+            return  l_chain;
+   }
+   return NULL;
+}
+
+
 void dap_chain_net_proc_datapool (dap_chain_net_t * a_net)
 {
 
diff --git a/dap_chain_net.h b/dap_chain_net.h
old mode 100755
new mode 100644
index 948db479f9acbfe3ff686ac67cd4857623c4226e..276a09b08a0b73a7f49bade1f00a554b7846566e
--- a/dap_chain_net.h
+++ b/dap_chain_net.h
@@ -22,16 +22,27 @@
     along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
 */
 #pragma once
+#include <sys/socket.h>
+#include <netinet/in.h>
 
 #include <stdint.h>
+#include <string.h>
 #include "dap_chain_common.h"
 #include "dap_chain.h"
 
-#include <sys/socket.h>
-#include <netinet/in.h>
 
 #define DAP_CHAIN_NET_NAME_MAX 32
 
+typedef  enum dap_chain_net_state{
+    NET_STATE_BEGIN = 0,
+    NET_STATE_LINKS_CONNECTING,
+    NET_STATE_LINKS_ESTABLISHED,
+    NET_STATE_SYNC_GDB,
+    NET_STATE_SYNC_CHAINS,
+    NET_STATE_STAND_BY,
+} dap_chain_net_state_t;
+
+
 typedef struct dap_chain_net{
     struct {
         dap_chain_net_id_t id;
@@ -48,9 +59,38 @@ void dap_chain_net_deinit(void);
 dap_chain_net_t * dap_chain_net_new (const char * a_id,  const char * a_name,
                                      const char* a_node_role );
 
+int dap_chain_net_state_go_to(dap_chain_net_t * a_net, dap_chain_net_state_t a_new_state);
+
+inline static int dap_chain_net_start(dap_chain_net_t * a_net){ return dap_chain_net_state_go_to(a_net,NET_STATE_STAND_BY); }
+inline static int dap_chain_net_stop(dap_chain_net_t * a_net) { return dap_chain_net_state_go_to(a_net,NET_STATE_BEGIN); }
+inline static int dap_chain_net_links_establish(dap_chain_net_t * a_net) { return dap_chain_net_state_go_to(a_net,NET_STATE_LINKS_ESTABLISHED); }
 
 void dap_chain_net_delete( dap_chain_net_t * a_net);
 void dap_chain_net_proc_datapool (dap_chain_net_t * a_net);
 
 dap_chain_net_t * dap_chain_net_by_name( const char * a_name);
+dap_chain_net_t * dap_chain_net_by_id( dap_chain_net_id_t a_id);
 dap_chain_net_id_t dap_chain_net_id_by_name( const char * a_name);
+
+dap_chain_t * dap_chain_net_get_chain_by_name( dap_chain_net_t * l_net, const char * a_name);
+
+void dap_chain_net_links_connect(dap_chain_net_t * a_net);
+
+/**
+ * @brief dap_chain_net_get_gdb_group_mempool
+ * @param l_chain
+ * @return
+ */
+static inline char * dap_chain_net_get_gdb_group_mempool(dap_chain_t * l_chain)
+{
+    dap_chain_net_t * l_net = dap_chain_net_by_id(l_chain->net_id);
+    char * l_ret = NULL;
+    if ( l_net ) {
+        const char c_mempool_group_str[]="mempool";
+        size_t l_ret_size =  strlen( l_net->pub.gdb_groups_prefix ) + 1 +
+                strlen( l_chain->name)+1+strlen(c_mempool_group_str)+1;
+        l_ret = DAP_NEW_Z_SIZE(char, l_ret_size);
+        snprintf( l_ret,l_ret_size,"%s.%s.%s",l_net->pub.gdb_groups_prefix,l_chain->name,c_mempool_group_str);
+    }
+    return l_ret;
+}
diff --git a/dap_chain_node.c b/dap_chain_node.c
old mode 100755
new mode 100644
index b35dfd188571cfc48f5ada1248c87bf022789f76..f1cee2def4fb832c125acac598553646664d2a42
--- a/dap_chain_node.c
+++ b/dap_chain_node.c
@@ -26,6 +26,7 @@
 #include "dap_hash.h"
 #include "rand/dap_rand.h"
 #include "dap_chain_net.h"
+#include "dap_chain_global_db.h"
 #include "dap_chain_node.h"
 
 #define LOG_TAG "chain_node"
@@ -56,66 +57,40 @@ bool dap_chain_node_check_addr(dap_chain_node_addr_t *addr, dap_chain_cell_id_t
 {
     bool ret = false;
     if(!addr || !shard_id)
-        return ret;
-    // generate new address by shard_id
-    dap_chain_node_addr_t *tmp_addr = dap_chain_node_gen_addr(shard_id);
-    if(tmp_addr) {
-
-        if((uint32_t) addr->uint64 == (uint32_t) tmp_addr->uint64)
-            ret = true;
-        DAP_DELETE(tmp_addr);
-    }
+        ret= false;
+
     return ret;
 }
 
 /**
- * Convert binary data to binhex encoded data.
- *
- * out output buffer, must be twice the number of bytes to encode.
- * len is the size of the data in the in[] buffer to encode.
- * return the number of bytes encoded, or -1 on error.
+ * Register alias in base
  */
-int bin2hex0(char *out, const unsigned char *in, int len)
+bool dap_chain_node_alias_register(const char *alias, dap_chain_node_addr_t *addr)
 {
-    int ct = len;
-    static char hex[] = "0123456789ABCDEF";
-    if(!in || !out || len < 0)
-        return -1;
-    // hexadecimal lookup table
-    while(ct-- > 0)
-    {
-        *out++ = hex[*in >> 4];
-        *out++ = hex[*in++ & 0x0F];
-    }
-    return len;
+    const char *a_key = alias;
+//    char a_value[2 * sizeof(dap_chain_node_addr_t) + 1];
+//    if(bin2hex(a_value, (const unsigned char *) addr, sizeof(dap_chain_node_addr_t)) == -1)
+//        return false;
+//    a_value[2 * sizeof(dap_chain_node_addr_t)] = '\0';
+    bool res = dap_chain_global_db_gr_set(a_key, (const uint8_t*) addr, sizeof(dap_chain_node_addr_t), GROUP_ALIAS);
+    return res;
 }
 
 /**
- * Convert binhex encoded data to binary data
- *
- * len is the size of the data in the in[] buffer to decode, and must be even.
- * out outputbuffer must be at least half of "len" in size.
- * The buffers in[] and out[] can be the same to allow in-place decoding.
- * return the number of bytes encoded, or -1 on error.
+ * Delete alias from base
  */
-int hex2bin0(char *out, const unsigned char *in, int len)
+bool dap_chain_node_alias_delete(const char *alias)
 {
-    // '0'-'9' = 0x30-0x39
-    // 'a'-'f' = 0x61-0x66
-    // 'A'-'F' = 0x41-0x46
-    int ct = len;
-    if(!in || !out || len < 0 || (len & 1))
-        return -1;
-    while(ct > 0)
-    {
-        char ch1 = ((*in >= 'a') ? (*in++ - 'a' + 10) : ((*in >= 'A') ? (*in++ - 'A' + 10) : (*in++ - '0'))) << 4;
-        char ch2 = ((*in >= 'a') ? (*in++ - 'a' + 10) : ((*in >= 'A') ? (*in++ - 'A' + 10) : (*in++ - '0'))); // ((*in >= 'A') ? (*in++ - 'A' + 10) : (*in++ - '0'));
-        *out++ = ch1 + ch2;
-        ct -= 2;
-    }
-    return len;
+    const char *a_key = alias;
+    bool res = dap_chain_global_db_gr_del(a_key, GROUP_ALIAS);
+    return res;
 }
 
+
+
+
+
+
 /**
  * Calculate size of struct dap_chain_node_info_t
  */
@@ -126,6 +101,10 @@ size_t dap_chain_node_info_get_size(dap_chain_node_info_t *node_info)
     return (sizeof(dap_chain_node_info_t) + node_info->hdr.links_number * sizeof(dap_chain_node_addr_t));
 }
 
+
+
+
+
 /**
  * Serialize dap_chain_node_info_t
  * size[out] - length of output string
diff --git a/dap_chain_node.h b/dap_chain_node.h
old mode 100755
new mode 100644
index e9f41c01e205ee7baad63cbc1e1709bbc8473a09..6f73b44fb53baff9ec49f36be232f43892753ac9
--- a/dap_chain_node.h
+++ b/dap_chain_node.h
@@ -119,23 +119,8 @@ dap_chain_node_addr_t* dap_chain_node_gen_addr(dap_chain_cell_id_t *shard_id);
  */
 bool dap_chain_node_check_addr(dap_chain_node_addr_t *addr, dap_chain_cell_id_t *shard_id);
 
-/**
- * Convert binary data to binhex encoded data.
- *
- * out output buffer, must be twice the number of bytes to encode.
- * len is the size of the data in the in[] buffer to encode.
- * return the number of bytes encoded, or -1 on error.
- */
-int bin2hex(char *out, const unsigned char *in, int len);
 
-/**
- * Convert binhex encoded data to binary data
- *
- * len is the size of the data in the in[] buffer to decode, and must be even.
- * out outputbuffer must be at least half of "len" in size.
- * The buffers in[] and out[] can be the same to allow in-place decoding.
- * return the number of bytes encoded, or -1 on error.
- */
-int hex2bin(char *out, const unsigned char *in, int len);
+bool dap_chain_node_alias_register(const char *alias, dap_chain_node_addr_t *addr);
+bool dap_chain_node_alias_delete(const char *alias);
 
 
diff --git a/dap_chain_node_cli.c b/dap_chain_node_cli.c
old mode 100755
new mode 100644
index 5eb0cda81864a68809e6b7a9012092d73d6c48f3..9b84aefe79b4da04acf410e01e4d66be91f6ca82
--- a/dap_chain_node_cli.c
+++ b/dap_chain_node_cli.c
@@ -452,16 +452,16 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
     //server.sun_family = AF_UNIX;
     //strcpy(server.sun_path, SOCKET_FILE);
     dap_chain_node_cli_cmd_item_create ("global_db", com_global_db, "Work with global database",
-                                                   "global_db wallet_info set -addr <wallet address> -cell <cell id> \n\n"
-                                                   "global_db cells add -cell <cell id> \n\n"
-                                                   "global_db node add -addr {<node address> | -alias <node alias>} -cell <cell id>  {-ipv4 <ipv4 external address> | -ipv6 <ipv6 external address>}\n\n"
-                                                            "global_db node del -addr <node address> | -alias <node alias>\n\n"
-                                                            "global_db node link {add|del} {-addr <node address> | -alias <node alias>} -link <node address>\n\n"
-                                                            "global_db node dump\n\n"
-                                                            "global_db node dump -addr <node address> | -alias <node alias>\n\n"
-                                                            "global_db node get\n\n"
-                                                            "global_db node set -addr <node address> | -alias <node alias>\n\n"
-                                                  "global_db node remote_set -addr <node address> | -alias <node alias>\n");
+           "global_db wallet_info set -addr <wallet address> -cell <cell id> \n\n"
+           "global_db cells add -cell <cell id> \n\n"
+           "global_db node add  -net <net name> -addr {<node address> | -alias <node alias>} -cell <cell id>  {-ipv4 <ipv4 external address> | -ipv6 <ipv6 external address>}\n\n"
+                    "global_db node del  -net <net name> -addr <node address> | -alias <node alias>\n\n"
+                    "global_db node link {add|del}  -net <net name> {-addr <node address> | -alias <node alias>} -link <node address>\n\n"
+                    "global_db node dump  -net <net name>\n\n"
+                    "global_db node dump  -net <net name> -addr <node address> | -alias <node alias>\n\n"
+                    "global_db node get -net <net name>\n\n"
+                    "global_db node set -net <net name> -addr <node address> | -alias <node alias>\n\n"
+          "global_db node remote_set -addr <node address> | -alias <node alias>\n");
     dap_chain_node_cli_cmd_item_create ("node", com_node, "Work with node",
             "node alias {<node address> | -alias <node alias>}\n\n"
                     "node connect {<node address> | -alias <node alias>}\n\n"
@@ -482,8 +482,32 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
                                         );
     dap_chain_node_cli_cmd_item_create("wallet", com_tx_wallet, "Wallet operations",
             "wallet [new -w <wallet_name> | list | info -addr <addr> -w <wallet_name>]\n");
+
+    // Token commands
+    dap_chain_node_cli_cmd_item_create ("token_decl", com_token_decl, "Token declaration",
+            "token_decl -net <net name> -chain <chain name> token <token ticker> total_supply <total supply> sign_total <sign total> sign_valid <sign valid> certs <certs list>\n"
+            "\t Declare new token for <netname>:<chain name> with ticker <token ticker>, maximum emission <total supply> and <sign valid> from <sign total> signatures on valid emission\n"
+            "token_decl_sign -net <net name> -chain <chain name> datum <datum_hash>  certs <certs list>\n"
+            "\t Sign existent <datum hash> in mempool with <certs list>\n"
+            );
+
+    dap_chain_node_cli_cmd_item_create ("token_decl_sign", com_token_decl_sign, "Token declaration add sign",
+            "token_decl_sign -net <net name> -chain <chain name> datum <datum_hash>  certs <certs list>\n"
+            "\t Sign existent <datum hash> in mempool with <certs list>\n"
+            );
+
     dap_chain_node_cli_cmd_item_create ("token_emit", com_token_emit, "Token emission",
-            "token_emit addr <addr> tokent <token> certs <cert> emission_value <val>\n");
+            "token_emit -net <net name> -chain_emission <chain for emission> -chain_base_tx <chain for base tx> addr <addr> token <token ticker> certs <cert> emission_value <val>\n");
+
+    dap_chain_node_cli_cmd_item_create ("mempool_list", com_mempool_list, "List mempool entries for selected chain network and chain id",
+            "mempool_list -net <net name> -chain <chain name>\n");
+
+    dap_chain_node_cli_cmd_item_create ("mempool_proc", com_mempool_proc, "Proc mempool entries for selected chain network and chain id",
+            "mempool_list -net <net name> -chain <chain name>\n");
+
+
+
+    // Transaction commands
     dap_chain_node_cli_cmd_item_create ("tx_create", com_tx_create, "Make transaction",
             "tx_create from_wallet_name <name> to_addr <addr> token <token> value <val> [fee <addr> value_fee <val>]\n" );
     dap_chain_node_cli_cmd_item_create ("tx_cond_create", com_tx_cond_create, "Make cond transaction",
diff --git a/dap_chain_node_cli.h b/dap_chain_node_cli.h
old mode 100755
new mode 100644
diff --git a/dap_chain_node_cli_cmd.c b/dap_chain_node_cli_cmd.c
old mode 100755
new mode 100644
index d8c3f399f7cfb0bf2fbf76198b9a0b902b86f62a..cfaad25febe846c0d2965b8f39fc247509b62459
--- a/dap_chain_node_cli_cmd.c
+++ b/dap_chain_node_cli_cmd.c
@@ -22,17 +22,19 @@
  along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdbool.h>
 #include <errno.h>
 #include <assert.h>
-#include <glib.h>
 #include <time.h>
-#include <ctype.h> // for isspace()
-#include <arpa/inet.h>
-#include <netinet/in.h>
+#include <ctype.h>
+#include <dirent.h>
 
 #include "iputils/iputils.h"
 #include "dap_string.h"
@@ -61,56 +63,12 @@
 
 #define LOG_TAG "chain_node_cli_cmd"
 
-/**
- * Convert string to digit
- */
-static void digit_from_string(const char *num_str, uint8_t *raw, size_t raw_len)
-{
-    if(!num_str)
-        return;
-    uint64_t val;
-    if(!strncasecmp(num_str, "0x", 2)) {
-        val = strtoull(num_str + 2, NULL, 16);
-    }
-    else {
-        val = strtoull(num_str, NULL, 10);
-    }
-    // for LITTLE_ENDIAN (Intel), do nothing, otherwise swap bytes
-    val = le64toh(val);
-    memset(raw, 0, raw_len);
-    memcpy(raw, &val, min(raw_len, sizeof(uint64_t)));
-}
-
-/**
- * Add alias in base
- */
-static bool add_alias(const char *alias, dap_chain_node_addr_t *addr)
-{
-    const char *a_key = alias;
-//    char a_value[2 * sizeof(dap_chain_node_addr_t) + 1];
-//    if(bin2hex(a_value, (const unsigned char *) addr, sizeof(dap_chain_node_addr_t)) == -1)
-//        return false;
-//    a_value[2 * sizeof(dap_chain_node_addr_t)] = '\0';
-    bool res = dap_chain_global_db_gr_set(a_key, (const uint8_t*) addr, sizeof(dap_chain_node_addr_t), GROUP_ALIAS);
-    return res;
-}
-
-/**
- * Delete alias from base
- */
-static bool del_alias(const char *alias)
-{
-    const char *a_key = alias;
-    bool res = dap_chain_global_db_gr_del(a_key, GROUP_ALIAS);
-    return res;
-}
-
 /**
  * Find in base addr by alias
  *
  * return addr, NULL if not found
  */
-dap_chain_node_addr_t* get_name_by_alias(const char *a_alias)
+dap_chain_node_addr_t* dap_chain_node_addr_get_by_alias(const char *a_alias)
 {
     dap_chain_node_addr_t *l_addr = NULL;
     if(!a_alias)
@@ -173,7 +131,7 @@ static dap_chain_node_addr_t* com_global_db_get_addr(dap_chain_node_info_t *node
 {
     dap_chain_node_addr_t *address = NULL;
     if(alias_str && !addr->uint64) {
-        address = get_name_by_alias(alias_str);
+        address = dap_chain_node_addr_get_by_alias(alias_str);
     }
     if(addr->uint64) {
         address = DAP_NEW(dap_chain_node_addr_t);
@@ -285,7 +243,7 @@ static int com_global_db_add(dap_chain_node_info_t *node_info, const char *alias
      }*/
     if(alias_str) {
         // add alias
-        if(!add_alias(alias_str, &node_info->hdr.address)) {
+        if(!dap_chain_node_alias_register(alias_str, &node_info->hdr.address)) {
             log_it(L_WARNING, "can't save alias %s", alias_str);
             dap_chain_node_cli_set_reply_text(str_reply, "alias '%s' can't be mapped to addr=0x%lld",
                     alias_str, node_info->hdr.address.uint64);
@@ -342,10 +300,10 @@ static int com_global_db_del(dap_chain_node_info_t *node_info, const char *alias
                 while(list)
                 {
                     const char *alias = (const char *) list->data;
-                    del_alias(alias);
+                    dap_chain_node_alias_delete(alias);
                     list = dap_list_next(list);
                 }
-                dap_list_free_full(list_aliases, (DapDestroyNotify) free);
+                dap_list_free_full(list_aliases, (dap_callback_destroyed_t) free);
             }
             // set text response
             dap_chain_node_cli_set_reply_text(str_reply, "node deleted");
@@ -536,7 +494,7 @@ static int com_global_db_dump(dap_chain_node_info_t *a_node_info, const char *al
                 dap_string_append_printf(aliases_string, "\nalias %s", alias);
                 list = dap_list_next(list);
             }
-            dap_list_free_full(list_aliases, (DapDestroyNotify) free);
+            dap_list_free_full(list_aliases, (dap_callback_destroyed_t) free);
         }
         else
             dap_string_append(aliases_string, "\nno aliases");
@@ -796,13 +754,13 @@ int com_global_db(int argc, const char ** argv, char **str_reply)
     memset(&node_info, 0, sizeof(dap_chain_node_info_t));
     memset(&link, 0, sizeof(dap_chain_node_addr_t));
     if(addr_str) {
-        digit_from_string(addr_str, node_info.hdr.address.raw, sizeof(node_info.hdr.address.raw));
+        dap_digit_from_string(addr_str, node_info.hdr.address.raw, sizeof(node_info.hdr.address.raw));
     }
     if(cell_str) {
-        digit_from_string(cell_str, node_info.hdr.cell_id.raw, sizeof(node_info.hdr.cell_id.raw)); //DAP_CHAIN_CELL_ID_SIZE);
+        dap_digit_from_string(cell_str, node_info.hdr.cell_id.raw, sizeof(node_info.hdr.cell_id.raw)); //DAP_CHAIN_CELL_ID_SIZE);
     }
     if(link_str) {
-        digit_from_string(link_str, link.raw, sizeof(link.raw));
+        dap_digit_from_string(link_str, link.raw, sizeof(link.raw));
     }
 
     switch (cmd_num)
@@ -887,182 +845,195 @@ int com_node(int argc, const char ** argv, char **str_reply)
     dap_chain_node_addr_t address;
     memset(&address, 0, sizeof(dap_chain_node_addr_t));
     const char *addr_str = NULL, *alias_str = NULL;
+    const char * l_net_str = NULL;
 // find addr, alias
     dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-addr", &addr_str);
     dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-alias", &alias_str);
+    dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-net", &l_net_str);
+
+    dap_digit_from_string(addr_str, address.raw, sizeof(address.raw));
+
+    if( l_net_str == NULL){
+        dap_chain_node_cli_set_reply_text(str_reply, "No -net <net name> option in command %s", argv[1]);
+        return -11;
+    }
+
+    dap_chain_net_t * l_net = dap_chain_net_by_name(l_net_str);
 
-    digit_from_string(addr_str, address.raw, sizeof(address.raw));
+    if( l_net == NULL){
+        dap_chain_node_cli_set_reply_text(str_reply, "%s: Can't find such network %s", argv[1], l_net_str);
+        return -12;
+    }
 
     switch (cmd_num)
-    {
-    // add alias
-    case CMD_ALIAS:
-        if(alias_str) {
-            if(addr_str) {
-                // add alias
-                if(!add_alias(alias_str, &address))
-                    log_it(L_WARNING, "can't save alias %s", alias_str);
+        {
+        // add alias
+        case CMD_ALIAS:
+            if(alias_str) {
+                if(addr_str) {
+                    // add alias
+                    if(!dap_chain_node_alias_register(alias_str, &address))
+                        log_it(L_WARNING, "can't save alias %s", alias_str);
+                    else {
+                        dap_chain_node_cli_set_reply_text(str_reply, "alias mapped successfully");
+                    }
+                }
                 else {
-                    dap_chain_node_cli_set_reply_text(str_reply, "alias mapped successfully");
+                    dap_chain_node_cli_set_reply_text(str_reply, "alias can't be mapped because -addr is not found");
+                    return -1;
                 }
             }
             else {
-                dap_chain_node_cli_set_reply_text(str_reply, "alias can't be mapped because -addr is not found");
+                dap_chain_node_cli_set_reply_text(str_reply, "alias can't be mapped because -alias is not found");
                 return -1;
             }
-        }
-        else {
-            dap_chain_node_cli_set_reply_text(str_reply, "alias can't be mapped because -alias is not found");
-            return -1;
-        }
 
-        break;
-        // make connect
-    case CMD_CONNECT: {
-        // get address from alias if addr not defined
-        if(alias_str && !address.uint64) {
-            dap_chain_node_addr_t *address_tmp = get_name_by_alias(alias_str);
-            if(address_tmp) {
-                memcpy(&address, address_tmp, sizeof(address_tmp));
-                DAP_DELETE(address_tmp);
+            break;
+            // make connect
+        case CMD_CONNECT: {
+            // get address from alias if addr not defined
+            if(alias_str && !address.uint64) {
+                dap_chain_node_addr_t *address_tmp = dap_chain_node_addr_get_by_alias(alias_str);
+                if(address_tmp) {
+                    memcpy(&address, address_tmp, sizeof(address_tmp));
+                    DAP_DELETE(address_tmp);
+                }
+                else {
+                    dap_chain_node_cli_set_reply_text(str_reply, "no address found by alias");
+                    return -1;
+                }
             }
-            else {
-                dap_chain_node_cli_set_reply_text(str_reply, "no address found by alias");
+            if(!address.uint64) {
+                dap_chain_node_cli_set_reply_text(str_reply, "addr not found");
                 return -1;
             }
-        }
-        if(!address.uint64) {
-            dap_chain_node_cli_set_reply_text(str_reply, "addr not found");
-            return -1;
-        }
 
-        // get cur node addr
-        uint64_t l_cur_node_addr = dap_db_get_cur_node_addr(); //0x12345
-        if(!l_cur_node_addr) {
-            dap_chain_node_cli_set_reply_text(str_reply, "node has no address");
-            return -1;
-        }
+            // get cur node addr
+            uint64_t l_cur_node_addr = dap_db_get_cur_node_addr(); //0x12345
+            if(!l_cur_node_addr) {
+                dap_chain_node_cli_set_reply_text(str_reply, "node has no address");
+                return -1;
+            }
 
-        dap_chain_node_info_t *node_info = dap_chain_node_info_read(&address, str_reply);
-        if(!node_info) {
-            return -1;
-        }
-        // start connect
-        dap_chain_node_client_t *client = dap_chain_node_client_connect(node_info);
-        if(!client) {
-            dap_chain_node_cli_set_reply_text(str_reply, "can't connect");
-            DAP_DELETE(node_info);
-            return -1;
-        }
-        // wait connected
-        int timeout_ms = 15000; //15 sec = 15000 ms
-        int res = chain_node_client_wait(client, NODE_CLIENT_STATE_CONNECTED, timeout_ms);
-        if(res != 1) {
-            dap_chain_node_cli_set_reply_text(str_reply, "no response from node");
-            // clean client struct
-            dap_chain_node_client_close(client);
-            DAP_DELETE(node_info);
-            return -1;
-        }
+            dap_chain_node_info_t *node_info = dap_chain_node_info_read(&address, str_reply);
+            if(!node_info) {
+                return -1;
+            }
+            // start connect
+            dap_chain_node_client_t *client = dap_chain_node_client_connect(node_info);
+            if(!client) {
+                dap_chain_node_cli_set_reply_text(str_reply, "can't connect");
+                DAP_DELETE(node_info);
+                return -1;
+            }
+            // wait connected
+            int timeout_ms = 15000; //15 sec = 15000 ms
+            int res = chain_node_client_wait(client, NODE_CLIENT_STATE_CONNECTED, timeout_ms);
+            if(res != 1) {
+                dap_chain_node_cli_set_reply_text(str_reply, "no response from node");
+                // clean client struct
+                dap_chain_node_client_close(client);
+                DAP_DELETE(node_info);
+                return -1;
+            }
 
-        // send request
-        size_t l_data_size_out = 0;
-        // Get last timestamp in log
-        time_t l_timestamp_start = dap_db_log_get_last_timestamp();
-        size_t l_data_send_len = 0;
-        uint8_t *l_data_send = dap_stream_ch_chain_net_make_packet(l_cur_node_addr, node_info->hdr.address.uint64,
-                l_timestamp_start, NULL, 0, &l_data_send_len);
-
-        uint8_t l_ch_id = dap_stream_ch_chain_net_get_id(); // Channel id for global_db sync
-        res = dap_chain_node_client_send_chain_net_request(client, l_ch_id,
-        STREAM_CH_CHAIN_NET_PKT_TYPE_GLOBAL_DB_REQUEST_SYNC, l_data_send, l_data_send_len); //, NULL);
-        DAP_DELETE(l_data_send);
-        if(res != 1) {
-            dap_chain_node_cli_set_reply_text(str_reply, "no request sent");
-            // clean client struct
-            dap_chain_node_client_close(client);
+            // send request
+            size_t l_data_size_out = 0;
+            // Get last timestamp in log
+            time_t l_timestamp_start = dap_db_log_get_last_timestamp();
+            size_t l_data_send_len = 0;
+            uint8_t *l_data_send = dap_stream_ch_chain_net_make_packet(l_cur_node_addr, node_info->hdr.address.uint64,
+                    l_timestamp_start, NULL, 0, &l_data_send_len);
+
+            uint8_t l_ch_id = dap_stream_ch_chain_net_get_id(); // Channel id for global_db sync
+            res = dap_chain_node_client_send_chain_net_request(client, l_ch_id,
+                        STREAM_CH_CHAIN_NET_PKT_TYPE_GLOBAL_DB_REQUEST_SYNC, l_data_send, l_data_send_len); //, NULL);
+            DAP_DELETE(l_data_send);
+            if(res != 1) {
+                dap_chain_node_cli_set_reply_text(str_reply, "no request sent");
+                // clean client struct
+                dap_chain_node_client_close(client);
+                DAP_DELETE(node_info);
+                return -1;
+            }
+
+            // wait for finishing of request
+            timeout_ms = 120000; // 2 min = 120 sec = 120 000 ms
+            // TODO add progress info to console
+            res = chain_node_client_wait(client, NODE_CLIENT_STATE_END, timeout_ms);
             DAP_DELETE(node_info);
-            return -1;
-        }
+            dap_client_disconnect(client->client);
+            dap_chain_node_client_close(client);
+            switch (res) {
+            case 0:
+                dap_chain_node_cli_set_reply_text(str_reply, "timeout");
+                return -1;
+            case 1:
+                dap_chain_node_cli_set_reply_text(str_reply, "nodes sync completed");
+                return 0;
+            default:
+                dap_chain_node_cli_set_reply_text(str_reply, "error");
+                return -1;
+            }
 
-        // wait for finishing of request
-        timeout_ms = 120000; // 2 min = 120 sec = 120 000 ms
-        // TODO add progress info to console
-        res = chain_node_client_wait(client, NODE_CLIENT_STATE_END, timeout_ms);
-        DAP_DELETE(node_info);
-        dap_client_disconnect(client->client);
-        dap_chain_node_client_close(client);
-        switch (res) {
-        case 0:
-            dap_chain_node_cli_set_reply_text(str_reply, "timeout");
-            return -1;
-        case 1:
-            dap_chain_node_cli_set_reply_text(str_reply, "nodes sync completed");
-            return 0;
-        default:
-            dap_chain_node_cli_set_reply_text(str_reply, "error");
-            return -1;
         }
-
-    }
-        break;
-        // make handshake
-    case CMD_HANDSHAKE: {
-        // get address from alias if addr not defined
-        if(alias_str && !address.uint64) {
-            dap_chain_node_addr_t *address_tmp = get_name_by_alias(alias_str);
-            if(address_tmp) {
-                memcpy(&address, address_tmp, sizeof(address_tmp));
-                DAP_DELETE(address_tmp);
+            break;
+            // make handshake
+        case CMD_HANDSHAKE: {
+            // get address from alias if addr not defined
+            if(alias_str && !address.uint64) {
+                dap_chain_node_addr_t *address_tmp = dap_chain_node_addr_get_by_alias(alias_str);
+                if(address_tmp) {
+                    memcpy(&address, address_tmp, sizeof(address_tmp));
+                    DAP_DELETE(address_tmp);
+                }
+                else {
+                    dap_chain_node_cli_set_reply_text(str_reply, "no address found by alias");
+                    return -1;
+                }
             }
-            else {
-                dap_chain_node_cli_set_reply_text(str_reply, "no address found by alias");
+            if(!address.uint64) {
+                dap_chain_node_cli_set_reply_text(str_reply, "addr not found");
                 return -1;
             }
-        }
-        if(!address.uint64) {
-            dap_chain_node_cli_set_reply_text(str_reply, "addr not found");
-            return -1;
-        }
 
-        dap_chain_node_info_t *node_info = dap_chain_node_info_read(&address, str_reply);
-        if(!node_info)
-            return -1;
-        int timeout_ms = 10000; //10 sec = 10000 ms
-        // start handshake
-        dap_chain_node_client_t *client = dap_chain_node_client_connect(node_info);
-        if(!client) {
-            dap_chain_node_cli_set_reply_text(str_reply, "can't connect");
-            DAP_DELETE(node_info);
-            return -1;
-        }
-        // wait handshake
-        int res = chain_node_client_wait(client, NODE_CLIENT_STATE_CONNECTED, timeout_ms);
-        if(res != 1) {
-            dap_chain_node_cli_set_reply_text(str_reply, "no response from node");
-            // clean client struct
-            dap_chain_node_client_close(client);
+            dap_chain_node_info_t *node_info = dap_chain_node_info_read(&address, str_reply);
+            if(!node_info)
+                return -1;
+            int timeout_ms = 10000; //10 sec = 10000 ms
+            // start handshake
+            dap_chain_node_client_t *client = dap_chain_node_client_connect(node_info);
+            if(!client) {
+                dap_chain_node_cli_set_reply_text(str_reply, "can't connect");
+                DAP_DELETE(node_info);
+                return -1;
+            }
+            // wait handshake
+            int res = chain_node_client_wait(client, NODE_CLIENT_STATE_CONNECTED, timeout_ms);
+            if(res != 1) {
+                dap_chain_node_cli_set_reply_text(str_reply, "no response from node");
+                // clean client struct
+                dap_chain_node_client_close(client);
+                DAP_DELETE(node_info);
+                return -1;
+            }
             DAP_DELETE(node_info);
-            return -1;
-        }
-        DAP_DELETE(node_info);
 
-        //Add new established connection in the list
-        int ret = chain_node_client_list_add(&address, client);
-        switch (ret)
-        {
-        case -1:
-            dap_chain_node_client_close(client);
-            dap_chain_node_cli_set_reply_text(str_reply, "connection established, but not saved");
-            return -1;
-        case -2:
-            dap_chain_node_client_close(client);
-            dap_chain_node_cli_set_reply_text(str_reply, "connection already present");
-            return -1;
-        }
-        dap_chain_node_cli_set_reply_text(str_reply, "connection established");
-    }
-        break;
+            //Add new established connection in the list
+            int ret = dap_chain_node_client_list_add(&address, client);
+            switch (ret)
+            {
+            case -1:
+                dap_chain_node_client_close(client);
+                dap_chain_node_cli_set_reply_text(str_reply, "connection established, but not saved");
+                return -1;
+            case -2:
+                dap_chain_node_client_close(client);
+                dap_chain_node_cli_set_reply_text(str_reply, "connection already present");
+                return -1;
+            }
+            dap_chain_node_cli_set_reply_text(str_reply, "connection established");
+        } break;
     }
     return 0;
 }
@@ -1372,18 +1343,18 @@ int com_tx_wallet(int argc, const char ** argv, char **str_reply)
         break;
         // wallet list
     case CMD_WALLET_LIST: {
-        GDir *l_dir = g_dir_open(c_wallets_path, 0, NULL);
-        if(l_dir) {
-            const char *l_file = NULL;
-            do {
-                l_file = g_dir_read_name(l_dir);
-                int l_file_len = (l_file) ? strlen(l_file) : 0;
-                if(l_file_len > 8 && !g_strcmp0(l_file + l_file_len - 8, ".dwallet")) {
-                    char *l_file_path_tmp = dap_strdup_printf("%s/%s", c_wallets_path, l_file);
+        DIR * l_dir = opendir(c_wallets_path);
+        if( l_dir ) {
+            struct dirent * l_dir_entry;
+            while((l_dir_entry=readdir(l_dir))!=NULL){
+                const char *l_file_name = l_dir_entry->d_name;
+                size_t l_file_name_len = (l_file_name) ? strlen(l_file_name) : 0;
+                if( (l_file_name_len > 8 )&& ( strcmp(l_file_name + l_file_name_len - 8, ".dwallet") == 0 ) ) {
+                    char *l_file_path_tmp = dap_strdup_printf("%s/%s", c_wallets_path, l_file_name);
                     dap_chain_wallet_t *l_wallet = dap_chain_wallet_open_file(l_file_path_tmp);
                     if(l_wallet) {
-                        dap_chain_addr_t *l_addr = (dap_chain_addr_t *) dap_chain_wallet_get_addr(l_wallet);
-                        char *l_addr_str = dap_chain_addr_to_str((dap_chain_addr_t*) l_addr);
+                        dap_chain_addr_t *l_addr = dap_chain_wallet_get_addr(l_wallet);
+                        char *l_addr_str = dap_chain_addr_to_str(l_addr);
                         dap_string_append_printf(l_string_ret, "\nwallet: %s\n", l_wallet->name);
                         dap_string_append_printf(l_string_ret, "addr: %s\n", (l_addr_str) ? l_addr_str : "-");
                         DAP_DELETE(l_addr_str);
@@ -1392,8 +1363,7 @@ int com_tx_wallet(int argc, const char ** argv, char **str_reply)
                     DAP_DELETE(l_file_path_tmp);
                 }
             }
-            while(l_file);
-            g_dir_close(l_dir);
+            closedir(l_dir);
         }
     }
         break;
@@ -1453,6 +1423,466 @@ int com_tx_wallet(int argc, const char ** argv, char **str_reply)
     return 0;
 }
 
+/**
+ * @brief s_values_parse_net_chain
+ * @param argc
+ * @param argv
+ * @param str_reply
+ * @param l_chain
+ * @param l_net
+ * @return
+ */
+int s_values_parse_net_chain(int *a_arg_index,int argc, const char ** argv, char ** a_str_reply,
+                             dap_chain_t ** a_chain, dap_chain_net_t ** a_net)
+{
+    const char * l_chain_str = NULL;
+    const char * l_net_str = NULL;
+    // Net name
+    dap_chain_node_cli_find_option_val(argv, *a_arg_index, argc, "-net", &l_net_str);
+
+    // Chain name
+    dap_chain_node_cli_find_option_val(argv, *a_arg_index, argc, "-chain", &l_chain_str);
+
+    // Select chain network
+    if(!l_net_str) {
+        dap_chain_node_cli_set_reply_text(a_str_reply, "%s requires parameter 'net'",argv[0]);
+        return -42;
+    }else {
+        if ( ( *a_net  = dap_chain_net_by_name(l_net_str) ) == NULL ){ // Can't find such network
+            dap_chain_node_cli_set_reply_text(a_str_reply, "%s cand find network \"%s\"",argv[0],l_net_str);
+            return -43;
+        }
+    }
+
+    // Select chain
+    if(!l_chain_str) {
+        dap_chain_node_cli_set_reply_text(a_str_reply, "%s requires parameter 'chain'",argv[0]);
+        return -44;
+    }else {
+        if ( ( *a_chain  = dap_chain_net_get_chain_by_name(*a_net, l_chain_str ) ) == NULL ){ // Can't find such chain
+            dap_chain_node_cli_set_reply_text(a_str_reply, "%s requires parameter 'chain' to be valid chain name in chain net %s",
+                                              argv[0] , l_net_str);
+            return -45;
+        }
+    }
+    return  0;
+
+}
+
+/**
+ * @brief com_token_decl_sign
+ * @param argc
+ * @param argv
+ * @param str_reply
+ * @return
+ */
+int com_token_decl_sign(int argc, const char ** argv, char ** a_str_reply)
+{
+    int arg_index = 1;
+
+    const char * l_datum_hash_str = NULL;
+    // Chain name
+    dap_chain_node_cli_find_option_val(argv, arg_index, argc, "datum", &l_datum_hash_str);
+
+    if ( l_datum_hash_str ){
+        const char * l_certs_str = NULL;
+        dap_chain_cert_t ** l_certs = NULL;
+        size_t l_certs_size = 0;
+        dap_chain_t * l_chain;
+
+        dap_chain_net_t * l_net = NULL;
+
+        if ( s_values_parse_net_chain(&arg_index,argc,argv,a_str_reply,&l_chain, &l_net) < 0 )
+            return -1;
+
+        // Load certs lists
+        size_t l_signs_size = dap_chain_cert_parse_str_list(l_certs_str,&l_certs, &l_certs_size);
+        if(!l_certs_size) {
+            dap_chain_node_cli_set_reply_text(a_str_reply,
+                    "token_create command requres at least one valid certificate to sign the basic transaction of emission");
+            return -7;
+        }
+        size_t l_certs_count = l_certs_size / sizeof(dap_chain_cert_t *);
+
+        char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool(l_chain);
+
+        log_it (L_DEBUG, "Requested to sign token declaration %s in gdb://%s with certs %s",
+                l_gdb_group_mempool,l_datum_hash_str,                l_certs_str);
+
+        dap_chain_datum_t * l_datum = NULL;
+        size_t l_datum_size = 0;
+        if( (l_datum = (dap_chain_datum_t*) dap_chain_global_db_gr_get(
+                    l_datum_hash_str ,&l_datum_size,l_gdb_group_mempool )) != NULL ) {
+
+            // Check if its token declaration
+            if ( l_datum->header.type_id == DAP_CHAIN_DATUM_TOKEN_DECL ){
+                dap_chain_datum_token_t * l_datum_token = (dap_chain_datum_token_t *) l_datum->data;
+                size_t l_datum_token_size = l_datum->header.data_size;
+                size_t l_signs_size = l_datum_token_size - sizeof(l_datum_token->header);
+
+                // Check for signatures, are they all in set and are good enought?
+                size_t l_signs_count = 0;
+
+                for ( size_t l_offset = 0; l_offset < l_signs_size; l_signs_count++ ) {
+                    dap_chain_sign_t * l_sign = (dap_chain_sign_t *) l_datum_token->signs + l_offset;
+                    l_offset += dap_chain_sign_get_size(l_sign);
+                    if ( dap_chain_sign_verify(l_sign,&l_datum_token->header,sizeof (l_datum_token->header) ) != 1 ){
+                        log_it(L_WARNING,"Wrong signature for datum_token with key %s in mempool!",l_datum_hash_str );
+                        dap_chain_node_cli_set_reply_text(a_str_reply, "Datum %s with datum token has wrong signature %u, break process and exit",
+                                                          l_datum_hash_str, l_signs_count+1);
+                        DAP_DELETE(l_datum);
+                        DAP_DELETE(l_datum_token);
+                        DAP_DELETE(l_gdb_group_mempool);
+                        return -666;
+                    }
+                }
+                log_it( L_DEBUG,"Datum % with token declaration: %u signatures are verified well", l_signs_count);
+
+                // Check if all signs are present
+                if ( l_signs_count == l_datum_token->header.signs_total ){
+                    dap_chain_node_cli_set_reply_text(a_str_reply, "Datum %s with datum token has all signs on board. Can't add anything in it");
+                    DAP_DELETE(l_datum);
+                    DAP_DELETE(l_datum_token);
+                    DAP_DELETE(l_gdb_group_mempool);
+                    return -7;
+                } // Check if more signs that could be (corrupted datum)
+                else if ( l_signs_count > l_datum_token->header.signs_total ){
+                    dap_chain_node_cli_set_reply_text(a_str_reply, "Warning! Datum %s with datum token has more signs on board (%u) than its possible to have (%u)!",
+                                                      l_signs_count, l_datum_token->header.signs_total );
+                    DAP_DELETE(l_datum);
+                    DAP_DELETE(l_datum_token);
+                    DAP_DELETE(l_gdb_group_mempool);
+                    return -8;
+                } // Check if we have enough place to sign the datum token declaration
+                else if (  l_datum_token->header.signs_total - l_signs_count < l_certs_count ){
+                    l_datum = DAP_REALLOC(l_datum, l_datum_size+ l_signs_size ); // add place for new signatures
+                    size_t l_offset =  0;
+                    for ( size_t i = 0 ; i < l_certs_count ; i++ ){
+                        dap_chain_sign_t * l_sign = dap_chain_sign_create( l_certs[i]->enc_key,
+                                                                           &l_datum_token->header,
+                                                                           sizeof (l_datum_token->header), 0 );
+                        size_t l_sign_size = dap_chain_sign_get_size(l_sign);
+                        if ( l_offset + l_sign_size <= l_signs_size ){
+                            memcpy( l_datum_token->signs  + l_datum_token_size - sizeof (l_datum_token->header) + l_offset,
+                                l_sign,l_sign_size );
+                            log_it (L_DEBUG, "Added datum token declaration sign with cert %s", l_certs[i]->name);
+                        }
+
+                        DAP_DELETE( l_sign);
+                        l_offset += l_sign_size;
+                        if (l_offset > l_signs_size ){
+                            break;
+                        }
+                    }
+                    l_datum_size += l_signs_size;
+
+
+                    // Recalc hash, string and place new datum
+
+                    // Calc datum's hash
+                    dap_chain_hash_fast_t l_key_hash;
+                    dap_hash_fast(l_datum,l_datum_size, &l_key_hash);
+                    char * l_key_str = dap_chain_hash_fast_to_str_new(&l_key_hash);
+
+                    // Add datum to mempool with datum_token hash as a key
+                    if(dap_chain_global_db_gr_set(l_key_str, (uint8_t *) l_datum, l_datum_size,l_gdb_group_mempool )) {
+                        // Remove old datum from pool
+                        if (dap_chain_global_db_gr_del(l_datum_hash_str,l_gdb_group_mempool) ){
+                            dap_chain_node_cli_set_reply_text(a_str_reply, "datum %s produced from %s is replacing the %s in datum pool",
+                                                              l_key_str, l_datum_hash_str,l_datum_hash_str);
+
+                            DAP_DELETE(l_datum);
+                            DAP_DELETE(l_datum_token);
+                            DAP_DELETE(l_gdb_group_mempool);
+                            return  0;
+                        } else {
+                            dap_chain_node_cli_set_reply_text(a_str_reply, "Warning! Can't remove old datum %s ( new datum %s added normaly in datum pool)",
+                                                               l_datum_hash_str,l_key_str);
+                            DAP_DELETE(l_datum);
+                            DAP_DELETE(l_datum_token);
+                            DAP_DELETE(l_gdb_group_mempool);
+                            return 1;
+                        }
+
+                    }
+                    else{
+                        dap_chain_node_cli_set_reply_text(a_str_reply, "Error! datum %s produced from %s can't be placed in mempool",
+                                                          l_key_str, l_datum_hash_str);
+                        DAP_DELETE(l_datum);
+                        DAP_DELETE(l_datum_token);
+                        DAP_DELETE(l_gdb_group_mempool);
+                        return -2;
+                    }
+
+                } else {
+                    dap_chain_node_cli_set_reply_text(a_str_reply, "Error! Not enought place for new signature (%u is left when we need %u signatures)",
+                                                       l_datum_token->header.signs_total - l_signs_count, l_certs_count );
+                    return -6;
+                }
+            } else {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Error! Wrong datum type. token_decl_sign sign only token declarations datum");
+                return -61;
+            }
+        }else {
+            dap_chain_node_cli_set_reply_text(a_str_reply, "token_decl_sign can't find datum with %s hash in the mempool of %s:%s", l_net->pub.name,l_chain->name);
+            return -5;
+        }
+    }else {
+        dap_chain_node_cli_set_reply_text(a_str_reply, "token_decl_sign need datum <datum hash> argument");
+        return -2;
+    }
+}
+
+
+/**
+ * @brief com_token_decl_list
+ * @param argc
+ * @param argv
+ * @param str_reply
+ * @return
+ */
+int com_mempool_list(int argc, const char ** argv, char ** a_str_reply)
+{
+    int arg_index = 1;
+    dap_chain_t * l_chain;
+    dap_chain_net_t * l_net = NULL;
+
+    if (s_values_parse_net_chain(&arg_index,argc,argv,a_str_reply,&l_chain, &l_net) < 0)
+        return -1;
+
+    char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool(l_chain);
+    size_t l_objs_size = 0;
+    dap_global_db_obj_t ** l_objs = dap_chain_global_db_gr_load(l_gdb_group_mempool,&l_objs_size);
+    dap_string_t * l_str_tmp = dap_string_new(NULL);
+    dap_string_append_printf(l_str_tmp,"%s.%s: Found %u records :\n",l_net->pub.name,l_chain->name,l_objs_size);
+    for ( size_t i = 0; i< l_objs_size; i++){
+        dap_chain_datum_t * l_datum =(dap_chain_datum_t* ) l_objs[i]->value;
+        char buf[50];
+        time_t l_ts_create = (time_t) l_datum->header.ts_create;
+        dap_string_append_printf(l_str_tmp,"0x%s: type_id=%s ts_create=%s data_size=%u\n",
+                                 l_objs[i]->key, c_datum_type_str[l_datum->header.type_id],
+                                    ctime_r( &l_ts_create,buf ),l_datum->header.data_size );
+    }
+    dap_chain_global_db_objs_delete(l_objs);
+    dap_chain_node_cli_set_reply_text(a_str_reply, l_str_tmp->str);
+    dap_string_free(l_str_tmp,false);
+    return  0;
+}
+
+/**
+ * @brief com_mempool_proc
+ * @param argc
+ * @param argv
+ * @param a_str_reply
+ * @return
+ */
+int com_mempool_proc(int argc, const char ** argv, char ** a_str_reply)
+{
+    int arg_index = 1;
+    dap_chain_t * l_chain;
+    dap_chain_net_t * l_net = NULL;
+
+    if (s_values_parse_net_chain(&arg_index,argc,argv,a_str_reply,&l_chain, &l_net) < 0)
+        return -1;
+
+    char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool(l_chain);
+    size_t l_objs_size = 0;
+    dap_global_db_obj_t ** l_objs = dap_chain_global_db_gr_load(l_gdb_group_mempool,&l_objs_size);
+    dap_string_t * l_str_tmp = dap_string_new(NULL);
+    if ( l_objs_size ) {
+        dap_string_append_printf(l_str_tmp,"%s.%s: Found %u records :\n",l_net->pub.name,l_chain->name);
+
+
+        size_t l_datums_size = l_objs_size;
+        dap_chain_datum_t ** l_datums = DAP_NEW_Z_SIZE(dap_chain_datum_t*,sizeof(dap_chain_datum_t*)*l_datums_size);
+        for ( size_t i = 0; i< l_objs_size; i++){
+            dap_chain_datum_t * l_datum = (dap_chain_datum_t* ) l_objs[i]->value;
+            l_datums[i] = l_datum;
+            char buf[50];
+            time_t l_ts_create = (time_t) l_datum->header.ts_create;
+            dap_string_append_printf(l_str_tmp,"0x%s: type_id=%s ts_create=%s data_size=%u\n",
+                                     l_objs[i]->key, c_datum_type_str[l_datum->header.type_id],
+                                        ctime_r( &l_ts_create,buf ),l_datum->header.data_size );
+        }
+        size_t l_objs_processed = l_chain->callback_datums_pool_proc(l_chain,l_datums,l_datums_size);
+        // Delete processed objects
+        for ( size_t i = 0; i< l_objs_processed; i++){
+            dap_chain_global_db_gr_del(l_objs[i]->key,l_gdb_group_mempool);
+            dap_string_append_printf(l_str_tmp,"New event created, removed datum 0x%s from mempool \n",l_objs[i]->key);
+        }
+        dap_chain_global_db_objs_delete(l_objs);
+
+        dap_chain_node_cli_set_reply_text(a_str_reply, l_str_tmp->str);
+        dap_string_free(l_str_tmp,false);
+    }else {
+        dap_chain_node_cli_set_reply_text(a_str_reply, "%s.^s: No records in mempool",l_net->pub.name,l_chain->name);
+    }
+    return 0;
+}
+
+/**
+ * @brief com_token_decl
+ * @param argc
+ * @param argv
+ * @param str_reply
+ * @return
+ */
+int com_token_decl(int argc, const char ** argv, char ** str_reply)
+{
+    int arg_index = 1;
+    const char *str_tmp = NULL;
+    char *str_reply_tmp = NULL;
+    const char * l_ticker = NULL;
+
+    const char * l_total_supply_str = NULL;
+    uint64_t l_total_supply = 0;
+
+    const char * l_signs_emission_str = NULL;
+    uint16_t l_signs_emission = 0;
+
+    const char * l_signs_total_str = NULL;
+    uint16_t l_signs_total = 0;
+
+
+    const char * l_certs_str = NULL;
+
+    dap_chain_cert_t ** l_certs = NULL;
+    size_t l_certs_size = 0;
+
+    dap_chain_t * l_chain;
+    dap_chain_net_t * l_net = NULL;
+
+    if (s_values_parse_net_chain(&arg_index,argc,argv,str_reply,&l_chain, &l_net) < 0)
+        return -1;
+
+
+
+    // Total supply value
+    dap_chain_node_cli_find_option_val(argv, arg_index, argc, "total_supply", &l_total_supply_str);
+
+    // Token ticker
+    dap_chain_node_cli_find_option_val(argv, arg_index, argc, "token", &l_ticker);
+
+
+    // Certificates thats will be used to sign currend datum token
+    dap_chain_node_cli_find_option_val(argv, arg_index, argc, "certs", &l_certs_str);
+
+    // Signs number thats own emissioncan't find
+    dap_chain_node_cli_find_option_val(argv, arg_index, argc, "signs_total", &l_signs_total_str);
+
+    // Signs minimum number thats need to authorize the emission
+    dap_chain_node_cli_find_option_val(argv, arg_index, argc, "signs_emission", &l_signs_emission_str);
+
+    if(!l_total_supply_str) {
+        dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter 'total_supply'");
+        return -11;
+    }else {
+        char * l_tmp = NULL;
+        if ( ( l_total_supply = strtoull(l_total_supply_str,&l_tmp,10) ) == 0 ){
+            dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter 'total_supply' to be unsigned integer value that fits in 8 bytes");
+            return -2;
+        }
+    }
+
+    // Signs emission
+    if(!l_signs_emission_str) {
+        dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter 'signs_emission'");
+        return -3;
+    }else {
+        char * l_tmp = NULL;
+        if ( ( l_signs_emission  =(uint16_t)  strtol(l_signs_emission_str,&l_tmp,10) ) == 0 ){
+            dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter 'signs_emission' to be unsigned integer value that fits in 2 bytes");
+            return -4;
+        }
+    }
+
+    // Signs total
+    if(!l_signs_total_str) {
+        dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter 'signs_total'");
+        return -31;
+    }else {
+        char * l_tmp = NULL;
+        if ( ( l_signs_total  =(uint16_t)  strtol(l_signs_total_str,&l_tmp,10) ) == 0 ){
+            dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter 'signs_total' to be unsigned integer value that fits in 2 bytes");
+            return -41;
+        }
+    }
+
+
+    // Check for ticker
+    if(!l_ticker) {
+        dap_chain_node_cli_set_reply_text(str_reply, "token_emit requires parameter 'token'");
+        return -5;
+    }
+
+
+    // Check certs list
+    if(!l_certs_str) {
+        dap_chain_node_cli_set_reply_text(str_reply, "token_emit requires parameter 'certs'");
+        return -6;
+    }
+
+    // Load certs lists
+    size_t l_signs_size = dap_chain_cert_parse_str_list(l_certs_str,&l_certs, &l_certs_size);
+    if(!l_certs_size) {
+        dap_chain_node_cli_set_reply_text(str_reply,
+                "token_create command requres at least one valid certificate to sign the basic transaction of emission");
+        return -7;
+    }
+
+    // If we have more certs than we need signs - use only first part of the list
+    if (l_certs_size > l_signs_total )
+        l_certs_size = l_signs_total;
+
+    // Create new datum token
+    dap_chain_datum_token_t * l_datum_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t,sizeof(l_datum_token->header) +
+                                                             l_signs_size);
+    l_datum_token->header.version = 1; // Current version
+    snprintf(l_datum_token->header.ticker,sizeof(l_datum_token->header.ticker),"%s",l_ticker);
+    l_datum_token->header.total_supply = l_total_supply;
+    l_datum_token->header.signs_total = l_signs_total;
+    l_datum_token->header.signs_valid = l_signs_emission;
+
+    size_t l_signs_offset = 0;
+    // Sign header with all certificates in the list and add signs to the end of ticker declaration
+    // Important:
+    for ( size_t i = 0 ; i < l_certs_size; i++ ){
+        dap_chain_sign_t * l_sign = dap_chain_cert_sign( l_certs[i],
+                                                         l_datum_token,
+                                                         sizeof(l_datum_token->header),
+                                                         0);
+        size_t l_sign_size = dap_chain_sign_get_size(l_sign);
+        memcpy(l_datum_token->signs+l_signs_offset,l_sign,l_sign_size);
+        DAP_DELETE(l_sign);
+    }
+    dap_chain_datum_t * l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_TOKEN_DECL,l_datum_token,
+                                                         sizeof (l_datum_token->header)+ l_signs_size);
+    size_t l_datum_size = dap_chain_datum_size(l_datum);
+
+    // Calc datum's hash
+    dap_chain_hash_fast_t l_key_hash;
+    dap_hash_fast(l_datum,l_datum_size, &l_key_hash);
+    char * l_key_str = dap_chain_hash_fast_to_str_new(&l_key_hash);
+
+    // Add datum to mempool with datum_token hash as a key
+    char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool(l_chain);
+    if(dap_chain_global_db_gr_set(l_key_str, (uint8_t *) l_datum, l_datum_size,l_gdb_group_mempool )) {
+        dap_chain_node_cli_set_reply_text(str_reply, "%s\ndatum %s with token %s is placed in datum pool ", str_reply_tmp, l_key_str,l_ticker);
+        DAP_DELETE(l_datum);
+        DAP_DELETE(l_datum_token);
+        DAP_DELETE(l_gdb_group_mempool);
+        return  0;
+    }
+    else{
+        dap_chain_node_cli_set_reply_text(str_reply, "%s\ndatum tx %s is not placed in datum pool ", str_reply_tmp, l_key_str);
+        DAP_DELETE(l_datum);
+        DAP_DELETE(l_datum_token);
+        DAP_DELETE(l_gdb_group_mempool);
+        return -2;
+    }
+
+}
+
 /**
  * @brief com_token_emit
  * @param argc
@@ -1476,6 +1906,13 @@ int com_token_emit(int argc, const char ** argv, char ** str_reply)
     dap_chain_cert_t ** l_certs = NULL;
     size_t l_certs_count = 0;
 
+    const char * l_chain_str = NULL;
+    dap_chain_t * l_chain;
+
+    const char * l_net_str = NULL;
+    dap_chain_net_t * l_net = NULL;
+
+
     // Wallet address that recieves the emission
     dap_chain_node_cli_find_option_val(argv, arg_index, argc, "certs", &l_certs_str);
 
@@ -1501,7 +1938,7 @@ int com_token_emit(int argc, const char ** argv, char ** str_reply)
     }
 
     if(!l_ticker) {
-        dap_chain_node_cli_set_reply_text(str_reply, "token_emit requires parameter 'tokent'");
+        dap_chain_node_cli_set_reply_text(str_reply, "token_emit requires parameter 'token'");
         return -3;
     }
 
@@ -1510,41 +1947,8 @@ int com_token_emit(int argc, const char ** argv, char ** str_reply)
         return -4;
     }
 
-    int n = 0;
-    char * l_certs_tmp_ptrs = NULL;
-    char * l_certs_str_dup = strdup(l_certs_str);
-    char *l_cert_str = strtok_r(l_certs_str_dup, ",", &l_certs_tmp_ptrs);
-
-    // First we just calc items
-    while(l_cert_str) {
-        l_cert_str = strtok_r(NULL, ",", &l_certs_tmp_ptrs);
-        l_certs_count++;
-    }
-    // init certs array
-    l_certs = DAP_NEW_Z_SIZE(dap_chain_cert_t*, l_certs_count * sizeof(dap_chain_cert_t));
-
-    // Second pass we parse them all
-    strcpy(l_certs_str_dup, l_certs_str);
-    l_cert_str = strtok_r(l_certs_str_dup, ",", &l_certs_tmp_ptrs);
-
-    size_t l_certs_pos = 0;
-    while(l_cert_str) {
-
-        // trim token whitespace
-        if(isspace(l_cert_str[0]))
-            l_cert_str = l_cert_str + 1;
-        if(isspace(l_cert_str[strlen(l_cert_str) - 1]))
-            l_cert_str[strlen(l_cert_str) - 1] = 0;
-        l_certs[l_certs_pos] = dap_chain_cert_find_by_name(l_cert_str);
-        if(l_certs[l_certs_pos]) {
-            l_certs_pos++;
-        } else {
-            dap_chain_node_cli_set_reply_text(str_reply, "Error: can't find %s certificate", l_cert_str);
-            return -6;
-        }
-        l_cert_str = strtok_r(NULL, ",", &l_certs_tmp_ptrs);
-    }
-    free(l_certs_str_dup);
+    // Load certs
+    dap_chain_cert_parse_str_list(l_certs_str,&l_certs,&l_certs_size);
 
     if(!l_certs_count) {
         dap_chain_node_cli_set_reply_text(str_reply,
@@ -1552,6 +1956,7 @@ int com_token_emit(int argc, const char ** argv, char ** str_reply)
         return -5;
     }
 
+
     dap_chain_addr_t * l_addr = dap_chain_str_to_addr(l_addr_str);
 
     if(!l_addr) {
@@ -1559,6 +1964,33 @@ int com_token_emit(int argc, const char ** argv, char ** str_reply)
         return -4;
     }
 
+
+    // Select chain network
+    if(!l_net_str) {
+        dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter 'net'");
+        return -42;
+    }else {
+        if ( ( l_net  = dap_chain_net_by_name(l_net_str) ) == NULL ){ // Can't find such network
+            dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter 'net' to be valid chain network name");
+            return -43;
+        }
+    }
+
+    // Select chain
+    if(!l_chain_str) {
+        dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter 'chain'");
+        return -44;
+    }else {
+        if ( ( l_chain  = dap_chain_net_get_chain_by_name(l_net, l_chain_str ) ) == NULL ){ // Can't find such chain
+            dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter 'chain' to be valid chain name in chain net %s",l_net_str);
+            return -45;
+        }
+    }
+
+    // Get mempool group for this chain
+    char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool(l_chain);
+
+
     // Create emission datum
     dap_chain_datum_token_emission_t * l_token_emission;
     dap_chain_hash_fast_t l_token_emission_hash;
@@ -1579,7 +2011,7 @@ int com_token_emit(int argc, const char ** argv, char ** str_reply)
 
     // Add to mempool emission token
     if(dap_chain_global_db_gr_set(l_key_str, (uint8_t *) l_datum_emission, l_datum_emission_size
-            , dap_config_get_item_str_default(g_config, "mempool", "gdb_group", "datum-pool"))) {
+            , l_gdb_group_mempool)) {
         str_reply_tmp = dap_strdup_printf("datum emission %s is placed in datum pool ", l_key_str);
     }
     else {
@@ -1623,15 +2055,17 @@ int com_token_emit(int argc, const char ** argv, char ** str_reply)
     size_t l_datum_tx_size = dap_chain_datum_size(l_datum_tx);
 
     // use l_tx hash for compatible with utho hash
-    dap_hash_fast(l_tx, l_tx_size, &l_key_hash); //dap_hash_fast(l_datum_tx, l_datum_tx_size, &l_key_hash);
+    //dap_hash_fast(l_tx, l_tx_size, &l_key_hash); //dap_hash_fast(l_datum_tx, l_datum_tx_size, &l_key_hash);
+    // calc datum hash
+    dap_hash_fast(l_datum_tx, l_datum_tx_size, &l_key_hash);
     l_key_str = dap_chain_hash_fast_to_str_new(&l_key_hash);
     DAP_DELETE(l_tx);
 
-    // Add to mempool emission token
+
+    // Add to mempool tx token
     if(dap_chain_global_db_gr_set(l_key_str, (uint8_t *) l_datum_tx, l_datum_tx_size
-            , dap_config_get_item_str_default(g_config, "mempool", "gdb_group", "datum-pool"))) {
-        dap_chain_node_cli_set_reply_text(str_reply, "%s\ndatum tx %s is placed in datum pool ", str_reply_tmp,
-                l_key_str);
+            , l_gdb_group_mempool)) {
+        dap_chain_node_cli_set_reply_text(str_reply, "%s\ndatum tx %s is placed in datum pool ", str_reply_tmp, l_key_str);
         dap_chain_utxo_tx_add((dap_chain_datum_tx_t*) l_datum_tx->data);
     }
     else {
diff --git a/dap_chain_node_cli_cmd.h b/dap_chain_node_cli_cmd.h
old mode 100755
new mode 100644
index 2c8692aab3fda12d5c4d72d63bc51253fba924a8..3428ccb42aa6d3c2fb740fa744a795d72687e29c
--- a/dap_chain_node_cli_cmd.h
+++ b/dap_chain_node_cli_cmd.h
@@ -32,7 +32,7 @@
  *
  * return addr, NULL if not found
  */
-dap_chain_node_addr_t* get_name_by_alias(const char *alias);
+dap_chain_node_addr_t* dap_chain_node_addr_get_by_alias(const char *alias);
 
 
 
@@ -73,8 +73,19 @@ int com_ping(int argc, const char** argv, char **str_reply);
 int com_help(int argc, const char ** argv, char **str_reply);
 
 
-int com_token_declare ( int argc, const char ** argv, char ** str_reply);
+/**
+ * Token declaration
+ */
+int com_token_decl ( int argc, const char ** argv, char ** str_reply);
+
+/**
+ * Token declaration add sign
+ */
+int com_token_decl_sign ( int argc, const char ** argv, char ** str_reply);
 
+/**
+ * Token emission
+ */
 int com_token_emit (int argc, const char ** argv, char ** str_reply);
 
 
@@ -99,3 +110,6 @@ int com_tx_cond_create(int argc, const char ** argv, char **str_reply);
  * Verifing transaction
  */
 int com_tx_verify(int argc, const char ** argv, char **str_reply);
+
+int com_mempool_list(int argc, const char ** argv, char ** a_str_reply);
+int com_mempool_proc(int argc, const char ** argv, char ** a_str_reply);
diff --git a/dap_chain_node_client.c b/dap_chain_node_client.c
old mode 100755
new mode 100644
diff --git a/dap_chain_node_client.h b/dap_chain_node_client.h
old mode 100755
new mode 100644
diff --git a/dap_chain_node_remote.c b/dap_chain_node_remote.c
old mode 100755
new mode 100644
index f3dccdc2f4df3fb5b10f327cfadd8b1344d824db..be119272751f27f5a7cf2cadc868371b8c80c872
--- a/dap_chain_node_remote.c
+++ b/dap_chain_node_remote.c
@@ -28,14 +28,14 @@
 #include "dap_common.h"
 #include "dap_chain_node_remote.h"
 
-typedef struct dap_chain_utxo_tx_item {
+typedef struct dap_chain_node_link_item {
     dap_chain_node_addr_t address;
     dap_chain_node_client_t *client;
     UT_hash_handle hh;
-} list_linked_item_t;
+} dap_chain_node_link_item_t;
 
 // List of connections
-static list_linked_item_t *conn_list = NULL;
+static dap_chain_node_link_item_t *conn_list = NULL;
 
 // for separate access to connect_list
 static pthread_mutex_t connect_list_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -46,16 +46,16 @@ static pthread_mutex_t connect_list_mutex = PTHREAD_MUTEX_INITIALIZER;
  *
  * return 0 OK, -1 error, -2 already present
  */
-int chain_node_client_list_add(dap_chain_node_addr_t *a_address, dap_chain_node_client_t *a_client)
+int dap_chain_node_client_list_add(dap_chain_node_addr_t *a_address, dap_chain_node_client_t *a_client)
 {
     int l_ret = 0;
     if(!a_address || !a_client)
         return -1;
-    list_linked_item_t *item_tmp = NULL;
+    dap_chain_node_link_item_t *item_tmp = NULL;
     pthread_mutex_lock(&connect_list_mutex);
     HASH_FIND(hh, conn_list, a_address, sizeof(dap_chain_node_addr_t), item_tmp); // address already in the hash?
     if(item_tmp == NULL) {
-        item_tmp = DAP_NEW(list_linked_item_t);
+        item_tmp = DAP_NEW(dap_chain_node_link_item_t);
         item_tmp->address.uint64 = a_address->uint64;
         item_tmp->client = a_client;
         HASH_ADD(hh, conn_list, address, sizeof(dap_chain_node_addr_t), item_tmp); // address: name of key field
@@ -79,7 +79,7 @@ int chain_node_client_list_del(dap_chain_node_addr_t *address)
     int ret = -1;
     if(!address)
         return -1;
-    list_linked_item_t *item_tmp;
+    dap_chain_node_link_item_t *item_tmp;
     pthread_mutex_lock(&connect_list_mutex);
     HASH_FIND(hh, conn_list, address, sizeof(dap_chain_node_addr_t), item_tmp);
     if(item_tmp != NULL) {
@@ -105,7 +105,7 @@ int chain_node_client_list_del(dap_chain_node_addr_t *address)
 void chain_node_client_list_del_all(void)
 {
     int ret = -1;
-    list_linked_item_t *iter_current, *item_tmp;
+    dap_chain_node_link_item_t *iter_current, *item_tmp;
     pthread_mutex_lock(&connect_list_mutex);
     HASH_ITER(hh, conn_list , iter_current, item_tmp) {
         // close connection
@@ -127,7 +127,7 @@ const dap_chain_node_client_t* chain_node_client_find(dap_chain_node_addr_t *add
     if(!address)
         return NULL;
     dap_chain_node_client_t *client_ret = NULL;
-    list_linked_item_t *item_tmp;
+    dap_chain_node_link_item_t *item_tmp;
     pthread_mutex_lock(&connect_list_mutex);
     HASH_FIND(hh, conn_list, address, sizeof(dap_chain_node_addr_t), item_tmp); // address already in the hash?
     if(item_tmp != NULL) {
diff --git a/dap_chain_node_remote.h b/dap_chain_node_remote.h
old mode 100755
new mode 100644
index ca175db0d008490f1c57dc5d5487c3039f6ce72a..ce8aedc93262ac6e2a2bf67cb27529d78726d50c
--- a/dap_chain_node_remote.h
+++ b/dap_chain_node_remote.h
@@ -31,7 +31,7 @@
  *
  * return 0 OK, -1 error, -2 already present
  */
-int chain_node_client_list_add(dap_chain_node_addr_t *address, dap_chain_node_client_t *client);
+int dap_chain_node_client_list_add(dap_chain_node_addr_t *address, dap_chain_node_client_t *client);
 
 /**
  * Delete established connection from the list
diff --git a/iputils/iputils.c b/iputils/iputils.c
old mode 100755
new mode 100644
index 07184747f198fcc2a5024374ee46b49de0fc731a..7d73d1a085a7ed2686740c4eb5f84e35b843a65b
--- a/iputils/iputils.c
+++ b/iputils/iputils.c
@@ -4,7 +4,6 @@
 
 #include <stdio.h>
 #include <stdbool.h>
-//#include <glib.h>
 #include "dap_common.h"
 #include "dap_strfuncs.h"
 
diff --git a/iputils/iputils.h b/iputils/iputils.h
old mode 100755
new mode 100644
diff --git a/iputils/ping.c b/iputils/ping.c
old mode 100755
new mode 100644
index 98a62dc4df95a0d2f5d2719a46d61203dd80a6f2..f9f65beada8ac7afb58535a9357037d5e0648521
--- a/iputils/ping.c
+++ b/iputils/ping.c
@@ -56,7 +56,6 @@
 #include <netinet/ip_icmp.h>
 #include <ifaddrs.h>
 #include <math.h>
-//#include <glib.h>
 #include "dap_common.h"
 #include "dap_strfuncs.h"
 
diff --git a/iputils/ping.h b/iputils/ping.h
old mode 100755
new mode 100644
diff --git a/iputils/ping6_common.c b/iputils/ping6_common.c
old mode 100755
new mode 100644
diff --git a/iputils/ping_common.c b/iputils/ping_common.c
old mode 100755
new mode 100644
diff --git a/iputils/tracepath.c b/iputils/tracepath.c
old mode 100755
new mode 100644
diff --git a/iputils/traceroute/as_lookups.c b/iputils/traceroute/as_lookups.c
old mode 100755
new mode 100644
diff --git a/iputils/traceroute/clif.c b/iputils/traceroute/clif.c
old mode 100755
new mode 100644
diff --git a/iputils/traceroute/clif.h b/iputils/traceroute/clif.h
old mode 100755
new mode 100644
diff --git a/iputils/traceroute/csum.c b/iputils/traceroute/csum.c
old mode 100755
new mode 100644
diff --git a/iputils/traceroute/extension.c b/iputils/traceroute/extension.c
old mode 100755
new mode 100644
diff --git a/iputils/traceroute/flowlabel.h b/iputils/traceroute/flowlabel.h
old mode 100755
new mode 100644
diff --git a/iputils/traceroute/mod-dccp.c b/iputils/traceroute/mod-dccp.c
old mode 100755
new mode 100644
diff --git a/iputils/traceroute/mod-icmp.c b/iputils/traceroute/mod-icmp.c
old mode 100755
new mode 100644
diff --git a/iputils/traceroute/mod-raw.c b/iputils/traceroute/mod-raw.c
old mode 100755
new mode 100644
diff --git a/iputils/traceroute/mod-tcp.c b/iputils/traceroute/mod-tcp.c
old mode 100755
new mode 100644
diff --git a/iputils/traceroute/mod-tcpconn.c b/iputils/traceroute/mod-tcpconn.c
old mode 100755
new mode 100644
diff --git a/iputils/traceroute/mod-udp.c b/iputils/traceroute/mod-udp.c
old mode 100755
new mode 100644
diff --git a/iputils/traceroute/module.c b/iputils/traceroute/module.c
old mode 100755
new mode 100644
diff --git a/iputils/traceroute/poll.c b/iputils/traceroute/poll.c
old mode 100755
new mode 100644
diff --git a/iputils/traceroute/random.c b/iputils/traceroute/random.c
old mode 100755
new mode 100644
diff --git a/iputils/traceroute/time.c b/iputils/traceroute/time.c
old mode 100755
new mode 100644
diff --git a/iputils/traceroute/traceroute.c b/iputils/traceroute/traceroute.c
old mode 100755
new mode 100644
diff --git a/iputils/traceroute/traceroute.h b/iputils/traceroute/traceroute.h
old mode 100755
new mode 100644