From 84e16ad640e38f996c6d902c2768f5fbf9ae58ac Mon Sep 17 00:00:00 2001
From: Roman Khlopkov <roman.khlopkov@demlabs.net>
Date: Mon, 4 Apr 2022 12:24:09 +0000
Subject: [PATCH] support-5340

---
 modules/chain/dap_chain_ledger.c              | 377 +++---------------
 modules/chain/include/dap_chain_ledger.h      |   2 +-
 modules/common/dap_chain_common.c             |   9 +-
 modules/common/dap_chain_datum_token.c        |  76 +---
 .../common/include/dap_chain_datum_token.h    |  56 +--
 modules/mempool/dap_chain_mempool.c           |  42 +-
 modules/mempool/include/dap_chain_mempool.h   |   1 +
 modules/net/dap_chain_net.c                   |  16 +-
 modules/net/dap_chain_node_cli_cmd.c          | 339 ++++++----------
 modules/net/dap_chain_node_cli_cmd_tx.c       | 229 ++++-------
 10 files changed, 346 insertions(+), 801 deletions(-)

diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c
index 519e66bfb4..7f3ef7b543 100644
--- a/modules/chain/dap_chain_ledger.c
+++ b/modules/chain/dap_chain_ledger.c
@@ -94,7 +94,6 @@ typedef struct dap_chain_ledger_token_item {
     dap_chain_hash_fast_t * auth_signs_pkey_hash;
     size_t auth_signs_total;
     size_t auth_signs_valid;
-    size_t auth_signs_current;
     uint16_t           flags;
     dap_chain_addr_t * tx_recv_allow;
     size_t             tx_recv_allow_size;
@@ -220,7 +219,6 @@ static bool s_ledger_tps_callback(void *a_arg);
 static size_t s_threshold_emissions_max = 1000;
 static size_t s_threshold_txs_max = 10000;
 static bool s_debug_more = false;
-static bool s_token_supply_limit_disable = false;
 
 /**
  * @brief dap_chain_ledger_init
@@ -230,7 +228,6 @@ static bool s_token_supply_limit_disable = false;
 int dap_chain_ledger_init()
 {
     s_debug_more = dap_config_get_item_bool_default(g_config,"ledger","debug_more",false);
-    s_token_supply_limit_disable = dap_config_get_item_bool_default(g_config,"ledger","token_supply_limit_disable",false);
     return 0;
 }
 
@@ -327,18 +324,18 @@ int dap_chain_ledger_token_decl_add_check(dap_ledger_t *a_ledger, dap_chain_datu
  * @param a_token_ticker
  * @return
  */
-int dap_chain_ledger_token_ticker_check(dap_ledger_t * a_ledger, const char *a_token_ticker)
+dap_chain_datum_token_t *dap_chain_ledger_token_ticker_check(dap_ledger_t * a_ledger, const char *a_token_ticker)
 {
     if ( !a_ledger){
         if(s_debug_more)
             log_it(L_WARNING, "NULL ledger, can't find token ticker");
-        return  -2;
+        return NULL;
     }
     dap_chain_ledger_token_item_t *l_token_item;
     pthread_rwlock_rdlock(&PVT(a_ledger)->tokens_rwlock);
     HASH_FIND_STR(PVT(a_ledger)->tokens, a_token_ticker, l_token_item);
     pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock);
-    return (size_t)l_token_item;
+    return l_token_item ? l_token_item->datum_token : NULL;
 }
 
 /**
@@ -372,133 +369,67 @@ int dap_chain_ledger_token_add(dap_ledger_t *a_ledger, dap_chain_datum_token_t *
     l_token_item->datum_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, a_token_size);
     l_token_item->datum_token_size = a_token_size;
     l_token_item->type = a_token->type;
-
     memcpy(l_token_item->datum_token, a_token, a_token_size);
-    dap_chain_datum_token_t *l_token_cache = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, a_token_size);
-    memcpy(l_token_cache, a_token, a_token_size);
-
-    // init current_supply value in token_declaration procedure (ledger cache and ledger memory object)
-    // header_simple, header_token_private, header_token_
-     switch(a_token->type){
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE:
-            l_token_item->datum_token->header_simple.current_supply_256 = a_token->header_simple.total_supply_256;
-            l_token_item->total_supply = a_token->header_simple.total_supply_256;
-            l_token_item->current_supply = a_token->header_simple.total_supply_256;
-            l_token_item->auth_signs_total = a_token->header_simple.signs_total;
-            l_token_item->auth_signs_valid = a_token->header_simple.signs_valid;
-            l_token_item->auth_signs_current = a_token->header_simple.signs_current;
-            l_token_cache->header_simple.current_supply_256 = a_token->header_simple.total_supply_256;
-        break;
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL:
-            l_token_item->datum_token->header_private_decl.current_supply_256 = a_token->header_private_decl.total_supply_256;
-            l_token_item->total_supply = a_token->header_private_decl.total_supply_256;
-            l_token_item->current_supply = a_token->header_private_decl.total_supply_256;
-            l_token_item->auth_signs_total = a_token->header_private_decl.signs_total;
-            l_token_item->auth_signs_valid = a_token->header_private_decl.signs_valid;
-            l_token_item->auth_signs_current = a_token->header_private_decl.signs_current;
-            l_token_cache->header_private_decl.current_supply_256 = a_token->header_private_decl.total_supply_256;
-        break;
-            case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL:
-            l_token_item->datum_token->header_native_decl.current_supply_256 = a_token->header_native_decl.total_supply_256;
-            l_token_item->total_supply = a_token->header_native_decl.total_supply_256;
-            l_token_item->current_supply = a_token->header_native_decl.total_supply_256;
-            l_token_item->auth_signs_total = a_token->header_native_decl.signs_total;
-            l_token_item->auth_signs_valid = a_token->header_native_decl.signs_valid;
-            l_token_item->auth_signs_current = a_token->header_native_decl.signs_current;
-            l_token_cache->header_native_decl.current_supply_256 = a_token->header_native_decl.total_supply_256;
-        default:
-        break;
-     }
+    dap_chain_datum_token_t *l_token = a_token;
+    size_t l_token_size = a_token_size;
+    if (a_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE)
+        l_token = dap_chain_datum_token_read((byte_t *)a_token, &l_token_size);
+    l_token_item->total_supply = l_token->total_supply;
+    l_token_item->auth_signs_total = l_token->signs_total;
+    l_token_item->auth_signs_valid = l_token->signs_valid;
+
     
     pthread_rwlock_wrlock(&PVT(a_ledger)->tokens_rwlock);
     HASH_ADD_STR(PVT(a_ledger)->tokens, ticker, l_token_item);
     pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock);
 
-    // Add it to cache
-    char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_TOKENS_STR);
-    if (!dap_chain_global_db_gr_set( a_token->ticker, l_token_cache, a_token_size, l_gdb_group)) {
-        if(s_debug_more)
-            log_it(L_WARNING, "Ledger cache mismatch");
-    }
-    DAP_DELETE(l_gdb_group);
-    switch(a_token->type){
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE: {// 256
-            l_token_item->auth_signs= dap_chain_datum_token_simple_signs_parse(a_token,a_token_size,
-                                                                                       &l_token_item->auth_signs_total,
-                                                                                       &l_token_item->auth_signs_valid );
-            if(l_token_item->auth_signs_total){
-                l_token_item->auth_signs_pkey_hash = DAP_NEW_Z_SIZE(dap_chain_hash_fast_t,sizeof (dap_chain_hash_fast_t)* l_token_item->auth_signs_total);
-                for(uint16_t k=0; k<l_token_item->auth_signs_current;k++){
-                    dap_sign_get_pkey_hash(l_token_item->auth_signs[k],&l_token_item->auth_signs_pkey_hash[k]);
-                }
-                if(s_debug_more)
-                    log_it(L_NOTICE, "Simple token %s added (total_supply = %s total_signs_valid=%hu signs_total=%hu type=DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE )",
-                       a_token->ticker, dap_chain_balance_to_coins(a_token->header_simple.total_supply_256),
-                       a_token->header_simple.signs_valid, a_token->header_simple.signs_total);
-            }
-            break;
+    l_token_item->auth_signs = dap_chain_datum_token_signs_parse(a_token, a_token_size,
+                                                               &l_token_item->auth_signs_total,
+                                                               &l_token_item->auth_signs_valid);
+    if(l_token_item->auth_signs_total){
+        l_token_item->auth_signs_pkey_hash = DAP_NEW_Z_SIZE(dap_chain_hash_fast_t, sizeof(dap_chain_hash_fast_t) * l_token_item->auth_signs_total);
+        for(uint16_t k=0; k<l_token_item->auth_signs_total;k++){
+            dap_sign_get_pkey_hash(l_token_item->auth_signs[k], &l_token_item->auth_signs_pkey_hash[k]);
         }
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE: {
-            l_token_item->auth_signs= dap_chain_datum_token_simple_signs_parse(a_token,a_token_size,
-                                                                                       &l_token_item->auth_signs_total,
-                                                                                       &l_token_item->auth_signs_valid );
-            if(l_token_item->auth_signs_total){
-                l_token_item->auth_signs_pkey_hash = DAP_NEW_Z_SIZE(dap_chain_hash_fast_t,sizeof (dap_chain_hash_fast_t)* l_token_item->auth_signs_total);
-                for(uint16_t k=0; k<l_token_item->auth_signs_current;k++){
-                    dap_sign_get_pkey_hash(l_token_item->auth_signs[k],&l_token_item->auth_signs_pkey_hash[k]);
-                }
-                if(s_debug_more)
-                    log_it(L_NOTICE, "Simple token %s added (total_supply = %.1Lf total_signs_valid=%hu signs_total=%hu type=DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE )",
-                       a_token->ticker, dap_chain_datoshi_to_coins(a_token->header_simple.total_supply),
-                       a_token->header_simple.signs_valid, a_token->header_simple.signs_total);
-            }
-            break;
-        }
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL: // 256
-            l_token_item->auth_signs= dap_chain_datum_token_simple_signs_parse(a_token,a_token_size,
-                                                                                    &l_token_item->auth_signs_total,
-                                                                                    &l_token_item->auth_signs_valid );
-            if(l_token_item->auth_signs_total){
-                l_token_item->auth_signs_pkey_hash = DAP_NEW_Z_SIZE(dap_chain_hash_fast_t,sizeof (dap_chain_hash_fast_t)* l_token_item->auth_signs_total);
-                for(uint16_t k=0; k<l_token_item->auth_signs_current;k++){
-                    dap_sign_get_pkey_hash(l_token_item->auth_signs[k],&l_token_item->auth_signs_pkey_hash[k]);
-                }
-                if(s_debug_more)
-                    log_it(L_NOTICE, "Private token %s added (total_supply = %s total_signs_valid=%hu signs_total=%hu type=DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL)",
-                    a_token->ticker, dap_chain_balance_to_coins(a_token->header_private_decl.total_supply_256),
-                    a_token->header_private_decl.signs_valid, a_token->header_private_decl.signs_total);
-            }
+    }
+
+    switch(a_token->type) {
+    case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE:
+    case DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE:
+        if(s_debug_more)
+            log_it(L_NOTICE, "Simple token %s added (total_supply = %s total_signs_valid=%hu signs_total=%hu type=DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE )",
+               l_token->ticker, dap_chain_balance_to_coins(l_token->total_supply),
+               l_token->signs_valid, l_token->signs_total);
+         break;
+    case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL: // 256
+        if(s_debug_more)
+            log_it(L_NOTICE, "Private token %s added (total_supply = %s total_signs_valid=%hu signs_total=%hu type=DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL)",
+            a_token->ticker, dap_chain_balance_to_coins(a_token->total_supply),
+            a_token->signs_valid, a_token->signs_total);
             s_token_tsd_parse(a_ledger,l_token_item, a_token, a_token_size);
             break;
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL: // 256
-            l_token_item->auth_signs= dap_chain_datum_token_simple_signs_parse(a_token,a_token_size,
-                                                                                    &l_token_item->auth_signs_total,
-                                                                                    &l_token_item->auth_signs_valid );
-            if(l_token_item->auth_signs_total){
-                l_token_item->auth_signs_pkey_hash = DAP_NEW_Z_SIZE(dap_chain_hash_fast_t,sizeof (dap_chain_hash_fast_t)* l_token_item->auth_signs_total);
-                for(uint16_t k=0; k<l_token_item->auth_signs_current;k++){
-                    dap_sign_get_pkey_hash(l_token_item->auth_signs[k],&l_token_item->auth_signs_pkey_hash[k]);
-                }
-                if(s_debug_more)
-                    log_it(L_NOTICE, "Native token %s added (total_supply = %s total_signs_valid=%hu signs_total=%hu type=DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL)",
-                    a_token->ticker, dap_chain_balance_to_coins(a_token->header_native_decl.total_supply_256),
-                    a_token->header_native_decl.signs_valid, a_token->header_native_decl.signs_total);
-            }
+   case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL: // 256
+        if(s_debug_more)
+            log_it(L_NOTICE, "Native token %s added (total_supply = %s total_signs_valid=%hu signs_total=%hu type=DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL)",
+            a_token->ticker, dap_chain_balance_to_coins(a_token->total_supply),
+            a_token->signs_valid, a_token->signs_total);
             s_token_tsd_parse(a_ledger,l_token_item, a_token, a_token_size);
             break;
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE: // 256
-            if(s_debug_more)
-                log_it( L_WARNING, "Private token %s type=DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE. Not processed, wait for software update", a_token->ticker);
-                // TODO: Check authorithy
-                //s_token_tsd_parse(a_ledger,l_token_item, a_token, a_token_size);
-            break;
-        default:
-            if(s_debug_more)
-                log_it(L_WARNING,"Unknown token declaration type 0x%04X", a_token->type );
+    case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE: // 256
+        if(s_debug_more)
+            log_it( L_WARNING, "Private token %s type=DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE. Not processed, wait for software update", a_token->ticker);
+            // TODO: Check authorithy
+            //s_token_tsd_parse(a_ledger,l_token_item, a_token, a_token_size);
+        break;
+    default:
+        if(s_debug_more)
+            log_it(L_WARNING,"Unknown token declaration type 0x%04X", a_token->type );
     }
+    l_token_item->current_supply = l_token_item->total_supply;
     // Proc emissions thresholds
     s_threshold_emissions_proc( a_ledger); //TODO process thresholds only for no-consensus chains
-
+    if (a_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE)
+        DAP_DELETE(l_token);
     return  0;
 }
 
@@ -516,7 +447,7 @@ static int s_token_tsd_parse(dap_ledger_t * a_ledger, dap_chain_ledger_token_ite
     UNUSED(a_ledger);
     dap_tsd_t * l_tsd= dap_chain_datum_token_tsd_get(a_token,a_token_size);
     size_t l_tsd_size=0;
-    size_t l_tsd_total_size =a_token_size-  (((byte_t*)l_tsd)- (byte_t*) a_token );
+    size_t l_tsd_total_size = a_token->header_native_decl.tsd_total_size;
 
     for( size_t l_offset=0; l_offset < l_tsd_total_size;  l_offset += l_tsd_size ){
         l_tsd = (dap_tsd_t *) (((byte_t*)l_tsd ) +l_offset);
@@ -965,7 +896,6 @@ int dap_chain_ledger_token_load(dap_ledger_t *a_ledger, dap_chain_datum_token_t
         pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock);
         if (l_token_item)
             return 0;
-        //l_token_item->current_supply = l_token_item->total_supply;
     }
     return dap_chain_ledger_token_add(a_ledger, a_token, a_token_size);
 }
@@ -1032,50 +962,21 @@ dap_list_t *dap_chain_ledger_token_info(dap_ledger_t *a_ledger)
  * @return true
  * @return false
  */
