From 4fbfd036bbc90cf2f6858bf2cd134640bb35c378 Mon Sep 17 00:00:00 2001
From: "daniil.frolov" <daniil.frolov@demlabs.net>
Date: Fri, 10 Jan 2025 10:45:33 +0300
Subject: [PATCH 1/7] [*] Fix tx_create_json for inputs with hash and index

---
 modules/net/dap_chain_node_cli_cmd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index b2c36368e2..5015ced1cc 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -6252,7 +6252,7 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply)
         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 (dap_strcmp(l_json_item_token, l_native_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;
                 }
-- 
GitLab


From 5dbd70bf83427f156bf0f06359034f2ab5a05318 Mon Sep 17 00:00:00 2001
From: "daniil.frolov" <daniil.frolov@demlabs.net>
Date: Fri, 10 Jan 2025 11:03:04 +0300
Subject: [PATCH 2/7] [*] Fix value_need counting for single channel tx

---
 modules/net/dap_chain_node_cli_cmd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index 5015ced1cc..663e6e8211 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -6365,7 +6365,7 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply)
                             }
                             l_item = (const uint8_t*) l_out_item;
                             if (l_item){
-                                if (!dap_strcmp(l_token, l_native_token))
+                                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);
-- 
GitLab


From b38b3119596ab5299afcab1626c8c7462488b8f6 Mon Sep 17 00:00:00 2001
From: Olzhas <oljas.jarasbaev@demlabs.net>
Date: Fri, 24 Jan 2025 16:42:05 +0700
Subject: [PATCH 3/7] [+] fix fee

---
 .../dap_chain_net_srv_stake_pos_delegate.c    | 23 +++++++++++++++----
 1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
