diff --git a/dap-sdk/core/include/dap_math_ops.h b/dap-sdk/core/include/dap_math_ops.h
index 7f6002d30685697a2ede56d96f2b434a2584dad2..5a8e8feeb3f7ad97788c53f93856b25b24b82fc4 100755
--- a/dap-sdk/core/include/dap_math_ops.h
+++ b/dap-sdk/core/include/dap_math_ops.h
@@ -14,6 +14,8 @@ typedef __int128 int128_t;
 #endif
 #if !defined (uint128_t)
 typedef unsigned __int128 uint128_t;
+#else
+typedef unsigned uint64_t[2] uint128_t;
 #endif
 #endif
 #endif
diff --git a/dap-sdk/core/include/dap_strfuncs.h b/dap-sdk/core/include/dap_strfuncs.h
index a50775d36763a1cc49a4a41fc2694dfad682ec75..ea2f6c20bc7b6566b4158121402b3ea414c9a352 100755
--- a/dap-sdk/core/include/dap_strfuncs.h
+++ b/dap-sdk/core/include/dap_strfuncs.h
@@ -12,6 +12,8 @@
 #include <time.h>
 #include <string.h>
 
+#include "dap_math_ops.h"
+
 #define dap_return_if_fail(expr)            {if(!(expr)) {return;}}
 #define dap_return_val_if_fail(expr,val)    {if(!(expr)) {return (val);}}
 
@@ -73,6 +75,35 @@ char* dap_strup(const char *a_str, ssize_t a_len);
 char* dap_strdown(const char *a_str, ssize_t a_len);
 char* dap_strreverse(char *a_string);
 
+#ifdef DAP_GLOBAL_IS_INT128
+uint128_t dap_strtou128(const char *p, char **endp, int base);
+int128_t dap_strtoi128(const char *p, char **endp, int base);
+
+/**
+ * @brief atoi128
+ * @param p
+ * @return
+ */
+static inline int128_t dap_atoi128(const char *p) {
+    return dap_strtoi128(p, (char**)NULL, 10);
+}
+
+
+/**
+ * @brief atou128
+ * @param p
+ * @return
+ */
+static inline uint128_t dap_atou128(const char *p) {
+    return dap_strtou128(p, (char**)NULL, 10);
+}
+
+char *dap_utoa128(char *dest, uint128_t v, int base);
+char *dap_itoa128(char *a_str, int128_t a_value, int a_base);
+
+#endif
+
+
 #ifdef _WIN32
 #ifdef HAVE_STRNDUP
 #define strndup(s, l) _strndup(s, l)
diff --git a/dap-sdk/core/include/dap_string.h b/dap-sdk/core/include/dap_string.h
index 7275f9db7599d6a24a8615c2cb75c18471dbb44f..65196c2a7e85ea622cf28927b001fceddf59993c 100755
--- a/dap-sdk/core/include/dap_string.h
+++ b/dap-sdk/core/include/dap_string.h
@@ -26,6 +26,7 @@ bool dap_string_equal(const dap_string_t *v, const dap_string_t *v2);
 
 unsigned int dap_string_hash(const dap_string_t *str);
 
+
 dap_string_t* dap_string_assign(dap_string_t *string, const char *rval);
 
 dap_string_t* dap_string_truncate(dap_string_t *string, size_t len);
diff --git a/dap-sdk/core/src/dap_strfuncs.c b/dap-sdk/core/src/dap_strfuncs.c
index 29ef7430d33710fd19f1b532537f86625f9e4df6..99180b36fc207d2a3d345a69d344d711815dc6e1 100755
--- a/dap-sdk/core/src/dap_strfuncs.c
+++ b/dap-sdk/core/src/dap_strfuncs.c
@@ -12,6 +12,171 @@
 #include "dap_common.h"
 #include "dap_strfuncs.h"
 
