diff --git a/modules/chain/dap_chain_tx.c b/modules/chain/dap_chain_tx.c
index d895ad60705cb8032b36d5f266b9500dad4bc897..6e4fb145d2c0f18416f8add80e541c0340a97266 100644
--- a/modules/chain/dap_chain_tx.c
+++ b/modules/chain/dap_chain_tx.c
@@ -79,9 +79,9 @@ dap_chain_tx_t* dap_chain_tx_dup(dap_chain_tx_t * a_tx)
  * @param a_tx_hh
  * @param a_tx
  */
-void dap_chain_tx_hh_add (dap_chain_tx_t * a_tx_hh, dap_chain_tx_t * a_tx)
+void dap_chain_tx_hh_add (dap_chain_tx_t ** a_tx_hh, dap_chain_tx_t * a_tx)
 {
-    HASH_ADD(hh,a_tx_hh,hash, sizeof(a_tx->hash),a_tx);
+    HASH_ADD(hh,*a_tx_hh,hash, sizeof(a_tx->hash),a_tx);
 }
 
 void dap_chain_tx_hh_free (dap_chain_tx_t * a_tx_hh)
diff --git a/modules/chain/include/dap_chain_tx.h b/modules/chain/include/dap_chain_tx.h
index fbae57c57cf1bf10389fd5224e63fb006e8aa3c7..4fc657eb358d8e28319d71d437a02b88ee5f2e07 100644
--- a/modules/chain/include/dap_chain_tx.h
+++ b/modules/chain/include/dap_chain_tx.h
@@ -66,7 +66,7 @@ typedef struct dap_chain_tx
 } dap_chain_tx_t;
 
 dap_chain_tx_t * dap_chain_tx_wrap_packed(dap_chain_datum_tx_t * a_tx_packed);
