diff --git a/dap-sdk b/dap-sdk
index a620492c6b5908345c55167618ab2802431cfdb9..e03e59dbf5f4c00d2232c43e3aa1ecd51b7f3622 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit a620492c6b5908345c55167618ab2802431cfdb9
+Subproject commit e03e59dbf5f4c00d2232c43e3aa1ecd51b7f3622
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 a036d7a3a6b4750b2db25bc30f32cfe5ceaecbc3..742271b5612c855b4d84d4163ace24004f0ea7b0 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
@@ -30,15 +30,15 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 #include "dap_hash.h"
 #include "rand/dap_rand.h"
 
-#include "dap_chain.h"
-#include "dap_chain_datum_tx.h"
-#include "dap_chain_datum_tx_in.h"
-#include "dap_chain_datum_tx_in_cond.h"
-#include "dap_chain_datum_tx_out.h"
-#include "dap_chain_datum_tx_out_cond.h"
-#include "dap_chain_datum_tx_receipt.h"
-#include "dap_chain_mempool.h"
-#include "dap_common.h"
+//#include "dap_chain.h"
+//#include "dap_chain_datum_tx.h"
+//#include "dap_chain_datum_tx_in.h"
+//#include "dap_chain_datum_tx_in_cond.h"
+//#include "dap_chain_datum_tx_out.h"
+//#include "dap_chain_datum_tx_out_cond.h"
+//#include "dap_chain_datum_tx_receipt.h"
+//#include "dap_chain_mempool.h"
+//#include "dap_common.h"
 
 #include "dap_chain_net_srv.h"
 #include "dap_chain_net_srv_stream_session.h"
@@ -54,6 +54,11 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 
 #define LOG_TAG "dap_stream_ch_chain_net_srv"
 
