diff --git a/dap-sdk b/dap-sdk
index d53d1ce3bea6a148aad3ea777e46c67f7249cc74..15c9dab8830dabb8f3e31022ea728a251567d7b3 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit d53d1ce3bea6a148aad3ea777e46c67f7249cc74
+Subproject commit 15c9dab8830dabb8f3e31022ea728a251567d7b3
diff --git a/modules/chain/dap_chain_cell.c b/modules/chain/dap_chain_cell.c
index 2abed7fec520b29250b68ce4f6fd259ebd01303f..f2457f322ea177994fa1668376dbcb0c96f6b808 100644
--- a/modules/chain/dap_chain_cell.c
+++ b/modules/chain/dap_chain_cell.c
@@ -144,7 +144,7 @@ DAP_STATIC_INLINE int s_cell_map_new_volume(dap_chain_cell_t *a_cell, size_t a_f
             .QuadPart = l_ssize 
         };
         
-        NTSTATUS err = pfnNtCreateSection(&hSection, SECTION_MAP_READ|SECTION_EXTEND_SIZE|SECTION_MAP_WRITE,
+        NTSTATUS err = pfnNtCreateSection(&hSection, SECTION_MAP_READ | SECTION_EXTEND_SIZE,
                                           NULL, &SectionSize, PAGE_READWRITE, SEC_RESERVE, (HANDLE)_get_osfhandle(fileno(a_cell->file_storage)));
         if ( !NT_SUCCESS(err) )
             return log_it(L_ERROR, "NtCreateSection() failed, status %lx", err), -1;
@@ -166,13 +166,13 @@ DAP_STATIC_INLINE int s_cell_map_new_volume(dap_chain_cell_t *a_cell, size_t a_f
         .QuadPart = l_volume_start
     };
     err = pfnNtMapViewOfSection(hSection, GetCurrentProcess(), (HANDLE)&a_cell->map, 0, 0, 
-                                &Offset, &l_map_size, ViewUnmap, MEM_RESERVE, PAGE_WRITECOPY);
+                                &Offset, &l_map_size, ViewUnmap, MEM_RESERVE, PAGE_READONLY);
     if ( !NT_SUCCESS(err) )
         return NtClose(hSection), log_it(L_ERROR, "NtMapViewOfSection() failed, status %lx", err), -1;
 #else
     if (a_load)
         s_cell_reclaim_cur_volume(a_cell);