-void dap_chain_tx_hh_add (dap_chain_tx_t * a_tx_hh, dap_chain_tx_t * a_tx);
+void dap_chain_tx_hh_add (dap_chain_tx_t ** a_tx_hh, dap_chain_tx_t * a_tx);
 
 /**
  * @brief Find tx in hashtable by its datum_tx hash
diff --git a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c
index 2c6ffd5ea1bd2bd5dbccac73442a4207583677fb..20bb4a14690cd4ee3c00fdc32caa2c97a4a5abd2 100644
--- a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c
+++ b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c
@@ -249,14 +249,14 @@ static void s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_
             l_srv->callbacks.response_error(l_srv, 0, NULL, &l_err, sizeof(l_err));
         return;
     }
-    
+
     bool l_check_role = dap_chain_net_get_role(l_net).enums > NODE_ROLE_MASTER;  // check role
     if ( ! l_srv || l_check_role) // Service not found
         l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_SERVICE_NOT_FOUND;
 
     if ( l_err.code || !l_srv_session){
         debug_if(
-            l_check_role, L_ERROR, 
+            l_check_role, L_ERROR,
             "You can't provide service with ID %lu in net %s. Node role should be not lower than master\n",
             l_srv->uid.uint64, l_net->pub.name
             );
@@ -289,7 +289,7 @@ static void s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_
             dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err));
         if (l_srv && l_srv->callbacks.response_error)
             l_srv->callbacks.response_error(l_srv, 0, NULL, &l_err, sizeof(l_err));
-        DAP_DEL_Z(l_usage);
+        dap_chain_net_srv_usage_delete(l_srv_session);
         return;
     }
     l_usage->client->stream_worker = a_ch->stream_worker;
@@ -303,10 +303,24 @@ static void s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_
     l_usage->client_pkey_hash = a_request->hdr.client_pkey_hash;
 
 
-    if (l_srv->pricelist){
+    if (l_srv->pricelist || !dap_hash_fast_is_blank(&a_request->hdr.order_hash)){
         // not free service
         log_it( L_INFO, "Valid pricelist is founded. Start service in pay mode.");
 
+        if (dap_chain_net_get_state(l_net) == NET_STATE_OFFLINE) {
+            log_it(L_ERROR, "Can't start service because net %s is offline.", l_net->pub.name);
+            l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_IS_OFFLINE;
+            if(a_ch)
+                dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err));
+            if (l_srv && l_srv->callbacks.response_error)
+                l_srv->callbacks.response_error(l_srv, 0, NULL, &l_err, sizeof(l_err));
+            dap_chain_net_srv_usage_delete(l_srv_session);
+            return;
+        }
+
+        if (!dap_hash_fast_is_blank(&a_request->hdr.order_hash))
+            l_usage->static_order_hash = a_request->hdr.order_hash;
+
         dap_chain_net_srv_grace_t *l_grace = DAP_NEW_Z(dap_chain_net_srv_grace_t);
         if (!l_grace) {
             log_it(L_CRITICAL, "Memory allocation error");
@@ -414,21 +428,51 @@ static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace)
         }
 
         a_grace->usage->is_grace = true;
+
         if (a_grace->usage->receipt){ // If it is repeated grace
-            DL_FOREACH(a_grace->usage->service->pricelist, l_price) {
-                switch (l_price->units_uid.enm) {
-                case SERV_UNIT_MB:
-                case SERV_UNIT_SEC:
-                case SERV_UNIT_DAY:
-                case SERV_UNIT_KB:
-                case SERV_UNIT_B:
-                    log_it(L_MSG, "Proper unit type %s found among available prices",
-                           dap_chain_srv_unit_enum_to_str(l_price->units_uid.enm));
-                    break;
-                default:
-                    continue;
+            if (dap_hash_fast_is_blank(&a_grace->usage->static_order_hash)){
+                log_it(L_MSG, "Get price from list.");
+                DL_FOREACH(a_grace->usage->service->pricelist, l_price) {
+                    switch (l_price->units_uid.enm) {
+                    case SERV_UNIT_MB:
+                    case SERV_UNIT_SEC:
+                    case SERV_UNIT_DAY:
+                    case SERV_UNIT_KB:
+                    case SERV_UNIT_B:
+                        log_it(L_MSG, "Proper unit type %s found among available prices",
+                               dap_chain_srv_unit_enum_to_str(l_price->units_uid.enm));
+                        break;
+                    default:
+                        continue;
+                    }
+                    break; // proper price found, thus we exit from the loop
+                }
+
+                if (!l_price) {
+                    log_it(L_ERROR, "Price with proper unit type not found, check available orders and/or pricelists");
+                    l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_CANT_ADD_USAGE;
+                    s_grace_error(a_grace, l_err);
+                    return;
+                }
+                a_grace->usage->price = l_price;
+            } else {
+                char *l_order_hash_str = dap_chain_hash_fast_to_str_new(&a_grace->usage->static_order_hash);
+                log_it(L_MSG, "Get price from order %s.", l_order_hash_str);
+                DAP_DELETE(l_order_hash_str);
+                if ((l_price = dap_chain_net_srv_get_price_from_order(a_grace->usage->service, "srv_vpn", &a_grace->usage->static_order_hash))){
+                    switch (l_price->units_uid.enm) {
+                    case SERV_UNIT_MB:
+                    case SERV_UNIT_SEC:
+                    case SERV_UNIT_DAY:
+                    case SERV_UNIT_KB:
+                    case SERV_UNIT_B:
+                        log_it(L_MSG, "Proper unit type %s found among available prices",
+                               dap_chain_srv_unit_enum_to_str(l_price->units_uid.enm));
+                        a_grace->usage->price = l_price;
+                    default:
+                        DAP_DEL_Z(l_price);
+                    }
                 }
-                break; // proper price found, thus we exit from the loop
             }
 
             if (!l_price) {
@@ -437,7 +481,6 @@ static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace)
                 s_grace_error(a_grace, l_err);
                 return;
             }
-            a_grace->usage->price = l_price;
             usages_in_grace_t *l_item = DAP_NEW_Z_SIZE(usages_in_grace_t, sizeof(usages_in_grace_t));
             if (!l_item) {
                 log_it(L_CRITICAL, "Memory allocation error");
@@ -499,6 +542,13 @@ static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace)
         }
 
     } else { // Start service in normal pay mode
+        if (dap_chain_net_get_state(l_net) == NET_STATE_OFFLINE) {
+            log_it(L_ERROR, "Can't pay service because net %s is offline.", l_net->pub.name);
+            l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_IS_OFFLINE;
+            s_grace_error(a_grace, l_err);
+            return;
+        }
+
         a_grace->usage->tx_cond = l_tx;
 
         l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY, NULL );
@@ -530,43 +580,92 @@ static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace)
         }
         dap_stpcpy(a_grace->usage->token_ticker, l_ticker);
 
-        dap_chain_net_srv_price_t *l_price_tmp;
-        DL_FOREACH(a_grace->usage->service->pricelist, l_price_tmp) {
-            if (!l_price_tmp){
-                continue;
-            }
 
-            if (l_price_tmp->net->pub.id.uint64  != a_grace->usage->net->pub.id.uint64){
-                log_it( L_WARNING, "Pricelist is not set for net %s", a_grace->usage->net->pub.name);
-                continue;
-            }
+        if (dap_hash_fast_is_blank(&a_grace->usage->static_order_hash)){
+            dap_chain_net_srv_price_t *l_price_tmp;
+            DL_FOREACH(a_grace->usage->service->pricelist, l_price_tmp) {
+                if (!l_price_tmp){
+                    continue;
+                }
 
-            if (dap_strcmp(l_price_tmp->token, l_ticker) != 0){
-                log_it( L_WARNING, "Token ticker in the pricelist and tx do not match");
-                continue;
-            }
+                if (l_price_tmp->net->pub.id.uint64  != a_grace->usage->net->pub.id.uint64){
+                    log_it( L_WARNING, "Pricelist is not for net %s.", a_grace->usage->net->pub.name);
+                    continue;
+                }
 
-            if (l_price_tmp->units_uid.enm != l_tx_out_cond->subtype.srv_pay.unit.enm){
-                log_it( L_WARNING, "Unit ID in the pricelist and tx do not match");
-                continue;
-            }
+                if (dap_strcmp(l_price_tmp->token, l_ticker) != 0){
+                    log_it( L_WARNING, "Token ticker in the pricelist and tx do not match");
+                    continue;
+                }
 
-            uint256_t l_unit_price = {};
-            if (l_price_tmp->units != 0){
-                DIV_256(l_price_tmp->value_datoshi, GET_256_FROM_64(l_price_tmp->units), &l_unit_price);
-            } else {
-                log_it( L_WARNING, "Units in pricelist is zero. ");
-                continue;
+                if (l_price_tmp->units_uid.enm != l_tx_out_cond->subtype.srv_pay.unit.enm){
+                    log_it( L_WARNING, "Unit ID in the pricelist and tx do not match");
+                    continue;
+                }
+
+                uint256_t l_unit_price = {};
+                if (l_price_tmp->units != 0){
+                    DIV_256(l_price_tmp->value_datoshi, GET_256_FROM_64(l_price_tmp->units), &l_unit_price);
+                } else {
+                    log_it( L_WARNING, "Units in pricelist is zero. ");
+                    continue;
+                }
+
+                if(IS_ZERO_256(l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) ||
+                    compare256(l_unit_price, l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) <= 0){
+                    l_price = l_price_tmp;
+                    break;
+                } else {
+                    log_it( L_WARNING, "Unit price in pricelist is greater than max allowable.");
+                }
             }
+        } else {
+            char *l_order_hash_str = dap_chain_hash_fast_to_str_new(&a_grace->usage->static_order_hash);
+            log_it(L_MSG, "Get price from order %s.", l_order_hash_str);
+            DAP_DELETE(l_order_hash_str);
+            if ((l_price = dap_chain_net_srv_get_price_from_order(a_grace->usage->service, "srv_vpn", &a_grace->usage->static_order_hash))){
+                if (l_price->net->pub.id.uint64  != a_grace->usage->net->pub.id.uint64){
+                    log_it( L_WARNING, "Pricelist is not for net %s.", a_grace->usage->net->pub.name);
+                    l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN;
+                    s_grace_error(a_grace, l_err);
+                    return;
+                }
 
-            if(IS_ZERO_256(l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) ||
-                compare256(l_unit_price, l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) <= 0){
-                l_price = l_price_tmp;
-                break;
-            } else {
-                log_it( L_WARNING, "Unit price in pricelist is greater than max allowable.");
+                if (dap_strcmp(l_price->token, l_ticker) != 0){
+                    log_it( L_WARNING, "Token ticker in the pricelist and tx do not match");
+                    l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN;
+                    s_grace_error(a_grace, l_err);
+                    return;
+                }
+
+                if (l_price->units_uid.enm != l_tx_out_cond->subtype.srv_pay.unit.enm){
+                    log_it( L_WARNING, "Unit ID in the pricelist and tx do not match");
+                    l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN;
+                    s_grace_error(a_grace, l_err);
+                    return;
+                }
+
+                uint256_t l_unit_price = {};
+                if (l_price->units != 0){
+                    DIV_256(l_price->value_datoshi, GET_256_FROM_64(l_price->units), &l_unit_price);
+                } else {
+                    log_it( L_WARNING, "Units in pricelist is zero. ");
+                    l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN;
+                    s_grace_error(a_grace, l_err);
+                    return;
+                }
+
+                if(IS_ZERO_256(l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) ||
+                    compare256(l_unit_price, l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) <= 0){
+                } else {
+                    log_it( L_WARNING, "Unit price in pricelist is greater than max allowable.");
+                    l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN;
+                    s_grace_error(a_grace, l_err);
+                    return;
+                }
             }
         }
+
         if ( !l_price ) {
             log_it( L_WARNING, "Request can't be processed because no acceptable price in pricelist for token %s in network %s",
                     l_ticker, l_net->pub.name );
@@ -714,6 +813,13 @@ static bool s_grace_period_finish(usages_in_grace_t *a_grace_item)
         s_grace_error(l_grace, l_err);
         RET_WITH_DEL_A_GRACE;
     } else { // Start service in normal pay mode
+        if (dap_chain_net_get_state(l_net) == NET_STATE_OFFLINE) {
+            log_it(L_ERROR, "Can't pay service because net %s is offline.", l_net->pub.name);
+            l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_IS_OFFLINE;
+            s_grace_error(l_grace, l_err);
+            RET_WITH_DEL_A_GRACE;
+        }
+
         log_it(L_INFO, "Tx is found in ledger.");
         l_grace->usage->tx_cond = l_tx;
 
@@ -740,43 +846,91 @@ static bool s_grace_period_finish(usages_in_grace_t *a_grace_item)
         l_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(l_ledger, &l_grace->usage->tx_cond_hash);
         dap_stpcpy(l_grace->usage->token_ticker, l_ticker);
 
-        dap_chain_net_srv_price_t *l_price_tmp;
-        DL_FOREACH(l_grace->usage->service->pricelist, l_price_tmp) {
-            if (!l_price_tmp){
-                continue;
-            }
+        if (dap_hash_fast_is_blank(&l_grace->usage->static_order_hash)){
+            dap_chain_net_srv_price_t *l_price_tmp;
+            DL_FOREACH(l_grace->usage->service->pricelist, l_price_tmp) {
+                if (!l_price_tmp){
+                    continue;
+                }
 
-            if (l_price_tmp->net->pub.id.uint64  != l_grace->usage->net->pub.id.uint64){
-                log_it( L_WARNING, "Pricelist is not set for net %s", l_grace->usage->net->pub.name);
-                continue;
-            }
+                if (l_price_tmp->net->pub.id.uint64  != l_grace->usage->net->pub.id.uint64){
+                    log_it( L_WARNING, "Pricelist is not for net %s.", l_grace->usage->net->pub.name);
+                    continue;
+                }
 
-            if (dap_strcmp(l_price_tmp->token, l_ticker) != 0){
-                log_it( L_WARNING, "Token ticker in the pricelist and tx do not match");
-                continue;
-            }
+                if (dap_strcmp(l_price_tmp->token, l_ticker) != 0){
+                    log_it( L_WARNING, "Token ticker in the pricelist and tx do not match");
+                    continue;
+                }
 
-            if (l_price_tmp->units_uid.enm != l_tx_out_cond->subtype.srv_pay.unit.enm){
-                log_it( L_WARNING, "Unit ID in the pricelist and tx do not match");
-                continue;
-            }
+                if (l_price_tmp->units_uid.enm != l_tx_out_cond->subtype.srv_pay.unit.enm){
+                    log_it( L_WARNING, "Unit ID in the pricelist and tx do not match");
+                    continue;
+                }
 
-            uint256_t l_unit_price = {};
-            if (l_price_tmp->units != 0){
-                DIV_256(l_price_tmp->value_datoshi, GET_256_FROM_64(l_price_tmp->units), &l_unit_price);
-            } else {
-                log_it( L_WARNING, "Units in pricelist is zero. ");
-                continue;
+                uint256_t l_unit_price = {};
+                if (l_price_tmp->units != 0){
+                    DIV_256(l_price_tmp->value_datoshi, GET_256_FROM_64(l_price_tmp->units), &l_unit_price);
+                } else {
+                    log_it( L_WARNING, "Units in pricelist is zero. ");
+                    continue;
+                }
+
+                if(IS_ZERO_256(l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) ||
+                    compare256(l_unit_price, l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) <= 0){
+                    l_price = l_price_tmp;
+                    break;
+                } else {
+                    log_it( L_WARNING, "Unit price in pricelist is greater than max allowable.");
+                }
             }
+        } else {
+            char *l_order_hash_str = dap_chain_hash_fast_to_str_new(&l_grace->usage->static_order_hash);
+            log_it(L_MSG, "Get price from order %s.", l_order_hash_str);
+            DAP_DELETE(l_order_hash_str);
+            if ((l_price = dap_chain_net_srv_get_price_from_order(l_grace->usage->service, "srv_vpn", &l_grace->usage->static_order_hash))){
+                if (l_price->net->pub.id.uint64  != l_grace->usage->net->pub.id.uint64){
+                    log_it( L_WARNING, "Pricelist is not for net %s.", l_grace->usage->net->pub.name);
+                    l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN;
+                    s_grace_error(l_grace, l_err);
+                    RET_WITH_DEL_A_GRACE;
+                }
 
-            if(IS_ZERO_256(l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) ||
-                compare256(l_unit_price, l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) <= 0){
-                l_price = l_price_tmp;
-                break;
-            } else {
-                log_it( L_WARNING, "Unit price in pricelist is greater than max allowable.");
+                if (dap_strcmp(l_price->token, l_ticker) != 0){
+                    log_it( L_WARNING, "Token ticker in the pricelist and tx do not match");
+                    l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN;
+                    s_grace_error(l_grace, l_err);
+                    RET_WITH_DEL_A_GRACE;
+                }
+
+                if (l_price->units_uid.enm != l_tx_out_cond->subtype.srv_pay.unit.enm){
+                    log_it( L_WARNING, "Unit ID in the pricelist and tx do not match");
+                    l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN;
+                    s_grace_error(l_grace, l_err);
+                    RET_WITH_DEL_A_GRACE;
+                }
+
+                uint256_t l_unit_price = {};
+                if (l_price->units != 0){
+                    DIV_256(l_price->value_datoshi, GET_256_FROM_64(l_price->units), &l_unit_price);
+                } else {
+                    log_it( L_WARNING, "Units in pricelist is zero. ");
+                    l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN;
+                    s_grace_error(l_grace, l_err);
+                    RET_WITH_DEL_A_GRACE;
+                }
+
+                if(IS_ZERO_256(l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) ||
+                    compare256(l_unit_price, l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) <= 0){
+                } else {
+                    log_it( L_WARNING, "Unit price in pricelist is greater than max allowable.");
+                    l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN;
+                    s_grace_error(l_grace, l_err);
+                    RET_WITH_DEL_A_GRACE;
+                }
             }
         }
+
         if ( !l_price ) {
             log_it( L_WARNING, "Request can't be processed because no acceptable price in pricelist for token %s in network %s",
                    l_ticker, l_net->pub.name );
@@ -1039,7 +1193,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
         }
         l_request->err_code = 0;
 
-        strncpy(l_request->ip_send, a_ch->stream->esocket->remote_addr_str, INET_ADDRSTRLEN - 1);
+        strncpy(l_request->ip_send, a_ch->stream->esocket->hostaddr, INET_ADDRSTRLEN - 1);
         l_request->ip_send[INET_ADDRSTRLEN - 1] = '\0'; // Compiler warning escape
         l_request->recv_time2 = dap_nanotime_now();
 
@@ -1063,6 +1217,13 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
 
     case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_RESPONSE: { // Check receipt sign and make tx if success
         dap_chain_net_srv_usage_t * l_usage = l_srv_session->usage_active;
+
+        if (dap_chain_net_get_state(l_usage->net) == NET_STATE_OFFLINE) {
+            log_it(L_ERROR, "Can't pay service because net %s is offline.", l_usage->net->pub.name);
+            l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_IS_OFFLINE;
+            break;
+        }
+
         if (l_ch_pkt->hdr.data_size < sizeof(dap_chain_receipt_info_t)) {
             log_it(L_ERROR, "Wrong sign response size, %u when expected at least %zu with smth", l_ch_pkt->hdr.data_size,
                    sizeof(dap_chain_receipt_info_t));
diff --git a/modules/channel/chain-voting/dap_stream_ch_chain_voting.c b/modules/channel/chain-voting/dap_stream_ch_chain_voting.c
index 114aba6dd340bd82e6717899ab96655208e2de3f..8e683aeb087db0b3bd3050210f48d36e628c0b31 100644
--- a/modules/channel/chain-voting/dap_stream_ch_chain_voting.c
+++ b/modules/channel/chain-voting/dap_stream_ch_chain_voting.c
@@ -31,6 +31,7 @@ static struct voting_node_client_list *s_node_client_list = NULL;
 
 static size_t s_pkt_in_callback_count = 0;
 static struct voting_pkt_in_callback s_pkt_in_callback[16] = {};
+static pthread_rwlock_t s_node_client_list_lock;
 
 static void s_stream_ch_new(dap_stream_ch_t *a_ch, void *a_arg);
 static void s_stream_ch_delete(dap_stream_ch_t *a_ch, void *a_arg);
@@ -40,6 +41,7 @@ int dap_stream_ch_chain_voting_init()
 {
     log_it(L_NOTICE, "Chains voting channel initialized");
 
+    pthread_rwlock_init(&s_node_client_list_lock, NULL);
     dap_stream_ch_proc_add(DAP_STREAM_CH_ID_VOTING,
                            s_stream_ch_new,
                            s_stream_ch_delete,
@@ -82,7 +84,9 @@ void dap_stream_ch_chain_voting_message_write(dap_chain_net_t *a_net, dap_chain_
     size_t l_voting_pkt_size =  sizeof(*a_voting_pkt) + a_voting_pkt->hdr.data_size;
     struct voting_node_client_list *l_node_client_item = NULL;
     if (a_remote_node_addr->uint64 != dap_chain_net_get_cur_addr_int(a_net)) {
+        pthread_rwlock_rdlock(&s_node_client_list_lock);
         HASH_FIND(hh, s_node_client_list, a_remote_node_addr, sizeof(dap_chain_node_addr_t), l_node_client_item);
+        pthread_rwlock_unlock(&s_node_client_list_lock);
         if (!l_node_client_item) {
             size_t node_info_size = 0;
             char *l_key = dap_chain_node_addr_to_hash_str(a_remote_node_addr);
@@ -111,7 +115,9 @@ void dap_stream_ch_chain_voting_message_write(dap_chain_net_t *a_net, dap_chain_
             l_node_client_item->node_addr = *a_remote_node_addr;
             l_node_client_item->node_info = l_node_info;
             l_node_client_item->node_client = l_node_client;
+            pthread_rwlock_wrlock(&s_node_client_list_lock);
             HASH_ADD(hh, s_node_client_list, node_addr, sizeof(dap_chain_node_addr_t), l_node_client_item);
+            pthread_rwlock_unlock(&s_node_client_list_lock);
         }
         if (!l_node_client_item->node_client) {
             log_it(L_ERROR, "NULL node_client in item of voting channel");
@@ -136,6 +142,21 @@ void dap_stream_ch_chain_voting_deinit()
     }
 }
 
+void dap_stream_ch_chain_voting_close_all_clients(dap_chain_net_id_t a_net_id)
+{
+    struct voting_node_client_list *l_node_info_item, *l_node_info_tmp;
+    pthread_rwlock_wrlock(&s_node_client_list_lock);
+    HASH_ITER(hh, s_node_client_list, l_node_info_item, l_node_info_tmp) {
+        // Clang bug at this, l_node_info_item should change at every loop cycle
+        if (l_node_info_item->node_client->net->pub.id.uint64 == a_net_id.uint64){
+            HASH_DEL(s_node_client_list, l_node_info_item);
+            dap_chain_node_client_close_mt(l_node_info_item->node_client);
+            DAP_DELETE(l_node_info_item);
+        }
+    }
+    pthread_rwlock_unlock(&s_node_client_list_lock);
+}
+
 static void s_stream_ch_new(dap_stream_ch_t *a_ch, void *a_arg)
 {
     UNUSED(a_arg);
@@ -163,6 +184,18 @@ static void s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg)
     }
 
     dap_stream_ch_chain_voting_pkt_t *l_voting_pkt = (dap_stream_ch_chain_voting_pkt_t *)l_ch_pkt->data;
+    dap_chain_net_t *l_net = dap_chain_net_by_id(l_voting_pkt->hdr.net_id);
+
+    if (!l_net)
+        return;
+    if (dap_chain_net_get_state(l_net) == NET_STATE_OFFLINE) {
+        log_it(L_ERROR, "Reject packet because net %s is offline", l_net->pub.name);
+        dap_stream_ch_chain_voting_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_VOTING_PKT_TYPE_ERROR, l_voting_pkt->hdr.net_id.uint64,
+                                                    &l_voting_pkt->hdr.sender_node_addr, &l_voting_pkt->hdr.receiver_node_addr, NULL, 0);
+        a_ch->stream->esocket->flags |= DAP_SOCK_SIGNAL_CLOSE;
+        return;
+    }
+
     dap_proc_thread_callback_add(dap_proc_thread_get(a_ch->stream_worker->worker->id), s_callback_pkt_in_call_all,
                                 DAP_DUP_SIZE(l_voting_pkt, l_voting_pkt_size));
     dap_stream_ch_chain_voting_t *l_ch_chain_voting = DAP_STREAM_CH_CHAIN_VOTING(a_ch);
diff --git a/modules/channel/chain-voting/include/dap_stream_ch_chain_voting.h b/modules/channel/chain-voting/include/dap_stream_ch_chain_voting.h
index bc8c16913a29449521966fb1b704e5d7322b4028..f55f67014b3fbedfd086279a0d3032c471ecf504 100644
--- a/modules/channel/chain-voting/include/dap_stream_ch_chain_voting.h
+++ b/modules/channel/chain-voting/include/dap_stream_ch_chain_voting.h
@@ -10,6 +10,7 @@
 
 #define DAP_STREAM_CH_CHAIN_VOTING_PKT_TYPE_DATA        0x01
 #define DAP_STREAM_CH_CHAIN_VOTING_PKT_TYPE_TEST        0x02
+#define DAP_STREAM_CH_CHAIN_VOTING_PKT_TYPE_ERROR       0xFF
 
 #define DAP_STREAM_CH_ID_VOTING 'V'
 
@@ -64,5 +65,5 @@ size_t dap_stream_ch_chain_voting_pkt_write_unsafe(dap_stream_ch_t *a_ch, uint8_
 
 int dap_stream_ch_chain_voting_init();
 void dap_stream_ch_chain_voting_deinit();
-
+void dap_stream_ch_chain_voting_close_all_clients(dap_chain_net_id_t a_net_id);
 void dap_stream_ch_voting_queue_clear();
diff --git a/modules/common/dap_chain_datum.c b/modules/common/dap_chain_datum.c
index dafae10e2933d5c059d56f1fdc450bdd56fcaaf1..dc3cae2a857ae95d56fce7799411650f8d44f0cb 100644
--- a/modules/common/dap_chain_datum.c
+++ b/modules/common/dap_chain_datum.c
@@ -503,17 +503,15 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum,
                     DAP_DELETE(l_hash_str);
                 } break;
                 case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE: {
-                    char *l_value_str = dap_chain_balance_print(((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.buy_value);
-                    char *l_coins_str = dap_chain_balance_to_coins(((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.buy_value);
+//                    char *l_value_str = dap_chain_balance_print(((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.buy_value);
+                    char *l_rate_str = dap_chain_balance_to_coins(((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.rate);
                     dap_string_append_printf(a_str_out, "\t\t\t net id: 0x%016"DAP_UINT64_FORMAT_x"\n"
                                                         "\t\t\t buy_token: %s\n"
-                                                        "\t\t\t buy_value: %s (%s)\n",
+                                                        "\t\t\t rate: %s (%s)\n",
                                              ((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.buy_net_id.uint64,
                                              ((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.buy_token,
-                                             l_coins_str,
-                                             l_value_str);
-                    DAP_DELETE(l_value_str);
-                    DAP_DELETE(l_coins_str);
+                                             l_rate_str);
+                    DAP_DELETE(l_rate_str);
                 } break;
                 case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK: {
                     dap_time_t l_ts_exp = ((dap_chain_tx_out_cond_t*)item)->subtype.srv_stake_lock.time_unlock;
diff --git a/modules/common/dap_chain_datum_tx_items.c b/modules/common/dap_chain_datum_tx_items.c
index 64e09ba41a5304fa982667ef72dc667f4388616f..233099e58e35ec55510c9a6e6f2f50eb6baec61b 100644
--- a/modules/common/dap_chain_datum_tx_items.c
+++ b/modules/common/dap_chain_datum_tx_items.c
@@ -504,13 +504,13 @@ json_object *dap_chain_datum_tx_item_out_cond_srv_pay_to_json(dap_chain_tx_out_c
 
 dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_xchange(dap_chain_net_srv_uid_t a_srv_uid, dap_chain_net_id_t a_sell_net_id,
                                                                              uint256_t a_value_sell, dap_chain_net_id_t a_buy_net_id,
-                                                                             const char *a_token, uint256_t a_value_buy,
+                                                                             const char *a_token, uint256_t a_value_rate,
                                                                              const dap_chain_addr_t *a_seller_addr,
                                                                              const void *a_params, uint32_t a_params_size)
 {
     if (!a_token)
         return NULL;
-    if (IS_ZERO_256(a_value_sell) || IS_ZERO_256(a_value_buy))
+    if (IS_ZERO_256(a_value_sell) || IS_ZERO_256(a_value_rate))
         return NULL;
     dap_chain_tx_out_cond_t *l_item = DAP_NEW_Z_SIZE(dap_chain_tx_out_cond_t, sizeof(dap_chain_tx_out_cond_t) + a_params_size);
     l_item->header.item_type = TX_ITEM_TYPE_OUT_COND;
@@ -520,7 +520,7 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_xchange(dap
     l_item->subtype.srv_xchange.buy_net_id = a_buy_net_id;
     l_item->subtype.srv_xchange.sell_net_id = a_sell_net_id;
     strncpy(l_item->subtype.srv_xchange.buy_token, a_token, DAP_CHAIN_TICKER_SIZE_MAX - 1);
-    l_item->subtype.srv_xchange.buy_value = a_value_buy;
+    l_item->subtype.srv_xchange.rate = a_value_rate;
     l_item->subtype.srv_xchange.seller_addr = *a_seller_addr;
     l_item->tsd_size = a_params_size;
     if (a_params_size) {
@@ -539,12 +539,12 @@ json_object* dap_chain_datum_tx_item_out_cond_srv_xchange_to_json(dap_chain_tx_o
         json_object *l_obj_buy_net_id = dap_chain_net_id_to_json(a_srv_xchange->subtype.srv_xchange.buy_net_id);
         json_object *l_obj_sell_net_id = dap_chain_net_id_to_json(a_srv_xchange->subtype.srv_xchange.sell_net_id);
         json_object *l_obj_buy_token = json_object_new_string(a_srv_xchange->subtype.srv_xchange.buy_token);
-        char *l_value_buy = dap_chain_balance_print(a_srv_xchange->subtype.srv_xchange.buy_value);
-        json_object *l_obj_value_buy = json_object_new_string(l_value_buy);
-        DAP_DELETE(l_value_buy);
+        char *l_value_rate = dap_chain_balance_print(a_srv_xchange->subtype.srv_xchange.rate);
+        json_object *l_obj_value_rate = json_object_new_string(l_value_rate);
+        DAP_DELETE(l_value_rate);
         json_object *l_obj_seller_addr = dap_chain_addr_to_json(&a_srv_xchange->subtype.srv_xchange.seller_addr);
         json_object_object_add(l_object, "value", l_obj_value);
-        json_object_object_add(l_object, "valueBuy", l_obj_value_buy);
+        json_object_object_add(l_object, "valueRate", l_obj_value_rate);
         json_object_object_add(l_object, "srvUID", l_obj_srv_uid);
         json_object_object_add(l_object, "buyNetId", l_obj_buy_net_id);
         json_object_object_add(l_object, "sellNetId", l_obj_sell_net_id);
diff --git a/modules/common/include/dap_chain_datum_tx_items.h b/modules/common/include/dap_chain_datum_tx_items.h
index 13a728fbc469102b4cab01da8c047e3cb2ba3354..d9815983dd2a89639e56d980767721fdbdb5b395 100644
--- a/modules/common/include/dap_chain_datum_tx_items.h
+++ b/modules/common/include/dap_chain_datum_tx_items.h
@@ -177,7 +177,7 @@ json_object *dap_chain_datum_tx_item_out_cond_srv_pay_to_json(dap_chain_tx_out_c
  */
 dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_xchange(dap_chain_net_srv_uid_t a_srv_uid, dap_chain_net_id_t a_sell_net_id,
                                                                              uint256_t a_value_sell, dap_chain_net_id_t a_buy_net_id,
-                                                                             const char *a_token, uint256_t a_value_buy, const dap_chain_addr_t *a_seller_addr,
+                                                                             const char *a_token, uint256_t a_value_rate, const dap_chain_addr_t *a_seller_addr,
                                                                              const void *a_params, uint32_t a_params_size);
 
 json_object* dap_chain_datum_tx_item_out_cond_srv_xchange_to_json(dap_chain_tx_out_cond_t* a_srv_xchange);
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 5bce661a7e0c06a61fd4f86a6fab3bef6e6a5e6d..0348c717a26930031648b9f4cd109a728567673d 100644
--- a/modules/common/include/dap_chain_datum_tx_out_cond.h
+++ b/modules/common/include/dap_chain_datum_tx_out_cond.h
@@ -98,7 +98,7 @@ typedef struct dap_chain_tx_out_cond {
             // Chain network to change to
             dap_chain_net_id_t buy_net_id;
             // Total amount of datoshi to change to
-            uint256_t buy_value;
+            uint256_t rate;
             // Token ticker to change to
             char buy_token[DAP_CHAIN_TICKER_SIZE_MAX];
             // Seller address
diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
index abe85906fa54f48572d2c24e121c2206e12bde44..fae28da6293526912b0d667e121e5caed7adb728 100644
--- a/modules/consensus/esbocs/dap_chain_cs_esbocs.c
+++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
@@ -429,6 +429,31 @@ bool dap_chain_esbocs_started()
     return s_session_items;
 }
 