+typedef struct usages_in_grace{
+    dap_hash_fast_t tx_cond_hash;
+    dap_chain_net_srv_grace_t *grace;
+    UT_hash_handle hh;
+} usages_in_grace_t;
 
 uint8_t dap_stream_ch_chain_net_srv_get_id()
 {
@@ -65,6 +70,62 @@ static void s_stream_ch_delete(dap_stream_ch_t* ch , void* arg);
 static void s_stream_ch_packet_in(dap_stream_ch_t* ch , void* arg);
 static void s_stream_ch_packet_out(dap_stream_ch_t* ch , void* arg);
 
+static bool s_unban_client(dap_chain_net_srv_banlist_item_t *a_item);
+
+static void s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_pkt_request_t * a_request, size_t a_request_size);
+static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace);
+static bool s_grace_period_finish(usages_in_grace_t *a_grace);
+
+static inline void s_grace_error(dap_chain_net_srv_grace_t *a_grace, dap_stream_ch_chain_net_srv_pkt_error_t a_err){
+    dap_stream_ch_t * l_ch = dap_stream_ch_find_by_uuid_unsafe(a_grace->stream_worker, a_grace->ch_uuid);
+    dap_chain_net_srv_stream_session_t *l_srv_session = l_ch && l_ch->stream && l_ch->stream->session ?
+                                        (dap_chain_net_srv_stream_session_t *)l_ch->stream->session->_inheritor : NULL;
+
+        a_grace->usage->is_grace = false;
+    if (a_grace->usage->receipt_next){ // If not first grace-period
+        log_it( L_WARNING, "Next receipt is rejected. Waiting until current limits is over.");
+        DAP_DEL_Z(a_grace->usage->receipt_next);
+        memset(&a_grace->usage->tx_cond_hash, 0, sizeof(a_grace->usage->tx_cond_hash));
+        DAP_DELETE(a_grace->request);
+        DAP_DELETE(a_grace);
+        return;
+    }
+
+    if (a_err.code) {
+        if(l_ch)
+            dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &a_err, sizeof (a_err));
+        if (a_grace->usage->service && a_grace->usage->service->callbacks.response_error)
+            a_grace->usage->service->callbacks.response_error(a_grace->usage->service, 0, NULL, &a_err, sizeof(a_err));
+    }
+
+    if (a_grace->usage) {   // add client pkey hash to banlist
+        a_grace->usage->is_active = false;
+        if (a_grace->usage->service) {
+            dap_chain_net_srv_banlist_item_t *l_item = NULL;
+            pthread_mutex_lock(&a_grace->usage->service->banlist_mutex);
+            HASH_FIND(hh, a_grace->usage->service->ban_list, &a_grace->usage->client_pkey_hash, sizeof(dap_chain_hash_fast_t), l_item);
+            if (l_item)
+                pthread_mutex_unlock(&a_grace->usage->service->banlist_mutex);
+            else {
+                l_item = DAP_NEW_Z(dap_chain_net_srv_banlist_item_t);
+                l_item->client_pkey_hash = a_grace->usage->client_pkey_hash;
+                l_item->ht_mutex = &a_grace->usage->service->banlist_mutex;
+                l_item->ht_head = &a_grace->usage->service->ban_list;
+                HASH_ADD(hh, a_grace->usage->service->ban_list, client_pkey_hash, sizeof(dap_chain_hash_fast_t), l_item);
+                pthread_mutex_unlock(&a_grace->usage->service->banlist_mutex);
+                dap_timerfd_start(a_grace->usage->service->grace_period * 1000, (dap_timerfd_callback_t)s_unban_client, l_item);
+            }
+        }
+
+    } else if (l_srv_session->usage_active)
+        dap_chain_net_srv_usage_delete(l_srv_session);
+    DAP_DELETE(a_grace->request);
+    DAP_DELETE(a_grace);
+}
+
+// TODO: move this to net_srv
+static usages_in_grace_t * s_grace_table = NULL;
+static pthread_mutex_t s_ht_grace_table_mutex;
 /**
  * @brief dap_stream_ch_chain_net_init
  * @return
@@ -73,6 +134,7 @@ int dap_stream_ch_chain_net_srv_init(void)
 {
     log_it(L_NOTICE,"Chain network services channel initialized");
     dap_stream_ch_proc_add(dap_stream_ch_chain_net_srv_get_id(),s_stream_ch_new,s_stream_ch_delete,s_stream_ch_packet_in,s_stream_ch_packet_out);
+    pthread_mutex_init(&s_ht_grace_table_mutex, NULL);
 
     return 0;
 }
@@ -105,7 +167,6 @@ void s_stream_ch_new(dap_stream_ch_t* a_ch , void* arg)
         log_it(L_ERROR, "Session inheritor is already present!");
 
     dap_chain_net_srv_call_opened_all( a_ch);
-
 }
 
 
@@ -120,6 +181,8 @@ void s_stream_ch_delete(dap_stream_ch_t* a_ch , void* a_arg)
     (void) a_arg;
     log_it(L_DEBUG, "Stream ch chain net srv delete");
     dap_chain_net_srv_call_closed_all( a_ch);
+    if (a_ch->stream->session && a_ch->stream->session->_inheritor)
+        dap_chain_net_srv_stream_session_delete( a_ch->stream->session );
     DAP_DEL_Z(a_ch->internal);
 }
 
@@ -132,29 +195,41 @@ static bool s_unban_client(dap_chain_net_srv_banlist_item_t *a_item)
     return false;
 }
 
-static bool s_grace_period_control(dap_chain_net_srv_grace_t *a_grace)
+void dap_stream_ch_chain_net_srv_tx_cond_added_cb(void *a_arg, dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx)
 {
-    assert(a_grace);
+    UNUSED(a_ledger);
+    UNUSED(a_arg);
+    // TODO: 1. Get net_srv by srv_uid from tx_cond
+    // 2. Get usages in grace HT from service
+    usages_in_grace_t *l_item = NULL;
+    dap_hash_fast_t tx_cond_hash = {};
+    dap_hash_fast((void*)a_tx, dap_chain_datum_tx_get_size(a_tx), &tx_cond_hash);
+    pthread_mutex_lock(&s_ht_grace_table_mutex);
+    HASH_FIND(hh, s_grace_table, &tx_cond_hash, sizeof(dap_hash_fast_t), l_item);
+    if (l_item){
+        log_it(L_INFO, "Found tx in ledger by notify. Finish grace.");
+        // Stop timer
+        dap_timerfd_delete_mt(l_item->grace->stream_worker->worker, l_item->grace->timer_es_uuid);
+        // finish grace
+        s_grace_period_finish(l_item);
+    }
+    pthread_mutex_unlock(&s_ht_grace_table_mutex);
+}
+
+static void s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_pkt_request_t * a_request, size_t a_request_size)
+{
+    assert(a_ch);
     dap_stream_ch_chain_net_srv_pkt_error_t l_err;
     memset(&l_err, 0, sizeof(l_err));
     dap_chain_net_srv_t * l_srv = NULL;
-    dap_chain_net_srv_usage_t *l_usage = NULL;
-    dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(a_grace->stream_worker, a_grace->ch_uuid);
 
-    if (!l_ch)
-        goto free_exit;
+    dap_chain_net_srv_stream_session_t *l_srv_session = a_ch->stream && a_ch->stream->session ?
+                                                        (dap_chain_net_srv_stream_session_t *)a_ch->stream->session->_inheritor : NULL;
+    l_srv = dap_chain_net_srv_get( a_request->hdr.srv_uid );
+    dap_chain_net_t * l_net = dap_chain_net_by_id( a_request->hdr.net_id );
 
-    dap_chain_net_srv_stream_session_t *l_srv_session = l_ch && l_ch->stream && l_ch->stream->session ?
-                                                        (dap_chain_net_srv_stream_session_t *)l_ch->stream->session->_inheritor : NULL;
-    if (!l_srv_session)
-        goto free_exit;
-
-    dap_stream_ch_chain_net_srv_pkt_request_t *l_request = a_grace->request;
-    l_srv = dap_chain_net_srv_get( l_request->hdr.srv_uid );
-    dap_chain_net_t * l_net = dap_chain_net_by_id( l_request->hdr.net_id );
-
-    l_err.net_id.uint64 = l_request->hdr.net_id.uint64;
-    l_err.srv_uid.uint64 = l_request->hdr.srv_uid.uint64;
+    l_err.net_id.uint64 = a_request->hdr.net_id.uint64;
+    l_err.srv_uid.uint64 = a_request->hdr.srv_uid.uint64;
 
     if ( ! l_net ) // Network not found
         l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_NOT_FOUND;
@@ -162,83 +237,149 @@ static bool s_grace_period_control(dap_chain_net_srv_grace_t *a_grace)
     if ( ! l_srv ) // Service not found
         l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_SERVICE_NOT_FOUND;
 
-    if ( l_err.code ){
-        goto free_exit;
+    if ( l_err.code || !l_srv_session){
+        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));
+        return;
+    }
+
+    dap_chain_net_srv_usage_t *l_usage = NULL;
+    l_usage = dap_chain_net_srv_usage_add(l_srv_session, l_net, l_srv);
+    if ( !l_usage ){ // Usage can't add
+        log_it( L_WARNING, "Can't add usage");
+        l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_CANT_ADD_USAGE;
+        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));
+        return;
+    }
+
+    l_err.usage_id = l_usage->id;
+    // Create one client
+    l_usage->client = DAP_NEW_Z( dap_chain_net_srv_client_remote_t);
+    l_usage->client->stream_worker = a_ch->stream_worker;
+    l_usage->client->ch = a_ch;
+    l_usage->client->session_id = a_ch->stream->session->id;
+    l_usage->client->ts_created = time(NULL);
+    l_usage->tx_cond_hash = a_request->hdr.tx_cond;
+    l_usage->ts_created = time(NULL);
+    l_usage->net = l_net;
+    l_usage->service = l_srv;
+
+
+    dap_chain_net_srv_grace_t *l_grace = DAP_NEW_Z(dap_chain_net_srv_grace_t);
+    l_grace->request = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_request_t, a_request_size);
+    memcpy(l_grace->request, a_request, a_request_size);
+    l_grace->request_size = a_request_size;
+    l_grace->ch_uuid = a_ch->uuid;
+    l_grace->stream_worker = a_ch->stream_worker;
+    l_grace->usage = l_usage;
+
+    if (l_srv->pricelist){
+        // not free service
+        s_grace_period_start(l_grace);
+    } else {
+        // Start service for free
+        log_it( L_INFO, "Service provide for free");
+        l_grace->usage->is_free = true;
+        size_t l_success_size = sizeof (dap_stream_ch_chain_net_srv_pkt_success_hdr_t );
+        dap_stream_ch_chain_net_srv_pkt_success_t *l_success = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_success_t,
+                                                                              l_success_size);
+        l_success->hdr.usage_id = l_usage->id;
+        l_success->hdr.net_id.uint64 = l_usage->net->pub.id.uint64;
+        l_success->hdr.srv_uid.uint64 = l_usage->service->uid.uint64;
+        dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_SUCCESS, l_success, l_success_size);
+        if (l_usage->service->callbacks.response_success)
+            l_usage->service->callbacks.response_success(l_usage->service, l_usage->id,  l_usage->client, NULL, 0);
+        DAP_DELETE(l_success);
+    }
+    return;
+}
+
+static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace)
+{
+    assert(a_grace);
+    dap_stream_ch_chain_net_srv_pkt_error_t l_err;
+    memset(&l_err, 0, sizeof(l_err));
+    dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(a_grace->stream_worker, a_grace->ch_uuid);
+
+    if (!l_ch){
+        s_grace_error(a_grace, l_err);
+        return;
     }
 
-    dap_ledger_t * l_ledger =l_net->pub.ledger;
+    dap_chain_net_t * l_net = a_grace->usage->net;
+
+    l_err.net_id.uint64 = l_net->pub.id.uint64;
+    l_err.srv_uid.uint64 = a_grace->usage->service->uid.uint64;
+
+    dap_ledger_t * l_ledger = l_net->pub.ledger;
     dap_chain_datum_tx_t * l_tx = NULL;
     dap_chain_tx_out_cond_t * l_tx_out_cond = NULL;
-    bool l_grace_start = false;
-    if (l_srv->pricelist ){ // Is present pricelist, not free service
+    dap_chain_net_srv_price_t * l_price = NULL;
+    if ( !l_ledger ){ // No ledger
+        log_it( L_WARNING, "No Ledger");
+        l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_NO_LEDGER ;
+        s_grace_error(a_grace, l_err);
+        return;
+    }
 
-        if ( !l_ledger ){ // No ledger
-            log_it( L_WARNING, "No Ledger");
-            l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_NO_LEDGER ;
-            goto free_exit;
-        }
+    l_tx = a_grace->usage->is_waiting_new_tx_cond ? NULL : dap_chain_ledger_tx_find_by_hash(l_ledger, &a_grace->usage->tx_cond_hash);
+    if ( ! l_tx ){ // No tx cond transaction, start grace-period
+        a_grace->usage->is_grace = true;
 
-        l_tx = dap_chain_ledger_tx_find_by_hash( l_ledger,& l_request->hdr.tx_cond );
-        if ( ! l_tx ){ // No tx cond transaction
-            if (a_grace->usage) {   // marker for reentry to function
-                log_it( L_WARNING, "No tx cond transaction");
-                l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_FOUND ;
-                goto free_exit;
-            } else
-                l_grace_start = true;
-        }
-        if (!l_grace_start) {
-            int l_tx_out_cond_size =0;
-            l_tx_out_cond = (dap_chain_tx_out_cond_t *)
-                    dap_chain_datum_tx_item_get(l_tx, NULL, TX_ITEM_TYPE_OUT_COND, &l_tx_out_cond_size );
+        l_price = DAP_NEW_Z(dap_chain_net_srv_price_t);
+                        memcpy(l_price, a_grace->usage->service->pricelist, sizeof(*l_price));
 
-            if ( ! l_tx_out_cond ) { // No conditioned output
-                log_it( L_WARNING, "No conditioned output");
-                l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NO_COND_OUT ;
-                goto free_exit;
-            }
+        a_grace->usage->price = l_price;
 
-            // Check cond output if it equesl or not to request
-            if (!dap_chain_net_srv_uid_compare(l_tx_out_cond->header.srv_uid, l_request->hdr.srv_uid)) {
-                log_it( L_WARNING, "Wrong service uid in request, tx expect to close its output with 0x%016"DAP_UINT64_FORMAT_X,
-                        l_tx_out_cond->header.srv_uid.uint64 );
-                l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_WRONG_SRV_UID  ;
-                goto free_exit;
-            }
+        if (!a_grace->usage->receipt){
+            a_grace->usage->receipt = dap_chain_net_srv_issue_receipt(a_grace->usage->service, a_grace->usage->price, NULL, 0);
+            dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST,
+                                       a_grace->usage->receipt, a_grace->usage->receipt->size);
         }
-    }
-    if (!a_grace->usage) {
-        l_usage = dap_chain_net_srv_usage_add(l_srv_session, l_net, l_srv);
-        if ( !l_usage ){ // Usage can't add
-            log_it( L_WARNING, "Can't add usage");
-            l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_CANT_ADD_USAGE;
-            goto free_exit;
+        usages_in_grace_t *l_item = DAP_NEW_Z_SIZE(usages_in_grace_t, sizeof(usages_in_grace_t));
+        l_item->grace = a_grace;
+        l_item->tx_cond_hash = a_grace->usage->tx_cond_hash;
+
+        pthread_mutex_lock(&s_ht_grace_table_mutex);
+        HASH_ADD(hh, s_grace_table, tx_cond_hash, sizeof(dap_hash_fast_t), l_item);
+        pthread_mutex_unlock(&s_ht_grace_table_mutex);
+        a_grace->timer_es_uuid = dap_timerfd_start_on_worker(a_grace->stream_worker->worker, a_grace->usage->service->grace_period * 1000,
+                                                             (dap_timerfd_callback_t)s_grace_period_finish, l_item)->esocket_uuid;
+
+
+    } else { // Start srvice in normal pay mode
+        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 );
+
+        if ( ! l_tx_out_cond ) { // No conditioned output
+            log_it( L_WARNING, "No conditioned output");
+            l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NO_COND_OUT ;
+            s_grace_error(a_grace, l_err);
+            return;
         }
 
-        l_err.usage_id = l_usage->id;
+        // Check cond output if it equesl or not to request
+        if (!dap_chain_net_srv_uid_compare(l_tx_out_cond->header.srv_uid, a_grace->usage->service->uid)) {
+            log_it( L_WARNING, "Wrong service uid in request, tx expect to close its output with 0x%016"DAP_UINT64_FORMAT_X,
+                    l_tx_out_cond->header.srv_uid.uint64 );
+            l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_WRONG_SRV_UID  ;
+            s_grace_error(a_grace, l_err);
+            return;
+        }
 
-        // Create one client
-        l_usage->client = DAP_NEW_Z( dap_chain_net_srv_client_remote_t);
-        l_usage->client->stream_worker = l_ch->stream_worker;
-        l_usage->client->ch = l_ch;
-        l_usage->client->session_id = l_ch->stream->session->id;
-        l_usage->client->ts_created = time(NULL);
-        l_usage->tx_cond = l_tx;
-        l_usage->tx_cond_hash = l_request->hdr.tx_cond;
-        l_usage->ts_created = time(NULL);
-    } else {
-        l_usage = a_grace->usage;
-        l_usage->tx_cond = l_tx;
-    }
-    dap_chain_net_srv_price_t * l_price = NULL;
-    const char * l_ticker = NULL;
-    if (l_srv->pricelist && !l_grace_start) {
-        l_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(l_ledger, &l_request->hdr.tx_cond );
-        dap_stpcpy(l_usage->token_ticker, l_ticker);
+        const char * l_ticker = NULL;
+        l_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(l_ledger, &a_grace->usage->tx_cond_hash);
+        dap_stpcpy(a_grace->usage->token_ticker, l_ticker);
 
         dap_chain_net_srv_price_t *l_price_tmp;
-        DL_FOREACH(l_srv->pricelist, l_price_tmp) {
-            if (l_price_tmp->net->pub.id.uint64                 == l_request->hdr.net_id.uint64
+        DL_FOREACH(a_grace->usage->service->pricelist, l_price_tmp) {
+            if (l_price_tmp && l_price_tmp->net->pub.id.uint64                 == a_grace->usage->net->pub.id.uint64
                 && dap_strcmp(l_price_tmp->token, l_ticker)     == 0
                 && l_price_tmp->units_uid.enm                   == l_tx_out_cond->subtype.srv_pay.unit.enm
                 )//&& (l_price_tmp->value_datoshi/l_price_tmp->units)  < l_tx_out_cond->subtype.srv_pay.header.unit_price_max_datoshi)
@@ -251,102 +392,232 @@ static bool s_grace_period_control(dap_chain_net_srv_grace_t *a_grace)
             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 );
             l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN;
-            goto free_exit;
+            s_grace_error(a_grace, l_err);
+            return;
+        }
+        a_grace->usage->price = l_price;
+        int ret;
+        if ((ret = a_grace->usage->service->callbacks.requested(a_grace->usage->service, a_grace->usage->id, a_grace->usage->client, a_grace->request, a_grace->request_size)) != 0) {
+            log_it( L_WARNING, "Request canceled by service callback, return code %d", ret);
+            l_err.code = (uint32_t) ret ;
+            s_grace_error(a_grace, l_err);
+            return;
         }
-    }
-    int ret;
-    if ((ret = l_srv->callbacks.requested(l_srv, l_usage->id, l_usage->client, l_request, a_grace->request_size)) != 0) {
-        log_it( L_WARNING, "Request canceled by service callback, return code %d", ret);
-        l_err.code = (uint32_t) ret ;
-        goto free_exit;
-    }
 
-    if ( l_srv->pricelist) {
-        if (l_price || l_grace_start) {
-            if (l_price) {
-                if (a_grace->usage) {
-                    DAP_DELETE(l_usage->price);
-                }
-            } else {
-                l_price = DAP_NEW_Z(dap_chain_net_srv_price_t);
-                memcpy(l_price, l_srv->pricelist, sizeof(*l_price));
-                l_price->value_datoshi = uint256_0;
-            }
-            l_usage->price = l_price;
-            if (l_usage->receipt_next){
-                DAP_DEL_Z(l_usage->receipt_next);
-                l_usage->receipt_next = dap_chain_net_srv_issue_receipt(l_usage->service, l_usage->price, NULL, 0);
-            }else{
-                dap_chain_net_srv_price_t l_b_price = *l_usage->price;
-                if (l_grace_start || a_grace->usage){
-                    l_b_price.units *= 2;
-                    MULT_256_256(l_b_price.value_datoshi, GET_256_FROM_64((uint64_t)2), &l_b_price.value_datoshi);
-                }
-                l_usage->receipt = dap_chain_net_srv_issue_receipt(l_usage->service, &l_b_price, NULL, 0);
-                dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST,
-                                           l_usage->receipt, l_usage->receipt->size);
-            }
+        if (a_grace->usage->receipt_next){
+            DAP_DEL_Z(a_grace->usage->receipt_next);
+            a_grace->usage->receipt_next = dap_chain_net_srv_issue_receipt(a_grace->usage->service, a_grace->usage->price, NULL, 0);
         }else{
-            l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_PRICE_NOT_FOUND ;
-            goto free_exit;
+            a_grace->usage->receipt = dap_chain_net_srv_issue_receipt(a_grace->usage->service, a_grace->usage->price, NULL, 0);
+            dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST,
+                                       a_grace->usage->receipt, a_grace->usage->receipt->size);
         }
-    // If we a here we passed all the checks, wow, now if we're not for free we request the signature.
-    } else{
-        log_it( L_INFO, "Service provide for free");
-        l_usage->is_free = true;
-        size_t l_success_size = sizeof (dap_stream_ch_chain_net_srv_pkt_success_hdr_t );
-        dap_stream_ch_chain_net_srv_pkt_success_t *l_success = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_success_t,
-                                                                              l_success_size);
-        l_success->hdr.usage_id = l_usage->id;
-        l_success->hdr.net_id.uint64 = l_usage->net->pub.id.uint64;
-        l_success->hdr.srv_uid.uint64 = l_usage->service->uid.uint64;
-        dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_SUCCESS, l_success, l_success_size);
-        if (l_usage->service->callbacks.response_success)
-            l_usage->service->callbacks.response_success(l_usage->service, l_usage->id,  l_usage->client, NULL, 0);
-        DAP_DELETE(l_success);
-    }
-    if (l_grace_start) {
-        l_usage->is_grace = true;
-        a_grace->usage = l_usage;
-        dap_timerfd_start_on_worker(a_grace->stream_worker->worker, l_srv->grace_period * 1000,
-                                    (dap_timerfd_callback_t)s_grace_period_control, a_grace);
-        return false;
-    } else {
+
         DAP_DELETE(a_grace->request);
         DAP_DELETE(a_grace);
-        l_usage->is_grace = false;
+
+    }
+}
+
+static bool s_grace_period_finish(usages_in_grace_t *a_grace_item)
+{
+    assert(a_grace_item);
+    dap_stream_ch_chain_net_srv_pkt_error_t l_err;
+    memset(&l_err, 0, sizeof(l_err));
+    dap_chain_net_srv_grace_t *l_grace = a_grace_item->grace;
+
+    dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(l_grace->stream_worker, l_grace->ch_uuid);
+
+    if (l_grace->usage->price && !l_grace->usage->receipt_next){ // if first grace delete price and set actual
+        DAP_DEL_Z(l_grace->usage->price);
+    }
+
+    if (!l_ch){
+        s_grace_error(l_grace, l_err);
+        HASH_DEL(s_grace_table, a_grace_item);
+        DAP_DEL_Z(a_grace_item);
         return false;
     }
-free_exit:
-    if (l_err.code) {
-        if(l_ch)
-            dap_stream_ch_pkt_write_unsafe(l_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));
+
+    if (l_grace->usage->is_waiting_new_tx_cond){
+        log_it(L_INFO, "No new tx cond!");
+        s_grace_error(l_grace, l_err);
+        l_grace->usage->is_waiting_new_tx_cond = false;
+        HASH_DEL(s_grace_table, a_grace_item);
+        DAP_DEL_Z(a_grace_item);
+        return false;
     }
-    if (a_grace->usage) {   // add client pkey hash to banlist
-        a_grace->usage->is_active = false;
-        if (l_srv) {
-            dap_chain_net_srv_banlist_item_t *l_item = NULL;
-            pthread_mutex_lock(&l_srv->banlist_mutex);
-            HASH_FIND(hh, l_srv->ban_list, &a_grace->usage->client_pkey_hash, sizeof(dap_chain_hash_fast_t), l_item);
-            if (l_item)
-                pthread_mutex_unlock(&l_srv->banlist_mutex);
-            else {
-                l_item = DAP_NEW_Z(dap_chain_net_srv_banlist_item_t);
-                l_item->client_pkey_hash = a_grace->usage->client_pkey_hash;
-                l_item->ht_mutex = &l_srv->banlist_mutex;
-                l_item->ht_head = &l_srv->ban_list;
-                HASH_ADD(hh, l_srv->ban_list, client_pkey_hash, sizeof(dap_chain_hash_fast_t), l_item);
-                pthread_mutex_unlock(&l_srv->banlist_mutex);
-                dap_timerfd_start(l_srv->grace_period * 1000, (dap_timerfd_callback_t)s_unban_client, l_item);
+
+    dap_chain_net_t * l_net = l_grace->usage->net;
+
+    l_err.net_id.uint64 = l_net->pub.id.uint64;
+    l_err.srv_uid.uint64 = l_grace->usage->service->uid.uint64;
+
+    dap_ledger_t * l_ledger = l_net->pub.ledger;
+    dap_chain_datum_tx_t * l_tx = NULL;
+    dap_chain_tx_out_cond_t * l_tx_out_cond = NULL;
+
+    if ( !l_ledger ){ // No ledger
+        log_it( L_WARNING, "No Ledger");
+        l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_NO_LEDGER ;
+        s_grace_error(l_grace, l_err);
+        HASH_DEL(s_grace_table, a_grace_item);
+        DAP_DEL_Z(a_grace_item);
+        return false;
+    }
+    log_it(L_INFO, "Grace period is over! Check tx in ledger.");
+    l_tx = dap_chain_ledger_tx_find_by_hash(l_ledger, &l_grace->usage->tx_cond_hash);
+    if ( ! l_tx ){ // No tx cond transaction, start grace-period
+        log_it( L_WARNING, "No tx cond transaction");
+        l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_FOUND ;
+        s_grace_error(l_grace, l_err);
+        HASH_DEL(s_grace_table, a_grace_item);
+        DAP_DEL_Z(a_grace_item);
+        return false;
+    } else { // Start srvice in normal pay mode
+        log_it(L_INFO, "Tx is found in ledger.");
+        l_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 );
+
+        if ( ! l_tx_out_cond ) { // No conditioned output
+            log_it( L_WARNING, "No conditioned output");
+            l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NO_COND_OUT ;
+            s_grace_error(l_grace, l_err);
+            HASH_DEL(s_grace_table, a_grace_item);
+            DAP_DEL_Z(a_grace_item);
+            return false;
+        }
+
+        // Check cond output if it equesl or not to request
+        if (!dap_chain_net_srv_uid_compare(l_tx_out_cond->header.srv_uid, l_grace->usage->service->uid)) {
+            log_it( L_WARNING, "Wrong service uid in request, tx expect to close its output with 0x%016"DAP_UINT64_FORMAT_X,
+                   l_tx_out_cond->header.srv_uid.uint64 );
+            l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_WRONG_SRV_UID  ;
+            s_grace_error(l_grace, l_err);
+            HASH_DEL(s_grace_table, a_grace_item);
+            DAP_DEL_Z(a_grace_item);
+            return false;
+        }
+
+        dap_chain_net_srv_price_t * l_price = NULL;
+        const char * l_ticker = NULL;
+        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 && l_price_tmp->net->pub.id.uint64                 == l_grace->usage->net->pub.id.uint64
+                && dap_strcmp(l_price_tmp->token, l_ticker)     == 0
+                && l_price_tmp->units_uid.enm                   == l_tx_out_cond->subtype.srv_pay.unit.enm
+                )//&& (l_price_tmp->value_datoshi/l_price_tmp->units)  < l_tx_out_cond->subtype.srv_pay.header.unit_price_max_datoshi)
+            {
+                l_price = l_price_tmp;
+                break;
+            }
+        }
+        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 );
+            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);
+            HASH_DEL(s_grace_table, a_grace_item);
+            DAP_DEL_Z(a_grace_item);
+            return false;
+        }
+
+        l_grace->usage->price = l_price;
+
+        int ret;
+        if ((ret = l_grace->usage->service->callbacks.requested(l_grace->usage->service, l_grace->usage->id, l_grace->usage->client, l_grace->request, l_grace->request_size)) != 0) {
+            log_it( L_WARNING, "Request canceled by service callback, return code %d", ret);
+            l_err.code = (uint32_t) ret ;
+            s_grace_error(l_grace, l_err);
+            HASH_DEL(s_grace_table, a_grace_item);
+            DAP_DEL_Z(a_grace_item);
+            return false;
+        }
+
+        // make receipt or tx
+        char *l_receipt_hash_str;
+        dap_chain_datum_tx_receipt_t *l_receipt = NULL;
+        if (l_grace->usage->receipt_next){
+            l_receipt = l_grace->usage->receipt_next;
+        } else if (l_grace->usage->receipt){
+            l_receipt = l_grace->usage->receipt;
+        } else {
+            // Send error???
+        }
+        size_t l_receipt_size = l_receipt->size;
+
+        // 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( l_receipt, l_receipt_size, 1);
+        if ( ! l_receipt_sign ){
+            log_it(L_WARNING, "Tx already in chain, but receipt is not signed by client. Finish grace and wait receipt sign responce.");
+            s_grace_error(l_grace, l_err);
+            HASH_DEL(s_grace_table, a_grace_item);
+            DAP_DEL_Z(a_grace_item);
+            return false;
+        }
+        dap_get_data_hash_str_static(l_receipt, l_receipt_size, l_receipt_hash_str);
+        dap_global_db_set("local.receipts", l_receipt_hash_str, l_receipt, l_receipt_size, false, NULL, NULL);
+            // Form input transaction
+        char *l_hash_str = dap_hash_fast_to_str_new(&l_grace->usage->tx_cond_hash);
+        log_it(L_NOTICE, "Trying create input tx cond from tx %s with active receipt", l_hash_str);
+        DAP_DEL_Z(l_hash_str);
+        dap_chain_addr_t *l_wallet_addr = dap_chain_wallet_get_addr(l_grace->usage->price->wallet, l_grace->usage->net->pub.id);
+        int ret_status = 0;
+        char *l_tx_in_hash_str = dap_chain_mempool_tx_create_cond_input(l_grace->usage->net, &l_grace->usage->tx_cond_hash, l_wallet_addr,
+                                                                        dap_chain_wallet_get_key(l_grace->usage->price->wallet, 0),
+                                                                        l_receipt, "hex", &ret_status);
+        DAP_DEL_Z(l_wallet_addr);
+        if (!ret_status) {
+            dap_chain_hash_fast_from_str(l_tx_in_hash_str, &l_grace->usage->tx_cond_hash);
+            log_it(L_NOTICE, "Formed tx %s for input with active receipt", l_tx_in_hash_str);
+            DAP_DELETE(l_tx_in_hash_str);
+
+        }else{
+            if(ret_status == DAP_CHAIN_MEMPOOl_RET_STATUS_NOT_ENOUGH){
+//                memset(&l_grace->usage->tx_cond_hash, 0, sizeof(l_grace->usage->tx_cond_hash));
+//                DAP_DEL_Z(l_grace->usage->receipt_next);
+                log_it(L_ERROR, "Tx cond have not enough funds");
+                dap_chain_net_srv_grace_t* l_grace_new = DAP_NEW_Z(dap_chain_net_srv_grace_t);
+                // Parse the request
+                l_grace_new->request = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_request_t, sizeof(dap_stream_ch_chain_net_srv_pkt_request_t));
+                l_grace_new->request->hdr.net_id = a_grace_item->grace->usage->net->pub.id;
+                memcpy(l_grace_new->request->hdr.token, a_grace_item->grace->usage->token_ticker, strlen(a_grace_item->grace->usage->token_ticker));
+                l_grace_new->request->hdr.srv_uid = a_grace_item->grace->usage->service->uid;
+                l_grace_new->request->hdr.tx_cond = a_grace_item->grace->usage->tx_cond_hash;
+                l_grace_new->request_size = sizeof(dap_stream_ch_chain_net_srv_pkt_request_t);
+                l_grace_new->ch_uuid = a_grace_item->grace->usage->client->ch->uuid;
+                l_grace_new->stream_worker = a_grace_item->grace->usage->client->ch->stream_worker;
+                l_grace_new->usage = a_grace_item->grace->usage;
+                l_grace_new->usage->is_waiting_new_tx_cond = true;
+                s_grace_period_start(l_grace_new);
+
+                l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ENOUGH;
+                dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err));
+
+            }else{
+                log_it(L_ERROR, "Can't create input tx cond transaction!");
+                memset(&l_grace->usage->tx_cond_hash, 0, sizeof(l_grace->usage->tx_cond_hash));
+                if (l_grace->usage->receipt_next){
+                    DAP_DEL_Z(l_grace->usage->receipt_next);
+                } else if (l_grace->usage->receipt){
+                    DAP_DEL_Z(l_grace->usage->receipt);
+                }
+                l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_SERVICE_NOT_FOUND;
+                dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err));
+                if (l_grace->usage->service->callbacks.response_error)
+                    l_grace->usage->service->callbacks.response_error(l_grace->usage->service,l_grace->usage->id, l_grace->usage->client,&l_err,sizeof (l_err));
             }
         }
     }
-    else if (l_usage)
-        dap_chain_net_srv_usage_delete(l_srv_session, l_usage);
-    DAP_DELETE(a_grace->request);
-    DAP_DELETE(a_grace);
+    l_grace->usage->is_grace = false;
+    DAP_DELETE(a_grace_item->grace->request);
+    DAP_DEL_Z(a_grace_item->grace);
+    HASH_DEL(s_grace_table, a_grace_item);
+    DAP_DEL_Z(a_grace_item);
     return false;
 }
 
@@ -434,26 +705,27 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
             log_it( L_WARNING, "Wrong request size, less than minimum");
             break;
         }
-        dap_chain_net_srv_grace_t *l_grace = DAP_NEW_Z(dap_chain_net_srv_grace_t);
-        // Parse the request
-        l_grace->request = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_request_t, l_ch_pkt->hdr.data_size);
-        memcpy(l_grace->request, l_ch_pkt->data, l_ch_pkt->hdr.data_size);
-        l_ch_chain_net_srv->srv_uid.uint64 = l_grace->request->hdr.srv_uid.uint64;
-        l_grace->request_size = l_ch_pkt->hdr.data_size;
-        l_grace->ch_uuid = a_ch->uuid;
-        l_grace->stream_worker = a_ch->stream_worker;
-        s_grace_period_control(l_grace);
+        dap_stream_ch_chain_net_srv_pkt_request_t *l_request = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_request_t, l_ch_pkt->hdr.data_size);
+        memcpy(l_request, l_ch_pkt->data, l_ch_pkt->hdr.data_size);
+        l_ch_chain_net_srv->srv_uid.uint64 = l_request->hdr.srv_uid.uint64;
+        s_service_start(a_ch, l_request, l_ch_pkt->hdr.data_size);
     } break; /* DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_REQUEST */
 
     case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_RESPONSE: { // Check receipt sign and make tx if success
-         if (l_ch_pkt->hdr.data_size < sizeof(dap_chain_receipt_info_t)) {
+        dap_chain_net_srv_usage_t * l_usage = l_srv_session->usage_active;
+        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));
+            if ( l_usage->receipt_next ){ // If we have receipt next
+                DAP_DEL_Z(l_usage->receipt_next);
+            }else if (l_usage->receipt ){ // If we sign first receipt
+                DAP_DEL_Z(l_usage->receipt);
+            }
             break;
         }
         dap_chain_datum_tx_receipt_t * l_receipt = (dap_chain_datum_tx_receipt_t *) l_ch_pkt->data;
         size_t l_receipt_size = l_ch_pkt->hdr.data_size;