-bool s_update_token_cache(dap_ledger_t *a_ledger, dap_chain_ledger_token_item_t * l_token_item, uint256_t l_emission_value)
+bool s_update_token_cache(dap_chain_ledger_token_item_t *l_token_item, uint256_t l_emission_value)
 {
     //Update value in ledger memory object
-
     if (IS_ZERO_256(l_token_item->total_supply))
         return true;     // Supply is unlimited
-    if (s_token_supply_limit_disable){
-        log_it(L_WARNING,"s_token_supply_limit_disable is enabled in config, please fix it and disable");
-        return false;
-    }
-
     if (compare256(l_token_item->current_supply, l_emission_value)>= 0){
         SUBTRACT_256_256(l_token_item->current_supply, l_emission_value, &l_token_item->current_supply);
         log_it(L_DEBUG,"New current supply %s for token %s",
             dap_chain_balance_print(l_token_item->current_supply), l_token_item->ticker);
     } else {
-            log_it(L_WARNING,"Token current supply %s lower, than emission value = %s",
-                dap_chain_balance_print(l_token_item->current_supply),
-                                        dap_chain_balance_print(l_emission_value));
-            return false;
-    }
-    // load ledger cache from GDB
-    // Get dap_chain_datum_token_t token object from GDB, key is token name
-    char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_TOKENS_STR);
-    size_t l_obj_length = 0;
-    dap_chain_datum_token_t *l_token_cache = (dap_chain_datum_token_t *)
-            dap_chain_global_db_gr_get(l_token_item->ticker, &l_obj_length, l_gdb_group);
-    if (!l_token_cache) {
-        if(s_debug_more)
-            log_it(L_WARNING, "Ledger cache mismatch");
-        DAP_DELETE(l_gdb_group);
+        log_it(L_WARNING,"Token current supply %s lower, than emission value = %s",
+            dap_chain_balance_print(l_token_item->current_supply),
+                                    dap_chain_balance_print(l_emission_value));
         return false;
     }
-    l_token_cache->header_simple.current_supply_256 = l_token_item->current_supply;
-    if (!dap_chain_global_db_gr_set(l_token_item->ticker, l_token_cache, l_obj_length, l_gdb_group)) {
-        if(s_debug_more)
-            log_it(L_WARNING, "Ledger cache mismatch");
-        DAP_DELETE(l_token_cache);
-        DAP_DELETE(l_gdb_group);
-        return false;
-    }
-    DAP_DELETE(l_token_cache);
-    DAP_DELETE(l_gdb_group);
-
     return true;
 }
 
@@ -1144,93 +1045,9 @@ void dap_chain_ledger_load_cache(dap_ledger_t *a_ledger)
 {
     dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger);
 
-    char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_TOKENS_STR);
+    char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_EMISSIONS_STR);
     size_t l_objs_count = 0;
     dap_global_db_obj_t *l_objs = dap_chain_global_db_gr_load(l_gdb_group, &l_objs_count);
-    for (size_t i = 0; i < l_objs_count; i++) {
-        dap_chain_ledger_token_item_t *l_token_item = DAP_NEW_Z(dap_chain_ledger_token_item_t);
-        strncpy(l_token_item->ticker, l_objs[i].key, sizeof(l_token_item->ticker) - 1);
-        l_token_item->ticker[sizeof(l_token_item->ticker) - 1] = '\0';
-        size_t l_token_size = l_objs[i].value_len;
-        l_token_item->datum_token = dap_chain_datum_token_read(l_objs[i].value, &l_token_size);
-        l_token_item->datum_token_size = l_objs[i].value_len;
-        pthread_rwlock_init(&l_token_item->token_emissions_rwlock, NULL);
-        l_token_item->type = l_token_item->datum_token->type;
-        // test tsd
-        // size_t signs_total = 0, signs_valid = 0, l_token_size_test = l_token_size - sizeof(dap_chain_datum_token_t) + sizeof(dap_chain_datum_token_old_t);
-        // dap_sign_t **sign = dap_chain_datum_token_simple_signs_parse( l_token_item->datum_token, l_token_size_test, &signs_total, &signs_valid);
-        // printf("---!!! dap_chain_ledger_load_cache() sign_type %d \n", ( (dap_sign_t *)sign[0])->header.type.type );
-
-        if (l_token_item->datum_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE) {
-            l_token_item->total_supply = GET_256_FROM_64(l_token_item->datum_token->header_simple.total_supply);
-            l_token_item->current_supply = GET_256_FROM_64(l_token_item->datum_token->header_simple.current_supply);
-            l_token_item->auth_signs_total = l_token_item->datum_token->header_simple.signs_total;
-            l_token_item->auth_signs_valid = l_token_item->datum_token->header_simple.signs_valid;
-            l_token_item->auth_signs_current = l_token_item->datum_token->header_simple.signs_current;
-        }  else if (l_token_item->datum_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE)
-        {
-            l_token_item->total_supply = l_token_item->datum_token->header_simple.total_supply_256;
-            l_token_item->current_supply = l_token_item->datum_token->header_simple.current_supply_256;
-            l_token_item->auth_signs_total = l_token_item->datum_token->header_simple.signs_total;
-            l_token_item->auth_signs_valid = l_token_item->datum_token->header_simple.signs_valid;
-            l_token_item->auth_signs_current = l_token_item->datum_token->header_simple.signs_current;
-            if (l_token_item->auth_signs_total)
-            {
-                l_token_item->auth_signs_pkey_hash = DAP_NEW_Z_SIZE(dap_chain_hash_fast_t,
-                                                                    sizeof(dap_chain_hash_fast_t) * l_token_item->auth_signs_total);
-                l_token_item->auth_signs= dap_chain_datum_token_simple_signs_parse(l_token_item->datum_token,l_token_item->datum_token_size,
-                                                                                    &l_token_item->auth_signs_total,
-                                                                                    &l_token_item->auth_signs_valid );
-                for (uint16_t k=0; k < l_token_item->auth_signs_current; k++) {
-                    dap_sign_get_pkey_hash(l_token_item->auth_signs[k], &l_token_item->auth_signs_pkey_hash[k]);
-                }
-            }
-        } else if (l_token_item->datum_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL)
-        {
-            l_token_item->total_supply = l_token_item->datum_token->header_private_decl.total_supply_256;
-            l_token_item->current_supply = l_token_item->datum_token->header_private_decl.current_supply_256;
-            l_token_item->auth_signs_total = l_token_item->datum_token->header_private_decl.signs_total;
-            l_token_item->auth_signs_valid = l_token_item->datum_token->header_private_decl.signs_valid;
-            l_token_item->auth_signs_current = l_token_item->datum_token->header_private_decl.signs_current;
-            if (l_token_item->auth_signs_total) {
-                l_token_item->auth_signs_pkey_hash = DAP_NEW_Z_SIZE(dap_chain_hash_fast_t,
-                                                                    sizeof(dap_chain_hash_fast_t) * l_token_item->auth_signs_total);
-
-                l_token_item->auth_signs= dap_chain_datum_token_simple_signs_parse(l_token_item->datum_token,l_token_item->datum_token_size,
-                                                                                    &l_token_item->auth_signs_total,
-                                                                                    &l_token_item->auth_signs_valid );
-                for (uint16_t k=0; k < l_token_item->auth_signs_current; k++) {
-                    dap_sign_get_pkey_hash(l_token_item->auth_signs[k], &l_token_item->auth_signs_pkey_hash[k]);
-                }
-            }
-        } else if (l_token_item->datum_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL)
-        {
-            l_token_item->total_supply = l_token_item->datum_token->header_native_decl.total_supply_256;
-            l_token_item->current_supply = l_token_item->datum_token->header_native_decl.current_supply_256;
-            l_token_item->auth_signs_total = l_token_item->datum_token->header_native_decl.signs_total;
-            l_token_item->auth_signs_valid = l_token_item->datum_token->header_native_decl.signs_valid;
-            l_token_item->auth_signs_current = l_token_item->datum_token->header_native_decl.signs_current;
-            if (l_token_item->auth_signs_total) {
-                l_token_item->auth_signs_pkey_hash = DAP_NEW_Z_SIZE(dap_chain_hash_fast_t,
-                                                                    sizeof(dap_chain_hash_fast_t) * l_token_item->auth_signs_total);
-
-                l_token_item->auth_signs= dap_chain_datum_token_simple_signs_parse(l_token_item->datum_token,l_token_item->datum_token_size,
-                                                                                    &l_token_item->auth_signs_total,
-                                                                                    &l_token_item->auth_signs_valid );
-                for (uint16_t k=0; k < l_token_item->auth_signs_current; k++) {
-                    dap_sign_get_pkey_hash(l_token_item->auth_signs[k], &l_token_item->auth_signs_pkey_hash[k]);
-                }
-            }
-        }
-
-        HASH_ADD_STR(l_ledger_pvt->tokens, ticker, l_token_item);
-    }
-    dap_chain_global_db_objs_delete(l_objs, l_objs_count);
-    DAP_DELETE(l_gdb_group);
-
-    l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_EMISSIONS_STR);
-    l_objs_count = 0;
-    l_objs = dap_chain_global_db_gr_load(l_gdb_group, &l_objs_count);
     for (size_t i = 0; i < l_objs_count; i++) {
         if (!l_objs[i].value_len)
             continue;
@@ -1250,7 +1067,6 @@ void dap_chain_ledger_load_cache(dap_ledger_t *a_ledger)
 
     l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_TXS_STR);
     l_objs_count = 0;
