diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c
index 38f4865fd73dabc5203415b336c6ff0cbfcd0c0a..6a31319fb60d1ca52080ae5d5ee4d98351f0f6dd 100644
--- a/modules/chain/dap_chain.c
+++ b/modules/chain/dap_chain.c
@@ -777,6 +777,7 @@ struct chain_thread_datum_removed_notifier {
     dap_chain_t *chain;
     dap_chain_cell_id_t cell_id;
     dap_hash_fast_t hash;
+    dap_chain_datum_t *datum;
     int ret_code;
 };
 
@@ -807,7 +808,7 @@ static bool s_notify_datum_removed_on_thread(void *a_arg)
 {
     struct chain_thread_datum_removed_notifier *l_arg = a_arg;
     assert(l_arg->callback);
-    l_arg->callback(l_arg->callback_arg, &l_arg->hash);
+    l_arg->callback(l_arg->callback_arg, &l_arg->hash, l_arg->datum);
     DAP_DELETE(l_arg);
     return false;
 }
@@ -928,7 +929,7 @@ void dap_chain_datum_notify(dap_chain_cell_t *a_chain_cell,  dap_hash_fast_t *a_
     }
 }
 
-void dap_chain_datum_removed_notify(dap_chain_cell_t *a_chain_cell,  dap_hash_fast_t *a_hash) {
+void dap_chain_datum_removed_notify(dap_chain_cell_t *a_chain_cell,  dap_hash_fast_t *a_hash, dap_chain_datum_t *a_datum) {
 #ifdef DAP_CHAIN_BLOCKS_TEST
     return;
 #endif
@@ -946,7 +947,7 @@ void dap_chain_datum_removed_notify(dap_chain_cell_t *a_chain_cell,  dap_hash_fa
         *l_arg = (struct chain_thread_datum_removed_notifier) {
             .callback = l_notifier->callback, .callback_arg = l_notifier->arg,
             .chain = a_chain_cell->chain,     .cell_id = a_chain_cell->id,
-            .hash = *a_hash};
+            .hash = *a_hash, .datum = a_datum};
         dap_proc_thread_callback_add_pri(l_notifier->proc_thread, s_notify_datum_removed_on_thread, l_arg, DAP_QUEUE_MSG_PRIORITY_LOW);
     }
 }
diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h
index 3e3076c70218941ad5c24c0cb7a34cacb675bdf6..348b5a071e8f051d2aea99826e6548bbe2f6c86b 100644
--- a/modules/chain/include/dap_chain.h
+++ b/modules/chain/include/dap_chain.h
@@ -128,7 +128,7 @@ typedef size_t (*dap_chain_callback_add_datums_t)(dap_chain_t * , dap_chain_datu
 typedef void (*dap_chain_callback_notify_t)(void *a_arg, dap_chain_t *a_chain, dap_chain_cell_id_t a_id, dap_chain_hash_fast_t *a_atom_hash, void *a_atom, size_t a_atom_size); //change in chain happened
 typedef void (*dap_chain_callback_datum_notify_t)(void *a_arg, dap_chain_hash_fast_t *a_datum_hash, dap_chain_hash_fast_t *a_atom_hash, void *a_datum, 
                                     size_t a_datum_size, int a_ret_code, uint32_t a_action, dap_chain_net_srv_uid_t a_uid); //change in chain happened
-typedef void (*dap_chain_callback_datum_removed_notify_t)(void *a_arg, dap_chain_hash_fast_t *a_datum_hash); //change in chain happened
+typedef void (*dap_chain_callback_datum_removed_notify_t)(void *a_arg, dap_chain_hash_fast_t *a_datum_hash, dap_chain_datum_t *a_datum); //change in chain happened
 
 typedef uint64_t (*dap_chain_callback_get_count)(dap_chain_t *a_chain);
 typedef dap_list_t *(*dap_chain_callback_get_list)(dap_chain_t *a_chain, size_t a_count, size_t a_page, bool a_reverse);
@@ -313,7 +313,7 @@ void dap_chain_add_callback_datum_removed_from_index_notify(dap_chain_t *a_chain
 void dap_chain_atom_confirmed_notify_add(dap_chain_t *a_chain, dap_chain_callback_notify_t a_callback, void *a_arg, uint64_t a_conf_cnt);
 void dap_chain_atom_notify(dap_chain_cell_t *a_chain_cell,  dap_hash_fast_t *a_hash, const uint8_t *a_atom, size_t a_atom_size);
 void dap_chain_datum_notify(dap_chain_cell_t *a_chain_cell,  dap_hash_fast_t *a_hash, dap_hash_fast_t *a_atom_hash, const uint8_t *a_datum, size_t a_datum_size, int a_ret_code, uint32_t a_action, dap_chain_net_srv_uid_t a_uid);
-void dap_chain_datum_removed_notify(dap_chain_cell_t *a_chain_cell,  dap_hash_fast_t *a_hash);
+void dap_chain_datum_removed_notify(dap_chain_cell_t *a_chain_cell,  dap_hash_fast_t *a_hash, dap_chain_datum_t *a_datum);
 void dap_chain_atom_add_from_threshold(dap_chain_t *a_chain);
 dap_chain_atom_ptr_t dap_chain_get_atom_by_hash(dap_chain_t * a_chain, dap_chain_hash_fast_t * a_atom_hash, size_t * a_atom_size);
 bool dap_chain_get_atom_last_hash_num(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_atom_hash, uint64_t *a_atom_num);
diff --git a/modules/net/dap_chain_node_cli.c b/modules/net/dap_chain_node_cli.c
index a5df1f47e44369642a25bd747c09a17330847d99..5faac2932007afb9fc02e5d573a9f7dbbd9ec26f 100644
--- a/modules/net/dap_chain_node_cli.c
+++ b/modules/net/dap_chain_node_cli.c
@@ -159,7 +159,7 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
                             "wallet info {-addr <addr> | -w <wallet_name>} -net <net_name>\n"
                             "wallet activate -w <wallet_name> -password <password> [-ttl <password_ttl_in_minutes>]\n"
                             "wallet deactivate -w <wallet_name>>\n"
-                            "wallet outputs {-addr <addr> | -w <wallet_name>} -net <net_name> -token <token_tiker> [-value <uint256_value>]"
+                            "wallet outputs {-addr <addr> | -w <wallet_name>} -net <net_name> -token <token_tiker> [-value <uint256_value>]\n"
                             "wallet convert -w <wallet_name> {-password <password> | -remove_password }\n");
 
 
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index b8cee60244afcc3b1505a6f5c8f782a1c8106e89..9cea97c5224afea5a87951b58ec9fd51bcf8ad59 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -1795,8 +1795,10 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
             dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-value", &l_value_str);
 
             dap_list_t *l_outs_list = NULL;
-
             uint256_t l_value_sum = uint256_0;
+
+
+
             if (l_value_str){
                 uint256_t l_value_datoshi = dap_chain_balance_scan(l_value_str);
                 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))
diff --git a/modules/net/dap_chain_node_cli_cmd_tx.c b/modules/net/dap_chain_node_cli_cmd_tx.c
index ec97601064776001617bb46cc8c134d35f065a07..afb5d99d285584e3c32b8d6df9ea5a7c21057b63 100644
--- a/modules/net/dap_chain_node_cli_cmd_tx.c
+++ b/modules/net/dap_chain_node_cli_cmd_tx.c
@@ -404,11 +404,7 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t
         uint256_t l_corr_value = {}, l_cond_value = {};
         bool l_recv_from_cond = false, l_send_to_same_cond = false;
         json_object *l_corr_object = NULL, *l_cond_recv_object = NULL, *l_cond_send_object = NULL;
-        dap_list_t *l_list_in_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_IN_ALL, NULL);
-        if (!l_list_in_items) // a bad tx
-            goto next_step;
-        // all in items should be from the same address
-        
+           
         dap_chain_addr_t *l_src_addr = NULL;
         bool l_base_tx = false, l_reward_collect = false;
         const char *l_noaddr_token = NULL;
@@ -421,23 +417,26 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t
         dap_hash_fast_t l_atom_hash = l_from_cache ? *l_wallet_cache_iter->cur_atom_hash : *l_datum_iter->cur_atom_hash;
 
         int l_src_subtype = DAP_CHAIN_TX_OUT_COND_SUBTYPE_UNDEFINED;
