diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0c004d8990799addb100c55defdfca7735539d57..9f39fae0270e87948077680944c78f7bbf23fa2a 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -33,7 +33,7 @@ add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_NET_SRCS} ${DAP_CHAIN_NET_HEADERS
 find_package(PkgConfig REQUIRED)
 pkg_search_module(GLIB REQUIRED glib-2.0)
 
-target_link_libraries(dap_chain_net dap_core dap_crypto dap_chain dap_chain_crypto dap_chain_mempool dap_chain_global_db -lresolv ${GLIB_LDFLAGS})
+target_link_libraries(dap_chain_net dap_core dap_crypto dap_chain dap_chain_crypto dap_chain_wallet dap_chain_mempool dap_chain_global_db -lresolv ${GLIB_LDFLAGS})
 target_include_directories(dap_chain_net INTERFACE . PUBLIC ${GLIB_INCLUDE_DIRS} ${IPUTILS_INCLUDE_DIRS})
 
 set(${PROJECT_NAME}_DEFINITIONS CACHE INTERNAL "${PROJECT_NAME}: Definitions" FORCE)
diff --git a/dap_chain_net.c b/dap_chain_net.c
index 5f2f6c9131fc24e790ea987fd149fd607e5adb2a..b359346e9ce5b4e2ba1ba34728bd33afa63779fd 100644
--- a/dap_chain_net.c
+++ b/dap_chain_net.c
@@ -221,7 +221,8 @@ int dap_chain_net_init()
 
                         // Create chain object
                         dap_chain_t * l_chain = dap_chain_load_from_cfg(l_net->pub.name,l_entry_name);
-                        DL_APPEND( l_net->pub.chains, l_chain);
+                        if(l_chain)
+                            DL_APPEND( l_net->pub.chains, l_chain);
                         free(l_entry_name);
                     }
                 }
diff --git a/dap_chain_node_cli.c b/dap_chain_node_cli.c
index 6f267f06a62ca13448b1ad759d7b16d605352848..bb446f11c43028f685375fe8e81f26f69c3aa6ae 100644
--- a/dap_chain_node_cli.c
+++ b/dap_chain_node_cli.c
@@ -58,16 +58,30 @@ typedef int SOCKET;
 
 static SOCKET server_sockfd = -1;
 
