From 08a22ad97dff3be072efb92978bcba9bfc1bec23 Mon Sep 17 00:00:00 2001
From: "daniil.frolov" <daniil.frolov@demlabs.net>
Date: Sun, 12 Jan 2025 12:55:20 +0300
Subject: [PATCH 01/18] [+] Created function int
 dap_chain_net_tx_create_by_json [+] Created function dap_chain_tx_tx_to_json

---
 dap-sdk                                      |    2 +-
 modules/net/dap_chain_net_tx.c               | 1045 ++++++++++++++++++
 modules/net/dap_chain_node_cli_cmd.c         |  855 +-------------
 modules/net/include/dap_chain_net_tx.h       |   30 +-
 modules/net/include/dap_chain_node_cli_cmd.h |   13 +-
 5 files changed, 1107 insertions(+), 838 deletions(-)

diff --git a/dap-sdk b/dap-sdk
index d6b6934683..5931f83c88 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit d6b6934683168160e7d25647ceef59d9439de2c3
+Subproject commit 5931f83c8894be1f78e4888ef39873fc87aa4df2
diff --git a/modules/net/dap_chain_net_tx.c b/modules/net/dap_chain_net_tx.c
index 7dd4b97464..5dd03126af 100644
--- a/modules/net/dap_chain_net_tx.c
+++ b/modules/net/dap_chain_net_tx.c
@@ -30,6 +30,12 @@
 #include "dap_chain_datum_tx_in_cond.h"
 #include "dap_chain_tx.h"
 #include "dap_list.h"
+#include "dap_chain_datum_tx_receipt.h"
+#include "dap_chain_wallet.h"
+#include "dap_chain_datum_tx_voting.h"
+#include "json.h"
+#include "dap_chain_net_srv.h"
+#include "dap_enc_base64.h"
 
 #define LOG_TAG "dap_chain_net_tx"
 
@@ -538,3 +544,1042 @@ bool dap_chain_net_tx_set_fee(dap_chain_net_id_t a_net_id, uint256_t a_value, da
 
     return true;
 }
+
+static const char* s_json_get_text(struct json_object *a_json, const char *a_key)
+{
+    if(!a_json || !a_key)
+        return NULL;
+    struct json_object *l_json = json_object_object_get(a_json, a_key);
+    if(l_json && json_object_is_type(l_json, json_type_string)) {
+        // Read text
+        return json_object_get_string(l_json);
+    }
+    return NULL;
+}
+
+static bool s_json_get_int64(struct json_object *a_json, const char *a_key, int64_t *a_out)
+{
+    if(!a_json || !a_key || !a_out)
+        return false;
+    struct json_object *l_json = json_object_object_get(a_json, a_key);
+    if(l_json) {
+        if(json_object_is_type(l_json, json_type_int)) {
+            // Read number
+            *a_out = json_object_get_int64(l_json);
+            return true;
+        }
+    }
+    return false;
+}
+
+static bool s_json_get_unit(struct json_object *a_json, const char *a_key, dap_chain_net_srv_price_unit_uid_t *a_out)
+{
+    const char *l_unit_str = s_json_get_text(a_json, a_key);
+    if(!l_unit_str || !a_out)
+        return false;
+    dap_chain_net_srv_price_unit_uid_t l_unit = dap_chain_net_srv_price_unit_uid_from_str(l_unit_str);
+    if(l_unit.enm == SERV_UNIT_UNDEFINED)
+        return false;
+    a_out->enm = l_unit.enm;
+    return true;
+}
+
+static bool s_json_get_uint256(struct json_object *a_json, const char *a_key, uint256_t *a_out)
+{
+    const char *l_uint256_str = s_json_get_text(a_json, a_key);
+    if(!a_out || !l_uint256_str)
+        return false;
+    uint256_t l_value = dap_chain_balance_scan(l_uint256_str);
+    if(!IS_ZERO_256(l_value)) {
+        memcpy(a_out, &l_value, sizeof(uint256_t));
+        return true;
+    }
+    return false;
+}
+
+// service names: srv_stake, srv_vpn, srv_xchange
+static bool s_json_get_srv_uid(struct json_object *a_json, const char *a_key_service_id, const char *a_key_service, uint64_t *a_out)
+{
+    uint64_t l_srv_id;
+    if(!a_out)
+        return false;
+    // Read service id
+    if(s_json_get_int64(a_json, a_key_service_id, (int64_t*) &l_srv_id)) {
+        *a_out = l_srv_id;
+        return true;
+    }
+    else {
+        // Read service as name
+        const char *l_service = s_json_get_text(a_json, a_key_service);
+        if(l_service) {
+            dap_chain_net_srv_t *l_srv = dap_chain_net_srv_get_by_name(l_service);
+            if(!l_srv)
+                return false;
+            *a_out = l_srv->uid.uint64;
+            return true;
+        }
+    }
+    return false;
+}
+
+static dap_chain_wallet_t* s_json_get_wallet(struct json_object *a_json, const char *a_key)
+{
+    return dap_chain_wallet_open(s_json_get_text(a_json, a_key), dap_chain_wallet_get_path(g_config), NULL);
+}
+
+static const dap_cert_t* s_json_get_cert(struct json_object *a_json, const char *a_key)
+{
+    return dap_cert_find_by_name(s_json_get_text(a_json, a_key));
+}
+
+// Read pkey from wallet or cert
+static dap_pkey_t* s_json_get_pkey(struct json_object *a_json)
+{
+    dap_pkey_t *l_pub_key = NULL;
+    // From wallet
+    dap_chain_wallet_t *l_wallet = s_json_get_wallet(a_json, "wallet");
+    if(l_wallet) {
+        l_pub_key = dap_chain_wallet_get_pkey(l_wallet, 0);
+        dap_chain_wallet_close(l_wallet);
+        if(l_pub_key) {
+            return l_pub_key;
+        }
+    }
+    // From cert
+    const dap_cert_t *l_cert = s_json_get_cert(a_json, "cert");
+    if(l_cert) {
+        l_pub_key = dap_pkey_from_enc_key(l_cert->enc_key);
+    }
+    return l_pub_key;
+}
+
+int dap_chain_net_tx_create_by_json(json_object *a_tx_json, dap_chain_net_t *a_net, json_object *a_json_obj_error, 
+                                        dap_chain_datum_tx_t** a_out_tx, size_t* a_items_count, size_t *a_items_ready, void **a_json_arr_reply)
+{
+
+    json_object *l_json = a_tx_json;
+    json_object *l_jobj_errors = a_json_obj_error ? a_json_obj_error : NULL;
+    
+    if (!a_tx_json)
+        return log_it(L_ERROR, "Empty json"), DAP_CHAIN_NET_TX_CREATE_JSON_CAN_NOT_OPEN_JSON_FILE;
+
+    if(!a_out_tx){
+        log_it(L_ERROR, "a_out_tx is NULL");
+        return DAP_CHAIN_NET_TX_CREATE_JSON_WRONG_ARGUMENTS;
+    }
+
+    const char *l_native_token = a_net ? a_net->pub.native_ticker : NULL;
+    const char *l_main_token = NULL;
+    bool l_multichanel = false;
+
+
+    // Read items from json file
+    struct json_object *l_json_items = json_object_object_get(l_json, "items");
+    size_t l_items_count;
+    if(!l_json_items || !json_object_is_type(l_json_items, json_type_array) || !(l_items_count = json_object_array_length(l_json_items))) {
+        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NET_TX_CREATE_JSON_NOT_FOUNT_ARRAY_ITEMS,
+                               "Wrong json format: not found array 'items' or array is empty");
+        json_object_put(l_json);
+        return DAP_CHAIN_NET_TX_CREATE_JSON_NOT_FOUNT_ARRAY_ITEMS;
+    }
+
+    log_it(L_ERROR, "Json TX: found %lu items", l_items_count);
+    // Create transaction
+    dap_chain_datum_tx_t *l_tx = DAP_NEW_Z_SIZE(dap_chain_datum_tx_t, sizeof(dap_chain_datum_tx_t));
+    if(!l_tx) {
+        json_object_put(l_json);
+        dap_json_rpc_allocation_error(*a_json_arr_reply);
+        return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED;
+    }
+
+    struct json_object *l_json_timestamp = json_object_object_get(l_json, "ts_created");
+    if (l_json_timestamp)
+        l_tx->header.ts_created = json_object_get_int64(l_json_timestamp);
+    else
+        l_tx->header.ts_created = time(NULL);
+
+    size_t l_items_ready = 0;
+    dap_list_t *l_in_list = NULL;// list 'in' items
+    dap_list_t *l_sign_list = NULL;// list 'sign' items
+    uint256_t l_value_need = { };// how many tokens are needed in the 'out' item
+    uint256_t l_value_need_fee = {};
+
+    if(a_net){ // if composition is not offline
+        // First iteration in input file. Check the tx will be multichannel or not
+        for(size_t i = 0; i < l_items_count; ++i) {
+            struct json_object *l_json_item_obj = json_object_array_get_idx(l_json_items, i);
+            if(!l_json_item_obj || !json_object_is_type(l_json_item_obj, json_type_object)) {
+                continue;
+            }
+            struct json_object *l_json_item_type = json_object_object_get(l_json_item_obj, "type");
+            if(!l_json_item_type && json_object_is_type(l_json_item_type, json_type_string)) {
+                log_it(L_WARNING, "Item %zu without type", i);
+                continue;
+            }
+            const char *l_item_type_str = json_object_get_string(l_json_item_type);
+            dap_chain_tx_item_type_t l_item_type = dap_chain_datum_tx_item_str_to_type(l_item_type_str);
+            if(l_item_type == TX_ITEM_TYPE_UNKNOWN) {
+                log_it(L_WARNING, "Item %zu has invalid type '%s'", i, l_item_type_str);
+                continue;
+            }
+
+            switch (l_item_type) {
+                case TX_ITEM_TYPE_IN: {
+                    const char *l_json_item_token = s_json_get_text(l_json_item_obj, "token");
+                    if (l_json_item_token && dap_strcmp(l_json_item_token, l_native_token)){
+                        l_multichanel = true;
+                        l_main_token = l_json_item_token;
+                    }
+                }break;
+                default: continue;
+            }
+            if(l_multichanel)
+                break;
+        }
+    }
+
+    // Creating and adding items to the transaction
+    for(size_t i = 0; i < l_items_count; ++i) {
+        struct json_object *l_json_item_obj = json_object_array_get_idx(l_json_items, i);
+        if(!l_json_item_obj || !json_object_is_type(l_json_item_obj, json_type_object)) {
+            continue;
+        }
+        struct json_object *l_json_item_type = json_object_object_get(l_json_item_obj, "type");
+        if(!l_json_item_type && json_object_is_type(l_json_item_type, json_type_string)) {
+            log_it(L_WARNING, "Item %zu without type", i);
+            continue;
+        }
+        const char *l_item_type_str = json_object_get_string(l_json_item_type);
+        dap_chain_tx_item_type_t l_item_type = dap_chain_datum_tx_item_str_to_type(l_item_type_str);
+        if(l_item_type == TX_ITEM_TYPE_UNKNOWN) {
+            log_it(L_WARNING, "Item %zu has invalid type '%s'", i, l_item_type_str);
+            continue;
+        }
+
+        log_it(L_DEBUG, "Json TX: process item %s", json_object_get_string(l_json_item_type));
+        // Create an item depending on its type
+        const uint8_t *l_item = NULL;
+        switch (l_item_type) {
+        case TX_ITEM_TYPE_IN: {
+            // Save item obj for in
+            // Read prev_hash and out_prev_idx
+            const char *l_prev_hash_str = s_json_get_text(l_json_item_obj, "prev_hash");
+            int64_t l_out_prev_idx;
+            bool l_is_out_prev_idx = s_json_get_int64(l_json_item_obj, "out_prev_idx", &l_out_prev_idx);
+            // If prev_hash and out_prev_idx were read
+            if(l_prev_hash_str && l_is_out_prev_idx) {
+                dap_chain_hash_fast_t l_tx_prev_hash;
+                if(!dap_chain_hash_fast_from_str(l_prev_hash_str, &l_tx_prev_hash)) {
+                    // Create IN item
+                    dap_chain_tx_in_t *l_in_item = dap_chain_datum_tx_item_in_create(&l_tx_prev_hash, (uint32_t) l_out_prev_idx);
+                    if (!l_in_item) {
+                        json_object *l_jobj_err = json_object_new_string("Unable to create in for transaction.");
+                        if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+                    }
+                    l_item = (const uint8_t*) l_in_item;
+                } else {
+                    log_it(L_WARNING, "Invalid 'in' item, bad prev_hash %s", l_prev_hash_str);
+                    char *l_str_err = dap_strdup_printf("Unable to create in for transaction. Invalid 'in' item, "
+                                                        "bad prev_hash %s", l_prev_hash_str);
+                    json_object *l_jobj_err = json_object_new_string(l_str_err);
+                    if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+                }
+            }
+            // Read addr_from
+            else {
+               l_in_list = dap_list_append(l_in_list, l_json_item_obj);
+            }
+        }
+            break;
+
+        case TX_ITEM_TYPE_OUT:
+        case TX_ITEM_TYPE_OUT_EXT: {
+            // Read address and value
+            uint256_t l_value = { };
+            const char *l_json_item_addr_str = s_json_get_text(l_json_item_obj, "addr");
+            bool l_is_value = s_json_get_uint256(l_json_item_obj, "value", &l_value);
+            const char *l_token = s_json_get_text(l_json_item_obj, "token");
+            if(l_is_value && l_json_item_addr_str) {
+                dap_chain_addr_t *l_addr = dap_chain_addr_from_str(l_json_item_addr_str);
+                if(l_addr && !IS_ZERO_256(l_value)) {
+                    if(l_item_type == TX_ITEM_TYPE_OUT) {
+                        // Create OUT item
+                        const uint8_t *l_out_item = NULL;
+                        if (a_net) {// if composition is not offline
+                            if(l_multichanel)
+                                l_out_item = (const uint8_t *)dap_chain_datum_tx_item_out_ext_create(l_addr, l_value, l_token ? l_token : (l_main_token ? l_main_token : l_native_token));
+                            else
+                                l_out_item = (const uint8_t *)dap_chain_datum_tx_item_out_create(l_addr, l_value);
+                            if (!l_out_item) {
+                                json_object *l_jobj_err = json_object_new_string("Failed to create transaction out. "
+                                                                                "There may not be enough funds in the wallet.");
+                                if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+                            }
+                            if (l_out_item){
+                                if (l_multichanel && !dap_strcmp(((dap_chain_tx_out_ext_t*)l_out_item)->token, l_native_token))
+                                    SUM_256_256(l_value_need_fee, l_value, &l_value_need_fee);
+                                else
+                                    SUM_256_256(l_value_need, l_value, &l_value_need);
+                            }
+                        } else {
+                            l_out_item = (const uint8_t *)dap_chain_datum_tx_item_out_create(l_addr, l_value);
+                            if (!l_out_item) {
+                                json_object *l_jobj_err = json_object_new_string("Failed to create transaction out. "
+                                                                                "There may not be enough funds in the wallet.");
+                                if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+                            }
+                        }
+                        l_item = (const uint8_t*) l_out_item;
+                    } else if(l_item_type == TX_ITEM_TYPE_OUT_EXT) {
+                        // Read address and value
+                        if(l_token) {
+                            // Create OUT_EXT item
+                            const uint8_t *l_out_item = NULL;
+                            if (a_net){ // if composition is not offline
+                                if(l_multichanel)
+                                    l_out_item = (const uint8_t *)dap_chain_datum_tx_item_out_ext_create(l_addr, l_value, l_token);
+                                else
+                                    l_out_item = (const uint8_t *)dap_chain_datum_tx_item_out_create(l_addr, l_value);
+                                if (!l_out_item) {
+                                    json_object *l_jobj_err = json_object_new_string("Failed to create a out ext"
+                                                                        "for a transaction. There may not be enough funds "
+                                                                        "on the wallet or the wrong ticker token "
+                                                                        "is indicated.");
+                                    if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+                                }
+                                if (l_out_item){
+                                    if (l_multichanel && !dap_strcmp(l_token, l_native_token))
+                                        SUM_256_256(l_value_need_fee, l_value, &l_value_need_fee);
+                                    else 
+                                        SUM_256_256(l_value_need, l_value, &l_value_need);
+                                }
+                            } else {
+                                l_out_item = (const uint8_t *)dap_chain_datum_tx_item_out_ext_create(l_addr, l_value, l_token);
+                                if (!l_out_item) {
+                                    json_object *l_jobj_err = json_object_new_string("Failed to create a out ext"
+                                                                        "for a transaction. There may not be enough funds "
+                                                                        "on the wallet or the wrong ticker token "
+                                                                        "is indicated.");
+                                    if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+                                }
+                            }
+                            l_item = (const uint8_t*) l_out_item;
+                        }
+                        else {
+                            log_it(L_WARNING, "Invalid 'out_ext' item %zu", i);
+                            continue;
+                        }
+                    }
+                } else {
+                    if(l_item_type == TX_ITEM_TYPE_OUT) {
+                        log_it(L_WARNING, "Invalid 'out' item %zu", i);
+                    }
+                    else if(l_item_type == TX_ITEM_TYPE_OUT_EXT) {
+                        log_it(L_WARNING, "Invalid 'out_ext' item %zu", i);
+                    }
+                    char *l_str_err = dap_strdup_printf("For item %zu of type 'out' or 'out_ext' the "
+                                                        "string representation of the address could not be converted, "
+                                                        "or the size of the output sum is 0.", i);
+                    json_object *l_jobj_err = json_object_new_string(l_str_err);
+                    DAP_DELETE(l_str_err);
+                    if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+                    continue;
+                }
+            }
+        }
+            break;
+        case TX_ITEM_TYPE_OUT_COND: {
+            // Read subtype of item
+            const char *l_subtype_str = s_json_get_text(l_json_item_obj, "subtype");
+            dap_chain_tx_out_cond_subtype_t l_subtype = dap_chain_tx_out_cond_subtype_from_str(l_subtype_str);
+            switch (l_subtype) {
+
+            case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY:{
+                uint256_t l_value = { };
+                bool l_is_value = s_json_get_uint256(l_json_item_obj, "value", &l_value);
+                if(!l_is_value || IS_ZERO_256(l_value)) {
+                    log_it(L_ERROR, "Json TX: bad value in OUT_COND_SUBTYPE_SRV_PAY");
+                    break;
+                }
+                uint256_t l_value_max_per_unit = { };
+                l_is_value = s_json_get_uint256(l_json_item_obj, "value_max_per_unit", &l_value_max_per_unit);
+                if(!l_is_value || IS_ZERO_256(l_value_max_per_unit)) {
+                    log_it(L_ERROR, "Json TX: bad value_max_per_unit in OUT_COND_SUBTYPE_SRV_PAY");
+                    break;
+                }
+                dap_chain_net_srv_price_unit_uid_t l_price_unit;
+                if(!s_json_get_unit(l_json_item_obj, "price_unit", &l_price_unit)) {
+                    log_it(L_ERROR, "Json TX: bad price_unit in OUT_COND_SUBTYPE_SRV_PAY");
+                    break;
+                }
+                dap_chain_net_srv_uid_t l_srv_uid;
+                if(!s_json_get_srv_uid(l_json_item_obj, "service_id", "service", &l_srv_uid.uint64)){
+                    // Default service DAP_CHAIN_NET_SRV_VPN_ID
+                    l_srv_uid.uint64 = 0x0000000000000001;
+                }
+
+                // From "wallet" or "cert"
+                dap_pkey_t *l_pkey = s_json_get_pkey(l_json_item_obj);
+                if(!l_pkey) {
+                    log_it(L_ERROR, "Json TX: bad pkey in OUT_COND_SUBTYPE_SRV_PAY");
+                    break;
+                }
+                const char *l_params_str = s_json_get_text(l_json_item_obj, "params");
+                size_t l_params_size = dap_strlen(l_params_str);
+                dap_chain_tx_out_cond_t *l_out_cond_item = dap_chain_datum_tx_item_out_cond_create_srv_pay(l_pkey, l_srv_uid, l_value, l_value_max_per_unit,
+                        l_price_unit, l_params_str, l_params_size);
+                l_item = (const uint8_t*) l_out_cond_item;
+                // Save value for using in In item
+                if(l_item) {
+                    SUM_256_256(l_value_need, l_value, &l_value_need);
+                } else {
+                    char *l_str_err = dap_strdup_printf("Unable to create conditional out for transaction "
+                                                        "can of type %s described in item %zu.\n", l_subtype_str, i);
+                    json_object *l_jobj_err = json_object_new_string(l_str_err);
+                    DAP_DELETE(l_str_err);
+                    if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+                }
+                DAP_DELETE(l_pkey);
+            }
+                break;
+            case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE: {
+
+                dap_chain_net_srv_uid_t l_srv_uid;
+                if(!s_json_get_srv_uid(l_json_item_obj, "service_id", "service", &l_srv_uid.uint64)) {
+                    // Default service DAP_CHAIN_NET_SRV_XCHANGE_ID
+                    l_srv_uid.uint64 = 0x2;
+                }
+                dap_chain_net_t *l_net = dap_chain_net_by_name(s_json_get_text(l_json_item_obj, "net"));
+                if(!l_net) {
+                    log_it(L_ERROR, "Json TX: bad net in OUT_COND_SUBTYPE_SRV_XCHANGE");
+                    break;
+                }
+                const char *l_token = s_json_get_text(l_json_item_obj, "token");
+                if(!l_token) {
+                    log_it(L_ERROR, "Json TX: bad token in OUT_COND_SUBTYPE_SRV_XCHANGE");
+                    break;
+                }
+                uint256_t l_value = { };
+                if(!s_json_get_uint256(l_json_item_obj, "value", &l_value) || IS_ZERO_256(l_value)) {
+                    log_it(L_ERROR, "Json TX: bad value in OUT_COND_SUBTYPE_SRV_XCHANGE");
+                    break;
+                }
+                //const char *l_params_str = s_json_get_text(l_json_item_obj, "params");
+                //size_t l_params_size = dap_strlen(l_params_str);
+                dap_chain_tx_out_cond_t *l_out_cond_item = NULL; //dap_chain_datum_tx_item_out_cond_create_srv_xchange(l_srv_uid, l_net->pub.id, l_token, l_value, l_params_str, l_params_size);
+                l_item = (const uint8_t*) l_out_cond_item;
+                // Save value for using in In item
+                if(l_item) {
+                    SUM_256_256(l_value_need, l_value, &l_value_need);
+                } else {
+                    char *l_str_err = dap_strdup_printf("Unable to create conditional out for transaction "
+                                                         "can of type %s described in item %zu.", l_subtype_str, i);
+                    json_object *l_jobj_err = json_object_new_string(l_str_err);
+                    DAP_DELETE(l_str_err);
+                    if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+                }
+            }
+                break;
+            case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE:{
+                dap_chain_net_srv_uid_t l_srv_uid;
+                if(!s_json_get_srv_uid(l_json_item_obj, "service_id", "service", &l_srv_uid.uint64)) {
+                    // Default service DAP_CHAIN_NET_SRV_STAKE_ID
+                    l_srv_uid.uint64 = 0x13;
+                }
+                uint256_t l_value = { };
+                if(!s_json_get_uint256(l_json_item_obj, "value", &l_value) || IS_ZERO_256(l_value)) {
+                    log_it(L_ERROR, "Json TX: bad value in OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE");
+                    break;
+                }
+                uint256_t l_fee_value = { };
+                if(!s_json_get_uint256(l_json_item_obj, "fee", &l_fee_value) || IS_ZERO_256(l_fee_value)) {
+                    break;
+                }
+                
+                const char *l_signing_addr_str = s_json_get_text(l_json_item_obj, "signing_addr");
+                dap_chain_addr_t *l_signing_addr = dap_chain_addr_from_str(l_signing_addr_str);
+                if(!l_signing_addr) {
+                {
+                    log_it(L_ERROR, "Json TX: bad signing_addr in OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE");
+                    break;
+                }
+                dap_chain_node_addr_t l_signer_node_addr;
+                const char *l_node_addr_str = s_json_get_text(l_json_item_obj, "node_addr");
+                if(!l_node_addr_str || dap_chain_node_addr_from_str(&l_signer_node_addr, l_node_addr_str)) {
+                    log_it(L_ERROR, "Json TX: bad node_addr in OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE");
+                    break;
+                }
+                dap_chain_tx_out_cond_t *l_out_cond_item = dap_chain_datum_tx_item_out_cond_create_srv_stake(l_srv_uid, l_value, l_signing_addr,
+                                                                                                             &l_signer_node_addr, NULL, uint256_0);
+                l_item = (const uint8_t*) l_out_cond_item;
+                // Save value for using in In item
+                if(l_item) {
+                    SUM_256_256(l_value_need, l_value, &l_value_need);
+                } else {
+                    char *l_err_str = dap_strdup_printf("Unable to create conditional out for transaction "
+                                                        "can of type %s described in item %zu.", l_subtype_str, i);
+                    json_object *l_jobj_err = json_object_new_string(l_err_str);
+                    DAP_DELETE(l_err_str);
+                    if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+                }
+                }
+            }
+                break;
+            case DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE: {
+                uint256_t l_value = { };
+                s_json_get_uint256(l_json_item_obj, "value", &l_value);
+                if(!IS_ZERO_256(l_value)) {
+                    dap_chain_tx_out_cond_t *l_out_cond_item = dap_chain_datum_tx_item_out_cond_create_fee(l_value);
+                    l_item = (const uint8_t*) l_out_cond_item;
+                    // Save value for using in In item
+                    if(l_item) {
+                        SUM_256_256(l_value_need_fee, l_value, &l_value_need_fee);
+                    } else {
+                        char *l_str_err = dap_strdup_printf("Unable to create conditional out for transaction "
+                                                            "can of type %s described in item %zu.", l_subtype_str, i);
+                        json_object *l_jobj_err = json_object_new_string(l_str_err);
+                        if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+                        DAP_DELETE(l_str_err);
+                    }
+                }
+                else
+                    log_it(L_ERROR, "Json TX: zero value in OUT_COND_SUBTYPE_FEE");
+            }
+                break;
+            case DAP_CHAIN_TX_OUT_COND_SUBTYPE_UNDEFINED:
+                log_it(L_WARNING, "Undefined subtype: '%s' of 'out_cond' item %zu ", l_subtype_str, i);
+                char *l_str_err = dap_strdup_printf("Specified unknown sub type %s of conditional out on item %zu.",
+                                                    l_subtype_str, i);
+                json_object *l_jobj_err = json_object_new_string(l_str_err);
+                DAP_DELETE(l_str_err);
+                if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+                break;
+            }
+        }
+            break;
+        case TX_ITEM_TYPE_SIG:{          
+            const char *l_sign_type_str = s_json_get_text(l_json_item_obj, "sig_type");          
+            if (l_sign_type_str) {
+                dap_sign_type_t l_sign_type = dap_sign_type_from_str(l_sign_type_str);
+                if (l_sign_type.type == SIG_TYPE_NULL) {
+                    json_object *l_jobj_err = json_object_new_string("Can't define sign type");
+                    json_object_array_add(l_jobj_errors, l_jobj_err);
+                    log_it(L_ERROR, "Json TX: Can't define sign type \"%s\"", l_sign_type_str);
+                    break;
+                }
+                int64_t l_pkey_size, l_sig_size, l_hash_type = 0;
+
+                s_json_get_int64(l_json_item_obj, "hash_type", &l_hash_type);
+                s_json_get_int64(l_json_item_obj, "pub_key_size", &l_pkey_size);
+                s_json_get_int64(l_json_item_obj, "sig_size", &l_sig_size);
+                debug_if(!l_pkey_size || !l_sig_size, L_WARNING,
+                         "\"pub_key_size\" or \"sig_size\" not provided! Will be calculated automatically");
+                
+                json_object *l_jobj_pub_key = json_object_object_get(l_json_item_obj, "pub_key_b64"),
+                            *l_jobj_sign = json_object_object_get(l_json_item_obj, "sig_b64");
+                if (!l_jobj_pub_key || !l_jobj_sign) {
+                    json_object *l_jobj_err = json_object_new_string("Can't get base64-encoded sign or pkey!");
+                    json_object_array_add(l_jobj_errors, l_jobj_err);
+                    log_it(L_ERROR, "Json TX: Can't get base64-encoded sign or pkey!");
+                    break;
+                }
+                const char *l_pub_key_str = json_object_get_string(l_jobj_pub_key),
+                           *l_sign_str = json_object_get_string(l_jobj_sign);
+                int64_t l_pkey_decoded_size = DAP_ENC_BASE64_DECODE_SIZE(strlen(l_pub_key_str)),
+                        l_sign_decoded_size = DAP_ENC_BASE64_DECODE_SIZE(strlen(l_sign_str));
+                
+                dap_sign_t *l_sign = DAP_NEW_SIZE(dap_sign_t, sizeof(dap_sign_t) + l_pkey_decoded_size + l_sign_decoded_size);
+                *l_sign = (dap_sign_t) {
+                    .header.type = l_sign_type,
+                    .header.hash_type = (uint8_t)l_hash_type,
+                };
+                l_pkey_decoded_size = dap_enc_base64_decode(l_pub_key_str, strlen(l_pub_key_str),
+                                                            l_sign->pkey_n_sign, DAP_ENC_DATA_TYPE_B64_URLSAFE);
+                debug_if(l_pkey_size != l_pkey_decoded_size, L_ERROR, "Json TX: pkey size mismatch, %zu != %zu",
+                                                                      l_pkey_size, l_pkey_decoded_size);
+
+                l_sign_decoded_size = dap_enc_base64_decode(l_sign_str, strlen(l_sign_str),
+                                                            l_sign->pkey_n_sign + l_pkey_decoded_size, DAP_ENC_DATA_TYPE_B64_URLSAFE);
+                debug_if(l_sig_size != l_sign_decoded_size, L_ERROR, "Json TX: sign size mismatch, %zu != %zu",
+                                                                     l_sig_size, l_sign_decoded_size);
+
+                l_sign->header.sign_size = l_sign_decoded_size;
+                l_sign->header.sign_pkey_size = l_pkey_decoded_size;
+                size_t l_sign_full_size = dap_sign_get_size(l_sign);
+                
+                dap_chain_tx_sig_t *l_tx_sig = DAP_NEW_Z_SIZE(dap_chain_tx_sig_t, sizeof(dap_chain_tx_sig_t) + l_sign_full_size);
+                l_tx_sig->header.type = TX_ITEM_TYPE_SIG;
+                l_tx_sig->header.version = 1;
+                l_tx_sig->header.sig_size = (uint32_t)l_sign_full_size;
+                memcpy(l_tx_sig->sig, l_sign, l_sign_full_size);
+                l_item = (const uint8_t*)l_tx_sig;
+                DAP_DELETE(l_sign);
+                break;
+            } else              
+                l_sign_list = dap_list_append(l_sign_list,l_json_item_obj);
+        }
+            break;
+        case TX_ITEM_TYPE_RECEIPT: {
+            dap_chain_net_srv_uid_t l_srv_uid;
+            if(!s_json_get_srv_uid(l_json_item_obj, "service_id", "service", &l_srv_uid.uint64)) {
+                log_it(L_ERROR, "Json TX: bad service_id in TYPE_RECEIPT");
+                break;
+            }
+            dap_chain_net_srv_price_unit_uid_t l_price_unit;
+            if(!s_json_get_unit(l_json_item_obj, "price_unit", &l_price_unit)) {
+                log_it(L_ERROR, "Json TX: bad price_unit in TYPE_RECEIPT");
+                break;
+            }
+            int64_t l_units;
+            if(!s_json_get_int64(l_json_item_obj, "units", &l_units)) {
+                log_it(L_ERROR, "Json TX: bad units in TYPE_RECEIPT");
+                break;
+            }
+            uint256_t l_value = { };
+            if(!s_json_get_uint256(l_json_item_obj, "value", &l_value) || IS_ZERO_256(l_value)) {
+                log_it(L_ERROR, "Json TX: bad value in TYPE_RECEIPT");
+                break;
+            }
+            const char *l_params_str = s_json_get_text(l_json_item_obj, "params");
+            size_t l_params_size = dap_strlen(l_params_str);
+            dap_chain_datum_tx_receipt_t *l_receipt = dap_chain_datum_tx_receipt_create(l_srv_uid, l_price_unit, l_units, l_value, l_params_str, l_params_size);
+            l_item = (const uint8_t*) l_receipt;
+            if (!l_item) {
+                char *l_str_err = dap_strdup_printf("Unable to create receipt out for transaction "
+                                                    "described by item %zu.", i);
+                json_object *l_jobj_err = json_object_new_string(l_str_err);
+                DAP_DELETE(l_str_err);
+                if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+            }
+        }
+            break;
+        case TX_ITEM_TYPE_TSD: {
+            int64_t l_tsd_type;
+            if(!s_json_get_int64(l_json_item_obj, "type_tsd", &l_tsd_type)) {
+                log_it(L_ERROR, "Json TX: bad type_tsd in TYPE_TSD");
+                break;
+            }
+            const char *l_tsd_data = s_json_get_text(l_json_item_obj, "data");
+            if (!l_tsd_data) {
+                log_it(L_ERROR, "Json TX: bad data in TYPE_TSD");
+                break;
+            }
+            size_t l_data_size = dap_strlen(l_tsd_data);
+            dap_chain_tx_tsd_t *l_tsd = dap_chain_datum_tx_item_tsd_create((void*)l_tsd_data, (int)l_tsd_type, l_data_size);
+            l_item = (const uint8_t*) l_tsd;
+            // l_tsd_list = dap_list_append(l_tsd_list, l_tsd);
+        }
+            break;
+            //case TX_ITEM_TYPE_PKEY:
+                //break;
+            //case TX_ITEM_TYPE_IN_EMS:
+                //break;
+            //case TX_ITEM_TYPE_IN_EMS_EXT:
+                //break;
+        }
+        // Add item to transaction
+        if(l_item) {
+            dap_chain_datum_tx_add_item(&l_tx, (const uint8_t*) l_item);
+            l_items_ready++;
+            DAP_DELETE(l_item);
+        }
+    }
+    
+    dap_list_t *l_list;
+    // Add In items
+    if(a_net){
+        l_list = l_in_list;
+        while(l_list) {
+            struct json_object *l_json_item_obj = (struct json_object*) l_list->data;
+
+            const char *l_json_item_addr_str = s_json_get_text(l_json_item_obj, "addr_from");
+            const char *l_json_item_token = s_json_get_text(l_json_item_obj, "token");
+            l_main_token = l_json_item_token;
+            dap_chain_addr_t *l_addr_from = NULL;
+            if(l_json_item_addr_str) {
+                l_addr_from = dap_chain_addr_from_str(l_json_item_addr_str);
+                if (!l_addr_from) {
+                    log_it(L_WARNING, "Invalid element 'in', unable to convert string representation of addr_from: '%s' "
+                                        "to binary.", l_json_item_addr_str);
+                    char *l_str_err = dap_strdup_printf("Invalid element 'to', unable to convert string representation "
+                                                        "of addr_from: '%s' to binary.", l_json_item_addr_str);
+                    json_object *l_jobj_err = json_object_new_string(l_str_err);
+                    DAP_DELETE(l_str_err);
+                    if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+                    // Go to the next item
+                    l_list = dap_list_next(l_list);
+                    continue;
+                }
+            }
+            else {
+                log_it(L_WARNING, "Invalid 'in' item, incorrect addr_from: '%s'", l_json_item_addr_str ? l_json_item_addr_str : "[null]");
+                char *l_str_err = dap_strdup_printf("Invalid 'in' item, incorrect addr_from: '%s'",
+                                            l_json_item_addr_str ? l_json_item_addr_str : "[null]");
+                json_object *l_jobj_err = json_object_new_string(l_str_err);
+                DAP_DELETE(l_str_err);
+                if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+                // Go to the next item
+                l_list = dap_list_next(l_list);
+                continue;
+            }
+            if(!l_json_item_token) {
+                log_it(L_WARNING, "Invalid 'in' item, not found token name");
+                json_object *l_jobj_err = json_object_new_string("Invalid 'in' item, not found token name");
+                if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+                // Go to the next item
+                l_list = dap_list_next(l_list);
+                continue;
+            }
+            if(IS_ZERO_256(l_value_need)) {
+                log_it(L_WARNING, "Invalid 'in' item, not found value in out items");
+                json_object *l_jobj_err = json_object_new_string("Invalid 'in' item, not found value in out items");
+                if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+                // Go to the next item
+                l_list = dap_list_next(l_list);
+                continue;
+            }
+
+            if(l_addr_from){
+                // find the transactions from which to take away coins
+                dap_list_t *l_list_used_out = NULL;
+                dap_list_t *l_list_used_out_fee = NULL;
+                uint256_t l_value_transfer = { }; // how many coins to transfer
+                uint256_t l_value_transfer_fee = { }; // how many coins to transfer
+                //SUM_256_256(a_value, a_value_fee, &l_value_need);
+                uint256_t l_value_need_check = {};
+                if (!dap_strcmp(l_native_token, l_main_token)) {
+                    SUM_256_256(l_value_need_check, l_value_need, &l_value_need_check);
+                    SUM_256_256(l_value_need_check, l_value_need_fee, &l_value_need_check);
+                    l_list_used_out = dap_ledger_get_list_tx_outs_with_val(a_net->pub.ledger, l_json_item_token,
+                                                                                                l_addr_from, l_value_need_check, &l_value_transfer);
+                    if(!l_list_used_out) {
+                        log_it(L_WARNING, "Not enough funds in previous tx to transfer");
+                        json_object *l_jobj_err = json_object_new_string("Can't create in transaction. Not enough funds in previous tx "
+                                                            "to transfer");
+                        if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+                        // Go to the next item
+                        l_list = dap_list_next(l_list);
+                        continue;
+                    }
+                } else {
+                    //CHECK value need
+                    l_list_used_out = dap_ledger_get_list_tx_outs_with_val(a_net->pub.ledger, l_json_item_token,
+                                                                                                l_addr_from, l_value_need, &l_value_transfer);
+                    if(!l_list_used_out) {
+                        log_it(L_WARNING, "Not enough funds in previous tx to transfer");
+                        json_object *l_jobj_err = json_object_new_string("Can't create in transaction. Not enough funds "
+                                                                            "in previous tx to transfer");
+                        if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+                        // Go to the next item
+                        l_list = dap_list_next(l_list);
+                        continue;
+                    }
+                    //CHECK value fee
+                    l_list_used_out_fee = dap_ledger_get_list_tx_outs_with_val(a_net->pub.ledger, l_native_token,
+                                                                                        l_addr_from, l_value_need_fee, &l_value_transfer_fee);
+                    if(!l_list_used_out_fee) {
+                        log_it(L_WARNING, "Not enough funds in previous tx to transfer");
+                        json_object *l_jobj_err = json_object_new_string("Can't create in transaction. Not enough funds "
+                                                                            "in previous tx to transfer");
+                        if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+                        // Go to the next item
+                        l_list = dap_list_next(l_list);
+                        continue;
+                    }
+                }
+                // add 'in' items
+                uint256_t l_value_got = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out);
+                assert(EQUAL_256(l_value_got, l_value_transfer));
+                if (l_list_used_out_fee) {
+                    uint256_t l_value_got_fee = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out_fee);
+                    assert(EQUAL_256(l_value_got_fee, l_value_transfer_fee));
+                    dap_list_free_full(l_list_used_out_fee, free);
+                    // add 'out' item for coin fee back
+                    uint256_t  l_value_back;
+                    SUBTRACT_256_256(l_value_got_fee, l_value_need_fee, &l_value_back);
+                    if (!IS_ZERO_256(l_value_back)) {
+                        dap_chain_datum_tx_add_out_ext_item(&l_tx, l_addr_from, l_value_back, l_native_token);
+                        l_items_ready++;
+                    }
+                } else {
+                    SUM_256_256(l_value_need, l_value_need_fee, &l_value_need);
+                }
+                dap_list_free_full(l_list_used_out, free);
+                if(!IS_ZERO_256(l_value_got)) {
+                    // add 'out' item for coin back
+                    uint256_t l_value_back;
+                    SUBTRACT_256_256(l_value_got, l_value_need, &l_value_back);
+                    if(!IS_ZERO_256(l_value_back)) {
+                        if (l_multichanel)
+                            dap_chain_datum_tx_add_out_ext_item(&l_tx, l_addr_from, l_value_back, l_main_token);
+                        else
+                            dap_chain_datum_tx_add_out_item(&l_tx, l_addr_from, l_value_back);
+                        l_items_ready++;
+                    }
+                }   
+            }
+            // Go to the next 'in' item
+            l_list = dap_list_next(l_list);
+        }
+    }
+    dap_list_free(l_in_list);
+
+    // Add signs
+    l_list = l_sign_list;
+    while(l_list) {
+        struct json_object *l_json_item_obj = (struct json_object*) l_list->data;
+        dap_enc_key_t * l_enc_key  = NULL;
+        
+        //get wallet or cert
+        dap_chain_wallet_t *l_wallet = s_json_get_wallet(l_json_item_obj, "wallet");
+        const dap_cert_t *l_cert = s_json_get_cert(l_json_item_obj, "cert");
+
+        int64_t l_pkey_size;
+        int64_t l_sig_size;
+        uint8_t *l_pkey = NULL;
+        int64_t l_hash_type = 0;
+        dap_sign_t *l_sign = NULL;
+        
+
+        //wallet goes first
+        if (l_wallet) {
+            l_enc_key = dap_chain_wallet_get_key(l_wallet, 0);
+        } else if (l_cert && l_cert->enc_key) {
+            l_enc_key = l_cert->enc_key; 
+        } else { 
+            json_object *l_jobj_err = json_object_new_string("Can't create sign for transactions.");
+            json_object_array_add(l_jobj_errors, l_jobj_err);
+            log_it(L_ERROR, "Json TX: Item sign has no wallet or cert of they are invalid ");
+            l_list = dap_list_next(l_list);
+            continue;
+        }
+
+        if (l_sign) {
+            size_t l_chain_sign_size = dap_sign_get_size(l_sign); // sign data
+            
+            dap_chain_tx_sig_t *l_tx_sig = DAP_NEW_Z_SIZE(dap_chain_tx_sig_t,
+                    sizeof(dap_chain_tx_sig_t) + l_chain_sign_size);
+            l_tx_sig->header.type = TX_ITEM_TYPE_SIG;
+            l_tx_sig->header.sig_size =(uint32_t) l_chain_sign_size;
+            memcpy(l_tx_sig->sig, l_sign, l_chain_sign_size);
+            dap_chain_datum_tx_add_item(&l_tx, l_tx_sig);
+            DAP_DELETE(l_sign);
+        }
+
+        if(l_enc_key && dap_chain_datum_tx_add_sign_item(&l_tx, l_enc_key) > 0) {
+            l_items_ready++;
+        } else {
+            log_it(L_ERROR, "Json TX: Item sign has invalid enc_key.");
+            l_list = dap_list_next(l_list);
+            continue;
+        }
+
+        if (l_wallet) {
+            dap_chain_wallet_close(l_wallet);  
+            dap_enc_key_delete(l_enc_key);
+        }  
+        l_list = dap_list_next(l_list);
+    }
+
+    dap_list_free(l_sign_list);
+    json_object_put(l_json);
+
+    *a_out_tx = l_tx;
+
+    if(a_items_count)
+        *a_items_count = l_items_count;
+
+    if(a_items_ready)
+        *a_items_ready = l_items_ready;
+
+    return DAP_CHAIN_NET_TX_CREATE_JSON_OK;
+}
+
+int dap_chain_net_tx_to_json(dap_chain_datum_tx_t *a_tx, json_object *a_out_json)
+{
+    if(!a_tx || !a_out_json)
+        return log_it(L_ERROR, "Empty transaction"), DAP_CHAIN_NET_TX_CREATE_JSON_WRONG_ARGUMENTS;
+
+    json_object* json_obj_out = a_out_json;
+    json_object* l_json_arr_reply = NULL;
+    dap_hash_fast_t l_hash_tmp = { };
+    byte_t *item; size_t l_size;
+    char *l_hash_str = NULL;
+    char l_tmp_buf[DAP_TIME_STR_SIZE];
+    json_object* json_arr_items = json_object_new_array();
+
+    char *l_tx_hash_str = dap_hash_fast_str_new(a_tx, dap_chain_datum_tx_get_size(a_tx));
+
+    json_object_object_add(json_obj_out, "datum_hash", json_object_new_string(l_tx_hash_str));
+    json_object_object_add(json_obj_out, "ts_created", json_object_new_int64(a_tx->header.ts_created));
+    json_object_object_add(json_obj_out, "datum_type", json_object_new_string("tx"));
+
+    TX_ITEM_ITER_TX(item, l_size, a_tx) {
+        json_object* json_obj_item = json_object_new_object();
+        switch (*item) {
+        case TX_ITEM_TYPE_IN:
+            l_hash_tmp = ((dap_chain_tx_in_t*)item)->header.tx_prev_hash;
+            l_hash_str = dap_hash_fast_to_str_static(&l_hash_tmp);
+            json_object_object_add(json_obj_item,"type", json_object_new_string("in"));
+            json_object_object_add(json_obj_item,"prev_hash", json_object_new_string(l_hash_str));
+            json_object_object_add(json_obj_item,"out_prev_idx", json_object_new_uint64(((dap_chain_tx_in_t*)item)->header.tx_out_prev_idx));
+            break;
+        case TX_ITEM_TYPE_OUT: { // 256
+            const char *l_coins_str,
+                    *l_value_str = dap_uint256_to_char(((dap_chain_tx_out_t*)item)->header.value, &l_coins_str),
+                    *l_addr_str = dap_chain_addr_to_str_static(&((dap_chain_tx_out_t*)item)->addr);
+            json_object_object_add(json_obj_item,"type", json_object_new_string("out"));
+            json_object_object_add(json_obj_item,"value", json_object_new_string(l_value_str));
+            json_object_object_add(json_obj_item,"addr", json_object_new_string(l_addr_str));            
+        } break;
+        case TX_ITEM_TYPE_SIG: {
+            dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t*)item);
+            json_object_object_add(json_obj_item,"type", json_object_new_string("sign"));
+            dap_chain_hash_fast_t l_hash_pkey;
+            json_object_object_add(json_obj_item,"sig_type",json_object_new_string(dap_sign_type_to_str(l_sign->header.type)));
+            json_object_object_add(json_obj_item,"pub_key_size",json_object_new_uint64(l_sign->header.sign_pkey_size));
+            json_object_object_add(json_obj_item,"sig_size",json_object_new_uint64(l_sign->header.sign_size));
+            json_object_object_add(json_obj_item,"hash_type",json_object_new_uint64(l_sign->header.hash_type));
+            
+            char l_pkey_base64[DAP_ENC_BASE64_ENCODE_SIZE(l_sign->header.sign_pkey_size) + 1];
+            size_t l_pkey_base64_size = dap_enc_base64_encode(l_sign->pkey_n_sign, l_sign->header.sign_pkey_size, l_pkey_base64, DAP_ENC_DATA_TYPE_B64_URLSAFE); 
+            l_pkey_base64[l_pkey_base64_size] = '\0';   
+            json_object_object_add(json_obj_item,"pub_key_b64", json_object_new_string(l_pkey_base64));     
+
+            char l_sign_base64[DAP_ENC_BASE64_ENCODE_SIZE(l_sign->header.sign_size) + 1];
+            size_t l_sign_base64_size = dap_enc_base64_encode(l_sign->pkey_n_sign + l_sign->header.sign_pkey_size, l_sign->header.sign_size, l_sign_base64, DAP_ENC_DATA_TYPE_B64_URLSAFE); 
+            l_sign_base64[l_sign_base64_size] = '\0';
+            json_object_object_add(json_obj_item,"sig_b64", json_object_new_string(l_sign_base64));
+
+        } break;
+        case TX_ITEM_TYPE_TSD: {
+            json_object_object_add(json_obj_item,"type", json_object_new_string("data"));
+            json_object_object_add(json_obj_item,"type", json_object_new_uint64(((dap_chain_tx_tsd_t*)item)->header.type));
+            json_object_object_add(json_obj_item,"size", json_object_new_uint64(((dap_chain_tx_tsd_t*)item)->header.size));            
+        } break;
+        case TX_ITEM_TYPE_IN_COND:
+            json_object_object_add(json_obj_item,"type", json_object_new_string("in_cond"));
+            l_hash_tmp = ((dap_chain_tx_in_cond_t*)item)->header.tx_prev_hash;
+            l_hash_str = dap_hash_fast_to_str_static(&l_hash_tmp);
+            json_object_object_add(json_obj_item,"receipt_idx", json_object_new_int(((dap_chain_tx_in_cond_t*)item)->header.receipt_idx));
+            json_object_object_add(json_obj_item,"out_prev_idx", json_object_new_string(l_hash_str));
+            json_object_object_add(json_obj_item,"prev_hash", json_object_new_uint64(((dap_chain_tx_in_cond_t*)item)->header.tx_out_prev_idx));
+            break;
+        case TX_ITEM_TYPE_OUT_COND: {
+            char l_tmp_buff[70]={0};
+            json_object_object_add(json_obj_item,"type", json_object_new_string("out_cond"));
+            const char *l_coins_str, *l_value_str = dap_uint256_to_char(((dap_chain_tx_out_cond_t*)item)->header.value, &l_coins_str);
+            dap_time_t l_ts_exp = ((dap_chain_tx_out_cond_t*)item)->header.ts_expires;
+            dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, l_ts_exp);
+            json_object_object_add(json_obj_item,"ts_expires", l_ts_exp ? json_object_new_string(l_tmp_buf) : json_object_new_string("never"));
+            json_object_object_add(json_obj_item,"value", json_object_new_string(l_value_str));
+            sprintf(l_tmp_buff,"0x%016"DAP_UINT64_FORMAT_x"",((dap_chain_tx_out_cond_t*)item)->header.srv_uid.uint64);
+            json_object_object_add(json_obj_item,"service_id", json_object_new_string(l_tmp_buff));
+            switch (((dap_chain_tx_out_cond_t*)item)->header.subtype) {
+                case DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE:
+                    json_object_object_add(json_obj_item,"subtype", json_object_new_string("fee"));
+                    break;
+                case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY: {
+                    const char *l_coins_str, *l_value_str =
+                        dap_uint256_to_char( ((dap_chain_tx_out_cond_t*)item)->subtype.srv_pay.unit_price_max_datoshi, &l_coins_str );
+                    l_hash_tmp = ((dap_chain_tx_out_cond_t*)item)->subtype.srv_pay.pkey_hash;
+                    l_hash_str = dap_hash_fast_to_str_static(&l_hash_tmp);
+                    sprintf(l_tmp_buff,"0x%08x",((dap_chain_tx_out_cond_t*)item)->subtype.srv_pay.unit.uint32);
+                    json_object_object_add(json_obj_item,"price_unit", json_object_new_string(l_tmp_buff));
+                    json_object_object_add(json_obj_item,"pkey", json_object_new_string(l_hash_str));
+                    json_object_object_add(json_obj_item,"value_max_per_unit", json_object_new_string(l_value_str));
+                    json_object_object_add(json_obj_item,"subtype", json_object_new_string("srv_pay"));
+                } break;
+                case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE: {
+                    dap_chain_node_addr_t *l_signer_node_addr = &((dap_chain_tx_out_cond_t*)item)->subtype.srv_stake_pos_delegate.signer_node_addr;
+                    dap_chain_addr_t *l_signing_addr = &((dap_chain_tx_out_cond_t*)item)->subtype.srv_stake_pos_delegate.signing_addr;
+                    l_hash_tmp = l_signing_addr->data.hash_fast;
+                    l_hash_str = dap_hash_fast_to_str_static(&l_hash_tmp);
+                    json_object_object_add(json_obj_item,"signing_addr", json_object_new_string(dap_chain_addr_to_str_static(l_signing_addr)));            
+                    sprintf(l_tmp_buff,""NODE_ADDR_FP_STR"",NODE_ADDR_FP_ARGS(l_signer_node_addr));
+                    json_object_object_add(json_obj_item,"signer_node_addr", json_object_new_string(l_tmp_buff));
+                    json_object_object_add(json_obj_item,"subtype", json_object_new_string("srv_stake_pos_delegate"));
+                } break;
+                case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE: {
+                    const char *l_rate_str, *l_tmp_str =
+                        dap_uint256_to_char( (((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.rate), &l_rate_str );
+                    sprintf(l_tmp_buff,"0x%016"DAP_UINT64_FORMAT_x"",((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.buy_net_id.uint64);
+                    json_object_object_add(json_obj_item,"net_id", json_object_new_string(l_tmp_buff));
+                    json_object_object_add(json_obj_item,"token", json_object_new_string(((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.buy_token));
+                    json_object_object_add(json_obj_item,"rate", json_object_new_string(l_rate_str));
+                    json_object_object_add(json_obj_item,"subtype", json_object_new_string("srv_xchange"));
+                } break;
+                case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK: {
+                    dap_time_t l_ts_unlock = ((dap_chain_tx_out_cond_t*)item)->subtype.srv_stake_lock.time_unlock;
+                    dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, l_ts_unlock);
+                    json_object_object_add(json_obj_item,"time_unlock", json_object_new_string(l_tmp_buf));
+                    json_object_object_add(json_obj_item,"subtype", json_object_new_string("srv_stake_lock"));
+                } break;
+                default: break;
+            }
+        } break;
+        case TX_ITEM_TYPE_OUT_EXT: {
+            const char *l_coins_str, *l_value_str = dap_uint256_to_char( ((dap_chain_tx_out_ext_t*)item)->header.value, &l_coins_str );
+            json_object_object_add(json_obj_item,"type", json_object_new_string("out_ext"));
+            json_object_object_add(json_obj_item,"addr", json_object_new_string(dap_chain_addr_to_str_static(&((dap_chain_tx_out_ext_t*)item)->addr)));
+            json_object_object_add(json_obj_item,"token", json_object_new_string(((dap_chain_tx_out_ext_t*)item)->token));
+            json_object_object_add(json_obj_item,"value", json_object_new_string(l_value_str));
+            
+        } break;
+        case TX_ITEM_TYPE_VOTING:{
+            size_t l_tsd_size = 0;
+            dap_chain_tx_tsd_t *l_item = (dap_chain_tx_tsd_t *)dap_chain_datum_tx_item_get(a_tx, NULL, (byte_t*)item + l_size, TX_ITEM_TYPE_TSD, &l_tsd_size);
+            if (!l_item || !l_tsd_size)
+                    break;
+            dap_chain_datum_tx_voting_params_t *l_voting_params = dap_chain_voting_parse_tsd(a_tx);
+            json_object_object_add(json_obj_item,"type", json_object_new_string("voting"));
+            json_object_object_add(json_obj_item,"voting_question", json_object_new_string(l_voting_params->voting_question));
+            json_object_object_add(json_obj_item,"answer_options", json_object_new_string(""));
+            
+            dap_list_t *l_temp = l_voting_params->answers_list;
+            uint8_t l_index = 0;
+            while (l_temp) {
+                json_object_object_add(json_obj_item, dap_itoa(l_index), json_object_new_string((char *)l_temp->data));
+                l_index++;
+                l_temp = l_temp->next;
+            }
+            if (l_voting_params->voting_expire) {
+                dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, l_voting_params->voting_expire);
+                json_object_object_add(json_obj_item,"Voting expire", json_object_new_string(l_tmp_buf));                
+            }
+            if (l_voting_params->votes_max_count) {
+                json_object_object_add(json_obj_item, "Votes max count", json_object_new_uint64(l_voting_params->votes_max_count));
+            }
+            json_object_object_add(json_obj_item,"Changing vote is", l_voting_params->vote_changing_allowed ? json_object_new_string("available") : 
+                                    json_object_new_string("not available"));
+            l_voting_params->delegate_key_required ? 
+                json_object_object_add(json_obj_item,"Delegated key for participating in voting", json_object_new_string("required")):
+                json_object_object_add(json_obj_item,"Delegated key for participating in voting", json_object_new_string("not required"));                 
+
+            dap_list_free_full(l_voting_params->answers_list, NULL);
+            DAP_DELETE(l_voting_params->voting_question);
+            DAP_DELETE(l_voting_params);
+        } break;
+        case TX_ITEM_TYPE_VOTE:{
+            dap_chain_tx_vote_t *l_vote_item = (dap_chain_tx_vote_t *)item;
+            const char *l_hash_str = dap_chain_hash_fast_to_str_static(&l_vote_item->voting_hash);
+            json_object_object_add(json_obj_item,"type", json_object_new_string("vote"));
+            json_object_object_add(json_obj_item,"voting_hash", json_object_new_string(l_hash_str));
+            json_object_object_add(json_obj_item,"vote_answer_idx", json_object_new_uint64(l_vote_item->answer_idx));
+
+        } break;
+        default:
+            json_object_object_add(json_obj_item,"type", json_object_new_string("This transaction have unknown item type"));
+            break;
+        }
+        json_object_array_add(json_arr_items, json_obj_item);
+    }
+
+    json_object_object_add(json_obj_out, "items", json_arr_items);
+
+    if(a_out_json)
+        a_out_json = json_obj_out;
+
+
+    return 0;
+}
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index 663e6e8211..96d0ef2cdc 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -106,6 +106,8 @@
 #include "dap_enc.h"
 #include "dap_notify_srv.h"
 
+#include "dap_chain_net_tx.h"
+
 #define LOG_TAG "chain_node_cli_cmd"
 
 int _cmd_mempool_add_ca(dap_chain_net_t *a_net, dap_chain_t *a_chain, dap_cert_t *a_cert, void **a_str_reply);
@@ -5995,116 +5997,6 @@ int com_chain_ca_pub( int a_argc,  char ** a_argv, void **a_str_reply)
     }
 }
 