-        dap_chain_net_srv_usage_t * l_usage = l_srv_session->usage_active;
+
         bool l_is_found = false;
         if ( l_usage->receipt_next ){ // If we have receipt next
             if ( memcmp(&l_usage->receipt_next->receipt_info, &l_receipt->receipt_info,sizeof (l_receipt->receipt_info) )==0 ){
@@ -488,9 +760,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
                                                                   &l_err, sizeof (l_err) );
                 break;
             }
-            int l_tx_out_cond_size =0;
-            l_tx_out_cond = (dap_chain_tx_out_cond_t *)dap_chain_datum_tx_item_get(l_usage->tx_cond, NULL,
-                                                                                   TX_ITEM_TYPE_OUT_COND, &l_tx_out_cond_size );
+            l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_usage->tx_cond, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY, NULL );
             if ( ! l_tx_out_cond ){ // No conditioned output
                 l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NO_COND_OUT ;
                 dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) );
@@ -519,6 +789,19 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
             HASH_FIND(hh, l_srv->ban_list, &l_usage->client_pkey_hash, sizeof(dap_chain_hash_fast_t), l_item);
             pthread_mutex_unlock(&l_srv->banlist_mutex);
             if (l_item) {   // client banned
+                    log_it(L_INFO, "Client pkey is banned!");
+                    usages_in_grace_t *l_grace_item = NULL;
+                    pthread_mutex_lock(&s_ht_grace_table_mutex);
+                    HASH_FIND(hh, s_grace_table, &l_usage->tx_cond_hash, sizeof(dap_hash_fast_t), l_grace_item);
+                    if (l_grace_item){
+                        // Stop timer
+                        dap_timerfd_delete_mt(l_grace_item->grace->stream_worker->worker, l_grace_item->grace->timer_es_uuid);
+                        // finish grace
+                        HASH_DEL(s_grace_table, l_grace_item);
+                        DAP_DEL_Z(l_grace_item);
+
+                    }
+                    pthread_mutex_unlock(&s_ht_grace_table_mutex);
                     l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_BANNED_PKEY_HASH ;
                     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_usage->service->callbacks.response_error)