-static const COMMAND commands[] = {
-    { "global_db", com_global_db, "Work with database" },
-    { "node", com_node, "Work with node" },
-    { "ping", com_ping, "Ping utility" },
-    { "traceroute", com_traceroute, "Traceroute utility" },
-    { "tracepath", com_tracepath, "Tracepath utility" },
-    { "help", com_help, "Display this text" },
-    { "?", com_help, "Synonym for `help'" },
-    { (char *) NULL, (cmdfunc_t *) NULL, (char *) NULL }
-};
+static const COMMAND commands[] =
+        {
+            { "global_db", com_global_db, "Work with global database",
+                "global_db node add -addr {<node address> | -alias <node alias>} -shard <shard id>  {-ipv4 <ipv4 external address> | -ipv6 <ipv6 external address>}\n"
+                        "global_db node del -addr <node address> | -alias <node alias>\n"
+                        "global_db node link {add|del} {-addr <node address> | -alias <node alias>} -link <node address>\n"
+                        "global_db node dump -addr <node address> | -alias <node alias>" },
+            { "node", com_node, "Work with node",
+                "node alias {<node address> | -alias <node alias>}\n"
+                        "node handshake {<node address> | -alias <node alias>}" },
+            { "ping", com_ping, "Send ICMP ECHO_REQUEST to network hosts",
+                "ping [-c <count>] host" },
+            { "traceroute", com_traceroute, "Print the hops and time of packets trace to network host",
+                "traceroute host" },
+            { "tracepath", com_tracepath, "Traces path to a network host along this path",
+                "tracepath host" },
+            { "help", com_help, "Description of command parameters", "" },
+            { "?", com_help, "Synonym for 'help'", "" },
+            { "tx_create", com_tx_create, "Signing transaction",
+                "tx_create -wallet <wallet name> [-path <wallet path>]" },
+            { "tx_verify", com_tx_verify, "Verifing transaction",
+                "tx_verify  -wallet <wallet name> [-path <wallet path>]" },
+            { (char *) NULL, (cmdfunc_t *) NULL, (char *) NULL }
+        };
 
 /**
  *  Look up NAME as the name of a command, and return a pointer to that
@@ -296,6 +310,8 @@ static void* thread_one_client_func(void *args)
                 // execute command
                 char *str_cmd = g_strdup_printf("%s", cmd_name);
                 const COMMAND *command = find_command(cmd_name);
+                int res = -1;
+                char *str_reply = NULL;
                 if(command)
                 {
                     while(list) {
@@ -304,26 +320,27 @@ static void* thread_one_client_func(void *args)
                     }
                     log_it(L_INFO, "execute command=%s", str_cmd);
                     // exec command
-                    int res = 0;
+
                     char **argv = g_strsplit(str_cmd, ";", -1);
-                    char *str_reply = NULL;
                     // Call the command function
                     if(command && command->func)
                         res = (*(command->func))(argc, (const char **) argv, &str_reply);
                     g_strfreev(argv);
-                    gchar *reply_body = g_strdup_printf("%d\r\n%s\r\n", res, (str_reply) ? str_reply : "");
-                    // return the result of the command function
-                    gchar *reply_str = g_strdup_printf("HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s",
-                            strlen(reply_body), reply_body);
-                    int ret = send(newsockfd, reply_str, strlen(reply_str), 1000);
-                    g_free(str_reply);
-                    g_free(reply_str);
-                    g_free(reply_body);
                 }
                 else
                 {
-                    log_it(L_ERROR, "can't recognize command=%s", str_cmd);
+                    str_reply = g_strdup_printf("can't recognize command=%s", str_cmd);
+                    log_it(L_ERROR, str_reply);
                 }
+                gchar *reply_body = g_strdup_printf("%d\r\n%s\r\n", res, (str_reply) ? str_reply : "");
+                // return the result of the command function
+                gchar *reply_str = g_strdup_printf("HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s",
+                        strlen(reply_body), reply_body);
+                int ret = send(newsockfd, reply_str, strlen(reply_str), 1000);
+                g_free(str_reply);
+                g_free(reply_str);
+                g_free(reply_body);
+
                 g_free(str_cmd);
             }
             g_list_free_full(cmd_param_list, free);
diff --git a/dap_chain_node_cli.h b/dap_chain_node_cli.h
index a449082ab5334abe11773d0d54fc90fdd4e7d287..37875ba60ed56c1bcceb49681808f64b17b0a6ac 100644
--- a/dap_chain_node_cli.h
+++ b/dap_chain_node_cli.h
@@ -34,6 +34,7 @@ typedef struct {
     char *name; /* User printable name of the function. */
     cmdfunc_t *func; /* Function to call to do the job. */
     char *doc; /* Documentation for this function.  */
+    char *doc_ex; /* Full documentation for this function.  */
 } COMMAND;
 
 /**
diff --git a/dap_chain_node_cli_cmd.c b/dap_chain_node_cli_cmd.c
index eddac8d1615a4626ce208a8e4a1c483d24c6a998..457c25e4935dda64f11a3fd03f705f44823d31c4 100644
--- a/dap_chain_node_cli_cmd.c
+++ b/dap_chain_node_cli_cmd.c
@@ -26,17 +26,28 @@
 #include <errno.h>
 #include <assert.h>
 #include <glib.h>
+#include <time.h>
 #include <arpa/inet.h>
 #include <netinet/in.h>
 
 #include "iputils/iputils.h"
 //#include "dap_common.h"
+#include "dap_hash.h"
+#include "dap_chain_common.h"
+#include "dap_chain_wallet.h"
 #include "dap_chain_node.h"
 #include "dap_chain_global_db.h"
 #include "dap_chain_node_client.h"
 #include "dap_chain_node_remote.h"
 #include "dap_chain_node_cli_cmd.h"
 
+#include "dap_chain_datum.h"
+#include "dap_chain_datum_tx_in.h"
+#include "dap_chain_datum_tx_out.h"
+#include "dap_chain_datum_tx_pkey.h"
+#include "dap_chain_datum_tx_sig.h"
+#include "dap_chain_datum_tx_cache.h"
+
 // Max and min macros
 #define max(a,b)              ((a) > (b) ? (a) : (b))
 #define min(a,b)              ((a) < (b) ? (a) : (b))
@@ -124,7 +135,7 @@ static bool del_alias(const char *alias)
  *
  * return addr, NULL if not found
  */