-        for (dap_list_t *it = l_list_in_items; it; it = it->next) {
+        uint8_t *l_tx_item = NULL;
+        size_t l_size; int i, q = 0;
+        // Проход по входам
+        TX_ITEM_ITER_TX_TYPE(l_tx_item, TX_ITEM_TYPE_IN_ALL, l_size, i, l_tx) {
             dap_chain_hash_fast_t *l_tx_prev_hash = NULL;
             int l_tx_prev_out_idx;
             dap_chain_datum_tx_t *l_tx_prev = NULL;
-            switch (*(byte_t *)it->data) {
+            switch (*l_tx_item) {
             case TX_ITEM_TYPE_IN: {
-                dap_chain_tx_in_t *l_tx_in = (dap_chain_tx_in_t *)it->data;
+                dap_chain_tx_in_t *l_tx_in = (dap_chain_tx_in_t *)l_tx_item;
                 l_tx_prev_hash = &l_tx_in->header.tx_prev_hash;
                 l_tx_prev_out_idx = l_tx_in->header.tx_out_prev_idx;
             } break;
             case TX_ITEM_TYPE_IN_COND: {
-                dap_chain_tx_in_cond_t *l_tx_in_cond = (dap_chain_tx_in_cond_t *)it->data;
+                dap_chain_tx_in_cond_t *l_tx_in_cond = (dap_chain_tx_in_cond_t *)l_tx_item;
                 l_tx_prev_hash = &l_tx_in_cond->header.tx_prev_hash;
                 l_tx_prev_out_idx = l_tx_in_cond->header.tx_out_prev_idx;
             } break;
             case TX_ITEM_TYPE_IN_EMS: {
-                dap_chain_tx_in_ems_t *l_tx_in_ems = (dap_chain_tx_in_ems_t *)it->data;
+                dap_chain_tx_in_ems_t *l_tx_in_ems = (dap_chain_tx_in_ems_t *)l_tx_item;
                 l_base_tx = true;
                 l_noaddr_token = l_tx_in_ems->header.ticker;
             } break;
@@ -482,7 +481,6 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t
                 break;  //it's not our addr
             
         }        
-        dap_list_free(l_list_in_items);
 
         // find OUT items
         bool l_header_printed = false;
diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c
index 14df28a1a67504b7f25cb59d65efaf328d442a56..f12cf616b22d290f9db8cbeb0e3b50bb021a2278 100644
--- a/modules/type/blocks/dap_chain_cs_blocks.c
+++ b/modules/type/blocks/dap_chain_cs_blocks.c
@@ -1625,7 +1625,7 @@ static int s_delete_atom_datums(dap_chain_cs_blocks_t *a_blocks, dap_chain_block
             HASH_DEL(PVT(a_blocks)->datum_index, l_datum_index);
             // notify datum removed
             dap_chain_cell_t *l_cell = dap_chain_cell_find_by_id(a_blocks->chain, a_blocks->chain->active_cell_id);
-            dap_chain_datum_removed_notify(l_cell, l_datum_hash);
+            dap_chain_datum_removed_notify(l_cell, l_datum_hash, l_datum);
         }
     }
     debug_if(s_debug_more, L_DEBUG, "Block %s checked, %s", a_block_cache->block_hash_str,
diff --git a/modules/wallet/dap_chain_wallet_cache.c b/modules/wallet/dap_chain_wallet_cache.c
index 79d8b3725ef3998e78ee9197ed242412237b940b..7406ade2f6e2264d109edaf15d9106706626ee7b 100644
--- a/modules/wallet/dap_chain_wallet_cache.c
+++ b/modules/wallet/dap_chain_wallet_cache.c
@@ -58,13 +58,13 @@ typedef enum dap_s_wallets_cache_type{
 
 typedef struct dap_wallet_tx_cache_input{
     dap_chain_hash_fast_t tx_prev_hash; 
-    uint32_t tx_out_prev_idx;
+    int tx_out_prev_idx;
     uint256_t value;
 } dap_wallet_tx_cache_input_t;
 
 typedef struct dap_wallet_tx_cache_output{
     void* tx_out;
-    uint32_t tx_out_idx;
+    int tx_out_idx;
 } dap_wallet_tx_cache_output_t;
 
 typedef struct dap_wallet_tx_cache {
@@ -81,9 +81,24 @@ typedef struct dap_wallet_tx_cache {
     UT_hash_handle hh;
 } dap_wallet_tx_cache_t;
 
+typedef struct unspent_cache_hh_key {
+    dap_hash_fast_t tx_hash;
+    int out_idx;
+} DAP_ALIGN_PACKED unspent_cache_hh_key;
+
+typedef struct dap_wallet_cache_unspent_outs {
+    unspent_cache_hh_key key;
+    dap_wallet_tx_cache_output_t *output;
+    char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX];
+    
+    UT_hash_handle hh;
+} dap_wallet_cache_unspent_outs_t;
+
 typedef struct dap_s_wallets_cache {
     dap_chain_addr_t wallet_addr;
     dap_wallet_tx_cache_t *wallet_txs;
+    dap_wallet_cache_unspent_outs_t *unspent_outputs;
+
     _Atomic bool is_loading;
     UT_hash_handle hh;
 } dap_wallet_cache_t;
@@ -105,7 +120,7 @@ static int s_save_cache_for_addr_in_net(dap_chain_net_t *a_net, dap_chain_addr_t
 static void s_callback_datum_notify(void *a_arg, dap_chain_hash_fast_t *a_datum_hash, dap_hash_fast_t *a_atom_hash, void *a_datum, 
                                     size_t a_datum_size, int a_ret_code, uint32_t a_action, 
                                     dap_chain_net_srv_uid_t a_uid);
-static void s_callback_datum_removed_notify(void *a_arg, dap_chain_hash_fast_t *a_datum_hash);
+static void s_callback_datum_removed_notify(void *a_arg, dap_chain_hash_fast_t *a_datum_hash, dap_chain_datum_t *a_datum);
 static void s_wallet_opened_callback(dap_chain_wallet_t *a_wallet, void *a_arg);
 
 static char * s_wallet_cache_type_to_str(dap_s_wallets_cache_type_t a_type)
@@ -347,19 +362,14 @@ int dap_chain_wallet_cache_tx_find_in_history(dap_chain_addr_t *a_addr, char **a
     return 0;
 }
 
-
-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_need, 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_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 (s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_DISABLED){
-        return -101;
-    }
-
     if (!a_token_ticker){
         log_it(L_ERROR, "Token ticker is not specified.");
         return -100;
@@ -370,11 +380,6 @@ int dap_chain_wallet_cache_tx_find_outs_with_val(dap_chain_net_t *a_net, const c
         return -100;
     }
 
-    if (IS_ZERO_256(a_value_need)){
-        log_it(L_ERROR, "Needed value is zero.");
-        return -100;
-    }
-
     if (a_outs_list == NULL){
         log_it(L_ERROR, "a_outs_list is NULL");
         return -100;
@@ -383,129 +388,73 @@ 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 || l_wallet_item->is_loading){
+    if (!l_wallet_item){
         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;
+    dap_wallet_cache_unspent_outs_t *l_item_cur = NULL, *l_tmp = NULL;
+    HASH_ITER(hh, l_wallet_item->unspent_outputs, l_item_cur, l_tmp){
 
-        
-        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)
+        if (dap_strcmp(l_item_cur->token_ticker, a_token_ticker))
             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:
+        else {
+            dap_wallet_tx_cache_output_t *l_out_cur = (dap_wallet_tx_cache_output_t*)l_item_cur->output;
+            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;
-                }
-                // 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);
-                    // already accumulated the required value, finish the search for 'out' items
-                    if ( compare256(l_value_transfer, a_value_need) >= 0 ) {
-                        break;
-                    }
-                }
-            }
-        } 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:
+                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;
-                }
-                // 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);
-                    // already accumulated the required value, finish the search for 'out' items
-                    if ( compare256(l_value_transfer, a_value_need) >= 0 ) {
-                        break;
-                    }
-                }
+                l_value = l_out->header.value;
+            } break;
+            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;
             }
-        }
-        if ( compare256(l_value_transfer, a_value_need) >= 0 ) {
-            break;
-        }
+
+            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_item_cur->key.tx_hash, (uint32_t)l_item_cur->key.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);
 