-
-static const char* s_json_get_text(struct json_object *a_json, const char *a_key)
-{
-    if(!a_json || !a_key)
-        return NULL;
-    struct json_object *l_json = json_object_object_get(a_json, a_key);
-    if(l_json && json_object_is_type(l_json, json_type_string)) {
-        // Read text
-        return json_object_get_string(l_json);
-    }
-    return NULL;
-}
-
-static bool s_json_get_int64(struct json_object *a_json, const char *a_key, int64_t *a_out)
-{
-    if(!a_json || !a_key || !a_out)
-        return false;
-    struct json_object *l_json = json_object_object_get(a_json, a_key);
-    if(l_json) {
-        if(json_object_is_type(l_json, json_type_int)) {
-            // Read number
-            *a_out = json_object_get_int64(l_json);
-            return true;
-        }
-    }
-    return false;
-}
-
-static bool s_json_get_unit(struct json_object *a_json, const char *a_key, dap_chain_net_srv_price_unit_uid_t *a_out)
-{
-    const char *l_unit_str = s_json_get_text(a_json, a_key);
-    if(!l_unit_str || !a_out)
-        return false;
-    dap_chain_net_srv_price_unit_uid_t l_unit = dap_chain_net_srv_price_unit_uid_from_str(l_unit_str);
-    if(l_unit.enm == SERV_UNIT_UNDEFINED)
-        return false;
-    a_out->enm = l_unit.enm;
-    return true;
-}
-
-static bool s_json_get_uint256(struct json_object *a_json, const char *a_key, uint256_t *a_out)
-{
-    const char *l_uint256_str = s_json_get_text(a_json, a_key);
-    if(!a_out || !l_uint256_str)
-        return false;
-    uint256_t l_value = dap_chain_balance_scan(l_uint256_str);
-    if(!IS_ZERO_256(l_value)) {
-        memcpy(a_out, &l_value, sizeof(uint256_t));
-        return true;
-    }
-    return false;
-}
-
-// service names: srv_stake, srv_vpn, srv_xchange
-static bool s_json_get_srv_uid(struct json_object *a_json, const char *a_key_service_id, const char *a_key_service, uint64_t *a_out)
-{
-    uint64_t l_srv_id;
-    if(!a_out)
-        return false;
-    // Read service id
-    if(s_json_get_int64(a_json, a_key_service_id, (int64_t*) &l_srv_id)) {
-        *a_out = l_srv_id;
-        return true;
-    }
-    else {
-        // Read service as name
-        const char *l_service = s_json_get_text(a_json, a_key_service);
-        if(l_service) {
-            dap_chain_net_srv_t *l_srv = dap_chain_net_srv_get_by_name(l_service);
-            if(!l_srv)
-                return false;
-            *a_out = l_srv->uid.uint64;
-            return true;
-        }
-    }
-    return false;
-}
-
-static dap_chain_wallet_t* s_json_get_wallet(struct json_object *a_json, const char *a_key)
-{
-    return dap_chain_wallet_open(s_json_get_text(a_json, a_key), dap_chain_wallet_get_path(g_config), NULL);
-}
-
-static const dap_cert_t* s_json_get_cert(struct json_object *a_json, const char *a_key)
-{
-    return dap_cert_find_by_name(s_json_get_text(a_json, a_key));
-}
-
-// Read pkey from wallet or cert
-static dap_pkey_t* s_json_get_pkey(struct json_object *a_json)
-{
-    dap_pkey_t *l_pub_key = NULL;
-    // From wallet
-    dap_chain_wallet_t *l_wallet = s_json_get_wallet(a_json, "wallet");
-    if(l_wallet) {
-        l_pub_key = dap_chain_wallet_get_pkey(l_wallet, 0);
-        dap_chain_wallet_close(l_wallet);
-        if(l_pub_key) {
-            return l_pub_key;
-        }
-    }
-    // From cert
-    const dap_cert_t *l_cert = s_json_get_cert(a_json, "cert");
-    if(l_cert) {
-        l_pub_key = dap_pkey_from_enc_key(l_cert->enc_key);
-    }
-    return l_pub_key;
-}
-
-
 /**
  * @brief Create transaction from json file
  * com_tx_create command
@@ -6121,9 +6013,6 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply)
     const char *l_chain_name = NULL; // optional parameter
     const char *l_json_file_path = NULL;
     const char *l_json_str = NULL;
-    const char *l_native_token = NULL;
-    const char *l_main_token = NULL;
-    bool l_multichanel = false;
 
     dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_name); // optional parameter
     dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-chain", &l_chain_name); // optional parameter
@@ -6131,9 +6020,9 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply)
     dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-json_str", &l_json_str);
 
     if(!l_json_file_path && !l_json_str) {
-        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_REQUIRE_PARAMETER_JSON,
+        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NET_TX_CREATE_JSON_REQUIRE_PARAMETER_JSON,
                                "Command requires one of parameters '-json <json file path> or -json_srt <string>'");
-        return DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_REQUIRE_PARAMETER_JSON;
+        return DAP_CHAIN_NET_TX_CREATE_JSON_REQUIRE_PARAMETER_JSON;
     } 
 
     // Open json file
@@ -6141,22 +6030,22 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply)
     if (l_json_file_path){
         l_json = json_object_from_file(l_json_file_path);
         if(!l_json) {
-            dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_CAN_NOT_OPEN_JSON_FILE,
+            dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NET_TX_CREATE_JSON_CAN_NOT_OPEN_JSON_FILE,
                                 "Can't open json file: %s", json_util_get_last_err());
-            return DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_CAN_NOT_OPEN_JSON_FILE;
+            return DAP_CHAIN_NET_TX_CREATE_JSON_CAN_NOT_OPEN_JSON_FILE;
         }
     } else if (l_json_str) {
         l_json = json_tokener_parse(l_json_str);
         if(!l_json) {
-            dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_CAN_NOT_OPEN_JSON_FILE,
+            dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NET_TX_CREATE_JSON_CAN_NOT_OPEN_JSON_FILE,
                                 "Can't parse input JSON-string", json_util_get_last_err());
-            return DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_CAN_NOT_OPEN_JSON_FILE;
+            return DAP_CHAIN_NET_TX_CREATE_JSON_CAN_NOT_OPEN_JSON_FILE;
         }
     }
     if(!json_object_is_type(l_json, json_type_object)) {
-        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_WRONG_JSON_FORMAT, "Wrong json format");
+        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NET_TX_CREATE_JSON_WRONG_JSON_FORMAT, "Wrong json format");
         json_object_put(l_json);
-        return DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_WRONG_JSON_FORMAT;
+        return DAP_CHAIN_NET_TX_CREATE_JSON_WRONG_JSON_FORMAT;
     }
 
     
@@ -6167,20 +6056,19 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply)
             l_net_name = json_object_get_string(l_json_net);
         }
         if(!l_net_name) {
-            dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_REQUIRE_PARAMETER_NET,
+            dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NET_TX_CREATE_JSON_REQUIRE_PARAMETER_NET,
                                    "Command requires parameter '-net' or set net in the json file");
             json_object_put(l_json);
-            return DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_REQUIRE_PARAMETER_NET;
+            return DAP_CHAIN_NET_TX_CREATE_JSON_REQUIRE_PARAMETER_NET;
         }
     }
     dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_name);
     if(!l_net) {
-        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_NOT_FOUNT_NET_BY_NAME, "Not found net by name '%s'", l_net_name);
+        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NET_TX_CREATE_JSON_NOT_FOUNT_NET_BY_NAME, "Not found net by name '%s'", l_net_name);
         json_object_put(l_json);
-        return DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_NOT_FOUNT_NET_BY_NAME;
+        return DAP_CHAIN_NET_TX_CREATE_JSON_NOT_FOUNT_NET_BY_NAME;
     }
-    l_native_token = l_net->pub.native_ticker;
-
+    
     // Read chain from json file
     if(!l_chain_name) {
         struct json_object *l_json_chain = json_object_object_get(l_json, "chain");
@@ -6193,707 +6081,26 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply)
         l_chain = dap_chain_net_get_chain_by_chain_type(l_net, CHAIN_TYPE_TX);
     }
     if(!l_chain) {
-        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_NOT_FOUNT_CHAIN_BY_NAME,
+        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NET_TX_CREATE_JSON_NOT_FOUNT_CHAIN_BY_NAME,
                                "Chain name '%s' not found, try use parameter '-chain' or set chain in the json file", l_chain_name);
         json_object_put(l_json);
-        return DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_NOT_FOUNT_CHAIN_BY_NAME;
-    }
-
-
-    // Read items from json file
-    struct json_object *l_json_items = json_object_object_get(l_json, "items");
-    size_t l_items_count;
-    if(!l_json_items || !json_object_is_type(l_json_items, json_type_array) || !(l_items_count = json_object_array_length(l_json_items))) {
-        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_NOT_FOUNT_ARRAY_ITEMS,
-                               "Wrong json format: not found array 'items' or array is empty");
-        json_object_put(l_json);
-        return DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_NOT_FOUNT_ARRAY_ITEMS;
-    }
-
-    log_it(L_ERROR, "Json TX: found %lu items", l_items_count);
-    // Create transaction
-    dap_chain_datum_tx_t *l_tx = DAP_NEW_Z_SIZE(dap_chain_datum_tx_t, sizeof(dap_chain_datum_tx_t));
-    if(!l_tx) {
-        json_object_put(l_json);
-        dap_json_rpc_allocation_error(*a_json_arr_reply);
-        return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED;
-    }
-
-    struct json_object *l_json_timestamp = json_object_object_get(l_json, "ts_created");
-    if (l_json_timestamp)
-        l_tx->header.ts_created = json_object_get_int64(l_json_timestamp);
-    else
-        l_tx->header.ts_created = time(NULL);
-
-    size_t l_items_ready = 0;
-    dap_list_t *l_sign_list = NULL;// list 'sing' items
-    dap_list_t *l_in_list = NULL;// list 'in' items
-    uint256_t l_value_need = { };// how many tokens are needed in the 'out' item
-    uint256_t l_value_need_fee = {};
-    json_object *l_jobj_errors = json_object_new_array();
-    // First iteration in input file. Check the tx will be multichannel or not
-    for(size_t i = 0; i < l_items_count; ++i) {
-        struct json_object *l_json_item_obj = json_object_array_get_idx(l_json_items, i);
-        if(!l_json_item_obj || !json_object_is_type(l_json_item_obj, json_type_object)) {
-            continue;
-        }
-        struct json_object *l_json_item_type = json_object_object_get(l_json_item_obj, "type");
-        if(!l_json_item_type && json_object_is_type(l_json_item_type, json_type_string)) {
-            log_it(L_WARNING, "Item %zu without type", i);
-            continue;
-        }
-        const char *l_item_type_str = json_object_get_string(l_json_item_type);
-        dap_chain_tx_item_type_t l_item_type = dap_chain_datum_tx_item_str_to_type(l_item_type_str);
-        if(l_item_type == TX_ITEM_TYPE_UNKNOWN) {
-            log_it(L_WARNING, "Item %zu has invalid type '%s'", i, l_item_type_str);
-            continue;
-        }
-
-        switch (l_item_type) {
-            case TX_ITEM_TYPE_IN: {
-                const char *l_json_item_token = s_json_get_text(l_json_item_obj, "token");
-                if (l_json_item_token && dap_strcmp(l_json_item_token, l_native_token)){
-                    l_multichanel = true;
-                    l_main_token = l_json_item_token;
-                }
-            }break;
-            default: continue;
-        }
-        if(l_multichanel)
-            break;
-    }
-
-    // Creating and adding items to the transaction
-    for(size_t i = 0; i < l_items_count; ++i) {
-        struct json_object *l_json_item_obj = json_object_array_get_idx(l_json_items, i);
-        if(!l_json_item_obj || !json_object_is_type(l_json_item_obj, json_type_object)) {
-            continue;
-        }
-        struct json_object *l_json_item_type = json_object_object_get(l_json_item_obj, "type");
-        if(!l_json_item_type && json_object_is_type(l_json_item_type, json_type_string)) {
-            log_it(L_WARNING, "Item %zu without type", i);
-            continue;
-        }
-        const char *l_item_type_str = json_object_get_string(l_json_item_type);
-        dap_chain_tx_item_type_t l_item_type = dap_chain_datum_tx_item_str_to_type(l_item_type_str);
-        if(l_item_type == TX_ITEM_TYPE_UNKNOWN) {
-            log_it(L_WARNING, "Item %zu has invalid type '%s'", i, l_item_type_str);
-            continue;
-        }
-
-        log_it(L_DEBUG, "Json TX: process item %s", json_object_get_string(l_json_item_type));
-        // Create an item depending on its type
-        const uint8_t *l_item = NULL;
-        switch (l_item_type) {
-        case TX_ITEM_TYPE_IN: {
-            // Save item obj for in
-            // Read prev_hash and out_prev_idx
-            const char *l_prev_hash_str = s_json_get_text(l_json_item_obj, "prev_hash");
-            int64_t l_out_prev_idx;
-            bool l_is_out_prev_idx = s_json_get_int64(l_json_item_obj, "out_prev_idx", &l_out_prev_idx);
-            // If prev_hash and out_prev_idx were read
-            if(l_prev_hash_str && l_is_out_prev_idx) {
-                dap_chain_hash_fast_t l_tx_prev_hash;
-                if(!dap_chain_hash_fast_from_str(l_prev_hash_str, &l_tx_prev_hash)) {
-                    // Create IN item
-                    dap_chain_tx_in_t *l_in_item = dap_chain_datum_tx_item_in_create(&l_tx_prev_hash, (uint32_t) l_out_prev_idx);
-                    if (!l_in_item) {
-                        json_object *l_jobj_err = json_object_new_string("Unable to create in for transaction.");
-                        json_object_array_add(l_jobj_errors, l_jobj_err);
-                    }
-                    l_item = (const uint8_t*) l_in_item;
-                } else {
-                    log_it(L_WARNING, "Invalid 'in' item, bad prev_hash %s", l_prev_hash_str);
-                    char *l_str_err = dap_strdup_printf("Unable to create in for transaction. Invalid 'in' item, "
-                                                        "bad prev_hash %s", l_prev_hash_str);
-                    json_object *l_jobj_err = json_object_new_string(l_str_err);
-                    json_object_array_add(l_jobj_errors, l_jobj_err);
-                }
-            }
-            // Read addr_from
-            else {
-               l_in_list = dap_list_append(l_in_list, l_json_item_obj);
-            }
-        }
-            break;
-
-        case TX_ITEM_TYPE_OUT:
-        case TX_ITEM_TYPE_OUT_EXT: {
-            // Read address and value
-            uint256_t l_value = { };
-            const char *l_json_item_addr_str = s_json_get_text(l_json_item_obj, "addr");
-            bool l_is_value = s_json_get_uint256(l_json_item_obj, "value", &l_value);
-            const char *l_token = s_json_get_text(l_json_item_obj, "token");
-            if(l_is_value && l_json_item_addr_str) {
-                dap_chain_addr_t *l_addr = dap_chain_addr_from_str(l_json_item_addr_str);
-                if(l_addr && !IS_ZERO_256(l_value)) {
-                    if(l_item_type == TX_ITEM_TYPE_OUT) {
-                        // Create OUT item
-                        const uint8_t *l_out_item = NULL;
-                            if(l_multichanel)
-                                l_out_item = (const uint8_t *)dap_chain_datum_tx_item_out_ext_create(l_addr, l_value, l_token ? l_token : (l_main_token ? l_main_token : l_native_token));
-                            else
-                                l_out_item = (const uint8_t *)dap_chain_datum_tx_item_out_create(l_addr, l_value);
-                        if (!l_out_item) {
-                            json_object *l_jobj_err = json_object_new_string("Failed to create transaction out. "
-                                                                             "There may not be enough funds in the wallet.");
-                            json_object_array_add(l_jobj_errors, l_jobj_err);
-                        }
-                        l_item = (const uint8_t*) l_out_item;
-                        if (l_item){
-                            if (l_multichanel && !dap_strcmp(((dap_chain_tx_out_ext_t*)l_out_item)->token, l_native_token))
-                                SUM_256_256(l_value_need_fee, l_value, &l_value_need_fee);
-                            else
-                                SUM_256_256(l_value_need, l_value, &l_value_need);
-                        }
-                            
-                    } else if(l_item_type == TX_ITEM_TYPE_OUT_EXT) {
-                        // Read address and value
-                        if(l_token) {
-                            // Create OUT_EXT item
-                            const uint8_t *l_out_item = NULL;
-                            if(l_multichanel)
-                                l_out_item = (const uint8_t *)dap_chain_datum_tx_item_out_ext_create(l_addr, l_value, l_token);
-                            else
-                                l_out_item = (const uint8_t *)dap_chain_datum_tx_item_out_create(l_addr, l_value);
-                            if (!l_out_item) {
-                                json_object *l_jobj_err = json_object_new_string("Failed to create a out ext"
-                                                                    "for a transaction. There may not be enough funds "
-                                                                    "on the wallet or the wrong ticker token "
-                                                                    "is indicated.");
-                                json_object_array_add(l_jobj_errors, l_jobj_err);
-                            }
-                            l_item = (const uint8_t*) l_out_item;
-                            if (l_item){
-                                if (l_multichanel && !dap_strcmp(l_token, l_native_token))
-                                    SUM_256_256(l_value_need_fee, l_value, &l_value_need_fee);
-                                else 
-                                    SUM_256_256(l_value_need, l_value, &l_value_need);
-                            }
-                        }
-                        else {
-                            log_it(L_WARNING, "Invalid 'out_ext' item %zu", i);
-                            continue;
-                        }
-                    }
-                } else {
-                    if(l_item_type == TX_ITEM_TYPE_OUT) {
-                        log_it(L_WARNING, "Invalid 'out' item %zu", i);
-                    }
-                    else if(l_item_type == TX_ITEM_TYPE_OUT_EXT) {
-                        log_it(L_WARNING, "Invalid 'out_ext' item %zu", i);
-                    }
-                    char *l_str_err = dap_strdup_printf("For item %zu of type 'out' or 'out_ext' the "
-                                                        "string representation of the address could not be converted, "
-                                                        "or the size of the output sum is 0.", i);
-                    json_object *l_jobj_err = json_object_new_string(l_str_err);
-                    DAP_DELETE(l_str_err);
-                    json_object_array_add(l_jobj_errors, l_jobj_err);
-                    continue;
-                }
-            }
-        }
-            break;
-        case TX_ITEM_TYPE_OUT_COND: {
-            // Read subtype of item
-            const char *l_subtype_str = s_json_get_text(l_json_item_obj, "subtype");
-            dap_chain_tx_out_cond_subtype_t l_subtype = dap_chain_tx_out_cond_subtype_from_str(l_subtype_str);
-            switch (l_subtype) {
-
-            case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY:{
-                uint256_t l_value = { };
-                bool l_is_value = s_json_get_uint256(l_json_item_obj, "value", &l_value);
-                if(!l_is_value || IS_ZERO_256(l_value)) {
-                    log_it(L_ERROR, "Json TX: bad value in OUT_COND_SUBTYPE_SRV_PAY");
-                    break;
-                }
-                uint256_t l_value_max_per_unit = { };
-                l_is_value = s_json_get_uint256(l_json_item_obj, "value_max_per_unit", &l_value_max_per_unit);
-                if(!l_is_value || IS_ZERO_256(l_value_max_per_unit)) {
-                    log_it(L_ERROR, "Json TX: bad value_max_per_unit in OUT_COND_SUBTYPE_SRV_PAY");
-                    break;
-                }
-                dap_chain_net_srv_price_unit_uid_t l_price_unit;
-                if(!s_json_get_unit(l_json_item_obj, "price_unit", &l_price_unit)) {
-                    log_it(L_ERROR, "Json TX: bad price_unit in OUT_COND_SUBTYPE_SRV_PAY");
-                    break;
-                }
-                dap_chain_net_srv_uid_t l_srv_uid;
-                if(!s_json_get_srv_uid(l_json_item_obj, "service_id", "service", &l_srv_uid.uint64)){
-                    // Default service DAP_CHAIN_NET_SRV_VPN_ID
-                    l_srv_uid.uint64 = 0x0000000000000001;
-                }
-
-                // From "wallet" or "cert"
-                dap_pkey_t *l_pkey = s_json_get_pkey(l_json_item_obj);
-                if(!l_pkey) {
-                    log_it(L_ERROR, "Json TX: bad pkey in OUT_COND_SUBTYPE_SRV_PAY");
-                    break;
-                }
-                const char *l_params_str = s_json_get_text(l_json_item_obj, "params");
-                size_t l_params_size = dap_strlen(l_params_str);
-                dap_chain_tx_out_cond_t *l_out_cond_item = dap_chain_datum_tx_item_out_cond_create_srv_pay(l_pkey, l_srv_uid, l_value, l_value_max_per_unit,
-                        l_price_unit, l_params_str, l_params_size);
-                l_item = (const uint8_t*) l_out_cond_item;
-                // Save value for using in In item
-                if(l_item) {
-                    SUM_256_256(l_value_need, l_value, &l_value_need);
-                } else {
-                    char *l_str_err = dap_strdup_printf("Unable to create conditional out for transaction "
-                                                        "can of type %s described in item %zu.\n", l_subtype_str, i);
-                    json_object *l_jobj_err = json_object_new_string(l_str_err);
-                    DAP_DELETE(l_str_err);
-                    json_object_array_add(l_jobj_errors, l_jobj_err);
-                }
-                DAP_DELETE(l_pkey);
-            }
-                break;
-            case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE: {
-
-                dap_chain_net_srv_uid_t l_srv_uid;
-                if(!s_json_get_srv_uid(l_json_item_obj, "service_id", "service", &l_srv_uid.uint64)) {
-                    // Default service DAP_CHAIN_NET_SRV_XCHANGE_ID
-                    l_srv_uid.uint64 = 0x2;
-                }
-                dap_chain_net_t *l_net = dap_chain_net_by_name(s_json_get_text(l_json_item_obj, "net"));
-                if(!l_net) {
-                    log_it(L_ERROR, "Json TX: bad net in OUT_COND_SUBTYPE_SRV_XCHANGE");
-                    break;
-                }
-                const char *l_token = s_json_get_text(l_json_item_obj, "token");
-                if(!l_token) {
-                    log_it(L_ERROR, "Json TX: bad token in OUT_COND_SUBTYPE_SRV_XCHANGE");
-                    break;
-                }
-                uint256_t l_value = { };
-                if(!s_json_get_uint256(l_json_item_obj, "value", &l_value) || IS_ZERO_256(l_value)) {
-                    log_it(L_ERROR, "Json TX: bad value in OUT_COND_SUBTYPE_SRV_XCHANGE");
-                    break;
-                }
-                //const char *l_params_str = s_json_get_text(l_json_item_obj, "params");
-                //size_t l_params_size = dap_strlen(l_params_str);
-                dap_chain_tx_out_cond_t *l_out_cond_item = NULL; //dap_chain_datum_tx_item_out_cond_create_srv_xchange(l_srv_uid, l_net->pub.id, l_token, l_value, l_params_str, l_params_size);
-                l_item = (const uint8_t*) l_out_cond_item;
-                // Save value for using in In item
-                if(l_item) {
-                    SUM_256_256(l_value_need, l_value, &l_value_need);
-                } else {
-                    char *l_str_err = dap_strdup_printf("Unable to create conditional out for transaction "
-                                                         "can of type %s described in item %zu.", l_subtype_str, i);
-                    json_object *l_jobj_err = json_object_new_string(l_str_err);
-                    DAP_DELETE(l_str_err);
-                    json_object_array_add(l_jobj_errors, l_jobj_err);
-                }
-            }
-                break;
-            case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE:{
-                dap_chain_net_srv_uid_t l_srv_uid;
-                if(!s_json_get_srv_uid(l_json_item_obj, "service_id", "service", &l_srv_uid.uint64)) {
-                    // Default service DAP_CHAIN_NET_SRV_STAKE_ID
-                    l_srv_uid.uint64 = 0x13;
-                }
-                uint256_t l_value = { };
-                if(!s_json_get_uint256(l_json_item_obj, "value", &l_value) || IS_ZERO_256(l_value)) {
-                    log_it(L_ERROR, "Json TX: bad value in OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE");
-                    break;
-                }
-                uint256_t l_fee_value = { };
-                if(!s_json_get_uint256(l_json_item_obj, "fee", &l_fee_value) || IS_ZERO_256(l_fee_value)) {
-                    break;
-                }
-                
-                const char *l_signing_addr_str = s_json_get_text(l_json_item_obj, "signing_addr");
-                dap_chain_addr_t *l_signing_addr = dap_chain_addr_from_str(l_signing_addr_str);
-                if(!l_signing_addr) {
-                {
-                    log_it(L_ERROR, "Json TX: bad signing_addr in OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE");
-                    break;
-                }
-                dap_chain_node_addr_t l_signer_node_addr;
-                const char *l_node_addr_str = s_json_get_text(l_json_item_obj, "node_addr");
-                if(!l_node_addr_str || dap_chain_node_addr_from_str(&l_signer_node_addr, l_node_addr_str)) {
-                    log_it(L_ERROR, "Json TX: bad node_addr in OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE");
-                    break;
-                }
-                dap_chain_tx_out_cond_t *l_out_cond_item = dap_chain_datum_tx_item_out_cond_create_srv_stake(l_srv_uid, l_value, l_signing_addr,
-                                                                                                             &l_signer_node_addr, NULL, uint256_0);
-                l_item = (const uint8_t*) l_out_cond_item;
-                // Save value for using in In item
-                if(l_item) {
-                    SUM_256_256(l_value_need, l_value, &l_value_need);
-                } else {
-                    char *l_err_str = dap_strdup_printf("Unable to create conditional out for transaction "
-                                                        "can of type %s described in item %zu.", l_subtype_str, i);
-                    json_object *l_jobj_err = json_object_new_string(l_err_str);
-                    DAP_DELETE(l_err_str);
-                    json_object_array_add(l_jobj_errors, l_jobj_err);
-                }
-                }
-            }
-                break;
-            case DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE: {
-                uint256_t l_value = { };
-                s_json_get_uint256(l_json_item_obj, "value", &l_value);
-                if(!IS_ZERO_256(l_value)) {
-                    dap_chain_tx_out_cond_t *l_out_cond_item = dap_chain_datum_tx_item_out_cond_create_fee(l_value);
-                    l_item = (const uint8_t*) l_out_cond_item;
-                    // Save value for using in In item
-                    if(l_item) {
-                        SUM_256_256(l_value_need_fee, l_value, &l_value_need_fee);
-                    } else {
-                        char *l_str_err = dap_strdup_printf("Unable to create conditional out for transaction "
-                                                            "can of type %s described in item %zu.", l_subtype_str, i);
-                        json_object *l_jobj_err = json_object_new_string(l_str_err);
-                        json_object_array_add(l_jobj_errors, l_jobj_err);
-                        DAP_DELETE(l_str_err);
-                    }
-                }
-                else
-                    log_it(L_ERROR, "Json TX: zero value in OUT_COND_SUBTYPE_FEE");
-            }
-                break;
-            case DAP_CHAIN_TX_OUT_COND_SUBTYPE_UNDEFINED:
-                log_it(L_WARNING, "Undefined subtype: '%s' of 'out_cond' item %zu ", l_subtype_str, i);
-                char *l_str_err = dap_strdup_printf("Specified unknown sub type %s of conditional out on item %zu.",
-                                                    l_subtype_str, i);
-                json_object *l_jobj_err = json_object_new_string(l_str_err);
-                DAP_DELETE(l_str_err);
-                json_object_array_add(l_jobj_errors, l_jobj_err);
-                break;
-            }
-        }
-            break;
-        case TX_ITEM_TYPE_SIG:{          
-            const char *l_sign_type_str = s_json_get_text(l_json_item_obj, "sig_type");          
-            if (l_sign_type_str) {
-                dap_sign_type_t l_sign_type = dap_sign_type_from_str(l_sign_type_str);
-                if (l_sign_type.type == SIG_TYPE_NULL) {
-                    json_object *l_jobj_err = json_object_new_string("Can't define sign type");
-                    json_object_array_add(l_jobj_errors, l_jobj_err);
-                    log_it(L_ERROR, "Json TX: Can't define sign type \"%s\"", l_sign_type_str);
-                    break;
-                }
-                int64_t l_pkey_size, l_sig_size, l_hash_type = 0;
-
-                s_json_get_int64(l_json_item_obj, "hash_type", &l_hash_type);
-                s_json_get_int64(l_json_item_obj, "pub_key_size", &l_pkey_size);
-                s_json_get_int64(l_json_item_obj, "sig_size", &l_sig_size);
-                debug_if(!l_pkey_size || !l_sig_size, L_WARNING,
-                         "\"pub_key_size\" or \"sig_size\" not provided! Will be calculated automatically");
-                
-                json_object *l_jobj_pub_key = json_object_object_get(l_json_item_obj, "pub_key_b64"),
-                            *l_jobj_sign = json_object_object_get(l_json_item_obj, "sig_b64");
-                if (!l_jobj_pub_key || !l_jobj_sign) {
-                    json_object *l_jobj_err = json_object_new_string("Can't get base64-encoded sign or pkey!");
-                    json_object_array_add(l_jobj_errors, l_jobj_err);
-                    log_it(L_ERROR, "Json TX: Can't get base64-encoded sign or pkey!");
-                    break;
-                }
-                const char *l_pub_key_str = json_object_get_string(l_jobj_pub_key),
-                           *l_sign_str = json_object_get_string(l_jobj_sign);
-                int64_t l_pkey_decoded_size = DAP_ENC_BASE64_DECODE_SIZE(strlen(l_pub_key_str)),
-                        l_sign_decoded_size = DAP_ENC_BASE64_DECODE_SIZE(strlen(l_sign_str));
-                
-                dap_sign_t *l_sign = DAP_NEW_SIZE(dap_sign_t, sizeof(dap_sign_t) + l_pkey_decoded_size + l_sign_decoded_size);
-                *l_sign = (dap_sign_t) {
-                    .header.type = l_sign_type,
-                    .header.hash_type = (uint8_t)l_hash_type,
-                };
-                l_pkey_decoded_size = dap_enc_base64_decode(l_pub_key_str, strlen(l_pub_key_str),
-                                                            l_sign->pkey_n_sign, DAP_ENC_DATA_TYPE_B64_URLSAFE);
-                debug_if(l_pkey_size != l_pkey_decoded_size, L_ERROR, "Json TX: pkey size mismatch, %zu != %zu",
-                                                                      l_pkey_size, l_pkey_decoded_size);
-
-                l_sign_decoded_size = dap_enc_base64_decode(l_sign_str, strlen(l_sign_str),
-                                                            l_sign->pkey_n_sign + l_pkey_decoded_size, DAP_ENC_DATA_TYPE_B64_URLSAFE);
-                debug_if(l_sig_size != l_sign_decoded_size, L_ERROR, "Json TX: sign size mismatch, %zu != %zu",
-                                                                     l_sig_size, l_sign_decoded_size);
-
-                l_sign->header.sign_size = l_sign_decoded_size;
-                l_sign->header.sign_pkey_size = l_pkey_decoded_size;
-                size_t l_sign_full_size = dap_sign_get_size(l_sign);
-                
-                dap_chain_tx_sig_t *l_tx_sig = DAP_NEW_Z_SIZE(dap_chain_tx_sig_t, sizeof(dap_chain_tx_sig_t) + l_sign_full_size);
-                l_tx_sig->header.type = TX_ITEM_TYPE_SIG;
-                l_tx_sig->header.sig_size = (uint32_t)l_sign_full_size;
-                memcpy(l_tx_sig->sig, l_sign, l_sign_full_size);
-                l_item = (const uint8_t*)l_tx_sig;
-                DAP_DELETE(l_sign);
-                break;
-            } else              
-                l_sign_list = dap_list_append(l_sign_list,l_json_item_obj);
-        }
-            break;
-        case TX_ITEM_TYPE_RECEIPT: {
-            dap_chain_net_srv_uid_t l_srv_uid;
-            if(!s_json_get_srv_uid(l_json_item_obj, "service_id", "service", &l_srv_uid.uint64)) {
-                log_it(L_ERROR, "Json TX: bad service_id in TYPE_RECEIPT");
-                break;
-            }
-            dap_chain_net_srv_price_unit_uid_t l_price_unit;
-            if(!s_json_get_unit(l_json_item_obj, "price_unit", &l_price_unit)) {
-                log_it(L_ERROR, "Json TX: bad price_unit in TYPE_RECEIPT");
-                break;
-            }
-            int64_t l_units;
-            if(!s_json_get_int64(l_json_item_obj, "units", &l_units)) {
-                log_it(L_ERROR, "Json TX: bad units in TYPE_RECEIPT");
-                break;
-            }
-            uint256_t l_value = { };
-            if(!s_json_get_uint256(l_json_item_obj, "value", &l_value) || IS_ZERO_256(l_value)) {
-                log_it(L_ERROR, "Json TX: bad value in TYPE_RECEIPT");
-                break;
-            }
-            const char *l_params_str = s_json_get_text(l_json_item_obj, "params");
-            size_t l_params_size = dap_strlen(l_params_str);
-            dap_chain_datum_tx_receipt_t *l_receipt = dap_chain_datum_tx_receipt_create(l_srv_uid, l_price_unit, l_units, l_value, l_params_str, l_params_size);
-            l_item = (const uint8_t*) l_receipt;
-            if (!l_item) {
-                char *l_str_err = dap_strdup_printf("Unable to create receipt out for transaction "
-                                                    "described by item %zu.", i);
-                json_object *l_jobj_err = json_object_new_string(l_str_err);
-                DAP_DELETE(l_str_err);
-                json_object_array_add(l_jobj_errors, l_jobj_err);
-            }
-        }
-            break;
-        case TX_ITEM_TYPE_TSD: {
-            int64_t l_tsd_type;
-            if(!s_json_get_int64(l_json_item_obj, "type_tsd", &l_tsd_type)) {
-                log_it(L_ERROR, "Json TX: bad type_tsd in TYPE_TSD");
-                break;
-            }
-            const char *l_tsd_data = s_json_get_text(l_json_item_obj, "data");
-            if (!l_tsd_data) {
-                log_it(L_ERROR, "Json TX: bad data in TYPE_TSD");
-                break;
-            }
-            size_t l_data_size = dap_strlen(l_tsd_data);
-            dap_chain_tx_tsd_t *l_tsd = dap_chain_datum_tx_item_tsd_create((void*)l_tsd_data, (int)l_tsd_type, l_data_size);
-            l_item = (const uint8_t*) l_tsd;
-            // l_tsd_list = dap_list_append(l_tsd_list, l_tsd);
-        }
-            break;
-            //case TX_ITEM_TYPE_PKEY:
-                //break;
-            //case TX_ITEM_TYPE_IN_EMS:
-                //break;
-            //case TX_ITEM_TYPE_IN_EMS_EXT:
-                //break;
-        }
-        // Add item to transaction
-        if(l_item) {
-            dap_chain_datum_tx_add_item(&l_tx, (const uint8_t*) l_item);
-            l_items_ready++;
-            DAP_DELETE(l_item);
-        }
+        return DAP_CHAIN_NET_TX_CREATE_JSON_NOT_FOUNT_CHAIN_BY_NAME;
     }
     
-    dap_list_t *l_list;
-    // Add In items
-    l_list = l_in_list;
-    while(l_list) {
-        struct json_object *l_json_item_obj = (struct json_object*) l_list->data;
-
-        const char *l_json_item_addr_str = s_json_get_text(l_json_item_obj, "addr_from");
-        const char *l_json_item_token = s_json_get_text(l_json_item_obj, "token");
-        l_main_token = l_json_item_token;
-        dap_chain_addr_t *l_addr_from = NULL;
-        if(l_json_item_addr_str) {
-            l_addr_from = dap_chain_addr_from_str(l_json_item_addr_str);
-            if (!l_addr_from) {
-                log_it(L_WARNING, "Invalid element 'in', unable to convert string representation of addr_from: '%s' "
-                                    "to binary.", l_json_item_addr_str);
-                char *l_str_err = dap_strdup_printf("Invalid element 'to', unable to convert string representation "
-                                                    "of addr_from: '%s' to binary.", l_json_item_addr_str);
-                json_object *l_jobj_err = json_object_new_string(l_str_err);
-                DAP_DELETE(l_str_err);
-                json_object_array_add(l_jobj_errors, l_jobj_err);
-                // Go to the next item
-                l_list = dap_list_next(l_list);
-                continue;
-            }
-        }
-        else {
-            log_it(L_WARNING, "Invalid 'in' item, incorrect addr_from: '%s'", l_json_item_addr_str ? l_json_item_addr_str : "[null]");
-            char *l_str_err = dap_strdup_printf("Invalid 'in' item, incorrect addr_from: '%s'",
-                                        l_json_item_addr_str ? l_json_item_addr_str : "[null]");
-            json_object *l_jobj_err = json_object_new_string(l_str_err);
-            DAP_DELETE(l_str_err);
-            json_object_array_add(l_jobj_errors, l_jobj_err);
-            // Go to the next item
-            l_list = dap_list_next(l_list);
-            continue;
-        }
-        if(!l_json_item_token) {
-            log_it(L_WARNING, "Invalid 'in' item, not found token name");
-            json_object *l_jobj_err = json_object_new_string("Invalid 'in' item, not found token name");
-            json_object_array_add(l_jobj_errors, l_jobj_err);
-            // Go to the next item
-            l_list = dap_list_next(l_list);
-            continue;
-        }
-        if(IS_ZERO_256(l_value_need)) {
-            log_it(L_WARNING, "Invalid 'in' item, not found value in out items");
-            json_object *l_jobj_err = json_object_new_string("Invalid 'in' item, not found value in out items");
-            json_object_array_add(l_jobj_errors, l_jobj_err);
-            // Go to the next item
-            l_list = dap_list_next(l_list);
-            continue;
-        }
-        if(l_addr_from)
-        {
-            // find the transactions from which to take away coins
-            dap_list_t *l_list_used_out = NULL;
-            dap_list_t *l_list_used_out_fee = NULL;
-            uint256_t l_value_transfer = { }; // how many coins to transfer
-            uint256_t l_value_transfer_fee = { }; // how many coins to transfer
-            //SUM_256_256(a_value, a_value_fee, &l_value_need);
-            uint256_t l_value_need_check = {};
-            if (!dap_strcmp(l_native_token, l_main_token)) {
-                SUM_256_256(l_value_need_check, l_value_need, &l_value_need_check);
-                SUM_256_256(l_value_need_check, l_value_need_fee, &l_value_need_check);
-                l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_net->pub.ledger, l_json_item_token,
-                                                                                            l_addr_from, l_value_need_check, &l_value_transfer);
-                if(!l_list_used_out) {
-                    log_it(L_WARNING, "Not enough funds in previous tx to transfer");
-                    json_object *l_jobj_err = json_object_new_string("Can't create in transaction. Not enough funds in previous tx "
-                                                        "to transfer");
-                    json_object_array_add(l_jobj_errors, l_jobj_err);
-                    // Go to the next item
-                    l_list = dap_list_next(l_list);
-                    continue;
-                }
-            } else {
-                //CHECK value need
-                l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_net->pub.ledger, l_json_item_token,
-                                                                                            l_addr_from, l_value_need, &l_value_transfer);
-                if(!l_list_used_out) {
-                    log_it(L_WARNING, "Not enough funds in previous tx to transfer");
-                    json_object *l_jobj_err = json_object_new_string("Can't create in transaction. Not enough funds "
-                                                                        "in previous tx to transfer");
-                    json_object_array_add(l_jobj_errors, l_jobj_err);
-                    // Go to the next item
-                    l_list = dap_list_next(l_list);
-                    continue;
-                }
-                //CHECK value fee
-                l_list_used_out_fee = dap_ledger_get_list_tx_outs_with_val(l_net->pub.ledger, l_native_token,
-                                                                                    l_addr_from, l_value_need_fee, &l_value_transfer_fee);
-                if(!l_list_used_out_fee) {
-                    log_it(L_WARNING, "Not enough funds in previous tx to transfer");
-                    json_object *l_jobj_err = json_object_new_string("Can't create in transaction. Not enough funds "
-                                                                        "in previous tx to transfer");
-                    json_object_array_add(l_jobj_errors, l_jobj_err);
-                    // Go to the next item
-                    l_list = dap_list_next(l_list);
-                    continue;
-                }
-            }
-            // add 'in' items
-            uint256_t l_value_got = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out);
-            assert(EQUAL_256(l_value_got, l_value_transfer));
-            if (l_list_used_out_fee) {
-                uint256_t l_value_got_fee = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out_fee);
-                assert(EQUAL_256(l_value_got_fee, l_value_transfer_fee));
-                dap_list_free_full(l_list_used_out_fee, free);
-                // add 'out' item for coin fee back
-                uint256_t  l_value_back;
-                SUBTRACT_256_256(l_value_got_fee, l_value_need_fee, &l_value_back);
-                if (!IS_ZERO_256(l_value_back)) {
-                    dap_chain_datum_tx_add_out_ext_item(&l_tx, l_addr_from, l_value_back, l_native_token);
-                    l_items_ready++;
-                }
-            } else {
-                SUM_256_256(l_value_need, l_value_need_fee, &l_value_need);
-            }
-            dap_list_free_full(l_list_used_out, free);
-            if(!IS_ZERO_256(l_value_got)) {
-                // add 'out' item for coin back
-                uint256_t l_value_back;
-                SUBTRACT_256_256(l_value_got, l_value_need, &l_value_back);
-                if(!IS_ZERO_256(l_value_back)) {
-                    if (l_multichanel)
-                        dap_chain_datum_tx_add_out_ext_item(&l_tx, l_addr_from, l_value_back, l_main_token);
-                    else
-                        dap_chain_datum_tx_add_out_item(&l_tx, l_addr_from, l_value_back);
-                    l_items_ready++;
-                }
-            }
-        }
-        // Go to the next 'in' item
-        l_list = dap_list_next(l_list);
-    }
-    dap_list_free(l_in_list);
-
-    // Add signs
-    l_list = l_sign_list;
-    while(l_list) {
-
-        struct json_object *l_json_item_obj = (struct json_object*) l_list->data;
-
-        dap_enc_key_t * l_enc_key  = NULL;
-        
-        //get wallet or cert
-        dap_chain_wallet_t *l_wallet = s_json_get_wallet(l_json_item_obj, "wallet");
-        const dap_cert_t *l_cert = s_json_get_cert(l_json_item_obj, "cert");
-
-        int64_t l_pkey_size;
-        int64_t l_sig_size;
-        uint8_t *l_pkey = NULL;
-        int64_t l_hash_type = 0;
-        dap_sign_t *l_sign = NULL;
-        
-
-        //wallet goes first
-        if (l_wallet) {
-            l_enc_key = dap_chain_wallet_get_key(l_wallet, 0);
-        } else if (l_cert && l_cert->enc_key) {
-            l_enc_key = l_cert->enc_key; 
-        } else { 
-            json_object *l_jobj_err = json_object_new_string("Can't create sign for transactions.");
-            json_object_array_add(l_jobj_errors, l_jobj_err);
-            log_it(L_ERROR, "Json TX: Item sign has no wallet or cert of they are invalid ");
-            l_list = dap_list_next(l_list);
-            continue;
-        }
-
-        if (l_sign) {
-            size_t l_chain_sign_size = dap_sign_get_size(l_sign); // sign data
-            
-            dap_chain_tx_sig_t *l_tx_sig = DAP_NEW_Z_SIZE(dap_chain_tx_sig_t,
-                    sizeof(dap_chain_tx_sig_t) + l_chain_sign_size);
-            l_tx_sig->header.type = TX_ITEM_TYPE_SIG;
-            l_tx_sig->header.sig_size =(uint32_t) l_chain_sign_size;
-            memcpy(l_tx_sig->sig, l_sign, l_chain_sign_size);
-            dap_chain_datum_tx_add_item(&l_tx, l_tx_sig);
-            DAP_DELETE(l_sign);
-        }
-
-        if(l_enc_key && dap_chain_datum_tx_add_sign_item(&l_tx, l_enc_key) > 0) {
-            l_items_ready++;
-        } else {
-            log_it(L_ERROR, "Json TX: Item sign has invalid enc_key.");
-            l_list = dap_list_next(l_list);
-            continue;
-        }
-
-        if (l_wallet) {
-            dap_chain_wallet_close(l_wallet);  
-            dap_enc_key_delete(l_enc_key);
-        }  
-
-    
-        l_list = dap_list_next(l_list);
+    json_object *l_jobj_errors = json_object_new_array();
+    size_t l_items_ready = 0, l_items_count = 0;
+    dap_chain_datum_tx_t *l_tx = NULL;
+    int l_ret = 0;
+    if((l_ret = dap_chain_net_tx_create_by_json(l_json, l_net, l_jobj_errors, &l_tx, &l_items_count, &l_items_ready, a_json_arr_reply)) != DAP_CHAIN_NET_TX_CREATE_JSON_OK) {
+        dap_json_rpc_error_add(*a_json_arr_reply, l_ret,
+                               "Can't create transaction from json file");
+        json_object_put(l_json);
+        return l_ret;
     }
 
-    dap_list_free(l_sign_list);
-    json_object_put(l_json);
-
     json_object *l_jobj_ret = json_object_new_object();
 
-    if(l_items_ready<l_items_count) {
+    if(l_items_ready < l_items_count) {
         json_object *l_tx_create = json_object_new_boolean(false);
         json_object *l_jobj_valid_items = json_object_new_uint64(l_items_ready);
         json_object *l_jobj_total_items = json_object_new_uint64(l_items_count);
@@ -6903,7 +6110,7 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply)
         json_object_object_add(l_jobj_ret, "errors", l_jobj_errors);
         json_object_array_add(*a_json_arr_reply, l_jobj_ret);
         DAP_DELETE(l_tx);
-        return DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_INVALID_ITEMS;
+        return DAP_CHAIN_NET_TX_CREATE_JSON_INVALID_ITEMS;
     }
     json_object_put(l_jobj_errors);
 
@@ -6920,9 +6127,9 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply)
     DAP_DEL_Z(l_datum_tx);
     DAP_DELETE(l_gdb_group_mempool_base_tx);
     if(!l_placed) {
-        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_CAN_NOT_ADD_TRANSACTION_TO_MEMPOOL,
+        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NET_TX_CREATE_JSON_CAN_NOT_ADD_TRANSACTION_TO_MEMPOOL,
                                "Can't add transaction to mempool");
-        return DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_CAN_NOT_ADD_TRANSACTION_TO_MEMPOOL;
+        return DAP_CHAIN_NET_TX_CREATE_JSON_CAN_NOT_ADD_TRANSACTION_TO_MEMPOOL;
     }
     // Completed successfully
     json_object *l_jobj_tx_create = json_object_new_boolean(true);
@@ -6932,7 +6139,7 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply)
     json_object_object_add(l_jobj_ret, "hash", l_jobj_hash);
     json_object_object_add(l_jobj_ret, "total_items", l_jobj_total_items);
     json_object_array_add(*a_json_arr_reply, l_jobj_ret);
-    return DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_OK;
+    return DAP_CHAIN_NET_TX_CREATE_JSON_OK;
 }
 
 /**
diff --git a/modules/net/include/dap_chain_net_tx.h b/modules/net/include/dap_chain_net_tx.h
index b06d35012f..b6e33b42e5 100644
--- a/modules/net/include/dap_chain_net_tx.h
+++ b/modules/net/include/dap_chain_net_tx.h
@@ -25,7 +25,21 @@
 
 #include "dap_chain_net.h"
 #include "dap_chain_datum_tx_items.h"
-
+#include "dap_json_rpc_errors.h"
+
+typedef enum s_com_tx_create_json_err {
+    DAP_CHAIN_NET_TX_CREATE_JSON_OK = 0,
+    DAP_CHAIN_NET_TX_CREATE_JSON_REQUIRE_PARAMETER_JSON = DAP_JSON_RPC_ERR_CODE_METHOD_ERR_START,
+    DAP_CHAIN_NET_TX_CREATE_JSON_CAN_NOT_OPEN_JSON_FILE,
+    DAP_CHAIN_NET_TX_CREATE_JSON_WRONG_JSON_FORMAT,
+    DAP_CHAIN_NET_TX_CREATE_JSON_REQUIRE_PARAMETER_NET,
+    DAP_CHAIN_NET_TX_CREATE_JSON_NOT_FOUNT_NET_BY_NAME,
+    DAP_CHAIN_NET_TX_CREATE_JSON_NOT_FOUNT_CHAIN_BY_NAME,
+    DAP_CHAIN_NET_TX_CREATE_JSON_NOT_FOUNT_ARRAY_ITEMS,
+    DAP_CHAIN_NET_TX_CREATE_JSON_INVALID_ITEMS,
+    DAP_CHAIN_NET_TX_CREATE_JSON_CAN_NOT_ADD_TRANSACTION_TO_MEMPOOL,
+    DAP_CHAIN_NET_TX_CREATE_JSON_WRONG_ARGUMENTS,
+}s_com_tx_create_json_err_t;
 typedef enum dap_chain_net_tx_search_type {
     /// Search local, in memory, possible load data from drive to memory
     TX_SEARCH_TYPE_LOCAL,
@@ -91,3 +105,17 @@ void dap_chain_datum_tx_spends_items_free(dap_chain_datum_tx_spends_items_t * a_
 
 bool dap_chain_net_tx_get_fee(dap_chain_net_id_t a_net_id, uint256_t *a_value, dap_chain_addr_t *a_addr);
 bool dap_chain_net_tx_set_fee(dap_chain_net_id_t a_net_id, uint256_t a_value, dap_chain_addr_t a_addr);
+
+/**
+ * @brief Compose transaction from json. If a_net is NULL it means offline tx creation and 
+ *          tx will be created from json as is without any checks and conversions.
+ * @param a_tx_json input json
+ * @param a_net network. If NULL it means offline tx creation
+ * @param a_out_tx output transaction
+ * @param a_items_count count of items in transaction
+ */
+int dap_chain_net_tx_create_by_json(json_object *a_tx_json, dap_chain_net_t *a_net, json_object *a_json_obj_error, 
+                                        dap_chain_datum_tx_t** a_out_tx, size_t* a_items_count, size_t *a_items_ready, void **a_json_arr_reply);
+
+
+int dap_chain_net_tx_to_json(dap_chain_datum_tx_t *a_tx, json_object *a_out_json);
\ No newline at end of file
diff --git a/modules/net/include/dap_chain_node_cli_cmd.h b/modules/net/include/dap_chain_node_cli_cmd.h
index 5304912bad..93572f9e91 100644
--- a/modules/net/include/dap_chain_node_cli_cmd.h
+++ b/modules/net/include/dap_chain_node_cli_cmd.h
@@ -211,18 +211,7 @@ typedef enum s_com_tx_create_err{
     DAP_CHAIN_NODE_CLI_COM_TX_CREATE_EQ_SOURCE_DESTINATION_ADDRESS
 }s_com_tx_create_err_t;
 int com_tx_create(int a_argc, char **a_argv, void **a_str_reply);