-static dap_chain_node_addr_t* get_name_by_alias(const char *alias)
+dap_chain_node_addr_t* get_name_by_alias(const char *alias)
 {
     dap_chain_node_addr_t *addr = NULL;
     if(!alias)
@@ -638,7 +649,7 @@ int com_global_db(int argc, const char ** argv, char **str_reply)
             return com_global_db_link(&node_info, "del", alias_str, &link, str_reply);
         else {
             set_reply_text(str_reply, "command not recognize, supported format:\n"
-                    "global_db node link [add|del] [-addr <node address>  | -alias <node alias>] -link <node address>");
+                    "global_db node link <add|del] [-addr <node address>  | -alias <node alias>] -link <node address>");
             return -1;
         }
         break;
@@ -733,7 +744,7 @@ int com_node(int argc, const char ** argv, char **str_reply)
         if(!node_info) {
             return -1;
         }
-        int timeout_ms = 100000; //100 sec.
+        int timeout_ms = 10000; //10 sec.
         // start handshake
         dap_chain_node_client_t *client = dap_chain_node_client_connect(node_info);
         if(!client) {
@@ -753,8 +764,18 @@ int com_node(int argc, const char ** argv, char **str_reply)
         DAP_DELETE(node_info);
 
         //Add new established connection in the list
-        chain_node_client_list_add(client);
-
+        int ret = chain_node_client_list_add(&address, client);
+        switch (ret)
+        {
+        case -1:
+            dap_chain_node_client_close(client);
+            set_reply_text(str_reply, "connection established, but not saved");
+            return -1;
+        case -2:
+            dap_chain_node_client_close(client);
+            set_reply_text(str_reply, "connection already present");
+            return -1;
+        }
         set_reply_text(str_reply, "connection established");
         break;
     }
@@ -943,6 +964,147 @@ int com_ping(int argc, const char** argv, char **str_reply)
  * Help command
  */
 int com_help(int argc, const char ** argv, char **str_reply)