-    if (compare256(l_value_transfer, a_value_need) >= 0 && l_list_used_out){
-        *a_outs_list = l_list_used_out;
-        if (a_value_transfer)
-            *a_value_transfer = l_value_transfer;
-    } else {
-        *a_outs_list = NULL;
-        dap_list_free(l_list_used_out);
-        if (a_value_transfer)
-            *a_value_transfer = uint256_0;
-    }
+    *a_outs_list = l_list_used_out;
+    if (a_value_transfer)
+        *a_value_transfer = l_value_transfer;
    
     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)
+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_need, 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 (s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_DISABLED){
+        return -101;
+    }
+
     if (!a_token_ticker){
         log_it(L_ERROR, "Token ticker is not specified.");
         return -100;
@@ -516,6 +465,11 @@ int dap_chain_wallet_cache_tx_find_outs(dap_chain_net_t *a_net, const char *a_to
         return -100;
     }
 
+    if (IS_ZERO_256(a_value_need)){
+        log_it(L_ERROR, "Needed value is zero.");
+        return -100;
+    }
+
     if (a_outs_list == NULL){
         log_it(L_ERROR, "a_outs_list is NULL");
         return -100;
@@ -529,94 +483,62 @@ int dap_chain_wallet_cache_tx_find_outs(dap_chain_net_t *a_net, const char *a_to
         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;
+    dap_wallet_cache_unspent_outs_t *l_item_cur = NULL, *l_tmp = NULL;
+    HASH_ITER(hh, l_wallet_item->unspent_outputs, l_item_cur, l_tmp){
 
-        
-        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)
+        if (dap_strcmp(l_item_cur->token_ticker, a_token_ticker))
             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:
+        else {
+            dap_wallet_tx_cache_output_t *l_out_cur = (dap_wallet_tx_cache_output_t*)l_item_cur->output;
+            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;
-                }
-                // 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:
+                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;
-                }
-                // 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);
-                }
+                l_value = l_out->header.value;
+            } break;
+            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;
             }