-typedef enum s_com_tx_create_json_err {
-    DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_OK = 0,
-    DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_REQUIRE_PARAMETER_JSON = DAP_JSON_RPC_ERR_CODE_METHOD_ERR_START,
-    DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_CAN_NOT_OPEN_JSON_FILE,
-    DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_WRONG_JSON_FORMAT,
-    DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_REQUIRE_PARAMETER_NET,
-    DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_NOT_FOUNT_NET_BY_NAME,
-    DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_NOT_FOUNT_CHAIN_BY_NAME,
-    DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_NOT_FOUNT_ARRAY_ITEMS,
-    DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_INVALID_ITEMS,
-    DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_CAN_NOT_ADD_TRANSACTION_TO_MEMPOOL
-}s_com_tx_create_json_err_t;
+
 int com_tx_create_json(int a_argc, char **a_argv, void **reply);
 typedef enum s_com_tx_cond_create{
     DAP_CHAIN_NODE_CLI_COM_TX_COND_CREATE_OK = 0,
-- 
GitLab


From 1707120ce734c1b4dc0c4c4248e1a26516b6aebc Mon Sep 17 00:00:00 2001
From: "daniil.frolov" <daniil.frolov@demlabs.net>
Date: Sun, 12 Jan 2025 13:39:51 +0300
Subject: [PATCH 02/18] [*] Fix functions docs

---
 modules/net/dap_chain_net_tx.c         |  5 +----
 modules/net/dap_chain_node_cli_cmd.c   |  2 +-
 modules/net/include/dap_chain_net_tx.h | 18 ++++++++++++++----
 3 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/modules/net/dap_chain_net_tx.c b/modules/net/dap_chain_net_tx.c
index 5dd03126af..c0ec91461d 100644
--- a/modules/net/dap_chain_net_tx.c
+++ b/modules/net/dap_chain_net_tx.c
@@ -654,7 +654,7 @@ static dap_pkey_t* s_json_get_pkey(struct json_object *a_json)
 }
 
 int dap_chain_net_tx_create_by_json(json_object *a_tx_json, dap_chain_net_t *a_net, json_object *a_json_obj_error, 
-                                        dap_chain_datum_tx_t** a_out_tx, size_t* a_items_count, size_t *a_items_ready, void **a_json_arr_reply)
+                                        dap_chain_datum_tx_t** a_out_tx, size_t* a_items_count, size_t *a_items_ready)
 {
 
     json_object *l_json = a_tx_json;
@@ -677,8 +677,6 @@ int dap_chain_net_tx_create_by_json(json_object *a_tx_json, dap_chain_net_t *a_n
     struct json_object *l_json_items = json_object_object_get(l_json, "items");
     size_t l_items_count;
     if(!l_json_items || !json_object_is_type(l_json_items, json_type_array) || !(l_items_count = json_object_array_length(l_json_items))) {
-        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NET_TX_CREATE_JSON_NOT_FOUNT_ARRAY_ITEMS,
-                               "Wrong json format: not found array 'items' or array is empty");
         json_object_put(l_json);
         return DAP_CHAIN_NET_TX_CREATE_JSON_NOT_FOUNT_ARRAY_ITEMS;
     }
@@ -688,7 +686,6 @@ int dap_chain_net_tx_create_by_json(json_object *a_tx_json, dap_chain_net_t *a_n
     dap_chain_datum_tx_t *l_tx = DAP_NEW_Z_SIZE(dap_chain_datum_tx_t, sizeof(dap_chain_datum_tx_t));
     if(!l_tx) {
         json_object_put(l_json);
-        dap_json_rpc_allocation_error(*a_json_arr_reply);
         return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED;
     }
 
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index 96d0ef2cdc..0c2000a7db 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -6091,7 +6091,7 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply)
     size_t l_items_ready = 0, l_items_count = 0;
     dap_chain_datum_tx_t *l_tx = NULL;
     int l_ret = 0;
-    if((l_ret = dap_chain_net_tx_create_by_json(l_json, l_net, l_jobj_errors, &l_tx, &l_items_count, &l_items_ready, a_json_arr_reply)) != DAP_CHAIN_NET_TX_CREATE_JSON_OK) {
+    if((l_ret = dap_chain_net_tx_create_by_json(l_json, l_net, l_jobj_errors, &l_tx, &l_items_count, &l_items_ready)) != DAP_CHAIN_NET_TX_CREATE_JSON_OK) {
         dap_json_rpc_error_add(*a_json_arr_reply, l_ret,
                                "Can't create transaction from json file");
         json_object_put(l_json);
diff --git a/modules/net/include/dap_chain_net_tx.h b/modules/net/include/dap_chain_net_tx.h
index b6e33b42e5..67e594d734 100644
--- a/modules/net/include/dap_chain_net_tx.h
+++ b/modules/net/include/dap_chain_net_tx.h
@@ -111,11 +111,21 @@ bool dap_chain_net_tx_set_fee(dap_chain_net_id_t a_net_id, uint256_t a_value, da
  *          tx will be created from json as is without any checks and conversions.
  * @param a_tx_json input json
  * @param a_net network. If NULL it means offline tx creation
- * @param a_out_tx output transaction
- * @param a_items_count count of items in transaction
+ * @param a_json_obj_error json object for tx items errors messages
+ * @param a_out_tx pointer to output transaction pointer
+ * @param a_items_count count of total items in input json transaction
+ * @param a_items_ready count of valid items in output transaction
+ * 
+ * @return s_com_tx_create_json_err_t status code
  */
 int dap_chain_net_tx_create_by_json(json_object *a_tx_json, dap_chain_net_t *a_net, json_object *a_json_obj_error, 
-                                        dap_chain_datum_tx_t** a_out_tx, size_t* a_items_count, size_t *a_items_ready, void **a_json_arr_reply);
-
+                                        dap_chain_datum_tx_t** a_out_tx, size_t* a_items_count, size_t *a_items_ready);
 
+/**
+ * @brief Convert binary transaction to json
+ * @param a_tx input transaction
+ * @param a_out_json pointer to json object created by json_object_new_object()
+ * 
+ * @return s_com_tx_create_json_err_t status code
+ */
 int dap_chain_net_tx_to_json(dap_chain_datum_tx_t *a_tx, json_object *a_out_json);
\ No newline at end of file
-- 
GitLab


From d731aa9529918f91741a272bacb0ce657b132022 Mon Sep 17 00:00:00 2001
From: "daniil.frolov" <daniil.frolov@demlabs.net>
Date: Tue, 14 Jan 2025 13:01:49 +0300
Subject: [PATCH 03/18] [+] srv_stake_lock out_cond added to
 dap_chain_net_tx_create_by_json

---
 dap-sdk                        |  2 +-
 modules/net/dap_chain_net_tx.c | 78 ++++++++++++++++++++++++++++++++++
 2 files changed, 79 insertions(+), 1 deletion(-)

diff --git a/dap-sdk b/dap-sdk
index 5931f83c88..e0e6309061 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit 5931f83c8894be1f78e4888ef39873fc87aa4df2
+Subproject commit e0e63090610a266c933fa4c2e04898e2c398f9ef
diff --git a/modules/net/dap_chain_net_tx.c b/modules/net/dap_chain_net_tx.c
index c0ec91461d..938819b088 100644
--- a/modules/net/dap_chain_net_tx.c
+++ b/modules/net/dap_chain_net_tx.c
@@ -977,6 +977,84 @@ int dap_chain_net_tx_create_by_json(json_object *a_tx_json, dap_chain_net_t *a_n
                 }
             }
                 break;
+            case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK:{
+                dap_chain_net_srv_uid_t l_srv_uid;
+                if(!s_json_get_srv_uid(l_json_item_obj, "service_id", "service", &l_srv_uid.uint64)) {
+                    // Default service DAP_CHAIN_NET_SRV_STAKE_ID
+                    l_srv_uid.uint64 = 0x12;
+                }
+                uint256_t l_value = { };
+                if(!s_json_get_uint256(l_json_item_obj, "value", &l_value) || IS_ZERO_256(l_value)) {
+                    log_it(L_ERROR, "Json TX: bad value in DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK");
+                    break;
+                }
+                const char* l_time_staking_str = NULL;
+                if((l_time_staking_str = s_json_get_text(l_json_item_obj, "time_staking")) == NULL || dap_strlen(l_time_staking_str) != 6)  {
+                    log_it(L_ERROR, "Json TX: bad time staking in DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK");
+                    break;
+                }
+                    
+                char l_time_staking_month_str[3] = {l_time_staking_str[2], l_time_staking_str[3], 0};
+                int l_time_staking_month = atoi(l_time_staking_month_str);
+                if (l_time_staking_month < 1 || l_time_staking_month > 12){
+                    log_it(L_ERROR, "Json TX: bad time staking in DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK");
+                    break;
+                }
+                    
+
+                char l_time_staking_day_str[3] = {l_time_staking_str[4], l_time_staking_str[5], 0};
+                int l_time_staking_day = atoi(l_time_staking_day_str);
+                if (l_time_staking_day < 1 || l_time_staking_day > 31){
+                    log_it(L_ERROR, "Json TX: bad time staking in DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK");
+                    break;
+                }
+
+                dap_time_t l_time_staking = 0;
+                l_time_staking = dap_time_from_str_simplified(l_time_staking_str);
+                if (0 == l_time_staking){
+                    log_it(L_ERROR, "Json TX: bad time staking in DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK");
+                    break;
+                }
+                dap_time_t l_time_now = dap_time_now();
+                if (l_time_staking < l_time_now){
+                    log_it(L_ERROR, "Json TX: bad time staking in DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK");
+                    break;
+                }
+                l_time_staking -= l_time_now;
+
+                uint256_t l_reinvest_percent = uint256_0;
+                const char* l_reinvest_percent_str = NULL;
+                if((l_reinvest_percent_str = s_json_get_text(l_json_item_obj, "reinvest_percent"))!=NULL) {
+                    l_reinvest_percent = dap_chain_coins_to_balance(l_reinvest_percent_str);
+                    if (compare256(l_reinvest_percent, dap_chain_coins_to_balance("100.0")) == 1){
+                    log_it(L_ERROR, "Json TX: bad reinvest percent in DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK");
+                        break;
+                    }
+                    if (IS_ZERO_256(l_reinvest_percent)) {
+                        int l_reinvest_percent_int = atoi(l_reinvest_percent_str);
+                        if (l_reinvest_percent_int < 0 || l_reinvest_percent_int > 100){
+                            log_it(L_ERROR, "Json TX: bad reinvest percent in DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK");
+                            break;
+                        }
+                        l_reinvest_percent = dap_chain_uint256_from(l_reinvest_percent_int);
+                        MULT_256_256(l_reinvest_percent, GET_256_FROM_64(1000000000000000000ULL), &l_reinvest_percent);
+                    }
+                }               
+
+                dap_chain_tx_out_cond_t *l_out_cond_item = dap_chain_datum_tx_item_out_cond_create_srv_stake_lock(l_srv_uid, l_value, l_time_staking, l_reinvest_percent);
+                l_item = (const uint8_t*) l_out_cond_item;
+                // Save value for using in In item
+                if(l_item) {
+                    SUM_256_256(l_value_need, l_value, &l_value_need);
+                } else {
+                    char *l_str_err = dap_strdup_printf("Unable to create conditional out for transaction "
+                                                         "can of type %s described in item %zu.", l_subtype_str, i);
+                    json_object *l_jobj_err = json_object_new_string(l_str_err);
+                    DAP_DELETE(l_str_err);
+                    if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+                }
+            } 
+                break;
             case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE:{
                 dap_chain_net_srv_uid_t l_srv_uid;
                 if(!s_json_get_srv_uid(l_json_item_obj, "service_id", "service", &l_srv_uid.uint64)) {
-- 
GitLab


From 2a2341e3c7bf2d1c4d4fb891f4ce2c97457bb2f9 Mon Sep 17 00:00:00 2001
From: "daniil.frolov" <daniil.frolov@demlabs.net>
Date: Wed, 15 Jan 2025 10:02:26 +0300
Subject: [PATCH 04/18] ..

---
 dap-sdk                        | 2 +-
 modules/net/dap_chain_net_tx.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/dap-sdk b/dap-sdk
index d6b6934683..e0e6309061 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit d6b6934683168160e7d25647ceef59d9439de2c3
+Subproject commit e0e63090610a266c933fa4c2e04898e2c398f9ef
diff --git a/modules/net/dap_chain_net_tx.c b/modules/net/dap_chain_net_tx.c
index 7dd4b97464..bf987657e3 100644
--- a/modules/net/dap_chain_net_tx.c
+++ b/modules/net/dap_chain_net_tx.c
@@ -537,4 +537,4 @@ bool dap_chain_net_tx_set_fee(dap_chain_net_id_t a_net_id, uint256_t a_value, da
     l_net->pub.fee_addr = a_addr;
 
     return true;
-}
+ }
-- 
GitLab


From 7861b3105251df04dc51965d9282f07330234856 Mon Sep 17 00:00:00 2001
From: "daniil.frolov" <daniil.frolov@demlabs.net>
Date: Wed, 15 Jan 2025 12:09:28 +0300
Subject: [PATCH 05/18] [+] Added checking inputs with prev hash in
 tx_create_json

---
 modules/net/dap_chain_net_tx.c | 49 ++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/modules/net/dap_chain_net_tx.c b/modules/net/dap_chain_net_tx.c
index 938819b088..250b5c0ad1 100644
--- a/modules/net/dap_chain_net_tx.c
+++ b/modules/net/dap_chain_net_tx.c
@@ -726,8 +726,57 @@ int dap_chain_net_tx_create_by_json(json_object *a_tx_json, dap_chain_net_t *a_n
                     if (l_json_item_token && dap_strcmp(l_json_item_token, l_native_token)){
                         l_multichanel = true;
                         l_main_token = l_json_item_token;
+                        break;
+                    }
+                    const char *l_prev_hash_str = s_json_get_text(l_json_item_obj, "prev_hash");
+                    int64_t l_out_prev_idx;
+                    bool l_is_out_prev_idx = s_json_get_int64(l_json_item_obj, "out_prev_idx", &l_out_prev_idx);
+                    // If prev_hash and out_prev_idx were read
+                    if(l_prev_hash_str && l_is_out_prev_idx){
+                        dap_chain_hash_fast_t l_tx_prev_hash = {};
+                        if(!dap_chain_hash_fast_from_str(l_prev_hash_str, &l_tx_prev_hash)) {
+                            //check out token
+                            dap_chain_datum_tx_t *l_prev_tx = dap_ledger_tx_find_by_hash(a_net->pub.ledger, &l_tx_prev_hash);
+                            byte_t *l_prev_item = l_prev_tx ? dap_chain_datum_tx_item_get_nth(l_prev_tx, TX_ITEM_TYPE_OUT_ALL, l_out_prev_idx) : NULL;
+                            if (l_prev_item){
+                                const char* l_token = NULL;
+                                if (*l_prev_item == TX_ITEM_TYPE_OUT){
+                                    l_token = dap_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, &l_tx_prev_hash);
+                                } else if(*l_prev_item == TX_ITEM_TYPE_OUT_EXT){
+                                    l_token = ((dap_chain_tx_out_ext_t*)l_prev_item)->token;
+                                } else {
+                                    log_it(L_WARNING, "Invalid 'in' item, wrong type of item with index %"DAP_UINT64_FORMAT_U" in previous tx %s", l_out_prev_idx, l_prev_hash_str);
+                                    char *l_str_err = dap_strdup_printf("Unable to create in for transaction. Invalid 'in' item, "
+                                                                        "wrong type of item with index %"DAP_UINT64_FORMAT_U" in previous tx %s", l_out_prev_idx, l_prev_hash_str);
+                                    json_object *l_jobj_err = json_object_new_string(l_str_err);
+                                    if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+                                    break;
+                                }
+                                if (dap_strcmp(l_token, l_native_token)){
+                                    l_multichanel = true;
+                                    l_main_token = l_json_item_token;
+                                    break;
+                                }
+
+                            } else {
+                                log_it(L_WARNING, "Invalid 'in' item, can't find item with index %"DAP_UINT64_FORMAT_U" in previous tx %s", l_out_prev_idx, l_prev_hash_str);
+                                char *l_str_err = dap_strdup_printf("Unable to create in for transaction. Invalid 'in' item, "
+                                                                    "can't find item with index %"DAP_UINT64_FORMAT_U" in previous tx %s", l_out_prev_idx, l_prev_hash_str);
+                                json_object *l_jobj_err = json_object_new_string(l_str_err);
+                                if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+                            }                            
+                        } else {
+                            log_it(L_WARNING, "Invalid 'in' item, bad prev_hash %s", l_prev_hash_str);
+                            char *l_str_err = dap_strdup_printf("Unable to create in for transaction. Invalid 'in' item, "
+                                                                "bad prev_hash %s", l_prev_hash_str);
+                            json_object *l_jobj_err = json_object_new_string(l_str_err);
+                            if (l_jobj_errors) json_object_array_add(l_jobj_errors, l_jobj_err);
+                        }
                     }
                 }break;
+                case TX_ITEM_TYPE_IN_COND:
+                case TX_ITEM_TYPE_IN_EMS:
+                case TX_ITEM_TYPE_IN_REWARD:
                 default: continue;
             }
             if(l_multichanel)
-- 
GitLab


From 613dd984cf402fdd83f5eb90f9afeef15e667705 Mon Sep 17 00:00:00 2001
From: "daniil.frolov" <daniil.frolov@demlabs.net>
Date: Thu, 16 Jan 2025 15:45:54 +0300
Subject: [PATCH 06/18] [*] Fix block dump command

---
 modules/type/blocks/dap_chain_cs_blocks.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c
index 05d3c5dde8..b74bfb74eb 100644
--- a/modules/type/blocks/dap_chain_cs_blocks.c
+++ b/modules/type/blocks/dap_chain_cs_blocks.c
@@ -733,6 +733,7 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
 
         case SUBCMD_DUMP:{
             const char *l_hash_out_type = NULL;
+            const char *l_hash_str = NULL;
             dap_chain_hash_fast_t l_block_hash={0};
             dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-H", &l_hash_out_type);
             if(!l_hash_out_type)
@@ -740,15 +741,17 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
             if(dap_strcmp(l_hash_out_type,"hex") && dap_strcmp(l_hash_out_type,"base58")) {
                 dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR, "invalid parameter -H, valid values: -H <hex | base58>");
                 return DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR;
-            }
-            if (!l_subcmd_str_arg) {
+            }           
+            dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-hash", &l_hash_str);
+            if (!l_hash_str) {
                 dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_BLOCK_HASH_ERR, "Enter block hash ");
                 return DAP_CHAIN_NODE_CLI_COM_BLOCK_HASH_ERR;
             }