+{
+    if(argc > 1) {
+        const COMMAND *cmd = find_command(argv[1]);
+        if(cmd)
+        {
+            set_reply_text(str_reply, "%s:\n%s", cmd->doc, cmd->doc_ex);
+            return 1;
+        }
+        set_reply_text(str_reply, "command \"%s\" not recognized", argv[1]);
+        return -1;
+    }
+    else {
+        // TODO Read list of commands & return it
+    }
+    if(str_reply)
+        set_reply_text(str_reply, "command not defined, enter \"help <cmd name>\"");
+    return -1;
+}
+
+dap_chain_datum_tx_t* create_tx(const char *net_name)
+{
+    dap_chain_tx_in_t tx_in;
+    dap_chain_tx_in_t tx_out;
+
+    tx_in.header.type = TX_ITEM_TYPE_IN;
+    //tx_in.header.sig_size = 0;
+    //tx_in
+
+    dap_chain_datum_tx_t *tx = DAP_NEW_Z(dap_chain_datum_tx_t);
+    tx->header.lock_time = time(NULL);
+    int res = dap_chain_datum_tx_add_item(&tx, (const uint8_t*) &tx_in);
+    //dap_chain_tx_in_t
+
+    //dap_chain_hash_t a_hash_fast;
+    //dap_hash((char*) tx, sizeof(tx), a_hash_fast.raw, sizeof(a_hash_fast.raw), DAP_HASH_TYPE_KECCAK);
+
+    /*
+     // create file with dap_chain_t
+     dap_chain_id_t a_chain_id = {0x1};
+     dap_chain_net_id_t a_chain_net_id = {0x2};
+     dap_chain_shard_id_t a_shard_id = {0x3};
+
+     dap_chain_t *a_chain = dap_chain_create(a_chain_net_id, a_chain_id, a_shard_id);
+     const char * a_chain_net_name = "0x1";
+     const char * a_chain_cfg_name = "chain-0";
+     dap_chain_t *ch2 =  dap_chain_load_from_cfg(a_chain_net_name, a_chain_cfg_name);
+
+     //dap_chain_net_t *l_net = dap_chain_net_by_name(net_name);
+     //dap_chain_id_t *chain = l_net->pub.chains;
+     */
+    return tx;
+}
+
+/**
+ * com_tx_create command
+ *
+ * Signing transaction
+ */
+int com_tx_create(int argc, const char ** argv, char **str_reply)
+{
+    // create wallet
+    const char *a_wallets_path = "/opt/kelvin-node/etc";
+    const char *a_wallet_name = "w1";
+    dap_chain_net_id_t a_net_id = { 0x1 };
+    dap_chain_sign_type_t a_sig_type = { SIG_TYPE_TESLA };
+    //dap_chain_sign_type_t a_sig_type = { SIG_TYPE_PICNIC };
+    //dap_chain_sign_type_t a_sig_type = { SIG_TYPE_BLISS };
+    dap_chain_wallet_t *wallet = dap_chain_wallet_create(a_wallet_name, a_wallets_path, a_net_id, a_sig_type);
+    dap_chain_wallet_t *wallet2 = dap_chain_wallet_open(a_wallet_name, a_wallets_path);
+    //wallet = dap_chain_wallet_open(a_wallet_name, a_wallets_path);
+    //dap_chain_wallet_save(wallet2);
+    dap_chain_datum_tx_t *tx = create_tx("0x123");
+
+    static bool l_first_start = true;
+    if(l_first_start)
+    {
+        const char *l_token_name = "KLVN";
+        dap_enc_key_t *l_key = dap_chain_wallet_get_key(wallet, 0);
+        const dap_chain_addr_t *l_addr = dap_chain_wallet_get_addr(wallet);
+        dap_chain_node_datum_tx_cache_init(l_key, l_token_name, (dap_chain_addr_t*)l_addr, 1000);
+        l_first_start = false;
+    }
+
+    const dap_chain_addr_t *addr = dap_chain_wallet_get_addr(wallet);
+
+    char *addr_str = dap_chain_addr_to_str((dap_chain_addr_t*)addr);
+    const dap_chain_addr_t *addr2 = dap_chain_str_to_addr(addr_str);
+    char *addr_str2 = dap_chain_addr_to_str(addr2);
+    free(addr_str);
+
+    // debug - check signing
+    {
+        int a_data_size = 50;
+        char *a_data = "DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify";
+
+
+        dap_enc_key_t *a_key0 = dap_enc_key_new_generate(DAP_ENC_KEY_TYPE_SIG_BLISS, NULL, 0, NULL, 0, 0);
+
+        dap_enc_key_t *a_key1 = dap_chain_wallet_get_key(wallet, 0);
+        dap_enc_key_t *a_key2 = dap_chain_wallet_get_key(wallet2, 0);
+        dap_chain_sign_t *a_chain_sign0 = dap_chain_sign_create(a_key0, a_data, a_data_size, 0);
+        dap_chain_sign_t *a_chain_sign1 = dap_chain_sign_create(a_key1, a_data, a_data_size, 0);
+        dap_chain_sign_t *a_chain_sign2 = dap_chain_sign_create(a_key2, a_data, a_data_size, 0);
+        size_t a_chain_sign_size = dap_chain_sign_get_size(a_chain_sign1);
+        int verify0 = dap_chain_sign_verify(a_chain_sign0, a_data, a_data_size);
+        int verify1 = dap_chain_sign_verify(a_chain_sign1, a_data, a_data_size);
+        int verify2 = dap_chain_sign_verify(a_chain_sign2, a_data, a_data_size);
+        printf("a_chain_sign=%d verify=%d %d %d\n", a_chain_sign_size, verify0, verify1, verify2);
+        free(a_chain_sign2);
+        free(a_chain_sign1);
+        free(a_chain_sign0);
+        //dap_enc_key_delete(a_key2);
+        dap_enc_key_delete(a_key0);
+        //dap_enc_key_delete(a_key1);
+    }
+
+    if(wallet) {
+        if(dap_chain_wallet_get_certs_number(wallet) > 0) {
+            dap_chain_pkey_t *pk0 = dap_chain_wallet_get_pkey(wallet, 0);
+            dap_enc_key_t *a_key = dap_chain_wallet_get_key(wallet, 0);
+            //dap_enc_key_t *a_key1 = dap_chain_wallet_get_key(wallet, 0);
+            //dap_enc_key_t *a_key2 = dap_chain_wallet_get_key(wallet2, 0);
+            int res = dap_chain_datum_tx_add_sign(&tx, a_key);
+            int res1 = dap_chain_datum_tx_add_sign(&tx, a_key);
+            int res2 = dap_chain_datum_tx_add_sign(&tx, a_key);
+            int res3 = dap_chain_datum_tx_verify_sign(tx);
+            res3 = 0;
+        }
+        dap_chain_wallet_close(wallet);
+        DAP_DELETE(tx);
+    }
+    set_reply_text(str_reply, "com_tx_create ok");
+    return 0;
+}
+
+/**
+ * tx_verify command
+ *
+ * Verifing transaction
+ */
+int com_tx_verify(int argc, const char ** argv, char **str_reply)
 {
     if(argc > 1) {
         const COMMAND *cmd = find_command(argv[1]);
@@ -959,4 +1121,3 @@ int com_help(int argc, const char ** argv, char **str_reply)
         set_reply_text(str_reply, "command not defined, enter \"help <cmd name>\"");
     return -1;
 }
-
diff --git a/dap_chain_node_cli_cmd.h b/dap_chain_node_cli_cmd.h
index c27e7ec822ac0cfbc3a6af0ef9f727196720f735..61f9e4484e0700b846c583238b64ac625a994e09 100644
--- a/dap_chain_node_cli_cmd.h
+++ b/dap_chain_node_cli_cmd.h
@@ -21,8 +21,16 @@
 
 #pragma once
 
+#include "dap_chain_node.h"
 #include "dap_chain_node_cli.h"
 
+/**
+ * Find in base addr by alias
+ *
+ * return addr, NULL if not found
+ */
+dap_chain_node_addr_t* get_name_by_alias(const char *alias);
+
 /**
  *  Look up NAME as the name of a command, and return a pointer to that
  *  command.  Return a NULL pointer if NAME isn't a command name.
@@ -64,3 +72,17 @@ int com_ping(int argc, const char** argv, char **str_reply);
  * Help command
  */
 int com_help(int argc, const char ** argv, char **str_reply);
+
+/**
+ * com_tx_create command
+ *
+ * Signing transaction
+ */
+int com_tx_create(int argc, const char ** argv, char **str_reply);
+
+/**
+ * tx_verify command
+ *
+ * Verifing transaction
+ */
+int com_tx_verify(int argc, const char ** argv, char **str_reply);
diff --git a/dap_chain_node_remote.c b/dap_chain_node_remote.c
index 9ba16a39893c26a2a7afe4174b629d8830041f95..4c923e3a4f9db93cd355cf75ed11747ff9bb8cdb 100644
--- a/dap_chain_node_remote.c
+++ b/dap_chain_node_remote.c
@@ -22,69 +22,117 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
-#include <glib.h>
 #include <pthread.h>
 
+#include "uthash.h"
+#include "dap_common.h"
 #include "dap_chain_node_remote.h"
 
+typedef struct list_linked_item {
+    dap_chain_node_addr_t address;
+    dap_chain_node_client_t *client;
+    UT_hash_handle hh;
+} list_linked_item_t;
 
 // List of connections
-static GList *connect_list = NULL;
+static list_linked_item_t *conn_list = NULL;
 
 // for separate access to connect_list
 static pthread_mutex_t connect_list_mutex = PTHREAD_MUTEX_INITIALIZER;
 
+
 /**
- * Add new established connection in the list
+ * Add new established connection to the list
+ *
+ * return 0 OK, -1 error, -2 already present
  */
-bool chain_node_client_list_add(dap_chain_node_client_t *client)
+int chain_node_client_list_add(dap_chain_node_addr_t *a_address, dap_chain_node_client_t *a_client)
 {
-    if(!client)
-        return false;
+    int l_ret = 0;
+    if(!a_address || !a_client)
+        return -1;
+    list_linked_item_t *item_tmp = NULL;
     pthread_mutex_lock(&connect_list_mutex);
-    connect_list = g_list_append(connect_list, client);
+    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->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
+        l_ret = 0;
+    }
+    // connection already present
+    else
+        l_ret = -2;
+    //connect_list = g_list_append(connect_list, client);
     pthread_mutex_unlock(&connect_list_mutex);
-    return true;
+    return l_ret;
 }
 
 /**
  * Delete established connection from the list
+ *
+ * return 0 OK, -1 error, -2 address not found
  */