+
+            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_item_cur->key.tx_hash, (uint32_t)l_item_cur->key.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);
+        } 
+        if ( compare256(l_value_transfer, a_value_need) >= 0 ) {
+            break;
         }
     }
     pthread_rwlock_unlock(&s_wallet_cache_rwlock);
 
-    *a_outs_list = l_list_used_out;
-    if (a_value_transfer)
-        *a_value_transfer = l_value_transfer;
+    if (compare256(l_value_transfer, a_value_need) >= 0 && l_list_used_out){
+        *a_outs_list = l_list_used_out;
+        if (a_value_transfer)
+            *a_value_transfer = l_value_transfer;
+    } else {
+        *a_outs_list = NULL;
+        dap_list_free_full(l_list_used_out, NULL);
+        if (a_value_transfer)
+            *a_value_transfer = uint256_0;
+    }
    
     return 0;
 }
@@ -627,25 +549,30 @@ static int s_save_tx_into_wallet_cache(dap_chain_t *a_chain, dap_chain_datum_tx_
     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;
+    int l_out_idx = 0, i = 0;
+    uint8_t *l_tx_item = NULL;
+    size_t l_size;
+    TX_ITEM_ITER_TX_TYPE(l_tx_item, TX_ITEM_TYPE_OUT_ALL, l_size, i, a_tx) {
+        uint8_t l_out_type = *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) && 
@@ -676,21 +603,33 @@ static int s_save_tx_into_wallet_cache(dap_chain_t *a_chain, dap_chain_datum_tx_
             } 
             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);
+            // Add unspent out into cache
+            if (!a_ret_code){
+                dap_wallet_cache_unspent_outs_t *l_unspent_out = DAP_NEW_Z(dap_wallet_cache_unspent_outs_t);
+                l_unspent_out->key.tx_hash = *a_tx_hash;
+                l_unspent_out->key.out_idx = l_out_idx;
+                l_unspent_out->output = l_out;
+                if (l_out_type != TX_ITEM_TYPE_OUT_EXT)
+                    dap_strncpy(l_unspent_out->token_ticker, a_main_token_ticker ? a_main_token_ticker : "0", DAP_CHAIN_TICKER_SIZE_MAX);
+                else
+                    dap_strncpy(l_unspent_out->token_ticker, ((dap_chain_tx_out_ext_t*)l_tx_item)->token, DAP_CHAIN_TICKER_SIZE_MAX);
+                HASH_ADD(hh, l_wallet_item->unspent_outputs, key, sizeof(unspent_cache_hh_key), l_unspent_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_in_list; it; it=it->next ){
-        uint8_t l_cond_type = *(uint8_t *)it->data;
+    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_t *l_prev_datum = a_chain->callback_datum_find_by_hash(a_chain, &l_prev_tx_hash, NULL, NULL);
@@ -750,18 +689,22 @@ static int s_save_tx_into_wallet_cache(dap_chain_t *a_chain, dap_chain_datum_tx_
                 l_tx_in->tx_out_prev_idx = l_prev_idx;
                 l_tx_in->value = l_value;
                 l_wallet_tx_item->tx_wallet_inputs = dap_list_append(l_wallet_tx_item->tx_wallet_inputs, l_tx_in);
+                if (!a_ret_code){
+                    unspent_cache_hh_key key = {0};
+                    key.tx_hash = l_prev_tx_hash;
+                    key.out_idx = l_prev_idx;
+                    dap_wallet_cache_unspent_outs_t *l_item = NULL;
+                    HASH_FIND(hh, l_wallet_item->unspent_outputs, &key, sizeof(unspent_cache_hh_key), l_item);
+                    if (l_item){
+                        HASH_DEL(l_wallet_item->unspent_outputs, l_item);
+                        DAP_DELETE(l_item);
+                    }
+                }
                 pthread_rwlock_unlock(&s_wallet_cache_rwlock);
             }
-
         }
     }
 