@@ -579,26 +862,41 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
                     l_grace = DAP_NEW_Z(dap_chain_net_srv_grace_t);
                     UNUSED(l_grace);
                     // Parse the request
-//                    l_grace->request = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_request_t, sizeof(dap_stream_ch_chain_net_srv_pkt_request_t));
-//                    l_grace->request->hdr.net_id = l_usage->net->pub.id;
-//                    memcpy(l_grace->request->hdr.token, l_usage->token_ticker, strlen(l_usage->token_ticker));
-//                    l_grace->request->hdr.srv_uid = l_usage->service->uid;
-//                    l_grace->request->hdr.tx_cond = l_usage->tx_cond_hash;
-//                    l_ch_chain_net_srv->srv_uid.uint64 = l_grace->request->hdr.srv_uid.uint64;
-//                    l_grace->request_size = l_ch_pkt->hdr.data_size;
-//                    l_grace->ch_uuid = a_ch->uuid;
-//                    l_grace->stream_worker = a_ch->stream_worker;
-//                    s_grace_period_control(l_grace);
+                    l_grace->request = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_request_t, sizeof(dap_stream_ch_chain_net_srv_pkt_request_t));
+                    l_grace->request->hdr.net_id = l_usage->net->pub.id;
+                    memcpy(l_grace->request->hdr.token, l_usage->token_ticker, strlen(l_usage->token_ticker));
+                    l_grace->request->hdr.srv_uid = l_usage->service->uid;
+                    l_grace->request->hdr.tx_cond = l_usage->tx_cond_hash;
+                    l_ch_chain_net_srv->srv_uid.uint64 = l_grace->request->hdr.srv_uid.uint64;
+                    l_grace->request_size = l_ch_pkt->hdr.data_size;
+                    l_grace->ch_uuid = a_ch->uuid;
+                    l_grace->stream_worker = a_ch->stream_worker;
+                    l_grace->usage = l_usage;
+                    s_grace_period_start(l_grace);
+                    DAP_DELETE(l_tx_in_hash_str);
                     break;
                 case DAP_CHAIN_MEMPOOl_RET_STATUS_NOT_ENOUGH:
                     // TODO send new tx cond request
