diff --git a/dap_chain.c b/dap_chain.c
index dfd585c0cdfe2cba3ca1122d6aae4d5bcaefe235..56a43f8fde8808720ec85cfe987e76d453206d32 100755
--- a/dap_chain.c
+++ b/dap_chain.c
@@ -165,6 +165,8 @@ void dap_chain_delete(dap_chain_t * a_chain)
     }else
        log_it(L_WARNING,"Trying to remove non-existent 0x%16llX:0x%16llX chain",a_chain->id.uint64,
               a_chain->net_id.uint64);
+    a_chain->datum_types_count = 0;
+    DAP_DELETE (a_chain->datum_types);
     pthread_rwlock_unlock(&s_chain_items_rwlock);
 }
 
@@ -239,6 +241,15 @@ dap_chain_t * dap_chain_load_from_cfg(dap_ledger_t* a_ledger, const char * a_cha
                 return NULL;
             }
 
+            // Read chain datum types
+            char** l_datum_types = NULL;
+            uint16_t l_datum_types_count = 0;
+            if((l_datum_types = dap_config_get_array_str(l_cfg, "chain", "datum_types", &l_datum_types_count)) == NULL) {
+                log_it(L_WARNING, "Can't read chain datum types ", l_chain_id_str);
+                //dap_config_close(l_cfg);
+                //return NULL;
+            }
+
             l_chain =  dap_chain_create(a_ledger,a_chain_net_name,l_chain_name, a_chain_net_id,l_chain_id);
             if ( dap_chain_cs_create(l_chain, l_cfg) == 0 ) {
                 log_it (L_NOTICE,"Consensus initialized for chain id 0x%016llX",
@@ -248,6 +259,7 @@ dap_chain_t * dap_chain_load_from_cfg(dap_ledger_t* a_ledger, const char * a_cha
                     DAP_CHAIN_PVT ( l_chain)->file_storage_dir = strdup (
                                 dap_config_get_item_str( l_cfg , "files","storage_dir" ) ) ;
                     if ( dap_chain_load_all( l_chain ) != 0 ){
+                        dap_chain_save_all( l_chain );
                         log_it (L_NOTICE, "Loaded chain files");
                     }else {
                         dap_chain_save_all( l_chain );
@@ -264,6 +276,26 @@ dap_chain_t * dap_chain_load_from_cfg(dap_ledger_t* a_ledger, const char * a_cha
                 dap_chain_delete(l_chain);
                 l_chain = NULL;
             }
+            // add datum types
+            if(l_chain && l_datum_types_count > 0) {
+                l_chain->datum_types = DAP_NEW_SIZE(dap_chain_type_t, l_datum_types_count * sizeof(dap_chain_type_t));
+                uint16_t l_count_recognized = 0;
+                for(uint16_t i = 0; i < l_datum_types_count; i++) {
+                    if(!dap_strcmp(l_datum_types[i], "token")) {
+                        l_chain->datum_types[l_count_recognized] = CHAIN_TYPE_TOKEN;
+                        l_count_recognized++;
+                    }
+                    else if(!dap_strcmp(l_datum_types[i], "emission")) {
+                        l_chain->datum_types[l_count_recognized] = CHAIN_TYPE_EMISSION;
+                        l_count_recognized++;
+                    }
+                    else if(!dap_strcmp(l_datum_types[i], "transaction")) {
+                        l_chain->datum_types[l_count_recognized] = CHAIN_TYPE_TX;
+                        l_count_recognized++;
+                    }
+                }
+                l_chain->datum_types_count = l_count_recognized;
+            }
 
             dap_config_close(l_cfg);
             return l_chain;
@@ -312,11 +344,13 @@ int dap_chain_save_all (dap_chain_t * l_chain)
  */
 int dap_chain_load_all (dap_chain_t * l_chain)
 {
-    int ret = -2;
+    int l_ret = -2;
+    if(!l_chain)
+        return l_ret;
     DIR * l_dir = opendir(DAP_CHAIN_PVT(l_chain)->file_storage_dir);
     if( l_dir ) {
         struct dirent * l_dir_entry;
-        ret = -1;
+        l_ret = -1;
         while((l_dir_entry=readdir(l_dir))!=NULL){
             const char * l_filename = l_dir_entry->d_name;
             size_t l_filename_len = strlen (l_filename);
@@ -327,15 +361,13 @@ int dap_chain_load_all (dap_chain_t * l_chain)
                 size_t l_suffix_len = strlen(l_suffix);
                 if (strncmp(l_filename+ l_filename_len-l_suffix_len,l_suffix,l_suffix_len) == 0 ){
                     if ( dap_chain_cell_load(l_chain,l_filename) == 0 )
-                        ret = 0;
+                        l_ret = 0;
                 }
             }
-
         }
         closedir(l_dir);
-
     }
-    return  ret;
+    return l_ret;
 }
 
 /**
diff --git a/dap_chain.h b/dap_chain.h
index 91a0d90b2f3dcb52cfde6e28835587d15fb60920..04e81474e3919acad29b475a3274ceeec833e1f1 100755
--- a/dap_chain.h
+++ b/dap_chain.h
@@ -64,6 +64,7 @@ typedef size_t (*dap_chain_callback_atom_hdr_get_size_t)(dap_chain_atom_ptr_t );
 typedef dap_chain_atom_iter_t* (*dap_chain_callback_atom_iter_create_t)(dap_chain_t * );
 typedef dap_chain_atom_iter_t* (*dap_chain_callback_atom_iter_create_from_t)(dap_chain_t * ,dap_chain_atom_ptr_t);
 typedef dap_chain_atom_ptr_t (*dap_chain_callback_atom_iter_get_first_t)(dap_chain_atom_iter_t * );
+typedef dap_chain_datum_t* (*dap_chain_callback_atom_get_datum)(dap_chain_atom_ptr_t );
 typedef dap_chain_atom_ptr_t (*dap_chain_callback_atom_iter_find_by_hash_t)(dap_chain_atom_iter_t * ,dap_chain_hash_fast_t *);
 
 typedef dap_chain_atom_ptr_t * (*dap_chain_callback_atom_iter_get_atoms_t)(dap_chain_atom_iter_t * ,size_t * );
@@ -75,6 +76,14 @@ typedef size_t (*dap_chain_datum_callback_datum_pool_proc_add_t)(dap_chain_t * ,
 typedef size_t (*dap_chain_datum_callback_datum_pool_proc_add_with_group_t)(dap_chain_t * , dap_chain_datum_t **, size_t, const char *);
 
 
+typedef  enum dap_chain_type
+{
+    CHAIN_TYPE_FIRST,
+    CHAIN_TYPE_TOKEN,
+    CHAIN_TYPE_EMISSION,
+    CHAIN_TYPE_TX,
+    CHAIN_TYPE_LAST
+} dap_chain_type_t;
 
 typedef struct dap_chain{
     dap_chain_id_t id;
@@ -87,6 +96,9 @@ typedef struct dap_chain{
     // Nested cells (hashtab by cell_id
     dap_chain_cell_t * cells;
 
+    uint16_t datum_types_count;
+    dap_chain_type_t *datum_types;
+
     // To hold it in double-linked lists
     struct dap_chain * next;
     struct dap_chain * prev;
@@ -107,6 +119,8 @@ typedef struct dap_chain{
     dap_chain_callback_atom_iter_create_t callback_atom_iter_create;
     dap_chain_callback_atom_iter_create_from_t callback_atom_iter_create_from;
     dap_chain_callback_atom_iter_get_first_t callback_atom_iter_get_first;
+    dap_chain_callback_atom_get_datum callback_atom_get_datum;
+
     dap_chain_callback_atom_iter_find_by_hash_t callback_atom_find_by_hash;
     dap_chain_callback_atom_iter_get_next_t callback_atom_iter_get_next;
     dap_chain_callback_atom_iter_get_atoms_t callback_atom_iter_get_links;
diff --git a/dap_chain_cell.c b/dap_chain_cell.c
index 025e45a7481d2a95f69ccf31a3414545d5984e57..12f2cf3072999b130df9aee45f3fac2aaf36057a 100755
--- a/dap_chain_cell.c
+++ b/dap_chain_cell.c
@@ -29,6 +29,7 @@
 #include "dap_chain.h"
 #include "dap_chain_cell.h"
 #include "dap_chain_cs.h"
+#include "dap_chain_pvt.h"
 
 #define LOG_TAG "dap_chain_cell"
 
@@ -53,7 +54,7 @@ typedef struct dap_chain_cell_file_header
 } DAP_ALIGN_PACKED dap_chain_cell_file_header_t;
 
 
-static const char* s_cells_path = NULL;
+//static const char* s_cells_path = NULL;
 
 /**
  * @brief dap_chain_cell_init
@@ -61,7 +62,7 @@ static const char* s_cells_path = NULL;
  */
 int dap_chain_cell_init(void)
 {
-    s_cells_path = dap_config_get_item_str(g_config,"resources","cells_storage");
+    //s_cells_path = dap_config_get_item_str(g_config,"resources","cells_storage");
     return  0;
 }
 
@@ -75,6 +76,20 @@ dap_chain_cell_t * dap_chain_cell_create()
     return  l_cell;
 }
 
+/**
+ * @brief dap_chain_cell_delete
+ * @return
+ */
+void dap_chain_cell_delete(dap_chain_cell_t *a_cell)
+{
+    if(!a_cell)
+        return;
+    if(a_cell->file_storage)
+        fclose(a_cell->file_storage);
+    DAP_DELETE(a_cell->file_storage_path);
+    DAP_DELETE(a_cell);
+}
+
 /**
  * @brief dap_chain_cell_load
  * @param a_chain
@@ -87,8 +102,11 @@ int dap_chain_cell_load(dap_chain_t * a_chain, const char * a_cell_file_path)
 
     l_cell->file_storage_path = dap_strdup( a_cell_file_path );
 
-    l_cell->file_storage = fopen(l_cell->file_storage_path,"a+b");
+    char *l_file_path = dap_strdup_printf("%s/%s", DAP_CHAIN_PVT (a_chain)->file_storage_dir,
+            l_cell->file_storage_path);
 
+    l_cell->file_storage = fopen(l_file_path,"rb");
+    DAP_DELETE(l_file_path);
     if ( l_cell->file_storage ){
         dap_chain_cell_file_header_t l_hdr = {0};
         if ( fread( &l_hdr,1,sizeof(l_hdr),l_cell->file_storage ) == sizeof (l_hdr) ) {
@@ -100,7 +118,7 @@ int dap_chain_cell_load(dap_chain_t * a_chain, const char * a_cell_file_path)
                         if ( l_element_size > 0 ){
                             dap_chain_atom_ptr_t * l_element = DAP_NEW_Z_SIZE (dap_chain_atom_ptr_t, l_element_size );
                             if ( fread( l_element,1,l_element_size,l_cell->file_storage ) == l_element_size ) {
-                                l_cell->chain->callback_atom_add (a_chain, l_element );
+                                a_chain->callback_atom_add (a_chain, l_element );
                             }
                         } else {
                             log_it (L_ERROR, "Zero element size, file is corrupted");
@@ -108,20 +126,25 @@ int dap_chain_cell_load(dap_chain_t * a_chain, const char * a_cell_file_path)
                         }
                     }
                 }
+                dap_chain_cell_delete(l_cell);
                 return 0;
             } else {
                 log_it (L_ERROR,"Wrong signature in file \"%s\", possible file corrupt",l_cell->file_storage_path);
+                dap_chain_cell_delete(l_cell);
                 return -3;
             }
         } else {
             log_it (L_ERROR,"Can't read dap_chain file header \"%s\"",l_cell->file_storage_path);
+            dap_chain_cell_delete(l_cell);
             return -2;
         }
     }else {
         log_it (L_WARNING,"Can't read dap_chain file \"%s\"",l_cell->file_storage_path);
+        dap_chain_cell_delete(l_cell);
         return -1;
     }
-
+    dap_chain_cell_delete(l_cell);
+    return -4;
 }
 
 /**
@@ -136,7 +159,7 @@ int dap_chain_cell_file_append( dap_chain_cell_t * a_cell, const void* a_atom, s
     size_t l_total_wrote_bytes = 0;
     if ( fwrite(&a_atom_size,1,sizeof(a_atom_size),a_cell->file_storage) == sizeof(a_atom_size) ){
         l_total_wrote_bytes += sizeof (a_atom_size);
-        if ( fwrite(&a_atom,1,a_atom_size,a_cell->file_storage) == a_atom_size ){
+        if ( fwrite(a_atom,1,a_atom_size,a_cell->file_storage) == a_atom_size ){
             l_total_wrote_bytes += a_atom_size;
         } else {
             log_it (L_ERROR, "Can't write data from cell 0x%016X to the file \"%s\"",
@@ -160,9 +183,17 @@ int dap_chain_cell_file_append( dap_chain_cell_t * a_cell, const void* a_atom, s
  */
 int dap_chain_cell_file_update( dap_chain_cell_t * a_cell)
 {
+    if(!a_cell->chain){
+        log_it(L_WARNING,"chain not defined for cell for cell 0x%016X ( %s )",
+                               a_cell->id.uint64,a_cell->file_storage_path);
+        return -1;
+    }
     if(a_cell->file_storage == NULL ){ // File need to be created
-        a_cell->file_storage = fopen(a_cell->file_storage_path,"wb");
-        if ( a_cell->file_storage ){
+        char *l_file_path = dap_strdup_printf("%s/%s", DAP_CHAIN_PVT ( a_cell->chain)->file_storage_dir,
+                a_cell->file_storage_path);
+        a_cell->file_storage = fopen(l_file_path, "wb");
+        DAP_DELETE(l_file_path);
+        if(a_cell->file_storage) {
             dap_chain_cell_file_header_t l_hdr = {
                 .signature = DAP_CHAIN_CELL_FILE_SIGNATURE,
                 .version = DAP_CHAIN_CELL_FILE_VERSION,
diff --git a/dap_chain_cell.h b/dap_chain_cell.h
index eb425343f66bc4291df88055fea21a9d4eb50b61..83bba2941348da89bdcdbfcc610a464774afa925 100755
--- a/dap_chain_cell.h
+++ b/dap_chain_cell.h
@@ -72,6 +72,8 @@ typedef struct dap_chain_cell_decl{
 
 
 int dap_chain_cell_init(void);
+dap_chain_cell_t * dap_chain_cell_create();
+void dap_chain_cell_delete(dap_chain_cell_t *a_cell);
 int dap_chain_cell_load(dap_chain_t * a_chain, const char * a_cell_file_path);
 int dap_chain_cell_file_update( dap_chain_cell_t * a_cell);
 int dap_chain_cell_file_append( dap_chain_cell_t * a_cell,const void* a_atom, size_t a_atom_size);
diff --git a/dap_chain_common.c b/dap_chain_common.c
index 3bb1f23ef1f45976d6f8b376762d21fc9150d641..44310f3239db9d0bcad759d511c8feb61382413f 100755
--- a/dap_chain_common.c
+++ b/dap_chain_common.c
@@ -177,7 +177,7 @@ void dap_chain_addr_fill(dap_chain_addr_t *a_addr, dap_enc_key_t *a_key, dap_cha
 
     if(dap_hash_fast(l_pub_key_data, l_pub_key_data_size, &l_hash_public_key)==1)
         memcpy(a_addr->data.hash, l_hash_public_key.raw, sizeof(l_hash_public_key.raw));
-
+    DAP_DELETE(l_pub_key_data);
     // calc checksum
     dap_hash_fast(a_addr, sizeof(dap_chain_addr_t) - sizeof(dap_chain_hash_fast_t), &a_addr->checksum);
 }
diff --git a/dap_chain_ledger.c b/dap_chain_ledger.c
index f09feef70abc208a5b36740693170e1c2db6bfa0..f42025960b83d9664d1ed7a9fe08921df9a44e65 100755
--- a/dap_chain_ledger.c
+++ b/dap_chain_ledger.c
@@ -591,7 +591,6 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
 
             // go to next previous transaction
             l_list_tmp = dap_list_next(l_list_tmp);
-
             continue;
         } else {
             log_it(L_INFO,"Previous transaction was found for hash %s",l_tx_prev_hash_str);