-    //uint8_t *l_result = dap_chain_global_db_gr_get("0xFB0770E29B59D588EF9FE0DAF6A9E9A14739797023C9C598C9708C8FC4922385", &l_objs_count, l_gdb_group);
     l_objs = dap_chain_global_db_gr_load(l_gdb_group, &l_objs_count);
     for (size_t i = 0; i < l_objs_count; i++) {
         dap_chain_ledger_tx_item_t *l_tx_item = DAP_NEW_Z(dap_chain_ledger_tx_item_t);
@@ -1329,71 +1145,6 @@ dap_ledger_t* dap_chain_ledger_create(uint16_t a_check_flags, char *a_net_name)
     return l_ledger;
 }
 
-/**
- * @brief
- *
- * @param l_add_addr01
- * @param l_add_addr02
- * @return true
- * @return false
- */
-bool s_chain_compare_token_addresses(dap_chain_addr_t * l_add_addr01, dap_chain_addr_t * l_add_addr02)
-{
-    if (!l_add_addr01 || !l_add_addr02)
-        return false;
-
-    //0 if equal
-    if (!memcmp(l_add_addr01,l_add_addr02,sizeof(dap_chain_addr_t)))
-        return true;
-
-    return false;
-}
-
-bool s_chain_ledger_token_tsd_check(dap_chain_ledger_token_item_t * l_token_item, dap_chain_datum_token_emission_t *a_token_emission)
-{
-    // for multiple tsd we need to parse every tsd in cycle
-    if (!l_token_item){
-        log_it(L_WARNING, "Token object is null. Probably, you set unknown token ticker in -token parameter of command");
-        return false;
-    }
-    //get fir tsd for next tsd getting
-    dap_tsd_t *l_tsd = dap_chain_datum_token_tsd_get(l_token_item->datum_token, l_token_item->datum_token_size);
-    if (!l_tsd)
-        return false;
-
-    dap_chain_addr_t *l_add_addr = NULL;
-    size_t l_tsd_size=0;
-    size_t l_tsd_total_size = l_token_item->datum_token->header_private_decl.tsd_total_size;
-
-    for( size_t l_offset=0; l_offset < l_tsd_total_size;  l_offset += l_tsd_size ){
-        l_tsd = (dap_tsd_t *) (((byte_t*)l_tsd ) +l_offset);
-        l_tsd_size = l_tsd? dap_tsd_size(l_tsd): 0;
-        if(l_tsd_size==0){
-            if(s_debug_more)
-                log_it(L_ERROR,"Wrong zero TSD size, exiting TSD parse");
-            break;
-        } else if (l_tsd_size + l_offset > l_tsd_total_size){
-            if(s_debug_more)
-                log_it(L_ERROR,"Wrong %zd TSD size, exiting TSD parse", l_tsd_size);
-            break;
-        }
-
-        switch(l_tsd->type){
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD:
-                l_add_addr = (dap_chain_addr_t *) l_tsd->data;
-                if (s_chain_compare_token_addresses(&a_token_emission->hdr.address, l_add_addr)){
-                    log_it(L_DEBUG, "Private tokens limitations for DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD flag were checked successfully");
-                    return true;
-                }
-                break;
-            default:
-                break;
-        }
-    }
-    log_it(L_WARNING, "Address %s is not allowed for emission for token %s", dap_chain_addr_to_str(&a_token_emission->hdr.address), l_token_item->ticker);
-    return false;
-}
-
 int dap_chain_ledger_token_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_token_emission, size_t a_token_emission_size)
 {
     int l_ret = 0;
@@ -1462,8 +1213,9 @@ int dap_chain_ledger_token_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_
             (l_token_item->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE) ||
             (l_token_item->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL) ||
              (l_token_item->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE)) {
-        if (!s_chain_ledger_token_tsd_check(l_token_item, l_emission))
-                return -5;
+        //s_ledger_permissions_check(l_token_item)
+        //    return -5;
+
     }
     switch (l_emission->hdr.type){
         case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_AUTH:{
@@ -1481,7 +1233,7 @@ int dap_chain_ledger_token_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_
                         dap_chain_hash_fast_t l_sign_pkey_hash;
                         dap_sign_get_pkey_hash(l_sign, &l_sign_pkey_hash);
                         // Find pkey in auth hashes
-                        for (uint16_t k=0; k< l_token_item->auth_signs_current; k++) {
+                        for (uint16_t k=0; k< l_token_item->auth_signs_total; k++) {
                             if (dap_hash_fast_compare(&l_sign_pkey_hash, &l_token_item->auth_signs_pkey_hash[k])) {
                                 // Verify if its token emission header signed
                                 if (dap_sign_verify(l_sign, &l_emission->hdr, sizeof(l_emission->hdr)) == 1) {
@@ -1556,12 +1308,12 @@ int dap_chain_ledger_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_
                     (l_token_item->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE) ||
                     (l_token_item->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL) ||
                     (l_token_item->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE))) {
-                if(!s_chain_ledger_token_tsd_check(l_token_item, (dap_chain_datum_token_emission_t*) a_token_emission))
-                    return -114;
+                //s_ledger_permissions_check(l_token_item)
+                //    return -114;
             }
 
             //update current_supply in ledger cache and ledger memory object
-            if(l_token_item && !s_update_token_cache(a_ledger, l_token_item, l_token_emission_item->datum_token_emission->hdr.value_256))
+            if(l_token_item && !s_update_token_cache(l_token_item, l_token_emission_item->datum_token_emission->hdr.value_256))
                 return -4;
 
             pthread_rwlock_wrlock(&l_token_item->token_emissions_rwlock);
@@ -1637,6 +1389,9 @@ int dap_chain_ledger_token_emission_load(dap_ledger_t *a_ledger, byte_t *a_token
             pthread_rwlock_unlock(&l_token_item->token_emissions_rwlock);
             if (l_token_emission_item) {
                 pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock);
+                dap_chain_datum_token_emission_t *l_ems = l_token_emission_item->datum_token_emission;
+                uint256_t l_value = (l_ems->hdr.version == 2) ? l_ems->hdr.value_256 : dap_chain_uint256_from(l_ems->hdr.value);
+                s_update_token_cache(l_token_item, l_value);
                 return 0;
             }
         }
diff --git a/modules/chain/include/dap_chain_ledger.h b/modules/chain/include/dap_chain_ledger.h
index c7d0900f14..85a1395502 100644
--- a/modules/chain/include/dap_chain_ledger.h
+++ b/modules/chain/include/dap_chain_ledger.h
@@ -115,7 +115,7 @@ int dap_chain_ledger_tx_add_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *
  *
  */
 
-int dap_chain_ledger_token_ticker_check(dap_ledger_t * a_ledger, const char *a_token_ticker);
+dap_chain_datum_token_t *dap_chain_ledger_token_ticker_check(dap_ledger_t * a_ledger, const char *a_token_ticker);
 
 /**
  * Add new token datum
diff --git a/modules/common/dap_chain_common.c b/modules/common/dap_chain_common.c
index 049296c3c9..24664b9305 100644
--- a/modules/common/dap_chain_common.c
+++ b/modules/common/dap_chain_common.c
@@ -626,7 +626,11 @@ uint32_t l_tmp[4];
     /* 456 - > "456" */
     l_cp2 = l_cp;
     l_nibble = a_uint256.lo;
-    do { *(l_cp++) = (l_nibble % 10) + '0'; } while (l_nibble /= 10);
+
+    do {
+        *(l_cp2++) = (l_nibble % 10) + '0';
+    } while (l_nibble /= 10);
+
 
     l_len = l_cp2 - l_cp;
     l_len = l_len / 2;
@@ -641,8 +645,7 @@ uint32_t l_tmp[4];
         *l_cpe = l_chr;
     }
 
-    if ( a_uint256.hi && (DAP_CHAIN$SZ_MAX128DEC > (l_len = l_cp2 - l_cp)) )    /* Insert zeroes if hi part of the digit is not zero */
-    {
+    if (  DAP_CHAIN$SZ_MAX128DEC > (l_len = l_cp2 - l_cp) ) {
         /* "123456" -> 123000...000456" */
         memmove(l_cp + ( DAP_CHAIN$SZ_MAX128DEC - l_len), l_cp, l_len);
         memset(l_cp, '0', ( DAP_CHAIN$SZ_MAX128DEC - l_len));
diff --git a/modules/common/dap_chain_datum_token.c b/modules/common/dap_chain_datum_token.c
index 596f585e08..e8d2850c4c 100644
--- a/modules/common/dap_chain_datum_token.c
+++ b/modules/common/dap_chain_datum_token.c
@@ -25,6 +25,7 @@
 #include <string.h>
 #include "dap_strfuncs.h"
 #include "dap_common.h"
+#include "dap_chain_datum.h"
 #include "dap_chain_datum_token.h"
 #include "dap_uuid.h"
 
@@ -65,56 +66,12 @@ const char *c_dap_chain_datum_token_flag_str[] = {
 dap_tsd_t* dap_chain_datum_token_tsd_get(dap_chain_datum_token_t *a_token, size_t a_token_size)
 {
     // Check if token type could have tsd section
-    size_t l_tsd_size;
     size_t l_hdr_size = sizeof(dap_chain_datum_token_t);
     if (l_hdr_size > a_token_size){
         log_it(L_WARNING, "Token size smaller then header, corrupted data");
         return NULL;
     }
-
-    switch( a_token->type){
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL: // 256
-            l_hdr_size = sizeof(dap_chain_datum_token_t);
-            l_tsd_size = a_token->header_private_decl.tsd_total_size;
-            break;
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE: // 256
-            l_hdr_size = sizeof(dap_chain_datum_token_t);
-            l_tsd_size = a_token->header_private_update.tsd_total_size;
-            break;
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL: // 256
-            l_hdr_size = sizeof(dap_chain_datum_token_t);
-            l_tsd_size = a_token->header_native_decl.tsd_total_size;
-            break;
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE: // 256
-            l_hdr_size = sizeof(dap_chain_datum_token_t);
-            l_tsd_size = a_token->header_native_update.tsd_total_size;
-            break;
-        default: return NULL;
-    }
-
-    if (l_tsd_size+l_hdr_size > a_token_size){
-        log_it(L_WARNING, "TSD size %zd overlaps with header, corrupted data", l_tsd_size);
-    }else if (l_tsd_size +l_hdr_size == a_token_size){
-        log_it(L_INFO, "No signatures at all, returning pointer to the top of data");
-        return (dap_tsd_t*) a_token->data_n_tsd;
-    }
-
-    // Pass through signatures to find top of TSD section
-    size_t l_offset = 0;
-    while( l_offset < (a_token_size - l_hdr_size-l_tsd_size) ){
-        dap_sign_t* l_sign = (dap_sign_t*) (a_token->data_n_tsd + l_offset);
-        if (l_sign->header.sign_size == 0){
-            log_it( L_WARNING, "Corrupted signature, 0 size");
-            return NULL;
-        }
-        l_offset += dap_sign_get_size( l_sign);
-    }
-    if ( l_offset + l_hdr_size +l_tsd_size <= a_token_size  )
-        return (dap_tsd_t*) (a_token->data_n_tsd+l_offset);
-    else{
-        log_it(L_WARNING, "Signatures overlaps with TSD section, corrupted data");
-        return NULL;
-    }
+    return (dap_tsd_t *)a_token->data_n_tsd;
 }
 
 dap_chain_datum_token_t *dap_chain_datum_token_read(byte_t *a_token_serial, size_t *a_token_size) {
@@ -132,17 +89,11 @@ dap_chain_datum_token_t *dap_chain_datum_token_read(byte_t *a_token_serial, size
         switch( l_token_type ){
             case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE: {
                 l_token->type = DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE; // 256
-                l_token->header_simple.total_supply_256 = GET_256_FROM_64(l_token_old->header_simple.total_supply);
-                l_token->header_simple.signs_valid = l_token_old->header_simple.signs_valid;
-                l_token->header_simple.signs_total = l_token_old->header_simple.signs_total;
+                l_token->total_supply = GET_256_FROM_64(l_token_old->header_simple.total_supply);
+                l_token->signs_valid = l_token_old->header_simple.signs_valid;
+                l_token->signs_total = l_token_old->header_simple.signs_total;
                 break;
             }
-            case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PUBLIC:
-                    l_token->type = DAP_CHAIN_DATUM_TOKEN_TYPE_PUBLIC; // 256
-                    l_token->header_public.total_supply_256 = GET_256_FROM_128(l_token_old->header_public.total_supply);
-                    l_token->header_public.premine_supply_256 = GET_256_FROM_128(l_token_old->header_public.premine_supply);
-                    memcpy(&l_token->header_public.premine_address, &l_token_old->header_public.premine_address, sizeof(l_token_old->header_public.premine_address));
-                break;
             default:
                 return NULL;
         }
@@ -217,23 +168,26 @@ void dap_chain_datum_token_certs_dump(dap_string_t * a_str_out, byte_t * a_data_
     }
 }
 
-dap_sign_t ** dap_chain_datum_token_simple_signs_parse(dap_chain_datum_token_t * a_datum_token, size_t a_datum_token_size, size_t *a_signs_total, size_t * a_signs_valid)
+dap_sign_t ** dap_chain_datum_token_signs_parse(dap_chain_datum_token_t * a_datum_token, size_t a_datum_token_size, size_t *a_signs_total, size_t * a_signs_valid)
 {
     assert(a_datum_token_size);
     assert(a_datum_token);
     assert(a_signs_total);
     assert(a_signs_valid);
     assert(a_datum_token_size >= sizeof(dap_chain_datum_token_old_t));
-    dap_sign_t ** l_ret = DAP_NEW_Z_SIZE(dap_sign_t*, sizeof (dap_sign_t*)*a_datum_token->header_simple.signs_current);
-    *a_signs_total=0;
-    *a_signs_valid = a_datum_token->header_simple.signs_valid;
+    dap_sign_t ** l_ret = DAP_NEW_Z_SIZE(dap_sign_t*, sizeof (dap_sign_t*)*a_datum_token->signs_total);
+    *a_signs_total = 0;
+    *a_signs_valid = a_datum_token->signs_valid;
     size_t l_offset = 0;
     uint16_t n = 0;
     size_t l_signs_offset = a_datum_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE
                                                  ? sizeof(dap_chain_datum_token_old_t)
                                                  : sizeof(dap_chain_datum_token_t);
-
-    while( l_offset < (a_datum_token_size - l_signs_offset) && n < a_datum_token->header_simple.signs_current ) {
+    if ((a_datum_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL) ||
+            (a_datum_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL)) {
+        l_signs_offset += a_datum_token->header_native_decl.tsd_total_size;
+    }
+    while( l_offset < (a_datum_token_size - l_signs_offset) && n < a_datum_token->signs_total ) {
         dap_sign_t *l_sign = (dap_sign_t *)((byte_t *)a_datum_token + l_signs_offset + l_offset);
         size_t l_sign_size = dap_sign_get_size(l_sign);
         if(!l_sign_size ){
@@ -383,5 +337,3 @@ bool dap_chain_datum_token_is_old(uint8_t a_type) {
             return false;
     }
 }
-
-
diff --git a/modules/common/include/dap_chain_datum_token.h b/modules/common/include/dap_chain_datum_token.h
index a5a5482d65..5cf13b6be7 100644
--- a/modules/common/include/dap_chain_datum_token.h
+++ b/modules/common/include/dap_chain_datum_token.h
@@ -65,81 +65,41 @@ typedef struct dap_chain_datum_token_old {
 typedef struct dap_chain_datum_token{
     uint16_t type;
     char ticker[DAP_CHAIN_TICKER_SIZE_MAX];
+    uint16_t signs_valid; // Emission auth signs
+    uint256_t total_supply;
     union {
         // Simple token declaration. Useful for 100% premined emission without any plays with token and owners after that
         struct {
-            union {
-                uint64_t total_supply; // Could be zero if unlimited
-                uint256_t total_supply_256;
-            };
-            union {
-                uint64_t current_supply; // Could be zero if unlimited
-                uint256_t current_supply_256;
-            };
-            uint16_t signs_valid; // Emission auth signs
-            uint16_t signs_total; // Emission auth signs
-            uint16_t field01; // empty field
-            uint64_t field02; // empty field
-            uint16_t signs_current;
+             // Nothing here
         } DAP_ALIGN_PACKED header_simple;
         // Private token declarations, with flags, manipulations and updates
         struct {
-            union {
-                uint64_t total_supply; // Could be zero if unlimited
-                uint256_t total_supply_256;
-            };
-            union {
-                uint64_t current_supply; // Could be zero if unlimited
-                uint256_t current_supply_256;
-            };
-            uint16_t signs_valid; // Emission auth signs
-            uint16_t signs_total; // Emission auth signs
             uint16_t flags; // Token declaration flags
             uint64_t tsd_total_size; // Data size section with values in key-length-value list trailing the signs section
-            uint16_t signs_current;
         } DAP_ALIGN_PACKED header_private_decl;
         //native tokens
         struct {
-            union {
-                uint64_t total_supply; // Could be zero if unlimited
-                uint256_t total_supply_256;
-            };
-            union {
-                uint64_t current_supply; // Could be zero if unlimited
-                uint256_t current_supply_256;
-            };
-            uint16_t signs_valid; // Emission auth signs
-            uint16_t signs_total; // Emission auth signs
             uint16_t flags; // Token declaration flags
             uint64_t tsd_total_size; // Data size section with values in key-length-value list trailing the signs section
-            uint16_t signs_current;
             uint16_t decimals;
         } DAP_ALIGN_PACKED header_native_decl;
         // Private token update
         struct {
-            uint16_t padding;
             uint64_t tsd_total_size; // Data size section with extended values in key-length-value list.
         } DAP_ALIGN_PACKED header_private_update;
         // native token update
         struct {
-            uint16_t padding;
             uint64_t tsd_total_size; // Data size section with extended values in key-length-value list.
         } DAP_ALIGN_PACKED header_native_update;
         // Public token declaration
         struct {
-            union {
-                uint128_t total_supply;
-                uint256_t total_supply_256;
-            };
-            union {
-                uint128_t premine_supply;
-                uint256_t premine_supply_256;
-            };
-            dap_chain_addr_t premine_address;
             uint32_t flags;
+            uint256_t premine_supply;
+            dap_chain_addr_t premine_address;
         } DAP_ALIGN_PACKED header_public;
-        byte_t free_space[256]; // For future changes
+        byte_t header[256]; // For future changes
     };
+    uint16_t signs_total; // Emission auth signs
     byte_t data_n_tsd[]; // Signs and/or types-size-data sections
 } DAP_ALIGN_PACKED dap_chain_datum_token_t;
 
@@ -459,7 +419,7 @@ extern const char *c_dap_chain_datum_token_emission_type_str[];
 dap_tsd_t* dap_chain_datum_token_tsd_get(dap_chain_datum_token_t * a_token,  size_t a_token_size);
 void dap_chain_datum_token_flags_dump(dap_string_t * a_str_out, uint16_t a_flags);
 void dap_chain_datum_token_certs_dump(dap_string_t * a_str_out, byte_t * a_data_n_tsd, size_t a_certs_size);
-dap_sign_t ** dap_chain_datum_token_simple_signs_parse(dap_chain_datum_token_t * a_datum_token, size_t a_datum_token_size, size_t *a_signs_count, size_t * a_signs_valid);
+dap_sign_t ** dap_chain_datum_token_signs_parse(dap_chain_datum_token_t * a_datum_token, size_t a_datum_token_size, size_t *a_signs_count, size_t * a_signs_valid);
 dap_chain_datum_token_t *dap_chain_datum_token_read(byte_t *a_token_serial, size_t *a_token_size);
 
 dap_chain_datum_token_emission_t *dap_chain_datum_emission_create(uint256_t a_value, const char *a_ticker, dap_chain_addr_t *a_addr);
diff --git a/modules/mempool/dap_chain_mempool.c b/modules/mempool/dap_chain_mempool.c
index 7160e16435..099cafae75 100644
--- a/modules/mempool/dap_chain_mempool.c
+++ b/modules/mempool/dap_chain_mempool.c
@@ -659,7 +659,7 @@ dap_chain_datum_token_emission_t *dap_chain_mempool_emission_get(dap_chain_t *a_
         DAP_DELETE(l_emission_hash_str_from_base58);
     }
     DAP_DELETE(l_gdb_group);
-    if (!l_emission)
+    if (!l_emission || l_emission->header.type_id != DAP_CHAIN_DATUM_TOKEN_EMISSION)
         return NULL;
     l_emission_size = l_emission_size - sizeof(l_emission->header);
     dap_chain_datum_token_emission_t *l_ret = dap_chain_datum_emission_read(l_emission->data, &l_emission_size);
@@ -667,6 +667,46 @@ dap_chain_datum_token_emission_t *dap_chain_mempool_emission_get(dap_chain_t *a_
     return l_ret;
 }
 
+dap_chain_datum_token_emission_t *dap_chain_mempool_datum_emission_extract(dap_chain_t *a_chain, byte_t *a_data, size_t a_size)
+{
+    if (!a_chain || !a_data || !a_size)
+        return NULL;
+    dap_chain_datum_t *l_datum = (dap_chain_datum_t *)a_data;
+    if ((l_datum->header.version_id != DAP_CHAIN_DATUM_VERSION) || (l_datum->header.type_id != DAP_CHAIN_DATUM_TOKEN_EMISSION) ||
+            ((l_datum->header.data_size + sizeof(l_datum->header)) != a_size))
+        return NULL;
+    dap_chain_datum_token_emission_t *l_emission = (dap_chain_datum_token_emission_t *)l_datum->data;
+    if (l_emission->hdr.type != DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_AUTH)
+        return NULL;
+    if (!l_emission->data.type_auth.signs_count)
+        return NULL;
+    char *l_ticker = l_emission->hdr.ticker;
+    if (l_ticker[DAP_CHAIN_TICKER_SIZE_MAX - 1])
+        return NULL;
+    dap_chain_net_t *l_net = dap_chain_net_by_name(a_chain->net_name);
+    if (!l_net)
+        return NULL;
+    dap_chain_datum_token_t *l_token = dap_chain_ledger_token_ticker_check(l_net->pub.ledger, l_ticker);
+    if (!l_token)
+        return NULL;
+    if (l_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL)
+        return NULL;
+    int l_signs_valid = 0;
+    dap_sign_t *l_token_sign = (dap_sign_t *)l_token->data_n_tsd;
+    for (int i = 0; i < l_token->signs_total; i++) {
+        uint32_t l_token_pkey_size = l_token_sign->header.sign_pkey_size;
+        dap_sign_t *l_ems_sign = (dap_sign_t *)(l_emission->tsd_n_signs + l_emission->data.type_auth.tsd_total_size);
+        for (int j = 0; j < l_emission->data.type_auth.signs_count; j++) {
+            if (l_token_pkey_size == l_ems_sign->header.sign_pkey_size &&
+                    !memcmp(l_token_sign->pkey_n_sign, l_ems_sign->pkey_n_sign, l_token_pkey_size))
+                l_signs_valid++;
+        }
+    }
+    if (l_signs_valid != l_emission->data.type_auth.signs_count)
+        return NULL;
+    return DAP_DUP_SIZE(l_emission, l_datum->header.data_size);
+}
+
 uint8_t* dap_datum_mempool_serialize(dap_datum_mempool_t *datum_mempool, size_t *size)
 {
     size_t a_request_size = 2 * sizeof(uint16_t), shift_size = 0;
diff --git a/modules/mempool/include/dap_chain_mempool.h b/modules/mempool/include/dap_chain_mempool.h
index 20118221f7..d24515666c 100644
--- a/modules/mempool/include/dap_chain_mempool.h
+++ b/modules/mempool/include/dap_chain_mempool.h
@@ -72,3 +72,4 @@ dap_chain_hash_fast_t *dap_chain_mempool_base_tx_create(dap_chain_t *a_chain, da
                                                         dap_chain_id_t a_emission_chain_id, uint256_t a_emission_value, const char *a_ticker,
                                                         dap_chain_addr_t *a_addr_to, dap_cert_t **a_certs, size_t a_certs_count);
 dap_chain_datum_token_emission_t *dap_chain_mempool_emission_get(dap_chain_t *a_chain, const char *a_emission_hash_str);
+dap_chain_datum_token_emission_t *dap_chain_mempool_datum_emission_extract(dap_chain_t *a_chain, byte_t *a_data, size_t a_size);
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index 7b8b3e417c..18dbf75695 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -2974,16 +2974,12 @@ void dap_chain_net_dump_datum(dap_string_t *a_str_out, dap_chain_datum_t *a_datu
             dap_string_append_printf(a_str_out, "ticker: %s\n", l_token->ticker);
             dap_string_append_printf(a_str_out, "size: %zd\n", l_token_size);
             switch (l_token->type) {
-                case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE:
+                //case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE:
                 case DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE:{
                     dap_string_append_printf(a_str_out, "type: SIMPLE\n");
-                    dap_string_append_printf(a_str_out, "sign_total: %hu\n", l_token->header_simple.signs_total );
-                    dap_string_append_printf(a_str_out, "sign_valid: %hu\n", l_token->header_simple.signs_valid );
-                    if ( dap_chain_datum_token_is_old(l_token->type) )
-                        dap_string_append_printf(a_str_out, "total_supply: %"DAP_UINT64_FORMAT_U"\n", l_token->header_simple.total_supply );
-                    else
-                        dap_string_append_printf(a_str_out, "total_supply: %s\n",
-                                                dap_chain_balance_print(l_token->header_simple.total_supply_256));
+                    dap_string_append_printf(a_str_out, "sign_total: %hu\n", l_token->signs_total );
+                    dap_string_append_printf(a_str_out, "sign_valid: %hu\n", l_token->signs_valid );
+                    dap_string_append_printf(a_str_out, "total_supply: %s\n", dap_chain_balance_print(l_token->total_supply));
                 }break;
                 case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE:{
                     dap_string_append_printf(a_str_out,"type: PRIVATE_UPDATE\n");
@@ -3167,7 +3163,7 @@ void dap_chain_net_dump_datum(dap_string_t *a_str_out, dap_chain_datum_t *a_datu
                     }
 
                     size_t l_certs_field_size = l_token_size - sizeof(*l_token) - l_token->header_private_decl.tsd_total_size;
-                    dap_chain_datum_token_certs_dump(a_str_out, l_token->data_n_tsd, l_certs_field_size);
+                    dap_chain_datum_token_certs_dump(a_str_out, l_token->data_n_tsd + l_token->header_private_decl.tsd_total_size, l_certs_field_size);
                 }break;
                 case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL:{
                     dap_string_append_printf(a_str_out,"type: CF20\n");
@@ -3243,7 +3239,7 @@ void dap_chain_net_dump_datum(dap_string_t *a_str_out, dap_chain_datum_t *a_datu
                     }
 
                     size_t l_certs_field_size = l_token_size - sizeof(*l_token) - l_token->header_native_decl.tsd_total_size;
-                    dap_chain_datum_token_certs_dump(a_str_out, l_token->data_n_tsd, l_certs_field_size);
+                    dap_chain_datum_token_certs_dump(a_str_out, l_token->data_n_tsd + l_token->header_native_decl.tsd_total_size, l_certs_field_size);
                 }break;
                 case DAP_CHAIN_DATUM_TX:{
                     dap_chain_datum_tx_t * l_tx =(dap_chain_datum_tx_t *) a_datum->data;
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index 5a6dfbec62..5af610f2a7 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -190,46 +190,6 @@ static dap_chain_node_addr_t* s_node_info_get_addr(dap_chain_net_t * a_net, dap_
     return l_address;
 }
 
-/**
- * @brief
- * sign data (datum_token) by certificates (1 or more)
- * successful count of signes return in l_sign_counter
- * @param l_certs - array with certificates loaded from dcert file
- * @param l_datum_token - updated pointer for l_datum_token variable after realloc
- * @param l_certs_count - count of certificate
- * @param l_datum_data_offset - offset of datum
- * @param l_sign_counter - counter of successful data signing operation
- * @return dap_chain_datum_token_t*
- */
-static dap_chain_datum_token_t * s_sign_cert_in_cycle(dap_cert_t ** l_certs, dap_chain_datum_token_t * l_datum_token, size_t l_certs_count,
-            size_t * l_datum_data_offset, uint32_t * l_sign_counter)
-{
-    if (!l_datum_data_offset)
-    {
-        log_it(L_DEBUG,"l_datum_data_offset is NULL");
-        return NULL;
-    }
-
-    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_simple), 0);
-
-        if (l_sign)
-        {
-            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);
-            log_it(L_DEBUG,"<-- Signed with '%s'", l_certs[i]->name);
-            *l_sign_counter += 1;
-        }
-    }
-
-    return l_datum_token;
-}
-
 /**
  * @brief node_info_read_and_reply
  * Read node from base
@@ -1946,6 +1906,49 @@ int dap_chain_node_cli_cmd_values_parse_net_chain(int *a_arg_index, int argc, ch
 
 }
 
+/**
+ * @brief
+ * sign data (datum_token) by certificates (1 or more)
+ * successful count of signes return in l_sign_counter
+ * @param l_certs - array with certificates loaded from dcert file
+ * @param l_datum_token - updated pointer for l_datum_token variable after realloc
+ * @param l_certs_count - count of certificate
+ * @param l_datum_data_offset - offset of datum
+ * @param l_sign_counter - counter of successful data signing operation
+ * @return dap_chain_datum_token_t*
+ */
+static dap_chain_datum_token_t * s_sign_cert_in_cycle(dap_cert_t ** l_certs, dap_chain_datum_token_t *l_datum_token, size_t l_certs_count,
+            size_t *l_datum_signs_offset, uint16_t * l_sign_counter)
+{
+    if (!l_datum_signs_offset) {
+        log_it(L_DEBUG,"l_datum_data_offset is NULL");
+        return NULL;
+    }
+
+    size_t l_tsd_size = 0;
+    if ((l_datum_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL) ||
+            (l_datum_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL))
+        l_tsd_size = l_datum_token->header_native_decl.tsd_total_size;
+
+    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) - sizeof(uint16_t), 0);
+
+        if (l_sign) {
+            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_signs_offset + l_sign_size);
+            memcpy(l_datum_token->data_n_tsd + *l_datum_signs_offset, l_sign, l_sign_size);
+            *l_datum_signs_offset += l_sign_size;
+            DAP_DELETE(l_sign);
+            log_it(L_DEBUG,"<-- Signed with '%s'", l_certs[i]->name);
+            (*l_sign_counter)++;
+        }
+    }
+
+    return l_datum_token;
+}
+
 /**
  * @brief com_token_decl_sign
  * @param argc
@@ -2010,8 +2013,7 @@ int com_token_decl_sign(int argc, char ** argv, char ** a_str_reply)
         if(!dap_strncmp(l_datum_hash_str, "0x", 2) || !dap_strncmp(l_datum_hash_str, "0X", 2)) {
             l_datum_hash_hex_str = dap_strdup(l_datum_hash_str);
             l_datum_hash_base58_str = dap_enc_base58_from_hex_str_to_str(l_datum_hash_str);
-        }
-        else {
+        } else {
             l_datum_hash_hex_str = dap_enc_base58_to_hex_str_from_str(l_datum_hash_str);
             l_datum_hash_base58_str = dap_strdup(l_datum_hash_str);
         }
@@ -2026,31 +2028,27 @@ int com_token_decl_sign(int argc, char ** argv, char ** a_str_reply)
 
         dap_chain_datum_t * l_datum = NULL;
         size_t l_datum_size = 0;
+        size_t l_tsd_size = 0;
         if((l_datum = (dap_chain_datum_t*) dap_chain_global_db_gr_get(
                 l_datum_hash_hex_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;
-
-                if (l_datum_token->header_simple.signs_valid == l_datum_token->header_simple.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 to it", l_datum_hash_out_str);
-                    DAP_DELETE(l_datum);
-                    DAP_DELETE(l_gdb_group_mempool);
-                    return -7;
-                }
+                dap_chain_datum_token_t *l_datum_token = DAP_DUP_SIZE(l_datum->data, l_datum->header.data_size);    // for realloc
+                DAP_DELETE(l_datum);
+                if ((l_datum_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL) ||
+                        (l_datum_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL))
+                    l_tsd_size = l_datum_token->header_native_decl.tsd_total_size;
                 // Check for signatures, are they all in set and are good enought?
                 size_t l_signs_size = 0, i = 1;
-                for (i = 1; i <= l_datum_token->header_simple.signs_current; i++){
-                    dap_sign_t *l_sign = (dap_sign_t *)(l_datum_token->data_n_tsd + l_signs_size);
-                    if( dap_sign_verify(l_sign, l_datum_token, sizeof(l_datum_token->header_simple)) != 1) {
+                for (i = 1; i <= l_datum_token->signs_total; i++){
+                    dap_sign_t *l_sign = (dap_sign_t *)(l_datum_token->data_n_tsd + l_tsd_size + l_signs_size);
+                    if( dap_sign_verify(l_sign, l_datum_token, sizeof(*l_datum_token) - sizeof(uint16_t)) != 1) {
                         log_it(L_WARNING, "Wrong signature %zu for datum_token with key %s in mempool!", i, l_datum_hash_out_str);
                         dap_chain_node_cli_set_reply_text(a_str_reply,
                                 "Datum %s with datum token has wrong signature %zu, break process and exit",
                                 l_datum_hash_out_str, i);
-                        DAP_DELETE(l_datum);
+                        DAP_DELETE(l_datum_token);
                         DAP_DELETE(l_gdb_group_mempool);
                         return -6;
                     }else{
@@ -2060,113 +2058,65 @@ int com_token_decl_sign(int argc, char ** argv, char ** a_str_reply)
                 }
 
                 log_it(L_DEBUG, "Datum %s with token declaration: %hu signatures are verified well (sign_size = %zu)",
-                                 l_datum_hash_out_str, l_datum_token->header_simple.signs_current, l_signs_size);
-
-                if (l_datum_token->header_simple.signs_total >= l_datum_token->header_simple.signs_valid + l_certs_count) {
-                    // Copy TSD sections to new location
-                    // rewrite to separate l_datum_token->header_private and l_datum_token->header_native
-                    size_t l_offset = 0;
-                    size_t l_tsd_size = 0 ;
-                    uint8_t *l_token_tsd = NULL;
-                    l_offset = l_signs_size;
-                    if (l_datum_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL || l_datum_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL)
-                    {
-                        l_tsd_size = l_datum_token->header_private_decl.tsd_total_size;
-                        l_token_tsd = DAP_NEW_SIZE(uint8_t, l_tsd_size);
-                        memcpy(l_token_tsd, l_datum_token->data_n_tsd + l_signs_size, l_tsd_size);
-                    }
-
-                    for(size_t i = 0; i < l_certs_count; i++) {
-                        // Add signs to token
-                        dap_sign_t * l_sign = dap_sign_create(l_certs[i]->enc_key,
-                                l_datum_token,
-                                sizeof(l_datum_token->header_simple), 0);
-                        size_t l_sign_size = dap_sign_get_size(l_sign);
-
-                        l_signs_size += l_sign_size;
-                        l_datum_size += l_sign_size;
-                        l_datum_token_size += l_sign_size;
-
-                        if ( (l_datum = DAP_REALLOC(l_datum, l_datum_size)) != NULL ) {
-                            // 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_n_tsd + l_offset, l_sign, l_sign_size);
-                            log_it(L_DEBUG, "Added datum token declaration sign with cert %s (new size %zu)",
-                                   l_certs[i]->name , l_datum_size);
-                            DAP_DELETE(l_sign);
-
-                            l_offset += l_sign_size;
-                            l_datum_token->header_simple.signs_current += 1;
-                        } else{
-                            log_it(L_ERROR, "Can't allocate more memory for datum token");
-                            return -81;
-                        }
-                    }
-                    // Return TSD sections to its place
-                    if (l_datum_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL || l_datum_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL)
-                    {
-                        memcpy(l_datum_token->data_n_tsd + l_signs_size, l_token_tsd, l_tsd_size);
-                        DAP_DELETE(l_token_tsd);
-                    }
+                                 l_datum_hash_out_str, l_datum_token->signs_total, l_signs_size);
+
+                // Sign header with all certificates in the list and add signs to the end of token update
+                uint16_t l_sign_counter;
+                size_t l_data_size = l_tsd_size + l_signs_size;
+                l_datum_token = s_sign_cert_in_cycle(l_certs, l_datum_token, l_certs_count, &l_data_size,
+                                                            &l_sign_counter);
+                l_datum_token->signs_total = l_sign_counter;
+                l_datum_size = sizeof(*l_datum_token) + l_data_size;
+                dap_chain_datum_t * l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_TOKEN_DECL,
+                                                                     l_datum_token, l_datum_size);
+                DAP_DELETE(l_datum_token);
+                // 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);
+                char * l_key_str_base58 = dap_enc_base58_encode_hash_to_str(&l_key_hash);
+                const char * l_key_out_str;
+                if(!dap_strcmp(l_hash_out_type,"hex"))
+                    l_key_out_str = l_key_str;
+                else
+                    l_key_out_str = l_key_str_base58;
 
-                    // Recalc hash, string and place new datum
+                // Add datum to mempool with datum_token hash as a key
+                if(dap_chain_global_db_gr_set(dap_strdup(l_key_str), (uint8_t *) l_datum, l_datum_size, l_gdb_group_mempool)) {
 
-                    // Calc datum's hash
-                    dap_chain_hash_fast_t l_key_hash={0};
-                    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);
-                    char * l_key_str_base58 = dap_enc_base58_encode_hash_to_str(&l_key_hash);
-                    const char * l_key_out_str;
-                    if(!dap_strcmp(l_hash_out_type,"hex"))
-                        l_key_out_str = l_key_str;
-                    else
-                        l_key_out_str = l_key_str_base58;
-
-                    // Add datum to mempool with datum_token hash as a key
-                    if(dap_chain_global_db_gr_set(dap_strdup(l_key_str), (uint8_t *) l_datum, l_datum_size, l_gdb_group_mempool)) {
-
-                        char* l_hash_str = l_datum_hash_hex_str;
-                        // Remove old datum from pool
-                        if( dap_chain_global_db_gr_del( dap_strdup(l_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_out_str, l_datum_hash_out_str, l_datum_hash_out_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_out_str, l_key_out_str);
-                            DAP_DELETE(l_datum);
-                            //DAP_DELETE(l_datum_token);
-                            DAP_DELETE(l_gdb_group_mempool);
-                            return 1;
-                        }
-                        DAP_DELETE(l_hash_str);
-                        DAP_DELETE(l_key_str);
-                        DAP_DELETE(l_key_str_base58);
-                    }
-                    else {
+                    char* l_hash_str = l_datum_hash_hex_str;
+                    // Remove old datum from pool
+                    if( dap_chain_global_db_gr_del( dap_strdup(l_hash_str) , l_gdb_group_mempool)) {
                         dap_chain_node_cli_set_reply_text(a_str_reply,
-                                "Error! datum %s produced from %s can't be placed in mempool",
+                                "datum %s is replacing the %s in datum pool",
                                 l_key_out_str, l_datum_hash_out_str);
+
                         DAP_DELETE(l_datum);
                         //DAP_DELETE(l_datum_token);
                         DAP_DELETE(l_gdb_group_mempool);
-                        DAP_DELETE(l_key_str);
-                        DAP_DELETE(l_key_str_base58);
-                        return -2;
+                        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_out_str, l_key_out_str);
+                        DAP_DELETE(l_datum);
+                        //DAP_DELETE(l_datum_token);
+                        DAP_DELETE(l_gdb_group_mempool);
+                        return 1;
                     }
-
+                    DAP_DELETE(l_hash_str);
+                    DAP_DELETE(l_key_str);
+                    DAP_DELETE(l_key_str_base58);
                 } else {
                     dap_chain_node_cli_set_reply_text(a_str_reply,
-                            "Error! Not enought place for new signature (%hu is left when we need %hu signatures)",
-                            l_datum_token->header_simple.signs_total - l_datum_token->header_simple.signs_valid, l_certs_count);
-                    return -6;
+                            "Error! datum %s produced from %s can't be placed in mempool",
+                            l_key_out_str, l_datum_hash_out_str);
+                    DAP_DELETE(l_datum);
+                    //DAP_DELETE(l_datum_token);
+                    DAP_DELETE(l_gdb_group_mempool);
+                    DAP_DELETE(l_key_str);
+                    DAP_DELETE(l_key_str_base58);
+                    return -2;
                 }
             } else {
                 dap_chain_node_cli_set_reply_text(a_str_reply,
@@ -2182,9 +2132,10 @@ int com_token_decl_sign(int argc, char ** argv, char ** a_str_reply)
         DAP_DELETE(l_datum_hash_hex_str);
         DAP_DELETE(l_datum_hash_base58_str);
     } else {
-        dap_chain_node_cli_set_reply_text(a_str_reply, "token_decl_sign need datum <datum hash> argument");
+        dap_chain_node_cli_set_reply_text(a_str_reply, "token_decl_sign need -datum <datum hash> argument");
         return -2;
     }
+    return 0;
 }
 
 /**
@@ -2572,7 +2523,8 @@ int com_token_update(int a_argc, char ** a_argv, char ** a_str_reply)
     uint32_t l_sign_counter = 0;
 
     switch(l_type){
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE:{ // 256
+        case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE: // 256
+        case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE: {
             dap_list_t *l_tsd_list = dap_list_alloc();
             size_t l_tsd_total_size = 0;
             l_arg_index++;
@@ -2721,11 +2673,10 @@ int com_token_update(int a_argc, char ** a_argv, char ** a_str_reply)
             l_datum_token_update->header_private_update.tsd_total_size = l_tsd_total_size;
 
             // Sign header with all certificates in the list and add signs to the end of token update
-            // Important:
-
-
-            l_datum_token_update = s_sign_cert_in_cycle(l_certs, l_datum_token_update, l_certs_count, &l_datum_data_offset,
+            uint16_t l_sign_counter;
+            l_datum_token_update = s_sign_cert_in_cycle(l_certs, l_datum_token_update, l_certs_count, &l_tsd_total_size,
                                                         &l_sign_counter);
+            l_datum_token_update->signs_total = l_sign_counter;
 
             // 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){
@@ -2888,7 +2839,7 @@ int com_token_decl(int a_argc, char ** a_argv, char ** a_str_reply)
     l_arg_index=dap_chain_node_cli_find_option_val(a_argv, 0, a_argc, "-token", &l_ticker);
     // Check for ticker
     if(!l_ticker) {
-        dap_chain_node_cli_set_reply_text(a_str_reply, "token_decl requires parameter 'token'");
+        dap_chain_node_cli_set_reply_text(a_str_reply, "token_decl requires parameter '-token'");
         return -2;
     }
 
@@ -2912,7 +2863,6 @@ int com_token_decl(int a_argc, char ** a_argv, char ** a_str_reply)
 
     dap_chain_datum_token_t * l_datum_token = NULL;
     size_t l_datum_data_offset = 0;
-    uint32_t l_sign_counter = 0;
 
     // Certificates thats will be used to sign currend datum token
     dap_chain_node_cli_find_option_val(a_argv, 0, a_argc, "-certs", &l_certs_str);
@@ -3080,50 +3030,28 @@ int com_token_decl(int a_argc, char ** a_argv, char ** a_str_reply)
                                                             DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD, l_arg_param);
                     l_tsd_list = dap_list_append( l_tsd_list, l_tsd);
                     l_tsd_total_size+= dap_tsd_size( l_tsd);
-                } else {
-                     dap_chain_node_cli_set_reply_text(a_str_reply, "Unknown param \"%s\"",a_argv[l_arg_index]);
-                     return -20;
                 }
                 l_arg_index+=2;
             }
 
-            // 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_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 = l_type;
-
             if (l_type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL) {
                 log_it(L_DEBUG,"Prepeared TSD sections for private token on %zd total size", l_tsd_total_size);
                 dap_snprintf(l_datum_token->ticker, sizeof(l_datum_token->ticker), "%s", l_ticker);
                 l_datum_token->header_private_decl.flags = l_flags;
-                l_datum_token->header_private_decl.total_supply_256 = l_total_supply;
-                l_datum_token->header_private_decl.current_supply_256 = l_total_supply;
-                l_datum_token->header_private_decl.signs_total = l_signs_total;
-                l_datum_token->header_private_decl.signs_valid = l_signs_emission;
+                l_datum_token->total_supply = l_total_supply;
+                l_datum_token->signs_valid = l_signs_emission;
+                l_datum_token->header_private_decl.tsd_total_size = l_tsd_total_size;
             } else { //DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL
                 log_it(L_DEBUG,"Prepeared TSD sections for CF20 token on %zd total size", l_tsd_total_size);
                 dap_snprintf(l_datum_token->ticker, sizeof(l_datum_token->ticker), "%s", l_ticker);
                 l_datum_token->header_native_decl.flags = l_flags;
-                l_datum_token->header_native_decl.total_supply_256 = uint256_0;
-                l_datum_token->header_native_decl.current_supply_256 = uint256_0;
-                l_datum_token->header_native_decl.signs_total = l_signs_total;
-                l_datum_token->header_native_decl.signs_valid = l_signs_emission;
+                l_datum_token->signs_valid = l_signs_emission;
+                l_datum_token->header_native_decl.tsd_total_size = l_tsd_total_size;
                 l_datum_token->header_native_decl.decimals = atoi(l_decimals_str);
             }
-
-            // Sign header with all certificates in the list and add signs to the end of ticker declaration
-            // Important:
-
-            l_datum_token = s_sign_cert_in_cycle(l_certs, l_datum_token, l_certs_count, &l_datum_data_offset, &l_sign_counter);
-
-            if (l_type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL)
-                l_datum_token->header_private_decl.signs_current = l_sign_counter;
-            else  //DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL
-                l_datum_token->header_native_decl.signs_current = l_sign_counter;
-
             // 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_tsd_t * l_tsd = (dap_tsd_t *) l_iter->data;
@@ -3164,48 +3092,35 @@ int com_token_decl(int a_argc, char ** a_argv, char ** a_str_reply)
                     default: log_it(L_DEBUG, "== 0x%04X: binary data %u size ",l_tsd->type, l_tsd->size );
                 }
                 size_t l_tsd_size = dap_tsd_size( l_tsd);
-                //add realloc: size of token header + sizeof signed data s_sign_cert_in_cycle + n * l_tsd_size
-                l_datum_token = DAP_REALLOC(l_datum_token, sizeof(dap_chain_datum_token_t) + l_datum_data_offset + l_tsd_size);
                 memcpy(l_datum_token->data_n_tsd + l_datum_data_offset, l_tsd, l_tsd_size);
-                if ( l_type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL) {
-                    l_datum_token->header_private_decl.tsd_total_size += l_tsd_size;
-                } else {
-                    l_datum_token->header_native_decl.tsd_total_size += l_tsd_size;
-                }
                 l_datum_data_offset += l_tsd_size;
             }
             log_it(L_DEBUG, "%s token declaration '%s' initialized", l_type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL ?
                             "Ptivate" : "CF20", l_datum_token->ticker);
         }break;
         case DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE: { // 256
-            // 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;
-
-            // Sign header with all certificates in the list and add signs to the end of ticker declaration
-            // Important:
-
             l_datum_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, sizeof(dap_chain_datum_token_t));
             l_datum_token->type = DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE; // 256
             dap_snprintf(l_datum_token->ticker, sizeof(l_datum_token->ticker), "%s", l_ticker);
-            l_datum_token->header_simple.total_supply_256 = l_total_supply;
-            l_datum_token->header_simple.current_supply_256 = l_total_supply;
-            l_datum_token->header_simple.signs_total = l_signs_total;
-            l_datum_token->header_simple.signs_valid = l_signs_emission;
-
-            // Create new datum token
-            l_datum_token = s_sign_cert_in_cycle(l_certs, l_datum_token, l_certs_count, &l_datum_data_offset, &l_sign_counter);
-            l_datum_token->header_simple.signs_current = l_sign_counter;
+            l_datum_token->total_supply = l_total_supply;
+            l_datum_token->signs_valid = l_signs_emission;
         }break;
         default:
             dap_chain_node_cli_set_reply_text(a_str_reply,
                     "Unknown token type");
             return -8;
     }
+    // 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;
+    // Sign header with all certificates in the list and add signs to the end of TSD cetions
+    uint16_t l_sign_counter;
+    l_datum_token = s_sign_cert_in_cycle(l_certs, l_datum_token, l_certs_count, &l_datum_data_offset, &l_sign_counter);
+    l_datum_token->signs_total = l_sign_counter;
 
     // We skip datum creation opeartion, if count of signed certificates in s_sign_cert_in_cycle is 0.
     // Usually it happen, when certificate in token_decl or token_update command doesn't contain private data or broken
-    if (l_sign_counter == 0){
+    if (!l_datum_token || l_datum_token->signs_total == 0){
         dap_chain_node_cli_set_reply_text(a_str_reply,
                     "Token declaration failed. Successful count of certificate signing is 0");
             return -9;
diff --git a/modules/net/dap_chain_node_cli_cmd_tx.c b/modules/net/dap_chain_node_cli_cmd_tx.c
index 5dc333bd87..988d2ae8fc 100644
--- a/modules/net/dap_chain_node_cli_cmd_tx.c
+++ b/modules/net/dap_chain_node_cli_cmd_tx.c
@@ -854,6 +854,76 @@ char* dap_db_history_addr(dap_chain_addr_t * a_addr, dap_chain_t * a_chain, cons
     return l_ret_str;
 }
 
+
+static char *s_token_info_print(dap_chain_datum_t *a_datum, const char *a_hash_out_type)
+{
+    dap_string_t *l_str_out = dap_string_new(NULL);
+    char l_time_str[70];
+    // get time of create datum
+    if (dap_time_to_str_rfc822(l_time_str, 70, a_datum->header.ts_create) < 1)
+        l_time_str[0] = '\0';
+    size_t l_token_size = a_datum->header.data_size;
+    dap_chain_datum_token_t *l_token = dap_chain_datum_token_read(a_datum->data, &l_token_size);
+    dap_chain_hash_fast_t l_token_hash = {};
+    dap_hash_fast(a_datum->data, a_datum->header.data_size, &l_token_hash);
+    char *l_out_hash_str;
+    if (!strcmp(a_hash_out_type, "hex"))
+        l_out_hash_str = dap_chain_hash_fast_to_str_new(&l_token_hash);
+    else
+        l_out_hash_str = dap_enc_base58_encode_hash_to_str(&l_token_hash);
+    dap_string_append(l_str_out, l_out_hash_str);
+    dap_string_append(l_str_out, "\n");
+    dap_string_append_printf(l_str_out, "Token %s, created: %s\n", l_token->ticker, l_time_str);
+    switch (l_token->type) {
+        // Simple private token decl
+        case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE:
+        case DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE: // 256
+        case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL: // 256
+            dap_string_append_printf(l_str_out, "  total_supply: %s(%s), signs: valid/total %02d/%02d \n",
+                        dap_chain_balance_to_coins(l_token->total_supply),
+                        dap_chain_balance_print(l_token->total_supply),
+                        l_token->signs_valid, l_token->signs_total);
+            if (l_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL) {
+                dap_string_append_printf(l_str_out, "  tsd_total_size: %"DAP_UINT64_FORMAT_U", flags: 0x%x \n",
+                        l_token->header_native_decl.tsd_total_size,
+                        l_token->header_native_decl.flags);
+            }
+            break;
+        case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL: // 256
+            dap_string_append_printf(l_str_out, "  tsd_total_size: %"DAP_UINT64_FORMAT_U", flags: 0x%x \n",
+                    l_token->header_private_decl.tsd_total_size,
+                    l_token->header_private_decl.flags);
+            break;
+        case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE: // 256
+            dap_string_append_printf(l_str_out, "  tsd_total_size: %"DAP_UINT64_FORMAT_U"\n",
+                    l_token->header_private_update.tsd_total_size);
+            break;
+        case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE: // 256
+            dap_string_append_printf(l_str_out, "  tsd_total_size: %"DAP_UINT64_FORMAT_U"\n",
+                    l_token->header_native_update.tsd_total_size);
+            break;
+        case DAP_CHAIN_DATUM_TOKEN_TYPE_PUBLIC: { // 256
+            char *l_addr = dap_chain_addr_to_str(&l_token->header_public.premine_address);
+            char * l_balance = dap_chain_balance_to_coins(l_token->total_supply);
+            dap_string_append_printf(l_str_out,
+                    " total_supply: %s(%s), flags: 0x%x\n, premine_supply: %s, premine_address '%s'\n",
+                    l_balance,
+                    dap_chain_balance_print(l_token->total_supply),
+                    l_token->header_public.flags,
+                    dap_chain_balance_print(l_token->header_public.premine_supply),
+                    l_addr ? l_addr : "-");
+            DAP_DELETE(l_addr);
+            DAP_DELETE(l_balance);
+        }break;
+        default:
+            dap_string_append_printf(l_str_out, "Unknown token type: 0x%x\n", l_token->type);
+            break;
+    }
+    dap_string_append_printf(l_str_out, "\n");
+    char *l_ret_str = l_str_out ? dap_string_free(l_str_out, false) : NULL;
+    return l_ret_str;
+}
+
 /**
  * @brief char* dap_db_history_token_list
  * 
@@ -883,91 +953,10 @@ static char* dap_db_history_token_list(dap_chain_t * a_chain, const char *a_toke
                 dap_chain_datum_t *l_datum = l_datums[l_datum_n];
                 if (!l_datum || l_datum->header.type_id != DAP_CHAIN_DATUM_TOKEN_DECL)
                     continue;
-                char l_time_str[70];
-                // get time of create datum
-                if (dap_time_to_str_rfc822(l_time_str, 70, l_datum->header.ts_create) < 1)
-                    l_time_str[0] = '\0';
-                size_t l_token_size = l_datum->header.data_size;
-                dap_chain_datum_token_t *l_token = dap_chain_datum_token_read(l_datum->data, &l_token_size);
-                if (!a_token_name || !dap_strcmp(l_token->ticker, a_token_name)) {
-                    dap_chain_hash_fast_t l_datum_hash = {};
-                    dap_hash_fast(l_datum, dap_chain_datum_size(l_datum), &l_datum_hash);
-                    char *l_out_hash_str;
-                    if (!strcmp(a_hash_out_type, "hex"))
-                        l_out_hash_str = dap_chain_hash_fast_to_str_new(&l_datum_hash);
-                    else
-                        l_out_hash_str = dap_enc_base58_encode_hash_to_str(&l_datum_hash);
-                    dap_string_append(l_str_out, l_out_hash_str);
-                    dap_string_append(l_str_out, "\n");
-                    dap_string_append_printf(l_str_out, "Token %s, created: %s\n", l_token->ticker, l_time_str);
-                    switch (l_token->type) {
-                        // Simple private token decl
-                        case DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE: // 256
-                           dap_string_append_printf(l_str_out, "  total_supply: %s(%s), signs: valid/total %02d/%02d \n",
-                                    dap_chain_balance_to_coins(l_token->header_simple.total_supply_256),
-                                    dap_chain_balance_print(l_token->header_simple.total_supply_256),
-                                    l_token->header_simple.signs_valid, l_token->header_simple.signs_total);
-                            break;
-                        case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE:
-                            dap_string_append_printf(l_str_out, "  total_supply: %.0Lf(%"DAP_UINT64_FORMAT_U"), signs: valid/total %02d/%02d \n",
-                                    dap_chain_datoshi_to_coins(l_token->header_simple.total_supply),
-                                    l_token->header_simple.total_supply,
-                                    l_token->header_simple.signs_valid, l_token->header_simple.signs_total);
-                            break;
-                        case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL: // 256
-                            dap_string_append_printf(l_str_out, "  tsd_total_size: %"DAP_UINT64_FORMAT_U", flags: 0x%x \n",
-                                    l_token->header_private_decl.tsd_total_size,
-                                    l_token->header_private_decl.flags);
-                            break;
-                        case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL: // 256
-                            dap_string_append_printf(l_str_out, "  tsd_total_size: %"DAP_UINT64_FORMAT_U", flags: 0x%x \n",
-                                    l_token->header_native_decl.tsd_total_size,
-                                    l_token->header_native_decl.flags);
-                            break;
-                        case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE: // 256
-                            dap_string_append_printf(l_str_out, "  tsd_total_size: %"DAP_UINT64_FORMAT_U"\n",
-                                    l_token->header_private_update.tsd_total_size);
-                            break;
-                        case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE: // 256
-                            dap_string_append_printf(l_str_out, "  tsd_total_size: %"DAP_UINT64_FORMAT_U"\n",
-                                    l_token->header_native_update.tsd_total_size);
-                            break;
-                        case DAP_CHAIN_DATUM_TOKEN_TYPE_PUBLIC: { // 256
-                            char *l_addr = dap_chain_addr_to_str(&l_token->header_public.premine_address);
-                            char * l_balance = dap_chain_balance_to_coins(l_token->header_public.total_supply_256);
-                            dap_string_append_printf(l_str_out,
-                                    " total_supply: %s(%s), flags: 0x%x\n, premine_supply: %s, premine_address '%s'\n",
-                                    dap_chain_balance_to_coins(l_token->header_public.total_supply_256),
-                                    dap_chain_balance_print(l_token->header_public.total_supply_256),
-                                    l_token->header_public.flags,
-                                    dap_chain_balance_print(l_token->header_public.premine_supply_256),
-                                    l_addr ? l_addr : "-");
-                            DAP_DELETE(l_addr);
-                            DAP_DELETE(l_balance);
-                        }break;
-                        case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PUBLIC: {
-                            char *l_addr = dap_chain_addr_to_str(&l_token->header_public.premine_address);
-                            char * l_balance = dap_chain_balance_to_coins(dap_chain_uint256_from_uint128(
-                                                                              l_token->header_public.total_supply));
-                            dap_string_append_printf(l_str_out,
-                                    " total_supply: %s(%s), flags: 0x%x\n, premine_supply: %s, premine_address '%s'\n",
-                                    l_balance,
-                                    dap_chain_balance_print(dap_chain_uint256_from_uint128(
-                                                                l_token->header_public.total_supply)),
-                                    l_token->header_public.flags,
-                                    dap_chain_balance_print(dap_chain_uint256_from_uint128(
-                                                                l_token->header_public.premine_supply)),
-                                    l_addr ? l_addr : "-");
-                            DAP_DELETE(l_addr);
-                            DAP_DELETE(l_balance);
-                        }break;
-                        default:
-                            dap_string_append_printf(l_str_out, "Unknown token type: 0x%x\n", l_token->type);
-                            break;
-                    }
-                    dap_string_append_printf(l_str_out, "\n");
-                    (*a_token_num)++;
-                }
+                if (!a_token_name && dap_strcmp(((dap_chain_datum_token_t *)l_datum->data)->ticker, a_token_name))
+                    continue;
+                dap_string_append_printf(l_str_out, s_token_info_print(l_datum, a_hash_out_type));
+                (*a_token_num)++;
             }
             DAP_DELETE(l_datums);
         }
@@ -1043,76 +1032,10 @@ static char* dap_db_history_filter(dap_chain_t * a_chain, dap_ledger_t *a_ledger
                         break;
                     }
                     if(!a_filter_token_name || !dap_strcmp(l_token->ticker, a_filter_token_name)) {
-                        dap_string_append_printf(l_str_out, "token %s, created: %s\n", l_token->ticker, l_time_str);
-                        switch (l_token->type) {
-                        // Simple private token decl
-                            case DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE: // 256
-                                dap_string_append_printf(l_str_out, "  256bit total_supply: %s(%s), signs: valid/total %02d/%02d \n",
-                                        dap_chain_balance_to_coins(l_token->header_simple.total_supply_256),
-                                        dap_chain_balance_print(l_token->header_simple.total_supply_256),
-                                        l_token->header_simple.signs_valid, l_token->header_simple.signs_total);
-                                break;
-                            case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE:
-                                dap_string_append_printf(l_str_out, "  total_supply: %.0Lf(%"DAP_UINT64_FORMAT_U"), signs: valid/total %02d/%02d \n",
-                                        dap_chain_datoshi_to_coins(l_token->header_simple.total_supply),
-                                        l_token->header_simple.total_supply,
-                                        l_token->header_simple.signs_valid, l_token->header_simple.signs_total);
-                                break;
-                            case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL: // 256
-                                dap_string_append_printf(l_str_out, "256bit  tsd_total_size: %"DAP_UINT64_FORMAT_U", flags: 0x%x \n",
-                                        l_token->header_private_decl.tsd_total_size,
-                                        l_token->header_private_decl.flags);
-                                break;
-                            case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL: // 256
-                                dap_string_append_printf(l_str_out, "256bit  tsd_total_size: %"DAP_UINT64_FORMAT_U", flags: 0x%x \n",
-                                        l_token->header_private_decl.tsd_total_size,
-                                        l_token->header_private_decl.flags);
-                                break;
-                            case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE: // 256
-                                dap_string_append_printf(l_str_out, "256bit  tsd_total_size: %"DAP_UINT64_FORMAT_U"\n",
-                                        l_token->header_private_update.tsd_total_size);
-                                break;
-                            case DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE: // 256
-                                dap_string_append_printf(l_str_out, "256bit  tsd_total_size: %"DAP_UINT64_FORMAT_U"\n",
-                                        l_token->header_native_update.tsd_total_size);
-                                break;
-                            case DAP_CHAIN_DATUM_TOKEN_TYPE_PUBLIC: { // 256
-                                char *l_addr = dap_chain_addr_to_str(&l_token->header_public.premine_address);
-                                dap_string_append_printf(l_str_out,
-                                        " total_supply: %s(%s), flags: 0x%x\n, premine_supply: %s, premine_address '%s'\n",
-                                        dap_chain_balance_to_coins(l_token->header_public.total_supply_256),
-                                        dap_chain_balance_print(l_token->header_public.total_supply_256),
-                                        l_token->header_public.flags,
-                                        dap_chain_balance_print(l_token->header_public.premine_supply_256),
-                                        l_addr ? l_addr : "-");
-                                DAP_DELETE(l_addr);
-                            } break;
-                            case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PUBLIC: {
-                                char *l_addr = dap_chain_addr_to_str(&l_token->header_public.premine_address);
-                                char * l_balance = dap_chain_balance_to_coins(dap_chain_uint256_from_uint128(
-                                                                                  l_token->header_public.total_supply));
-                                dap_string_append_printf(l_str_out,
-                                        " total_supply: %s(%s), flags: 0x%x\n, premine_supply: %s, premine_address '%s'\n",
-                                        l_balance,
-                                        dap_chain_balance_print(dap_chain_uint256_from_uint128(
-                                                                    l_token->header_public.total_supply)),
-                                        l_token->header_public.flags,
-                                        dap_chain_balance_print(dap_chain_uint256_from_uint128(
-                                                                    l_token->header_public.premine_supply)),
-                                        l_addr ? l_addr : "-");
-                                DAP_DELETE(l_addr);
-                                DAP_DELETE(l_balance);
-                            } break;
-                            default:
-                                dap_string_append_printf(l_str_out, "unknown token type: 0x%x\n", l_token->type);
-                                break;
-
-                        }
-                        dap_string_append_printf(l_str_out, "\n");
+                        dap_string_append_printf(l_str_out, s_token_info_print(l_datum, a_hash_out_type));
                         l_token_num++;
                     }
-                }
-                    break;
+                } break;
 
                 // emission
                 case DAP_CHAIN_DATUM_TOKEN_EMISSION: {
-- 
GitLab