-                    memset(&l_usage->tx_cond_hash, 0, sizeof(l_usage->tx_cond_hash));
-                    DAP_DEL_Z(l_usage->receipt_next);
                     log_it(L_ERROR, "Tx cond have not enough funds");
+                    l_usage->is_waiting_new_tx_cond = true;
+                    l_grace = DAP_NEW_Z(dap_chain_net_srv_grace_t);
+                    // Parse the request
+                    l_grace->request = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_request_t, sizeof(dap_stream_ch_chain_net_srv_pkt_request_t));
+                    l_grace->request->hdr.net_id = l_usage->net->pub.id;
+                    memcpy(l_grace->request->hdr.token, l_usage->token_ticker, strlen(l_usage->token_ticker));
+                    l_grace->request->hdr.srv_uid = l_usage->service->uid;
+                    l_grace->request->hdr.tx_cond = l_usage->tx_cond_hash;
+                    l_ch_chain_net_srv->srv_uid.uint64 = l_grace->request->hdr.srv_uid.uint64;
+                    l_grace->request_size = l_ch_pkt->hdr.data_size;
+                    l_grace->ch_uuid = a_ch->uuid;
+                    l_grace->stream_worker = a_ch->stream_worker;
+                    l_grace->usage = l_usage;
+                    s_grace_period_start(l_grace);
                     l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ENOUGH;
                     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_usage->service->callbacks.response_error)
-//                            l_usage->service->callbacks.response_error(l_usage->service,l_usage->id, l_usage->client,&l_err,sizeof (l_err));
+                    if (l_usage->service->callbacks.response_error)
+                            l_usage->service->callbacks.response_error(l_usage->service,l_usage->id, l_usage->client,&l_err,sizeof (l_err));
+                    DAP_DELETE(l_tx_in_hash_str);
                     break;
                 case DAP_CHAIN_MEMPOOL_RET_STATUS_BAD_ARGUMENTS:
                 case DAP_CHAIN_MEMPOOl_RET_STATUS_WRONG_ADDR:
@@ -614,16 +912,17 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
                     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_usage->service->callbacks.response_error)
                             l_usage->service->callbacks.response_error(l_usage->service,l_usage->id, l_usage->client,&l_err,sizeof (l_err));
+                    DAP_DELETE(l_tx_in_hash_str);
                     break;
                 }
-
-
-                break;
+                if (!l_usage->is_grace)
+                    break;
             }
             l_success_size = sizeof(dap_stream_ch_chain_net_srv_pkt_success_hdr_t) + DAP_CHAIN_HASH_FAST_STR_SIZE;//sizeof(dap_chain_hash_fast_t);
         } else {
             l_success_size = sizeof(dap_stream_ch_chain_net_srv_pkt_success_hdr_t);
         }
+
         dap_stream_ch_chain_net_srv_pkt_success_t *l_success = DAP_NEW_STACK_SIZE(dap_stream_ch_chain_net_srv_pkt_success_t,
                                                                               l_success_size);
         memset(&l_success->hdr, 0, sizeof(l_success->hdr));
@@ -634,8 +933,9 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
 
         if (l_usage->is_grace){
             char *l_hash_str = dap_hash_fast_to_str_new(&l_usage->tx_cond_hash);
-            log_it(L_NOTICE, "Receipt is OK, but transaction %s can't be found. Start the grace period for %d seconds", l_hash_str,
-                   l_srv->grace_period);
+                log_it(L_NOTICE, "Receipt is OK, but tx transaction %s %s. Start the grace period for %d seconds", l_hash_str,
+                       l_usage->is_waiting_new_tx_cond ? "have no enough funds. New tx cond requested": "can't be found",
+                       l_srv->grace_period);
             DAP_DEL_Z(l_hash_str);
         }else {
             char *l_hash_str = dap_hash_fast_to_str_new(&l_usage->tx_cond_hash);
@@ -708,10 +1008,51 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
         dap_chain_net_srv_usage_t * l_usage = NULL;
         l_usage = l_srv_session->usage_active;
         dap_stream_ch_chain_net_srv_pkt_request_t* l_responce = (dap_stream_ch_chain_net_srv_pkt_request_t*)l_ch_pkt->data;
-        l_usage->tx_cond_hash = l_responce->hdr.tx_cond;
-        char *l_tx_in_hash_str = dap_chain_hash_fast_to_str_new(&l_usage->tx_cond_hash);
+
+        char *l_tx_in_hash_str = dap_chain_hash_fast_to_str_new(&l_responce->hdr.tx_cond);
         log_it(L_NOTICE, "Received new tx cond %s", l_tx_in_hash_str);
         DAP_DELETE(l_tx_in_hash_str);
+        l_usage->is_waiting_new_tx_cond = false;
+
+        usages_in_grace_t *l_curr_grace_item = NULL;
+        pthread_mutex_lock(&s_ht_grace_table_mutex);
+        HASH_FIND(hh, s_grace_table, &l_usage->tx_cond_hash, sizeof(dap_hash_fast_t), l_curr_grace_item);
+        pthread_mutex_unlock(&s_ht_grace_table_mutex);
+
+//        if (dap_hash_fast_compare(&l_responce->hdr.tx_cond, &l_usage->tx_cond_hash) || !l_usage->is_grace){ //check new tx not equals to old tx or tx waiting grace period is over
+//            // if equals delete receipt and tx and stop grace if running
+//            if (l_curr_grace_item){
+//                HASH_DEL(s_grace_table, l_curr_grace_item);
+//                dap_timerfd_delete_mt(l_curr_grace_item->grace->stream_worker->worker, l_curr_grace_item->grace->timer_es_uuid);
+//            }
+//            break;
+//        }
+
+        dap_chain_datum_tx_t *l_tx = dap_chain_ledger_tx_find_by_hash(l_usage->net->pub.ledger, &l_responce->hdr.tx_cond);
+        if (l_tx){
+            // Replace
+            if (l_curr_grace_item){
+                log_it(L_INFO, "Found tx in ledger by net tx responce handler. Finish waiting new tx grace period.");
+                // Stop timer
+                dap_timerfd_delete_mt(l_curr_grace_item->grace->stream_worker->worker, l_curr_grace_item->grace->timer_es_uuid);
+                // finish grace
+                l_usage->tx_cond_hash = l_responce->hdr.tx_cond;
+                l_curr_grace_item->grace->request->hdr.tx_cond = l_responce->hdr.tx_cond;
+                s_grace_period_finish(l_curr_grace_item);
+            }
+        }else{
+            if (l_curr_grace_item){
+                l_curr_grace_item->grace->usage->tx_cond_hash = l_responce->hdr.tx_cond;
+                l_curr_grace_item->grace->request->hdr.tx_cond = l_responce->hdr.tx_cond;
+                pthread_mutex_lock(&s_ht_grace_table_mutex);
+                HASH_DEL(s_grace_table, l_curr_grace_item);
+                l_curr_grace_item->tx_cond_hash = l_responce->hdr.tx_cond;
+                HASH_ADD(hh, s_grace_table, tx_cond_hash, sizeof(dap_hash_fast_t), l_curr_grace_item);
+                pthread_mutex_unlock(&s_ht_grace_table_mutex);
+            }
+        }
+
+
         size_t l_success_size = sizeof (dap_stream_ch_chain_net_srv_pkt_success_hdr_t );
         dap_stream_ch_chain_net_srv_pkt_success_t *l_success = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_success_t,
                                                                               l_success_size);
diff --git a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.h b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.h
index 53490cc0c59594dc5215bceb4549146935108c6c..649a749c21f00447d3b8d18b9f27801043aa0b1c 100644
--- a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.h
+++ b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.h
@@ -29,6 +29,16 @@
 #include "dap_stream_ch_pkt.h"
 #include "dap_chain_common.h"
 