-    if (l_out_list)
-        dap_list_free(l_out_list);
-
-    if (l_in_list)
-        dap_list_free(l_in_list);
-
     return l_ret_val;
 }
 
@@ -925,6 +868,18 @@ static int s_save_tx_cache_for_addr(dap_chain_t *a_chain, dap_chain_addr_t *a_ad
             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);
+            // Add unspent out into cache
+            if (!a_ret_code){
+                dap_wallet_cache_unspent_outs_t *l_unspent_out = DAP_NEW_Z(dap_wallet_cache_unspent_outs_t);
+                l_unspent_out->key.tx_hash = *a_tx_hash;
+                l_unspent_out->key.out_idx = l_out_idx;
+                l_unspent_out->output = l_out;
+                if (l_out_type != TX_ITEM_TYPE_OUT_EXT)
+                    dap_strncpy(l_unspent_out->token_ticker, a_main_token_ticker ? a_main_token_ticker : "0", DAP_CHAIN_TICKER_SIZE_MAX);
+                else
+                    dap_strncpy(l_unspent_out->token_ticker, ((dap_chain_tx_out_ext_t*)l_tx_item)->token, DAP_CHAIN_TICKER_SIZE_MAX);
+                HASH_ADD(hh, l_wallet_item->unspent_outputs, key, sizeof(unspent_cache_hh_key), l_unspent_out);
+            }
             pthread_rwlock_unlock(&s_wallet_cache_rwlock);
         }
         l_out_idx++;
@@ -947,20 +902,18 @@ static int s_save_tx_cache_for_addr(dap_chain_t *a_chain, dap_chain_addr_t *a_ad
                 continue;
             }
             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));
+            if (!l_prev_item)
                 continue;
-            }
-            uint8_t l_out_type = *(uint8_t *)l_prev_item;
+            uint8_t l_out_type = *(uint8_t *)l_tx_item;
             switch(l_out_type){
                 case TX_ITEM_TYPE_OUT_OLD: {
-                    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;
+                    l_value = GET_256_FROM_64(((dap_chain_tx_out_old_t*)l_tx_item)->header.value);
+                    l_addr_from = ((dap_chain_tx_out_old_t*)l_tx_item)->addr;
                 } break;
                 case TX_ITEM_TYPE_OUT:
                 case TX_ITEM_TYPE_OUT_EXT: {
-                    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;
+                    l_value = ((dap_chain_tx_out_ext_t*)l_tx_item)->header.value;
+                    l_addr_from = ((dap_chain_tx_out_ext_t*)l_tx_item)->addr;
                 } break;
                 default:
                     continue;
@@ -997,37 +950,166 @@ static int s_save_tx_cache_for_addr(dap_chain_t *a_chain, dap_chain_addr_t *a_ad
                 l_tx_in->tx_out_prev_idx = l_prev_idx;
                 l_tx_in->value = l_value;
                 l_wallet_tx_item->tx_wallet_inputs = dap_list_append(l_wallet_tx_item->tx_wallet_inputs, l_tx_in);
+                // Delete unspent out from unspent outs cache
+                if (!a_ret_code){
+                    unspent_cache_hh_key key;
+                    key.tx_hash = l_prev_tx_hash;
+                    key.out_idx = l_prev_idx;
+                    dap_wallet_cache_unspent_outs_t *l_item = NULL;
+                    HASH_FIND(hh, l_wallet_item->unspent_outputs, &key, sizeof(unspent_cache_hh_key), l_item);
+                    if (l_item){
+                        HASH_DEL(l_wallet_item->unspent_outputs, l_item);
+                        DAP_DELETE(l_item);
+                    }
+                }                
                 pthread_rwlock_unlock(&s_wallet_cache_rwlock);
             }
-
         }
     }
 
     return l_ret_val;
 }
 