-bool chain_node_client_list_del(dap_chain_node_client_t *client)
+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;
     pthread_mutex_lock(&connect_list_mutex);
-    GList *list = g_list_find(connect_list, client);
-    // found
-    if(list)
-        connect_list = g_list_remove(connect_list, client);
+    HASH_FIND(hh, conn_list, address, sizeof(dap_chain_node_addr_t), item_tmp);
+    if(item_tmp != NULL) {
+        HASH_DEL(conn_list, item_tmp);
+        ret = 0;
+    }
+    else
+        // address not found in the hash
+        ret = -2;
     pthread_mutex_unlock(&connect_list_mutex);
-    if(list)
-        return true;
-    return false;
+    if(!ret) {
+        // close connection
+        dap_chain_node_client_close(item_tmp->client);
+        // del struct for hash
+        DAP_DELETE(item_tmp);
+    }
+    return ret;
 }
 
 /**
- * Get one established connection
- *
- * n - the position of the established connection, counting from 0
- *
- * return client, or NULL if the position is off the end of the list
+ * Delete all established connection from the list
  */
-dap_chain_node_client_t* chain_node_client_list_get_item(int n)
+void chain_node_client_list_del_all(void)
 {
+    int ret = -1;
+    list_linked_item_t *iter_current, *item_tmp;
     pthread_mutex_lock(&connect_list_mutex);
-    dap_chain_node_client_t *client = g_list_nth_data(connect_list, (guint) n);
+    HASH_ITER(hh, conn_list , iter_current, item_tmp) {
+        // close connection
+        dap_chain_node_client_close(iter_current->client);
+        // del struct for hash
+        HASH_DEL(conn_list, iter_current);
+    }
     pthread_mutex_unlock(&connect_list_mutex);
-    return client;
 }