-            dap_chain_hash_fast_from_str(l_subcmd_str_arg, &l_block_hash); // Convert argument to hash
+
+            dap_chain_hash_fast_from_str(l_hash_str, &l_block_hash);
             dap_chain_block_cache_t *l_block_cache = dap_chain_block_cache_get_by_hash(l_blocks, &l_block_hash);
             if (!l_block_cache) {
-                dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_BLOCK_FIND_ERR, "Can't find block %s ", l_subcmd_str_arg);
+                dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_BLOCK_FIND_ERR, "Can't find block %s ", l_hash_str);
                 return DAP_CHAIN_NODE_CLI_COM_BLOCK_FIND_ERR;
             }
             dap_chain_block_t *l_block = l_block_cache->block;
-- 
GitLab


From 59726cdb1b65dfb1199795348b830955a77b71d7 Mon Sep 17 00:00:00 2001
From: "daniil.frolov" <daniil.frolov@demlabs.net>
Date: Thu, 16 Jan 2025 16:47:06 +0300
Subject: [PATCH 07/18] ..

---
 modules/type/blocks/dap_chain_cs_blocks.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c
index b74bfb74eb..9c85963438 100644
--- a/modules/type/blocks/dap_chain_cs_blocks.c
+++ b/modules/type/blocks/dap_chain_cs_blocks.c
@@ -201,7 +201,7 @@ int dap_chain_cs_blocks_init()
                 "\t\tComplete the current new round, verify it and if everything is ok - publish new blocks in chain\n\n"
 
         "Blockchain explorer:\n"
-            "block -net <net_name> [-chain <chain_name>] dump <block_hash>\n"
+            "block -net <net_name> [-chain <chain_name>] dump -hash <block_hash>\n"
                 "\t\tDump block info\n\n"
 
             "block -net <net_name> [-chain <chain_name>] list [{signed | first_signed}] [-limit] [-offset] [-head]"
-- 
GitLab


From 55aaace60e0ed2e0ec734514422d6a21d0983915 Mon Sep 17 00:00:00 2001
From: "daniil.frolov" <daniil.frolov@demlabs.net>
Date: Thu, 16 Jan 2025 17:30:53 +0300
Subject: [PATCH 08/18] [*] Change json_str to tx_obj [+] Add availability send
 number as string in tx obj

---
 modules/net/dap_chain_net_tx.c       | 5 +++++
 modules/net/dap_chain_node_cli_cmd.c | 4 ++--
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/modules/net/dap_chain_net_tx.c b/modules/net/dap_chain_net_tx.c
index 250b5c0ad1..f3affeae81 100644
--- a/modules/net/dap_chain_net_tx.c
+++ b/modules/net/dap_chain_net_tx.c
@@ -567,6 +567,11 @@ static bool s_json_get_int64(struct json_object *a_json, const char *a_key, int6
             // Read number
             *a_out = json_object_get_int64(l_json);
             return true;
+        } else if (json_object_is_type(l_json, json_type_string)){
+            // Read number
+            const char* l_value_text = json_object_get_string(l_json);
+            *a_out = atol(l_value_text);
+            return true;
         }
     }
     return false;
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index 0c2000a7db..45bd7fcf2e 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -6017,11 +6017,11 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply)
     dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_name); // optional parameter
     dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-chain", &l_chain_name); // optional parameter
     dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-json", &l_json_file_path);
-    dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-json_str", &l_json_str);
+    dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-tx_obj", &l_json_str);
 
     if(!l_json_file_path && !l_json_str) {
         dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NET_TX_CREATE_JSON_REQUIRE_PARAMETER_JSON,
-                               "Command requires one of parameters '-json <json file path> or -json_srt <string>'");
+                               "Command requires one of parameters '-json <json file path> or -tx_obj <string>'");
         return DAP_CHAIN_NET_TX_CREATE_JSON_REQUIRE_PARAMETER_JSON;
     } 
 
-- 
GitLab


From dcbd33692d673605ac826581e863b8c8e328d4ad Mon Sep 17 00:00:00 2001
From: "daniil.frolov" <daniil.frolov@demlabs.net>
Date: Thu, 16 Jan 2025 17:33:55 +0300
Subject: [PATCH 09/18] up sub

---
 dap-sdk | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/dap-sdk b/dap-sdk
index e0e6309061..69f295dd81 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit e0e63090610a266c933fa4c2e04898e2c398f9ef
+Subproject commit 69f295dd81601b52bbf222edab814d8df7c3ace9
-- 
GitLab


From 55f4295b198f89d2144e15963b3127848578252d Mon Sep 17 00:00:00 2001
From: denis <denis.sumin>
Date: Fri, 17 Jan 2025 10:35:49 +0300
Subject: [PATCH 10/18] [*] up dap-sdk

---
 dap-sdk | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/dap-sdk b/dap-sdk
index bca10a63f6..da046e00eb 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit bca10a63f6fe82df2808c1741e80592148b85e85
+Subproject commit da046e00ebeb5261ebcd874d5bdeeb05d37c9a0f
-- 
GitLab


From 08f40f801e0826d9e3a9112671141fdeec50792f Mon Sep 17 00:00:00 2001
From: "daniil.frolov" <daniil.frolov@demlabs.net>
Date: Fri, 17 Jan 2025 12:21:17 +0300
Subject: [PATCH 11/18] [+] Add extern "C" into headers

---
 modules/common/include/dap_chain_datum.h               |  8 ++++++++
 modules/common/include/dap_chain_datum_anchor.h        |  8 ++++++++
 modules/common/include/dap_chain_datum_decree.h        |  9 +++++++++
 .../common/include/dap_chain_datum_hashtree_roots.h    |  6 ++++++
 modules/common/include/dap_chain_datum_poll.h          |  7 +++++++
 modules/common/include/dap_chain_datum_token.h         |  7 +++++++
 modules/common/include/dap_chain_datum_tx.h            |  9 +++++++++
 modules/common/include/dap_chain_datum_tx_in.h         |  9 +++++++++
 modules/common/include/dap_chain_datum_tx_in_cond.h    |  9 +++++++++
 modules/common/include/dap_chain_datum_tx_in_ems.h     |  8 ++++++++
 modules/common/include/dap_chain_datum_tx_in_reward.h  |  7 +++++++
 modules/common/include/dap_chain_datum_tx_items.h      |  6 ++++++
 modules/common/include/dap_chain_datum_tx_out.h        |  8 ++++++++
 modules/common/include/dap_chain_datum_tx_out_cond.h   |  8 ++++++++
 modules/common/include/dap_chain_datum_tx_out_ext.h    |  7 +++++++
 modules/common/include/dap_chain_datum_tx_pkey.h       |  9 +++++++++
 modules/common/include/dap_chain_datum_tx_receipt.h    |  1 +
 modules/common/include/dap_chain_datum_tx_sig.h        |  7 +++++++
 modules/common/include/dap_chain_datum_tx_tsd.h        |  6 ++++++
 modules/common/include/dap_chain_datum_tx_voting.h     |  7 +++++++
 modules/net/include/dap_chain_ledger.h                 |  8 ++++++++
 modules/net/include/dap_chain_net.h                    |  7 +++++++
 modules/net/include/dap_chain_net_anchor.h             | 10 +++++++++-
 modules/net/include/dap_chain_net_balancer.h           | 10 +++++++++-
 modules/net/include/dap_chain_net_bugreport.h          |  8 ++++++++
 modules/net/include/dap_chain_net_decree.h             |  8 ++++++++
 modules/net/include/dap_chain_net_node_list.h          |  8 ++++++++
 modules/net/include/dap_chain_net_tx.h                 | 10 +++++++++-
 modules/net/include/dap_chain_node.h                   |  8 ++++++++
 modules/net/include/dap_chain_node_cli.h               |  8 ++++++++
 modules/net/include/dap_chain_node_cli_cmd.h           |  8 ++++++++
 modules/net/include/dap_chain_node_cli_cmd_tx.h        |  7 +++++++
 modules/net/include/dap_chain_node_client.h            |  8 ++++++++
 modules/net/include/dap_chain_node_dns_client.h        |  7 +++++++
 modules/net/include/dap_chain_node_dns_server.h        |  7 +++++++
 modules/net/include/dap_chain_node_ping.h              |  8 ++++++++
 modules/wallet/include/dap_chain_coin.h                |  9 +++++++++
 modules/wallet/include/dap_chain_wallet.h              | 10 +++++++++-
 modules/wallet/include/dap_chain_wallet_cache.h        | 10 +++++++++-
 modules/wallet/include/dap_chain_wallet_internal.h     |  6 ++++++
 modules/wallet/include/dap_chain_wallet_ops.h          |  8 ++++++++
 41 files changed, 314 insertions(+), 5 deletions(-)