-static void s_callback_datum_removed_notify(void *a_arg, dap_chain_hash_fast_t *a_datum_hash)
+static void s_callback_datum_removed_notify(void *a_arg, dap_chain_hash_fast_t *a_datum_hash, dap_chain_datum_t *a_datum)
 {
-    if (!a_datum_hash)
+    if (!a_datum_hash || !a_datum || a_datum->header.type_id != DAP_CHAIN_DATUM_TX)
         return;
 
-    pthread_rwlock_wrlock(&s_wallet_cache_rwlock);
-    dap_wallet_cache_t *l_wallet_item = NULL, *l_tmp;
-    HASH_ITER(hh, s_wallets_cache, l_wallet_item, l_tmp){
-        dap_wallet_tx_cache_t *l_wallet_tx_item = NULL;
-        HASH_FIND(hh, l_wallet_item->wallet_txs, a_datum_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
-        if (l_wallet_tx_item){
-            HASH_DEL(l_wallet_item->wallet_txs, l_wallet_tx_item);
-            dap_list_free_full(l_wallet_tx_item->tx_wallet_inputs, NULL);
-            dap_list_free_full(l_wallet_tx_item->tx_wallet_outputs, NULL);
-            DAP_DEL_Z(l_wallet_tx_item);
+    dap_atom_notify_arg_t *l_arg = (dap_atom_notify_arg_t*)a_arg;
+    dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*)a_datum->data;
+    int l_out_idx = 0, i = 0;
+    uint8_t *l_tx_item = NULL;
+    size_t l_size;
+    // remove this tx outs from unspent outs cache
+    TX_ITEM_ITER_TX_TYPE(l_tx_item, TX_ITEM_TYPE_OUT_ALL, l_size, i, l_tx) {
+        uint8_t l_out_type = *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*)l_tx_item)->addr;
+            } break;
+            case TX_ITEM_TYPE_OUT: {
+                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*)l_tx_item)->addr;
+            } break;
+            default:{
+                l_out_idx++;
+                continue;
+            }   
+        }
+
+        if(!dap_chain_addr_is_blank(&l_addr) && 
+                ((s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_LOCAL &&
+                dap_chain_wallet_addr_cache_get_name(&l_addr) != NULL) || s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_ALL) &&
+                l_addr.net_id.uint64 == l_arg->chain->net_id.uint64
+            ){
+            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){
+                dap_wallet_tx_cache_t *l_wallet_tx_item = NULL;
+                HASH_FIND(hh, l_wallet_item->wallet_txs, a_datum_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
+                if (l_wallet_tx_item){
+                    HASH_DEL(l_wallet_item->wallet_txs, l_wallet_tx_item);
+                    dap_list_free_full(l_wallet_tx_item->tx_wallet_inputs, NULL);
+                    dap_list_free_full(l_wallet_tx_item->tx_wallet_outputs, NULL);
+                    DAP_DEL_Z(l_wallet_tx_item);
+                }
+                if (!l_wallet_item->wallet_txs){
+                    HASH_DEL(s_wallets_cache, l_wallet_item);
+                    DAP_DEL_Z(l_wallet_item);
+                }
+                                
+                unspent_cache_hh_key key = {0};
+                key.tx_hash = *a_datum_hash;
+                key.out_idx = l_out_idx;
+                dap_wallet_cache_unspent_outs_t *l_item = NULL;
+                HASH_FIND(hh, l_wallet_item->unspent_outputs, &key, sizeof(unspent_cache_hh_key), l_item);
+                if (l_item){
+                    HASH_DEL(l_wallet_item->unspent_outputs, l_item);
+                    DAP_DELETE(l_item);
+                }
+            }
+            pthread_rwlock_unlock(&s_wallet_cache_rwlock);
         }
-        if (!l_wallet_item->wallet_txs){
-            HASH_DEL(s_wallets_cache, l_wallet_item);
-            DAP_DEL_Z(l_wallet_item);
-        }            
+        l_out_idx++;
     }