index 581c26b64c..cc2624a125 100644
--- a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
+++ b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
@@ -3689,7 +3689,7 @@ bool dap_chain_net_srv_stake_get_fee_validators(dap_chain_net_t *a_net,
     dap_global_db_obj_t *l_orders = dap_global_db_get_all_sync(l_gdb_group_str, &l_orders_count);
     DAP_DELETE(l_gdb_group_str);
     uint256_t l_min = uint256_0, l_max = uint256_0, l_average = uint256_0, l_median = uint256_0;
-    uint64_t l_order_fee_count = 0;
+    size_t l_order_fee_count = 0;
     uint256_t* l_all_fees = DAP_NEW_Z_COUNT(uint256_t, l_orders_count);
     for (size_t i = 0; i < l_orders_count; i++) {
         const dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_check(l_orders[i].key, l_orders[i].value, l_orders[i].value_len);
@@ -3712,11 +3712,24 @@ bool dap_chain_net_srv_stake_get_fee_validators(dap_chain_net_t *a_net,
         uint256_t t = uint256_0;
         SUM_256_256(l_order->price, l_average, &t);
         l_average = t;
-        if (compare256(l_min, l_order->price) == 1) {
-            l_min = l_order->price;
+    }
+
+    uint16_t l_min_count = dap_chain_esbocs_get_min_validators_count(a_net->pub.id);
+    uint256_t l_min_tmp = uint256_0;
+    uint16_t l_min_tmp_count = 0;
+    for (size_t k = 0; k < l_order_fee_count; k++) {
+        if (IS_ZERO_256(l_min)) {
+            switch (compare256(l_min_tmp, l_all_fees[k])) {
+                case 0: l_min_tmp_count++; break;
+                case 1: l_min_tmp = l_all_fees[k]; l_min_tmp_count = 1; break;
+                default: break;
+            }
+            if (l_min_tmp_count == l_min_count) {
+                l_min = l_min_tmp;
+            }
         }
-        if (compare256(l_max, l_order->price) == -1) {
-            l_max = l_order->price;
+        if (compare256(l_max, l_all_fees[k]) == -1) {
+            l_max = l_all_fees[k];
         }
     }
     dap_global_db_objs_delete(l_orders, l_orders_count);
-- 
GitLab


From df28a99a6deb3eb96f61851299ba583e60a9a65b Mon Sep 17 00:00:00 2001
From: Olzhas <oljas.jarasbaev@demlabs.net>
Date: Fri, 24 Jan 2025 17:04:28 +0700
Subject: [PATCH 4/7] [*] fix

---
 modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
index cc2624a125..42ef600b8f 100644
--- a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
+++ b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
@@ -3718,7 +3718,6 @@ bool dap_chain_net_srv_stake_get_fee_validators(dap_chain_net_t *a_net,
     uint256_t l_min_tmp = uint256_0;
     uint16_t l_min_tmp_count = 0;
     for (size_t k = 0; k < l_order_fee_count; k++) {
-        if (IS_ZERO_256(l_min)) {
             switch (compare256(l_min_tmp, l_all_fees[k])) {
                 case 0: l_min_tmp_count++; break;
                 case 1: l_min_tmp = l_all_fees[k]; l_min_tmp_count = 1; break;
@@ -3727,7 +3726,6 @@ bool dap_chain_net_srv_stake_get_fee_validators(dap_chain_net_t *a_net,
             if (l_min_tmp_count == l_min_count) {
                 l_min = l_min_tmp;
             }
-        }
         if (compare256(l_max, l_all_fees[k]) == -1) {
             l_max = l_all_fees[k];
         }
-- 
GitLab


From f89a9475a805f6a89cb3b4bb695159f032e8aa51 Mon Sep 17 00:00:00 2001
From: Olzhas <oljas.jarasbaev@demlabs.net>
Date: Mon, 27 Jan 2025 15:20:47 +0700
Subject: [PATCH 5/7] [*] fix

---
 .../service/stake/dap_chain_net_srv_stake_pos_delegate.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
index 42ef600b8f..115c68fb6c 100644
--- a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
+++ b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
@@ -3717,15 +3717,20 @@ bool dap_chain_net_srv_stake_get_fee_validators(dap_chain_net_t *a_net,
     uint16_t l_min_count = dap_chain_esbocs_get_min_validators_count(a_net->pub.id);
     uint256_t l_min_tmp = uint256_0;
     uint16_t l_min_tmp_count = 0;
+    bool l_found = false;
     for (size_t k = 0; k < l_order_fee_count; k++) {
+        if (!l_found) {
             switch (compare256(l_min_tmp, l_all_fees[k])) {
-                case 0: l_min_tmp_count++; break;
-                case 1: l_min_tmp = l_all_fees[k]; l_min_tmp_count = 1; break;
+                case  0: l_min_tmp_count++; break;
+                case  1: 
+                case -1: l_min_tmp = l_all_fees[k]; l_min_tmp_count = 1; break;
                 default: break;
             }
             if (l_min_tmp_count == l_min_count) {
                 l_min = l_min_tmp;
+                l_found = true;
             }
+        }
         if (compare256(l_max, l_all_fees[k]) == -1) {
             l_max = l_all_fees[k];
         }
-- 
GitLab


From fc4640cde1abc07ecbf59922b1deafc252cfe010 Mon Sep 17 00:00:00 2001
From: Olzhas <oljas.jarasbaev@demlabs.net>
Date: Tue, 18 Feb 2025 11:37:27 +0700
Subject: [PATCH 6/7] [*] merge master

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

diff --git a/dap-sdk b/dap-sdk
index b85e227d3c..2c22bd8784 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit b85e227d3cdb7b8ffbc5ff16b56138e3b37ef23a
+Subproject commit 2c22bd87846323807de76ec4ab5ae926ccbfeaad
-- 
GitLab


From 3e36ef8ee4eda8a74350248a49cc8e41e9a0e796 Mon Sep 17 00:00:00 2001
From: Olzhas <oljas.jarasbaev@demlabs.net>
Date: Tue, 18 Feb 2025 11:43:25 +0700
Subject: [PATCH 7/7] [*] fix merge

---
 modules/net/dap_chain_node_cli_cmd.c | 672 ---------------------------
 1 file changed, 672 deletions(-)

diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index dccc66925e..62a0a69108 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -6210,678 +6210,6 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply)
         return l_ret;
     }
 
-    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 (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 (!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);
-        }
-    }
-    
-    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);
-    }
-
-    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) {
-- 
GitLab