+
 /**
- * Get the number of established connections
+ * Get present established connection by address
+ *
+ * return client, or NULL if the connection not found in the list
  */
-int chain_node_client_list_count(void)
+const dap_chain_node_client_t* chain_node_client_find(dap_chain_node_addr_t *address)
 {
+    int ret = 0;
+    if(!address)
+        return NULL;
+    dap_chain_node_client_t *client_ret = NULL;
+    list_linked_item_t *item_tmp;
     pthread_mutex_lock(&connect_list_mutex);
-    int len = g_list_length(connect_list);
+    HASH_FIND(hh, conn_list, address, sizeof(dap_chain_node_addr_t), item_tmp); // address already in the hash?
+    if(item_tmp != NULL) {
+        client_ret = item_tmp->client;
+    }
     pthread_mutex_unlock(&connect_list_mutex);
-    return len;
+    return client_ret;
 }
-
diff --git a/dap_chain_node_remote.h b/dap_chain_node_remote.h
index 0ce1cfdb528e863fb0f0ede875d996af0629b215..ca175db0d008490f1c57dc5d5487c3039f6ce72a 100644
--- a/dap_chain_node_remote.h
+++ b/dap_chain_node_remote.h
@@ -23,28 +23,31 @@
 
 #include <stdbool.h>
 
+#include "dap_chain_node.h"
 #include "dap_chain_node_client.h"
 
 /**
- * Add new established connection in the list
+ * Add new established connection to the list
+ *
+ * return 0 OK, -1 error, -2 already present
  */
-bool chain_node_client_list_add(dap_chain_node_client_t *client);
+int chain_node_client_list_add(dap_chain_node_addr_t *address, dap_chain_node_client_t *client);
 
 /**
  * Delete established connection from the list
+ *
+ * return 0 OK, -1 error, -2 address not found
  */
-bool chain_node_client_list_del(dap_chain_node_client_t *client);
+int chain_node_client_list_del(dap_chain_node_addr_t *address);
 
 /**
- * Get one established connection
- *
- * n - the position of the established connection, counting from 0
- *
- * return client, or NULL if the position is off the end of the list
+ * Delete all established connection from the list
  */
-dap_chain_node_client_t* chain_node_client_list_get_item(int n);
+void chain_node_client_list_del_all(void);
 
 /**
- * Get the number of established connections
+ * Get present established connection by address
+ *
+ * return client, or NULL if the connection not found in the list
  */
-int chain_node_client_list_count(void);
+const dap_chain_node_client_t* chain_node_client_find(dap_chain_node_addr_t *address);