-    pthread_rwlock_unlock(&s_wallet_cache_rwlock);
+
+    // return previous transactions outs to unspent outs cache
+    TX_ITEM_ITER_TX_TYPE(l_tx_item, TX_ITEM_TYPE_IN_ALL, l_size, i, l_tx) {
+        uint8_t l_cond_type = *l_tx_item;
+        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*)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 *)(l_arg->chain->callback_datum_find_by_hash(l_arg->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_ALL, l_prev_idx);
+            if (!l_prev_item)
+                continue;
+            uint8_t l_out_type = *(uint8_t *)l_prev_item;
+            switch(l_out_type){
+                case TX_ITEM_TYPE_OUT_OLD: {
+                    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_addr_from = ((dap_chain_tx_out_ext_t*)l_prev_item)->addr;
+                } break;
+                default:
+                    continue;
+            }
+
+            if(!dap_chain_addr_is_blank(&l_addr_from) && ((s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_LOCAL &&
+                dap_chain_wallet_addr_cache_get_name(&l_addr_from) != NULL) || s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_ALL) &&
+                l_addr_from.net_id.uint64 == l_arg->chain->net_id.uint64
+                ){
+                pthread_rwlock_wrlock(&s_wallet_cache_rwlock);
+                dap_wallet_cache_t *l_wallet_item = NULL;
+                HASH_FIND(hh, s_wallets_cache, &l_addr_from, sizeof(dap_chain_addr_t), l_wallet_item);
+                if (l_wallet_item){
+                    dap_wallet_tx_cache_t *l_wallet_tx_item = NULL;
+                    HASH_FIND(hh, l_wallet_item->wallet_txs, a_datum_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
+                    if (l_wallet_tx_item){
+                        HASH_DEL(l_wallet_item->wallet_txs, l_wallet_tx_item);
+                        dap_list_free_full(l_wallet_tx_item->tx_wallet_inputs, NULL);
+                        dap_list_free_full(l_wallet_tx_item->tx_wallet_outputs, NULL);
+                        DAP_DEL_Z(l_wallet_tx_item);
+                    }
+                    // Add unspent out into cache
+                    dap_wallet_tx_cache_t *l_wallet_prev_tx_item = NULL;
+                    HASH_FIND(hh, l_wallet_item->wallet_txs, &l_prev_tx_hash, sizeof(dap_hash_fast_t), l_wallet_prev_tx_item);
+                    if (l_wallet_prev_tx_item){
+                        if (!l_wallet_prev_tx_item->ret_code){
+                            void *l_out = NULL;
+                            for (dap_list_t *it = l_wallet_prev_tx_item->tx_wallet_outputs; it; it=it->next){
+                                if (((dap_wallet_tx_cache_output_t *)it->data)->tx_out_idx == l_prev_idx)
+                                    l_out = ((dap_wallet_tx_cache_output_t *)it->data)->tx_out;
+                            }
+                            if (l_out){
+                                dap_wallet_cache_unspent_outs_t *l_unspent_out = DAP_NEW_Z(dap_wallet_cache_unspent_outs_t);
+                                l_unspent_out->key.tx_hash = l_prev_tx_hash;
+                                l_unspent_out->key.out_idx = l_prev_idx;
+                                l_unspent_out->output = l_out;
+                                if (l_out_type != TX_ITEM_TYPE_OUT_EXT)
+                                    dap_strncpy(l_unspent_out->token_ticker, l_wallet_prev_tx_item->token_ticker, DAP_CHAIN_TICKER_SIZE_MAX);
+                                else
+                                    dap_strncpy(l_unspent_out->token_ticker, ((dap_chain_tx_out_ext_t*)l_tx_item)->token, DAP_CHAIN_TICKER_SIZE_MAX);
+                                HASH_ADD(hh, l_wallet_item->unspent_outputs, key, sizeof(unspent_cache_hh_key), l_unspent_out);
+                            }
+                        }   
+                    }
+                    
+                }
+                pthread_rwlock_unlock(&s_wallet_cache_rwlock);
+            }               
+        }
+    }            
 }
 
 
diff --git a/modules/wallet/include/dap_chain_wallet_cache.h b/modules/wallet/include/dap_chain_wallet_cache.h
index 197dcc65650f070ad3adfe4a337532b6acb303ca..3b109800841159e0f719fe2c0e09c0b2f9ef6133 100644
--- a/modules/wallet/include/dap_chain_wallet_cache.h
+++ b/modules/wallet/include/dap_chain_wallet_cache.h
@@ -99,10 +99,10 @@ 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);