+#include "dap_chain.h"
+#include "dap_chain_datum_tx.h"
+#include "dap_chain_datum_tx_in.h"
+#include "dap_chain_datum_tx_in_cond.h"
+#include "dap_chain_datum_tx_out.h"
+#include "dap_chain_datum_tx_out_cond.h"
+#include "dap_chain_datum_tx_receipt.h"
+#include "dap_chain_mempool.h"
+#include "dap_common.h"
+
 typedef struct dap_stream_ch_chain_net_srv dap_stream_ch_chain_net_srv_t;
 
 typedef void (*dap_stream_ch_chain_net_srv_callback_packet_t)(dap_stream_ch_chain_net_srv_t *, uint8_t,
@@ -46,3 +56,5 @@ typedef struct dap_stream_ch_chain_net_srv {
 
 uint8_t dap_stream_ch_chain_net_srv_get_id();
 int dap_stream_ch_chain_net_srv_init(void);
+
+void dap_stream_ch_chain_net_srv_tx_cond_added_cb(void *a_arg, dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx);
diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
index 249208360d712c6eab023ff04caebf3804946c5d..8bc3fbf1c0277d30706a22793ec1857b993eef69 100644
--- a/modules/consensus/esbocs/dap_chain_cs_esbocs.c
+++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
@@ -1087,6 +1087,10 @@ static void s_message_chain_add(dap_chain_esbocs_session_t *a_session,
                                 dap_chain_hash_fast_t *a_message_hash,
                                 dap_chain_addr_t *a_signing_addr)
 {
+    if (NULL == a_message) {
+        log_it(L_ERROR, "Argument is NULL for s_message_chain_add");
+        return;
+    }
     dap_chain_esbocs_round_t *l_round = &a_session->cur_round;
     dap_chain_esbocs_message_item_t *l_message_item = DAP_NEW_Z(dap_chain_esbocs_message_item_t);
     if (!a_message_hash) {
@@ -1134,6 +1138,10 @@ static void s_session_candidate_submit(dap_chain_esbocs_session_t *a_session)
 static void s_session_candidate_verify(dap_chain_esbocs_session_t *a_session, dap_chain_block_t *a_candidate,
                                        size_t a_candidate_size, dap_hash_fast_t *a_candidate_hash)
 {
+    if (NULL == a_candidate) {
+        log_it(L_ERROR, "Argument is NULL for s_session_candidate_verify");
+        return;
+    }
     // Process early received messages
     for (dap_chain_esbocs_message_item_t *l_item = a_session->cur_round.message_items; l_item; l_item = l_item->hh.next) {
         if (l_item->unprocessed &&
@@ -1177,6 +1185,10 @@ static void s_session_candidate_verify(dap_chain_esbocs_session_t *a_session, da
 
 static void s_session_candidate_precommit(dap_chain_esbocs_session_t *a_session, dap_chain_esbocs_message_t *a_message)
 {
+    if (NULL == a_message) {
+        log_it(L_ERROR, "Argument is NULL for s_session_candidate_precommit");
+        return;
+    }
     bool l_cs_debug = PVT(a_session->esbocs)->debug;
     uint16_t l_cs_level = PVT(a_session->esbocs)->min_validators_count;
     byte_t *l_message_data = a_message->msg_n_sign;
@@ -1240,6 +1252,10 @@ static void s_session_candidate_precommit(dap_chain_esbocs_session_t *a_session,
 static bool s_session_candidate_to_chain(dap_chain_esbocs_session_t *a_session, dap_chain_hash_fast_t *a_candidate_hash,
                                          dap_chain_block_t *a_candidate, size_t a_candidate_size)
 {
+    if (NULL == a_candidate) {
+        log_it(L_ERROR, "Argument is NULL for s_session_candidate_to_chain");
+        return false;
+    }
     bool res = false;
     dap_chain_block_t *l_candidate = DAP_DUP_SIZE(a_candidate, a_candidate_size);
     dap_chain_atom_verify_res_t l_res = a_session->chain->callback_atom_add(a_session->chain, l_candidate, a_candidate_size);
diff --git a/modules/consensus/none/dap_chain_cs_none.c b/modules/consensus/none/dap_chain_cs_none.c
index 608ea742ffe1cd4c9cc7cc9ece14dc0e1858a2dd..8b7937825c51a1b6aa7e7e8134ccaa38b37045bb 100644
--- a/modules/consensus/none/dap_chain_cs_none.c
+++ b/modules/consensus/none/dap_chain_cs_none.c
@@ -239,7 +239,8 @@ void dap_chain_gdb_delete(dap_chain_t * a_chain)
     DAP_DELETE(l_gdb_priv->group_datums);
 
     DAP_DELETE(l_gdb);
-    a_chain->_inheritor = NULL;
+    if (a_chain)
+        a_chain->_inheritor = NULL;
 }
 
 /**
@@ -360,6 +361,10 @@ static size_t s_chain_callback_datums_pool_proc(dap_chain_t * a_chain, dap_chain
  */
 static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom, size_t a_atom_size)
 {
+    if (NULL == a_chain) {
+        log_it(L_WARNING, "Arguments is NULL for s_chain_callback_atom_add");
+        return ATOM_REJECT;
+    }
     dap_chain_gdb_t * l_gdb = DAP_CHAIN_GDB(a_chain);
     dap_chain_gdb_private_t *l_gdb_priv = PVT(l_gdb);
     dap_chain_datum_t *l_datum = (dap_chain_datum_t*) a_atom;
diff --git a/modules/mempool/dap_chain_mempool.c b/modules/mempool/dap_chain_mempool.c
index 562dbc76647670e61e86811e890870384605f6aa..c438ca2e17e297014a600981de0665e688c8fea6 100644
--- a/modules/mempool/dap_chain_mempool.c
+++ b/modules/mempool/dap_chain_mempool.c
@@ -828,19 +828,19 @@ char *dap_chain_mempool_tx_create_cond(dap_chain_net_t *a_net,
 
 char *dap_chain_mempool_base_tx_create(dap_chain_t *a_chain, dap_chain_hash_fast_t *a_emission_hash,
                                        dap_chain_id_t a_emission_chain_id, uint256_t a_emission_value, const char *a_ticker,
-                                       dap_enc_key_t *a_key_from, dap_chain_addr_t *a_addr_to, dap_cert_t **a_certs, size_t a_certs_count,
+                                       dap_chain_addr_t *a_addr_to, dap_enc_key_t *a_private_key,
                                        const char *a_hash_out_type, uint256_t a_value_fee)
 {
     uint256_t l_net_fee = {};
     uint256_t l_total_fee = a_value_fee;
     uint256_t l_value_need = a_emission_value;
     uint256_t l_value_transfer = {};
-    dap_chain_addr_t l_addr_fee = {};
-    dap_chain_addr_t* l_addr_from = NULL;
+    dap_chain_addr_t l_addr_to_fee = {};
+    dap_chain_addr_t l_addr_from_fee = {};
     dap_list_t *l_list_used_out;
     const char *l_native_ticker = dap_chain_net_by_id(a_chain->net_id)->pub.native_ticker;
     bool not_native = dap_strcmp(a_ticker, l_native_ticker);
-    bool l_net_fee_used = dap_chain_net_tx_get_fee(a_chain->net_id, &l_net_fee, &l_addr_fee);
+    bool l_net_fee_used = dap_chain_net_tx_get_fee(a_chain->net_id, &l_net_fee, &l_addr_to_fee);
     if(l_net_fee_used)
         SUM_256_256(l_total_fee,l_net_fee,&l_total_fee);
 
@@ -857,19 +857,16 @@ char *dap_chain_mempool_base_tx_create(dap_chain_t *a_chain, dap_chain_hash_fast
     }
     if (not_native)
     {
-        l_addr_from = DAP_NEW_Z(dap_chain_addr_t);
-        dap_chain_addr_fill_from_key(l_addr_from, a_key_from, a_chain->net_id);
-        if(!l_addr_from){
+        if (dap_chain_addr_fill_from_key(&l_addr_from_fee, a_private_key, a_chain->net_id) != 0 ) {
             log_it(L_WARNING,"Can't fill address from transfer");
             dap_chain_datum_tx_delete(l_tx);
             return NULL;
         }
             // list of transaction with 'out' items
         l_list_used_out = dap_chain_ledger_get_list_tx_outs_with_val(a_chain->ledger, l_native_ticker,
-                                                                                 l_addr_from, l_total_fee, &l_value_transfer);
+                                                                     &l_addr_from_fee, l_total_fee, &l_value_transfer);
         if (!l_list_used_out) {
             log_it(L_WARNING,"Not enough funds to transfer");
-            DAP_DEL_Z(l_addr_from);
             dap_chain_datum_tx_delete(l_tx);
             return NULL;
         }
@@ -882,21 +879,18 @@ char *dap_chain_mempool_base_tx_create(dap_chain_t *a_chain, dap_chain_hash_fast
          //add out
         uint256_t l_value_back = l_value_transfer; // how much datoshi add to 'out' items
          // Network fee
-        if (!dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_addr_fee, l_net_fee, l_native_ticker)){
+        if (!dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_addr_to_fee, l_net_fee, l_native_ticker)){
             dap_chain_datum_tx_delete(l_tx);
-            DAP_DEL_Z(l_addr_from);
             return NULL;
         }
         SUBTRACT_256_256(l_value_back, l_net_fee, &l_value_back);
         if (!IS_ZERO_256(a_value_fee))
             SUBTRACT_256_256(l_value_back, a_value_fee, &l_value_back);
         // coin back
-        if (!dap_chain_datum_tx_add_out_ext_item(&l_tx, l_addr_from, l_value_back, l_native_ticker)){
+        if (!dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_addr_from_fee, l_value_back, l_native_ticker)){
             dap_chain_datum_tx_delete(l_tx);
-            DAP_DEL_Z(l_addr_from);
             return NULL;
         }
-        DAP_DEL_Z(l_addr_from);
 
         if (!dap_chain_datum_tx_add_out_ext_item(&l_tx, a_addr_to, l_value_need, a_ticker)){
             dap_chain_datum_tx_delete(l_tx);
@@ -907,7 +901,7 @@ char *dap_chain_mempool_base_tx_create(dap_chain_t *a_chain, dap_chain_hash_fast
             SUBTRACT_256_256(l_value_need, a_value_fee, &l_value_need);
         if(l_net_fee_used){
             SUBTRACT_256_256(l_value_need, l_net_fee, &l_value_need);
-            if (!dap_chain_datum_tx_add_out_item(&l_tx, &l_addr_fee, l_net_fee)){
+            if (!dap_chain_datum_tx_add_out_item(&l_tx, &l_addr_to_fee, l_net_fee)){
                 dap_chain_datum_tx_delete(l_tx);
                 return NULL;
             }
@@ -924,29 +918,9 @@ char *dap_chain_mempool_base_tx_create(dap_chain_t *a_chain, dap_chain_hash_fast
         }
     }
     //sign item
-    if (not_native)
-    {
-        if(a_key_from)
-            if(dap_chain_datum_tx_add_sign_item(&l_tx, a_key_from) < 0) {
-                log_it(L_WARNING, "No private key for sign");
-                return NULL;
-            }
-    }
-    else{
-        if (a_certs) {
-            for(size_t i = 0; i < a_certs_count; i++) {
-                if(dap_chain_datum_tx_add_sign_item(&l_tx, a_certs[i]->enc_key) < 0) {
-                    log_it(L_WARNING, "No private key for certificate '%s'", a_certs[i]->name);
-                    return NULL;
-                }
-            }
-        }
-        else
-            if(a_key_from)
-                if(dap_chain_datum_tx_add_sign_item(&l_tx, a_key_from) < 0) {
-                    log_it(L_WARNING, "No private key for sign");
-                    return NULL;
-                }
+    if(dap_chain_datum_tx_add_sign_item(&l_tx, a_private_key) < 0) {
+        log_it(L_WARNING, "No private key for sign");
+        return NULL;
     }
 
     size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx);
diff --git a/modules/mempool/include/dap_chain_mempool.h b/modules/mempool/include/dap_chain_mempool.h
index f14bdce4ebae2ee3249b48147e618ab0b787a0e9..97a3042c191e27cf21c386cb799deadf115e269e 100644
--- a/modules/mempool/include/dap_chain_mempool.h
+++ b/modules/mempool/include/dap_chain_mempool.h
@@ -83,9 +83,23 @@ int dap_chain_mempool_tx_create_massive(dap_chain_t * a_chain, dap_enc_key_t *a_
         const char a_token_ticker[DAP_CHAIN_TICKER_SIZE_MAX],
         uint256_t a_value, uint256_t a_value_fee, size_t a_tx_num);
 
+/**
+ * @brief dap_chain_mempool_base_tx_create
+ * @param a_chain
+ * @param a_emission_hash
+ * @param a_emission_chain_id
+ * @param a_emission_value
+ * @param a_ticker
+ * @param a_addr_to
+ * @param a_private_key For a basic transaction not in a native token, use the key obtained from the wallet. For the
+ * basic transaction in the native token, use the key obtained from the certificate.
+ * @param a_hash_out_type
+ * @param a_value_fee
+ * @return
+ */
 char *dap_chain_mempool_base_tx_create(dap_chain_t *a_chain, dap_chain_hash_fast_t *a_emission_hash,
                                        dap_chain_id_t a_emission_chain_id, uint256_t a_emission_value, const char *a_ticker,
-                                       dap_enc_key_t *a_key_from, dap_chain_addr_t *a_addr_to, dap_cert_t **a_certs, size_t a_certs_count,
+                                       dap_chain_addr_t *a_addr_to, dap_enc_key_t *a_private_key,
                                        const char *a_hash_out_type, uint256_t a_value_fee);
 
 dap_chain_datum_token_emission_t *dap_chain_mempool_emission_get(dap_chain_t *a_chain, const char *a_emission_hash_str);
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index 81229ae1a2313b649130d8ceacddf5d5e5516058..2b7829a57e0ba2838e5f660a42ce71fd4141bc2d 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -556,8 +556,10 @@ static bool s_net_send_atoms(dap_proc_thread_t *a_thread, void *a_arg)
  */
 static void s_chain_callback_notify(void *a_arg, dap_chain_t *a_chain, dap_chain_cell_id_t a_id, void* a_atom, size_t a_atom_size)
 {
-    if (!a_arg)
+    if (!a_arg || !a_chain) {
+        log_it(L_ERROR, "Argument is NULL for s_chain_callback_notify");
         return;
+    }
     dap_chain_net_t *l_net = (dap_chain_net_t *)a_arg;
     if (!HASH_COUNT(PVT(l_net)->downlinks))
         return;
diff --git a/modules/net/dap_chain_node_cli.c b/modules/net/dap_chain_node_cli.c
index 314bd2dcedd970e0103ee1c936d7da709ba74af7..cd8edd3ad001012d941598cfccfc3a22b9b8cb99 100644
--- a/modules/net/dap_chain_node_cli.c
+++ b/modules/net/dap_chain_node_cli.c
@@ -273,7 +273,7 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
     // Transaction commands
     dap_cli_server_cmd_add ("tx_create", com_tx_create, "Make transaction",
             "tx_create -net <net_name> -chain <chain_name> -value <value> -token <token_ticker> -to_addr <addr>"
-            "{-from_wallet <wallet_name> | -from_emission <emission_hash> {-certs <cert list> | -wallet_fee <wallet_name>}} -fee <value>\n");
+            "{-from_wallet <wallet_name> | -from_emission <emission_hash> {-cert <cert_name> | -wallet_fee <wallet_name>}} -fee <value>\n");
     dap_cli_server_cmd_add ("tx_create_json", com_tx_create_json, "Make transaction",
                 "tx_create_json -net <net_name> -chain <chain_name> -json <json_file_path>\n" );
     dap_cli_server_cmd_add ("tx_cond_create", com_tx_cond_create, "Make cond transaction",
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index a8e1cb47ec395a0294dd945b0959ba2623b09ba7..a62447ea254df379062ec2efacf50079ea6c1df8 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -5112,9 +5112,9 @@ int com_tx_create(int a_argc, char **a_argv, char **a_str_reply)
     const char * l_emission_chain_name = NULL;
     const char * l_tx_num_str = NULL;
     const char *l_emission_hash_str = NULL;
-    const char *l_certs_str = NULL;
-    dap_cert_t **l_certs = NULL;
-    size_t l_certs_count = 0;
+    const char *l_cert_str = NULL;
+    dap_cert_t *l_cert = NULL;
+    dap_enc_key_t *l_priv_key = NULL;
     dap_chain_hash_fast_t l_emission_hash = {};
     size_t l_tx_num = 0;
     dap_chain_wallet_t * l_wallet_fee = NULL;
@@ -5139,7 +5139,7 @@ int com_tx_create(int a_argc, char **a_argv, char **a_str_reply)
     dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-net", &l_net_name);
     dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-chain", &l_chain_name);
     dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-tx_num", &l_tx_num_str);
-    dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-certs", &l_certs_str);
+    dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-cert", &l_cert_str);
 
     if(l_tx_num_str)
         l_tx_num = strtoul(l_tx_num_str, NULL, 10);
@@ -5221,6 +5221,7 @@ int com_tx_create(int a_argc, char **a_argv, char **a_str_reply)
                     dap_cli_server_cmd_set_reply_text(a_str_reply, "wallet %s does not exist", l_wallet_fee_name);
                     return -12;
                 }
+                l_priv_key = dap_chain_wallet_get_key(l_wallet_fee, 0);
             } else {
                 dap_cli_server_cmd_set_reply_text(a_str_reply, "To create a basic transaction with a "
                                                                "non-native ticker, you must specify the '-wallet_fee' "
@@ -5229,16 +5230,17 @@ int com_tx_create(int a_argc, char **a_argv, char **a_str_reply)
                 return -11;
             }
         } else {
-            if (l_certs_str) {
-                dap_cert_parse_str_list(l_certs_str, &l_certs, &l_certs_count);
-                if (!l_certs_count) {
+            if (l_cert_str) {
+                l_cert = dap_cert_find_by_name(l_cert_str);
+                if (!l_cert) {
                     dap_cli_server_cmd_set_reply_text(a_str_reply,
-                                                      "tx_create requires at least one valid certificate to sign the basic transaction of emission");
+                                                      "tx_create requires one valid certificate to sign the basic transaction of emission");
                     return -5;
                 }
+                l_priv_key = l_cert->enc_key;
             } else {
                 dap_cli_server_cmd_set_reply_text(a_str_reply,
-                                                  "tx_create requires parameter '-certs' for create base tx for emission in native token");
+                                                  "tx_create requires parameter '-cert' for create base tx for emission in native token");
                 return -10;
             }
         }
@@ -5268,15 +5270,14 @@ int com_tx_create(int a_argc, char **a_argv, char **a_str_reply)
     if (l_emission_hash_str) {
         bool not_native = dap_strcmp(l_token_ticker, l_net->pub.native_ticker);
         char *l_tx_hash_str = NULL;
-        if (not_native) {
-            l_tx_hash_str = dap_chain_mempool_base_tx_create(l_chain, &l_emission_hash, l_emission_chain->id,
-                                             l_value, l_token_ticker,dap_chain_wallet_get_key(l_wallet_fee, 0), l_addr_to, NULL,
-                                             0, l_hash_out_type,l_value_fee);
-        } else {
-            l_tx_hash_str = dap_chain_mempool_base_tx_create(l_chain, &l_emission_hash, l_emission_chain->id,
-                                             l_value, l_token_ticker,NULL, l_addr_to, l_certs,
-                                             l_certs_count, l_hash_out_type,l_value_fee);
-        }
+        if (!l_priv_key) {
+            dap_string_append_printf(l_string_ret, "No private key defined for creating the underlying "
+                                                   "transaction no '-wallet_fee' or ' -cert' parameter specified.");
+            res = -10;
+        }
+        l_tx_hash_str = dap_chain_mempool_base_tx_create(l_chain, &l_emission_hash, l_emission_chain->id,
+                                                         l_value, l_token_ticker, l_addr_to, l_priv_key,
+                                                         l_hash_out_type,l_value_fee);
         if (l_tx_hash_str) {
             dap_string_append_printf(l_string_ret, "\nDatum %s with 256bit TX is placed in datum pool\n", l_tx_hash_str);
             DAP_DELETE(l_tx_hash_str);
@@ -5288,6 +5289,7 @@ int com_tx_create(int a_argc, char **a_argv, char **a_str_reply)
         dap_string_free(l_string_ret, true);
         DAP_DELETE(l_addr_to);
         dap_chain_wallet_close(l_wallet_fee);
+        DAP_DEL_Z(l_cert);
         return res;        
     }
 
diff --git a/modules/net/srv/dap_chain_net_srv.c b/modules/net/srv/dap_chain_net_srv.c
index 72982d1f9ae47f60ca53d6e33a69e4424bb1924f..7640a9c071ccac787478d48617a887da6e0a6ea7 100644
--- a/modules/net/srv/dap_chain_net_srv.c
+++ b/modules/net/srv/dap_chain_net_srv.c
@@ -863,6 +863,8 @@ dap_chain_net_srv_t* dap_chain_net_srv_add(dap_chain_net_srv_uid_t a_uid,
         l_sdata->srv = l_srv;
         dap_chain_net_srv_parse_pricelist(l_srv, a_config_section);
         HASH_ADD(hh, s_srv_list, uid, sizeof(l_srv->uid), l_sdata);
+        if (l_srv->pricelist)
+            dap_chain_ledger_tx_add_notify(l_srv->pricelist->net->pub.ledger, dap_stream_ch_chain_net_srv_tx_cond_added_cb, NULL);
     }else{
         log_it(L_ERROR, "Already present service with 0x%016"DAP_UINT64_FORMAT_X, a_uid.uint64);
     }
diff --git a/modules/net/srv/dap_chain_net_srv_order.c b/modules/net/srv/dap_chain_net_srv_order.c
index 43d6a4b0b644ad928e51076671cc3330cea61edb..c69291a663bc974c62a92787cef8a47eac1b7cf8 100644
--- a/modules/net/srv/dap_chain_net_srv_order.c
+++ b/modules/net/srv/dap_chain_net_srv_order.c
@@ -356,6 +356,10 @@ char *dap_chain_net_srv_order_save(dap_chain_net_t *a_net, dap_chain_net_srv_ord
 
 dap_chain_net_srv_order_t *dap_chain_net_srv_order_read(byte_t *a_order, size_t a_order_size)
 {
+    if (NULL == a_order) {
+        log_it(L_ERROR, "Argumets are NULL for dap_chain_net_srv_order_read");
+        return NULL;
+    }
     dap_chain_net_srv_order_t *l_order = (dap_chain_net_srv_order_t *)a_order;
     size_t l_order_size = dap_chain_net_srv_order_get_size((dap_chain_net_srv_order_t *)a_order);
     if (l_order->version > 3 || l_order->direction > SERV_DIR_SELL || l_order_size != a_order_size)
diff --git a/modules/net/srv/dap_chain_net_srv_stream_session.c b/modules/net/srv/dap_chain_net_srv_stream_session.c
index 34128a0d38f0abfb4c01c3c734d90449b470ae0d..6df72f5346370ae52134c607fb9f8dd2ce756a84 100644
--- a/modules/net/srv/dap_chain_net_srv_stream_session.c
+++ b/modules/net/srv/dap_chain_net_srv_stream_session.c
@@ -47,6 +47,22 @@ dap_chain_net_srv_stream_session_t * dap_chain_net_srv_stream_session_create( da
     return  l_session_srv;
 }
 
+/**
+ * @brief dap_chain_net_srv_stream_session_create
+ * @param a_session
+ * @return
+ */
+void dap_chain_net_srv_stream_session_delete( dap_stream_session_t * a_session)
+{
+    if (!a_session){
+        log_it (L_ERROR, "Session is NULL!");
+        return;
+    }
+    dap_chain_net_srv_stream_session_t * l_session_srv = a_session->_inheritor;
+    dap_chain_net_srv_usage_delete(l_session_srv);
+}
+
+
 /**
  * @brief dap_chain_net_srv_usage_add
  * @param a_srv_session
@@ -78,21 +94,20 @@ dap_chain_net_srv_usage_t* dap_chain_net_srv_usage_add (dap_chain_net_srv_stream
  * @param a_usage
  * @return
  */
-void dap_chain_net_srv_usage_delete (dap_chain_net_srv_stream_session_t * a_srv_session,
-                                                                               dap_chain_net_srv_usage_t* a_usage)
+void dap_chain_net_srv_usage_delete (dap_chain_net_srv_stream_session_t * a_srv_session)
 {
-    if ( a_usage->receipt )
-        DAP_DELETE( a_usage->receipt );
-    if ( a_usage->client ){
-        for (dap_chain_net_srv_client_remote_t * l_srv_client = a_usage->client, * tmp = NULL; l_srv_client; ){
+    if ( a_srv_session->usage_active->receipt )
+        DAP_DELETE( a_srv_session->usage_active->receipt );
+    if ( a_srv_session->usage_active->receipt_next )
+        DAP_DELETE( a_srv_session->usage_active->receipt_next );
+    if ( a_srv_session->usage_active->client ){
+        for (dap_chain_net_srv_client_remote_t * l_srv_client = a_srv_session->usage_active->client, * tmp = NULL; l_srv_client; ){
             tmp = l_srv_client;
             l_srv_client = l_srv_client->next;
             DAP_DELETE( tmp);
         }
-
-
     }
-    DAP_DELETE( a_usage );
+    DAP_DEL_Z(a_srv_session->usage_active);
 }
 
 /**
diff --git a/modules/net/srv/include/dap_chain_net_srv.h b/modules/net/srv/include/dap_chain_net_srv.h
index 53db3a75b0f8dbb20b38f303711514b75882822d..08db33f999802ef1582c25ee15c9d3e5ad283568 100755
--- a/modules/net/srv/include/dap_chain_net_srv.h
+++ b/modules/net/srv/include/dap_chain_net_srv.h
@@ -186,6 +186,7 @@ typedef struct dap_chain_net_srv_grace {
     dap_stream_worker_t *stream_worker;
     dap_stream_ch_uuid_t ch_uuid;
     dap_chain_net_srv_usage_t *usage;
+    dap_events_socket_uuid_t timer_es_uuid;
     dap_stream_ch_chain_net_srv_pkt_request_t *request;
     size_t request_size;
 } dap_chain_net_srv_grace_t;
diff --git a/modules/net/srv/include/dap_chain_net_srv_stream_session.h b/modules/net/srv/include/dap_chain_net_srv_stream_session.h
index 6f7a7b0dda5c930ca9557af4378dab2a708c8756..af8bb938713a95f508ce0d14c06441e5276c0d37 100644
--- a/modules/net/srv/include/dap_chain_net_srv_stream_session.h
+++ b/modules/net/srv/include/dap_chain_net_srv_stream_session.h
@@ -55,6 +55,7 @@ typedef struct dap_chain_net_srv_usage{
     bool is_active;
     bool is_free;
     bool is_grace;
+    bool is_waiting_new_tx_cond;
 //    UT_hash_handle hh; //
 } dap_chain_net_srv_usage_t;
 
@@ -91,9 +92,9 @@ typedef struct dap_chain_net_srv_stream_session {
 #define DAP_CHAIN_NET_SRV_STREAM_SESSION(a) ((dap_chain_net_srv_stream_session_t *) (a)->_inheritor )
 
 dap_chain_net_srv_stream_session_t * dap_chain_net_srv_stream_session_create( dap_stream_session_t * a_session);
+void dap_chain_net_srv_stream_session_delete( dap_stream_session_t * a_session);
 dap_chain_net_srv_usage_t* dap_chain_net_srv_usage_add (dap_chain_net_srv_stream_session_t * a_srv_session,
                                                                             dap_chain_net_t * a_net, dap_chain_net_srv_t * a_srv);
-void dap_chain_net_srv_usage_delete (dap_chain_net_srv_stream_session_t * a_srv_session,
-                                                                               dap_chain_net_srv_usage_t* a_usage);
+void dap_chain_net_srv_usage_delete (dap_chain_net_srv_stream_session_t * a_srv_session);
 dap_chain_net_srv_usage_t* dap_chain_net_srv_usage_find_unsafe (dap_chain_net_srv_stream_session_t * a_srv_session,
                                                                              uint32_t a_usage_id);
diff --git a/modules/service/vpn/dap_chain_net_srv_vpn.c b/modules/service/vpn/dap_chain_net_srv_vpn.c
index 05683727900ab216fb5522df9842d7ff5f38d032..b2ff5ae724d0851897898eaf962219a03cdd4379 100644
--- a/modules/service/vpn/dap_chain_net_srv_vpn.c
+++ b/modules/service/vpn/dap_chain_net_srv_vpn.c
@@ -1076,7 +1076,7 @@ void s_ch_vpn_new(dap_stream_ch_t* a_ch, void* a_arg)
 
     dap_chain_net_srv_stream_session_t * l_srv_session = (dap_chain_net_srv_stream_session_t *) a_ch->stream->session->_inheritor;
 
-    l_srv_vpn->usage_id = l_srv_session->usage_active?  l_srv_session->usage_active->id : 0;
+    l_srv_vpn->usage_id = l_srv_session->usage_active ?  l_srv_session->usage_active->id : 0;
 
     if( l_srv_vpn->usage_id) {
         // So complicated to update usage client to be sure that nothing breaks it
@@ -1088,7 +1088,6 @@ void s_ch_vpn_new(dap_stream_ch_t* a_ch, void* a_arg)
         }
         pthread_rwlock_unlock(&s_clients_rwlock);
     }
-
 }
 
 
@@ -1146,6 +1145,7 @@ static void s_ch_vpn_delete(dap_stream_ch_t* a_ch, void* arg)
     l_ch_vpn->ch = NULL;
     l_ch_vpn->net_srv = NULL;
     l_ch_vpn->is_allowed =false;
+    DAP_DEL_Z(a_ch->internal);
 }
 
 /**
@@ -1162,21 +1162,20 @@ static void s_update_limits(dap_stream_ch_t * a_ch ,
     bool l_issue_new_receipt = false;
     // Check if there are time limits
 
-    if (a_usage->is_free)
+    if (a_usage->is_free || !a_usage->receipt || !a_usage->is_active)
         return;
 
     if (a_usage->receipt->receipt_info.units_type.enm == SERV_UNIT_DAY ||
         a_usage->receipt->receipt_info.units_type.enm == SERV_UNIT_SEC){
         time_t l_current_limit_ts = 0;
-        if ( a_usage->receipt){
-            switch( a_usage->receipt->receipt_info.units_type.enm){
+
+        switch( a_usage->receipt->receipt_info.units_type.enm){
             case SERV_UNIT_DAY:{
                 l_current_limit_ts = (time_t)a_usage->receipt->receipt_info.units*24*3600;
             } break;
             case SERV_UNIT_SEC:{
                 l_current_limit_ts = (time_t)a_usage->receipt->receipt_info.units;
             }
-            }
         }
 
         a_srv_session->limits_ts -= time(NULL) - a_srv_session->last_update_ts;
diff --git a/modules/service/vpn/dap_chain_net_vpn_client_tun.c b/modules/service/vpn/dap_chain_net_vpn_client_tun.c
index 801422a282b49dca80c6d51f57f8927bb0e0714b..f75fbb914cebbe6b9180f5bcd02c7db224106b8e 100644
--- a/modules/service/vpn/dap_chain_net_vpn_client_tun.c
+++ b/modules/service/vpn/dap_chain_net_vpn_client_tun.c
@@ -638,7 +638,7 @@ static void ch_sf_pkt_send(dap_stream_ch_t * a_ch, void * a_data, size_t a_data_
     //       ,inet_ntoa(in_daddr), read_ret);
     if(!a_ch) {
         log_it(L_ERROR, "Try to send to NULL channel");
-//        return;
+       return;
     }
     l_pkt_out = DAP_NEW_SIZE(ch_vpn_pkt_t, l_pkt_out_size);
     memset(&l_pkt_out->header,0,sizeof(l_pkt_out->header));
diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c
index dffba69ad8fdccfdca9b5aaf69a36d5d0bb050be..0a18e641b0f0145b3b5f00bbdf9a7b4a13294d51 100644
--- a/modules/type/dag/dap_chain_cs_dag.c
+++ b/modules/type/dag/dap_chain_cs_dag.c
@@ -616,8 +616,10 @@ static size_t s_callback_add_datums(dap_chain_t *a_chain, dap_chain_datum_t **a_
 }
 
 static bool s_chain_callback_datums_pool_proc(dap_chain_t *a_chain, dap_chain_datum_t *a_datum) {
-    if (!a_datum || !a_chain)
-        log_it(L_ERROR, "Datum or chain in mempool processing comes NULL");
+    if (!a_datum || !a_chain){
+        log_it(L_ERROR, "Datum or chain in mempool processing comes NULL in s_chain_callback_datums_pool_proc");
+        return false;
+    }
 
     dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG(a_chain);
     /* If datum passes thru rounds, let's check if it wasn't added before */