+void dap_chain_esbocs_stop_timer(dap_chain_net_id_t a_net_id)
+{
+    dap_chain_esbocs_session_t *l_session;
+    DL_FOREACH(s_session_items, l_session) {
+        if (l_session->chain->net_id.uint64 == a_net_id.uint64 &&
+            l_session->cs_timer){
+            log_it(L_INFO, "Stop consensus timer for net: %s, chain: %s", dap_chain_net_by_id(a_net_id)->pub.name, l_session->chain->name);
+            dap_timerfd_delete_mt(l_session->cs_timer->worker, l_session->cs_timer->esocket_uuid);
+            l_session->cs_timer = NULL;
+        }
+    }
+    dap_stream_ch_chain_voting_close_all_clients(a_net_id);
+}
+
+void dap_chain_esbocs_start_timer(dap_chain_net_id_t a_net_id)
+{
+    dap_chain_esbocs_session_t *l_session;
+    DL_FOREACH(s_session_items, l_session) {
+        if (l_session->chain->net_id.uint64 == a_net_id.uint64){
+            log_it(L_INFO, "Start consensus timer for net: %s, chain: %s", dap_chain_net_by_id(a_net_id)->pub.name, l_session->chain->name);
+            l_session->cs_timer = dap_timerfd_start(1000, s_session_timer, l_session);
+        }
+    }
+}
+
 static uint256_t s_callback_get_minimum_fee(dap_chain_t *a_chain)
 {
     dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain);
diff --git a/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h
index f680c1b6958951c9224f61f36394fa91a98c2988..fb23fe97a9617a75ef0185b5041f14f6a035fa8b 100644
--- a/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h
+++ b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h
@@ -209,3 +209,6 @@ typedef struct dap_chain_esbocs_session {
 int dap_chain_cs_esbocs_init();
 void dap_chain_cs_esbocs_deinit(void);
 bool dap_chain_esbocs_started();
+
+void dap_chain_esbocs_stop_timer(dap_chain_net_id_t a_net_id);
+void dap_chain_esbocs_start_timer(dap_chain_net_id_t a_net_id);
diff --git a/modules/net/CMakeLists.txt b/modules/net/CMakeLists.txt
index 533ef70d5b997302fc923fb460b8ebec09db1daa..bc27aa577a109f6f19686661fde8901bada25d4d 100644
--- a/modules/net/CMakeLists.txt
+++ b/modules/net/CMakeLists.txt
@@ -30,7 +30,7 @@ add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_NET_SRCS} ${DAP_CHAIN_NET_HEADERS
 
 target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_client dap_io dap_notify_srv dap_cli_server dap_chain dap_chain_wallet
                                         dap_chain_net_srv dap_chain_mempool dap_global_db dap_chain_net_srv_xchange dap_chain_cs_none
-                                        dap_stream_ch_chain_net dap_stream_ch_chain_voting)
+                                        dap_stream_ch_chain_net dap_stream_ch_chain_voting dap_chain_cs_esbocs)
 if(LINUX)
     target_link_libraries(${PROJECT_NAME} resolv)
 endif()
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index e491970c19f5546474418865d3b909786b52d916..88481d80d146c38829c75a660a81645b6d3664e3 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -117,6 +117,7 @@
 #include "dap_chain_net_srv_stake_pos_delegate.h"
 #include "dap_chain_net_srv_xchange.h"
 #include "dap_chain_node_net_ban_list.h"
+#include "dap_chain_cs_esbocs.h"
 
 #include <stdio.h>
 #include <sys/types.h>
@@ -372,8 +373,14 @@ int dap_chain_net_state_go_to(dap_chain_net_t * a_net, dap_chain_net_state_t a_n
     }
     PVT(a_net)->state_target = a_new_state;
     //PVT(a_net)->flags |= F_DAP_CHAIN_NET_SYNC_FROM_ZERO;  // TODO set this flag according to -mode argument from command line
-    if (a_new_state == NET_STATE_OFFLINE)
+    if(a_new_state == NET_STATE_ONLINE)
+        dap_chain_esbocs_start_timer(a_net->pub.id);
+
+    if (a_new_state == NET_STATE_OFFLINE){
+        dap_chain_esbocs_stop_timer(a_net->pub.id);
         return 0;
+    }
+
     return dap_proc_thread_callback_add(NULL, s_net_states_proc, a_net);
 }
 