+#define LOG_TAG "dap_strfunc"
+/**
+ * @brief s_strdigit
+ * @param c
+ * @return
+ */
+static int s_strdigit(char c)
+{
+    /* This is ASCII / UTF-8 specific, would not work for EBCDIC */
+    return (c >= '0' && c <= '9') ? c - '0'
+        :  (c >= 'a' && c <= 'z') ? c - 'a' + 10
+        :  (c >= 'A' && c <= 'Z') ? c - 'A' + 10
+        :  255;
+}
+
+#ifdef DAP_GLOBAL_IS_INT128
+
+/**
+ * @brief s_strtou128
+ * @param p
+ * @param endp
+ * @param base
+ * @return
+ */
+static uint128_t s_strtou128(const char *p, char **endp, int base)
+{
+    uint128_t v = 0;
+    int digit;
+
+    if (base == 0) {    /* handle octal and hexadecimal syntax */
+        base = 10;
+        if (*p == '0') {
+            base = 8;
+            if ((p[1] == 'x' || p[1] == 'X') && s_strdigit(p[2]) < 16) {
+                p += 2;
+                base = 16;
+            }
+        }
+    }
+    if (base < 2 || base > 36) {
+        errno = EINVAL;
+    } else
+    if ((digit = s_strdigit(*p)) < base) {
+        v = digit;
+        /* convert to unsigned 128 bit with overflow control */
+        while ((digit = s_strdigit(*++p)) < base) {
+            uint128_t v0 = v;
+            v = v * base + digit;
+            if (v < v0) {
+                v = ~(uint128_t)0;
+                errno = ERANGE;
+            }
+        }
+        if (endp) {
+            *endp = (char *)p;
+        }
+    }
+    return v;
+}
+
+/**
+ * @brief dap_strtou128
+ * @param p
+ * @param endp
+ * @param base
+ * @return
+ */
+uint128_t dap_strtou128(const char *p, char **endp, int base)
+{
+    if (endp) {
+        *endp = (char *)p;
+    }
+    while (isspace((unsigned char)*p)) {
+        p++;
+    }
+    if (*p == '-') {
+        p++;
+        return -s_strtou128(p, endp, base);
+    } else {
+        if (*p == '+')
+            p++;
+        return s_strtou128(p, endp, base);
+    }
+}
+
+/**
+ * @brief dap_strtoi128
+ * @param p
+ * @param endp
+ * @param base
+ * @return
+ */
+int128_t dap_strtoi128(const char *p, char **endp, int base)
+{
+    uint128_t v;
+
+    if (endp) {
+        *endp = (char *)p;
+    }
+    while (isspace((unsigned char)*p)) {
+        p++;
+    }
+    if (*p == '-') {
+        p++;
+        v = s_strtou128(p, endp, base);
+        if (v >= (uint128_t)1 << 127) {
+            if (v > (uint128_t)1 << 127)
+                errno = ERANGE;
+            return -(int128_t)(((uint128_t)1 << 127) - 1) - 1;
+        }
+        return -(int128_t)v;
+    } else {
+        if (*p == '+')
+            p++;
+        v = s_strtou128(p, endp, base);
+        if (v >= (uint128_t)1 << 127) {
+            errno = ERANGE;
+            return (int128_t)(((uint128_t)1 << 127) - 1);
+        }
+        return (int128_t)v;
+    }
+}
+/**
+ * @brief dap_utoa128
+ * @param dest
+ * @param v
+ * @param base
+ * @return
+ */
+char *dap_utoa128(char *dest, uint128_t v, int base)
+{
+    char buf[129];
+    char *p = buf + 128;
+    const char *digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+    *p = '\0';
+    if (base >= 2 && base <= 36) {
+        while (v > (unsigned)base - 1) {
+            *--p = digits[v % base];
+            v /= base;
+        }
+        *--p = digits[v];
+    }
+    return strcpy(dest, p);
+}
+
+char *dap_itoa128(char *a_str, int128_t a_value, int a_base)
+{
+    char *p = a_str;
+    uint128_t uv = (uint128_t)a_value;
+    if (a_value < 0) {
+        *p++ = '-';
+        uv = -uv;
+    }
+    if (a_base == 10)
+        dap_utoa128(p, uv, 10);
+    else
+    if (a_base == 16)
+        dap_utoa128(p, uv, 16);
+    else
+        dap_utoa128(p, uv, a_base);
+    return a_str;
+}
+#endif
+
 /**
  * dap_strlen:
  * @a_str: (nullable): the string
diff --git a/dap-sdk/core/src/dap_string.c b/dap-sdk/core/src/dap_string.c
index 072107e390f4b55d887f83bdf3f901c47fb29fa7..be00ca8534fcf1862951dc0fc6e19acacbea1019 100755
--- a/dap-sdk/core/src/dap_string.c
+++ b/dap-sdk/core/src/dap_string.c
@@ -6,6 +6,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
+#include <errno.h>
 
 #include "dap_common.h"
 #include "dap_strfuncs.h"
diff --git a/dap-sdk/net/client/dap_client_pvt.c b/dap-sdk/net/client/dap_client_pvt.c
index 2d5be02b2588c47f50fc3e58f25dd572eb95cf8b..f86c269f808a9bba0fec98d36f826061367a97c3 100644
--- a/dap-sdk/net/client/dap_client_pvt.c
+++ b/dap-sdk/net/client/dap_client_pvt.c
@@ -359,7 +359,6 @@ static void* dap_client_pvt_delete_proc(void *a_arg)
  */
 void dap_client_pvt_delete(dap_client_pvt_t * a_client_pvt)
 {
-    pthread_t l_thread = NULL;
     //pthread_create(&l_thread, NULL, dap_client_pvt_delete_proc, a_client_pvt);
     dap_client_pvt_delete_in(a_client_pvt);
 }
diff --git a/modules/common/dap_chain_datum_token.c b/modules/common/dap_chain_datum_token.c
index 58edc370c30c75ccfbd8ee3d6cb0adbb17f44872..d0c8a39a530444b29c0714ee2b2cc8f1c05051b9 100644
--- a/modules/common/dap_chain_datum_token.c
+++ b/modules/common/dap_chain_datum_token.c
@@ -23,12 +23,44 @@
 */
 #include <stdio.h>
 #include <string.h>