diff --git a/modules/common/include/dap_chain_datum.h b/modules/common/include/dap_chain_datum.h
index 1fad5120e8..7c20ce32be 100644
--- a/modules/common/include/dap_chain_datum.h
+++ b/modules/common/include/dap_chain_datum.h
@@ -104,6 +104,10 @@
 
 #define DAP_CHAIN_DATUM_ID_SIZE 2
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 // Datum subchain type id
 typedef union dap_chain_datum_typeid{
     uint8_t data[DAP_CHAIN_DATUM_ID_SIZE];
@@ -168,3 +172,7 @@ bool dap_chain_datum_dump_tx_json(json_object* a_json_arr_reply,
                              dap_chain_net_id_t a_net_id);
 json_object * dap_chain_datum_to_json(dap_chain_datum_t* a_datum);
 void dap_chain_datum_dump_json(json_object* a_json_arr_reply,json_object  *a_obj_out, dap_chain_datum_t *a_datum, const char *a_hash_out_type, dap_chain_net_id_t a_net_id, bool a_verbose);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_anchor.h b/modules/common/include/dap_chain_datum_anchor.h
index 79a0c48102..41986a06be 100644
--- a/modules/common/include/dap_chain_datum_anchor.h
+++ b/modules/common/include/dap_chain_datum_anchor.h
@@ -48,8 +48,16 @@ DAP_STATIC_INLINE size_t dap_chain_datum_anchor_get_size(dap_chain_datum_anchor_
     return sizeof(*a_datum_anchor) + a_datum_anchor->header.data_size + a_datum_anchor->header.signs_size;
 }
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 int dap_chain_datum_anchor_get_hash_from_data(dap_chain_datum_anchor_t* a_anchor, dap_hash_fast_t * a_out_hash);
 void dap_chain_datum_anchor_certs_dump(dap_string_t * a_str_out, byte_t * a_signs,
                                        size_t a_certs_size, const char *a_hash_out_type);
 
 void dap_chain_datum_anchor_certs_dump_json(json_object * a_json_out, byte_t * a_signs, size_t a_certs_size, const char *a_hash_out_type);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_decree.h b/modules/common/include/dap_chain_datum_decree.h
index 70ef4f65bd..e1292b35b2 100644
--- a/modules/common/include/dap_chain_datum_decree.h
+++ b/modules/common/include/dap_chain_datum_decree.h
@@ -31,6 +31,10 @@
 
 #define DAP_CHAIN_DATUM_DECREE_VERSION  0
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 // Governance decree
 typedef struct dap_chain_datum_decree {
     uint16_t decree_version;
@@ -343,3 +347,8 @@ void dap_chain_datum_decree_certs_dump_json(json_object * a_json_out, byte_t * a
  */
 dap_chain_datum_decree_t* dap_chain_datum_decree_sign_in_cycle(dap_cert_t ** a_certs, dap_chain_datum_decree_t *a_datum_decree,
                                                   size_t a_certs_count, size_t *a_total_sign_count);
+
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_hashtree_roots.h b/modules/common/include/dap_chain_datum_hashtree_roots.h
index 2b8ec9b513..8ff8f79d86 100644
--- a/modules/common/include/dap_chain_datum_hashtree_roots.h
+++ b/modules/common/include/dap_chain_datum_hashtree_roots.h
@@ -26,6 +26,9 @@
 #include "dap_common.h"
 #include "dap_chain_common.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 /**
   * @struct dap_chain_datum_hashtree_roots_v1
   * @brief Hash tree roots for block, version 1
@@ -45,3 +48,6 @@ typedef struct dap_chain_datum_hashtree_roots_v2{
 
 typedef dap_chain_datum_hashtree_roots_v2_t dap_chain_datum_hashtree_roots_t;
 
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_poll.h b/modules/common/include/dap_chain_datum_poll.h
index d023c26b51..30993b3805 100644
--- a/modules/common/include/dap_chain_datum_poll.h
+++ b/modules/common/include/dap_chain_datum_poll.h
@@ -20,3 +20,10 @@
     along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/licenses/>.
 */
 #pragma once
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_token.h b/modules/common/include/dap_chain_datum_token.h
index 8f6d89e63a..c37131dc12 100644
--- a/modules/common/include/dap_chain_datum_token.h
+++ b/modules/common/include/dap_chain_datum_token.h
@@ -34,6 +34,9 @@
 
 
 #define DAP_CHAIN_DATUM_NONCE_SIZE                                          64
+#ifdef __cplusplus
+extern "C" {
+#endif
 // Token declaration
 typedef struct dap_chain_datum_token_old {
     uint16_t type;
@@ -437,3 +440,7 @@ dap_chain_datum_token_emission_t *dap_chain_datum_emission_append_sign(dap_sign_
 dap_sign_t *dap_chain_datum_emission_get_signs(dap_chain_datum_token_emission_t *a_emission, size_t *a_signs_count);
 // 256 TYPE
 bool dap_chain_datum_token_is_old(uint8_t a_type);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_tx.h b/modules/common/include/dap_chain_datum_tx.h
index 98b8b7bff9..f5ef493eed 100644
--- a/modules/common/include/dap_chain_datum_tx.h
+++ b/modules/common/include/dap_chain_datum_tx.h
@@ -29,6 +29,11 @@
 #include "dap_time.h"
 #include "dap_pkey.h"
 
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /**
   * @struct dap_chain_datum_tx
   * @brief Transaction section, consists from lot of tx_items
@@ -182,3 +187,7 @@ DAP_STATIC_INLINE dap_hash_fast_t dap_chain_node_datum_tx_calc_hash(dap_chain_da
     dap_hash_fast_t l_res;
     return dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), &l_res), l_res;
 }
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_tx_in.h b/modules/common/include/dap_chain_datum_tx_in.h
index bac85f8809..242ae43ecf 100644
--- a/modules/common/include/dap_chain_datum_tx_in.h
+++ b/modules/common/include/dap_chain_datum_tx_in.h
@@ -27,6 +27,11 @@
 #include "dap_common.h"
 #include "dap_chain_common.h"
 #include "dap_chain_datum_tx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /**
   * @struct dap_chain_tx_item
   * @brief Sections belongs to heading tx section, with inputs, outputs and others tx relatated items
@@ -45,3 +50,7 @@ typedef struct dap_chain_tx_used_out_item {
     uint32_t num_idx_out;
     uint256_t value;
 } dap_chain_tx_used_out_item_t;
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_tx_in_cond.h b/modules/common/include/dap_chain_datum_tx_in_cond.h
index 553e7f71ac..f6ffe2fca0 100644
--- a/modules/common/include/dap_chain_datum_tx_in_cond.h
+++ b/modules/common/include/dap_chain_datum_tx_in_cond.h
@@ -27,6 +27,11 @@
 #include "dap_common.h"
 #include "dap_chain_common.h"
 #include "dap_chain_datum_tx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /**
  * @struct dap_chain_tx_item
  * @brief Sections belongs to heading tx section, with inputs, outputs and others tx relatated items
@@ -40,3 +45,7 @@ typedef struct dap_chain_tx_in_cond {
         uint32_t receipt_idx DAP_ALIGNED(4);
     } DAP_PACKED header; /// Only header's hash is used for verification
 } DAP_PACKED dap_chain_tx_in_cond_t;
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_tx_in_ems.h b/modules/common/include/dap_chain_datum_tx_in_ems.h
index 04a17f84b7..b745fa727d 100644
--- a/modules/common/include/dap_chain_datum_tx_in_ems.h
+++ b/modules/common/include/dap_chain_datum_tx_in_ems.h
@@ -27,6 +27,10 @@
 #include "dap_common.h"
 #include "dap_chain_common.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /**
   * @struct dap_chain_tx_token
   * @brief Token item
@@ -58,3 +62,7 @@ typedef struct dap_chain_tx_in_ems_ext{
         uint16_t ext_tx_out_idx; // Output index
     } header; /// Only header's hash is used for verification
 } DAP_ALIGN_PACKED dap_chain_tx_in_ems_ext_t;
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_tx_in_reward.h b/modules/common/include/dap_chain_datum_tx_in_reward.h
index 220d10a0d5..6d8fa17a37 100644
--- a/modules/common/include/dap_chain_datum_tx_in_reward.h
+++ b/modules/common/include/dap_chain_datum_tx_in_reward.h
@@ -24,7 +24,14 @@ along with any DAP SDK based project.  If not, see <http://www.gnu.org/licenses/
 #pragma once
 #include "dap_chain_common.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 typedef struct dap_chain_tx_in_reward {
     dap_chain_tx_item_type_t type;          /// @param type             @brief Transaction item type
     dap_hash_t block_hash;                  /// @param block_hash       @brief Hash of the block signed with current validator
 } DAP_ALIGN_PACKED dap_chain_tx_in_reward_t;
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_tx_items.h b/modules/common/include/dap_chain_datum_tx_items.h
index 9c004c1979..d62f1c12a6 100644
--- a/modules/common/include/dap_chain_datum_tx_items.h
+++ b/modules/common/include/dap_chain_datum_tx_items.h
@@ -41,6 +41,9 @@
 #include "dap_chain_datum_tx_tsd.h"
 #include "dap_chain_datum_tx_in_reward.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 typedef struct dap_chain_datum_tx_item_groups {
 
     dap_list_t *items_in_all;
@@ -249,3 +252,6 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_out_cond_get(dap_chain_datum_tx_t *a
 #define dap_chain_datum_tx_out_get_by_out_idx(a_tx, a_out_num) \
     dap_chain_datum_tx_item_get_nth(a_tx, TX_ITEM_TYPE_OUT_ALL, a_out_num);
 
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_tx_out.h b/modules/common/include/dap_chain_datum_tx_out.h
index 3b877a4456..084b5bba20 100644
--- a/modules/common/include/dap_chain_datum_tx_out.h
+++ b/modules/common/include/dap_chain_datum_tx_out.h
@@ -28,6 +28,10 @@
 #include "dap_chain_common.h"
 #include "dap_chain_datum_tx.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /**
   * @struct dap_chain_tx_out
   * @brief Transaction item outout
@@ -48,3 +52,7 @@ typedef struct dap_chain_tx_out {
     } DAP_PACKED header; /// Only header's hash is used for verification
     dap_chain_addr_t addr; ////
 } DAP_PACKED dap_chain_tx_out_t;
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_tx_out_cond.h b/modules/common/include/dap_chain_datum_tx_out_cond.h
index c528b329c6..1325127e68 100644
--- a/modules/common/include/dap_chain_datum_tx_out_cond.h
+++ b/modules/common/include/dap_chain_datum_tx_out_cond.h
@@ -29,6 +29,10 @@
 #include "dap_time.h"
 #include "dap_chain_common.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 enum dap_chain_tx_out_cond_subtype {
     DAP_CHAIN_TX_OUT_COND_SUBTYPE_UNDEFINED = 0x0,
     DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY = 0x01,
@@ -134,3 +138,7 @@ typedef struct dap_chain_tx_out_cond {
     uint32_t tsd_size; // Condition parameters size
     uint8_t tsd[]; // condition parameters, pkey, hash or smth like this
 } DAP_ALIGN_PACKED dap_chain_tx_out_cond_t;
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_tx_out_ext.h b/modules/common/include/dap_chain_datum_tx_out_ext.h
index 6c9351f1b5..69aa1e9f5b 100644
--- a/modules/common/include/dap_chain_datum_tx_out_ext.h
+++ b/modules/common/include/dap_chain_datum_tx_out_ext.h
@@ -29,6 +29,9 @@
 #include "dap_chain_common.h"
 #include "dap_chain_datum_tx.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 typedef struct dap_chain_tx_out_ext{
     struct {
         dap_chain_tx_item_type_t type;     // Transaction item type - should be TX_ITEM_TYPE_OUT_EXT
@@ -37,3 +40,7 @@ typedef struct dap_chain_tx_out_ext{
     dap_chain_addr_t addr;                 // Address to transfer to
     const char token[DAP_CHAIN_TICKER_SIZE_MAX]; // Which token is transferred
 } DAP_PACKED dap_chain_tx_out_ext_t;
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_tx_pkey.h b/modules/common/include/dap_chain_datum_tx_pkey.h
index af5e911358..817f6b2244 100644
--- a/modules/common/include/dap_chain_datum_tx_pkey.h
+++ b/modules/common/include/dap_chain_datum_tx_pkey.h
@@ -27,6 +27,11 @@
 #include "dap_common.h"
 #include "dap_chain_common.h"
 #include "dap_chain_datum_tx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /**
   * @struct dap_chain_tx_pkey
   * @brief TX item with one of the transaction's public keys
@@ -40,3 +45,7 @@ typedef struct dap_chain_tx_pkey{
     uint32_t seq_no; /// Sequence number, out of the header so could be changed during reorganization
     uint8_t pkey[]; /// @param sig @brief raw pkey dat
 } DAP_PACKED dap_chain_tx_pkey_t;
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_tx_receipt.h b/modules/common/include/dap_chain_datum_tx_receipt.h
index 5210c4fff5..ee0bb2845d 100644
--- a/modules/common/include/dap_chain_datum_tx_receipt.h
+++ b/modules/common/include/dap_chain_datum_tx_receipt.h
@@ -27,6 +27,7 @@
 #include <stdint.h>
 #include "dap_chain_common.h"
 
+
 typedef struct dap_chain_receipt_info {
     dap_chain_net_srv_uid_t srv_uid; // Service UID
 #if DAP_CHAIN_NET_SRV_UID_SIZE == 8
diff --git a/modules/common/include/dap_chain_datum_tx_sig.h b/modules/common/include/dap_chain_datum_tx_sig.h
index a44e1a36c8..90bea9846d 100644
--- a/modules/common/include/dap_chain_datum_tx_sig.h
+++ b/modules/common/include/dap_chain_datum_tx_sig.h
@@ -28,6 +28,9 @@
 #include "dap_chain_common.h"
 #include "dap_chain_datum_tx.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 /**
   * @struct dap_chain_tx_sig
@@ -41,3 +44,7 @@ typedef struct dap_chain_tx_sig{
     } DAP_PACKED header; /// Only header's hash is used for verification
     uint8_t sig[]; /// @param sig @brief raw signature data
 } DAP_PACKED dap_chain_tx_sig_t;
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_tx_tsd.h b/modules/common/include/dap_chain_datum_tx_tsd.h
index fc78dcd320..1b3484b876 100644
--- a/modules/common/include/dap_chain_datum_tx_tsd.h
+++ b/modules/common/include/dap_chain_datum_tx_tsd.h
@@ -5,6 +5,9 @@
 #include "dap_chain_datum_tx.h"
 #include "dap_tsd.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 typedef struct dap_chain_tx_tsd {
     struct {
         dap_chain_tx_item_type_t type;
@@ -13,3 +16,6 @@ typedef struct dap_chain_tx_tsd {
     byte_t tsd[];
 } DAP_PACKED dap_chain_tx_tsd_t;
 
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_tx_voting.h b/modules/common/include/dap_chain_datum_tx_voting.h
index d9a991a839..91139d1bd9 100644
--- a/modules/common/include/dap_chain_datum_tx_voting.h
+++ b/modules/common/include/dap_chain_datum_tx_voting.h
@@ -36,6 +36,9 @@
 #define DAP_CHAIN_DATUM_TX_VOTING_OPTION_MAX_LENGTH 100
 #define DAP_CHAIN_DATUM_TX_VOTING_OPTION_MAX_COUNT 10
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 typedef enum dap_chain_datum_voting_tsd_type {
     VOTING_TSD_TYPE_QUESTION = 0x01,
@@ -90,3 +93,7 @@ json_object *dap_chain_datum_tx_item_voting_tsd_to_json(dap_chain_datum_tx_t* a_
 
 dap_chain_tx_vote_t *dap_chain_datum_tx_item_vote_create(dap_chain_hash_fast_t *a_voting_hash, uint64_t *a_answer_idx);
 json_object *dap_chain_datum_tx_item_vote_to_json(dap_chain_tx_vote_t *a_vote, dap_ledger_t *a_ledger);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/net/include/dap_chain_ledger.h b/modules/net/include/dap_chain_ledger.h
index b0b3456a2a..bfbee3ca8d 100644
--- a/modules/net/include/dap_chain_ledger.h
+++ b/modules/net/include/dap_chain_ledger.h
@@ -40,6 +40,10 @@
 #define DAP_CHAIN_NET_SRV_TRANSFER_ID 0x09
 #define DAP_CHAIN_NET_SRV_BLOCK_REWARD_ID 0x08
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef struct dap_ledger {
     dap_chain_net_t *net;
     void *_internal;
@@ -465,3 +469,7 @@ bool dap_ledger_cache_enabled(dap_ledger_t *a_ledger);
 void dap_ledger_set_cache_tx_check_callback(dap_ledger_t *a_ledger, dap_ledger_cache_tx_check_callback_t a_callback);
 dap_chain_tx_out_cond_t* dap_chain_ledger_get_tx_out_cond_linked_to_tx_in_cond(dap_ledger_t *a_ledger, dap_chain_tx_in_cond_t *a_in_cond);
 void dap_ledger_load_end(dap_ledger_t *a_ledger);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/net/include/dap_chain_net.h b/modules/net/include/dap_chain_net.h
index 92989ff89f..9d47cc67b1 100644
--- a/modules/net/include/dap_chain_net.h
+++ b/modules/net/include/dap_chain_net.h
@@ -41,6 +41,9 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 #define DAP_CHAIN_NET_MEMPOOL_TTL 4 * 3600  // 4 hours
 #define DAP_CHAIN_NET_NODES_TTL 14 * 24 * 3600   // 2 weeks
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 typedef struct dap_chain_node_client dap_chain_node_client_t;
 typedef struct dap_ledger dap_ledger_t;
@@ -239,3 +242,7 @@ dap_chain_net_decree_t *dap_chain_net_get_net_decree(dap_chain_net_t *a_net);
 void dap_chain_net_set_net_decree(dap_chain_net_t *a_net, dap_chain_net_decree_t *a_decree);
 decree_table_t **dap_chain_net_get_decrees(dap_chain_net_t *a_net);
 anchor_table_t **dap_chain_net_get_anchors(dap_chain_net_t *a_net);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/net/include/dap_chain_net_anchor.h b/modules/net/include/dap_chain_net_anchor.h
index cb19ca0811..36d33c3d63 100644
--- a/modules/net/include/dap_chain_net_anchor.h
+++ b/modules/net/include/dap_chain_net_anchor.h
@@ -24,8 +24,16 @@
 #include "dap_chain_datum_anchor.h"
 #include "dap_chain_net.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 int dap_chain_net_anchor_init();
 
 int dap_chain_net_anchor_verify(dap_chain_net_t *a_net, dap_chain_datum_anchor_t * a_anchor, size_t a_data_size);
 int dap_chain_net_anchor_load(dap_chain_datum_anchor_t * a_anchor, dap_chain_t *a_chain, dap_hash_fast_t *a_anchor_hash);
-int dap_chain_net_anchor_unload(dap_chain_datum_anchor_t * a_anchor, dap_chain_t *a_chain, dap_hash_fast_t *a_anchor_hash);
\ No newline at end of file
+int dap_chain_net_anchor_unload(dap_chain_datum_anchor_t * a_anchor, dap_chain_t *a_chain, dap_hash_fast_t *a_anchor_hash);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/net/include/dap_chain_net_balancer.h b/modules/net/include/dap_chain_net_balancer.h
index 4d314dbc7e..e005eea71d 100644
--- a/modules/net/include/dap_chain_net_balancer.h
+++ b/modules/net/include/dap_chain_net_balancer.h
@@ -30,6 +30,10 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 #define DAP_BALANCER_PROTOCOL_VERSION 2
 #define DAP_BALANCER_MAX_REPLY_SIZE 2048
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef struct dap_balancer_request_info dap_balancer_request_info_t;
 
 typedef struct dap_chain_net_links {
@@ -66,4 +70,8 @@ void dap_chain_net_balancer_http_issue_link(dap_http_simple_t *a_http_simple, vo
 dap_link_info_t *dap_chain_net_balancer_dns_issue_link(const char *a_net_name);
 int dap_chain_net_balancer_handshake(dap_chain_node_info_t *a_node_info, dap_chain_net_t * a_net);
 dap_string_t *dap_chain_net_balancer_get_node_str(dap_chain_net_t *a_net);
-void dap_chain_net_balancer_request(void *a_arg);
\ No newline at end of file
+void dap_chain_net_balancer_request(void *a_arg);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/net/include/dap_chain_net_bugreport.h b/modules/net/include/dap_chain_net_bugreport.h
index b336ac607f..c8da9094df 100644
--- a/modules/net/include/dap_chain_net_bugreport.h
+++ b/modules/net/include/dap_chain_net_bugreport.h
@@ -24,4 +24,12 @@
 
 #include "dap_http_server.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 int dap_chain_net_bugreport_init(dap_http_server_t * a_http);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/net/include/dap_chain_net_decree.h b/modules/net/include/dap_chain_net_decree.h
index 6cf2e6eff0..dcb2bceee1 100644
--- a/modules/net/include/dap_chain_net_decree.h
+++ b/modules/net/include/dap_chain_net_decree.h
@@ -25,6 +25,10 @@
 #include "dap_list.h"
 #include "dap_chain_net.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef struct dap_chain_net_decree {
     dap_list_t *pkeys;
     uint16_t num_of_owners;
@@ -41,3 +45,7 @@ int dap_chain_net_decree_verify(dap_chain_net_t *a_net, dap_chain_datum_decree_t
 int dap_chain_net_decree_load(dap_chain_datum_decree_t * a_decree, dap_chain_t *a_chain, dap_chain_hash_fast_t *a_decree_hash);
 dap_chain_datum_decree_t *dap_chain_net_decree_get_by_hash(dap_chain_net_t *a_net, dap_hash_fast_t *a_hash, bool *is_applied);
 int dap_chain_net_decree_reset_applied(dap_chain_net_t *a_net, dap_chain_hash_fast_t *a_decree_hash);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/net/include/dap_chain_net_node_list.h b/modules/net/include/dap_chain_net_node_list.h
index 8fe6dd6b1b..f61624c9b4 100644
--- a/modules/net/include/dap_chain_net_node_list.h
+++ b/modules/net/include/dap_chain_net_node_list.h
@@ -29,6 +29,10 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 
 #define DAP_NODE_LIST_URI_HASH "node_list_hash"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 struct node_link_request {
     dap_chain_node_info_t *link_info;
     dap_chain_net_t *net;
@@ -55,3 +59,7 @@ DAP_STATIC_INLINE char* dap_chain_net_node_list_get_gdb_group(dap_chain_net_t *
 void dap_chain_net_node_check_http_issue_link(dap_http_simple_t *a_http_simple, void *a_arg);
 int dap_chain_net_node_list_request(dap_chain_net_t *a_net, uint16_t a_port, bool a_sync, char a_cmd);
 int dap_chain_net_node_list_init();
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/net/include/dap_chain_net_tx.h b/modules/net/include/dap_chain_net_tx.h
index 67e594d734..b729a75025 100644
--- a/modules/net/include/dap_chain_net_tx.h
+++ b/modules/net/include/dap_chain_net_tx.h
@@ -27,6 +27,10 @@
 #include "dap_chain_datum_tx_items.h"
 #include "dap_json_rpc_errors.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef enum s_com_tx_create_json_err {
     DAP_CHAIN_NET_TX_CREATE_JSON_OK = 0,
     DAP_CHAIN_NET_TX_CREATE_JSON_REQUIRE_PARAMETER_JSON = DAP_JSON_RPC_ERR_CODE_METHOD_ERR_START,
@@ -128,4 +132,8 @@ int dap_chain_net_tx_create_by_json(json_object *a_tx_json, dap_chain_net_t *a_n
  * 
  * @return s_com_tx_create_json_err_t status code
  */
-int dap_chain_net_tx_to_json(dap_chain_datum_tx_t *a_tx, json_object *a_out_json);
\ No newline at end of file
+int dap_chain_net_tx_to_json(dap_chain_datum_tx_t *a_tx, json_object *a_out_json);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/net/include/dap_chain_node.h b/modules/net/include/dap_chain_node.h
index 320748529e..a6d46f8c51 100644
--- a/modules/net/include/dap_chain_node.h
+++ b/modules/net/include/dap_chain_node.h
@@ -28,6 +28,10 @@
 #include "dap_chain.h"
 #include "dap_client.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef struct dap_chain_net dap_chain_net_t;
 
 typedef struct dap_chain_node_info_old {
@@ -91,3 +95,7 @@ bool dap_chain_node_mempool_autoproc_init();
 inline static void dap_chain_node_mempool_autoproc_deinit() {}
 dap_list_t *dap_chain_node_get_states_list_sort(dap_chain_net_t *a_net, dap_chain_node_addr_t *a_ignored, size_t a_ignored_count);
 dap_string_t *dap_chain_node_states_info_read(dap_chain_net_t *a_net, dap_stream_node_addr_t a_addr);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/net/include/dap_chain_node_cli.h b/modules/net/include/dap_chain_node_cli.h
index 14b52dc90b..2893306b7d 100644
--- a/modules/net/include/dap_chain_node_cli.h
+++ b/modules/net/include/dap_chain_node_cli.h
@@ -32,6 +32,10 @@
 
 #include "dap_cli_server.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /**
  * Initialization of the server side of the interaction
  * with the console kelvin-node-cli
@@ -42,3 +46,7 @@ int dap_chain_node_cli_init(dap_config_t * g_config);
  * Deinitialization of the server side
  */
 void dap_chain_node_cli_delete(void);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/net/include/dap_chain_node_cli_cmd.h b/modules/net/include/dap_chain_node_cli_cmd.h
index 93572f9e91..3b8871adf0 100644
--- a/modules/net/include/dap_chain_node_cli_cmd.h
+++ b/modules/net/include/dap_chain_node_cli_cmd.h
@@ -31,6 +31,10 @@
 #include "dap_chain_node_cli.h"
 #include "json.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 int dap_chain_node_cli_cmd_values_parse_net_chain_for_json(json_object* a_json_arr_reply, int *a_arg_index, int a_argc,
                                                            char **a_argv,
                                                            dap_chain_t **a_chain, dap_chain_net_t **a_net,
@@ -375,3 +379,7 @@ int cmd_find(int a_argc, char **a_argv, void **a_str_reply);
 void dap_notify_new_client_send_info(dap_events_socket_t *a_es, void *a_arg);
 
 int com_exec_cmd(int argc, char **argv, void **reply);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/net/include/dap_chain_node_cli_cmd_tx.h b/modules/net/include/dap_chain_node_cli_cmd_tx.h
index 442f895e7e..def00d9838 100644
--- a/modules/net/include/dap_chain_node_cli_cmd_tx.h
+++ b/modules/net/include/dap_chain_node_cli_cmd_tx.h
@@ -29,6 +29,10 @@
 #include "dap_chain_common.h"
 #include "dap_chain_net.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef struct dap_chain_tx_hash_processed_ht{
     dap_chain_hash_fast_t hash;
     UT_hash_handle hh;
@@ -115,3 +119,6 @@ typedef enum s_com_token_err{
  */
 int cmd_decree(int a_argc, char **a_argv, void **a_str_reply);
 
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/net/include/dap_chain_node_client.h b/modules/net/include/dap_chain_node_client.h
index d255d2b35c..b696f030bb 100644
--- a/modules/net/include/dap_chain_node_client.h
+++ b/modules/net/include/dap_chain_node_client.h
@@ -30,6 +30,10 @@
 #include "dap_chain_node.h"
 #include "dap_stream_ch_pkt.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 // connection states
 typedef enum dap_chain_node_client_state {
     NODE_CLIENT_STATE_ERROR = -1,
@@ -171,3 +175,7 @@ static inline const char * dap_chain_node_client_state_to_str( dap_chain_node_cl
     }
 
 }
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/net/include/dap_chain_node_dns_client.h b/modules/net/include/dap_chain_node_dns_client.h
index 5ab385243c..0ce425c7a7 100644
--- a/modules/net/include/dap_chain_node_dns_client.h
+++ b/modules/net/include/dap_chain_node_dns_client.h
@@ -33,6 +33,9 @@
 #define DNS_LISTEN_PORT 53      // UDP
 #define DNS_LISTEN_PORT_STR "53"      // UDP
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 typedef struct _dap_dns_buf_t {
     char *data;
     uint32_t size;
@@ -51,3 +54,7 @@ void dap_dns_buf_put_uint64(dap_dns_buf_t *buf, uint64_t val);
 void dap_dns_buf_put_uint32(dap_dns_buf_t *buf, uint32_t val);
 void dap_dns_buf_put_uint16(dap_dns_buf_t *buf, uint16_t val);
 uint16_t dap_dns_buf_get_uint16(dap_dns_buf_t *buf);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/net/include/dap_chain_node_dns_server.h b/modules/net/include/dap_chain_node_dns_server.h
index aa22b05bd3..56f79e1b26 100644
--- a/modules/net/include/dap_chain_node_dns_server.h
+++ b/modules/net/include/dap_chain_node_dns_server.h
@@ -38,6 +38,10 @@
 #define DNS_MAX_HOSTNAME_LEN 255
 #define DNS_MAX_DOMAIN_NAME_LEN 63
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef enum _dap_dns_query_type_t {
     DNS_QUERY_TYPE_STANDARD,
     DNS_QUERY_TYPE_INVERSE,
@@ -122,3 +126,6 @@ void dap_dns_server_stop();
 int dap_dns_zone_register(char *zone, dap_dns_zone_callback_t callback);
 int dap_dns_zone_unregister(char *zone);
 
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/net/include/dap_chain_node_ping.h b/modules/net/include/dap_chain_node_ping.h
index b94fa2ad8f..5c4a6eb30c 100644
--- a/modules/net/include/dap_chain_node_ping.h
+++ b/modules/net/include/dap_chain_node_ping.h
@@ -27,6 +27,10 @@
 #endif
 #include <pthread.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 // start sending ping
 int start_node_ping(pthread_t *a_thread, struct in_addr a_addr, int a_port, int a_count);
 
@@ -38,3 +42,7 @@ int wait_node_ping(pthread_t l_thread, int timeout_ms);
 int dap_chain_node_ping_background_start(dap_chain_net_t *a_net, dap_list_t *a_node_list);
 int dap_chain_node_ping_background_stop(void);
 int dap_chain_node_ping_background_status(void);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/wallet/include/dap_chain_coin.h b/modules/wallet/include/dap_chain_coin.h
index e7e79f6034..5395e039a5 100644
--- a/modules/wallet/include/dap_chain_coin.h
+++ b/modules/wallet/include/dap_chain_coin.h
@@ -22,3 +22,12 @@
     along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
 */
 #pragma once
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/wallet/include/dap_chain_wallet.h b/modules/wallet/include/dap_chain_wallet.h
index 01c65dc889..ecea35b5f8 100644
--- a/modules/wallet/include/dap_chain_wallet.h
+++ b/modules/wallet/include/dap_chain_wallet.h
@@ -38,6 +38,10 @@
 #define DAP_WALLET$M_FL_PROTECTED        (1 << 0)                           /* Wallet is password protected */
 #define DAP_WALLET$M_FL_ACTIVE           (1 << 1)                           /* Has been activated (has been open with password) */
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef struct dap_chain_wallet{
     char        name[ DAP_WALLET$SZ_NAME + 1 ];                             /* Human readable name of BMF Wallet */
     uint64_t    flags;                                                      /* See DAP_WALLET$M_FL_* constants */
@@ -95,4 +99,8 @@ int dap_chain_wallet_get_pkey_hash(dap_chain_wallet_t *a_wallet, dap_hash_fast_t
 
 int dap_chain_wallet_add_wallet_opened_notify(dap_chain_wallet_opened_callback_t a_callback, void *a_arg);
 int dap_chain_wallet_add_wallet_created_notify(dap_chain_wallet_opened_callback_t a_callback, void *a_arg);
-dap_list_t* dap_chain_wallet_get_local_addr();
\ No newline at end of file
+dap_list_t* dap_chain_wallet_get_local_addr();
+
+#ifdef __cplusplus
+extern "C" {
+#endif
\ No newline at end of file
diff --git a/modules/wallet/include/dap_chain_wallet_cache.h b/modules/wallet/include/dap_chain_wallet_cache.h
index 2225436069..d277fca4cd 100644
--- a/modules/wallet/include/dap_chain_wallet_cache.h
+++ b/modules/wallet/include/dap_chain_wallet_cache.h
@@ -27,6 +27,10 @@
 #include "dap_chain_common.h"
 #include "dap_chain_ledger.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef enum dap_chain_wallet_getting_type {
     DAP_CHAIN_WALLET_CACHE_GET_FIRST = 0,
     DAP_CHAIN_WALLET_CACHE_GET_LAST,
@@ -100,4 +104,8 @@ int dap_chain_wallet_cache_tx_find_outs(dap_chain_net_t *a_net, const char *a_to
                                                     
 dap_chain_wallet_cache_iter_t *dap_chain_wallet_cache_iter_create(dap_chain_addr_t a_addr);
 void dap_chain_wallet_cache_iter_delete(dap_chain_wallet_cache_iter_t *a_iter);
-dap_chain_datum_tx_t *dap_chain_wallet_cache_iter_get(dap_chain_wallet_cache_iter_t *a_iter, dap_chain_wallet_getting_type_t a_type);
\ No newline at end of file
+dap_chain_datum_tx_t *dap_chain_wallet_cache_iter_get(dap_chain_wallet_cache_iter_t *a_iter, dap_chain_wallet_getting_type_t a_type);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/wallet/include/dap_chain_wallet_internal.h b/modules/wallet/include/dap_chain_wallet_internal.h
index f11d1bc16c..40de3c46b6 100644
--- a/modules/wallet/include/dap_chain_wallet_internal.h
+++ b/modules/wallet/include/dap_chain_wallet_internal.h
@@ -31,6 +31,9 @@
 
 #define DAP_CHAIN_WALLETS_FILE_SIGNATURE (uint64_t)0x1a167bef15feea18
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 enum    {
     DAP_WALLET$K_TYPE_PLAIN = 0,                                            /* 0x00 - uncompressed and unencrypted */
@@ -97,3 +100,6 @@ typedef struct dap_chain_wallet_internal
 #define DAP_CHAIN_WALLET_INTERNAL_LOCAL(a) dap_chain_wallet_internal_t * l_wallet_internal = DAP_CHAIN_WALLET_INTERNAL(a)
 #define DAP_CHAIN_WALLET_INTERNAL_LOCAL_NEW(a) dap_chain_wallet_internal_t * l_wallet_internal = DAP_NEW_Z(dap_chain_wallet_internal_t); a->_internal = l_wallet_internal
 
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/modules/wallet/include/dap_chain_wallet_ops.h b/modules/wallet/include/dap_chain_wallet_ops.h
index 90f610a1e8..6085befa48 100644
--- a/modules/wallet/include/dap_chain_wallet_ops.h
+++ b/modules/wallet/include/dap_chain_wallet_ops.h
@@ -3,6 +3,14 @@
 #include "dap_chain.h"
 #include "dap_chain_wallet.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 void dap_chain_wallet_op_tx_request(dap_chain_wallet_t * a_wallet, uint32_t a_wallet_key_idx, /// Sender's wallet and key index in it
                              dap_chain_t * a_chain_source, uint64_t a_value, /// Token source and daptoshi's value
                              dap_chain_t * a_chain_tx_request, dap_chain_addr_t a_destination ); ///  TX blockchain where to create new block
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
-- 
GitLab


From 6a8370c8c46c6155a121496c4518b97fa2c20c24 Mon Sep 17 00:00:00 2001
From: "daniil.frolov" <daniil.frolov@demlabs.net>
Date: Fri, 17 Jan 2025 14:14:30 +0300
Subject: [PATCH 12/18] ..

---
 modules/common/include/dap_chain_datum.h      |   7 +-
 .../common/include/dap_chain_datum_anchor.h   |  10 +-
 .../common/include/dap_chain_datum_decree.h   |   9 +-
 .../include/dap_chain_datum_hashtree_roots.h  |   6 -
 .../common/include/dap_chain_datum_token.h    | 101 +++----
 modules/common/include/dap_chain_datum_tx.h   |   8 +-
 .../common/include/dap_chain_datum_tx_in.h    |   6 -
 .../include/dap_chain_datum_tx_in_cond.h      |   8 -
 .../include/dap_chain_datum_tx_in_ems.h       |   6 -
 .../include/dap_chain_datum_tx_in_reward.h    |   6 -
 .../common/include/dap_chain_datum_tx_items.h |   6 +-
 .../common/include/dap_chain_datum_tx_out.h   |   6 -
 .../include/dap_chain_datum_tx_out_cond.h     |  34 +--
 .../include/dap_chain_datum_tx_out_ext.h      |   7 -
 .../common/include/dap_chain_datum_tx_pkey.h  |   8 -
 .../common/include/dap_chain_datum_tx_sig.h   |   8 -
 .../common/include/dap_chain_datum_tx_tsd.h   |   6 -
 .../include/dap_chain_datum_tx_voting.h       |   8 +-
 modules/net/include/dap_chain_ledger.h        | 154 +++++------
 modules/net/include/dap_chain_net.h           |  63 ++---
 modules/net/include/dap_chain_net_balancer.h  |   7 +-
 modules/net/include/dap_chain_net_decree.h    |   7 +-
 modules/net/include/dap_chain_net_node_list.h |   7 +-
 modules/net/include/dap_chain_net_tx.h        |   9 +-
 modules/net/include/dap_chain_node.h          |   6 +-
 modules/net/include/dap_chain_node_cli_cmd.h  | 251 +++++++++---------
 .../net/include/dap_chain_node_cli_cmd_tx.h   |  63 ++---
 modules/net/include/dap_chain_node_client.h   |   8 +-
 .../net/include/dap_chain_node_dns_client.h   |   6 +-
 .../net/include/dap_chain_node_dns_server.h   |   8 +-
 modules/wallet/include/dap_chain_coin.h       |   8 -
 modules/wallet/include/dap_chain_wallet.h     |   8 +-
 .../wallet/include/dap_chain_wallet_cache.h   |   7 +-
 .../include/dap_chain_wallet_internal.h       |   7 -
 34 files changed, 403 insertions(+), 466 deletions(-)

diff --git a/modules/common/include/dap_chain_datum.h b/modules/common/include/dap_chain_datum.h
index 7c20ce32be..e171564335 100644
--- a/modules/common/include/dap_chain_datum.h
+++ b/modules/common/include/dap_chain_datum.h
@@ -104,9 +104,6 @@
 
 #define DAP_CHAIN_DATUM_ID_SIZE 2
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 
 // Datum subchain type id
 typedef union dap_chain_datum_typeid{
@@ -133,6 +130,10 @@ typedef struct dap_chain_datum{
     byte_t data[]; /// Stored datum body
 } DAP_ALIGN_PACKED dap_chain_datum_t;
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /**
  * @brief dap_chain_datum_size
  * @param a_datum
diff --git a/modules/common/include/dap_chain_datum_anchor.h b/modules/common/include/dap_chain_datum_anchor.h
index 41986a06be..37014cce76 100644
--- a/modules/common/include/dap_chain_datum_anchor.h
+++ b/modules/common/include/dap_chain_datum_anchor.h
@@ -43,15 +43,17 @@ typedef struct dap_chain_datum_anchor{
 // ANCHOR TSD types
 #define DAP_CHAIN_DATUM_ANCHOR_TSD_TYPE_DECREE_HASH                0x0001
 
-DAP_STATIC_INLINE size_t dap_chain_datum_anchor_get_size(dap_chain_datum_anchor_t *a_datum_anchor)
-{
-    return sizeof(*a_datum_anchor) + a_datum_anchor->header.data_size + a_datum_anchor->header.signs_size;
-}
+
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+DAP_STATIC_INLINE size_t dap_chain_datum_anchor_get_size(dap_chain_datum_anchor_t *a_datum_anchor)
+{
+    return sizeof(*a_datum_anchor) + a_datum_anchor->header.data_size + a_datum_anchor->header.signs_size;
+}
+
 int dap_chain_datum_anchor_get_hash_from_data(dap_chain_datum_anchor_t* a_anchor, dap_hash_fast_t * a_out_hash);
 void dap_chain_datum_anchor_certs_dump(dap_string_t * a_str_out, byte_t * a_signs,
                                        size_t a_certs_size, const char *a_hash_out_type);
diff --git a/modules/common/include/dap_chain_datum_decree.h b/modules/common/include/dap_chain_datum_decree.h
index e1292b35b2..19e956cbbd 100644
--- a/modules/common/include/dap_chain_datum_decree.h
+++ b/modules/common/include/dap_chain_datum_decree.h
@@ -31,10 +31,6 @@
 
 #define DAP_CHAIN_DATUM_DECREE_VERSION  0
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 // Governance decree
 typedef struct dap_chain_datum_decree {
     uint16_t decree_version;
@@ -98,6 +94,11 @@ DAP_STATIC_INLINE size_t dap_chain_datum_decree_get_size(dap_chain_datum_decree_
 #define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_ACTION                              0x010A
 #define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGNATURE_TYPE                      0x010B
 
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 DAP_STATIC_INLINE const char *dap_chain_datum_decree_subtype_to_str(uint16_t a_decree_subtype)
 {
     switch(a_decree_subtype) {
diff --git a/modules/common/include/dap_chain_datum_hashtree_roots.h b/modules/common/include/dap_chain_datum_hashtree_roots.h
index 8ff8f79d86..2b8ec9b513 100644
--- a/modules/common/include/dap_chain_datum_hashtree_roots.h
+++ b/modules/common/include/dap_chain_datum_hashtree_roots.h
@@ -26,9 +26,6 @@
 #include "dap_common.h"
 #include "dap_chain_common.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 /**
   * @struct dap_chain_datum_hashtree_roots_v1
   * @brief Hash tree roots for block, version 1
@@ -48,6 +45,3 @@ typedef struct dap_chain_datum_hashtree_roots_v2{
 
 typedef dap_chain_datum_hashtree_roots_v2_t dap_chain_datum_hashtree_roots_t;
 
-#ifdef __cplusplus
-}
-#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_token.h b/modules/common/include/dap_chain_datum_token.h
index c37131dc12..f596c2e605 100644
--- a/modules/common/include/dap_chain_datum_token.h
+++ b/modules/common/include/dap_chain_datum_token.h
@@ -34,9 +34,6 @@
 
 
 #define DAP_CHAIN_DATUM_NONCE_SIZE                                          64
-#ifdef __cplusplus
-extern "C" {
-#endif
 // Token declaration
 typedef struct dap_chain_datum_token_old {
     uint16_t type;
@@ -217,30 +214,6 @@ typedef struct dap_chain_datum_token_tsd_delegate_from_stake_lock {
 
 #define DAP_CHAIN_DATUM_TOKEN_FLAG_UNDEFINED                                0xffff
 
-DAP_STATIC_INLINE const char *dap_chain_datum_token_flag_to_str(uint32_t a_flag)
-{
-    switch (a_flag) {
-    case DAP_CHAIN_DATUM_TOKEN_FLAG_NONE: return "NONE";
-    case DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_BLOCKED: return "ALL_SENDER_BLOCKED";
-    case DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_ALLOWED: return "ALL_SENDER_ALLOWED";
-    case DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_FROZEN: return "ALL_SENDER_FROZEN";
-    case DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_UNFROZEN: return "ALL_SENDER_UNFROZEN";
-    case DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_BLOCKED: return "ALL_RECEIVER_BLOCKED";
-    case DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_ALLOWED: return "ALL_RECEIVER_ALLOWED";
-    case DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_FROZEN: return "ALL_RECEIVER_FROZEN";
-    case DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_UNFROZEN: return "ALL_RECEIVER_UNFROZEN";
-    case DAP_CHAIN_DATUM_TOKEN_FLAG_STATIC_ALL: return "STATIC_ALL";
-    case DAP_CHAIN_DATUM_TOKEN_FLAG_STATIC_FLAGS: return "STATIC_FLAGS";
-    case DAP_CHAIN_DATUM_TOKEN_FLAG_STATIC_PERMISSIONS_ALL: return "STATIC_PERMISSIONS_ALL";
-    case DAP_CHAIN_DATUM_TOKEN_FLAG_STATIC_PERMISSIONS_DATUM_TYPE: return "STATIC_PERMISSIONS_DATUM_TYPE";
-    case DAP_CHAIN_DATUM_TOKEN_FLAG_STATIC_PERMISSIONS_TX_SENDER: return "TATIC_PERMISSIONS_TX_SENDER";
-    case DAP_CHAIN_DATUM_TOKEN_FLAG_STATIC_PERMISSIONS_TX_RECEIVER: return "STATIC_PERMISSIONS_TX_RECEIVER";
-    default: return "UNKNOWN FLAG OR FLAGS GROUP";
-    }
-}
-
-uint32_t dap_chain_datum_token_flag_from_str(const char *a_str);
-
 /// -------- General tsd types ----
 // Flags set/unsed
 #define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_SET_FLAGS                            0x0001
@@ -298,29 +271,6 @@ uint32_t dap_chain_datum_token_flag_from_str(const char *a_str);
 #define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_REMOVE             0x0024
 #define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_CLEAR              0x0025
 
-
-// Get delegated ticker
-DAP_STATIC_INLINE int dap_chain_datum_token_get_delegated_ticker(char *a_buf, const char *a_ticker)
-{
-    if (!a_buf || !a_ticker)
-        return -1;
-    *a_buf = 'm';
-    dap_strncpy(a_buf + 1, a_ticker, DAP_CHAIN_TICKER_SIZE_MAX - 1);
-    return 0;
-}
-
-DAP_STATIC_INLINE bool dap_chain_datum_token_is_old(uint8_t a_type)
-{
-    return a_type == DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE
-           || a_type == DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PRIVATE_DECL
-           || a_type == DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PRIVATE_UPDATE
-           || a_type == DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_NATIVE_DECL
-           || a_type == DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_NATIVE_UPDATE
-           || a_type == DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PUBLIC;
-}
-
-/*                              Token emission section                          */
-
 struct DAP_ALIGN_PACKED dap_chain_emission_header_v0 {
     uint8_t version;
     uint8_t type; // Emission Type
@@ -410,6 +360,57 @@ typedef struct dap_chain_datum_token_emission {
 #define DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_BRIDGE_CROSSCHAIN "CROSSCHAIN"
 #define DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_BRIDGE_OUT "OUT"
 
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+DAP_STATIC_INLINE const char *dap_chain_datum_token_flag_to_str(uint32_t a_flag)
+{
+    switch (a_flag) {
+    case DAP_CHAIN_DATUM_TOKEN_FLAG_NONE: return "NONE";
+    case DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_BLOCKED: return "ALL_SENDER_BLOCKED";
+    case DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_ALLOWED: return "ALL_SENDER_ALLOWED";
+    case DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_FROZEN: return "ALL_SENDER_FROZEN";
+    case DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_UNFROZEN: return "ALL_SENDER_UNFROZEN";
+    case DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_BLOCKED: return "ALL_RECEIVER_BLOCKED";
+    case DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_ALLOWED: return "ALL_RECEIVER_ALLOWED";
+    case DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_FROZEN: return "ALL_RECEIVER_FROZEN";
+    case DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_UNFROZEN: return "ALL_RECEIVER_UNFROZEN";
+    case DAP_CHAIN_DATUM_TOKEN_FLAG_STATIC_ALL: return "STATIC_ALL";
+    case DAP_CHAIN_DATUM_TOKEN_FLAG_STATIC_FLAGS: return "STATIC_FLAGS";
+    case DAP_CHAIN_DATUM_TOKEN_FLAG_STATIC_PERMISSIONS_ALL: return "STATIC_PERMISSIONS_ALL";
+    case DAP_CHAIN_DATUM_TOKEN_FLAG_STATIC_PERMISSIONS_DATUM_TYPE: return "STATIC_PERMISSIONS_DATUM_TYPE";
+    case DAP_CHAIN_DATUM_TOKEN_FLAG_STATIC_PERMISSIONS_TX_SENDER: return "TATIC_PERMISSIONS_TX_SENDER";
+    case DAP_CHAIN_DATUM_TOKEN_FLAG_STATIC_PERMISSIONS_TX_RECEIVER: return "STATIC_PERMISSIONS_TX_RECEIVER";
+    default: return "UNKNOWN FLAG OR FLAGS GROUP";
+    }
+}
+
+uint32_t dap_chain_datum_token_flag_from_str(const char *a_str);
+
+// Get delegated ticker
+DAP_STATIC_INLINE int dap_chain_datum_token_get_delegated_ticker(char *a_buf, const char *a_ticker)
+{
+    if (!a_buf || !a_ticker)
+        return -1;
+    *a_buf = 'm';
+    dap_strncpy(a_buf + 1, a_ticker, DAP_CHAIN_TICKER_SIZE_MAX - 1);
+    return 0;
+}
+
+DAP_STATIC_INLINE bool dap_chain_datum_token_is_old(uint8_t a_type)
+{
+    return a_type == DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE
+           || a_type == DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PRIVATE_DECL
+           || a_type == DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PRIVATE_UPDATE
+           || a_type == DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_NATIVE_DECL
+           || a_type == DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_NATIVE_UPDATE
+           || a_type == DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PUBLIC;
+}
+
+/*                              Token emission section                          */
+
 DAP_STATIC_INLINE const char *dap_chain_datum_emission_type_str(uint8_t a_type)
 {
     switch (a_type) {
diff --git a/modules/common/include/dap_chain_datum_tx.h b/modules/common/include/dap_chain_datum_tx.h
index f5ef493eed..110f2313c5 100644
--- a/modules/common/include/dap_chain_datum_tx.h
+++ b/modules/common/include/dap_chain_datum_tx.h
@@ -30,10 +30,6 @@
 #include "dap_pkey.h"
 
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
   * @struct dap_chain_datum_tx
   * @brief Transaction section, consists from lot of tx_items
@@ -61,6 +57,10 @@ typedef struct dap_chain_datum_tx {
         !!( item = dap_chain_datum_tx_item_get(tx, &item_index, (byte_t*)item + item_size, item_type, &item_size) );\
         item_index = 0 )
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /**
  * Create empty transaction
  *
diff --git a/modules/common/include/dap_chain_datum_tx_in.h b/modules/common/include/dap_chain_datum_tx_in.h
index 242ae43ecf..5352eca464 100644
--- a/modules/common/include/dap_chain_datum_tx_in.h
+++ b/modules/common/include/dap_chain_datum_tx_in.h
@@ -28,9 +28,6 @@
 #include "dap_chain_common.h"
 #include "dap_chain_datum_tx.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 
 /**
   * @struct dap_chain_tx_item
@@ -51,6 +48,3 @@ typedef struct dap_chain_tx_used_out_item {
     uint256_t value;
 } dap_chain_tx_used_out_item_t;
 
-#ifdef __cplusplus
-}
-#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_tx_in_cond.h b/modules/common/include/dap_chain_datum_tx_in_cond.h
index f6ffe2fca0..3991f242ed 100644
--- a/modules/common/include/dap_chain_datum_tx_in_cond.h
+++ b/modules/common/include/dap_chain_datum_tx_in_cond.h
@@ -28,10 +28,6 @@
 #include "dap_chain_common.h"
 #include "dap_chain_datum_tx.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * @struct dap_chain_tx_item
  * @brief Sections belongs to heading tx section, with inputs, outputs and others tx relatated items
@@ -45,7 +41,3 @@ typedef struct dap_chain_tx_in_cond {
         uint32_t receipt_idx DAP_ALIGNED(4);
     } DAP_PACKED header; /// Only header's hash is used for verification
 } DAP_PACKED dap_chain_tx_in_cond_t;
-
-#ifdef __cplusplus
-}
-#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_tx_in_ems.h b/modules/common/include/dap_chain_datum_tx_in_ems.h
index b745fa727d..bc9ee838ce 100644
--- a/modules/common/include/dap_chain_datum_tx_in_ems.h
+++ b/modules/common/include/dap_chain_datum_tx_in_ems.h
@@ -27,9 +27,6 @@
 #include "dap_common.h"
 #include "dap_chain_common.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 
 /**
   * @struct dap_chain_tx_token
@@ -63,6 +60,3 @@ typedef struct dap_chain_tx_in_ems_ext{
     } header; /// Only header's hash is used for verification
 } DAP_ALIGN_PACKED dap_chain_tx_in_ems_ext_t;
 
-#ifdef __cplusplus
-}
-#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_tx_in_reward.h b/modules/common/include/dap_chain_datum_tx_in_reward.h
index 6d8fa17a37..3e05f35218 100644
--- a/modules/common/include/dap_chain_datum_tx_in_reward.h
+++ b/modules/common/include/dap_chain_datum_tx_in_reward.h
@@ -24,14 +24,8 @@ along with any DAP SDK based project.  If not, see <http://www.gnu.org/licenses/
 #pragma once
 #include "dap_chain_common.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 typedef struct dap_chain_tx_in_reward {
     dap_chain_tx_item_type_t type;          /// @param type             @brief Transaction item type
     dap_hash_t block_hash;                  /// @param block_hash       @brief Hash of the block signed with current validator
 } DAP_ALIGN_PACKED dap_chain_tx_in_reward_t;
 
-#ifdef __cplusplus
-}
-#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_tx_items.h b/modules/common/include/dap_chain_datum_tx_items.h
index d62f1c12a6..4d2c90f790 100644
--- a/modules/common/include/dap_chain_datum_tx_items.h
+++ b/modules/common/include/dap_chain_datum_tx_items.h
@@ -41,9 +41,6 @@
 #include "dap_chain_datum_tx_tsd.h"
 #include "dap_chain_datum_tx_in_reward.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 typedef struct dap_chain_datum_tx_item_groups {
 
     dap_list_t *items_in_all;
@@ -78,6 +75,9 @@ typedef struct dap_chain_datum_tx_item_groups {
 
 } dap_chain_datum_tx_item_groups_t;
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 /**
  * Get item name by item type
  *
diff --git a/modules/common/include/dap_chain_datum_tx_out.h b/modules/common/include/dap_chain_datum_tx_out.h
index 084b5bba20..f7e48c54a7 100644
--- a/modules/common/include/dap_chain_datum_tx_out.h
+++ b/modules/common/include/dap_chain_datum_tx_out.h
@@ -28,9 +28,6 @@
 #include "dap_chain_common.h"
 #include "dap_chain_datum_tx.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 
 /**
   * @struct dap_chain_tx_out
@@ -53,6 +50,3 @@ typedef struct dap_chain_tx_out {
     dap_chain_addr_t addr; ////
 } DAP_PACKED dap_chain_tx_out_t;
 
-#ifdef __cplusplus
-}
-#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_tx_out_cond.h b/modules/common/include/dap_chain_datum_tx_out_cond.h
index 1325127e68..b5988638c9 100644
--- a/modules/common/include/dap_chain_datum_tx_out_cond.h
+++ b/modules/common/include/dap_chain_datum_tx_out_cond.h
@@ -29,10 +29,6 @@
 #include "dap_time.h"
 #include "dap_chain_common.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 enum dap_chain_tx_out_cond_subtype {
     DAP_CHAIN_TX_OUT_COND_SUBTYPE_UNDEFINED = 0x0,
     DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY = 0x01,
@@ -45,19 +41,6 @@ enum dap_chain_tx_out_cond_subtype {
 };
 typedef byte_t dap_chain_tx_out_cond_subtype_t;
 
-DAP_STATIC_INLINE const char *dap_chain_tx_out_cond_subtype_to_str(dap_chain_tx_out_cond_subtype_t a_subtype){
-    switch (a_subtype) {
-    case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY: return "DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY";
-    case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE: return "DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE";
-    case DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE: return "DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE";
-    case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE: return "DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE";
-    case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK: return "DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK";
-    case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_EMIT_DELEGATE: return "DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_EMIT_DELEGATE";
-    default: {}
-    }
-    return "UNDEFINED";
-}
-
 // Stake lock base flags
 // Lock by time
 #define DAP_CHAIN_NET_SRV_STAKE_LOCK_FLAG_BY_TIME           0x00000008
@@ -139,6 +122,23 @@ typedef struct dap_chain_tx_out_cond {
     uint8_t tsd[]; // condition parameters, pkey, hash or smth like this
 } DAP_ALIGN_PACKED dap_chain_tx_out_cond_t;
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+DAP_STATIC_INLINE const char *dap_chain_tx_out_cond_subtype_to_str(dap_chain_tx_out_cond_subtype_t a_subtype){
+    switch (a_subtype) {
+    case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY: return "DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY";
+    case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE: return "DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE";
+    case DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE: return "DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE";
+    case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE: return "DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE";
+    case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK: return "DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK";
+    case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_EMIT_DELEGATE: return "DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_EMIT_DELEGATE";
+    default: {}
+    }
+    return "UNDEFINED";
+}
+
 #ifdef __cplusplus
 }
 #endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_tx_out_ext.h b/modules/common/include/dap_chain_datum_tx_out_ext.h
index 69aa1e9f5b..6c9351f1b5 100644
--- a/modules/common/include/dap_chain_datum_tx_out_ext.h
+++ b/modules/common/include/dap_chain_datum_tx_out_ext.h
@@ -29,9 +29,6 @@
 #include "dap_chain_common.h"
 #include "dap_chain_datum_tx.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 typedef struct dap_chain_tx_out_ext{
     struct {
         dap_chain_tx_item_type_t type;     // Transaction item type - should be TX_ITEM_TYPE_OUT_EXT
@@ -40,7 +37,3 @@ typedef struct dap_chain_tx_out_ext{
     dap_chain_addr_t addr;                 // Address to transfer to
     const char token[DAP_CHAIN_TICKER_SIZE_MAX]; // Which token is transferred
 } DAP_PACKED dap_chain_tx_out_ext_t;
-
-#ifdef __cplusplus
-}
-#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_tx_pkey.h b/modules/common/include/dap_chain_datum_tx_pkey.h
index 817f6b2244..117d906c00 100644
--- a/modules/common/include/dap_chain_datum_tx_pkey.h
+++ b/modules/common/include/dap_chain_datum_tx_pkey.h
@@ -28,10 +28,6 @@
 #include "dap_chain_common.h"
 #include "dap_chain_datum_tx.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
   * @struct dap_chain_tx_pkey
   * @brief TX item with one of the transaction's public keys
@@ -45,7 +41,3 @@ typedef struct dap_chain_tx_pkey{
     uint32_t seq_no; /// Sequence number, out of the header so could be changed during reorganization
     uint8_t pkey[]; /// @param sig @brief raw pkey dat
 } DAP_PACKED dap_chain_tx_pkey_t;
-
-#ifdef __cplusplus
-}
-#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_tx_sig.h b/modules/common/include/dap_chain_datum_tx_sig.h
index 90bea9846d..93b5562b18 100644
--- a/modules/common/include/dap_chain_datum_tx_sig.h
+++ b/modules/common/include/dap_chain_datum_tx_sig.h
@@ -28,10 +28,6 @@
 #include "dap_chain_common.h"
 #include "dap_chain_datum_tx.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
   * @struct dap_chain_tx_sig
   * @brief Section with set of transaction signatures
@@ -44,7 +40,3 @@ typedef struct dap_chain_tx_sig{
     } DAP_PACKED header; /// Only header's hash is used for verification
     uint8_t sig[]; /// @param sig @brief raw signature data
 } DAP_PACKED dap_chain_tx_sig_t;
-
-#ifdef __cplusplus
-}
-#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_tx_tsd.h b/modules/common/include/dap_chain_datum_tx_tsd.h
index 1b3484b876..fc78dcd320 100644
--- a/modules/common/include/dap_chain_datum_tx_tsd.h
+++ b/modules/common/include/dap_chain_datum_tx_tsd.h
@@ -5,9 +5,6 @@
 #include "dap_chain_datum_tx.h"
 #include "dap_tsd.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 typedef struct dap_chain_tx_tsd {
     struct {
         dap_chain_tx_item_type_t type;
@@ -16,6 +13,3 @@ typedef struct dap_chain_tx_tsd {
     byte_t tsd[];
 } DAP_PACKED dap_chain_tx_tsd_t;
 
-#ifdef __cplusplus
-}
-#endif
\ No newline at end of file
diff --git a/modules/common/include/dap_chain_datum_tx_voting.h b/modules/common/include/dap_chain_datum_tx_voting.h
index 91139d1bd9..a87c67824c 100644
--- a/modules/common/include/dap_chain_datum_tx_voting.h
+++ b/modules/common/include/dap_chain_datum_tx_voting.h
@@ -36,10 +36,6 @@
 #define DAP_CHAIN_DATUM_TX_VOTING_OPTION_MAX_LENGTH 100
 #define DAP_CHAIN_DATUM_TX_VOTING_OPTION_MAX_COUNT 10
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 typedef enum dap_chain_datum_voting_tsd_type {
     VOTING_TSD_TYPE_QUESTION = 0x01,
     VOTING_TSD_TYPE_ANSWER,
@@ -76,6 +72,10 @@ typedef struct dap_chain_datum_tx_voting_params {
     bool       vote_changing_allowed;
 } dap_chain_datum_tx_voting_params_t;
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 
 dap_chain_datum_tx_voting_params_t *dap_chain_voting_parse_tsd(dap_chain_datum_tx_t* a_tx);
 
diff --git a/modules/net/include/dap_chain_ledger.h b/modules/net/include/dap_chain_ledger.h
index bfbee3ca8d..3f0b2aa997 100644
--- a/modules/net/include/dap_chain_ledger.h
+++ b/modules/net/include/dap_chain_ledger.h
@@ -40,10 +40,6 @@
 #define DAP_CHAIN_NET_SRV_TRANSFER_ID 0x09
 #define DAP_CHAIN_NET_SRV_BLOCK_REWARD_ID 0x08
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 typedef struct dap_ledger {
     dap_chain_net_t *net;
     void *_internal;
@@ -109,66 +105,6 @@ typedef enum dap_ledger_check_error {
     DAP_LEDGER_TX_CHECK_MULTIPLE_OUTS_TO_OTHER_NET,
 } dap_ledger_check_error_t;
 
-DAP_STATIC_INLINE const char *dap_ledger_check_error_str(dap_ledger_check_error_t a_error)
-{
-    switch (a_error) {
-    case DAP_LEDGER_CHECK_OK: return "No error";
-    case DAP_LEDGER_CHECK_INVALID_ARGS: return "Invalid arguments";
-    case DAP_LEDGER_CHECK_INVALID_SIZE: return "Incorrect size of datum or datum's content";
-    case DAP_LEDGER_CHECK_ALREADY_CACHED: return "Datum already cached in ledger";
-    case DAP_LEDGER_CHECK_PARSE_ERROR: return "Incorrect datum interrnal structure, can't pasre it";
-    case DAP_LEDGER_CHECK_APPLY_ERROR: return "Datum can't be applied";
-    case DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY: return "Not enough memory";
-    case DAP_LEDGER_CHECK_INTEGER_OVERFLOW: return "Incorrect datum values relationship lead to integer overflow, can't process";
-    case DAP_LEDGER_CHECK_NOT_ENOUGH_VALID_SIGNS: return "No enough valid signatures in datum";
-    case DAP_LEDGER_CHECK_TICKER_NOT_FOUND: return "Can't find specified token ticker";
-    case DAP_LEDGER_CHECK_ZERO_VALUE: return "Unacceptable zero value";
-    case DAP_LEDGER_CHECK_ADDR_FORBIDDEN: return "Specified address is forbidden";
-    case DAP_LEDGER_CHECK_WHITELISTED: return "Datum is in hard accept list";
-    /* TX check return codes */
-    case DAP_LEDGER_TX_CHECK_IN_EMS_ALREADY_USED: return "Double spend attempt for emission";
-    case DAP_LEDGER_TX_CHECK_STAKE_LOCK_IN_EMS_ALREADY_USED: return "Double spend attempt for stake-lock emission";
-    case DAP_LEDGER_TX_CHECK_EMISSION_NOT_FOUND: return "Specified emission not found in ledger";
-    case DAP_LEDGER_TX_CHECK_TX_NO_VALID_INPUTS: return "Transaction has no valid inputs, can't process";
-    case DAP_LEDGER_TX_CHECK_STAKE_LOCK_INVALID_TOKEN: return "Incorrect deledated token specified in stake-lock transaction";
-    case DAP_LEDGER_TX_CHECK_STAKE_LOCK_NO_OUT_COND_FOR_IN_EMS: return "Condtional output for stake-lock emission not found";
-    case DAP_LEDGER_TX_CHECK_NO_OUT_EXT_FOR_GIRDLED_IN_EMS: return "Tokenized output for stake-lock girdled emission not found";
-    case DAP_LEDGER_TX_CHECK_NO_OUT_ITEMS_FOR_BASE_TX: return "Output for basic transaction not found";
-    case DAP_LEDGER_TX_CHECK_STAKE_LOCK_UNEXPECTED_VALUE: return "Incorrect value for stake-lock emission, should be stake * rate";
-    case DAP_LEDGER_TX_CHECK_STAKE_LOCK_OTHER_TICKER_EXPECTED: return "Incorrect token ticker for stake-lock emission";
-    case DAP_LEDGER_TX_CHECK_OUT_ITEM_ALREADY_USED: return "Double spend attempt for transaction output";
-    case DAP_LEDGER_TX_CHECK_PREV_TX_NOT_FOUND: return "No previous transaction found";
-    case DAP_LEDGER_TX_CHECK_PREV_OUT_ITEM_NOT_FOUND: return "Specified output number not found in previous transaction";
-    case DAP_LEDGER_TX_CHECK_PREV_OUT_ITEM_MISSTYPED: return "Previuos transaction output has unknown type, possible ledger corruption";
-    case DAP_LEDGER_TX_CHECK_PKEY_HASHES_DONT_MATCH: return "Trying to spend transaction output from wrongful wallet";
-    case DAP_LEDGER_TX_CHECK_PREV_OUT_ALREADY_USED_IN_CURRENT_TX: return "Double spend attempt within single transaction";
-    case DAP_LEDGER_TX_CHECK_NO_VERIFICATOR_SET: return "No verificator found for specified conditional ipnput";
-    case DAP_LEDGER_TX_CHECK_VERIFICATOR_CHECK_FAILURE: return "Verificator check return error";
-    case DAP_LEDGER_TX_CHECK_SUM_INS_NOT_EQUAL_SUM_OUTS: return "Sum of transaction outputs isn't equal to sum of its inputs";
-    case DAP_LEDGER_TX_CHECK_REWARD_ITEM_ALREADY_USED: return "Double spend attempt for reward";
-    case DAP_LEDGER_TX_CHECK_REWARD_ITEM_ILLEGAL: return "Wrongful reward item in transaction";
-    case DAP_LEDGER_TX_CHECK_NO_MAIN_TICKER: return "Can't calculate main ticker found for transaction";
-    case DAP_LEDGER_TX_CHECK_UNEXPECTED_TOKENIZED_OUT: return "Tokenized out is forbidden for single-channel transactions";
-    case DAP_LEDGER_TX_CHECK_NOT_ENOUGH_FEE: return "Not enough network fee for transaction processing";
-    case DAP_LEDGER_TX_CHECK_NOT_ENOUGH_TAX: return "Not enough sovereign tax provided with current transaction";
-    case DAP_LEDGER_TX_CHECK_FOR_REMOVING_CANT_FIND_TX: return "Can't find tx in ledger for removing.";
-    case DAP_LEDGER_TX_CHECK_MULTIPLE_OUTS_TO_OTHER_NET: return "The transaction was rejected because it contains multiple outputs to other networks.";
-    /* Emisssion check return codes */
-    case DAP_LEDGER_EMISSION_CHECK_VALUE_EXCEEDS_CURRENT_SUPPLY: return "Value of emission execeeds current token supply";
-    case DAP_LEDGER_EMISSION_CHECK_LEGACY_FORBIDDEN: return "Legacy type of emissions are present for old chains comliance only";
-    /* Token declaration/update return codes */
-    case DAP_LEDGER_TOKEN_ADD_CHECK_NOT_ENOUGH_UNIQUE_SIGNS: return "Not all token signs is unique";
-    case DAP_LEDGER_TOKEN_ADD_CHECK_LEGACY_FORBIDDEN: return "Legacy type of tokens are present for old chains comliance only";
-    case DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_SUPPLY: return "Specified supply must be greater than current one";
-    case DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR: return "Specified address has invalid format";
-    case DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH: return "Specified address can't be processed cause double (for adding) or absent (for removing)";
-    case DAP_LEDGER_TOKEN_ADD_CHECK_TSD_PKEY_MISMATCH: return "Specified public key or its hash can't be processed cause double (for adding) or absent (for removing)";
-    case DAP_LEDGER_TOKEN_ADD_CHECK_TSD_FORBIDDEN: return "Specified TSD section type is not allowed in datum token of specified type";
-    case DAP_LEDGER_TOKEN_ADD_CHECK_TSD_OTHER_TICKER_EXPECTED: return "Incorrect token ticker for delegated token";
-    default: return "Unknown error";
-    }
-}
-
 typedef enum dap_chan_ledger_notify_opcodes{
     DAP_LEDGER_NOTIFY_OPCODE_ADDED = 'a', // 0x61
     DAP_LEDGER_NOTIFY_OPCODE_DELETED = 'd', // 0x64 
@@ -210,18 +146,6 @@ typedef struct dap_ledger_datum_iter_data {
     dap_chain_net_srv_uid_t uid;
 } dap_ledger_datum_iter_data_t;
 
-typedef int (*dap_ledger_verificator_callback_t)(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_tx_out_cond, dap_chain_datum_tx_t *a_tx_in, bool a_owner);
-typedef void (*dap_ledger_updater_callback_t)(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx_in, dap_hash_fast_t *a_tx_in_hash, dap_chain_tx_out_cond_t *a_prev_cond);
-typedef void (*dap_ledger_delete_callback_t)(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx_in, dap_chain_tx_out_cond_t *a_prev_cond);
-typedef void (* dap_ledger_tx_add_notify_t)(void *a_arg, dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, dap_chan_ledger_notify_opcodes_t a_opcode);
-typedef void (* dap_ledger_bridged_tx_notify_t)(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, void *a_arg, dap_chan_ledger_notify_opcodes_t a_opcode);
-typedef bool (*dap_ledger_cache_tx_check_callback_t)(dap_ledger_t *a_ledger, dap_hash_fast_t *a_tx_hash);
-typedef struct dap_chain_net dap_chain_net_t;
-typedef int (*dap_chain_ledger_voting_callback_t)(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, bool a_apply);
-typedef bool (*dap_chain_ledger_voting_delete_callback_t)(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx);
-typedef bool (*dap_ledger_tag_check_callback_t)(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_datum_tx_item_groups_t *a_items_grp, dap_chain_tx_tag_action_type_t *a_action);
-
-
 //Change this UUID to automatically reload ledger cache on next node startup
 #define DAP_LEDGER_CACHE_RELOAD_ONCE_UUID "0c92b759-a565-448f-b8bd-99103dacf7fc"
 
@@ -256,6 +180,84 @@ typedef bool (*dap_ledger_tag_check_callback_t)(dap_ledger_t *a_ledger, dap_chai
 #define DAP_LEDGER_SPENT_TXS_STR           "spent_txs"
 #define DAP_LEDGER_BALANCES_STR            "balances"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+DAP_STATIC_INLINE const char *dap_ledger_check_error_str(dap_ledger_check_error_t a_error)
+{
+    switch (a_error) {
+    case DAP_LEDGER_CHECK_OK: return "No error";
+    case DAP_LEDGER_CHECK_INVALID_ARGS: return "Invalid arguments";
+    case DAP_LEDGER_CHECK_INVALID_SIZE: return "Incorrect size of datum or datum's content";
+    case DAP_LEDGER_CHECK_ALREADY_CACHED: return "Datum already cached in ledger";
+    case DAP_LEDGER_CHECK_PARSE_ERROR: return "Incorrect datum interrnal structure, can't pasre it";
+    case DAP_LEDGER_CHECK_APPLY_ERROR: return "Datum can't be applied";
+    case DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY: return "Not enough memory";
+    case DAP_LEDGER_CHECK_INTEGER_OVERFLOW: return "Incorrect datum values relationship lead to integer overflow, can't process";
+    case DAP_LEDGER_CHECK_NOT_ENOUGH_VALID_SIGNS: return "No enough valid signatures in datum";
+    case DAP_LEDGER_CHECK_TICKER_NOT_FOUND: return "Can't find specified token ticker";
+    case DAP_LEDGER_CHECK_ZERO_VALUE: return "Unacceptable zero value";
+    case DAP_LEDGER_CHECK_ADDR_FORBIDDEN: return "Specified address is forbidden";
+    case DAP_LEDGER_CHECK_WHITELISTED: return "Datum is in hard accept list";
+    /* TX check return codes */
+    case DAP_LEDGER_TX_CHECK_IN_EMS_ALREADY_USED: return "Double spend attempt for emission";
+    case DAP_LEDGER_TX_CHECK_STAKE_LOCK_IN_EMS_ALREADY_USED: return "Double spend attempt for stake-lock emission";
+    case DAP_LEDGER_TX_CHECK_EMISSION_NOT_FOUND: return "Specified emission not found in ledger";
+    case DAP_LEDGER_TX_CHECK_TX_NO_VALID_INPUTS: return "Transaction has no valid inputs, can't process";
+    case DAP_LEDGER_TX_CHECK_STAKE_LOCK_INVALID_TOKEN: return "Incorrect deledated token specified in stake-lock transaction";
+    case DAP_LEDGER_TX_CHECK_STAKE_LOCK_NO_OUT_COND_FOR_IN_EMS: return "Condtional output for stake-lock emission not found";
+    case DAP_LEDGER_TX_CHECK_NO_OUT_EXT_FOR_GIRDLED_IN_EMS: return "Tokenized output for stake-lock girdled emission not found";
+    case DAP_LEDGER_TX_CHECK_NO_OUT_ITEMS_FOR_BASE_TX: return "Output for basic transaction not found";
+    case DAP_LEDGER_TX_CHECK_STAKE_LOCK_UNEXPECTED_VALUE: return "Incorrect value for stake-lock emission, should be stake * rate";
+    case DAP_LEDGER_TX_CHECK_STAKE_LOCK_OTHER_TICKER_EXPECTED: return "Incorrect token ticker for stake-lock emission";
+    case DAP_LEDGER_TX_CHECK_OUT_ITEM_ALREADY_USED: return "Double spend attempt for transaction output";
+    case DAP_LEDGER_TX_CHECK_PREV_TX_NOT_FOUND: return "No previous transaction found";
+    case DAP_LEDGER_TX_CHECK_PREV_OUT_ITEM_NOT_FOUND: return "Specified output number not found in previous transaction";
+    case DAP_LEDGER_TX_CHECK_PREV_OUT_ITEM_MISSTYPED: return "Previuos transaction output has unknown type, possible ledger corruption";
+    case DAP_LEDGER_TX_CHECK_PKEY_HASHES_DONT_MATCH: return "Trying to spend transaction output from wrongful wallet";
+    case DAP_LEDGER_TX_CHECK_PREV_OUT_ALREADY_USED_IN_CURRENT_TX: return "Double spend attempt within single transaction";
+    case DAP_LEDGER_TX_CHECK_NO_VERIFICATOR_SET: return "No verificator found for specified conditional ipnput";
+    case DAP_LEDGER_TX_CHECK_VERIFICATOR_CHECK_FAILURE: return "Verificator check return error";
+    case DAP_LEDGER_TX_CHECK_SUM_INS_NOT_EQUAL_SUM_OUTS: return "Sum of transaction outputs isn't equal to sum of its inputs";
+    case DAP_LEDGER_TX_CHECK_REWARD_ITEM_ALREADY_USED: return "Double spend attempt for reward";
+    case DAP_LEDGER_TX_CHECK_REWARD_ITEM_ILLEGAL: return "Wrongful reward item in transaction";
+    case DAP_LEDGER_TX_CHECK_NO_MAIN_TICKER: return "Can't calculate main ticker found for transaction";
+    case DAP_LEDGER_TX_CHECK_UNEXPECTED_TOKENIZED_OUT: return "Tokenized out is forbidden for single-channel transactions";
+    case DAP_LEDGER_TX_CHECK_NOT_ENOUGH_FEE: return "Not enough network fee for transaction processing";
+    case DAP_LEDGER_TX_CHECK_NOT_ENOUGH_TAX: return "Not enough sovereign tax provided with current transaction";
+    case DAP_LEDGER_TX_CHECK_FOR_REMOVING_CANT_FIND_TX: return "Can't find tx in ledger for removing.";
+    case DAP_LEDGER_TX_CHECK_MULTIPLE_OUTS_TO_OTHER_NET: return "The transaction was rejected because it contains multiple outputs to other networks.";
+    /* Emisssion check return codes */
+    case DAP_LEDGER_EMISSION_CHECK_VALUE_EXCEEDS_CURRENT_SUPPLY: return "Value of emission execeeds current token supply";
+    case DAP_LEDGER_EMISSION_CHECK_LEGACY_FORBIDDEN: return "Legacy type of emissions are present for old chains comliance only";
+    /* Token declaration/update return codes */
+    case DAP_LEDGER_TOKEN_ADD_CHECK_NOT_ENOUGH_UNIQUE_SIGNS: return "Not all token signs is unique";
+    case DAP_LEDGER_TOKEN_ADD_CHECK_LEGACY_FORBIDDEN: return "Legacy type of tokens are present for old chains comliance only";
+    case DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_SUPPLY: return "Specified supply must be greater than current one";
+    case DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR: return "Specified address has invalid format";
+    case DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH: return "Specified address can't be processed cause double (for adding) or absent (for removing)";
+    case DAP_LEDGER_TOKEN_ADD_CHECK_TSD_PKEY_MISMATCH: return "Specified public key or its hash can't be processed cause double (for adding) or absent (for removing)";
+    case DAP_LEDGER_TOKEN_ADD_CHECK_TSD_FORBIDDEN: return "Specified TSD section type is not allowed in datum token of specified type";
+    case DAP_LEDGER_TOKEN_ADD_CHECK_TSD_OTHER_TICKER_EXPECTED: return "Incorrect token ticker for delegated token";
+    default: return "Unknown error";
+    }
+}
+
+
+typedef int (*dap_ledger_verificator_callback_t)(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_tx_out_cond, dap_chain_datum_tx_t *a_tx_in, bool a_owner);
+typedef void (*dap_ledger_updater_callback_t)(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx_in, dap_hash_fast_t *a_tx_in_hash, dap_chain_tx_out_cond_t *a_prev_cond);
+typedef void (*dap_ledger_delete_callback_t)(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx_in, dap_chain_tx_out_cond_t *a_prev_cond);
+typedef void (* dap_ledger_tx_add_notify_t)(void *a_arg, dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, dap_chan_ledger_notify_opcodes_t a_opcode);
+typedef void (* dap_ledger_bridged_tx_notify_t)(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, void *a_arg, dap_chan_ledger_notify_opcodes_t a_opcode);
+typedef bool (*dap_ledger_cache_tx_check_callback_t)(dap_ledger_t *a_ledger, dap_hash_fast_t *a_tx_hash);
+typedef struct dap_chain_net dap_chain_net_t;
+typedef int (*dap_chain_ledger_voting_callback_t)(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, bool a_apply);
+typedef bool (*dap_chain_ledger_voting_delete_callback_t)(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx);
+typedef bool (*dap_ledger_tag_check_callback_t)(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_datum_tx_item_groups_t *a_items_grp, dap_chain_tx_tag_action_type_t *a_action);
+
+
+
 int dap_ledger_init();
 void dap_ledger_deinit();
 
diff --git a/modules/net/include/dap_chain_net.h b/modules/net/include/dap_chain_net.h
index 9d47cc67b1..2d15a72444 100644
--- a/modules/net/include/dap_chain_net.h
+++ b/modules/net/include/dap_chain_net.h
@@ -41,10 +41,6 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 #define DAP_CHAIN_NET_MEMPOOL_TTL 4 * 3600  // 4 hours
 #define DAP_CHAIN_NET_NODES_TTL 14 * 24 * 3600   // 2 weeks
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 typedef struct dap_chain_node_client dap_chain_node_client_t;
 typedef struct dap_ledger dap_ledger_t;
 typedef struct dap_chain_net_decree dap_chain_net_decree_t;
@@ -81,6 +77,38 @@ typedef struct dap_chain_net {
     uint8_t pvt[];
 } dap_chain_net_t;
 
+enum dap_chain_net_json_rpc_error_list{
+    DAP_CHAIN_NET_JSON_RPC_OK,
+    DAP_CHAIN_NET_JSON_RPC_INVALID_PARAMETER_HASH = DAP_JSON_RPC_ERR_CODE_METHOD_ERR_START,
+    DAP_CHAIN_NET_JSON_RPC_CAN_NOT_PARAMETER_NET_REQUIRE,
+    DAP_CHAIN_NET_JSON_RPC_WRONG_NET,
+    DAP_CHAIN_NET_JSON_RPC_MANY_ARGUMENT_FOR_COMMAND_NET_LIST,
+    DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETER_COMMAND_STATS,
+    DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETER_COMMAND_GO,
+    DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETER_ADDR_COMMAND_INFO,
+    DAP_CHAIN_NET_JSON_RPC_CANT_CALCULATE_HASH_FOR_ADDR,
+    DAP_CHAIN_NET_JSON_RPC_CAN_NOT_GET_CLUSTER,
+    DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETERS_COMMAND_LINK,
+    DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETERS_COMMAND_SYNC,
+    DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETERS_CA_ADD,
+    DAP_CHAIN_NET_JSON_RPC_CAN_NOT_FIND_CERT_CA_ADD,
+    DAP_CHAIN_NET_JSON_RPC_CAN_NOT_KEY_IN_CERT_CA_ADD,
+    DAP_CHAIN_NET_JSON_RPC_CAN_SERIALIZE_PUBLIC_KEY_CERT_CA_ADD,
+    DAP_CHAIN_NET_JSON_RPC_DATABASE_ACL_GROUP_NOT_DEFINED_FOR_THIS_NETWORK_CA_ADD,
+    DAP_CHAIN_NET_JSON_RPC_CAN_NOT_SAVE_PUBLIC_KEY_IN_DATABASE,
+    DAP_CHAIN_NET_JSON_RPC_DATABASE_ACL_GROUP_NOT_DEFINED_FOR_THIS_NETWORK_CA_LIST,
+    DAP_CHAIN_NET_JSON_RPC_UNKNOWN_HASH_CA_DEL,
+    DAP_CHAIN_NET_JSON_RPC_DATABASE_ACL_GROUP_NOT_DEFINED_FOR_THIS_NETWORK_CA_DEL,
+    DAP_CHAIN_NET_JSON_RPC_CAN_NOT_FIND_CERT_CA_DEL,
+    DAP_CHAIN_NET_JSON_RPC_INVALID_PARAMETER_COMMAND_CA,
+    DAP_CHAIN_NET_JSON_RPC_NO_POA_CERTS_FOUND_POA_CERTS,
+    DAP_CHAIN_NET_JSON_RPC_UNKNOWN_SUBCOMMANDS
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 DAP_STATIC_INLINE int dap_chain_net_id_parse(const char *a_id_str, dap_chain_net_id_t *a_id)
 {
     uint64_t l_id;
@@ -211,33 +239,6 @@ struct json_object *dap_chain_net_states_json_collect(dap_chain_net_t * l_net);
 struct json_object *dap_chain_net_list_json_collect();
 struct json_object *dap_chain_nets_info_json_collect();
 
-enum dap_chain_net_json_rpc_error_list{
-    DAP_CHAIN_NET_JSON_RPC_OK,
-    DAP_CHAIN_NET_JSON_RPC_INVALID_PARAMETER_HASH = DAP_JSON_RPC_ERR_CODE_METHOD_ERR_START,
-    DAP_CHAIN_NET_JSON_RPC_CAN_NOT_PARAMETER_NET_REQUIRE,
-    DAP_CHAIN_NET_JSON_RPC_WRONG_NET,
-    DAP_CHAIN_NET_JSON_RPC_MANY_ARGUMENT_FOR_COMMAND_NET_LIST,
-    DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETER_COMMAND_STATS,
-    DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETER_COMMAND_GO,
-    DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETER_ADDR_COMMAND_INFO,
-    DAP_CHAIN_NET_JSON_RPC_CANT_CALCULATE_HASH_FOR_ADDR,
-    DAP_CHAIN_NET_JSON_RPC_CAN_NOT_GET_CLUSTER,
-    DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETERS_COMMAND_LINK,
-    DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETERS_COMMAND_SYNC,
-    DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETERS_CA_ADD,
-    DAP_CHAIN_NET_JSON_RPC_CAN_NOT_FIND_CERT_CA_ADD,
-    DAP_CHAIN_NET_JSON_RPC_CAN_NOT_KEY_IN_CERT_CA_ADD,
-    DAP_CHAIN_NET_JSON_RPC_CAN_SERIALIZE_PUBLIC_KEY_CERT_CA_ADD,
-    DAP_CHAIN_NET_JSON_RPC_DATABASE_ACL_GROUP_NOT_DEFINED_FOR_THIS_NETWORK_CA_ADD,
-    DAP_CHAIN_NET_JSON_RPC_CAN_NOT_SAVE_PUBLIC_KEY_IN_DATABASE,
-    DAP_CHAIN_NET_JSON_RPC_DATABASE_ACL_GROUP_NOT_DEFINED_FOR_THIS_NETWORK_CA_LIST,
-    DAP_CHAIN_NET_JSON_RPC_UNKNOWN_HASH_CA_DEL,
-    DAP_CHAIN_NET_JSON_RPC_DATABASE_ACL_GROUP_NOT_DEFINED_FOR_THIS_NETWORK_CA_DEL,
-    DAP_CHAIN_NET_JSON_RPC_CAN_NOT_FIND_CERT_CA_DEL,
-    DAP_CHAIN_NET_JSON_RPC_INVALID_PARAMETER_COMMAND_CA,
-    DAP_CHAIN_NET_JSON_RPC_NO_POA_CERTS_FOUND_POA_CERTS,
-    DAP_CHAIN_NET_JSON_RPC_UNKNOWN_SUBCOMMANDS
-};
 dap_chain_net_decree_t *dap_chain_net_get_net_decree(dap_chain_net_t *a_net);
 void dap_chain_net_set_net_decree(dap_chain_net_t *a_net, dap_chain_net_decree_t *a_decree);
 decree_table_t **dap_chain_net_get_decrees(dap_chain_net_t *a_net);
diff --git a/modules/net/include/dap_chain_net_balancer.h b/modules/net/include/dap_chain_net_balancer.h
index e005eea71d..3390633718 100644
--- a/modules/net/include/dap_chain_net_balancer.h
+++ b/modules/net/include/dap_chain_net_balancer.h
@@ -30,9 +30,6 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 #define DAP_BALANCER_PROTOCOL_VERSION 2
 #define DAP_BALANCER_MAX_REPLY_SIZE 2048
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 
 typedef struct dap_balancer_request_info dap_balancer_request_info_t;
 
@@ -56,6 +53,10 @@ typedef struct dap_balancer_link_request {
     dap_balancer_type_t type;
 } dap_balancer_link_request_t;
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 DAP_STATIC_INLINE const char *dap_chain_net_balancer_type_to_str(dap_balancer_type_t a_type)
 {
     switch (a_type) {
diff --git a/modules/net/include/dap_chain_net_decree.h b/modules/net/include/dap_chain_net_decree.h
index dcb2bceee1..ed4658b184 100644
--- a/modules/net/include/dap_chain_net_decree.h
+++ b/modules/net/include/dap_chain_net_decree.h
@@ -25,9 +25,6 @@
 #include "dap_list.h"
 #include "dap_chain_net.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 
 typedef struct dap_chain_net_decree {
     dap_list_t *pkeys;
@@ -35,6 +32,10 @@ typedef struct dap_chain_net_decree {
     uint16_t min_num_of_owners;
 }   dap_chain_net_decree_t;
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 int dap_chain_net_decree_init(dap_chain_net_t *a_net);
 int dap_chain_net_decree_deinit(dap_chain_net_t *a_net);
 
diff --git a/modules/net/include/dap_chain_net_node_list.h b/modules/net/include/dap_chain_net_node_list.h
index f61624c9b4..d438ee2c60 100644
--- a/modules/net/include/dap_chain_net_node_list.h
+++ b/modules/net/include/dap_chain_net_node_list.h
@@ -29,9 +29,6 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 
 #define DAP_NODE_LIST_URI_HASH "node_list_hash"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 
 struct node_link_request {
     dap_chain_node_info_t *link_info;
@@ -46,6 +43,10 @@ struct node_link_request {
     int response;
 };
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /**
 * @brief dap_chain_net_node_list_get_gdb_group
 * @param a_net
diff --git a/modules/net/include/dap_chain_net_tx.h b/modules/net/include/dap_chain_net_tx.h
index b729a75025..0447fcb165 100644
--- a/modules/net/include/dap_chain_net_tx.h
+++ b/modules/net/include/dap_chain_net_tx.h
@@ -27,10 +27,6 @@
 #include "dap_chain_datum_tx_items.h"
 #include "dap_json_rpc_errors.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 typedef enum s_com_tx_create_json_err {
     DAP_CHAIN_NET_TX_CREATE_JSON_OK = 0,
     DAP_CHAIN_NET_TX_CREATE_JSON_REQUIRE_PARAMETER_JSON = DAP_JSON_RPC_ERR_CODE_METHOD_ERR_START,
@@ -82,6 +78,11 @@ typedef struct dap_chain_datum_tx_cond_list_item {
     dap_hash_fast_t hash;
     dap_chain_datum_tx_t *tx;
 } dap_chain_datum_tx_cond_list_item_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 // TX functions
 dap_chain_datum_tx_t * dap_chain_net_get_tx_by_hash(dap_chain_net_t * a_net, dap_chain_hash_fast_t * a_tx_hash,
                                                      dap_chain_net_tx_search_type_t a_search_type);
diff --git a/modules/net/include/dap_chain_node.h b/modules/net/include/dap_chain_node.h
index a6d46f8c51..19da1cc694 100644
--- a/modules/net/include/dap_chain_node.h
+++ b/modules/net/include/dap_chain_node.h
@@ -28,9 +28,6 @@
 #include "dap_chain.h"
 #include "dap_client.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 
 typedef struct dap_chain_net dap_chain_net_t;
 
@@ -72,6 +69,9 @@ typedef dap_stream_node_addr_t dap_chain_node_addr_t;
 #define dap_chain_node_addr_from_str dap_stream_node_addr_from_str
 #define dap_chain_node_addr_is_blank dap_stream_node_addr_is_blank
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 /**
  * Calculate size of struct dap_chain_node_info_t
  */
diff --git a/modules/net/include/dap_chain_node_cli_cmd.h b/modules/net/include/dap_chain_node_cli_cmd.h
index 3b8871adf0..c084731bb3 100644
--- a/modules/net/include/dap_chain_node_cli_cmd.h
+++ b/modules/net/include/dap_chain_node_cli_cmd.h
@@ -31,18 +31,37 @@
 #include "dap_chain_node_cli.h"
 #include "json.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+typedef enum s_com_tx_history_err{
+    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_OK = 0,
+    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_MEMORY_ERR,
+    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_PARAM_ERR,
+    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_HASH_REC_ERR,
+    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_NET_PARAM_ERR,
+    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_INCOMPATIBLE_PARAMS_ERR,
+    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_WALLET_ADDR_ERR,
+    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_ID_NET_ADDR_DIF_ERR,
+    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_ADDR_WALLET_DIF_ERR,
+    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_WALLET_ERR,
+    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_NET_ERR,
+    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_CHAIN_PARAM_ERR,
+    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_DAP_DB_HISTORY_TX_ERR,
+    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_DAP_DB_HISTORY_ADDR_ERR,
+    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_DAP_DB_HISTORY_ALL_ERR,
 
-int dap_chain_node_cli_cmd_values_parse_net_chain_for_json(json_object* a_json_arr_reply, int *a_arg_index, int a_argc,
-                                                           char **a_argv,
-                                                           dap_chain_t **a_chain, dap_chain_net_t **a_net,
-                                                           dap_chain_type_t a_default_chain_type);
+    /* add custom codes here */
 
+    //DAP_CHAIN_NODE_CLI_COM_TX_UNKNOWN /* MAX */
+} s_com_tx_history_err_t;
 
-int dap_chain_node_cli_cmd_values_parse_net_chain(int *a_arg_index, int a_argc, char **a_argv, void **a_str_reply,
-                             dap_chain_t ** a_chain, dap_chain_net_t ** a_net, dap_chain_type_t a_default_chain_type);
+typedef enum cmd_find_list_err {
+    DAP_CHAIN_NODE_CLI_FIND_OK = 0,
+    DAP_CHAIN_NODE_CLI_FIND_ERR_PARSE_HASH = DAP_JSON_RPC_ERR_CODE_METHOD_ERR_START,
+    DAP_CHAIN_NODE_CLI_FUND_ERR_UNKNOWN_SUBCMD,
+    DAP_CHAIN_NODE_CLI_FIND_ERR_HASH_IS_NOT_SPECIFIED,
+    DAP_CHAIN_NODE_CLI_FIND_ERR_UNKNOWN_SUBTYPE_DECREE,
+    DAP_CHIAN_NODE_CLI_FIND_ERR_SUBTYPE_DECREE_IS_NOT_SPECIFIED,
+    DAP_CHAIN_NODE_CLI_FIND_ERR_UNKNOWN_PARAMETR_WHERE,
+}cmd_find_list_err_t;
 
 typedef enum s_com_parse_net_chain_err{
     DAP_CHAIN_NODE_CLI_COM_PARSE_NET_NET_STR_ERR = 100,
@@ -54,12 +73,6 @@ typedef enum s_com_parse_net_chain_err{
 
     DAP_CHAIN_NODE_CLI_COM_PARSE_NET_UNKNOWN /* MAX */
 } s_com_parse_net_chain_err_t;
-
-
-/**
- * global_db command
- */
-int com_global_db(int a_argc,  char **a_argv, void **a_str_reply);
 typedef enum s_com_global_db_json_err {
     DAP_CHAIN_NODE_CLI_COM_GLOBAL_DB_JSON_OK = 0,
 
@@ -92,62 +105,6 @@ typedef enum s_com_global_db_json_err {
     DAP_CHAIN_NODE_CLI_COM_GLOBAL_DB_JSON_CAN_NOT_ADD_TRANSACTION_TO_MEMPOOL
 }s_com_global_db_json_err_t;
 
-/**
- * Node command
- */
-int com_node(int a_argc,  char **a_argv, void **a_str_reply);
-
-#ifndef DAP_OS_ANDROID
-/**
- * Traceroute command
- *
- * return 0 OK, -1 Err
- */
-int com_traceroute(int a_argc,  char** argv, void **a_str_reply);
-
-/**
- * Tracepath command
- *
- * return 0 OK, -1 Err
- */
-int com_tracepath(int a_argc,  char** argv, void **a_str_reply);
-
-/**
- * Ping command
- *
- * return 0 OK, -1 Err
- */
-int com_ping(int a_argc,  char** argv, void **a_str_reply);
-#endif
-/**
- * Help command
- */
-int com_help(int a_argc,  char **a_argv, void **a_str_reply);
-
-int com_version(int a_argc, char **a_argv, void **a_str_reply);
-
-/**
- * Token declaration
- */
-int com_token_decl(int a_argc,  char **a_argv, void **a_str_reply);
-
-int com_token_update(int a_argc, char **a_argv, void **a_str_reply);
-
-/**
- * Token declaration add sign
- */
-int com_token_decl_sign ( int a_argc,  char **a_argv, void **a_str_reply);
-
-/*
- * Token update sign
- */
-int com_token_update_sign(int argc, char ** argv, void **a_str_reply);
-
-/**
- * Token emission
- */
-int com_token_emit (int a_argc,  char **a_argv, void **a_str_reply);
-
 typedef enum s_com_tx_wallet_err{
     DAP_CHAIN_NODE_CLI_COM_TX_WALLET_MEMORY_ERR,
     DAP_CHAIN_NODE_CLI_COM_TX_WALLET_PARAM_ERR,
@@ -176,13 +133,6 @@ typedef enum s_com_tx_wallet_err{
     DAP_CHAIN_NODE_CLI_COM_TX_UNKNOWN /* MAX */
 } s_com_tx_wallet_err_t;
 
-/**
- * com_tx_create command
- *
- * Wallet info
- */
-int com_tx_wallet(int a_argc, char **a_argv, void **a_str_reply);
-
 /**
  * com_tx_create command
  *
@@ -214,9 +164,6 @@ typedef enum s_com_tx_create_err{
     DAP_CHAIN_NODE_CLI_COM_TX_CREATE_CAN_NOT_CREATE_TRANSACTION,
     DAP_CHAIN_NODE_CLI_COM_TX_CREATE_EQ_SOURCE_DESTINATION_ADDRESS
 }s_com_tx_create_err_t;
-int com_tx_create(int a_argc, char **a_argv, void **a_str_reply);
-
-int com_tx_create_json(int a_argc, char **a_argv, void **reply);
 typedef enum s_com_tx_cond_create{
     DAP_CHAIN_NODE_CLI_COM_TX_COND_CREATE_OK = 0,
     DAP_CHAIN_NODE_CLI_COM_TX_COND_CREATE_INVALID_PARAMETER_HEX = DAP_JSON_RPC_ERR_CODE_METHOD_ERR_START,
@@ -238,7 +185,6 @@ typedef enum s_com_tx_cond_create{
     DAP_CHAIN_NODE_CLI_COM_TX_COND_CREATE_CERT_DOES_NOT_CONATIN_VALID_PUBLIC_KEY,
     DAP_CHAIN_NODE_CLI_COM_TX_COND_CREATE_CAN_NOT_CONDITIONAL_TX_CREATE
 }s_com_tx_cond_create_t;
-int com_tx_cond_create(int a_argc, char **a_argv, void **reply);
 typedef enum s_com_tx_cond_remove{
     DAP_CHAIN_NODE_CLI_COM_TX_COND_REMOVE_OK = 0,
     DAP_CHAIN_NODE_CLI_COM_TX_COND_REMOVE_INVALID_PARAMETER_HEX = DAP_JSON_RPC_ERR_CODE_METHOD_ERR_START,
@@ -264,7 +210,6 @@ typedef enum s_com_tx_cond_remove{
     DAP_CHAIN_NODE_CLI_COM_TX_COND_REMOVE_CAN_FIND_DEFAULT_CHAIN_WITH_TX_FOR_NET,
     DAP_CHAIN_NODE_CLI_COM_TX_COND_REMOVE_OTHER_ERROR
 }s_com_tx_cond_remove_t;
-int com_tx_cond_remove(int a_argc, char **a_argv, void **reply);
 typedef enum s_com_tx_cond_unspent_find{
     DAP_CHAIN_NODE_CLI_COM_TX_COND_UNSPEND_FIND_OK = 0,
     DAP_CHAIN_NODE_CLI_COM_TX_COND_UNSPEND_FIND_INVALID_PARAMETER_HEX = DAP_JSON_RPC_ERR_CODE_METHOD_ERR_START,
@@ -277,8 +222,6 @@ typedef enum s_com_tx_cond_unspent_find{
     DAP_CHAIN_NODE_CLI_COM_TX_COND_UNSPEND_FIND_CAN_NOT_FIND_NATIVE_TICKER_IN_NET,
     DAP_CHAIN_NODE_CLI_COM_TX_COND_UNSPEND_FIND_CAN_NOT_FIND_LEDGER_FOR_NET,
 }s_com_tx_cond_unspent_find_t;
-int com_tx_cond_unspent_find(int a_argc, char **a_argv, void **reply);
-
 typedef enum s_com_tx_verify{
     DAP_CHAIN_NODE_CLI_COM_TX_VERIFY_OK = 0,
     DAP_CHAIN_NODE_CLI_COM_TX_VERIFY_REQUIRE_PARAMETER_TX = DAP_JSON_RPC_ERR_CODE_METHOD_ERR_START,
@@ -288,6 +231,106 @@ typedef enum s_com_tx_verify{
     DAP_CHAIN_NODE_CLI_COM_TX_VERIFY_HASH_IS_NOT_TX_HASH,
     DAP_CHAIN_NODE_CLI_COM_TX_VERIFY_TX_NOT_VERIFY
 }s_com_tx_verify_t;
+typedef enum cmd_mempool_list_err{
+    DAP_CHAIN_NODE_CLI_COM_MEMPOOL_LIST_OK = 0,
+    DAP_CHAIN_NODE_CLI_COM_MEMPOOL_LIST_CAN_NOT_READ_EMISSION,
+    DAP_CHAIN_NODE_CLI_COM_MEMPOOL_LIST_CHAIN_NOT_FOUND,
+    DAP_CHAIN_NODE_CLI_COM_MEMPOOL_LIST_CAN_NOT_GET_MEMPOOL_GROUP,
+    /* add custom codes here */
+
+    DAP_CHAIN_NODE_CLI_COM_MEMPOOL_LIST_UNKNOWN /* MAX */
+} cmd_mempool_list_err_t;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int dap_chain_node_cli_cmd_values_parse_net_chain_for_json(json_object* a_json_arr_reply, int *a_arg_index, int a_argc,
+                                                           char **a_argv,
+                                                           dap_chain_t **a_chain, dap_chain_net_t **a_net,
+                                                           dap_chain_type_t a_default_chain_type);
+
+
+int dap_chain_node_cli_cmd_values_parse_net_chain(int *a_arg_index, int a_argc, char **a_argv, void **a_str_reply,
+                             dap_chain_t ** a_chain, dap_chain_net_t ** a_net, dap_chain_type_t a_default_chain_type);
+
+
+
+/**
+ * global_db command
+ */
+int com_global_db(int a_argc,  char **a_argv, void **a_str_reply);
+/**
+ * Node command
+ */
+int com_node(int a_argc,  char **a_argv, void **a_str_reply);
+
+#ifndef DAP_OS_ANDROID
+/**
+ * Traceroute command
+ *
+ * return 0 OK, -1 Err
+ */
+int com_traceroute(int a_argc,  char** argv, void **a_str_reply);
+
+/**
+ * Tracepath command
+ *
+ * return 0 OK, -1 Err
+ */
+int com_tracepath(int a_argc,  char** argv, void **a_str_reply);
+
+/**
+ * Ping command
+ *
+ * return 0 OK, -1 Err
+ */
+int com_ping(int a_argc,  char** argv, void **a_str_reply);
+#endif
+/**
+ * Help command
+ */
+int com_help(int a_argc,  char **a_argv, void **a_str_reply);
+
+int com_version(int a_argc, char **a_argv, void **a_str_reply);
+
+/**
+ * Token declaration
+ */
+int com_token_decl(int a_argc,  char **a_argv, void **a_str_reply);
+
+int com_token_update(int a_argc, char **a_argv, void **a_str_reply);
+
+/**
+ * Token declaration add sign
+ */
+int com_token_decl_sign ( int a_argc,  char **a_argv, void **a_str_reply);
+
+/*
+ * Token update sign
+ */
+int com_token_update_sign(int argc, char ** argv, void **a_str_reply);
+
+/**
+ * Token emission
+ */
+int com_token_emit (int a_argc,  char **a_argv, void **a_str_reply);
+
+/**
+ * com_tx_create command
+ *
+ * Wallet info
+ */
+int com_tx_wallet(int a_argc, char **a_argv, void **a_str_reply);
+
+int com_tx_create(int a_argc, char **a_argv, void **a_str_reply);
+
+int com_tx_create_json(int a_argc, char **a_argv, void **reply);
+int com_tx_cond_create(int a_argc, char **a_argv, void **reply);
+int com_tx_cond_remove(int a_argc, char **a_argv, void **reply);
+int com_tx_cond_unspent_find(int a_argc, char **a_argv, void **reply);
+
 /**
  * tx_verify command
  *
@@ -296,27 +339,7 @@ typedef enum s_com_tx_verify{
 
 int com_tx_verify(int a_argc, char ** a_argv, void **a_str_reply);
 
-typedef enum s_com_tx_history_err{
-    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_OK = 0,
-    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_MEMORY_ERR,
-    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_PARAM_ERR,
-    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_HASH_REC_ERR,
-    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_NET_PARAM_ERR,
-    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_INCOMPATIBLE_PARAMS_ERR,
-    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_WALLET_ADDR_ERR,
-    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_ID_NET_ADDR_DIF_ERR,
-    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_ADDR_WALLET_DIF_ERR,
-    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_WALLET_ERR,
-    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_NET_ERR,
-    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_CHAIN_PARAM_ERR,
-    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_DAP_DB_HISTORY_TX_ERR,
-    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_DAP_DB_HISTORY_ADDR_ERR,
-    DAP_CHAIN_NODE_CLI_COM_TX_HISTORY_DAP_DB_HISTORY_ALL_ERR,
-
-    /* add custom codes here */
 
-    //DAP_CHAIN_NODE_CLI_COM_TX_UNKNOWN /* MAX */
-} s_com_tx_history_err_t;
 
 char *dap_chain_node_cli_com_tx_history_err(int a_code);
 
@@ -339,15 +362,6 @@ int com_exit(int a_argc, char **a_argv, void **a_str_reply);
 int cmd_gdb_import(int a_argc, char **a_argv, void **a_str_reply);
 int cmd_gdb_export(int a_argc, char **a_argv, void **a_str_reply);
 
-typedef enum cmd_mempool_list_err{
-    DAP_CHAIN_NODE_CLI_COM_MEMPOOL_LIST_OK = 0,
-    DAP_CHAIN_NODE_CLI_COM_MEMPOOL_LIST_CAN_NOT_READ_EMISSION,
-    DAP_CHAIN_NODE_CLI_COM_MEMPOOL_LIST_CHAIN_NOT_FOUND,
-    DAP_CHAIN_NODE_CLI_COM_MEMPOOL_LIST_CAN_NOT_GET_MEMPOOL_GROUP,
-    /* add custom codes here */
-
-    DAP_CHAIN_NODE_CLI_COM_MEMPOOL_LIST_UNKNOWN /* MAX */
-} cmd_mempool_list_err_t;
 int com_mempool(int a_argc, char **a_argv, void **a_str_reply);
 /**
  * Place public CA into the mempool
@@ -358,15 +372,6 @@ int com_signer(int a_argc, char **a_argv, void **a_str_reply);
 //remove func
 int cmd_remove(int a_argc, char **a_argv, void **a_str_reply);
 
-typedef enum cmd_find_list_err {
-    DAP_CHAIN_NODE_CLI_FIND_OK = 0,
-    DAP_CHAIN_NODE_CLI_FIND_ERR_PARSE_HASH = DAP_JSON_RPC_ERR_CODE_METHOD_ERR_START,
-    DAP_CHAIN_NODE_CLI_FUND_ERR_UNKNOWN_SUBCMD,
-    DAP_CHAIN_NODE_CLI_FIND_ERR_HASH_IS_NOT_SPECIFIED,
-    DAP_CHAIN_NODE_CLI_FIND_ERR_UNKNOWN_SUBTYPE_DECREE,
-    DAP_CHIAN_NODE_CLI_FIND_ERR_SUBTYPE_DECREE_IS_NOT_SPECIFIED,
-    DAP_CHAIN_NODE_CLI_FIND_ERR_UNKNOWN_PARAMETR_WHERE,
-}cmd_find_list_err_t;
 /**
  * Handler coomand find
  * @param a_argc
diff --git a/modules/net/include/dap_chain_node_cli_cmd_tx.h b/modules/net/include/dap_chain_node_cli_cmd_tx.h
index def00d9838..cd5e2cc7e2 100644
--- a/modules/net/include/dap_chain_node_cli_cmd_tx.h
+++ b/modules/net/include/dap_chain_node_cli_cmd_tx.h
@@ -29,15 +29,45 @@
 #include "dap_chain_common.h"
 #include "dap_chain_net.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+typedef enum s_com_ledger_err{
+    DAP_CHAIN_NODE_CLI_COM_LEDGER_OK = 0,
+    DAP_CHAIN_NODE_CLI_COM_LEDGER_PARAM_ERR,
+    DAP_CHAIN_NODE_CLI_COM_LEDGER_HASH_ERR,
+    DAP_CHAIN_NODE_CLI_COM_LEDGER_NET_PARAM_ERR,
+    DAP_CHAIN_NODE_CLI_COM_LEDGER_INCOMPATIBLE_PARAMS_ERR,
+    DAP_CHAIN_NODE_CLI_COM_LEDGER_WALLET_ADDR_ERR,
+    DAP_CHAIN_NODE_CLI_COM_LEDGER_TRESHOLD_ERR,
+    DAP_CHAIN_NODE_CLI_COM_LEDGER_LACK_ERR,
+    DAP_CHAIN_NODE_CLI_COM_LEDGER_NET_FIND_ERR,
+    DAP_CHAIN_NODE_CLI_COM_LEDGER_ID_NET_ADDR_DIF_ERR,
+    DAP_CHAIN_NODE_CLI_COM_LEDGER_HASH_GET_ERR,
+    DAP_CHAIN_NODE_CLI_COM_LEDGER_TX_HASH_ERR,
+
+    /* add custom codes here */
+
+    DAP_CHAIN_NODE_CLI_COM_LEDGER_UNKNOWN /* MAX */
+} s_com_ledger_err_t;
+
+typedef enum s_com_token_err{
+    DAP_CHAIN_NODE_CLI_COM_TOKEN_OK = 0,
+    DAP_CHAIN_NODE_CLI_COM_TOKEN_PARAM_ERR,
+    DAP_CHAIN_NODE_CLI_COM_TOKEN_HASH_ERR,
+    DAP_CHAIN_NODE_CLI_COM_TOKEN_FOUND_ERR,
+
+    /* add custom codes here */
+
+    DAP_CHAIN_NODE_CLI_COM_TOKEN_UNKNOWN /* MAX */
+} s_com_token_err_t;
 
 typedef struct dap_chain_tx_hash_processed_ht{
     dap_chain_hash_fast_t hash;
     UT_hash_handle hh;
 }dap_chain_tx_hash_processed_ht_t;
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 void s_dap_chain_tx_hash_processed_ht_free(dap_chain_tx_hash_processed_ht_t **l_hash_processed);
 
 /**
@@ -79,40 +109,13 @@ bool s_dap_chain_datum_tx_out_data(json_object* a_json_arr_reply,
  */
 int com_ledger(int a_argc, char ** a_argv, void **a_str_reply);
 
-typedef enum s_com_ledger_err{
-    DAP_CHAIN_NODE_CLI_COM_LEDGER_OK = 0,
-    DAP_CHAIN_NODE_CLI_COM_LEDGER_PARAM_ERR,
-    DAP_CHAIN_NODE_CLI_COM_LEDGER_HASH_ERR,
-    DAP_CHAIN_NODE_CLI_COM_LEDGER_NET_PARAM_ERR,
-    DAP_CHAIN_NODE_CLI_COM_LEDGER_INCOMPATIBLE_PARAMS_ERR,
-    DAP_CHAIN_NODE_CLI_COM_LEDGER_WALLET_ADDR_ERR,
-    DAP_CHAIN_NODE_CLI_COM_LEDGER_TRESHOLD_ERR,
-    DAP_CHAIN_NODE_CLI_COM_LEDGER_LACK_ERR,
-    DAP_CHAIN_NODE_CLI_COM_LEDGER_NET_FIND_ERR,
-    DAP_CHAIN_NODE_CLI_COM_LEDGER_ID_NET_ADDR_DIF_ERR,
-    DAP_CHAIN_NODE_CLI_COM_LEDGER_HASH_GET_ERR,
-    DAP_CHAIN_NODE_CLI_COM_LEDGER_TX_HASH_ERR,
-
-    /* add custom codes here */
 
-    DAP_CHAIN_NODE_CLI_COM_LEDGER_UNKNOWN /* MAX */
-} s_com_ledger_err_t;
 /**
  * token command
  *
  */
 int com_token(int a_argc, char ** a_argv, void **a_str_reply);
 
-typedef enum s_com_token_err{
-    DAP_CHAIN_NODE_CLI_COM_TOKEN_OK = 0,
-    DAP_CHAIN_NODE_CLI_COM_TOKEN_PARAM_ERR,
-    DAP_CHAIN_NODE_CLI_COM_TOKEN_HASH_ERR,
-    DAP_CHAIN_NODE_CLI_COM_TOKEN_FOUND_ERR,
-
-    /* add custom codes here */
-
-    DAP_CHAIN_NODE_CLI_COM_TOKEN_UNKNOWN /* MAX */
-} s_com_token_err_t;
 /**
  * decree command
  *
diff --git a/modules/net/include/dap_chain_node_client.h b/modules/net/include/dap_chain_node_client.h
index b696f030bb..54e05ac384 100644
--- a/modules/net/include/dap_chain_node_client.h
+++ b/modules/net/include/dap_chain_node_client.h
@@ -30,10 +30,6 @@
 #include "dap_chain_node.h"
 #include "dap_stream_ch_pkt.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 // connection states
 typedef enum dap_chain_node_client_state {
     NODE_CLIENT_STATE_ERROR = -1,
@@ -110,6 +106,10 @@ typedef struct dap_chain_node_client {
 
 #define DAP_CHAIN_NODE_CLIENT(a) (a ? (dap_chain_node_client_t *) (a)->_inheritor : NULL)
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 int dap_chain_node_client_init();
 
 void dap_chain_node_client_deinit(void);
diff --git a/modules/net/include/dap_chain_node_dns_client.h b/modules/net/include/dap_chain_node_dns_client.h
index 0ce425c7a7..f2efb561a6 100644
--- a/modules/net/include/dap_chain_node_dns_client.h
+++ b/modules/net/include/dap_chain_node_dns_client.h
@@ -33,14 +33,14 @@
 #define DNS_LISTEN_PORT 53      // UDP
 #define DNS_LISTEN_PORT_STR "53"      // UDP
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 typedef struct _dap_dns_buf_t {
     char *data;
     uint32_t size;
 } dap_dns_buf_t;
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 // node info request callbacks
 typedef void (*dap_dns_client_node_info_request_success_callback_t) (dap_worker_t *a_worker, dap_chain_net_links_t *a_result, void *a_arg);
 typedef void (*dap_dns_client_node_info_request_error_callback_t) (dap_worker_t *a_worker, void *a_arg, int a_errno);
diff --git a/modules/net/include/dap_chain_node_dns_server.h b/modules/net/include/dap_chain_node_dns_server.h
index 56f79e1b26..d936863995 100644
--- a/modules/net/include/dap_chain_node_dns_server.h
+++ b/modules/net/include/dap_chain_node_dns_server.h
@@ -38,10 +38,6 @@
 #define DNS_MAX_HOSTNAME_LEN 255
 #define DNS_MAX_DOMAIN_NAME_LEN 63
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 typedef enum _dap_dns_query_type_t {
     DNS_QUERY_TYPE_STANDARD,
     DNS_QUERY_TYPE_INVERSE,
@@ -119,7 +115,9 @@ typedef struct _dap_dns_server_t {
     dap_dns_zone_hash_t *hash_table;
 } dap_dns_server_t;
 
-
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 void dap_dns_server_start(const char* a_cfg_section);
 void dap_dns_server_stop();
diff --git a/modules/wallet/include/dap_chain_coin.h b/modules/wallet/include/dap_chain_coin.h
index 5395e039a5..766d093120 100644
--- a/modules/wallet/include/dap_chain_coin.h
+++ b/modules/wallet/include/dap_chain_coin.h
@@ -23,11 +23,3 @@
 */
 #pragma once
 
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef __cplusplus
-}
-#endif
\ No newline at end of file
diff --git a/modules/wallet/include/dap_chain_wallet.h b/modules/wallet/include/dap_chain_wallet.h
index ecea35b5f8..bb156cacc9 100644
--- a/modules/wallet/include/dap_chain_wallet.h
+++ b/modules/wallet/include/dap_chain_wallet.h
@@ -38,9 +38,6 @@
 #define DAP_WALLET$M_FL_PROTECTED        (1 << 0)                           /* Wallet is password protected */
 #define DAP_WALLET$M_FL_ACTIVE           (1 << 1)                           /* Has been activated (has been open with password) */
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 
 typedef struct dap_chain_wallet{
     char        name[ DAP_WALLET$SZ_NAME + 1 ];                             /* Human readable name of BMF Wallet */
@@ -50,6 +47,9 @@ typedef struct dap_chain_wallet{
 } dap_chain_wallet_t;
 
 typedef void (*dap_chain_wallet_opened_callback_t)(dap_chain_wallet_t *a_wallet, void *a_arg);
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 int dap_chain_wallet_init();
 void dap_chain_wallet_deinit(void);
@@ -102,5 +102,5 @@ int dap_chain_wallet_add_wallet_created_notify(dap_chain_wallet_opened_callback_
 dap_list_t* dap_chain_wallet_get_local_addr();
 
 #ifdef __cplusplus
-extern "C" {
+}
 #endif
\ No newline at end of file
diff --git a/modules/wallet/include/dap_chain_wallet_cache.h b/modules/wallet/include/dap_chain_wallet_cache.h
index d277fca4cd..197dcc6565 100644
--- a/modules/wallet/include/dap_chain_wallet_cache.h
+++ b/modules/wallet/include/dap_chain_wallet_cache.h
@@ -27,9 +27,6 @@
 #include "dap_chain_common.h"
 #include "dap_chain_ledger.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 
 typedef enum dap_chain_wallet_getting_type {
     DAP_CHAIN_WALLET_CACHE_GET_FIRST = 0,
@@ -49,6 +46,10 @@ typedef struct dap_chain_wallet_cache_iter {
     void *cur_addr_cache;
 } dap_chain_wallet_cache_iter_t;
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 int dap_chain_wallet_cache_init();
 int dap_chain_wallet_cache_deinit();
 
diff --git a/modules/wallet/include/dap_chain_wallet_internal.h b/modules/wallet/include/dap_chain_wallet_internal.h
index 40de3c46b6..f782ff40b9 100644
--- a/modules/wallet/include/dap_chain_wallet_internal.h
+++ b/modules/wallet/include/dap_chain_wallet_internal.h
@@ -31,9 +31,6 @@
 
 #define DAP_CHAIN_WALLETS_FILE_SIGNATURE (uint64_t)0x1a167bef15feea18
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 
 enum    {
     DAP_WALLET$K_TYPE_PLAIN = 0,                                            /* 0x00 - uncompressed and unencrypted */
@@ -99,7 +96,3 @@ typedef struct dap_chain_wallet_internal
 #define DAP_CHAIN_WALLET_INTERNAL(a) (a ? (dap_chain_wallet_internal_t *) a->_internal : NULL)
 #define DAP_CHAIN_WALLET_INTERNAL_LOCAL(a) dap_chain_wallet_internal_t * l_wallet_internal = DAP_CHAIN_WALLET_INTERNAL(a)
 #define DAP_CHAIN_WALLET_INTERNAL_LOCAL_NEW(a) dap_chain_wallet_internal_t * l_wallet_internal = DAP_NEW_Z(dap_chain_wallet_internal_t); a->_internal = l_wallet_internal
-
-#ifdef __cplusplus
-}
-#endif
\ No newline at end of file
-- 
GitLab


From 79808f84a8e7f41985fcebb48a05fb481d807f32 Mon Sep 17 00:00:00 2001
From: "daniil.frolov" <daniil.frolov@demlabs.net>
Date: Mon, 20 Jan 2025 17:17:09 +0300
Subject: [PATCH 13/18] [+] Add net checking in wallet outputs command handler

---
 modules/net/dap_chain_node_cli_cmd.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index 45bd7fcf2e..c82c41f381 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -1731,6 +1731,13 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
             break;
         }
         case CMD_WALLET_OUTPUTS: {
+            if(!l_net) {
+                dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NET_PARAM_ERR,
+                                        "Subcommand info requires parameter '-net'");
+                json_object_put(json_arr_out);
+                return DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NET_PARAM_ERR;
+            }
+
             if ((l_wallet_name && l_addr_str) || (!l_wallet_name && !l_addr_str)) {
                 dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NAME_ERR,
                 "You should use either the -w or -addr option for the wallet info command.");
@@ -1738,12 +1745,6 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
                 return DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NAME_ERR;
             }
             if(l_wallet_name) {
-                if(!l_net) {
-                    dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NET_PARAM_ERR,
-                                           "Subcommand info requires parameter '-net'");
-                    json_object_put(json_arr_out);
-                    return DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NET_PARAM_ERR;
-                }
                 l_wallet = dap_chain_wallet_open(l_wallet_name, c_wallets_path, NULL);
                 if (!l_wallet){
                     dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NET_PARAM_ERR,
-- 
GitLab


From 2172efa3509d75076d669738717cbb18d31b8931 Mon Sep 17 00:00:00 2001
From: "Constantin P." <papizh.konstantin@demlabs.net>
Date: Tue, 21 Jan 2025 14:36:14 +0700
Subject: [PATCH 14/18] ...

---
 cellframe-sdk.pro              | 4 ++--
 dap-sdk                        | 2 +-
 modules/net/srv/CMakeLists.txt | 9 +++++++++
 3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/cellframe-sdk.pro b/cellframe-sdk.pro
index 3e1b5e1eaf..fbb7b419b0 100644
--- a/cellframe-sdk.pro
+++ b/cellframe-sdk.pro
@@ -9,8 +9,8 @@ linux: !android {
 
 win32 {
     
-    CONFIG(release, debug | release): sdk_build.commands = "$$shell_path($$PWD/../cellframe-sdk/prod_build/build.sh)" --target windows release -DINSTALL_SDK=1 -DCMAKE_INSTALL_PREFIX=/ -DCELLFRAME_NO_OPTIMIZATION=1
-    CONFIG(debug, debug | release): sdk_build.commands = "$$shell_path($$PWD/../cellframe-sdk/prod_build/build.sh)" --target windows rwd -DINSTALL_SDK=1 -DCMAKE_INSTALL_PREFIX=/ -DCELLFRAME_NO_OPTIMIZATION=1
+    CONFIG(release, debug | release): sdk_build.commands = "$$PWD/../cellframe-sdk/prod_build/build.sh" --target windows release -DINSTALL_SDK=1 -DCMAKE_INSTALL_PREFIX=/ -DCELLFRAME_NO_OPTIMIZATION=1
+    CONFIG(debug, debug | release): sdk_build.commands = "$$PWD/../cellframe-sdk/prod_build/build.sh" --target windows rwd -DINSTALL_SDK=1 -DCMAKE_INSTALL_PREFIX=/ -DCELLFRAME_NO_OPTIMIZATION=1
     
 }
 
diff --git a/dap-sdk b/dap-sdk
index da046e00eb..8092ada06d 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit da046e00ebeb5261ebcd874d5bdeeb05d37c9a0f
+Subproject commit 8092ada06dca5730f2efb16f7851fbf7c1c29eb1
diff --git a/modules/net/srv/CMakeLists.txt b/modules/net/srv/CMakeLists.txt
index c3e5655091..d48b0f9a3b 100644
--- a/modules/net/srv/CMakeLists.txt
+++ b/modules/net/srv/CMakeLists.txt
@@ -12,3 +12,12 @@ target_link_libraries(${PROJECT_NAME} maxminddb dap_core dap_crypto dap_chain da
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
 target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../../dap-sdk/3rdparty/uthash/src)
+
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER "${DAP_CHAIN_NET_SRV_HEADERS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/net/srv/
+        ARCHIVE DESTINATION lib/modules/net/srv/
+        PUBLIC_HEADER DESTINATION include/modules/net/srv/
+)
+endif()
-- 
GitLab


From 46dc65646a77cc72283ce4f9ddc3b331e6f81239 Mon Sep 17 00:00:00 2001
From: "daniil.frolov" <daniil.frolov@demlabs.net>
Date: Thu, 23 Jan 2025 13:22:14 +0300
Subject: [PATCH 15/18] up sub

---
 dap-sdk | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/dap-sdk b/dap-sdk
index da046e00eb..1d22be263b 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit da046e00ebeb5261ebcd874d5bdeeb05d37c9a0f
+Subproject commit 1d22be263bef8c792979827a94dfdbef6d74fc8c
-- 
GitLab


From d880fa3e08df9b527192c0bcd882999212753066 Mon Sep 17 00:00:00 2001
From: "P. Constantin" <papizh.konstantin@demlabs.net>
Date: Thu, 23 Jan 2025 22:34:43 +0700
Subject: [PATCH 16/18] Signature serialization refined

---
 modules/net/dap_chain_net_tx.c | 122 ++++++++++++---------------------
 1 file changed, 45 insertions(+), 77 deletions(-)

diff --git a/modules/net/dap_chain_net_tx.c b/modules/net/dap_chain_net_tx.c
index f3affeae81..90e239b626 100644
--- a/modules/net/dap_chain_net_tx.c
+++ b/modules/net/dap_chain_net_tx.c
@@ -1186,68 +1186,46 @@ int dap_chain_net_tx_create_by_json(json_object *a_tx_json, dap_chain_net_t *a_n
             }
         }
             break;
-        case TX_ITEM_TYPE_SIG:{          
-            const char *l_sign_type_str = s_json_get_text(l_json_item_obj, "sig_type");          
-            if (l_sign_type_str) {
-                dap_sign_type_t l_sign_type = dap_sign_type_from_str(l_sign_type_str);
-                if (l_sign_type.type == SIG_TYPE_NULL) {
-                    json_object *l_jobj_err = json_object_new_string("Can't define sign type");
-                    json_object_array_add(l_jobj_errors, l_jobj_err);
-                    log_it(L_ERROR, "Json TX: Can't define sign type \"%s\"", l_sign_type_str);
-                    break;
-                }
-                int64_t l_pkey_size, l_sig_size, l_hash_type = 0;
-
-                s_json_get_int64(l_json_item_obj, "hash_type", &l_hash_type);
-                s_json_get_int64(l_json_item_obj, "pub_key_size", &l_pkey_size);
-                s_json_get_int64(l_json_item_obj, "sig_size", &l_sig_size);
-                debug_if(!l_pkey_size || !l_sig_size, L_WARNING,
-                         "\"pub_key_size\" or \"sig_size\" not provided! Will be calculated automatically");
-                
-                json_object *l_jobj_pub_key = json_object_object_get(l_json_item_obj, "pub_key_b64"),
-                            *l_jobj_sign = json_object_object_get(l_json_item_obj, "sig_b64");
-                if (!l_jobj_pub_key || !l_jobj_sign) {
-                    json_object *l_jobj_err = json_object_new_string("Can't get base64-encoded sign or pkey!");
-                    json_object_array_add(l_jobj_errors, l_jobj_err);
-                    log_it(L_ERROR, "Json TX: Can't get base64-encoded sign or pkey!");
-                    break;
+        case TX_ITEM_TYPE_SIG: {
+            json_object *l_jobj_sign = json_object_object_get(l_json_item_obj, "sig_b64");
+            if (!l_jobj_sign) {
+                l_sign_list = dap_list_append(l_sign_list, l_json_item_obj);
+                break;
+            }
+            const char *l_sign_b64_str = json_object_get_string(l_json_item_obj);
+            if ( !l_sign_b64_str ) {
+                json_object_array_add(l_jobj_errors, json_object_new_string("Can't get base64-encoded sign"));
+                log_it(L_ERROR, "Json TX: Can't get base64-encoded sign!");
+                break;
+            }
+            int64_t l_sign_size = 0, l_sign_b64_strlen = json_object_get_string_len(l_json_item_obj),
+                    l_sign_decoded_size = DAP_ENC_BASE64_DECODE_SIZE(l_sign_b64_strlen);
+            if ( !s_json_get_int64(l_json_item_obj, "sig_size", &l_sign_size) )
+                log_it(L_NOTICE, "Json TX: \"sig_size\" unspecified, will be calculated automatically");
+
+            dap_chain_tx_sig_t *l_tx_sig = DAP_NEW_Z_SIZE(dap_chain_tx_sig_t, sizeof(dap_chain_tx_sig_t) + l_sign_decoded_size);
+            *l_tx_sig = (dap_chain_tx_sig_t) {
+                .header = {
+                    .type = TX_ITEM_TYPE_SIG, .version = 1,
+                    .sig_size = dap_enc_base64_decode(l_sign_b64_str, l_sign_b64_strlen, l_tx_sig->sig, DAP_ENC_DATA_TYPE_B64_URLSAFE)
                 }
-                const char *l_pub_key_str = json_object_get_string(l_jobj_pub_key),
-                           *l_sign_str = json_object_get_string(l_jobj_sign);
-                int64_t l_pkey_decoded_size = DAP_ENC_BASE64_DECODE_SIZE(strlen(l_pub_key_str)),
-                        l_sign_decoded_size = DAP_ENC_BASE64_DECODE_SIZE(strlen(l_sign_str));
-                
-                dap_sign_t *l_sign = DAP_NEW_SIZE(dap_sign_t, sizeof(dap_sign_t) + l_pkey_decoded_size + l_sign_decoded_size);
-                *l_sign = (dap_sign_t) {
-                    .header.type = l_sign_type,
-                    .header.hash_type = (uint8_t)l_hash_type,
-                };
-                l_pkey_decoded_size = dap_enc_base64_decode(l_pub_key_str, strlen(l_pub_key_str),
-                                                            l_sign->pkey_n_sign, DAP_ENC_DATA_TYPE_B64_URLSAFE);
-                debug_if(l_pkey_size != l_pkey_decoded_size, L_ERROR, "Json TX: pkey size mismatch, %zu != %zu",
-                                                                      l_pkey_size, l_pkey_decoded_size);
-
-                l_sign_decoded_size = dap_enc_base64_decode(l_sign_str, strlen(l_sign_str),
-                                                            l_sign->pkey_n_sign + l_pkey_decoded_size, DAP_ENC_DATA_TYPE_B64_URLSAFE);
-                debug_if(l_sig_size != l_sign_decoded_size, L_ERROR, "Json TX: sign size mismatch, %zu != %zu",
-                                                                     l_sig_size, l_sign_decoded_size);
-
-                l_sign->header.sign_size = l_sign_decoded_size;
-                l_sign->header.sign_pkey_size = l_pkey_decoded_size;
-                size_t l_sign_full_size = dap_sign_get_size(l_sign);
-                
-                dap_chain_tx_sig_t *l_tx_sig = DAP_NEW_Z_SIZE(dap_chain_tx_sig_t, sizeof(dap_chain_tx_sig_t) + l_sign_full_size);
-                l_tx_sig->header.type = TX_ITEM_TYPE_SIG;
-                l_tx_sig->header.version = 1;
-                l_tx_sig->header.sig_size = (uint32_t)l_sign_full_size;
-                memcpy(l_tx_sig->sig, l_sign, l_sign_full_size);
-                l_item = (const uint8_t*)l_tx_sig;
-                DAP_DELETE(l_sign);
+            };
+            
+            debug_if(l_sign_size && l_tx_sig->header.sig_size != l_sign_size, L_ERROR,
+                     "Json TX: sign size mismatch, %zu != %zu!", l_sign_size, l_tx_sig->header.sig_size);
+            /* But who cares?... */
+            size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx), l_tx_items_size = l_tx->header.tx_items_size;
+            l_tx->header.tx_items_size = 0;
+            if ( dap_sign_verify_all((dap_sign_t*)l_tx_sig->sig, l_tx_sig->header.sig_size, (byte_t*)l_tx, l_tx_size) ) {
+                json_object_array_add(l_jobj_errors, json_object_new_string("Sign verification failed!"));
+                log_it(L_ERROR, "Json TX: sign verification failed!");
                 break;
-            } else              
-                l_sign_list = dap_list_append(l_sign_list,l_json_item_obj);
-        }
-            break;
+                // TODO: delete the datum and return
+            } else {
+                l_tx->header.tx_items_size = l_tx_items_size;
+                l_item = (const uint8_t*)l_tx_sig;
+            }
+        } break;
         case TX_ITEM_TYPE_RECEIPT: {
             dap_chain_net_srv_uid_t l_srv_uid;
             if(!s_json_get_srv_uid(l_json_item_obj, "service_id", "service", &l_srv_uid.uint64)) {
@@ -1483,7 +1461,7 @@ int dap_chain_net_tx_create_by_json(json_object *a_tx_json, dap_chain_net_t *a_n
             continue;
         }
 
-        if (l_sign) {
+        if (l_sign) { /* WTF is this for?... */
             size_t l_chain_sign_size = dap_sign_get_size(l_sign); // sign data
             
             dap_chain_tx_sig_t *l_tx_sig = DAP_NEW_Z_SIZE(dap_chain_tx_sig_t,
@@ -1563,23 +1541,13 @@ int dap_chain_net_tx_to_json(dap_chain_datum_tx_t *a_tx, json_object *a_out_json
         } break;
         case TX_ITEM_TYPE_SIG: {
             dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t*)item);
-            json_object_object_add(json_obj_item,"type", json_object_new_string("sign"));
-            dap_chain_hash_fast_t l_hash_pkey;
-            json_object_object_add(json_obj_item,"sig_type",json_object_new_string(dap_sign_type_to_str(l_sign->header.type)));
-            json_object_object_add(json_obj_item,"pub_key_size",json_object_new_uint64(l_sign->header.sign_pkey_size));
-            json_object_object_add(json_obj_item,"sig_size",json_object_new_uint64(l_sign->header.sign_size));
-            json_object_object_add(json_obj_item,"hash_type",json_object_new_uint64(l_sign->header.hash_type));
-            
-            char l_pkey_base64[DAP_ENC_BASE64_ENCODE_SIZE(l_sign->header.sign_pkey_size) + 1];
-            size_t l_pkey_base64_size = dap_enc_base64_encode(l_sign->pkey_n_sign, l_sign->header.sign_pkey_size, l_pkey_base64, DAP_ENC_DATA_TYPE_B64_URLSAFE); 
-            l_pkey_base64[l_pkey_base64_size] = '\0';   
-            json_object_object_add(json_obj_item,"pub_key_b64", json_object_new_string(l_pkey_base64));     
-
-            char l_sign_base64[DAP_ENC_BASE64_ENCODE_SIZE(l_sign->header.sign_size) + 1];
-            size_t l_sign_base64_size = dap_enc_base64_encode(l_sign->pkey_n_sign + l_sign->header.sign_pkey_size, l_sign->header.sign_size, l_sign_base64, DAP_ENC_DATA_TYPE_B64_URLSAFE); 
-            l_sign_base64[l_sign_base64_size] = '\0';
-            json_object_object_add(json_obj_item,"sig_b64", json_object_new_string(l_sign_base64));
+            char *l_sign_b64 = DAP_NEW_Z_SIZE(char, DAP_ENC_BASE64_ENCODE_SIZE(dap_sign_get_size(l_sign)) + 1);
+            size_t l_sign_size = dap_sign_get_size(l_sign);
+            dap_enc_base64_encode(l_sign, l_sign_size, l_sign_b64, DAP_ENC_DATA_TYPE_B64_URLSAFE);
 
+            json_object_object_add(json_obj_item, "type",       json_object_new_string("sign"));
+            json_object_object_add(json_obj_item, "sig_size",   json_object_new_uint64(l_sign_size));
+            json_object_object_add(json_obj_item, "sig_b64",    json_object_new_string(l_sign_b64));
         } break;
         case TX_ITEM_TYPE_TSD: {
             json_object_object_add(json_obj_item,"type", json_object_new_string("data"));
-- 
GitLab


From 56a33e55f9e959523bbc7f72b55ca795cd63b425 Mon Sep 17 00:00:00 2001
From: "daniil.frolov" <daniil.frolov@demlabs.net>
Date: Fri, 24 Jan 2025 10:15:27 +0300
Subject: [PATCH 17/18] [*] Fix hash output in voting list

---
 modules/service/voting/dap_chain_net_srv_voting.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/modules/service/voting/dap_chain_net_srv_voting.c b/modules/service/voting/dap_chain_net_srv_voting.c
index d858aaf109..c74cf6fd33 100644
--- a/modules/service/voting/dap_chain_net_srv_voting.c
+++ b/modules/service/voting/dap_chain_net_srv_voting.c
@@ -919,7 +919,7 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply)
                 continue;
             json_object* json_obj_vote = json_object_new_object();
             json_object_object_add( json_obj_vote, "voting_tx", 
-                                    json_object_new_string_len(dap_chain_hash_fast_to_str_static(&l_voting->voting_hash), sizeof(dap_hash_str_t)) );            
+                                    json_object_new_string(dap_chain_hash_fast_to_str_static(&l_voting->voting_hash)));            
             char* l_voting_question = (char*)l_voting->voting_params.voting_tx + l_voting->voting_params.voting_question_offset;
             json_object_object_add( json_obj_vote, "question", 
                                     json_object_new_string_len(l_voting_question, l_voting->voting_params.voting_question_length) );
-- 
GitLab


From f360e6a4f6a028e7d080c3caa7eb3d8d0875f8ce Mon Sep 17 00:00:00 2001
From: "daniil.frolov" <daniil.frolov@demlabs.net>
Date: Fri, 24 Jan 2025 12:54:29 +0300
Subject: [PATCH 18/18] Up sub

---
 dap-sdk | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/dap-sdk b/dap-sdk
index 1d22be263b..b714164dac 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit 1d22be263bef8c792979827a94dfdbef6d74fc8c
+Subproject commit b714164dac76d65db91fe470d684861812c022cf
-- 
GitLab