-    if (( a_cell->map = mmap(NULL, l_map_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
+    if (( a_cell->map = mmap(NULL, l_map_size, PROT_READ, MAP_PRIVATE,
                              fileno(a_cell->file_storage), l_volume_start) ) == MAP_FAILED )
         return log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X" cannot be mapped, errno %d",
                                 a_cell->file_storage_path, a_cell->id.uint64, errno), -1;
@@ -565,7 +565,7 @@ static int s_cell_file_atom_add(dap_chain_cell_t *a_cell, dap_chain_atom_ptr_t a
 #ifdef DAP_OS_DARWIN
     fflush(a_cell->file_storage);
     if (a_cell->chain->is_mapped) {
-        if ( MAP_FAILED == (a_cell->map = mmap(a_cell->map, dap_page_roundup(DAP_MAPPED_VOLUME_LIMIT), PROT_READ|PROT_WRITE,
+        if ( MAP_FAILED == (a_cell->map = mmap(a_cell->map, dap_page_roundup(DAP_MAPPED_VOLUME_LIMIT), PROT_READ,
                                             MAP_PRIVATE|MAP_FIXED, fileno(a_cell->file_storage), a_cell->cur_vol_start)) ) {
             log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X" cannot be remapped, errno %d",
                             a_cell->file_storage_path, a_cell->id.uint64, errno);
diff --git a/modules/common/dap_chain_datum_tx.c b/modules/common/dap_chain_datum_tx.c
index f0891a8569d8fff33d9db4f49d0ec0eec73a88a3..30e6cbc5c441fc3e365deac986d017b672731215 100644
--- a/modules/common/dap_chain_datum_tx.c
+++ b/modules/common/dap_chain_datum_tx.c
@@ -74,7 +74,8 @@ int dap_chain_datum_tx_add_item(dap_chain_datum_tx_t **a_tx, const void *a_item)
 {
     size_t size = 0;
     dap_return_val_if_pass(!a_tx || !*a_tx || !(size = dap_chain_datum_item_tx_get_size(a_item, 0)), -1 );
-    dap_chain_datum_tx_t *tx_new = DAP_REALLOC_RET_VAL_IF_FAIL( *a_tx, dap_chain_datum_tx_get_size(*a_tx) + size, -2 );
+    size_t new_size = dap_chain_datum_tx_get_size(*a_tx) + size;
+    dap_chain_datum_tx_t *tx_new = DAP_REALLOC_RET_VAL_IF_FAIL( *a_tx, new_size, -2 );
     memcpy((uint8_t*) tx_new->tx_items + tx_new->header.tx_items_size, a_item, size);
     tx_new->header.tx_items_size += size;
     *a_tx = tx_new;
@@ -240,24 +241,36 @@ int dap_chain_datum_tx_verify_sign(dap_chain_datum_tx_t *a_tx, int a_sign_num)
 {
     dap_return_val_if_pass(!a_tx, -1);
     int l_ret = -4, l_sign_num = 0;
-    byte_t *l_item; size_t l_item_size;
+    byte_t *l_item = NULL; size_t l_item_size;
     TX_ITEM_ITER_TX(l_item, l_item_size, a_tx) {
-        if (*l_item != TX_ITEM_TYPE_SIG)
-            continue;
-        if (l_sign_num++ != a_sign_num)
-            continue;
-        dap_chain_tx_sig_t *l_sign_item = (dap_chain_tx_sig_t *)l_item;
-        dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig(l_sign_item);
-        byte_t *l_data_ptr = l_sign_item->header.version ? (byte_t *)a_tx : a_tx->tx_items;
-        const size_t l_data_size = (size_t)(l_item - l_data_ptr);
-        size_t l_tx_items_size = a_tx->header.tx_items_size;
-        if (l_sign_item->header.version)
-            a_tx->header.tx_items_size = 0;
-        l_ret = dap_sign_verify_all(l_sign, l_item_size, l_data_ptr, l_data_size);
-        a_tx->header.tx_items_size = l_tx_items_size;
-        if (l_ret < -1)
-            log_it(L_WARNING, "Incorrect signature header, possible corrupted data");
-        break;
+        if ( *l_item == TX_ITEM_TYPE_SIG && l_sign_num++ == a_sign_num )
+            break;
+    }
+    if (!l_item || !l_item_size)
+        return log_it(L_ERROR, "Sign not found in TX"), l_ret;
+    
+    dap_chain_tx_sig_t *l_sign_item = (dap_chain_tx_sig_t*)l_item;
+    dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig(l_sign_item);
+    size_t l_tx_items_size = a_tx->header.tx_items_size, l_data_size;
+    dap_chain_datum_tx_t *l_tx;
+    byte_t *l_tx_data;
+    if ( l_sign_item->header.version ) {
+        l_data_size = (size_t)( l_item - (byte_t*)a_tx );
+        l_tx = dap_config_get_item_bool_default(g_config, "ledger", "mapped", true)
+            ? DAP_DUP_SIZE(a_tx, dap_chain_datum_tx_get_size(a_tx)) : a_tx;
+        l_tx_data = (byte_t*)l_tx;
+        l_tx->header.tx_items_size = 0;
+    } else {
+        l_tx = a_tx;
+        l_tx_data = a_tx->tx_items;
+        l_data_size = (size_t)( l_item - l_tx_data );
+    }
+    l_ret = dap_sign_verify_all(l_sign, l_item_size, l_tx_data, l_data_size);
+    if (l_sign_item->header.version) {
+        if ( dap_config_get_item_bool_default(g_config, "ledger", "mapped", true) )
+            DAP_DELETE(l_tx);
+        else
+            a_tx->header.tx_items_size = l_tx_items_size;
     }
-    return l_ret;
+    return debug_if(l_ret, L_ERROR, "Sign verification error %d", l_ret), l_ret;
 }
diff --git a/modules/common/include/dap_chain_datum_token.h b/modules/common/include/dap_chain_datum_token.h
index b92e61446d60dde2d9ffd5048291b5829cc1ace9..8f6d89e63afd5d612b7ae12a6f0a93de8626b856 100644
--- a/modules/common/include/dap_chain_datum_token.h
+++ b/modules/common/include/dap_chain_datum_token.h
@@ -405,6 +405,7 @@ typedef struct dap_chain_datum_token_emission {
 #define DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_BRIDGE_COMMISSION_OLD "COMISSION"
 #define DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_BRIDGE_COMMISSION "COMMISSION"
 #define DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_BRIDGE_CROSSCHAIN "CROSSCHAIN"
+#define DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_BRIDGE_OUT "OUT"
 
 DAP_STATIC_INLINE const char *dap_chain_datum_emission_type_str(uint8_t a_type)
 {
diff --git a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
index dd2472a8fc3530a49ec38495db5ae9bd792b203d..3ba0e8d3367b66847563df3c455116da4114b019 100644
--- a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
+++ b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
@@ -858,21 +858,27 @@ static int s_callback_event_verify(dap_chain_cs_dag_t *a_dag, dap_chain_cs_dag_e
     }
     uint16_t l_signs_verified_count = 0;
     if (l_signs_count >= l_certs_count_verify) {
-        uint16_t l_event_signs_count = a_event->header.signs_count;
+        dap_chain_cs_dag_event_t * l_event = a_dag->chain->is_mapped
+            ? DAP_DUP_SIZE(a_event, l_event_size)
+            : a_event;
+        uint16_t l_event_signs_count = l_event->header.signs_count;
         for (size_t i = 0; i < l_signs_count; i++) {
             dap_sign_t *l_sign = (dap_sign_t *)l_signs[i];
             // Compare signature with auth_certs
-            a_event->header.signs_count = i;
+            l_event->header.signs_count = i;
             for (uint16_t j = 0; j < l_poa_pvt->auth_certs_count; j++) {
                 if (!dap_cert_compare_with_sign( l_poa_pvt->auth_certs[j], l_sign)
-                            && !dap_sign_verify(l_sign, a_event, l_offset_from_beginning)){
+                            && !dap_sign_verify(l_sign, l_event, l_offset_from_beginning)){
                     l_signs_verified_count++;
                     break;
                 }
             }
         }
-        a_event->header.signs_count = l_event_signs_count;
         DAP_DELETE(l_signs);
+        if (a_dag->chain->is_mapped)
+            DAP_DELETE(l_event);
+        else
+            a_event->header.signs_count = l_event_signs_count;
         if (l_signs_verified_count >= l_certs_count_verify)
             return 0;
     }
diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
index 73831b057d33c6f12f87554f51ce29027feea018..f181e5c9ba03ccffe74144f8968a33bf1c55b803 100644
--- a/modules/consensus/esbocs/dap_chain_cs_esbocs.c
+++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
@@ -2846,7 +2846,10 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl
     bool l_block_is_emergency = s_block_is_emergency(a_block, l_block_size);
     // Get the header on signing operation time
     size_t l_block_original = a_block->hdr.meta_n_datum_n_signs_size;
-    a_block->hdr.meta_n_datum_n_signs_size = l_block_excl_sign_size - sizeof(a_block->hdr);
+    dap_chain_block_t *l_block = a_blocks->chain->is_mapped
+        ? DAP_DUP_SIZE(a_block, l_block_size)
+        : a_block;
+    l_block->hdr.meta_n_datum_n_signs_size = l_block_excl_sign_size - sizeof(l_block->hdr);
     for (size_t i = 0; i < l_signs_count; i++) {
         dap_sign_t *l_sign = l_signs[i];
         dap_chain_addr_t l_signing_addr = { .net_id = a_blocks->chain->net_id };
@@ -2882,7 +2885,7 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl
                 l_ret = -5;
                 break;
             } else if (l_esbocs_pvt->check_signs_structure &&
-                       !s_check_signing_rights(l_esbocs, a_block, l_block_size, &l_signing_addr, true)) {
+                       !s_check_signing_rights(l_esbocs, l_block, l_block_size, &l_signing_addr, true)) {
                 if (l_esbocs_pvt->debug) {
                     char l_block_hash_str[DAP_HASH_FAST_STR_SIZE];
                     dap_hash_fast_to_str(a_block_hash, l_block_hash_str, DAP_HASH_FAST_STR_SIZE);
@@ -2894,7 +2897,7 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl
         } else {
             if (l_block_is_emergency && !s_check_emergency_rights(l_esbocs, &l_signing_addr) &&
                     l_esbocs_pvt->check_signs_structure &&
-                    !s_check_signing_rights(l_esbocs, a_block, l_block_size, &l_signing_addr, false)) {
+                    !s_check_signing_rights(l_esbocs, l_block, l_block_size, &l_signing_addr, false)) {
                 if (l_esbocs_pvt->debug) {
                     char l_block_hash_str[DAP_HASH_FAST_STR_SIZE];
                     dap_hash_fast_to_str(a_block_hash, l_block_hash_str, DAP_HASH_FAST_STR_SIZE);
@@ -2903,7 +2906,7 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl
                 l_ret = -5;
                 break;
             } else if (l_esbocs_pvt->check_signs_structure &&
-                    !s_check_signing_rights(l_esbocs, a_block, l_block_size, &l_signing_addr, false)) {
+                    !s_check_signing_rights(l_esbocs, l_block, l_block_size, &l_signing_addr, false)) {
                 if (l_esbocs_pvt->debug) {
                     char l_block_hash_str[DAP_HASH_FAST_STR_SIZE];
                     dap_hash_fast_to_str(a_block_hash, l_block_hash_str, DAP_HASH_FAST_STR_SIZE);
@@ -2913,13 +2916,15 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl
                 break;
             }
         }
-        if (!dap_sign_verify(l_sign, a_block, l_block_excl_sign_size))
+        if (!dap_sign_verify(l_sign, l_block, l_block_excl_sign_size))
             l_signs_verified_count++;
     }
     DAP_DELETE(l_signs);
     // Restore the original header
-    a_block->hdr.meta_n_datum_n_signs_size = l_block_original;
-
+    if ( a_blocks->chain->is_mapped )
+        DAP_DELETE(l_block);
+    else
+        l_block->hdr.meta_n_datum_n_signs_size = l_block_original;
     if (l_signs_verified_count < l_esbocs_pvt->min_validators_count) {
         debug_if(l_esbocs_pvt->debug, L_ERROR, "Corrupted block %s: not enough authorized signs: %u of %u",
                     dap_hash_fast_to_str_static(a_block_hash), l_signs_verified_count, l_esbocs_pvt->min_validators_count);
diff --git a/modules/net/dap_chain_ledger.c b/modules/net/dap_chain_ledger.c
index 71328097945b49122c491ca4493a4895a4a691df..028edd4b972c85e29ada0c945065c44ea4c200ed 100644
--- a/modules/net/dap_chain_ledger.c
+++ b/modules/net/dap_chain_ledger.c
@@ -674,7 +674,10 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain
             }
             if (!a_apply)
                 break;
+            uint256_t l_supply_delta = {};
+            SUBTRACT_256_256(l_new_supply, a_item_apply_to->total_supply, &l_supply_delta);
             a_item_apply_to->total_supply = l_new_supply;
+            SUM_256_256(a_item_apply_to->current_supply, l_supply_delta, &a_item_apply_to->current_supply);
         } break;
 
         // Allowed tx receiver addres list add, remove or clear
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index a877f86191557ef0f3b15c9a2519903addb30e95..0e8d86b71216119c79d212dc8ba7b5dfae356e54 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -210,6 +210,7 @@ static void s_link_manager_callback_error(dap_link_t *a_link, uint64_t a_net_id,
 static bool s_link_manager_callback_disconnected(dap_link_t *a_link, uint64_t a_net_id, int a_links_count);
 static int s_link_manager_fill_net_info(dap_link_t *a_link);
 static int s_link_manager_link_request(uint64_t a_net_id);
+static int s_link_manager_link_count_changed();
 
 static const dap_link_manager_callbacks_t s_link_manager_callbacks = {
     .connected      = s_link_manager_callback_connected,
@@ -217,6 +218,7 @@ static const dap_link_manager_callbacks_t s_link_manager_callbacks = {
     .error          = s_link_manager_callback_error,
     .fill_net_info  = s_link_manager_fill_net_info,
     .link_request   = s_link_manager_link_request,
+    .link_count_changed = s_link_manager_link_count_changed,
 };
 
 // State machine switchs here
@@ -413,14 +415,6 @@ static void s_link_manager_callback_connected(dap_link_t *a_link, uint64_t a_net
     log_it(L_NOTICE, "Established connection with %s."NODE_ADDR_FP_STR,l_net->pub.name,
            NODE_ADDR_FP_ARGS_S(a_link->addr));
 
-    struct json_object *l_json = dap_chain_net_states_json_collect(l_net);
-    char l_err_str[128] = { };
-    snprintf(l_err_str, sizeof(l_err_str)
-                 , "Established connection with link " NODE_ADDR_FP_STR
-                 , NODE_ADDR_FP_ARGS_S(a_link->addr));
-    json_object_object_add(l_json, "errorMessage", json_object_new_string(l_err_str));
-    dap_notify_server_send_mt(json_object_get_string(l_json));
-    json_object_put(l_json);
     if(l_net_pvt->state == NET_STATE_LINKS_CONNECTING ){
         l_net_pvt->state = NET_STATE_LINKS_ESTABLISHED;
     }
@@ -521,6 +515,15 @@ int s_link_manager_link_request(uint64_t a_net_id)
     return dap_worker_exec_callback_on(dap_worker_get_auto(), dap_chain_net_balancer_request, l_arg), 0;
 }
 
+static int s_link_manager_link_count_changed()
+{
+    struct json_object *l_json = dap_chain_nets_info_json_collect();
+    json_object_object_add(l_json, "errorMessage", json_object_new_string(" ")); // regular notify has no error
+    dap_notify_server_send_mt(json_object_get_string(l_json));
+    json_object_put(l_json);
+    return 0;
+}
+
 struct request_link_info *s_get_permanent_link_info(dap_chain_net_t *a_net, dap_chain_node_addr_t *a_address)
 {
     dap_chain_net_pvt_t *l_net_pvt = PVT(a_net);
@@ -679,6 +682,22 @@ static void s_net_states_notify(dap_chain_net_t *a_net)
     json_object_put(l_json);
 }
 
+/**
+ * @brief s_net_states_notify
+ * @param l_net
+ */
+static bool s_net_states_notify_timer_callback(UNUSED_ARG void *a_arg)
+{
+    for (dap_chain_net_t *net = s_nets_by_name; net; net = net->hh.next) {
+        struct json_object *l_json = dap_chain_net_states_json_collect(net);
+        json_object_object_add(l_json, "errorMessage", json_object_new_string(" ")); // regular notify has no error
+        dap_notify_server_send_mt(json_object_get_string(l_json));
+        json_object_put(l_json);
+    }
+
+    return true;
+}
+
 /**
  * @brief dap_chain_net_get_role
  * @param a_net
@@ -783,6 +802,7 @@ bool s_net_disk_load_notify_callback(UNUSED_ARG void *a_arg) {
     json_object_object_add(json_obj, "nets", l_jobj_nets);
     dap_notify_server_send_mt(json_object_get_string(json_obj));
     json_object_put(json_obj);
+    s_net_states_notify_timer_callback(NULL);
     return true;
 }
 
diff --git a/modules/net/dap_chain_net_anchor.c b/modules/net/dap_chain_net_anchor.c
index ebc9dedc274d6941d40fd49d366fc91c9f20c97f..c11d222d4ca37f47826c81e94744caa28c81262d 100644
--- a/modules/net/dap_chain_net_anchor.c
+++ b/modules/net/dap_chain_net_anchor.c
@@ -82,26 +82,31 @@ static int s_anchor_verify(dap_chain_net_t *a_net, dap_chain_datum_anchor_t *a_a
         return log_it(L_WARNING, "No unique signatures!"), -106;
     bool l_sign_authorized = false;
     size_t l_signs_size_original = a_anchor->header.signs_size;
-    a_anchor->header.signs_size = 0;
+    dap_chain_datum_anchor_t *l_anchor = a_net->pub.chains->is_mapped
+        ? DAP_DUP_SIZE(a_anchor, a_data_size)
+        : a_anchor;
+    l_anchor->header.signs_size = 0;
     for (size_t i = 0; i < l_num_of_unique_signs; i++) {
         dap_chain_net_decree_t *l_net_decree = dap_chain_net_get_net_decree(a_net);
         for (dap_list_t *it = l_net_decree->pkeys; it; it = it->next) {
             if (dap_pkey_compare_with_sign(it->data, l_unique_signs[i])) {
                 // TODO make signs verification in s_concate_all_signs_in_array to correctly header.signs_size calculation
-                size_t l_verify_data_size = a_anchor->header.data_size + sizeof(dap_chain_datum_anchor_t);
-                if (dap_sign_verify_all(l_unique_signs[i], l_signs_size_original, a_anchor, l_verify_data_size))
+                size_t l_verify_data_size = l_anchor->header.data_size + sizeof(dap_chain_datum_anchor_t);
+                if (dap_sign_verify_all(l_unique_signs[i], l_signs_size_original, l_anchor, l_verify_data_size))
                     continue;
                 l_sign_authorized = true;
                 break;
             }
         }
-        a_anchor->header.signs_size += dap_sign_get_size(l_unique_signs[i]);
+        l_anchor->header.signs_size += dap_sign_get_size(l_unique_signs[i]);
         if (l_sign_authorized)
             break;
     }
     DAP_DELETE(l_unique_signs);
-    a_anchor->header.signs_size = l_signs_size_original;
-
+    if ( a_net->pub.chains->is_mapped )
+        DAP_DELETE(l_anchor);
+    else
+        l_anchor->header.signs_size = l_signs_size_original;
     if (!l_sign_authorized) {
         log_it(L_WARNING, "Anchor signs verify failed");
         return -108;
diff --git a/modules/net/dap_chain_net_balancer.c b/modules/net/dap_chain_net_balancer.c
index a215cfa4b85e8b584e495a26eb3c933836062950..c9235a873bab26cb5624c53caa73de5fb1c8abc9 100644
--- a/modules/net/dap_chain_net_balancer.c
+++ b/modules/net/dap_chain_net_balancer.c
@@ -149,10 +149,6 @@ static void s_balancer_link_prepare_success(dap_chain_net_t* a_net, dap_chain_ne
         if (dap_chain_net_link_add(a_net, &l_link_info->node_addr, l_link_info->uplink_addr, l_link_info->uplink_port))
             continue;
         l_json = s_balancer_states_json_collect(a_net, a_host_addr, a_host_port);
-        snprintf(l_err_str, sizeof(l_err_str)
-                     , "Link " NODE_ADDR_FP_STR " prepared"
-                     , NODE_ADDR_FP_ARGS_S(l_link_info->node_addr));
-        json_object_object_add(l_json, "errorMessage", json_object_new_string(l_err_str));
         dap_notify_server_send_mt(json_object_get_string(l_json));
         json_object_put(l_json);
     }
diff --git a/modules/net/dap_chain_net_decree.c b/modules/net/dap_chain_net_decree.c
index ff0023527ee8a42261e98185fa31849a4586ee5e..92efb30620732e0d54484dec0cfa515178908e0f 100644
--- a/modules/net/dap_chain_net_decree.c
+++ b/modules/net/dap_chain_net_decree.c
@@ -154,13 +154,13 @@ static int s_decree_verify(dap_chain_net_t *a_net, dap_chain_datum_decree_t *a_d
     // Find unique pkeys in pkeys set from previous step and check that number of signs > min
     size_t l_num_of_unique_signs = 0;
     dap_sign_t **l_unique_signs = dap_sign_get_unique_signs(l_signs_block, l_signs_size, &l_num_of_unique_signs);
-    dap_chain_net_decree_t *l_decree = dap_chain_net_get_net_decree(a_net);
-    if (!l_decree) {
+    dap_chain_net_decree_t *l_net_decree = dap_chain_net_get_net_decree(a_net);
+    if (!l_net_decree) {
         log_it(L_ERROR, "Decree module hasn't been initialized yet");
         return -404;
     }
 
-    uint16_t l_min_signs = l_decree->min_num_of_owners;
+    uint16_t l_min_signs = l_net_decree->min_num_of_owners;
     if (l_num_of_unique_signs < l_min_signs) {
         log_it(L_WARNING, "Not enough unique signatures, get %zu from %hu", l_num_of_unique_signs, l_min_signs);
         return -106;
@@ -168,32 +168,33 @@ static int s_decree_verify(dap_chain_net_t *a_net, dap_chain_datum_decree_t *a_d
 
     // Verify all keys and its signatures
     uint16_t l_signs_size_for_current_sign = 0, l_signs_verify_counter = 0;
-    a_decree->header.signs_size = 0;
-    size_t l_verify_data_size = a_decree->header.data_size + sizeof(dap_chain_datum_decree_t);
+    dap_chain_datum_decree_t *l_decree = a_net->pub.chains->is_mapped
+        ? DAP_DUP_SIZE(a_decree, a_data_size)
+        : a_decree;
+    l_decree->header.signs_size = 0;
+    size_t l_verify_data_size = l_decree->header.data_size + sizeof(dap_chain_datum_decree_t);
 
     for (size_t i = 0; i < l_num_of_unique_signs; i++) {
         size_t l_sign_max_size = dap_sign_get_size(l_unique_signs[i]);
         if (s_verify_pkey(l_unique_signs[i], a_net)) {
             // 3. verify sign
-            if(!dap_sign_verify_all(l_unique_signs[i], l_sign_max_size, a_decree, l_verify_data_size))
+            if(!dap_sign_verify_all(l_unique_signs[i], l_sign_max_size, l_decree, l_verify_data_size))
                 l_signs_verify_counter++;
         } else {
             dap_hash_fast_t l_sign_pkey_hash = {0};
             size_t l_pkey_size = 0;
             uint8_t *l_pkey = dap_sign_get_pkey(l_unique_signs[i], &l_pkey_size);
-            dap_hash_fast(l_pkey, l_pkey_size, &l_sign_pkey_hash);
-            char *l_sign_hash_str = dap_hash_fast_to_str_new(&l_sign_pkey_hash);
-            log_it(L_WARNING, "Signature [%zu] %s failed public key verification.", i, l_sign_hash_str);
-            DAP_DELETE(l_sign_hash_str);
+            log_it(L_WARNING, "Signature [%zu] %s failed public key verification.", i, dap_get_data_hash_str(l_pkey, l_pkey_size).s);
         }
         // Each sign change the sign_size field by adding its size after signing. So we need to change this field in header for each sign.
         l_signs_size_for_current_sign += l_sign_max_size;
-        a_decree->header.signs_size = l_signs_size_for_current_sign;
+        l_decree->header.signs_size = l_signs_size_for_current_sign;
     }
 
-    a_decree->header.signs_size = l_signs_size;
-
-//    DAP_DELETE(l_signs_arr);
+    if ( a_net->pub.chains->is_mapped )
+        DAP_DELETE(l_decree);
+    else
+        l_decree->header.signs_size = l_signs_size;
     DAP_DELETE(l_unique_signs);
 
     if (l_signs_verify_counter < l_min_signs) {
@@ -373,6 +374,19 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain
     switch (a_decree->header.sub_type)
     {
         case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_FEE:
+                // if (dap_chain_datum_decree_get_fee_addr(a_decree, &l_addr)) {
+                //     if (dap_chain_addr_is_blank(&a_net->pub.fee_addr)) {
+                //         log_it(L_WARNING, "Fee wallet address not set.");
+                //         return -111;
+                //     } else
+                //         l_addr = a_net->pub.fee_addr;
+                // }
+                if (dap_chain_datum_decree_get_fee(a_decree, &l_value)) {
+                    log_it(L_WARNING,"Can't get fee value from decree.");
+                    return -103;
+                }
+                if (!a_anchored)
+                    break;
                 if (dap_chain_datum_decree_get_fee_addr(a_decree, &l_addr)) {
                     if (dap_chain_addr_is_blank(&a_net->pub.fee_addr)) {
                         log_it(L_WARNING, "Fee wallet address not set.");
@@ -380,10 +394,6 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain
                     } else
                         l_addr = a_net->pub.fee_addr;
                 }
-                if (dap_chain_datum_decree_get_fee(a_decree, &l_value)) {
-                    log_it(L_WARNING,"Can't get fee value from decree.");
-                    return -103;
-                }
                 if (!a_apply)
                     break;
                 if (!dap_chain_net_tx_set_fee(a_net->pub.id, l_value, l_addr))
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index ab7eee0ea539d22885b7bca9800ef97fcd2c8ec8..1b03e1f25bceb493ba60a74ad7a29e9263175d87 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -104,11 +104,13 @@
 #include "dap_json_rpc_request.h"
 #include "dap_client_pvt.h"
 #include "dap_enc.h"
-
+#include "dap_notify_srv.h"
 
 #define LOG_TAG "chain_node_cli_cmd"
 
 int _cmd_mempool_add_ca(dap_chain_net_t *a_net, dap_chain_t *a_chain, dap_cert_t *a_cert, void **a_str_reply);
+static void s_new_wallet_info_notify(const char *a_wallet_name); 
+struct json_object *wallet_list_json_collect();
 
 dap_chain_t *s_get_chain_with_datum(dap_chain_net_t *a_net, const char *a_datum_hash) {
     dap_chain_t *l_chain = NULL;
@@ -1741,7 +1743,19 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
                     return DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NET_PARAM_ERR;
                 }
                 l_wallet = dap_chain_wallet_open(l_wallet_name, c_wallets_path, NULL);
+                if (!l_wallet){
+                    dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NET_PARAM_ERR,
+                                           "Can't find wallet (%s)", l_wallet_name);
+                    json_object_put(json_arr_out);
+                    return DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NET_PARAM_ERR;
+                }
                 l_addr = (dap_chain_addr_t *) dap_chain_wallet_get_addr(l_wallet, l_net->pub.id );
+                if (!l_addr){
+                    dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NET_PARAM_ERR,
+                                           "Can't get addr from wallet (%s)", l_wallet_name);
+                    json_object_put(json_arr_out);
+                    return DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NET_PARAM_ERR;
+                }
             } else {
                 l_addr = dap_chain_addr_from_str(l_addr_str);
             }
@@ -1763,28 +1777,37 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
             uint256_t l_value_sum = uint256_0;
             if (l_value_str){
                 uint256_t l_value_datoshi = dap_chain_balance_scan(l_value_str);
-                l_outs_list = dap_ledger_get_list_tx_outs_with_val(l_net->pub.ledger, l_token_tiker, l_addr, l_value_datoshi, &l_value_sum);
+                if (dap_chain_wallet_cache_tx_find_outs_with_val(l_net, l_token_tiker, l_addr, &l_outs_list, l_value_datoshi, &l_value_sum))
+                    l_outs_list = dap_ledger_get_list_tx_outs_with_val(l_net->pub.ledger, l_token_tiker, l_addr, l_value_datoshi, &l_value_sum);
             } else {
-                l_outs_list = dap_ledger_get_list_tx_outs(l_net->pub.ledger, l_token_tiker, l_addr, &l_value_sum);
-            }
-
-            json_object_object_add(json_obj_wall, "total_value", json_object_new_string(dap_uint256_to_char(l_value_sum, NULL)));
+                if (dap_chain_wallet_cache_tx_find_outs(l_net, l_token_tiker, l_addr, &l_outs_list, &l_value_sum))
+                    l_outs_list = dap_ledger_get_list_tx_outs(l_net->pub.ledger, l_token_tiker, l_addr, &l_value_sum);
+            }
+            json_object_object_add(json_obj_wall, "wallet_addr", json_object_new_string(dap_chain_addr_to_str_static(l_addr)));
+            const char *l_out_total_value_str = dap_chain_balance_print(l_value_sum);
+            const char *l_out_total_value_coins_str = dap_chain_balance_to_coins(l_value_sum);
+            json_object_object_add(json_obj_wall, "total_value_coins", json_object_new_string(l_out_total_value_coins_str));
+            json_object_object_add(json_obj_wall, "total_value_datoshi", json_object_new_string(l_out_total_value_str));
+            DAP_DEL_Z(l_out_total_value_str);
+            DAP_DEL_Z(l_out_total_value_coins_str);
             struct json_object *l_json_outs_arr = json_object_new_array();
             for (dap_list_t *l_temp = l_outs_list; l_temp; l_temp = l_temp->next){
                 dap_chain_tx_used_out_item_t *l_item = l_temp->data;
                 json_object* json_obj_item = json_object_new_object();
-                const char *l_out_value_str = dap_uint256_to_char(l_item->value, NULL);
+                const char *l_out_value_str = dap_chain_balance_print(l_item->value);
+                const char *l_out_value_coins_str = dap_chain_balance_to_coins(l_item->value);
                 json_object_object_add(json_obj_item,"item_type", json_object_new_string("unspent_out"));
-                json_object_object_add(json_obj_item,"value", json_object_new_string(l_out_value_str));
+                json_object_object_add(json_obj_item,"value_coins", json_object_new_string(l_out_value_coins_str));
+                json_object_object_add(json_obj_item,"value_datosi", json_object_new_string(l_out_value_str));
                 json_object_object_add(json_obj_item,"prev_hash", json_object_new_string(dap_hash_fast_to_str_static(&l_item->tx_hash_fast)));  
                 json_object_object_add(json_obj_item,"out_prev_idx", json_object_new_int64(l_item->num_idx_out));   
                 json_object_array_add(l_json_outs_arr, json_obj_item);
+                DAP_DEL_Z(l_out_value_str);
+                DAP_DEL_Z(l_out_value_coins_str);
             }
             dap_list_free_full(l_outs_list, NULL);
             json_object_object_add(json_obj_wall, "outs", l_json_outs_arr);
             json_object_array_add(json_arr_out, json_obj_wall);
-
-
         } break;
         default: {
             if( !l_wallet_name ) {
@@ -1823,6 +1846,11 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
                         json_object_object_add(json_obj_wall, "Wallet name", json_object_new_string(l_wallet_name));
                         json_object_object_add(json_obj_wall, "protection", cmd_num == CMD_WALLET_ACTIVATE ?
                         json_object_new_string("is activated") : json_object_new_string("is deactivated"));
+                        // Notify about wallet
+                        s_new_wallet_info_notify(l_wallet_name);
+                        struct json_object *l_json_wallets = wallet_list_json_collect();
+                        dap_notify_server_send_mt(json_object_get_string(l_json_wallets));
+                        json_object_put(l_json_wallets);
                         break;
                     case -EBUSY:
                         dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_WALLET_ALREADY_ERR,
@@ -1909,6 +1937,12 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
                     json_object_object_add(json_obj_wall, "Status", json_object_new_string("successfully converted"));
                     dap_chain_wallet_close(l_wallet);
                     json_object_array_add(json_arr_out, json_obj_wall);
+
+                    // Notify about wallet
+                    s_new_wallet_info_notify(l_wallet_name);
+                    struct json_object *l_json_wallets = wallet_list_json_collect();
+                    dap_notify_server_send_mt(json_object_get_string(l_json_wallets));
+                    json_object_put(l_json_wallets);
                     break;
                 }
                 // new wallet
@@ -2053,6 +2087,11 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
                     }
                     json_object_array_add(json_arr_out, json_obj_wall);
                     dap_chain_wallet_close(l_wallet);
+                    // Notify about wallet
+                    s_new_wallet_info_notify(l_wallet_name);
+                    struct json_object *l_json_wallets = wallet_list_json_collect();
+                    dap_notify_server_send_mt(json_object_get_string(l_json_wallets));
+                    json_object_put(l_json_wallets);
                     break;
                 }
             }
@@ -6084,6 +6123,7 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply)
     const char *l_json_str = NULL;
     const char *l_native_token = NULL;
     const char *l_main_token = NULL;
+    bool l_multichanel = false;
 
     dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_name); // optional parameter
     dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-chain", &l_chain_name); // optional parameter
@@ -6188,11 +6228,41 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply)
     size_t l_items_ready = 0;
     dap_list_t *l_sign_list = NULL;// list 'sing' items
     dap_list_t *l_in_list = NULL;// list 'in' items
-    // dap_list_t *l_tsd_list = NULL;// list tsd sections
     uint256_t l_value_need = { };// how many tokens are needed in the 'out' item
     uint256_t l_value_need_fee = {};
     json_object *l_jobj_errors = json_object_new_array();
-//    dap_string_t *l_err_str = dap_string_new("Errors: \n");
+    // First iteration in input file. Check the tx will be multichannel or not
+    for(size_t i = 0; i < l_items_count; ++i) {
+        struct json_object *l_json_item_obj = json_object_array_get_idx(l_json_items, i);
+        if(!l_json_item_obj || !json_object_is_type(l_json_item_obj, json_type_object)) {
+            continue;
+        }
+        struct json_object *l_json_item_type = json_object_object_get(l_json_item_obj, "type");
+        if(!l_json_item_type && json_object_is_type(l_json_item_type, json_type_string)) {
+            log_it(L_WARNING, "Item %zu without type", i);
+            continue;
+        }
+        const char *l_item_type_str = json_object_get_string(l_json_item_type);
+        dap_chain_tx_item_type_t l_item_type = dap_chain_datum_tx_item_str_to_type(l_item_type_str);
+        if(l_item_type == TX_ITEM_TYPE_UNKNOWN) {
+            log_it(L_WARNING, "Item %zu has invalid type '%s'", i, l_item_type_str);
+            continue;
+        }
+
+        switch (l_item_type) {
+            case TX_ITEM_TYPE_IN: {
+                const char *l_json_item_token = s_json_get_text(l_json_item_obj, "token");
+                if (l_json_item_token && dap_strcmp(l_json_item_token, l_native_token)){
+                    l_multichanel = true;
+                    l_main_token = l_json_item_token;
+                }
+            }break;
+            default: continue;
+        }
+        if(l_multichanel)
+            break;
+    }
+
     // Creating and adding items to the transaction
     for(size_t i = 0; i < l_items_count; ++i) {
         struct json_object *l_json_item_obj = json_object_array_get_idx(l_json_items, i);
@@ -6253,44 +6323,59 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply)
             uint256_t l_value = { };
             const char *l_json_item_addr_str = s_json_get_text(l_json_item_obj, "addr");
             bool l_is_value = s_json_get_uint256(l_json_item_obj, "value", &l_value);
+            const char *l_token = s_json_get_text(l_json_item_obj, "token");
             if(l_is_value && l_json_item_addr_str) {
                 dap_chain_addr_t *l_addr = dap_chain_addr_from_str(l_json_item_addr_str);
                 if(l_addr && !IS_ZERO_256(l_value)) {
                     if(l_item_type == TX_ITEM_TYPE_OUT) {
                         // Create OUT item
-                        dap_chain_tx_out_t *l_out_item = dap_chain_datum_tx_item_out_create(l_addr, l_value);
+                        const uint8_t *l_out_item = NULL;
+                            if(l_multichanel)
+                                l_out_item = (const uint8_t *)dap_chain_datum_tx_item_out_ext_create(l_addr, l_value, l_token ? l_token : (l_main_token ? l_main_token : l_native_token));
+                            else
+                                l_out_item = (const uint8_t *)dap_chain_datum_tx_item_out_create(l_addr, l_value);
                         if (!l_out_item) {
                             json_object *l_jobj_err = json_object_new_string("Failed to create transaction out. "
                                                                              "There may not be enough funds in the wallet.");
                             json_object_array_add(l_jobj_errors, l_jobj_err);
                         }
                         l_item = (const uint8_t*) l_out_item;
-                    }
-                    else if(l_item_type == TX_ITEM_TYPE_OUT_EXT) {
+                        if (l_item){
+                            if (l_multichanel && !dap_strcmp(((dap_chain_tx_out_ext_t*)l_out_item)->token, l_native_token))
+                                SUM_256_256(l_value_need_fee, l_value, &l_value_need_fee);
+                            else
+                                SUM_256_256(l_value_need, l_value, &l_value_need);
+                        }
+                            
+                    } else if(l_item_type == TX_ITEM_TYPE_OUT_EXT) {
                         // Read address and value
-                        const char *l_token = s_json_get_text(l_json_item_obj, "token");
-                        l_main_token = l_token;
                         if(l_token) {
                             // Create OUT_EXT item
-                            dap_chain_tx_out_ext_t *l_out_ext_item = dap_chain_datum_tx_item_out_ext_create(l_addr, l_value, l_token);
-                            if (!l_out_ext_item) {
+                            const uint8_t *l_out_item = NULL;
+                            if(l_multichanel)
+                                l_out_item = (const uint8_t *)dap_chain_datum_tx_item_out_ext_create(l_addr, l_value, l_token);
+                            else
+                                l_out_item = (const uint8_t *)dap_chain_datum_tx_item_out_create(l_addr, l_value);
+                            if (!l_out_item) {
                                 json_object *l_jobj_err = json_object_new_string("Failed to create a out ext"
                                                                     "for a transaction. There may not be enough funds "
                                                                     "on the wallet or the wrong ticker token "
                                                                     "is indicated.");
                                 json_object_array_add(l_jobj_errors, l_jobj_err);
                             }
-                            l_item = (const uint8_t*) l_out_ext_item;
+                            l_item = (const uint8_t*) l_out_item;
+                            if (l_item){
+                                if (l_multichanel && !dap_strcmp(l_token, l_native_token))
+                                    SUM_256_256(l_value_need_fee, l_value, &l_value_need_fee);
+                                else 
+                                    SUM_256_256(l_value_need, l_value, &l_value_need);
+                            }
                         }
                         else {
                             log_it(L_WARNING, "Invalid 'out_ext' item %zu", i);
                             continue;
                         }
                     }
-                    // Save value for using in In item
-                    if(l_item) {
-                        SUM_256_256(l_value_need, l_value, &l_value_need);
-                    }
                 } else {
                     if(l_item_type == TX_ITEM_TYPE_OUT) {
                         log_it(L_WARNING, "Invalid 'out' item %zu", i);
@@ -6736,7 +6821,10 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply)
                 uint256_t l_value_back;
                 SUBTRACT_256_256(l_value_got, l_value_need, &l_value_back);
                 if(!IS_ZERO_256(l_value_back)) {
-                    dap_chain_datum_tx_add_out_item(&l_tx, l_addr_from, l_value_back);
+                    if (l_multichanel)
+                        dap_chain_datum_tx_add_out_ext_item(&l_tx, l_addr_from, l_value_back, l_main_token);
+                    else
+                        dap_chain_datum_tx_add_out_item(&l_tx, l_addr_from, l_value_back);
                     l_items_ready++;
                 }
             }
@@ -8611,6 +8699,17 @@ void dap_notify_new_client_send_info(dap_events_socket_t *a_es, UNUSED_ARG void
     }
 }
 
+static void s_new_wallet_info_notify(const char *a_wallet_name)
+{
+    struct json_object *l_json = json_object_new_object();
+    json_object_object_add(l_json, "class", json_object_new_string("WalletInfo"));
+    struct json_object *l_json_wallet_info = json_object_new_object();
+    json_object_object_add(l_json_wallet_info, a_wallet_name, dap_chain_wallet_info_to_json(a_wallet_name, dap_chain_wallet_get_path(g_config)));
+    json_object_object_add(l_json, "wallet", l_json_wallet_info);
+    dap_notify_server_send_mt(json_object_get_string(l_json));
+    json_object_put(l_json);
+}
+
 static void s_stage_connected_callback(dap_client_t* a_client, void * a_arg) {
     dap_chain_node_client_t *l_node_client = DAP_CHAIN_NODE_CLIENT(a_client);
     UNUSED(a_arg);
diff --git a/modules/service/bridge/dap_chain_net_srv_bridge.c b/modules/service/bridge/dap_chain_net_srv_bridge.c
index 439d0556d046e6b02be8511127dc2a2944e1a82c..04d696727c03f152d7a5773d78e241d6b23aec59 100644
--- a/modules/service/bridge/dap_chain_net_srv_bridge.c
+++ b/modules/service/bridge/dap_chain_net_srv_bridge.c
@@ -135,14 +135,38 @@ static bool s_tag_check_bridge(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_t
 
     //crosschain bridge AUTH emissions 
     
-    if (!a_items_grp->items_in_ems)
+    if (a_items_grp->items_in_ems){
+        dap_chain_tx_in_ems_t *l_tx_in_ems = a_items_grp->items_in_ems->data;
+        dap_hash_fast_t ems_hash = l_tx_in_ems->header.token_emission_hash;
+        dap_chain_datum_token_emission_t *l_emission = dap_ledger_token_emission_find(a_ledger, &ems_hash);
+        if(l_emission)
+            return s_get_ems_bridge_action(l_emission, a_action);
+    }
+
+    if (!a_items_grp->items_tsd)
         return false;
 
-    dap_chain_tx_in_ems_t *l_tx_in_ems = a_items_grp->items_in_ems->data;
-    dap_hash_fast_t ems_hash = l_tx_in_ems->header.token_emission_hash;
-    dap_chain_datum_token_emission_t *l_emission = dap_ledger_token_emission_find(a_ledger, &ems_hash);
-    if(l_emission)
-        return s_get_ems_bridge_action(l_emission, a_action);
+    bool src_bridge = false;
+    bool subtype_out = false;
+    for (dap_list_t *it = a_items_grp->items_tsd; it; it = it->next) {
+        dap_chain_tx_tsd_t *l_tx_tsd = it->data;
+        int l_type;
+        size_t l_size;
+        byte_t *l_data = dap_chain_datum_tx_item_get_data(l_tx_tsd, &l_type, &l_size);
+        
+        
+        if (l_type == DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_SOURCE && s_tsd_str_cmp(l_data, l_size, DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_BRIDGE) == 0)
+            src_bridge = true;
+        
+        if (l_type == DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_SOURCE_SUBTYPE && s_tsd_str_cmp(l_data, l_size, DAP_CHAIN_DATUM_TOKEN_EMISSION_SOURCE_SUBTYPE_BRIDGE_OUT) == 0)
+            subtype_out = true;
+    }
+    if (src_bridge && subtype_out)
+    {
+        if(a_action) *a_action = DAP_CHAIN_TX_TAG_ACTION_CLOSE;
+        return true;
+    }
+
 
     return false;
 }
diff --git a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
index b9a9b5772e807bbe08fa085797efe4c5afc4b8ea..5494b0ee718bac1e07545f504e1d01572a2bc551 100644
--- a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
+++ b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
@@ -33,6 +33,7 @@
 #include "dap_chain_net_srv_emit_delegate.h"
 #include "dap_chain_node_cli_cmd.h"
 
+
 enum emit_delegation_error {
     DAP_NO_ERROR = 0,
     ERROR_MEMORY,
@@ -287,7 +288,7 @@ static bool s_is_key_present(dap_chain_tx_out_cond_t *a_cond, dap_enc_key_t *a_e
     return false;
 }
 
-static dap_chain_datum_tx_t *s_taking_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key,
+dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key,
                                                 dap_chain_addr_t *a_addr_to, uint256_t a_value, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash)
 {
     // create empty transaction
@@ -355,7 +356,8 @@ static dap_chain_datum_tx_t *s_taking_tx_create(json_object *a_json_arr_reply, d
         if (!l_out_cond)
             m_tx_fail(ERROR_COMPOSE, c_error_memory_alloc);
         l_out_cond->header.value = l_value_back;
-        dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_out_cond);
+        if (-1 == dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_out_cond))
+            m_tx_fail(ERROR_COMPOSE, "Cant add emission cond output");
         DAP_DELETE(l_out_cond);
     }
 
@@ -390,7 +392,7 @@ static dap_chain_datum_tx_t *s_taking_tx_create(json_object *a_json_arr_reply, d
 
 #undef m_tx_fail
 
-static dap_chain_datum_tx_t *s_taking_tx_sign(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key, dap_chain_datum_tx_t *a_tx_in)
+dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_sign(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key, dap_chain_datum_tx_t *a_tx_in)
 {
     int l_cond_idx = 0;
     dap_chain_tx_out_cond_t *l_cond = dap_chain_datum_tx_out_cond_get(a_tx_in, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_EMIT_DELEGATE, &l_cond_idx);
@@ -614,7 +616,7 @@ static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object **
         return ERROR_VALUE;
     }
      // Create emission from conditional transaction
-    dap_chain_datum_tx_t *l_tx = s_taking_tx_create(*a_json_arr_reply, a_net, l_enc_key, l_addr, l_value, l_fee, &l_tx_in_hash);
+    dap_chain_datum_tx_t *l_tx = dap_chain_net_srv_emit_delegate_taking_tx_create(*a_json_arr_reply, a_net, l_enc_key, l_addr, l_value, l_fee, &l_tx_in_hash);
     DAP_DEL_MULTY(l_enc_key, l_addr);
     if (!l_tx) {
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_CREATE, "Can't compose transaction for delegated emission");
@@ -669,7 +671,7 @@ static int s_cli_sign(int a_argc, char **a_argv, int a_arg_index, json_object **
     dap_chain_wallet_close(l_wallet);
 
      // Create emission from conditional transaction
-    dap_chain_datum_tx_t *l_tx = s_taking_tx_sign(*a_json_arr_reply, a_net, l_enc_key, (dap_chain_datum_tx_t *)l_tx_in->data);
+    dap_chain_datum_tx_t *l_tx = dap_chain_net_srv_emit_delegate_taking_tx_sign(*a_json_arr_reply, a_net, l_enc_key, (dap_chain_datum_tx_t *)l_tx_in->data);
     DAP_DELETE(l_enc_key);
     if (!l_tx) {
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_CREATE, "Can't compose transaction for delegated emission");
diff --git a/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h b/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h
index bbe35ccf9121ce1f7a285bb72f98d181f3730b18..210f73c531198bce14b6c75f02408b10f2d9dc88 100644
--- a/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h
+++ b/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h
@@ -3,6 +3,15 @@
 #define DAP_CHAIN_NET_SRV_EMIT_DELEGATE_ID 0x07
 #define DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF 0x14
 
+#include "dap_chain_datum_tx.h"
+#include "dap_chain_mempool.h"
+
 int dap_chain_net_srv_emit_delegate_init();
 
-void dap_chain_net_srv_bridge_deinit();
+void dap_chain_net_srv_emit_delegate_deinit();
+
+
+dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_object *a_json_arr_rweply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key,
+                                                dap_chain_addr_t *a_addr_to, uint256_t a_value, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash);
+
+dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_sign(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key, dap_chain_datum_tx_t *a_tx_in);
diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c
index 562d0455663f4e6b7692493c4af55dc94cc6f0d1..888beac875856f3e2f21503e50c0e06532d0f1fd 100644
--- a/modules/type/blocks/dap_chain_cs_blocks.c
+++ b/modules/type/blocks/dap_chain_cs_blocks.c
@@ -396,11 +396,7 @@ static char *s_blocks_decree_set_reward(dap_chain_net_t *a_net, dap_chain_t *a_c
     // Create decree
     size_t l_tsd_total_size = sizeof(dap_tsd_t) + sizeof(uint256_t);
     size_t l_decree_size = sizeof(dap_chain_datum_decree_t) + l_tsd_total_size;
-    dap_chain_datum_decree_t *l_decree = DAP_NEW_Z_SIZE(dap_chain_datum_decree_t, l_decree_size);
-    if (!l_decree) {
-        log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-        return NULL;
-    }
+    dap_chain_datum_decree_t *l_decree = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_datum_decree_t, l_decree_size, NULL);
     // Fill the header
     l_decree->decree_version = DAP_CHAIN_DATUM_DECREE_VERSION;
     l_decree->header.ts_created = dap_time_now();
diff --git a/modules/wallet/dap_chain_wallet.c b/modules/wallet/dap_chain_wallet.c
index e972ea0a8e2fc24f2775a4e9c0a617fb55aa657b..6b4cdd3c08a2ef0d634da56b3f29fd9900a690bb 100644
--- a/modules/wallet/dap_chain_wallet.c
+++ b/modules/wallet/dap_chain_wallet.c
@@ -1185,12 +1185,12 @@ json_object *dap_chain_wallet_info_to_json(const char *a_name, const char *a_pat
                 json_object_object_add(l_balance_data, "description", l_description ?
                                                                       json_object_new_string(l_description)
                                                                                     : json_object_new_null());
-                json_object_object_add(l_balance_data, "coin", json_object_new_string(l_balance_coins));
+                json_object_object_add(l_balance_data, "coins", json_object_new_string(l_balance_coins));
                 json_object_object_add(l_balance_data, "datoshi", json_object_new_string(l_balance_datoshi));
                 json_object_array_add(l_arr_balance, l_balance_data);
                 DAP_DELETE(l_addr_tokens[i]);
             }
-            json_object_object_add(l_jobj_net, "balance", l_arr_balance);
+            json_object_object_add(l_jobj_net, "tokens", l_arr_balance);
             DAP_DELETE(l_addr_tokens);
         }
         json_object_object_add(l_json_ret, "networks", l_jobj_network);
diff --git a/modules/wallet/dap_chain_wallet_cache.c b/modules/wallet/dap_chain_wallet_cache.c
index a0ef35e1ffc2bd7c5cff9c5542e6c7e2b3bbfa51..3b3f7ea6c07f0c22f54b27aae065251cb2eff6af 100644
--- a/modules/wallet/dap_chain_wallet_cache.c
+++ b/modules/wallet/dap_chain_wallet_cache.c
@@ -84,6 +84,7 @@ typedef struct dap_wallet_tx_cache {
 typedef struct dap_s_wallets_cache {
     dap_chain_addr_t wallet_addr;
     dap_wallet_tx_cache_t *wallet_txs;
+    _Atomic bool is_loading;
     UT_hash_handle hh;
 } dap_wallet_cache_t;
 
@@ -92,7 +93,7 @@ typedef struct dap_atom_notify_arg {
     dap_chain_net_t *net;
 } dap_atom_notify_arg_t;
 
-static dap_s_wallets_cache_type_t s_wallets_cache_type = DAP_WALLET_CACHE_TYPE_ALL;
+static dap_s_wallets_cache_type_t s_wallets_cache_type = DAP_WALLET_CACHE_TYPE_LOCAL;
 static dap_wallet_cache_t *s_wallets_cache = NULL;
 static pthread_rwlock_t s_wallet_cache_rwlock;
 
@@ -202,7 +203,7 @@ int dap_chain_wallet_cache_tx_find(dap_chain_addr_t *a_addr, char *a_token, dap_
 
     pthread_rwlock_rdlock(&s_wallet_cache_rwlock);
     HASH_FIND(hh, s_wallets_cache, a_addr, sizeof(dap_chain_addr_t), l_wallet_item);
-    if (!l_wallet_item){
+    if (!l_wallet_item || l_wallet_item->is_loading){
         log_it(L_ERROR, "Can't find wallet with address %s", dap_chain_addr_to_str_static(a_addr));
         pthread_rwlock_unlock(&s_wallet_cache_rwlock);
         return -101;
@@ -290,7 +291,7 @@ int dap_chain_wallet_cache_tx_find_in_history(dap_chain_addr_t *a_addr, char **a
 
     pthread_rwlock_rdlock(&s_wallet_cache_rwlock);
     HASH_FIND(hh, s_wallets_cache, a_addr, sizeof(dap_chain_addr_t), l_wallet_item);
-    if (!l_wallet_item){
+    if (!l_wallet_item || l_wallet_item->is_loading){
         log_it(L_ERROR, "Can't find wallet with address %s", dap_chain_addr_to_str_static(a_addr));
         pthread_rwlock_unlock(&s_wallet_cache_rwlock);
         return -101;
@@ -382,7 +383,7 @@ int dap_chain_wallet_cache_tx_find_outs_with_val(dap_chain_net_t *a_net, const c
     dap_wallet_cache_t *l_wallet_item = NULL;
     pthread_rwlock_rdlock(&s_wallet_cache_rwlock);
     HASH_FIND(hh, s_wallets_cache, a_addr, sizeof(dap_chain_addr_t), l_wallet_item);
-    if (!l_wallet_item){
+    if (!l_wallet_item || l_wallet_item->is_loading){
         log_it(L_ERROR, "Can't find wallet with address %s", dap_chain_addr_to_str_static(a_addr));
         pthread_rwlock_unlock(&s_wallet_cache_rwlock);
         return -101;
@@ -497,6 +498,129 @@ int dap_chain_wallet_cache_tx_find_outs_with_val(dap_chain_net_t *a_net, const c
     return 0;
 }
 
+int dap_chain_wallet_cache_tx_find_outs(dap_chain_net_t *a_net, const char *a_token_ticker, const dap_chain_addr_t *a_addr, 
+                                                    dap_list_t **a_outs_list, uint256_t *a_value_transfer)
+{
+
+    dap_list_t *l_list_used_out = NULL; // list of transaction with 'out' items
+    uint256_t l_value_transfer = { };
+    dap_chain_datum_tx_t *l_tx;
+
+    if (!a_token_ticker){
+        log_it(L_ERROR, "Token ticker is not specified.");
+        return -100;
+    } 
+    
+    if(!a_addr || dap_chain_addr_is_blank(a_addr)){
+        log_it(L_ERROR, "Wallet addr is not specified.");
+        return -100;
+    }
+
+    if (a_outs_list == NULL){
+        log_it(L_ERROR, "a_outs_list is NULL");
+        return -100;
+    }
+
+    dap_wallet_cache_t *l_wallet_item = NULL;
+    pthread_rwlock_rdlock(&s_wallet_cache_rwlock);
+    HASH_FIND(hh, s_wallets_cache, a_addr, sizeof(dap_chain_addr_t), l_wallet_item);
+    if (!l_wallet_item || l_wallet_item->is_loading){
+        log_it(L_ERROR, "Can't find wallet with address %s", dap_chain_addr_to_str_static(a_addr));
+        pthread_rwlock_unlock(&s_wallet_cache_rwlock);
+        return -101;
+    }
+    dap_wallet_tx_cache_t *l_current_wallet_tx = l_wallet_item->wallet_txs;
+
+    // Go iterate wallet txs
+    dap_wallet_tx_cache_t *l_current_wallet_tx_iter = NULL, *l_tmp = NULL;
+    HASH_ITER(hh, l_current_wallet_tx, l_current_wallet_tx_iter, l_tmp) {
+        if (l_current_wallet_tx_iter->ret_code != DAP_LEDGER_CHECK_OK)
+            continue;
+
+        
+        if (*l_current_wallet_tx_iter->token_ticker &&
+            dap_strcmp(l_current_wallet_tx_iter->token_ticker, a_token_ticker) &&
+            !l_current_wallet_tx_iter->multichannel)
+            continue;
+        else if (*l_current_wallet_tx_iter->token_ticker && dap_strcmp(l_current_wallet_tx_iter->token_ticker, a_token_ticker) &&
+                    l_current_wallet_tx_iter->multichannel){
+
+            bool skip = true;
+            for (dap_list_t *l_temp = l_current_wallet_tx_iter->tx_wallet_outputs; l_temp; l_temp=l_temp->next){
+                dap_wallet_tx_cache_output_t *l_out_cur = (dap_wallet_tx_cache_output_t*)l_temp->data;
+                dap_chain_tx_item_type_t l_type = *(dap_chain_tx_item_type_t*)l_out_cur->tx_out;
+                uint256_t l_value = { };
+                switch (l_type) {
+                case TX_ITEM_TYPE_OUT_EXT: {
+                    dap_chain_tx_out_ext_t *l_out_ext = (dap_chain_tx_out_ext_t*)l_out_cur->tx_out;
+                    if (dap_strcmp(l_out_ext->token, a_token_ticker))
+                        continue;
+                    if (IS_ZERO_256(l_out_ext->header.value) )
+                        continue;
+                    l_value = l_out_ext->header.value;
+                } break;
+                default:
+                    continue;
+                }
+                // Check whether used 'out' items
+                if ( !dap_ledger_tx_hash_is_used_out_item (a_net->pub.ledger, &l_current_wallet_tx_iter->tx_hash, l_out_cur->tx_out_idx, NULL) ) {
+                    dap_chain_tx_used_out_item_t *l_item = DAP_NEW_Z(dap_chain_tx_used_out_item_t);
+                    *l_item = (dap_chain_tx_used_out_item_t) { l_current_wallet_tx_iter->tx_hash, (uint32_t)l_out_cur->tx_out_idx, l_value };
+                    l_list_used_out = dap_list_append(l_list_used_out, l_item);
+                    SUM_256_256(l_value_transfer, l_item->value, &l_value_transfer);
+                }
+            }
+        } else {
+            bool skip = true;
+            for (dap_list_t *l_temp = l_current_wallet_tx_iter->tx_wallet_outputs; l_temp; l_temp=l_temp->next){
+                dap_wallet_tx_cache_output_t *l_out_cur = (dap_wallet_tx_cache_output_t*)l_temp->data;
+                dap_chain_tx_item_type_t l_type = *(dap_chain_tx_item_type_t*)l_out_cur->tx_out;
+                uint256_t l_value = { };
+                switch (l_type) {
+                case TX_ITEM_TYPE_OUT_OLD: {
+                    dap_chain_tx_out_old_t *l_out = (dap_chain_tx_out_old_t*)l_out_cur->tx_out;
+                    if (!l_out->header.value)
+                        continue;
+                    l_value = GET_256_FROM_64(l_out->header.value);
+                } break;
+                case TX_ITEM_TYPE_OUT: {
+                    dap_chain_tx_out_t *l_out = (dap_chain_tx_out_t*)l_out_cur->tx_out;
+                    if (IS_ZERO_256(l_out->header.value) )
+                        continue;
+                    l_value = l_out->header.value;
+                } break;
+                case TX_ITEM_TYPE_OUT_EXT: {
+                    // TODO: check ticker
+                    dap_chain_tx_out_ext_t *l_out_ext = (dap_chain_tx_out_ext_t*)l_out_cur->tx_out;
+                    if (dap_strcmp(l_out_ext->token, a_token_ticker))
+                        continue;
+                    if (IS_ZERO_256(l_out_ext->header.value) )
+                        continue;
+                    l_value = l_out_ext->header.value;
+                } break;
+                default:
+                    continue;
+                }
+                // Check whether used 'out' items
+
+                if ( !dap_ledger_tx_hash_is_used_out_item (a_net->pub.ledger, &l_current_wallet_tx_iter->tx_hash, l_out_cur->tx_out_idx, NULL) ) {
+                    dap_chain_tx_used_out_item_t *l_item = DAP_NEW_Z(dap_chain_tx_used_out_item_t);
+                    *l_item = (dap_chain_tx_used_out_item_t) { l_current_wallet_tx_iter->tx_hash, (uint32_t)l_out_cur->tx_out_idx, l_value };
+                    l_list_used_out = dap_list_append(l_list_used_out, l_item);
+                    SUM_256_256(l_value_transfer, l_item->value, &l_value_transfer);
+                }
+            }
+        }
+    }
+    pthread_rwlock_unlock(&s_wallet_cache_rwlock);
+
+    *a_outs_list = l_list_used_out;
+    if (a_value_transfer)
+        *a_value_transfer = l_value_transfer;
+   
+    return 0;
+}
+
 static int s_save_tx_into_wallet_cache(dap_chain_t *a_chain, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, dap_hash_fast_t *a_atom_hash, int a_ret_code, char* a_main_token_ticker,
                                                 dap_chain_net_srv_uid_t a_srv_uid, dap_chain_tx_tag_action_type_t a_action)
 {
@@ -568,13 +692,18 @@ static int s_save_tx_into_wallet_cache(dap_chain_t *a_chain, dap_chain_datum_tx_
             dap_hash_fast_t l_prev_tx_hash = ((dap_chain_tx_in_t*)it->data)->header.tx_prev_hash;
             int l_prev_idx = ((dap_chain_tx_in_t*)it->data)->header.tx_out_prev_idx;
             if (dap_hash_fast_is_blank(&l_prev_tx_hash))
+                continue;              
+            dap_chain_datum_t *l_prev_datum = a_chain->callback_datum_find_by_hash(a_chain, &l_prev_tx_hash, NULL, NULL);
+            dap_chain_datum_tx_t *l_tx_prev = l_prev_datum ? (dap_chain_datum_tx_t *)(l_prev_datum->data) : NULL;
+            if (!l_tx_prev){
+                log_it(L_ERROR, "Can't find previous transactions (hash=%s)", dap_hash_fast_to_str_static(&l_prev_tx_hash));
                 continue;
-            dap_chain_datum_tx_t *l_tx_prev = (dap_chain_datum_tx_t *)(a_chain->callback_datum_find_by_hash(a_chain, &l_prev_tx_hash, NULL, NULL)->data);
-            if (!l_tx_prev)
-                continue;
-            uint8_t* l_prev_item = dap_chain_datum_tx_item_get_nth(l_tx_prev, TX_ITEM_TYPE_OUT, l_prev_idx);
-            if (!l_prev_item)
+            }
+            uint8_t* l_prev_item = dap_chain_datum_tx_item_get_nth(l_tx_prev, TX_ITEM_TYPE_OUT_ALL, l_prev_idx);
+            if (!l_prev_item){
+                log_it(L_ERROR, "Can't find out with index %d in transaction %s", l_prev_idx, dap_hash_fast_to_str_static(&l_prev_tx_hash));
                 continue;
+            }
             uint8_t l_out_type = *(uint8_t *)l_prev_item;
             switch(l_out_type){
                 case TX_ITEM_TYPE_OUT_OLD: {
@@ -639,11 +768,6 @@ static int s_save_tx_into_wallet_cache(dap_chain_t *a_chain, dap_chain_datum_tx_
 
 static int s_save_cache_for_addr_in_net(dap_chain_net_t *a_net, dap_chain_addr_t *a_addr)
 {
-    // Find chain with transactions    
-    dap_hash_fast_t l_curr_tx_hash = {0};
-    if (dap_chain_wallet_cache_tx_find_in_history(a_addr, NULL, NULL, NULL, NULL, NULL, &l_curr_tx_hash) == 0)
-        return 0;
-
     dap_chain_t *l_chain = a_net->pub.chains;
     while (l_chain){
         for(int i = 0; i < l_chain->datum_types_count; i++) {
@@ -654,8 +778,10 @@ static int s_save_cache_for_addr_in_net(dap_chain_net_t *a_net, dap_chain_addr_t
                         l_datum;
                         l_datum = l_chain->callback_datum_iter_get_next(l_iter)){
 
-                    s_save_tx_cache_for_addr(l_chain, a_addr, (dap_chain_datum_tx_t*)l_datum->data, l_iter->cur_hash, l_iter->cur_atom_hash, l_iter->ret_code, l_iter->token_ticker, l_iter->uid, l_iter->action);
+                    if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX)
+                        s_save_tx_cache_for_addr(l_chain, a_addr, (dap_chain_datum_tx_t*)l_datum->data, l_iter->cur_hash, l_iter->cur_atom_hash, l_iter->ret_code, l_iter->token_ticker, l_iter->uid, l_iter->action);
                 }
+                l_chain->callback_datum_iter_delete(l_iter);
                 break;
             }
         }
@@ -683,22 +809,59 @@ static void s_callback_datum_notify(void *a_arg, dap_chain_hash_fast_t *a_datum_
     s_save_tx_into_wallet_cache(l_arg->chain, l_tx, a_datum_hash, a_atom_hash, a_ret_code, (char*)l_main_token_ticker, a_uid, a_action);
 }
 
+typedef struct wallet_cache_load_args {
+    dap_chain_net_t *net;
+    dap_chain_addr_t addr;
+    dap_wallet_cache_t *wallet_item;
+} wallet_cache_load_args_t;
+
+static void *s_wallet_load(void *a_arg)
+{
+    wallet_cache_load_args_t *l_args = (wallet_cache_load_args_t*)a_arg;
+
+    s_save_cache_for_addr_in_net(l_args->net, &l_args->addr);
+
+    l_args->wallet_item->is_loading = false;
+    DAP_DEL_Z(a_arg);
+
+    return NULL;
+}
+
+
 static void s_wallet_opened_callback(dap_chain_wallet_t *a_wallet, void *a_arg)
 {
+
     for(dap_chain_net_t *l_net = dap_chain_net_iter_start(); l_net; l_net=dap_chain_net_iter_next(l_net)){
+        if (dap_chain_net_get_load_mode(l_net))
+            continue;
         // get wallet addr in current net
         dap_chain_addr_t *l_addr = dap_chain_wallet_get_addr(a_wallet, l_net->pub.id);
         pthread_rwlock_wrlock(&s_wallet_cache_rwlock);
         dap_wallet_cache_t *l_wallet_item = NULL;
         HASH_FIND(hh, s_wallets_cache, l_addr, sizeof(dap_chain_addr_t), l_wallet_item);
-        if (!l_wallet_item){
-            l_wallet_item = DAP_NEW_Z(dap_wallet_cache_t);
-            memcpy (&l_wallet_item->wallet_addr, l_addr, sizeof(dap_chain_addr_t));
-            HASH_ADD(hh, s_wallets_cache, wallet_addr, sizeof(dap_chain_addr_t), l_wallet_item);
-            pthread_rwlock_unlock(&s_wallet_cache_rwlock);
-            s_save_cache_for_addr_in_net(l_net, l_addr);
-        } else 
+        if (l_wallet_item){
             pthread_rwlock_unlock(&s_wallet_cache_rwlock);
+            continue;
+        }
+
+        l_wallet_item = DAP_NEW_Z(dap_wallet_cache_t);
+        memcpy (&l_wallet_item->wallet_addr, l_addr, sizeof(dap_chain_addr_t));
+        l_wallet_item->is_loading = true;
+        HASH_ADD(hh, s_wallets_cache, wallet_addr, sizeof(dap_chain_addr_t), l_wallet_item);
+        pthread_rwlock_unlock(&s_wallet_cache_rwlock);
+
+        wallet_cache_load_args_t *l_args = DAP_NEW_Z(wallet_cache_load_args_t);
+        l_args->net = l_net;
+        l_args->addr = *l_addr;
+        l_args->wallet_item = l_wallet_item;
+
+        pthread_t l_tid;
+        pthread_attr_t attr;
+        pthread_attr_init(&attr);
+        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+        pthread_create(&l_tid, &attr, s_wallet_load, l_args);
+        
+        // s_save_cache_for_addr_in_net(l_net, l_addr); 
     }
 }
 
@@ -708,29 +871,32 @@ static int s_save_tx_cache_for_addr(dap_chain_t *a_chain, dap_chain_addr_t *a_ad
 {
     int l_ret_val = 0;
     int l_items_cnt = 0;
-
-    dap_list_t *l_out_list = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT_ALL, &l_items_cnt);
     bool l_multichannel = false;
     int l_out_idx = 0;
-    for (dap_list_t *it=l_out_list; it; it=it->next, l_out_idx++){
-        uint8_t l_out_type = *(uint8_t *)it->data;
+    uint8_t *l_tx_item = NULL;
+    size_t l_size; int i;
+    TX_ITEM_ITER_TX_TYPE(l_tx_item, TX_ITEM_TYPE_OUT_ALL, l_size, i, a_tx) {
+        uint8_t l_out_type = *(uint8_t *)l_tx_item;
         dap_chain_addr_t l_addr = {};
         switch(l_out_type){
             case TX_ITEM_TYPE_OUT_OLD: {
-                l_addr = ((dap_chain_tx_out_old_t*)it->data)->addr;
+                l_addr = ((dap_chain_tx_out_old_t*)l_tx_item)->addr;
             } break;
             case TX_ITEM_TYPE_OUT: {
-                l_addr = ((dap_chain_tx_out_t*)it->data)->addr;
+                l_addr = ((dap_chain_tx_out_t*)l_tx_item)->addr;
             } break;
             case TX_ITEM_TYPE_OUT_EXT: {
-                l_addr = ((dap_chain_tx_out_ext_t*)it->data)->addr;
+                l_addr = ((dap_chain_tx_out_ext_t*)l_tx_item)->addr;
                 l_multichannel = true;
             } break;
-            default:
+            default:{
+                l_out_idx++;
                 continue;
+            } 
         }
 
-        if(!dap_chain_addr_is_blank(&l_addr) && dap_chain_addr_compare(&l_addr, a_addr) &&
+        if(!dap_chain_addr_is_blank(&l_addr) && 
+                dap_chain_addr_compare(&l_addr, a_addr) &&
                 l_addr.net_id.uint64 == a_chain->net_id.uint64
             ){
             pthread_rwlock_wrlock(&s_wallet_cache_rwlock);
@@ -756,45 +922,52 @@ static int s_save_tx_cache_for_addr(dap_chain_t *a_chain, dap_chain_addr_t *a_ad
             } 
             l_wallet_tx_item->multichannel = l_multichannel;
             dap_wallet_tx_cache_output_t *l_out = DAP_NEW_Z(dap_wallet_tx_cache_output_t);
-            l_out->tx_out = it->data;
+            l_out->tx_out = l_tx_item;
             l_out->tx_out_idx = l_out_idx;
             l_wallet_tx_item->tx_wallet_outputs = dap_list_append(l_wallet_tx_item->tx_wallet_outputs, l_out);
             pthread_rwlock_unlock(&s_wallet_cache_rwlock);
         }
+        l_out_idx++;
     }
 
-    dap_list_t *l_in_list = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_IN_ALL, &l_items_cnt);
-    for (dap_list_t *it=l_out_list; it; it=it->next ){
-        uint8_t l_cond_type = *(uint8_t *)it->data;
+    l_tx_item = NULL;
+    TX_ITEM_ITER_TX_TYPE(l_tx_item, TX_ITEM_TYPE_IN_ALL, l_size, i, a_tx) {
+        uint8_t l_cond_type = *l_tx_item;
         uint256_t l_value = {};
         dap_chain_addr_t l_addr_from = {};
         if(l_cond_type == TX_ITEM_TYPE_IN){
-            dap_hash_fast_t l_prev_tx_hash = ((dap_chain_tx_in_t*)it->data)->header.tx_prev_hash;
-            int l_prev_idx = ((dap_chain_tx_in_t*)it->data)->header.tx_out_prev_idx;
+            dap_hash_fast_t l_prev_tx_hash = ((dap_chain_tx_in_t*)l_tx_item)->header.tx_prev_hash;
+            int l_prev_idx = ((dap_chain_tx_in_t*)l_tx_item)->header.tx_out_prev_idx;
             if (dap_hash_fast_is_blank(&l_prev_tx_hash))
                 continue;
-            dap_chain_datum_tx_t *l_tx_prev = (dap_chain_datum_tx_t *)(a_chain->callback_datum_find_by_hash(a_chain, &l_prev_tx_hash, NULL, NULL)->data);
-            if (!l_tx_prev)
+            dap_chain_datum_t *l_prev_datum = a_chain->callback_datum_find_by_hash(a_chain, &l_prev_tx_hash, NULL, NULL);
+            dap_chain_datum_tx_t *l_tx_prev = l_prev_datum ? (dap_chain_datum_tx_t *)(l_prev_datum->data) : NULL;
+            if (!l_tx_prev){
+                log_it(L_ERROR, "Can't find previous transactions (hash=%s)", dap_hash_fast_to_str_static(&l_prev_tx_hash));
                 continue;
+            }
             uint8_t* l_prev_item = dap_chain_datum_tx_item_get_nth(l_tx_prev, TX_ITEM_TYPE_OUT, l_prev_idx);
-            if (!l_prev_item)
+            if (!l_prev_item){
+                log_it(L_ERROR, "Can't find out with index %d in transaction %s", l_prev_idx, dap_hash_fast_to_str_static(&l_prev_tx_hash));
                 continue;
-            uint8_t l_out_type = *(uint8_t *)it->data;
+            }
+            uint8_t l_out_type = *(uint8_t *)l_prev_item;
             switch(l_out_type){
                 case TX_ITEM_TYPE_OUT_OLD: {
-                    l_value = GET_256_FROM_64(((dap_chain_tx_out_old_t*)it->data)->header.value);
-                    l_addr_from = ((dap_chain_tx_out_old_t*)it->data)->addr;
+                    l_value = GET_256_FROM_64(((dap_chain_tx_out_old_t*)l_prev_item)->header.value);
+                    l_addr_from = ((dap_chain_tx_out_old_t*)l_prev_item)->addr;
                 } break;
                 case TX_ITEM_TYPE_OUT:
                 case TX_ITEM_TYPE_OUT_EXT: {
-                    l_value = ((dap_chain_tx_out_ext_t*)it->data)->header.value;
-                    l_addr_from = ((dap_chain_tx_out_ext_t*)it->data)->addr;
+                    l_value = ((dap_chain_tx_out_ext_t*)l_prev_item)->header.value;
+                    l_addr_from = ((dap_chain_tx_out_ext_t*)l_prev_item)->addr;
                 } break;
                 default:
                     continue;
             }
 
-            if(!dap_chain_addr_is_blank(&l_addr_from)  && dap_chain_addr_compare(&l_addr_from, a_addr) &&
+            if(!dap_chain_addr_is_blank(&l_addr_from) && 
+                dap_chain_addr_compare(&l_addr_from, a_addr) &&
                 l_addr_from.net_id.uint64 == a_chain->net_id.uint64
                 ){
                 pthread_rwlock_wrlock(&s_wallet_cache_rwlock);
@@ -830,12 +1003,6 @@ static int s_save_tx_cache_for_addr(dap_chain_t *a_chain, dap_chain_addr_t *a_ad
         }
     }
 
-    if (l_out_list)
-        dap_list_free(l_out_list);
-
-    if (l_in_list)
-        dap_list_free(l_in_list);
-
     return l_ret_val;
 }
 
diff --git a/modules/wallet/include/dap_chain_wallet_cache.h b/modules/wallet/include/dap_chain_wallet_cache.h
index 1be93e6468336411318833230552f8bf9c5f23c9..222543606932bf6cbea9639cb9e0d5a85e19587a 100644
--- a/modules/wallet/include/dap_chain_wallet_cache.h
+++ b/modules/wallet/include/dap_chain_wallet_cache.h
@@ -95,7 +95,9 @@ int dap_chain_wallet_cache_tx_find_in_history(dap_chain_addr_t *a_addr, char **a
 int dap_chain_wallet_cache_tx_find_outs_with_val(dap_chain_net_t *a_net, const char *a_token_ticker, const dap_chain_addr_t *a_addr, 
                                                     dap_list_t **a_outs_list, uint256_t a_value_needed, uint256_t *a_value_transfer);
 
-
+int dap_chain_wallet_cache_tx_find_outs(dap_chain_net_t *a_net, const char *a_token_ticker, const dap_chain_addr_t *a_addr, 
+                                                    dap_list_t **a_outs_list, uint256_t *a_value_transfer);
+                                                    
 dap_chain_wallet_cache_iter_t *dap_chain_wallet_cache_iter_create(dap_chain_addr_t a_addr);
 void dap_chain_wallet_cache_iter_delete(dap_chain_wallet_cache_iter_t *a_iter);
 dap_chain_datum_tx_t *dap_chain_wallet_cache_iter_get(dap_chain_wallet_cache_iter_t *a_iter, dap_chain_wallet_getting_type_t a_type);
\ No newline at end of file