+#include "dap_strfuncs.h"
+#include "dap_common.h"
 #include "dap_chain_datum_token.h"
 
+#define LOG_TAG "dap_chain_datum_token"
+
 const char *c_dap_chain_datum_token_emission_type_str[]={
-    [DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_UNDEFINED] = "DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_UNDEFINED",
-    [DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_AUTH] = "DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_AUTH",
-    [DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_ALGO] = "DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_ALGO",
-    [DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_ATOM_OWNER] = "DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_ATOM_OWNER",
-    [DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_SMART_CONTRACT] = "DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_SMART_CONTRACT",
+    [DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_UNDEFINED] = "UNDEFINED",
+    [DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_AUTH] = "AUTH",
+    [DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_ALGO] = "ALGO",
+    [DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_ATOM_OWNER] = "OWNER",
+    [DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_SMART_CONTRACT] = "SMART_CONTRACT",
+};
+
+const char *c_dap_chain_datum_token_flag_str[] = {
+    [DAP_CHAIN_DATUM_TOKEN_FLAG_NONE] = "NONE",
+    [DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_BLOCKED] = "ALL_BLOCKED",
+    [DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_ALLOWED] = "ALL_ALLOWED",
+    [DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_FROZEN] = "ALL_FROZEN",
+    [DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_UNFROZEN] = "ALL_UNFROZEN",
 };
+
+/**
+ * @brief dap_chain_datum_token_tsd_create
+ * @param a_type
+ * @param a_data
+ * @param a_data_size
+ * @return
+ */
+dap_chain_datum_token_tsd_t * dap_chain_datum_token_tsd_create(uint16_t a_type, const void * a_data, size_t a_data_size)
+{
+    dap_chain_datum_token_tsd_t * l_tsd = DAP_NEW_Z_SIZE(dap_chain_datum_token_tsd_t,
+                                                         sizeof(dap_chain_datum_token_tsd_t) + a_data_size );
+    if ( l_tsd ){
+        memcpy(l_tsd->data,&a_data , a_data_size );
+        l_tsd->type = a_type;
+        l_tsd->size = a_data_size;
+    }
+    return l_tsd;
+
+}
diff --git a/modules/common/include/dap_chain_datum_token.h b/modules/common/include/dap_chain_datum_token.h
index ea1e80da48718761721c31bd4799a20061e05ac5..83f9b36e7547c4ccbcc7e90e6e4b2433b2a3d4d5 100644
--- a/modules/common/include/dap_chain_datum_token.h
+++ b/modules/common/include/dap_chain_datum_token.h
@@ -26,7 +26,7 @@
 #include "dap_chain_common.h"
 #include "dap_sign.h"
 
-
+#include "dap_strfuncs.h"
 
 // Token declaration
 typedef struct dap_chain_datum_token{
@@ -57,7 +57,7 @@ typedef struct dap_chain_datum_token{
             uint32_t flags;
         } DAP_ALIGN_PACKED header_public;
     };
-    byte_t data[]; // Signs or types-size-data sections if exists
+    byte_t data_n_tsd[]; // Signs and/or types-size-data sections
 } DAP_ALIGN_PACKED dap_chain_datum_token_t;
 
 // Token declaration type