diff --git a/modules/net/dap_chain_net_tx.c b/modules/net/dap_chain_net_tx.c
index 9f983be66b01e70a7d89a74304cc092ef8ab8d1a..55b8824e4471b74a758bd2e57f25215ed194bc72 100644
--- a/modules/net/dap_chain_net_tx.c
+++ b/modules/net/dap_chain_net_tx.c
@@ -291,7 +291,7 @@ static void s_get_tx_cond_chain_callback(dap_chain_net_t* a_net, dap_chain_datum
     if( l_args->ret ){
         int l_item_idx = 0;
         byte_t *l_tx_item;
-
+        dap_hash_fast_t * l_tx_hash = dap_chain_node_datum_tx_calc_hash(a_tx);
         // Get items from transaction
         while ((l_tx_item = dap_chain_datum_tx_item_get(a_tx, &l_item_idx, TX_ITEM_TYPE_IN_COND , NULL)) != NULL){
             dap_chain_tx_in_cond_t * l_in_cond = (dap_chain_tx_in_cond_t *) l_tx_item;
@@ -299,9 +299,21 @@ static void s_get_tx_cond_chain_callback(dap_chain_net_t* a_net, dap_chain_datum
                     (uint32_t)l_args->tx_last_cond_idx == l_in_cond->header.tx_out_prev_idx ){ // Found output
                 // We're the next tx in tx cond chain
                 l_args->ret = dap_list_append(l_args->ret, a_tx);
+                // Check cond output and update tx last hash and index
+                dap_chain_tx_out_cond_t * l_out_cond = NULL;
+                int l_out_item_idx = 0;
+                if (l_out_cond = dap_chain_datum_tx_out_cond_get(a_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_out_item_idx)){
+                    if ( l_out_cond->header.srv_uid.uint64 == l_args->srv_uid.uint64 ){ // We found output with target service uuid
+                        l_args->tx_last = a_tx; // Record current transaction as the last in tx chain
+                        memcpy(&l_args->tx_last_hash, l_tx_hash, sizeof(*l_tx_hash)); // Record current hash
+                        l_args->tx_last_cond_idx = l_out_item_idx;
+                    }
+                }
+                break;
             }
             l_item_idx++;
         }
+        DAP_DELETE(l_tx_hash);
     }else if(a_tx){
         dap_hash_fast_t * l_tx_hash = dap_chain_node_datum_tx_calc_hash(a_tx);
         if (!l_tx_hash) {
@@ -311,11 +323,10 @@ static void s_get_tx_cond_chain_callback(dap_chain_net_t* a_net, dap_chain_datum
         if (dap_hash_fast_compare(l_tx_hash,l_args->tx_begin_hash)) {
             // Found condition
             int l_item_idx = 0;
-            byte_t *l_tx_item;
 
             // Get items from transaction
-            while ((l_tx_item = dap_chain_datum_tx_item_get(a_tx, &l_item_idx, TX_ITEM_TYPE_OUT_COND , NULL)) != NULL){
-                dap_chain_tx_out_cond_t * l_out_cond = (dap_chain_tx_out_cond_t *) l_tx_item;
+            dap_chain_tx_out_cond_t * l_out_cond = NULL;
+            while (l_out_cond = dap_chain_datum_tx_out_cond_get(a_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_item_idx)){
                 if ( l_out_cond->header.srv_uid.uint64 == l_args->srv_uid.uint64 ){ // We found output with target service uuid
                     l_args->tx_last = a_tx; // Record current transaction as the last in tx chain
                     memcpy(&l_args->tx_last_hash, l_tx_hash, sizeof(*l_tx_hash)); // Record current hash
@@ -385,8 +396,8 @@ static void s_get_tx_cond_all_for_addr_callback(dap_chain_net_t* a_net, dap_chai
                 dap_chain_tx_in_t * l_in = (dap_chain_tx_in_t *) l_tx_item;
                 if( l_tx_from_addr) // Already detected thats spends from addr
                     break;
-                dap_chain_tx_t * l_tx = dap_chain_tx_hh_find( l_args->tx_all_hh, &l_in->header.tx_prev_hash);
-                if( l_tx ){ // Its input thats closing output for target address - we note it
+//                dap_chain_tx_t * l_tx = dap_chain_tx_hh_find( l_args->tx_all_hh, &l_in->header.tx_prev_hash);
+                if( dap_chain_tx_hh_find( l_args->tx_all_hh, &l_in->header.tx_prev_hash) ){ // Its input thats closing output for target address - we note it
                     l_tx_from_addr = true;
                     //l_tx_from_addr_token = dap_chain_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, &l_tx->hash);
                 }
@@ -395,8 +406,8 @@ static void s_get_tx_cond_all_for_addr_callback(dap_chain_net_t* a_net, dap_chai
                 if(l_tx_collected) // Already collected
                     break;
                 dap_chain_tx_in_cond_t * l_in_cond = (dap_chain_tx_in_cond_t *) l_tx_item;
-                dap_chain_tx_t * l_tx = dap_chain_tx_hh_find( l_args->tx_all_hh, &l_in_cond->header.tx_prev_hash);
-                if( l_tx ){ // Its input thats closing conditioned tx related with target address, collect it
+//                dap_chain_tx_t * l_tx = dap_chain_tx_hh_find( l_args->tx_all_hh, &l_in_cond->header.tx_prev_hash);
+                if( dap_chain_tx_hh_find( l_args->tx_all_hh, &l_in_cond->header.tx_prev_hash) ){ // Its input thats closing conditioned tx related with target address, collect it
                     //dap_chain_tx_t *l_tx_add = dap_chain_tx_wrap_packed(a_datum_tx);
                     l_args->ret = dap_list_append(l_args->ret, a_datum_tx);
                     l_tx_collected = true;
@@ -407,6 +418,7 @@ static void s_get_tx_cond_all_for_addr_callback(dap_chain_net_t* a_net, dap_chai
     }
 
     // Get out items from transaction
+    l_item_idx = 0;
     while ((l_tx_item = (dap_chain_datum_tx_item_t *) dap_chain_datum_tx_item_get(a_datum_tx, &l_item_idx, TX_ITEM_TYPE_OUT_ALL , NULL)) != NULL){
         switch (l_tx_item->type){
             case TX_ITEM_TYPE_OUT:{
@@ -415,7 +427,7 @@ static void s_get_tx_cond_all_for_addr_callback(dap_chain_net_t* a_net, dap_chai
                 dap_chain_tx_out_t * l_out = (dap_chain_tx_out_t*) l_tx_item;
                 if ( memcmp(&l_out->addr, l_args->addr, sizeof(*l_args->addr)) == 0){ // Its our address tx
                     dap_chain_tx_t * l_tx = dap_chain_tx_wrap_packed(a_datum_tx);
-                    dap_chain_tx_hh_add(l_args->tx_all_hh, l_tx);
+                    dap_chain_tx_hh_add(&l_args->tx_all_hh, l_tx);
                     l_tx_for_addr = true;
                 }
             }break;
@@ -425,7 +437,7 @@ static void s_get_tx_cond_all_for_addr_callback(dap_chain_net_t* a_net, dap_chai
                 dap_chain_tx_out_ext_t * l_out = (dap_chain_tx_out_ext_t*) l_tx_item;
                 if ( memcmp(&l_out->addr, l_args->addr, sizeof(*l_args->addr)) == 0){ // Its our address tx
                     dap_chain_tx_t * l_tx = dap_chain_tx_wrap_packed(a_datum_tx);
-                    dap_chain_tx_hh_add(l_args->tx_all_hh, l_tx);
+                    dap_chain_tx_hh_add(&l_args->tx_all_hh, l_tx);
                     l_tx_for_addr = true;
                 }
             }break;
diff --git a/modules/net/dap_chain_node_client.c b/modules/net/dap_chain_node_client.c
index bca24578358ed8ce00644532da641e3cefc604e7..98afec04ffcb5401c46382aa0839b25529bdf52b 100644
--- a/modules/net/dap_chain_node_client.c
+++ b/modules/net/dap_chain_node_client.c
@@ -64,6 +64,7 @@
 #include "dap_stream_ch_chain.h"
 #include "dap_stream_ch_chain_pkt.h"
 #include "dap_stream_ch_chain_net.h"
+#include "dap_stream_ch_proc.h"
 #include "dap_stream_ch_chain_net_pkt.h"
 #include "dap_stream_ch_chain_net_srv.h"
 #include "dap_stream_ch_chain_voting.h"
diff --git a/modules/net/srv/dap_chain_net_srv_order.c b/modules/net/srv/dap_chain_net_srv_order.c
index 810d334befdd7969e66fd389f8d7cf344d571378..07c316c94b588942b4bccc98d475340046e00799 100644
--- a/modules/net/srv/dap_chain_net_srv_order.c
+++ b/modules/net/srv/dap_chain_net_srv_order.c
@@ -550,6 +550,8 @@ void dap_chain_net_srv_order_dump_to_string(dap_chain_net_srv_order_t *a_order,d
         DAP_DELETE(l_balance);
         if( a_order->price_unit.uint32 )
             dap_string_append_printf(a_str_out, "  price_unit:       %s\n", dap_chain_net_srv_price_unit_uid_to_str(a_order->price_unit) );
+        if(a_order->price_ticker)
+            dap_string_append_printf(a_str_out, "  price_token:      %s\n",  a_order->price_ticker);
         if ( a_order->node_addr.uint64)
             dap_string_append_printf(a_str_out, "  node_addr:        "NODE_ADDR_FP_STR"\n", NODE_ADDR_FP_ARGS_S(a_order->node_addr) );
 
diff --git a/modules/net/srv/include/dap_chain_net_srv.h b/modules/net/srv/include/dap_chain_net_srv.h
index d8f6a3b43d61f9fcf5d057862ba19122a61800df..feb61aeb697529160a37fd65065774b584fec18e 100755
--- a/modules/net/srv/include/dap_chain_net_srv.h
+++ b/modules/net/srv/include/dap_chain_net_srv.h
@@ -104,6 +104,7 @@ typedef struct dap_chain_net_srv_price
 #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_SERVICE_IN_CLIENT_MODE     0x00000102
 #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_NOT_FOUND          0x00000200
 #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_NO_LEDGER          0x00000201
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_IS_OFFLINE         0x00000202
 #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_CANT_ADD_USAGE             0x00000300
 #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_FOUND          0x00000400
 #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NO_COND_OUT        0x00000401
diff --git a/modules/service/vpn/dap_chain_net_srv_vpn.c b/modules/service/vpn/dap_chain_net_srv_vpn.c
index ad2d44767bb9e6123bd0b088754873dc35dd49f3..11f6558f8f12e62cee4c1e800b2d34d3974f7157 100644
--- a/modules/service/vpn/dap_chain_net_srv_vpn.c
+++ b/modules/service/vpn/dap_chain_net_srv_vpn.c
@@ -82,7 +82,6 @@ typedef struct iphdr dap_os_iphdr_t;
 #include "dap_strfuncs.h"
 #include "dap_config.h"
 
-#include "dap_context.h"
 #include "dap_events_socket.h"
 #include "dap_http_client.h"
 
@@ -313,6 +312,10 @@ static bool s_tun_client_send_data(dap_chain_net_srv_ch_vpn_info_t * l_ch_vpn_in
             DAP_DEL_Z(l_pkt_out);
             return false;
         }
+       /*
+        dap_stream_worker_t *l_stream_worker = (dap_stream_worker_t *)dap_worker_get_current()->_inheritor;
+        s_tun_client_send_data_inter(l_stream_worker->queue_ch_io_input[l_ch_vpn_info->worker->id], l_ch_vpn_info->ch_vpn, l_pkt_out);
+        */
         if(s_debug_more){
 #ifdef DAP_OS_LINUX
             struct in_addr l_in_daddr = { .s_addr = ((dap_os_iphdr_t*)l_pkt_out->data)->daddr };
@@ -373,7 +376,7 @@ static void s_tun_recv_msg_callback(dap_events_socket_t * a_esocket_queue, void
     switch (l_msg->type) {
         case TUN_SOCKET_MSG_ESOCKET_REASSIGNED: {
             assert(l_msg->esocket_reassigment.worker_id < s_tun_sockets_count);
-            dap_chain_net_srv_vpn_tun_socket_t* l_tun_sock = s_tun_sockets[a_esocket_queue->worker->id];
+            dap_chain_net_srv_vpn_tun_socket_t* l_tun_sock = s_tun_sockets[a_esocket_queue->context->worker->id];
             assert(l_tun_sock);
             dap_chain_net_srv_ch_vpn_info_t* l_info = NULL;
             HASH_FIND(hh, l_tun_sock->clients, &l_msg->esocket_reassigment.addr, sizeof(l_msg->esocket_reassigment.addr), l_info);
@@ -381,11 +384,11 @@ static void s_tun_recv_msg_callback(dap_events_socket_t * a_esocket_queue, void
                 l_info->worker = dap_events_worker_get(l_msg->esocket_reassigment.worker_id);
                 l_info->queue_msg = s_tun_sockets_queue_msg[l_msg->esocket_reassigment.worker_id];
                 l_info->is_reassigned_once = true;
-                l_info->is_on_this_worker = (a_esocket_queue->worker->id == l_msg->esocket_reassigment.worker_id);
+                l_info->is_on_this_worker = (a_esocket_queue->context->worker->id == l_msg->esocket_reassigment.worker_id);
                 if (s_debug_more) {
                     char l_addrbuf[INET_ADDRSTRLEN];
                     inet_ntop(AF_INET, &l_msg->esocket_reassigment.addr, l_addrbuf, sizeof(l_addrbuf));
-                    log_it(L_INFO, "Tun:%u message: addr %s reassign on worker #%u", a_esocket_queue->worker->id,
+                    log_it(L_INFO, "Tun:%u message: addr %s reassign on worker #%u", a_esocket_queue->context->worker->id,
                         l_addrbuf, l_msg->esocket_reassigment.worker_id);
                 }
             }
@@ -393,13 +396,13 @@ static void s_tun_recv_msg_callback(dap_events_socket_t * a_esocket_queue, void
                 char l_addrbuf[INET_ADDRSTRLEN];
                 inet_ntop(AF_INET, &l_msg->esocket_reassigment.addr, l_addrbuf, sizeof(l_addrbuf));
                 log_it(L_INFO, "Reassigment message for address %s on worker %u comes but no such address was found on tun socket %u",
-                    l_addrbuf, l_msg->esocket_reassigment.worker_id, a_esocket_queue->worker->id);
+                    l_addrbuf, l_msg->esocket_reassigment.worker_id, a_esocket_queue->context->worker->id);
             }
         } break; /* l_msg->type == TUN_SOCKET_MSG_ESOCKET_REASSIGNED */
 
         case TUN_SOCKET_MSG_IP_ASSIGNED:{
             assert(l_msg->ip_assigment.worker_id < s_tun_sockets_count);
-            dap_chain_net_srv_vpn_tun_socket_t * l_tun_sock = s_tun_sockets[a_esocket_queue->worker->id];
+            dap_chain_net_srv_vpn_tun_socket_t * l_tun_sock = s_tun_sockets[a_esocket_queue->context->worker->id];
             assert(l_tun_sock);
 
             dap_chain_net_srv_ch_vpn_info_t * l_new_info = NULL;
@@ -420,7 +423,7 @@ static void s_tun_recv_msg_callback(dap_events_socket_t * a_esocket_queue, void
                 l_new_info->queue_msg           = s_tun_sockets_queue_msg[l_msg->ip_assigment.worker_id];
                 l_new_info->usage_id            = l_msg->ip_assigment.usage_id;
                 l_new_info->is_reassigned_once  = l_msg->is_reassigned_once;
-                l_new_info->is_on_this_worker   = (l_msg->ip_assigment.worker_id == a_esocket_queue->worker->id);
+                l_new_info->is_on_this_worker   = (l_msg->ip_assigment.worker_id == a_esocket_queue->context->worker->id);
                 l_new_info->esocket             = l_msg->esocket;
                 l_new_info->esocket_uuid        = l_msg->esocket_uuid;
                 l_new_info->worker              = dap_events_worker_get(l_msg->ip_assigment.worker_id);
@@ -428,7 +431,7 @@ static void s_tun_recv_msg_callback(dap_events_socket_t * a_esocket_queue, void
                 if (dap_log_level_get() <= L_INFO) {
                     char l_addrbuf[INET_ADDRSTRLEN];
                     inet_ntop(AF_INET, &l_msg->ip_assigment.addr, l_addrbuf, sizeof(l_addrbuf));
-                    log_it(L_DEBUG, "Tun:%u message: addr %s assigned for worker #%u on tun #u", a_esocket_queue->worker->id,
+                    log_it(L_DEBUG, "Tun:%u message: addr %s assigned for worker #%u on tun #u", a_esocket_queue->context->worker->id,
                         l_addrbuf, l_msg->ip_assigment.worker_id);
                 }
             }
@@ -436,7 +439,7 @@ static void s_tun_recv_msg_callback(dap_events_socket_t * a_esocket_queue, void
 
         case TUN_SOCKET_MSG_IP_UNASSIGNED:{
             assert(l_msg->ip_unassigment.worker_id < s_tun_sockets_count);
-            dap_chain_net_srv_vpn_tun_socket_t *l_tun_sock = s_tun_sockets[a_esocket_queue->worker->id];
+            dap_chain_net_srv_vpn_tun_socket_t *l_tun_sock = s_tun_sockets[a_esocket_queue->context->worker->id];
             assert(l_tun_sock);
 
             dap_chain_net_srv_ch_vpn_info_t *l_new_info = NULL;
@@ -457,18 +460,18 @@ static void s_tun_recv_msg_callback(dap_events_socket_t * a_esocket_queue, void
         }break; /* l_msg->type == TUN_SOCKET_MSG_IP_UNASSIGNED */
 
         case TUN_SOCKET_MSG_CH_VPN_SEND: {
-            if (dap_context_find(a_esocket_queue->worker->context, l_msg->esocket_uuid) == l_msg->esocket) {
+            if (dap_context_find(a_esocket_queue->context->worker->context, l_msg->esocket_uuid) == l_msg->esocket) {
                 s_tun_client_send_data_unsafe(l_msg->ch_vpn, l_msg->ch_vpn_send.pkt);
                 if (s_debug_more) {
                     char l_addrbuf[INET_ADDRSTRLEN];
                     inet_ntop(AF_INET, &l_msg->ip_assigment.addr, l_addrbuf, sizeof(l_addrbuf));
                     log_it(L_DEBUG, "Tun:%u message: send %u bytes for ch vpn protocol",
-                        a_esocket_queue->worker->id, l_msg->ch_vpn_send.pkt->header.op_data.data_size);
+                        a_esocket_queue->context->worker->id, l_msg->ch_vpn_send.pkt->header.op_data.data_size);
                 }
             }
             else {
                 log_it(L_ERROR, "MSG: No esocket %p on worker #%u, lost %d data",
-                    l_msg->esocket, a_esocket_queue->worker->id, l_msg->ch_vpn_send.pkt->header.op_data.data_size);
+                    l_msg->esocket, a_esocket_queue->context->worker->id, l_msg->ch_vpn_send.pkt->header.op_data.data_size);
             }
             DAP_DELETE(l_msg->ch_vpn_send.pkt);
         } break; /* l_msg->type == TUN_SOCKET_MSG_CH_VPN_SEND */
@@ -1195,7 +1198,7 @@ static void s_ch_vpn_esocket_unassigned(dap_events_socket_t* a_es, dap_worker_t
    //dap_chain_net_srv_ch_vpn_info_t * l_info = NULL;
    // HASH_FIND(hh,l_tun_sock->clients,&l_ch_vpn->addr_ipv4 , sizeof (l_ch_vpn->addr_ipv4), l_info);
 
-    s_tun_send_msg_esocket_reassigned_all_inter(a_es->worker->id, l_ch_vpn, l_ch_vpn->ch->stream->esocket,
+    s_tun_send_msg_esocket_reassigned_all_inter(a_es->context->worker->id, l_ch_vpn, l_ch_vpn->ch->stream->esocket,
                                                l_ch_vpn->ch->stream->esocket_uuid, l_ch_vpn->addr_ipv4);
 }
 
@@ -1249,7 +1252,9 @@ static void s_ch_vpn_delete(dap_stream_ch_t* a_ch, void* arg)
     usage_client_t * l_usage_client = NULL;
 
     dap_chain_net_srv_stream_session_t *l_srv_session = DAP_CHAIN_NET_SRV_STREAM_SESSION(l_ch_vpn->ch->stream->session);
-    dap_timerfd_delete_mt(l_srv_session->usage_active->client->stream_worker->worker, l_srv_session->usage_active->timer_es_uuid);
+    if (l_srv_session && l_srv_session->usage_active &&
+        l_srv_session->usage_active->client && l_srv_session->usage_active->client->stream_worker)
+        dap_timerfd_delete_mt(l_srv_session->usage_active->client->stream_worker->worker, l_srv_session->usage_active->timer_es_uuid);
 
     bool l_is_unleased = false;
     if ( l_ch_vpn->addr_ipv4.s_addr ){ // if leased address
@@ -1339,10 +1344,12 @@ static void s_update_limits(dap_stream_ch_t * a_ch ,
 
         if( a_srv_session->limits_ts <= 0 && !a_usage->is_grace){
             log_it(L_INFO, "Limits by timestamp are over. Switch to the next receipt");
-            dap_sign_t * l_receipt_sign = dap_chain_datum_tx_receipt_sign_get( a_usage->receipt_next, a_usage->receipt_next->size, 1);
-            if ( ! l_receipt_sign ){
-                log_it(L_WARNING, "Next receipt does not have client's sign. Delete it.");
-                DAP_DEL_Z(a_usage->receipt_next);
+            if (a_usage->receipt_next){
+                dap_sign_t * l_receipt_sign = dap_chain_datum_tx_receipt_sign_get( a_usage->receipt_next, a_usage->receipt_next->size, 1);
+                if ( ! l_receipt_sign ){
+                    log_it(L_WARNING, "Next receipt does not have client's sign. Delete it.");
+                    DAP_DEL_Z(a_usage->receipt_next);
+                }
             }
             DAP_DEL_Z(a_usage->receipt);
             a_usage->receipt = a_usage->receipt_next;
@@ -1401,11 +1408,12 @@ static void s_update_limits(dap_stream_ch_t * a_ch ,
 
         if (a_srv_session->limits_bytes <= 0  && !a_usage->is_grace){
             log_it(L_INFO, "Limits by traffic is over. Switch to the next receipt");
-            // get a second signature - from the client (first sign in server, second sign in client)
-            dap_sign_t * l_receipt_sign = dap_chain_datum_tx_receipt_sign_get( a_usage->receipt_next, a_usage->receipt_next->size, 1);
-            if ( ! l_receipt_sign ){
-                log_it(L_WARNING, "Next receipt does not have client's sign. Delete it.");
-                DAP_DEL_Z(a_usage->receipt_next);
+            if (a_usage->receipt_next){
+                dap_sign_t * l_receipt_sign = dap_chain_datum_tx_receipt_sign_get( a_usage->receipt_next, a_usage->receipt_next->size, 1);
+                if ( ! l_receipt_sign ){
+                    log_it(L_WARNING, "Next receipt does not have client's sign. Delete it.");
+                    DAP_DEL_Z(a_usage->receipt_next);
+                }
             }
             DAP_DEL_Z(a_usage->receipt);
             a_usage->receipt = a_usage->receipt_next;
@@ -1843,9 +1851,9 @@ static void s_ch_packet_out(dap_stream_ch_t* a_ch, void* a_arg)
 static void s_es_tun_delete(dap_events_socket_t * a_es, void * arg)
 {
     (void) arg;
-    if (a_es->worker) {
-        s_tun_sockets[a_es->worker->id] = NULL;
-        dap_events_socket_remove_and_delete_unsafe(s_tun_sockets_queue_msg[a_es->worker->id],false);
+    if (a_es->context->worker) {
+        s_tun_sockets[a_es->context->worker->id] = NULL;
+        dap_events_socket_remove_and_delete_unsafe(s_tun_sockets_queue_msg[a_es->context->worker->id],false);
         log_it(L_NOTICE,"Destroyed TUN event socket");
     }
 }
@@ -1965,11 +1973,11 @@ static void s_es_tun_read(dap_events_socket_t * a_es, void * arg)
         }
         if (l_vpn_info) {
             if ( !l_vpn_info->is_on_this_worker && !l_vpn_info->is_reassigned_once && s_raw_server->auto_cpu_reassignment) {
-                log_it(L_NOTICE, "Reassigning from worker %u to %u", l_vpn_info->worker->id, a_es->worker->id);
+                log_it(L_NOTICE, "Reassigning from worker %u to %u", l_vpn_info->worker->id, a_es->context->worker->id);
                 l_vpn_info->is_reassigned_once = true;
-                s_tun_send_msg_esocket_reassigned_all_inter(a_es->worker->id, l_vpn_info->ch_vpn, l_vpn_info->esocket, l_vpn_info->esocket_uuid,
+                s_tun_send_msg_esocket_reassigned_all_inter(a_es->context->worker->id, l_vpn_info->ch_vpn, l_vpn_info->esocket, l_vpn_info->esocket_uuid,
                     l_vpn_info->addr_ipv4);
-                dap_events_socket_reassign_between_workers_mt(l_vpn_info->worker, l_vpn_info->esocket, a_es->worker);
+                dap_events_socket_reassign_between_workers_mt(l_vpn_info->worker, l_vpn_info->esocket, a_es->context->worker);
             }
             s_tun_client_send_data(l_vpn_info, a_es->buf_in, l_buf_in_size);
         } else if(s_debug_more) {
@@ -2003,7 +2011,7 @@ static void s_es_tun_new(dap_events_socket_t * a_es, void * arg)
     (void) arg;
     dap_chain_net_srv_vpn_tun_socket_t * l_tun_socket = DAP_NEW_Z(dap_chain_net_srv_vpn_tun_socket_t);
     if ( l_tun_socket ){
-        dap_worker_t * l_worker = l_tun_socket->worker = a_es->worker;
+        dap_worker_t * l_worker = l_tun_socket->worker = a_es->context->worker;
         uint32_t l_worker_id = l_tun_socket->worker_id = l_worker->id;
         l_tun_socket->es = a_es;
 
diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c
index 9fcd359d8f2aa7ac083ffc10136b6946889c2f8b..41c4e2dedc754fb4e699191636353d7a47251518 100644
--- a/modules/service/xchange/dap_chain_net_srv_xchange.c
+++ b/modules/service/xchange/dap_chain_net_srv_xchange.c
@@ -50,6 +50,10 @@
 
 #define LOG_TAG "dap_chain_net_srv_xchange"
 
+typedef struct order_find_list{
+    dap_list_t *tx_list;
+}order_find_list_t;
+
 static dap_chain_net_srv_fee_item_t *s_service_fees = NULL; // Governance statements for networks
 static pthread_rwlock_t s_service_fees_rwlock = PTHREAD_RWLOCK_INITIALIZER;
 
@@ -86,9 +90,6 @@ int dap_chain_net_srv_xchange_init()
         "\tCreate a new order and tx with specified amount of datoshi to exchange with specified rate (buy / sell)\n"
     "srv_xchange order remove -net <net_name> -order <order_hash> -w <wallet_name>\n"
          "\tRemove order with specified order hash in specified net name\n"
-    "srv_xchange order update -net <net_name> -order <order_hash> -w <wallet_name> [-token_sell <token_ticker>] "
-                            "[-net_buy <net_name>] [-token_buy <token_ticker>] [-coins <value>] [-rate <value>]\n"
-         "\tUpdate order with specified order hash in specified net name\n"
     "srv_xchange order history -net <net_name> {-order <order_hash> | -addr <wallet_addr>}"
          "\tShows transaction history for the selected order\n"
     "srv_xchange order status -net <net_name> -order <order_hash>"
@@ -237,7 +238,8 @@ static bool s_xchange_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_
         return false;
     SUBTRACT_256_256(a_tx_out_cond->header.value, l_sell_again_val, &l_sell_val);
     MULT_256_256(a_tx_out_cond->header.value, l_buy_val, &l_seller_mul);
-    MULT_256_256(a_tx_out_cond->subtype.srv_xchange.buy_value, l_sell_val, &l_buyer_mul);
+
+//    MULT_256_256(a_tx_out_cond->subtype.srv_xchange.buy_value, l_sell_val, &l_buyer_mul);
     if (compare256(l_seller_mul, l_buyer_mul) < 0)
         return false;
 
@@ -496,7 +498,7 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha
     bool l_pay_with_native = !dap_strcmp(a_price->token_buy, l_native_ticker);
     // find the transactions from which to take away coins
     uint256_t l_value_transfer, // how many coins to transfer
-              l_value_need = a_price->datoshi_buy,
+              l_value_need = a_datoshi_buy, //a_price->datoshi_buy,
               l_net_fee,
               l_service_fee,
               l_total_fee = a_datoshi_fee,
@@ -894,6 +896,7 @@ char *s_xchange_order_create(dap_chain_net_srv_xchange_price_t *a_price, dap_cha
     dap_chain_hash_fast_t l_tx_hash = {};
     dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), &l_tx_hash);
     a_price->tx_hash = l_tx_hash;
+    dap_chain_node_addr_t *l_node_addr = dap_chain_net_get_cur_addr(a_price->net);
     dap_chain_net_srv_price_unit_uid_t l_unit = { .uint32 =  SERV_UNIT_UNDEFINED};
     dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_XCHANGE_ID };
     uint256_t l_datoshi_buy = uint256_0;
@@ -902,7 +905,7 @@ char *s_xchange_order_create(dap_chain_net_srv_xchange_price_t *a_price, dap_cha
     l_ext.datoshi_buy = l_datoshi_buy;
     strncpy(l_ext.token_buy, a_price->token_buy, DAP_CHAIN_TICKER_SIZE_MAX);
     uint32_t l_ext_size = sizeof(dap_srv_xchange_order_ext_t);
-    char *l_order_hash_str = dap_chain_net_srv_order_create(a_price->net, SERV_DIR_SELL, l_uid, g_node_addr,
+    char *l_order_hash_str = dap_chain_net_srv_order_create(a_price->net, SERV_DIR_SELL, l_uid, *l_node_addr,
                                                             l_tx_hash, &a_price->datoshi_sell, l_unit, a_price->token_sell, 0,
                                                             (uint8_t *)&l_ext, l_ext_size, 0, NULL, 0, a_price->wallet_key);
     return l_order_hash_str;
@@ -914,7 +917,7 @@ char *s_xchange_order_create(dap_chain_net_srv_xchange_price_t *a_price, dap_cha
  * @param a_order
  * @return
  */
-dap_chain_net_srv_xchange_price_t *s_xchange_price_from_order(dap_chain_net_t *a_net, dap_chain_net_srv_order_t *a_order,  bool a_ret_is_invalid)
+dap_chain_net_srv_xchange_price_t *s_xchange_price_from_order(dap_chain_net_t *a_net, dap_chain_datum_tx_t *a_order,  bool a_ret_is_invalid)
 {
     if (!a_net || !a_order)
         return NULL;
@@ -923,16 +926,24 @@ dap_chain_net_srv_xchange_price_t *s_xchange_price_from_order(dap_chain_net_t *a
         log_it(L_CRITICAL, "Memory allocation error");
         return NULL;
     }
-    dap_srv_xchange_order_ext_t *l_ext = (dap_srv_xchange_order_ext_t *)a_order->ext_n_sign;
-    strcpy(l_price->token_buy, l_ext->token_buy);
-    l_price->datoshi_buy = l_ext->datoshi_buy;
-    strcpy(l_price->token_sell, a_order->price_ticker);
-    l_price->datoshi_sell = a_order->price;
+
+     dap_chain_tx_out_cond_t *l_out_cond = dap_chain_datum_tx_out_cond_get(a_order, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE , NULL);
+
+    strcpy(l_price->token_buy, l_out_cond->subtype.srv_xchange.buy_token);
+    MULT_256_256(l_out_cond->header.value, l_out_cond->subtype.srv_xchange.rate, &l_price->datoshi_buy);
+
+    dap_hash_fast_t l_tx_hash = {};
+    dap_hash_fast(a_order, dap_chain_datum_tx_get_size(a_order), &l_tx_hash);
+    const char *l_token_sell = dap_chain_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, &l_tx_hash);
+    strcpy(l_price->token_sell, l_token_sell);
+
+
+    l_price->datoshi_sell = l_out_cond->header.value;
     l_price->net = a_net;
     if (!IS_ZERO_256(l_price->datoshi_buy)) {
-        DIV_256_COIN(l_price->datoshi_buy, l_price->datoshi_sell, &l_price->rate);
+        l_price->rate = l_out_cond->subtype.srv_xchange.rate;
         dap_hash_fast_t *l_final_hash = dap_chain_ledger_get_final_chain_tx_hash(a_net->pub.ledger,
-                                           DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &a_order->tx_cond_hash);
+                                            DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_tx_hash);
         if (l_final_hash) {
             l_price->tx_hash = *l_final_hash;
             return l_price;
@@ -970,9 +981,6 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c
     else if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, MIN(a_argc, a_arg_index + 1), "remove", NULL)) {
         l_cmd_num = CMD_REMOVE;
     }
-    else if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, MIN(a_argc, a_arg_index + 1), "update", NULL)) {
-        l_cmd_num = CMD_UPDATE;
-    }
     else if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, MIN(a_argc, a_arg_index + 1), "history", NULL)) {
         l_cmd_num = CMD_HISTORY;
     }
@@ -1104,28 +1112,45 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c
                 dap_chain_wallet_close(l_wallet);
                 return -14;
             }
-            // Create the order & put it to GDB
-            l_price->wallet_key = dap_chain_wallet_get_key(l_wallet, 0);
-            char *l_order_hash_str = s_xchange_order_create(l_price, l_tx);
-            dap_chain_wallet_close(l_wallet);
-            if (l_order_hash_str) {
-                dap_chain_hash_fast_from_str(l_order_hash_str, &l_price->order_hash);
-                if(!s_xchange_tx_put(l_tx, l_net)) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't put transaction to mempool", l_sign_str);
-                    dap_chain_net_srv_order_delete_by_hash_str_sync(l_net, l_order_hash_str);
-                    DAP_DELETE(l_order_hash_str);
-                    DAP_DELETE(l_price->wallet_str);
-                    DAP_DELETE(l_price);
-                    return -15;
-                }
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nSuccessfully created order %s", l_sign_str, l_order_hash_str);
-                DAP_DELETE(l_order_hash_str);
-            } else {
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't compose the order", l_sign_str);
+            dap_hash_fast_t l_tx_hash ={};
+            dap_hash_fast(l_tx, dap_chain_datum_tx_get_size(l_tx), &l_tx_hash);
+            if(!s_xchange_tx_put(l_tx, l_net)) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't put transaction to mempool", l_sign_str);
                 DAP_DELETE(l_price->wallet_str);
                 DAP_DELETE(l_price);
-                return -18;
+                return -15;
             }
+            // To avoid confusion, the term "order" will apply to the original conditional exchange offer transactions.
+            char *l_tx_hash_str = dap_hash_fast_str_new(&l_tx_hash, sizeof(l_tx_hash));
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nSuccessfully created order %s", l_sign_str, l_tx_hash_str);
+            DAP_DELETE(l_tx_hash_str);
+
+            // Note: Orders are transferred to conditional transactions, but it is necessary to leave
+            // the possibility of subsequent improvements with standard orders, so the next block of
+            // code will be commented out until better times.
+
+            // Create the order & put it to GDB
+//            l_price->wallet_key = dap_chain_wallet_get_key(l_wallet, 0);
+//            char *l_order_hash_str = s_xchange_order_create(l_price, l_tx);
+//            dap_chain_wallet_close(l_wallet);
+//            if (l_order_hash_str) {
+//                dap_chain_hash_fast_from_str(l_order_hash_str, &l_price->order_hash);
+//                if(!s_xchange_tx_put(l_tx, l_net)) {
+//                    dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't put transaction to mempool", l_sign_str);
+//                    dap_chain_net_srv_order_delete_by_hash_str_sync(l_net, l_order_hash_str);
+//                    DAP_DELETE(l_order_hash_str);
+//                    DAP_DELETE(l_price->wallet_str);
+//                    DAP_DELETE(l_price);
+//                    return -15;
+//                }
+//                dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nSuccessfully created order %s", l_sign_str, l_order_hash_str);
+//                DAP_DELETE(l_order_hash_str);
+//            } else {
+//                dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't compose the order", l_sign_str);
+//                DAP_DELETE(l_price->wallet_str);
+//                DAP_DELETE(l_price);
+//                return -18;
+//            }
         } break;
 
         case CMD_HISTORY:{
@@ -1150,40 +1175,48 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c
                 dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'order history' requires parameter -order or -addr" );
                 return -12;
             }
+
             if(l_addr_hash_str){
                 dap_chain_addr_t *l_addr = dap_chain_addr_from_str(l_addr_hash_str);
                 if (!l_addr) {
                     dap_cli_server_cmd_set_reply_text(a_str_reply, "Incorrect chain address");
                     return -14;
                 }
-                if (dap_chain_addr_check_sum(l_addr)) {
+                if (dap_chain_addr_check_sum(l_addr) != 1 ) {
                     dap_cli_server_cmd_set_reply_text(a_str_reply, "Incorrect chain address");
                     return -15;
                 }
                 dap_list_t *l_tx_list = dap_chain_net_get_tx_cond_all_for_addr(l_net,l_addr, c_dap_chain_net_srv_xchange_uid );
                 dap_string_t * l_str_reply = dap_string_new("");
-                while(l_tx_list ){
-                    dap_chain_datum_tx_t * l_tx_cur = (dap_chain_datum_tx_t*) l_tx_list->data;
-                    s_string_append_tx_cond_info(l_str_reply, l_net, l_tx_cur );
 
-                    //INFINITE LOOP ????
-                    
+                if (l_tx_list){
+                    dap_list_t *l_tx_list_temp = l_tx_list;
+                    while(l_tx_list_temp ){
+                    dap_chain_datum_tx_t * l_tx_cur = (dap_chain_datum_tx_t*) l_tx_list_temp->data;
+                    s_string_append_tx_cond_info(l_str_reply, l_net, l_tx_cur );
+                    l_tx_list_temp = l_tx_list_temp->next;
+                    }
+                    dap_list_free(l_tx_list);
+                    *a_str_reply = dap_string_free(l_str_reply, false);
+                }else{
+                    dap_cli_server_cmd_set_reply_text(a_str_reply, "No history");
                 }
-                dap_list_free(l_tx_list);
-                *a_str_reply = dap_string_free(l_str_reply, false);
                 DAP_DELETE(l_addr);
             }
-            if(l_order_hash_str){
-                dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_str);
-                if (!l_order) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified order not found");
-                    return -13;
-                }
 
-                dap_chain_datum_tx_t * l_tx = dap_chain_net_get_tx_by_hash(l_net,&l_order->tx_cond_hash, TX_SEARCH_TYPE_NET);
+            if(l_order_hash_str){
+//                dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_str);
+//                if (!l_order) {
+//                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified order not found");
+//                    return -13;
+//                }
+
+                dap_hash_fast_t l_order_tx_hash = {};
+                dap_chain_hash_fast_from_str(l_order_hash_str, &l_order_tx_hash);
+                dap_chain_datum_tx_t * l_tx = dap_chain_net_get_tx_by_hash(l_net, &l_order_tx_hash, TX_SEARCH_TYPE_NET);
                 if( l_tx){
                     int l_rc = s_tx_check_for_open_close(l_net,l_tx);
-                    char *l_tx_hash = dap_chain_hash_fast_to_str_new(&l_order->tx_cond_hash);
+                    char *l_tx_hash = dap_chain_hash_fast_to_str_new(&l_order_tx_hash);
                     if(l_rc == 0){
                         dap_cli_server_cmd_set_reply_text(a_str_reply, "WRONG TX %s", l_tx_hash);
                     }else if(l_rc == 1){
@@ -1192,13 +1225,12 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c
                         *a_str_reply = dap_string_free(l_str_reply, false);
                     }else if(l_rc == 2){
                         dap_string_t * l_str_reply = dap_string_new("");
-                        dap_list_t *l_tx_list = dap_chain_net_get_tx_cond_chain(l_net,&l_order->tx_cond_hash, c_dap_chain_net_srv_xchange_uid );
-                        while(l_tx_list ){
-                            dap_chain_datum_tx_t * l_tx_cur = (dap_chain_datum_tx_t*) l_tx_list->data;
+                        dap_list_t *l_tx_list = dap_chain_net_get_tx_cond_chain(l_net, &l_order_tx_hash, c_dap_chain_net_srv_xchange_uid );
+                        dap_list_t *l_tx_list_temp = l_tx_list;
+                        while(l_tx_list_temp ){
+                            dap_chain_datum_tx_t * l_tx_cur = (dap_chain_datum_tx_t*) l_tx_list_temp->data;
                             s_string_append_tx_cond_info(l_str_reply, l_net, l_tx_cur );
-
-                            //INFINITE LOOP ????
-
+                            l_tx_list_temp = l_tx_list_temp->next;
                         }
                         dap_list_free(l_tx_list);
                         *a_str_reply = dap_string_free(l_str_reply, false);
@@ -1212,7 +1244,7 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c
         } break;
 
         case CMD_REMOVE:
-        case CMD_UPDATE: {
+        {
             const char * l_order_hash_str = NULL;
             dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str);
             if (!l_net_str) {
@@ -1245,12 +1277,16 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c
                                                                 l_cmd_num == CMD_REMOVE ? "remove" : "update");
                 return -12;
             }
-            dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_str);
-            if (!l_order) {
+//            dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_str);
+
+            dap_hash_fast_t l_tx_hash = {};
+            dap_chain_hash_fast_from_str(l_order_hash_str, &l_tx_hash);
+            dap_chain_datum_tx_t *l_cond_tx = dap_chain_ledger_tx_find_by_hash(l_net->pub.ledger, &l_tx_hash);
+            if (!l_cond_tx) {
                 dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nSpecified order not found", l_sign_str);
                 return -13;
             }
-            dap_chain_net_srv_xchange_price_t *l_price = s_xchange_price_from_order(l_net, l_order, false);
+            dap_chain_net_srv_xchange_price_t *l_price = s_xchange_price_from_order(l_net, l_cond_tx, false);
             if (!l_price) {
                 dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't create price object from order", l_sign_str);
                 return -13;
@@ -1269,102 +1305,11 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c
                         DAP_DELETE(l_tx_hash_str);
                     }
                 }
-                if (dap_chain_net_srv_order_delete_by_hash_str_sync(l_net, l_order_hash_str)) {
-                    dap_string_append_printf(l_str_reply, "Can't remove order %s\n", l_order_hash_str);
-                } else {
-                    dap_string_append_printf(l_str_reply, "Remove order %s\n", l_order_hash_str);
-                }
                 DAP_DELETE(l_price);
                 if (!l_str_reply->len) {
                     dap_string_append(l_str_reply, "Price successfully removed");
                 }
                 *a_str_reply = dap_string_free(l_str_reply, false);
-            } else {    // CMD_UPDATE
-                const char *l_val_sell_str = NULL, *l_val_rate_str = NULL, *l_wallet_str = NULL, *l_new_wallet_str = NULL;
-                uint256_t l_datoshi_sell = {};
-                uint256_t l_rate = uint256_0;
-                dap_chain_wallet_t *l_wallet = NULL;
-                dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-coins", &l_val_sell_str);
-                if (l_val_sell_str) {
-                    l_datoshi_sell = dap_chain_balance_scan(l_val_sell_str);
-                    if (IS_ZERO_256(l_datoshi_sell)) {
-                        dap_cli_server_cmd_set_reply_text(a_str_reply, "Format -coins <unsigned long long>");
-                        return -9;
-                    }
-                }
-                dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-rate", &l_val_rate_str);
-                if (l_val_rate_str) {
-                    l_rate = dap_chain_coins_to_balance(l_val_rate_str);
-                    if (IS_ZERO_256(l_rate)) {
-                        dap_cli_server_cmd_set_reply_text(a_str_reply, "Format -rate <long double> = sell / buy");
-                        return -9;
-                    }
-                }
-                dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-w", &l_new_wallet_str);
-                l_wallet_str = l_new_wallet_str ? l_new_wallet_str : l_price->wallet_str;
-                l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config));
-                if (!l_wallet) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified wallet not found");
-                    return -11;
-                }  else {
-                    l_sign_str = dap_chain_wallet_check_bliss_sign(l_wallet);
-                }
-                if (!l_val_sell_str && !l_val_rate_str && !l_wallet_str) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "At least one of updating parameters is mandatory");
-                    return -13;
-                }
-                uint256_t l_value = dap_chain_wallet_get_balance(l_wallet, l_net->pub.id, l_token_sell_str);
-                if (!IS_ZERO_256(l_datoshi_sell) && compare256(l_value, l_datoshi_sell) == -1) {
-                        dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nNot enough cash in specified wallet", l_sign_str);
-                        dap_chain_wallet_close(l_wallet);
-                        return -12;
-                }
-                if (l_val_sell_str) {
-                    l_price->datoshi_sell = l_datoshi_sell;
-                }
-                if (l_val_rate_str) {
-                    l_price->rate = l_rate;
-                }
-                // Update the transaction
-                dap_chain_datum_tx_t *l_tx = s_xchange_tx_create_request(l_price, l_wallet);
-                if (l_new_wallet_str) {
-                    dap_chain_wallet_close(l_wallet);
-                    l_wallet = dap_chain_wallet_open(l_price->wallet_str, dap_chain_wallet_get_path(g_config));
-                    DAP_DELETE(l_price->wallet_str);
-                    l_price->wallet_str = dap_strdup(l_new_wallet_str);
-                }
-                if (!l_tx) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't compose the conditional transaction", l_sign_str);
-                    return -14;
-                }
-                bool l_ret = s_xchange_tx_invalidate(l_price, l_wallet); // may be changed to old price later
-                dap_chain_wallet_close(l_wallet);
-                if (!l_ret) {
-                    char *l_tx_hash_str = dap_chain_hash_fast_to_str_new(&l_price->tx_hash);
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't invalidate transaction %s\n", l_sign_str, l_tx_hash_str);
-                    DAP_DELETE(l_tx_hash_str);
-                    return -17;
-                }
-                // Update the order
-                dap_chain_net_srv_order_delete_by_hash_str_sync(l_price->net, l_order_hash_str);
-                DAP_DELETE(l_order_hash_str);
-                l_order_hash_str = s_xchange_order_create(l_price, l_tx);
-                if (l_order_hash_str) {
-                    dap_chain_hash_fast_from_str(l_order_hash_str, &l_price->order_hash);
-                    if(!s_xchange_tx_put(l_tx, l_net)) {
-                        dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't put transaction to mempool", l_sign_str);
-                        dap_chain_net_srv_order_delete_by_hash_str_sync(l_net, l_order_hash_str);
-                        DAP_DELETE(l_order_hash_str);
-                        return -15;
-                    }
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nSuccessfully created order %s", l_sign_str, l_order_hash_str);
-                    DAP_DELETE(l_order_hash_str);
-                } else {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't compose the order", l_sign_str);
-                    DAP_DELETE(l_price->wallet_str);
-                    DAP_DELETE(l_price);
-                    return -18;
-                }
             }
         } break;
 
@@ -1491,9 +1436,9 @@ static int s_tx_check_for_open_close(dap_chain_net_t * a_net, dap_chain_datum_tx
                                                                                &l_cond_idx);
     if (l_out_cond_item) {
         if(dap_chain_ledger_tx_hash_is_used_out_item(a_net->pub.ledger, &l_tx_hash, l_cond_idx, NULL))
-            return 1; // If its SRV_XCHANGE and spent its closed
+            return 2; // If its SRV_XCHANGE and spent its closed
         else
-            return 2; // If its SRV_XCHANGE and not spent its open
+            return 1; // If its SRV_XCHANGE and not spent its open
     }
     return 0;
 }
@@ -1519,9 +1464,6 @@ static void s_string_append_tx_cond_info( dap_string_t * a_reply_str, dap_chain_
     const char * l_tx_input_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(
                 a_net->pub.ledger, &l_tx_hash);
 
-
-
-
     // Find SRV_XCHANGE out_cond item
     int l_cond_idx = 0;
     dap_chain_tx_out_cond_t *l_out_cond_item = dap_chain_datum_tx_out_cond_get(a_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE,
@@ -1532,17 +1474,23 @@ static void s_string_append_tx_cond_info( dap_string_t * a_reply_str, dap_chain_
         bool l_is_closed = dap_chain_ledger_tx_hash_is_used_out_item(a_net->pub.ledger, &l_tx_hash, l_cond_idx, NULL);
 
         uint256_t l_value_from = l_out_cond_item->header.value;
-        uint256_t l_value_to = l_out_cond_item->subtype.srv_xchange.buy_value;
-        char *l_value_to_str = dap_chain_balance_to_coins(l_value_to);
+        uint256_t l_rate = l_out_cond_item->subtype.srv_xchange.rate;
+        char *l_rate_str = dap_chain_balance_to_coins(l_rate);
         char *l_value_from_str = dap_chain_balance_to_coins(l_value_from);
 
         dap_string_append_printf(a_reply_str, "Hash: %s", l_tx_hash_str);
         dap_string_append_printf(a_reply_str, "  Status: %s", l_is_closed ? "closed" : "open");
         dap_string_append_printf(a_reply_str, "  From: %s %s", l_value_from_str, l_tx_input_ticker);
-        dap_string_append_printf(a_reply_str, "  To: %s %s", l_value_to_str, l_out_cond_item->subtype.srv_xchange.buy_token);
+        dap_string_append_printf(a_reply_str, "  Rate: %s Buy token: %s", l_rate_str, l_out_cond_item->subtype.srv_xchange.buy_token);
 
         DAP_DELETE(l_value_from_str);
-        DAP_DELETE(l_value_to_str);
+        DAP_DELETE(l_rate_str);
+        l_is_cond_out = true;
+    }
+    else {
+        dap_string_append_printf(a_reply_str, "Hash: %s", l_tx_hash_str);
+        dap_string_append_printf(a_reply_str, "  Status: closed");
+        dap_string_append_printf(a_reply_str, "  Order is used out");
         l_is_cond_out = true;
     }
     if(l_is_cond_out){
@@ -1638,19 +1586,19 @@ dap_chain_tx_out_cond_t *l_out_cond_item;
 
             const char *l_tx_input_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, &l_hash);
 
-            uint256_t l_value_to = l_out_cond_item->subtype.srv_xchange.buy_value;
+            uint256_t l_rate = l_out_cond_item->subtype.srv_xchange.rate;
             uint256_t l_tx_input_values = dap_chain_net_get_tx_total_value(a_net, l_datum_tx);
 
             char *l_tx_input_values_str = dap_chain_balance_to_coins(l_tx_input_values);
             char *l_value_from_str = dap_chain_balance_to_coins(l_tx_input_values);
-            char *l_value_to_str = dap_chain_balance_to_coins(l_value_to);
+            char *l_rate_str = dap_chain_balance_to_coins(l_rate);
 
             dap_string_append_printf(l_reply_str, "  Status: %s,", l_rc ? "closed" : "open");
             dap_string_append_printf(l_reply_str, "  From: %s %s,", l_tx_input_values_str, l_tx_input_ticker);
-            dap_string_append_printf(l_reply_str, "  To: %s %s\n", l_value_to_str, l_out_cond_item->subtype.srv_xchange.buy_token);
+            dap_string_append_printf(l_reply_str, "  Rate: %s Buy token: %s\n", l_rate_str, l_out_cond_item->subtype.srv_xchange.buy_token);
 
             DAP_DELETE(l_value_from_str);
-            DAP_DELETE(l_value_to_str);
+            DAP_DELETE(l_rate_str);
             dap_string_append(l_reply_str, "\n");
         }
 
@@ -1662,7 +1610,19 @@ dap_chain_tx_out_cond_t *l_out_cond_item;
 }
 
 
+void s_tx_is_order_check (dap_chain_net_t* a_net, dap_chain_datum_tx_t *a_tx, void *a_arg)
+{
+    UNUSED(a_net);
+
+    order_find_list_t *l_arg = (order_find_list_t*)a_arg;
 
+    if (dap_chain_datum_tx_out_cond_get(a_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE , NULL) &&
+        !dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_IN_COND, NULL))
+    {
+        l_arg->tx_list = dap_list_append(l_arg->tx_list, a_tx);
+    }
+
+}
 
 static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply)
 {
@@ -1710,25 +1670,36 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply)
                 return -3;
             }
 
-            char * l_gdb_group_str = dap_chain_net_srv_order_get_gdb_group(l_net);
+//            char * l_gdb_group_str = dap_chain_net_srv_order_get_gdb_group(l_net);
 
-            size_t l_orders_count = 0;
-            dap_global_db_obj_t * l_orders = dap_global_db_get_all_sync(l_gdb_group_str, &l_orders_count);
-            dap_chain_net_srv_xchange_price_t *l_price;
+//            size_t l_orders_count = 0;
+//            dap_global_db_obj_t * l_orders = dap_global_db_get_all_sync(l_gdb_group_str, &l_orders_count);
+//            dap_chain_net_srv_xchange_price_t *l_price;
             dap_string_t *l_reply_str = dap_string_new("");
 
+            // Iterate blockchain, find txs with xchange cond out and without cond input
+            order_find_list_t l_arg = {};
+            dap_chain_net_get_tx_all(l_net,TX_SEARCH_TYPE_NET, s_tx_is_order_check, &l_arg);
 
-            for (size_t i = 0; i < l_orders_count; i++)
-            {
-                dap_chain_net_srv_order_t *l_order = (dap_chain_net_srv_order_t *)l_orders[i].value;
 
-                if (l_order->srv_uid.uint64 != DAP_CHAIN_NET_SRV_XCHANGE_ID)
+            // Print all txs
+            dap_list_t *l_temp = l_arg.tx_list;
+            while(l_temp)
+            {
+//                dap_chain_net_srv_order_t *l_order = (dap_chain_net_srv_order_t *)l_orders[i].value;
+                dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *)l_temp->data;
+                dap_chain_tx_out_cond_t *l_out_cond = dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE , NULL);
+                if (!l_out_cond || l_out_cond->header.srv_uid.uint64 != DAP_CHAIN_NET_SRV_XCHANGE_ID){
+                    l_temp = l_temp->next;
                     continue;
+                }
 
                 // TODO add filters to list (tokens, network, etc.)
-                l_price = s_xchange_price_from_order(l_net, l_order, true);
+                dap_chain_net_srv_xchange_price_t * l_price = NULL;
+                l_price = s_xchange_price_from_order(l_net, l_tx, true);
                 if( !l_price ){
                     log_it(L_WARNING,"Can't create price from order");
+                    l_temp = l_temp->next;
                     continue;
                 }
 
@@ -1743,7 +1714,11 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply)
 
                 MULT_256_COIN(l_price->datoshi_sell, l_price->rate, &l_datoshi_buy);  /* sell/buy computation */
 
-                dap_string_append_printf(l_reply_str, "orderHash: %s (%s) tokSel: %s, net: %s, tokBuy: %s, sell: %s (%s), buy: %s (%s) buy/sell: %s\n", l_orders[i].key,
+                dap_hash_fast_t l_tx_hash = {};
+                dap_hash_fast(l_tx, dap_chain_datum_tx_get_size(l_tx), &l_tx_hash);
+                char *l_tx_hash_str = dap_chain_hash_fast_to_str_new(&l_tx_hash);
+
+                dap_string_append_printf(l_reply_str, "orderHash: %s (%s) tokSel: %s, net: %s, tokBuy: %s, sell: %s (%s), buy: %s (%s) buy/sell: %s\n", l_tx_hash_str,
                                          l_status_order, l_price->token_sell, l_price->net->pub.name,
                                          l_price->token_buy,
                                          l_cp_sell_coins = dap_chain_balance_to_coins(l_price->datoshi_sell),
@@ -1752,15 +1727,18 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply)
                                          l_cp_buy_datoshi = dap_chain_balance_print(l_datoshi_buy),
                                          l_cp_rate = dap_chain_balance_to_coins(l_price->rate));
 
+                DAP_DEL_Z(l_tx_hash_str);
                 DAP_DEL_Z(l_cp_buy_coins);
                 DAP_DEL_Z(l_cp_buy_datoshi);
                 DAP_DEL_Z(l_cp_sell_coins);
                 DAP_DEL_Z(l_cp_sell_datoshi);
                 DAP_DEL_Z(l_cp_rate);
                 DAP_DEL_Z(l_price);
+                l_temp = l_temp->next;
             }
-            dap_global_db_objs_delete(l_orders, l_orders_count);
-            DAP_DELETE( l_gdb_group_str);
+//            dap_global_db_objs_delete(l_orders, l_orders_count);
+//            DAP_DELETE( l_gdb_group_str);
+            dap_list_free(l_arg.tx_list);
             if (!l_reply_str->len) {
                 dap_string_append(l_reply_str, "No orders found");
             }
@@ -1816,9 +1794,13 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply)
                 dap_cli_server_cmd_set_reply_text(a_str_reply, "Format -fee <unsigned int256>");
                 return -9;
             }
-            dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_str);
-            if (l_order) {
-                dap_chain_net_srv_xchange_price_t *l_price = s_xchange_price_from_order(l_net, l_order, false);
+//            dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_str);
+            dap_hash_fast_t l_tx_hash = {};
+            dap_chain_hash_fast_from_str(l_order_hash_str, &l_tx_hash);
+            dap_chain_datum_tx_t *l_cond_tx = dap_chain_ledger_tx_find_by_hash(l_net->pub.ledger, &l_tx_hash);
+
+            if (l_cond_tx) {
+                dap_chain_net_srv_xchange_price_t *l_price = s_xchange_price_from_order(l_net, l_cond_tx, false);
                 if(!l_price){
                     dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't create price from order");
                     return -13;
@@ -1830,7 +1812,6 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply)
                         dap_hash_fast_is_blank(&l_price->order_hash))
                     dap_chain_net_srv_order_delete_by_hash_str_sync(l_price->net, l_order_hash_str);
                 DAP_DELETE(l_price);
-                DAP_DELETE(l_order);
                 dap_cli_server_cmd_set_reply_text(a_str_reply, l_tx ? "Exchange transaction has done" :
                                                                       "Exchange transaction error");
             } else {
@@ -1959,8 +1940,8 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply)
                                                                                                &l_prev_cond_idx);
                     if (l_out_cond_item) {
                         uint256_t l_value_from = l_out_cond_item->header.value;
-                        uint256_t l_value_to = l_out_cond_item->subtype.srv_xchange.buy_value;
-                        char *l_value_to_str = dap_chain_balance_to_coins(l_value_to);
+                        uint256_t l_rate = l_out_cond_item->subtype.srv_xchange.rate;
+                        char *l_rate_str = dap_chain_balance_to_coins(l_rate);
                         char *l_value_from_str = dap_chain_balance_to_coins(l_value_from);
 
                         l_rc = dap_chain_ledger_tx_hash_is_used_out_item(l_net->pub.ledger, &l_tx_hash, l_prev_cond_idx, NULL);
@@ -1974,10 +1955,10 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply)
                         dap_string_append_printf(l_reply_str, "Hash: %s,", l_hash_str);
                         dap_string_append_printf(l_reply_str, "  Status: %s,", l_rc ? "closed" : "open");
                         dap_string_append_printf(l_reply_str, "  From: %s %s,", l_value_from_str, l_tx_input_ticker);
-                        dap_string_append_printf(l_reply_str, "  To: %s %s\n", l_value_to_str, l_out_cond_item->subtype.srv_xchange.buy_token);
+                        dap_string_append_printf(l_reply_str, "  Rate: %s Buy token: %s\n", l_rate_str, l_out_cond_item->subtype.srv_xchange.buy_token);
 
                         DAP_DELETE(l_value_from_str);
-                        DAP_DELETE(l_value_to_str);
+                        DAP_DELETE(l_rate_str);
                     }
 
                     l_datum_list = dap_list_next(l_datum_list);
@@ -2068,51 +2049,22 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply)
                         if(l_tx){
                             dap_hash_fast_t * l_tx_hash = dap_chain_node_datum_tx_calc_hash(l_tx);
 
-                            // Get input token ticker
-                            const char * l_tx_input_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(
-                                        l_net->pub.ledger, l_tx_hash);
-
-                            int l_direction = 0; //  1 - from/to,  -1  - to/from
-                            // Compare with token_from and token_to
-                            if(dap_strcmp(l_tx_input_ticker, l_token_from_str) == 0)
-                                l_direction = 1;
-                            else if (dap_strcmp(l_tx_input_ticker, l_token_to_str) == 0)
-                                l_direction = -1;
-                            else {
-                                l_cur = dap_list_next(l_cur);
-                                DAP_DEL_Z(l_tx_hash);
-                                continue;
-                            }
                             int l_cond_idx = 0;
                             dap_chain_tx_out_cond_t *l_out_cond_item = dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE,
                                                                                                        &l_cond_idx);
                             if (l_out_cond_item &&
                                     dap_chain_ledger_tx_hash_is_used_out_item(l_net->pub.ledger, l_tx_hash, l_cond_idx, NULL)) {
                                 uint256_t l_value_sell = l_out_cond_item->header.value;
-                                uint256_t l_value_buy = l_out_cond_item->subtype.srv_xchange.buy_value;
-                                if( l_direction == 1){
+                                l_rate = l_out_cond_item->subtype.srv_xchange.rate;
                                     if (!IS_ZERO_256(l_value_sell)) {
-                                        DIV_256_COIN(l_value_buy, l_value_sell, &l_rate);
                                         if(SUM_256_256(l_rate, l_total_rates, &l_total_rates )!= 0)
                                             log_it(L_ERROR, "Overflow on avarage price calculation (summing)");
                                         INCR_256(&l_total_rates_count);
                                     }else{
                                         log_it(L_ERROR, "Sell value is 0 in avarage price calculation (summing)");
                                     }
-                                }else if (l_direction == -1){
-                                    if (!IS_ZERO_256(l_value_buy)) {
-                                        DIV_256_COIN(l_value_sell, l_value_buy, &l_rate);
-                                        if(SUM_256_256(l_rate, l_total_rates, &l_total_rates )!= 0)
-                                            log_it(L_ERROR, "Overflow on avarage price calculation (summing)");
-                                        INCR_256(&l_total_rates_count);
-                                    }else{
-                                        log_it(L_ERROR, "Buy value is 0 in avarage price calculation (summing)");
-                                    }
-                                }else{
-                                    log_it(L_ERROR,"Wrong direction, not buy nor send (%d)",l_direction);
-                                }
+                                DAP_DEL_Z(l_tx_hash);
                             }
-                            DAP_DEL_Z(l_tx_hash);
                         }
                         l_cur = dap_list_next(l_cur);
                     }
@@ -2121,9 +2073,6 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply)
                     if (!IS_ZERO_256(l_total_rates_count))
                         DIV_256(l_total_rates,l_total_rates_count,&l_rate_average);
 
-                    if (!IS_ZERO_256(l_total_rates_count))
-                        DIV_256(l_total_rates,l_total_rates_count,&l_rate_average);
-
                     char *l_rate_average_str = dap_chain_balance_to_coins(l_rate_average);
                     char *l_last_rate_str = dap_chain_balance_to_coins(l_rate);
                     dap_string_append_printf(l_reply_str,"Average price: %s   Last price: %s", l_rate_average_str, l_last_rate_str);
@@ -2149,16 +2098,6 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply)
                             const char * l_tx_input_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(
                                         l_net->pub.ledger, l_tx_hash);
 
-                            int l_direction = 0; //  1 - from/to,  -1  - to/from
-                            // Compare with token_from and token_to
-                            if(dap_strcmp(l_tx_input_ticker, l_token_from_str) == 0)
-                                l_direction = 1;
-                            else if (dap_strcmp(l_tx_input_ticker, l_token_to_str) == 0)
-                                l_direction = -1;
-                            else {
-                                continue;
-                            }
-
                             // Check if output is spent
                             dap_chain_tx_out_cond_t *l_out_cond_item = l_cur->out_cond;
                             if(l_out_cond_item && l_cur->tx_next) {
@@ -2169,30 +2108,30 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply)
                                 DAP_DEL_Z(l_tx_hash_str);
 
                                 // Print tx_created
-                                char l_tx_ts_str[92] = {};  /* Convert ts to Sat May 17 01:17:08 2014 */
-                                dap_time_to_str_rfc822(l_tx_ts_str, 92, l_tx->header.ts_created);
+                                char l_tx_ts_str[92] = {0};
+                                struct tm l_tm={0};                                             /* Convert ts to  Sat May 17 01:17:08 2014 */
+                                uint64_t l_ts = l_tx->header.ts_created; // We take the next tx in chain to print close time, not the open one
+                                if ( (localtime_r((time_t *) &l_ts, &l_tm )) )
+                                    asctime_r (&l_tm, l_tx_ts_str);
+
                                 dap_string_append_printf(l_reply_str,"\tts_created: %s", l_tx_ts_str);
+
                                 // Print tx_closed
                                 memset(l_tx_ts_str,0,sizeof(l_tx_ts_str));
-                                dap_time_to_str_rfc822(l_tx_ts_str, 92, l_cur->tx_next->header.ts_created);
+                                memset(&l_tm,0,sizeof(l_tm));                                             /* Convert ts to  Sat May 17 01:17:08 2014 */
+                                l_ts = l_cur->tx_next->header.ts_created; // We take the next tx in chain to print close time, not the open one
+                                if ( (localtime_r((time_t *) &l_ts, &l_tm )) )
+                                    asctime_r (&l_tm, l_tx_ts_str);
+
                                 dap_string_append_printf(l_reply_str,"\tts_closed: %s", l_tx_ts_str);
+
                                 // Print value_from/value_to
+
                                 uint256_t l_value_from = l_out_cond_item->header.value;
-                                uint256_t l_value_to = l_out_cond_item->subtype.srv_xchange.buy_value;
-                                uint256_t l_rate = {};
-                                if( l_direction == 1){
-                                    if(compare256(l_value_from, uint256_0) != 0){
-                                        DIV_256_COIN(l_value_to, l_value_from, &l_rate);
-                                    }else
-                                        log_it(L_ERROR,"Value_from is zero, can't calc rate");
-                                }else if(l_direction == -1){
-                                    if(compare256(l_value_to, uint256_0) != 0){
-                                        DIV_256_COIN(l_value_from, l_value_to, &l_rate);
-                                    }else
-                                        log_it(L_ERROR,"Value_tois zero, can't calc rate");
-                                }else{
-                                    log_it(L_ERROR,"Wrong direction, not buy nor send (%d)",l_direction);
-                                }
+                                uint256_t l_rate = l_out_cond_item->subtype.srv_xchange.rate;
+                                uint256_t l_value_to = {};
+                                MULT_256_COIN(l_value_from, l_rate, &l_value_to);
+
                                 char * l_value_from_str = dap_chain_balance_to_coins(l_value_from);
                                 char * l_value_to_str = dap_chain_balance_to_coins(l_value_to);
                                 char *l_rate_str = dap_chain_balance_to_coins(l_rate);