@@ -73,6 +73,8 @@ typedef struct dap_chain_datum_token{
 
 // Macros for token flags
 /// ------- Global section flags --------
+// No any flags
+#define DAP_CHAIN_DATUM_TOKEN_FLAG_NONE                                    0x0000
 // Blocked all permissions, usefull issue it by default and then allow what you want to allow
 #define DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_BLOCKED                             0x0001
 // Allowed all permissions if not blocked them. Be careful with this mode
@@ -82,6 +84,29 @@ typedef struct dap_chain_datum_token{
 // Unfrozen permissions
 #define DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_UNFROZEN                            0x0004
 
+//  Maximal flag
+#define DAP_CHAIN_DATUM_TOKEN_FLAG_MAX                                     0x0004
+
+#define DAP_CHAIN_DATUM_TOKEN_FLAG_UNDEFINED                               0xffff
+
+extern const char *c_dap_chain_datum_token_flag_str[];
+
+#define dap_chain_datum_token_flag_to_str(a) (if (a<=DAP_CHAIN_DATUM_TOKEN_FLAG_MAX) c_dap_chain_datum_token_flag_str[a]; else "OUT_OF_RANGE")
+
+/**
+ * @brief dap_chain_datum_token_flag_from_str
+ * @param a_str
+ * @return
+ */
+static inline uint16_t dap_chain_datum_token_flag_from_str(const char* a_str)
+{
+    for (uint16_t i = DAP_CHAIN_DATUM_TOKEN_FLAG_NONE; i <=DAP_CHAIN_DATUM_TOKEN_FLAG_MAX; i++ ){
+        if ( strcmp( a_str, c_dap_chain_datum_token_flag_str[i]) == 0 )
+            return i;
+    }
+    return DAP_CHAIN_DATUM_TOKEN_FLAG_UNDEFINED;
+}
+
 /// ------ Static configured flags
 // No token manipulations after declarations at all. Token declares staticly and can't variabed after
 #define DAP_CHAIN_DATUM_TOKEN_FLAG_STATIC_ALL                              0x0010
@@ -107,7 +132,7 @@ typedef struct dap_chain_datum_token_tsd{
     uint16_t type; /// Section type
     size_t size;   /// Data size trailing the section
     byte_t data[]; /// Section's data
-} DAP_ALIGN_PACKED dap_chain_datum_token_klv_t;
+} DAP_ALIGN_PACKED dap_chain_datum_token_tsd_t;
 
 /// -------- General tsd types ----
 // Flags set/unsed
@@ -197,3 +222,17 @@ typedef struct dap_chain_datum_token_emission{
 #define DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_ATOM_OWNER        0x03
 #define DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_SMART_CONTRACT    0x04
 extern const char *c_dap_chain_datum_token_emission_type_str[];
+
+/// TDS op funcs
+///
+
+dap_chain_datum_token_tsd_t * dap_chain_datum_token_tsd_create(uint16_t a_type, const void * a_data, size_t a_data_size);
+#define dap_chain_datum_token_tsd_create_scalar(type,value) dap_chain_datum_token_tsd_create (type, &value, sizeof(value) )
+#define dap_chain_datum_token_tsd_get_scalar(a,typeconv)  *((typeconv*) a->data)
+
+// NULL-terminated string
+#define dap_chain_datum_token_tsd_create_string(type,str) dap_chain_datum_token_tsd_create (type,str, dap_strlen(str))
+#define dap_chain_datum_token_tsd_get_string(a)  ((char*) a->data )
+#define dap_chain_datum_token_tsd_get_string_const(a)  ((const char*) a->data )
+
+#define dap_chain_datum_token_tsd_size(a) (sizeof(*a)+a->size)
diff --git a/modules/global-db/dap_chain_global_db.c b/modules/global-db/dap_chain_global_db.c
index fa753cb3c3aad93d3bda43bf74d86473c12d2250..f3ac1f41b2c3ca6abb99848300fe0fa74408db8f 100644
--- a/modules/global-db/dap_chain_global_db.c
+++ b/modules/global-db/dap_chain_global_db.c
@@ -126,7 +126,8 @@ char* dap_chain_global_db_get_history_group_by_group_name(const char * a_group_n
     HASH_FIND_STR(s_history_extra_group_items, a_group_name, l_history_extra_group_item);
     if(l_history_extra_group_item) {
         return dap_strdup(l_history_extra_group_item->group_name_for_history);
-    }
+    }else
+        return NULL;
 }
 
 /**
@@ -167,7 +168,7 @@ void dap_chain_global_db_add_history_callback_notify(const char * a_group_prefix
  * @details Add group prefix that will be tracking all changes
  * @param a_group_prefix
  */
-const char* dap_chain_global_db_add_history_extra_group(const char * a_group_name, dap_chain_node_addr_t *a_nodes, size_t *a_nodes_count)
+const char* dap_chain_global_db_add_history_extra_group(const char * a_group_name, dap_chain_node_addr_t *a_nodes, uint16_t *a_nodes_count)
 {
     history_extra_group_item_t* l_item = DAP_NEW_Z(history_extra_group_item_t);
     l_item->group_name = dap_strdup(a_group_name);
diff --git a/modules/global-db/include/dap_chain_global_db.h b/modules/global-db/include/dap_chain_global_db.h
index 0a0ecda751202a7c9370571baee4a83a295b61c6..702814029c995a581255da31232d4d7e68476156 100644
--- a/modules/global-db/include/dap_chain_global_db.h
+++ b/modules/global-db/include/dap_chain_global_db.h
@@ -62,7 +62,7 @@ char* dap_chain_global_db_get_history_group_by_group_name(const char * a_group_n
 void dap_chain_global_db_add_history_group_prefix(const char * a_group_prefix, const char * a_group_name_for_history);
 void dap_chain_global_db_add_history_callback_notify(const char * a_group_prefix,
                                                      dap_global_db_obj_callback_notify_t a_callback, void * a_arg);
-const char* dap_chain_global_db_add_history_extra_group(const char * a_group_name, dap_chain_node_addr_t *a_nodes, size_t *a_nodes_count);
+const char* dap_chain_global_db_add_history_extra_group(const char * a_group_name, dap_chain_node_addr_t *a_nodes, uint16_t *a_nodes_count);
 void dap_chain_global_db_add_history_extra_group_callback_notify(const char * a_group_prefix,
         dap_global_db_obj_callback_notify_t a_callback, void * a_arg);
 /**
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index b8384cf4b4fb40010581ae45b2b32d42cb3f52f0..afcc63f34c8c3d505275613095cc74832ee11bd5 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -1259,8 +1259,9 @@ int s_net_load(const char * a_net_name)
                     char *l_group_name = l_groups->data;
                     // do not use groups with names like *.del
                     if(!strstr(l_group_name, ".del")) {
-                        const char *l_history_group = dap_chain_global_db_add_history_extra_group(l_group_name, PVT(l_net)->gdb_sync_nodes_addrs,
-                                PVT(l_net)->gdb_sync_nodes_addrs_count);
+                        const char *l_history_group = dap_chain_global_db_add_history_extra_group(l_group_name,
+                                                        PVT(l_net)->gdb_sync_nodes_addrs,
+                                                        &PVT(l_net)->gdb_sync_nodes_addrs_count);
                         dap_chain_global_db_add_history_extra_group_callback_notify(l_group_name,
                                 s_gbd_history_callback_notify, l_net);
                         // create history for group
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index 4504d1c791ea9b64f0b583307a4917eb027f6c44..1eb3920a9776fdb0cbe02179b840114507717a4e 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -1831,7 +1831,7 @@ int com_token_decl_sign(int argc, char ** argv, void *arg_func, char ** a_str_re
                 size_t l_signs_count = 0;
 
                 for(size_t l_offset = 0; l_offset < l_signs_size; l_signs_count++) {
-                    dap_sign_t * l_sign = (dap_sign_t *) l_datum_token->data + l_offset;
+                    dap_sign_t * l_sign = (dap_sign_t *) l_datum_token->data_n_tsd + l_offset;
                     l_offset += dap_sign_get_size(l_sign);
                     if( dap_sign_verify(l_sign, l_datum_token, sizeof(l_datum_token->header_private)) != 1) {
                         log_it(L_WARNING, "Wrong signature %u for datum_token with key %s in mempool!", l_signs_count, l_datum_hash_str);
@@ -1883,7 +1883,7 @@ int com_token_decl_sign(int argc, char ** argv, void *arg_func, char ** a_str_re
                         if ( l_datum = DAP_REALLOC(l_datum, l_datum_size) ){ // add place for new signatures
                             l_datum_token = (dap_chain_datum_token_t*) l_datum->data;
                             l_datum->header.data_size = l_datum_token_size;
-                            memcpy(l_datum_token->data + l_offset, l_sign, l_sign_size);
+                            memcpy(l_datum_token->data_n_tsd + l_offset, l_sign, l_sign_size);
                             log_it(L_DEBUG, "Added datum token declaration sign with cert %s (new size %lu)",
                                    l_certs[i]->name , l_datum_size);
                             DAP_DELETE(l_sign);
@@ -2309,7 +2309,7 @@ int com_token_decl(int argc, char ** argv, void *arg_func, char ** a_str_reply)
     const char * l_certs_str = NULL;
 
     dap_cert_t ** l_certs = NULL;
-    size_t l_certs_size = 0;
+    size_t l_certs_count = 0;
 
     dap_chain_t * l_chain = NULL;
     dap_chain_net_t * l_net = NULL;
@@ -2343,38 +2343,117 @@ int com_token_decl(int argc, char ** argv, void *arg_func, char ** a_str_reply)
     }
 
     dap_chain_datum_token_t * l_datum_token = NULL;
-    size_t l_signs_offset = 0;
+    size_t l_datum_data_offset = 0;
 
     switch(l_type){
         case DAP_CHAIN_DATUM_TOKEN_PRIVATE_DECL:{
             dap_list_t *l_tsd_list = dap_list_alloc();
-            size_t l_tsd_size = 0;
+            size_t l_tsd_total_size = 0;
             uint16_t l_flags = 0;
-            while (l_arg_index<argc){
-                if ( strcmp( argv[l_arg_index],"-flags" )){
-                }else if ( strcmp( argv[l_arg_index],"-total_supply" )){
-
-                }else if ( strcmp( argv[l_arg_index],"-signs_valid" )){
-
+            char ** l_str_flags = NULL;
+            while (l_arg_index<argc-1){
+                char * l_arg_param=  argv[l_arg_index+1];
+                if ( strcmp( argv[l_arg_index],"-flags" )){   // Flags
+                     l_str_flags = dap_strsplit( l_arg_param,",",0xffff );
+                     while (l_str_flags){
+                         uint16_t l_flag = dap_chain_datum_token_flag_from_str(*l_str_flags);
+                         if ( l_flag == DAP_CHAIN_DATUM_TOKEN_FLAG_UNDEFINED ){
+                             dap_chain_node_cli_set_reply_text(a_str_reply, "Flag can't be \"%s\"",*l_str_flags);
+                             return -20;
+                         }
+                         l_flags |= l_flag;
+                         l_str_flags++;
+                     }
+                } else if ( strcmp( argv[l_arg_index],"-total_supply" )){ // Total supply
+                    uint128_t l_param_value = dap_atou128(l_arg_param);
+                    dap_chain_datum_token_tsd_t * l_tsd = dap_chain_datum_token_tsd_create_scalar(
+                                                            DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY, l_param_value);
+                    dap_list_append( l_tsd_list, l_tsd);
+                    l_tsd_total_size+= dap_chain_datum_token_tsd_size( l_tsd);
+                }else if ( strcmp( argv[l_arg_index],"-signs_valid" )){ // Signs valid
+                    uint16_t l_param_value = (uint16_t)atoi(l_arg_param);
+                    dap_chain_datum_token_tsd_t * l_tsd = dap_chain_datum_token_tsd_create_scalar(
+                                                            DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID, l_param_value);
+                    dap_list_append( l_tsd_list, l_tsd);
+                    l_tsd_total_size+= dap_chain_datum_token_tsd_size( l_tsd);
                 }else if ( strcmp( argv[l_arg_index],"-signs" )){
-
+                    dap_cert_parse_str_list(l_arg_param, &l_certs, &l_certs_count);
+                    if(!l_certs_count) {
+                        dap_chain_node_cli_set_reply_text(a_str_reply,
+                                "token_decl command requres at least one valid certificate to sign the basic transaction of emission");
+                        return -10;
+                    }
                 }else if ( strcmp( argv[l_arg_index],"-datum_type_allowed" )){
-
+                    dap_chain_datum_token_tsd_t * l_tsd = dap_chain_datum_token_tsd_create_string(
+                                                            DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_ADD, l_arg_param);
+                    dap_list_append( l_tsd_list, l_tsd);
+                    l_tsd_total_size+= dap_chain_datum_token_tsd_size( l_tsd);
                 }else if ( strcmp( argv[l_arg_index],"-datum_type_blocked" )){
-
+                    dap_chain_datum_token_tsd_t * l_tsd = dap_chain_datum_token_tsd_create_string(
+                                                            DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_ADD, l_arg_param);
+                    dap_list_append( l_tsd_list, l_tsd);
+                    l_tsd_total_size+= dap_chain_datum_token_tsd_size( l_tsd);
                 }else if ( strcmp( argv[l_arg_index],"-tx_receiver_allowed" )){
-
+                    dap_chain_datum_token_tsd_t * l_tsd = dap_chain_datum_token_tsd_create_string(
+                                                            DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD, l_arg_param);
+                    dap_list_append( l_tsd_list, l_tsd);
+                    l_tsd_total_size+= dap_chain_datum_token_tsd_size( l_tsd);
                 }else if ( strcmp( argv[l_arg_index],"-tx_receiver_blocked" )){
-
+                    dap_chain_datum_token_tsd_t * l_tsd = dap_chain_datum_token_tsd_create_string(
+                                                            DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD, l_arg_param);
+                    dap_list_append( l_tsd_list, l_tsd);
+                    l_tsd_total_size+= dap_chain_datum_token_tsd_size( l_tsd);
                 }else if ( strcmp( argv[l_arg_index],"-tx_sender_allowed" )){
-
+                    dap_chain_datum_token_tsd_t * l_tsd = dap_chain_datum_token_tsd_create_string(
+                                                            DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD, l_arg_param);
+                    dap_list_append( l_tsd_list, l_tsd);
+                    l_tsd_total_size+= dap_chain_datum_token_tsd_size( l_tsd);
                 }else if ( strcmp( argv[l_arg_index],"-tx_sender_blocked" )){
-
+                    dap_chain_datum_token_tsd_t * l_tsd = dap_chain_datum_token_tsd_create_string(
+                                                            DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD, l_arg_param);
+                    dap_list_append( l_tsd_list, l_tsd);
+                    l_tsd_total_size+= dap_chain_datum_token_tsd_size( l_tsd);
                 }else {
-
+                    dap_chain_node_cli_set_reply_text(a_str_reply, "Unknown param \"%s\"",argv[l_arg_index]);
+                    return -20;
                 }
                 ++l_arg_index;
             }
+
+
+            // If we have more certs than we need signs - use only first part of the list
+            if(l_certs_count > l_signs_total)
+                l_certs_count = l_signs_total;
+
+            // Create new datum token
+            l_datum_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, sizeof(dap_chain_datum_token_t)+l_tsd_total_size ) ;
+            l_datum_token->type = DAP_CHAIN_DATUM_TOKEN_PRIVATE_DECL;
+            dap_snprintf(l_datum_token->ticker, sizeof(l_datum_token->ticker), "%s", l_ticker);
+            l_datum_token->header_private_decl.flags = l_flags;
+
+            // 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_count; i++) {
+                dap_sign_t * l_sign = dap_cert_sign(l_certs[i],
+                        l_datum_token,
+                        sizeof(l_datum_token->header_private),
+                        0);
+                size_t l_sign_size = dap_sign_get_size(l_sign);
+                l_datum_token = DAP_REALLOC(l_datum_token, sizeof(dap_chain_datum_token_t) + l_datum_data_offset + l_sign_size);
+                memcpy(l_datum_token->data_n_tsd + l_datum_data_offset, l_sign, l_sign_size);
+                l_datum_data_offset += l_sign_size;
+                DAP_DELETE(l_sign);
+            }
+
+            // Add TSD sections in the end
+            for ( dap_list_t* l_iter=dap_list_first(l_tsd_list); l_iter; l_iter=l_iter->next){
+                dap_chain_datum_token_tsd_t * l_tsd = (dap_chain_datum_token_tsd_t *) l_iter->data;
+                size_t l_tsd_size = dap_chain_datum_token_tsd_size( l_tsd);
+                memcpy(l_datum_token->data_n_tsd + l_datum_data_offset, l_tsd, l_tsd_size);
+                l_datum_data_offset += l_tsd_size;
+            }
+
+
         }break;
         case DAP_CHAIN_DATUM_TOKEN_PRIVATE:{
             // Total supply value
@@ -2438,16 +2517,16 @@ int com_token_decl(int argc, char ** argv, void *arg_func, char ** a_str_reply)
             }
 
             // Load certs lists
-            dap_cert_parse_str_list(l_certs_str, &l_certs, &l_certs_size);
-            if(!l_certs_size) {
+            dap_cert_parse_str_list(l_certs_str, &l_certs, &l_certs_count);
+            if(!l_certs_count) {
                 dap_chain_node_cli_set_reply_text(a_str_reply,
                         "token_decl command requres at least one valid certificate to sign the basic transaction of emission");
                 return -10;
             }
 
             // 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;
+            if(l_certs_count > l_signs_total)
+                l_certs_count = l_signs_total;
 
             // Create new datum token
             l_datum_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, sizeof(dap_chain_datum_token_t));
@@ -2459,15 +2538,15 @@ int com_token_decl(int argc, char ** argv, void *arg_func, char ** a_str_reply)
 
             // 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++) {
+            for(size_t i = 0; i < l_certs_count; i++) {
                 dap_sign_t * l_sign = dap_cert_sign(l_certs[i],
                         l_datum_token,
                         sizeof(l_datum_token->header_private),
                         0);
                 size_t l_sign_size = dap_sign_get_size(l_sign);
-                l_datum_token = DAP_REALLOC(l_datum_token, sizeof(dap_chain_datum_token_t) + l_signs_offset + l_sign_size);
-                memcpy(l_datum_token->data + l_signs_offset, l_sign, l_sign_size);
-                l_signs_offset += l_sign_size;
+                l_datum_token = DAP_REALLOC(l_datum_token, sizeof(dap_chain_datum_token_t) + l_datum_data_offset + l_sign_size);
+                memcpy(l_datum_token->data_n_tsd + l_datum_data_offset, l_sign, l_sign_size);
+                l_datum_data_offset += l_sign_size;
                 DAP_DELETE(l_sign);
             }
         }break;
@@ -2478,7 +2557,7 @@ int com_token_decl(int argc, char ** argv, void *arg_func, char ** a_str_reply)
     }
 
     dap_chain_datum_t * l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_TOKEN_DECL, l_datum_token,
-            sizeof(l_datum_token->header_private) + l_signs_offset);
+            sizeof(l_datum_token->header_private) + l_datum_data_offset);
     size_t l_datum_size = dap_chain_datum_size(l_datum);
 
     // Calc datum's hash
diff --git a/modules/net/dap_chain_node_client.c b/modules/net/dap_chain_node_client.c
index 572ad92622ac31c02226fc5e279c5486c38957e3..5780765f0b2319d572267354b149bc84524e7743 100644
--- a/modules/net/dap_chain_node_client.c
+++ b/modules/net/dap_chain_node_client.c
@@ -325,28 +325,38 @@ static void s_ch_chain_callback_notify_packet_in(dap_stream_ch_chain_t* a_ch_cha
                     if(l_type == DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_CHAIN)
                     {
                         dap_chain_t * l_chain = dap_chain_find_by_id(a_pkt->hdr.net_id, a_pkt->hdr.chain_id);
-                        dap_chain_atom_iter_t* l_iter = l_chain ? l_chain->callback_atom_iter_create(l_chain) : NULL;
-                        //a_ch_chain->request_atom_iter = l_iter;
-
-                        dap_chain_atom_ptr_t * l_lasts = NULL;
-                        size_t l_lasts_size = 0;
-                        l_lasts = l_chain->callback_atom_iter_get_lasts(l_iter, &l_lasts_size);
-                        for(size_t i = 0; i < l_lasts_size; i++) {
-                            dap_chain_atom_item_t * l_item = NULL;
-                            dap_chain_hash_fast_t l_atom_hash;
-                            dap_hash_fast(l_lasts[i], l_chain->callback_atom_get_size(l_lasts[i]), &l_atom_hash);
-                            HASH_FIND(hh, a_ch_chain->request_atoms_lasts, &l_atom_hash, sizeof(l_atom_hash), l_item);
-                            if(l_item == NULL) { // Not found, add new lasts
-                                l_item = DAP_NEW_Z(dap_chain_atom_item_t);
-                                l_item->atom = l_lasts[i];
-                                memcpy(&l_item->atom_hash, &l_atom_hash, sizeof(l_atom_hash));
-                                HASH_ADD(hh, a_ch_chain->request_atoms_lasts, atom_hash, sizeof(l_atom_hash), l_item);
+                        if (l_chain ){
+                            dap_chain_atom_iter_t* l_iter = l_chain ? l_chain->callback_atom_iter_create(l_chain) : NULL;
+                            if ( l_iter ){
+                                //a_ch_chain->request_atom_iter = l_iter;
+
+                                dap_chain_atom_ptr_t * l_lasts = NULL;
+                                size_t l_lasts_size = 0;
+                                l_lasts = l_chain->callback_atom_iter_get_lasts(l_iter, &l_lasts_size);
+                                if ( l_lasts){
+                                    for(size_t i = 0; i < l_lasts_size; i++) {
+                                        dap_chain_atom_item_t * l_item = NULL;
+                                        dap_chain_hash_fast_t l_atom_hash;
+                                        dap_hash_fast(l_lasts[i], l_chain->callback_atom_get_size(l_lasts[i]), &l_atom_hash);
+                                        HASH_FIND(hh, a_ch_chain->request_atoms_lasts, &l_atom_hash, sizeof(l_atom_hash), l_item);
+                                        if(l_item == NULL) { // Not found, add new lasts
+                                            l_item = DAP_NEW_Z(dap_chain_atom_item_t);
+                                            l_item->atom = l_lasts[i];
+                                            memcpy(&l_item->atom_hash, &l_atom_hash, sizeof(l_atom_hash));
+                                            HASH_ADD(hh, a_ch_chain->request_atoms_lasts, atom_hash, sizeof(l_atom_hash), l_item);
+                                        }
+                                        //else
+                                        //    DAP_DELETE(l_lasts[i]);
+                                    }
+                                    DAP_DELETE(l_lasts);
+                                }
+                                DAP_DELETE(l_iter);
+                            }else{
+                                log_it(L_ERROR, "Can't create iterator for chain_id 0x%016X", a_pkt->hdr.chain_id );
                             }
-                            //else
-                            //    DAP_DELETE(l_lasts[i]);
+                        }else {
+                            log_it(L_WARNING, "Can't find chain_id 0x%016X", a_pkt->hdr.chain_id );
                         }
-                        DAP_DELETE(l_lasts);
-                        DAP_DELETE(l_iter);
                     }
                     dap_chain_node_addr_t l_node_addr = { 0 };
                     dap_chain_net_t *l_net = dap_chain_net_by_id(a_ch_chain->request_net_id);
diff --git a/modules/net/srv/dap_chain_net_srv.c b/modules/net/srv/dap_chain_net_srv.c
index 8d7b8217c9442c427872ceb16fcfc04e4e792e05..15b1167389a48664c85f1d1ca62d08ef8afdc962 100644
--- a/modules/net/srv/dap_chain_net_srv.c
+++ b/modules/net/srv/dap_chain_net_srv.c
@@ -42,8 +42,10 @@
 
 #include "uthash.h"
 #include "utlist.h"
+#include "dap_common.h"
 #include "dap_list.h"
 #include "dap_string.h"
+#include "dap_file_utils.h"
 
 #include "dap_chain.h"
 #include "dap_chain_common.h"
@@ -383,7 +385,7 @@ static int s_cli_net_srv( int argc, char **argv, void *arg_func, char **a_str_re
                     dap_string_append_printf(l_string_ret,"Found %zd orders:\n",l_orders_num);
                     size_t l_orders_size = 0;
                     for(size_t i = 0; i < l_orders_num; i++) {
-                        dap_chain_net_srv_order_t *l_order = (char*) l_orders + l_orders_size;
+                        dap_chain_net_srv_order_t *l_order =(dap_chain_net_srv_order_t *) (((byte_t*) l_orders) + l_orders_size);
                         dap_chain_net_srv_order_dump_to_string(l_order, l_string_ret);
                         l_orders_size += dap_chain_net_srv_order_get_size(l_order);
                         dap_string_append(l_string_ret, "\n");
diff --git a/modules/service/vpn/include/dap_chain_net_vpn_client_tun.h b/modules/service/vpn/include/dap_chain_net_vpn_client_tun.h
index 250b638c4e8aa23f09c7372ce50f42d89a4bcf68..8322907d10761622ec5260d1fca036b589d9be92 100644
--- a/modules/service/vpn/include/dap_chain_net_vpn_client_tun.h
+++ b/modules/service/vpn/include/dap_chain_net_vpn_client_tun.h
@@ -31,3 +31,4 @@ int dap_chain_net_vpn_client_tun_delete(void);
 int dap_chain_net_vpn_client_tun_status(void);
 
 int ch_sf_tun_addr_leased(dap_chain_net_srv_ch_vpn_t * a_sf, ch_vpn_pkt_t * a_pkt, size_t a_pkt_data_size);
+void ch_sf_tun_send(dap_chain_net_srv_ch_vpn_t * ch_sf, void * pkt_data, size_t pkt_data_size);