From 62d8f46693140af5fdf53c162e5e3293844db86e Mon Sep 17 00:00:00 2001
From: "pavel.uhanov" <pavel.uhanov@demlabs.net>
Date: Mon, 17 Mar 2025 10:03:25 +0000
Subject: [PATCH] feature-15670

---
 modules/common/dap_chain_common.c             |  74 ++-
 modules/common/dap_chain_datum_tx_items.c     |   8 +-
 modules/common/include/dap_chain_common.h     |   1 +
 .../common/include/dap_chain_datum_tx_items.h |   2 +-
 .../include/dap_chain_datum_tx_out_cond.h     |   2 +
 modules/net/dap_chain_ledger.c                |   9 +-
 modules/net/dap_chain_node_cli_cmd_tx.c       |   3 +-
 modules/net/include/dap_chain_ledger.h        |   4 +
 .../dap_chain_net_srv_emit_delegate.c         | 570 +++++++++++++++---
 .../include/dap_chain_net_srv_emit_delegate.h |   5 +-
 modules/wallet/dap_chain_wallet.c             |   2 +-
 modules/wallet/dap_chain_wallet_cache.c       |   2 +-
 12 files changed, 581 insertions(+), 101 deletions(-)

diff --git a/modules/common/dap_chain_common.c b/modules/common/dap_chain_common.c
index c611a4ddf7..298cbdd149 100644
--- a/modules/common/dap_chain_common.c
+++ b/modules/common/dap_chain_common.c
@@ -75,25 +75,73 @@ dap_chain_addr_str_t dap_chain_addr_to_str_static_(const dap_chain_addr_t *a_add
     return res;
 }
 
+/**
+ * @brief s_addr_from_str
+ * @param [out] a_addr - pointer to addr fill
+ * @param [in] a_str - string with one addr
+ * @return 0 if pass, other if error
+ */
+static int s_addr_from_str(dap_chain_addr_t *a_addr, const char *a_str)
+{
+    dap_return_val_if_pass(!a_addr || !a_str || !a_str[0], -1);
+    if (!dap_strcmp(a_str, "null") || !dap_strcmp(a_str, "0")) {
+        memset(a_addr, 0, sizeof(dap_chain_addr_t));
+        return 0;
+    }
+    int l_ret = 0;
+    size_t l_ret_size = DAP_ENC_BASE58_DECODE_SIZE(strlen(a_str));
+    dap_chain_addr_t *l_addr_cur = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_addr_t, l_ret_size, -2);
+    if (dap_enc_base58_decode(a_str, l_addr_cur) == sizeof(dap_chain_addr_t) && !dap_chain_addr_check_sum(l_addr_cur)) {
+        memcpy(a_addr, l_addr_cur, sizeof(dap_chain_addr_t));
+    } else {
+        l_ret = -3;
+    }
+    DAP_DELETE(l_addr_cur);
+    return l_ret;
+}
+
 /**
  * @brief dap_chain_str_to_addr
- * @param a_addr
- * @return
+ * @param a_str - string with one addr
+ * @return pointer to dap_chain_addr_t if pass, if not - NULL
  */
-dap_chain_addr_t* dap_chain_addr_from_str(const char *a_str)
+dap_chain_addr_t *dap_chain_addr_from_str(const char *a_str)
 {
-    size_t l_str_len = (a_str) ? strlen(a_str) : 0;
-    if(l_str_len <= 0)
+    dap_chain_addr_t *l_ret = DAP_NEW_Z_RET_VAL_IF_FAIL(dap_chain_addr_t, NULL);
+    if (s_addr_from_str(l_ret, a_str)) {
+        DAP_DELETE(l_ret);
         return NULL;
-    if (!dap_strcmp(a_str, "null") || !dap_strcmp(a_str, "0")) {
-        return DAP_NEW_Z(dap_chain_addr_t);
     }
-    size_t l_ret_size = DAP_ENC_BASE58_DECODE_SIZE(l_str_len);
-    dap_chain_addr_t *l_addr = DAP_NEW_Z_SIZE(dap_chain_addr_t, l_ret_size);
-    return ( dap_enc_base58_decode(a_str, l_addr) == sizeof(dap_chain_addr_t) ) 
-        && !dap_chain_addr_check_sum(l_addr)
-            ? l_addr
-            : ( DAP_DELETE(l_addr), NULL );
+    return l_ret;
+}
+
+
+/**
+ * @brief parce addrs string div by ',', alloc memory to addrs
+ * @param a_addr_str - ddrs string div by ','
+ * @param a_addr - pointer to memory alloc
+ * @return addr count
+ */
+size_t dap_chain_addr_from_str_array(const char *a_addr_str, dap_chain_addr_t **a_addr)
+{
+    dap_return_val_if_pass(!a_addr_str || !a_addr, 0);
+    size_t l_count = dap_str_symbol_count(a_addr_str, ',') + 1;
+    dap_chain_addr_t *l_addr = DAP_NEW_Z_COUNT_RET_VAL_IF_FAIL(dap_chain_addr_t, l_count, 0);
+    char **l_addr_str_array = dap_strsplit(a_addr_str, ",", l_count);
+    if (!l_addr_str_array) {
+        DAP_DELETE(l_addr);
+        return 0;
+    }
+    for (size_t i = 0; i < l_count; ++i) {
+        if (s_addr_from_str(l_addr + i, l_addr_str_array[i])) {
+            DAP_DELETE(l_addr);
+            dap_strfreev(l_addr_str_array);
+            return 0;
+        }
+    }
+    dap_strfreev(l_addr_str_array);
+    *a_addr = l_addr;
+    return l_count;
 }
 
 bool dap_chain_addr_is_blank(const dap_chain_addr_t *a_addr)
diff --git a/modules/common/dap_chain_datum_tx_items.c b/modules/common/dap_chain_datum_tx_items.c
index b694961e23..6384a2573f 100644
--- a/modules/common/dap_chain_datum_tx_items.c
+++ b/modules/common/dap_chain_datum_tx_items.c
@@ -104,7 +104,7 @@ dap_chain_tx_out_cond_subtype_t dap_chain_tx_out_cond_subtype_from_str(const cha
  */
 
 size_t dap_chain_datum_item_tx_get_size(const byte_t *a_item, size_t a_max_size) {
-    dap_return_val_if_fail(a_item, TX_ITEM_TYPE_UNKNOWN);
+    dap_return_val_if_fail(a_item, 0);
     size_t l_ret = 0;
 #define m_tx_item_size(t) ( !a_max_size || sizeof(t) <= a_max_size ? sizeof(t) : 0 )
 #define m_tx_item_size_ext(t, size_field)                                                                                       \
@@ -366,11 +366,11 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_stake_lock(
 
 dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_emit_delegate(dap_chain_net_srv_uid_t a_srv_uid, uint256_t a_value,
                                                                                    uint32_t a_signs_min, dap_hash_fast_t *a_pkey_hashes,
-                                                                                   size_t a_pkey_hashes_count)
+                                                                                   size_t a_pkey_hashes_count, const char *a_tag_str)
 {
     if (IS_ZERO_256(a_value))
         return NULL;
-    size_t l_tsd_total_size = a_pkey_hashes_count * (sizeof(dap_hash_fast_t) + sizeof(dap_tsd_t));
+    size_t l_tsd_total_size = a_pkey_hashes_count * (sizeof(dap_hash_fast_t) + sizeof(dap_tsd_t)) + (a_tag_str ? sizeof(dap_tsd_t) + strlen(a_tag_str) + 1 : 0);
     dap_chain_tx_out_cond_t *l_item = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_tx_out_cond_t, sizeof(dap_chain_tx_out_cond_t) + l_tsd_total_size, NULL);
     l_item->header.item_type = TX_ITEM_TYPE_OUT_COND;
     l_item->header.value = a_value;
@@ -381,6 +381,8 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_emit_delega
     byte_t *l_next_tsd_ptr = l_item->tsd;
     for (size_t i = 0; i < a_pkey_hashes_count; i++)
         l_next_tsd_ptr = dap_tsd_write(l_next_tsd_ptr, DAP_CHAIN_TX_OUT_COND_TSD_HASH, a_pkey_hashes + i, sizeof(dap_hash_fast_t));
+    if (a_tag_str)
+        l_next_tsd_ptr = dap_tsd_write(l_next_tsd_ptr, DAP_CHAIN_TX_OUT_COND_TSD_STR, (const void*)a_tag_str, strlen(a_tag_str) + 1);
     return l_item;
 }
 
diff --git a/modules/common/include/dap_chain_common.h b/modules/common/include/dap_chain_common.h
index 69bc2c00fc..0b930d2925 100644
--- a/modules/common/include/dap_chain_common.h
+++ b/modules/common/include/dap_chain_common.h
@@ -225,6 +225,7 @@ dap_chain_addr_str_t dap_chain_addr_to_str_static_(const dap_chain_addr_t *a_add
 #define dap_chain_addr_to_str dap_chain_addr_to_str_static
 
 dap_chain_addr_t* dap_chain_addr_from_str(const char *str);
+size_t dap_chain_addr_from_str_array(const char *a_addr_str, dap_chain_addr_t **a_addr);
 bool dap_chain_addr_is_blank(const dap_chain_addr_t *a_addr);
 
 dap_chain_net_srv_uid_t dap_chain_net_srv_uid_from_str(const char* a_str);
diff --git a/modules/common/include/dap_chain_datum_tx_items.h b/modules/common/include/dap_chain_datum_tx_items.h
index 3039494890..e864aef95f 100644
--- a/modules/common/include/dap_chain_datum_tx_items.h
+++ b/modules/common/include/dap_chain_datum_tx_items.h
@@ -212,7 +212,7 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_stake_lock(
 
 dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_emit_delegate(dap_chain_net_srv_uid_t a_srv_uid, uint256_t a_value,
                                                                                    uint32_t a_signs_min, dap_hash_fast_t *a_pkey_hashes,
-                                                                                   size_t a_pkey_hashes_count);
+                                                                                   size_t a_pkey_hashes_count, const char *a_tag_str);
 
 /**
  * Create item dap_chain_tx_sig_t
diff --git a/modules/common/include/dap_chain_datum_tx_out_cond.h b/modules/common/include/dap_chain_datum_tx_out_cond.h
index 1014316a43..ddc1dc6a87 100644
--- a/modules/common/include/dap_chain_datum_tx_out_cond.h
+++ b/modules/common/include/dap_chain_datum_tx_out_cond.h
@@ -56,6 +56,8 @@ typedef byte_t dap_chain_tx_out_cond_subtype_t;
 #define DAP_CHAIN_TX_OUT_COND_TSD_ADDR                      0xf001
 // Chain hash
 #define DAP_CHAIN_TX_OUT_COND_TSD_HASH                      0xf002
+// Custom str
+#define DAP_CHAIN_TX_OUT_COND_TSD_STR                       0xf003
 
 /**
  * @struct dap_chain_tx_out
diff --git a/modules/net/dap_chain_ledger.c b/modules/net/dap_chain_ledger.c
index 1a883dd8dd..2dec66972d 100644
--- a/modules/net/dap_chain_ledger.c
+++ b/modules/net/dap_chain_ledger.c
@@ -352,7 +352,7 @@ static bool s_tag_check_transfer(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a
     //crosschain transfer
     //regular transfer
     //comission transfer
-    
+
     // fee transfer: in_cond item linked to out_cond_fee
     if (a_items_grp->items_in_cond) 
     {
@@ -3268,6 +3268,9 @@ const char *dap_ledger_tx_action_str(dap_chain_tx_tag_action_type_t a_tag)
     if (a_tag == DAP_CHAIN_TX_TAG_ACTION_CHANGE) return "change";
     if (a_tag == DAP_CHAIN_TX_TAG_ACTION_VOTING) return "voting";
     if (a_tag == DAP_CHAIN_TX_TAG_ACTION_VOTE) return "vote";
+    if (a_tag == DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_HOLD) return "hold";
+    if (a_tag == DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_TAKE) return "take";
+    if (a_tag == DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_REFILL) return "refill";
 
     return "WTFSUBTAG";
 
@@ -3288,7 +3291,9 @@ dap_chain_tx_tag_action_type_t dap_ledger_tx_action_str_to_action_t(const char *
     if (strcmp("extend", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_EXTEND;
     if (strcmp("close", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_CLOSE;
     if (strcmp("change", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_CHANGE;
-
+    if (strcmp("hold", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_HOLD;
+    if (strcmp("take", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_TAKE;
+    if (strcmp("refill", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_REFILL;
     return DAP_CHAIN_TX_TAG_ACTION_UNKNOWN;
 }
 
diff --git a/modules/net/dap_chain_node_cli_cmd_tx.c b/modules/net/dap_chain_node_cli_cmd_tx.c
index 0748ba83ce..178d914648 100644
--- a/modules/net/dap_chain_node_cli_cmd_tx.c
+++ b/modules/net/dap_chain_node_cli_cmd_tx.c
@@ -552,7 +552,7 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t
             case TX_ITEM_TYPE_OUT_COND:
                 l_value = ((dap_chain_tx_out_cond_t *)it->data)->header.value;
                 if (((dap_chain_tx_out_cond_t *)it->data)->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE) {
-                    SUM_256_256(l_fee_sum, ((dap_chain_tx_out_cond_t *)it->data)->header.value, &l_fee_sum);
+                    SUM_256_256(l_fee_sum, l_value, &l_fee_sum);
                     l_dst_token = l_native_ticker;
                 } else
                     l_dst_token = l_src_token;
@@ -704,7 +704,6 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t
             json_object *l_cond_send_value_obj = json_object_object_get(l_cond_send_object, "send_datoshi");
             const char *l_cond_send_value_str = json_object_get_string(l_cond_send_value_obj);
             uint256_t l_cond_send_value = dap_uint256_scan_uninteger(l_cond_send_value_str);
-            assert(!IS_ZERO_256(l_cond_recv_value) && !IS_ZERO_256(l_cond_send_value));
             int l_direction = compare256(l_cond_recv_value, l_cond_send_value);
             if (l_direction > 0) {
                 SUBTRACT_256_256(l_cond_recv_value, l_cond_send_value, &l_cond_recv_value);
diff --git a/modules/net/include/dap_chain_ledger.h b/modules/net/include/dap_chain_ledger.h
index f2e43d962d..e11479f6e0 100644
--- a/modules/net/include/dap_chain_ledger.h
+++ b/modules/net/include/dap_chain_ledger.h
@@ -127,6 +127,10 @@ typedef enum dap_chain_tx_tag_action_type {
 
     DAP_CHAIN_TX_TAG_ACTION_VOTING =                1 << 11,
     DAP_CHAIN_TX_TAG_ACTION_VOTE =                  1 << 12,
+
+    DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_HOLD =    1 << 13,
+    DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_TAKE =    1 << 14,
+    DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_REFILL =  1 << 15,
    
     DAP_CHAIN_TX_TAG_ACTION_ALL =                          ~0,
 } dap_chain_tx_tag_action_type_t;
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 3df74f1368..4a16024466 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
@@ -47,7 +47,8 @@ enum emit_delegation_error {
     ERROR_COMPOSE,
     ERROR_CREATE,
     ERROR_PLACE,
-    ERROR_SUBCOMMAND
+    ERROR_SUBCOMMAND,
+    ERROR_NETWORK
 };
 
 #define LOG_TAG "dap_chain_net_srv_emit_delegate"
@@ -60,6 +61,7 @@ static int s_emit_delegate_verificator(dap_ledger_t *a_ledger, dap_chain_tx_out_
     uint256_t l_writeoff_value = uint256_0;
     dap_chain_tx_out_cond_t *l_cond_out = NULL;
     dap_chain_addr_t l_net_fee_addr;
+    uint16_t l_change_type = 0;
     bool l_net_fee_used = dap_chain_net_tx_get_fee(a_ledger->net->pub.id, NULL, &l_net_fee_addr);
     byte_t *l_item; size_t l_tx_item_size;
     TX_ITEM_ITER_TX(l_item, l_tx_item_size, a_tx_in) {
@@ -76,7 +78,7 @@ static int s_emit_delegate_verificator(dap_ledger_t *a_ledger, dap_chain_tx_out_
             break;
         case TX_ITEM_TYPE_TSD: {
             dap_tsd_t *l_tsd = (dap_tsd_t *)((dap_chain_tx_tsd_t *)l_item)->tsd;
-            if (l_tsd->type != DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF)
+            if (l_tsd->type != DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF && l_tsd->type != DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_REFILL)
                 break; // Skip it
             if (l_tsd->size != sizeof(uint256_t)) {
                 log_it(L_ERROR, "TSD section size control error");
@@ -87,6 +89,7 @@ static int s_emit_delegate_verificator(dap_ledger_t *a_ledger, dap_chain_tx_out_
                 return -5;
             }
             l_writeoff_value = dap_tsd_get_scalar(l_tsd, uint256_t);
+            l_change_type = l_tsd->type;
             break;
         }
         // Verify signs
@@ -125,13 +128,22 @@ static int s_emit_delegate_verificator(dap_ledger_t *a_ledger, dap_chain_tx_out_
     }
 
     uint256_t l_change_value;
-    if (SUBTRACT_256_256(a_cond->header.value, l_writeoff_value, &l_change_value)) {
+    if (l_change_type == DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF && SUBTRACT_256_256(a_cond->header.value, l_writeoff_value, &l_change_value)) {
         char *l_balance = dap_uint256_decimal_to_char(a_cond->header.value);
-        const char *l_writeoff; dap_uint256_to_char(l_writeoff_value, &l_writeoff);
+        const char *l_writeoff = NULL;
+        dap_uint256_to_char(l_change_value, &l_writeoff);
         log_it(L_ERROR, "Write-off value %s is greater than account balance %s", l_writeoff, l_balance);
         DAP_DELETE(l_balance);
         return -7;
     }
+    if (l_change_type == DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_REFILL && SUM_256_256(a_cond->header.value, l_writeoff_value, &l_change_value)) {
+        char *l_balance = dap_uint256_decimal_to_char(a_cond->header.value);
+        const char *l_refill = NULL;
+        dap_uint256_to_char(l_change_value, &l_refill);
+        log_it(L_ERROR, "Sum of re-fill value %s and account balance %s is owerflow 256 bit num", l_refill, l_balance);
+        DAP_DELETE(l_balance);
+        return -9;
+    }
     if (!IS_ZERO_256(l_change_value)) {
         if (!l_cond_out) {
             log_it(L_ERROR, "Changeback on conditional output is need but not found");
@@ -148,12 +160,9 @@ static int s_emit_delegate_verificator(dap_ledger_t *a_ledger, dap_chain_tx_out_
             log_it(L_ERROR, "Condtional output in current TX have different TSD sections vs previous TX's one");
             return -11;
         }
-    } else if (l_cond_out) {
-        log_it(L_ERROR, "Changeback on conditional output is not need but found");
-        return -10;
     }
 
-    if (l_signs_verified < a_cond->subtype.srv_emit_delegate.signers_minimum) {
+    if (l_change_type == DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF && l_signs_verified < a_cond->subtype.srv_emit_delegate.signers_minimum) {
         log_it(L_WARNING, "Not enough valid signs (%u from %u) for delegated emission",
                                     l_signs_verified, a_cond->subtype.srv_emit_delegate.signers_minimum);
         return DAP_CHAIN_CS_VERIFY_CODE_NOT_ENOUGH_SIGNS;
@@ -163,7 +172,17 @@ static int s_emit_delegate_verificator(dap_ledger_t *a_ledger, dap_chain_tx_out_
 
 static bool s_tag_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx,  dap_chain_datum_tx_item_groups_t *a_items_grp, dap_chain_tx_tag_action_type_t *a_action)
 {   
-    return a_items_grp->items_out_cond_srv_emit_delegate;
+    if (!a_items_grp->items_out_cond_srv_emit_delegate)
+        return false;
+    if (a_action) {
+        if (dap_chain_datum_tx_item_get_tsd_by_type(a_tx, DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF))
+            *a_action = DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_TAKE;
+        else if (dap_chain_datum_tx_item_get_tsd_by_type(a_tx, DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_REFILL))
+            *a_action = DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_REFILL;
+        else
+            *a_action = DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_HOLD;
+    }
+    return true;
 }
 
 // Put a transaction to the mempool
@@ -183,11 +202,11 @@ static char *s_tx_put(dap_chain_datum_tx_t *a_tx, dap_chain_t *a_chain, const ch
 
 #define m_sign_fail(e,s) { dap_json_rpc_error_add(a_json_arr_reply, e, s); log_it(L_ERROR, "%s", s); return NULL; }
 
-#define m_tx_fail(e,s) { DAP_DELETE(l_tx); m_sign_fail(e,s) }
+#define m_tx_fail(e,s) { DAP_DELETE(l_tx); m_sign_fail(e,s); log_it(L_ERROR, "%s", s); }
 
 static dap_chain_datum_tx_t *s_emitting_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key,
                                                   const char *a_token_ticker, uint256_t a_value, uint256_t a_fee,
-                                                  uint32_t a_signs_min, dap_hash_fast_t *a_pkey_hashes, size_t a_pkey_hashes_count)
+                                                  uint32_t a_signs_min, dap_hash_fast_t *a_pkey_hashes, size_t a_pkey_hashes_count, const char *a_tag_str)
 {
     const char *l_native_ticker = a_net->pub.native_ticker;
     bool l_delegate_native = !dap_strcmp(l_native_ticker, a_token_ticker);
@@ -233,7 +252,7 @@ static dap_chain_datum_tx_t *s_emitting_tx_create(json_object *a_json_arr_reply,
     // add 'out_cond' & 'out_ext' items
     dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_EMIT_DELEGATE_ID };
     dap_chain_tx_out_cond_t *l_tx_out = dap_chain_datum_tx_item_out_cond_create_srv_emit_delegate(
-                                                l_uid, a_value, a_signs_min, a_pkey_hashes, a_pkey_hashes_count);
+                                                l_uid, a_value, a_signs_min, a_pkey_hashes, a_pkey_hashes_count, a_tag_str);
     if (!l_tx_out)
         m_tx_fail(ERROR_COMPOSE, "Can't compose the transaction conditional output");
     dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_tx_out);
@@ -266,6 +285,134 @@ static dap_chain_datum_tx_t *s_emitting_tx_create(json_object *a_json_arr_reply,
         if (!IS_ZERO_256(l_fee_back) && dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_fee_back, l_native_ticker) != 1)
             m_tx_fail(ERROR_COMPOSE, "Cant add fee back output");
     }
+    // add 'sign' item
+    if (dap_chain_datum_tx_add_sign_item(&l_tx, a_enc_key) != 1)
+        m_tx_fail(ERROR_COMPOSE, "Can't add sign output");
+    return l_tx;
+}
+
+
+dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_refilling_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key,
+    uint256_t a_value, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* tsd_items)
+{
+    dap_return_val_if_pass(!a_net || IS_ZERO_256(a_value) || IS_ZERO_256(a_fee), NULL);
+    dap_ledger_t *l_ledger = a_net->pub.ledger;
+    const char *l_tx_ticker = dap_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, a_tx_in_hash);
+    bool l_refill_native = !dap_strcmp(a_net->pub.native_ticker, l_tx_ticker);
+    uint256_t l_value = a_value, l_value_transfer = {}, l_fee_transfer = {}; // how many coins to transfer
+    uint256_t l_net_fee, l_fee_total = a_fee;
+    dap_chain_addr_t l_net_fee_addr;
+    // create empty transaction
+    dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create();
+
+    bool l_net_fee_used = dap_chain_net_tx_get_fee(a_net->pub.id, &l_net_fee, &l_net_fee_addr);
+    if (l_net_fee_used && SUM_256_256(l_fee_total, l_net_fee, &l_fee_total))
+        m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer");
+    if (l_refill_native && SUM_256_256(l_value, l_fee_total, &l_value))
+        m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer");
+
+    // list of transaction with 'out' items to sell
+    dap_chain_addr_t l_owner_addr;
+    dap_chain_addr_fill_from_key(&l_owner_addr, a_enc_key, a_net->pub.id);
+    dap_list_t *l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_tx_ticker,
+                                                                       &l_owner_addr, l_value, &l_value_transfer);
+    if (!l_list_used_out)
+        m_tx_fail(ERROR_FUNDS, "Nothing to pay for refill (not enough funds)");
+
+    // add 'in' items to pay for delegate
+    uint256_t l_value_to_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out);
+    dap_list_free_full(l_list_used_out, NULL);
+    if (!EQUAL_256(l_value_to_items, l_value_transfer))
+        m_tx_fail(ERROR_COMPOSE, "Can't compose the transaction input");
+
+    if (!l_refill_native) {
+        dap_list_t *l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, a_net->pub.native_ticker,
+                                                                          &l_owner_addr, l_fee_total, &l_fee_transfer);
+        if (!l_list_fee_out)
+            m_tx_fail(ERROR_FUNDS, "Nothing to pay for fee (not enough funds)");
+        // add 'in' items to pay fee
+        uint256_t l_value_fee_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_fee_out);
+        dap_list_free_full(l_list_fee_out, NULL);
+        if (!EQUAL_256(l_value_fee_items, l_fee_transfer))
+            m_tx_fail(ERROR_COMPOSE, "Can't compose the fee transaction input");
+    }
+
+    dap_hash_fast_t l_final_tx_hash = dap_ledger_get_final_chain_tx_hash(l_ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_EMIT_DELEGATE, a_tx_in_hash, false);
+    if (dap_hash_fast_is_blank(&l_final_tx_hash))
+        m_tx_fail(ERROR_FUNDS, "Nothing to refill, can't find tx");
+
+    log_it(L_NOTICE, "Actual TX hash %s will be used for refill TX composing", dap_hash_fast_to_str_static(&l_final_tx_hash));
+    dap_chain_datum_tx_t *l_tx_in = dap_ledger_tx_find_by_hash(l_ledger, &l_final_tx_hash);
+    assert(l_tx_in);
+    int l_prev_cond_idx = 0;
+    dap_chain_tx_out_cond_t *l_cond_prev = dap_chain_datum_tx_out_cond_get(l_tx_in, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_EMIT_DELEGATE, &l_prev_cond_idx);
+    if (!l_cond_prev)
+        m_tx_fail(ERROR_TX_MISMATCH, "Requested conditional transaction requires conditional output");
+
+    if (dap_ledger_tx_hash_is_used_out_item(l_ledger, &l_final_tx_hash, l_prev_cond_idx, NULL))
+        m_tx_fail(ERROR_TX_MISMATCH, "Requested conditional transaction is already used out");
+
+    // add 'in_cond' item
+    if (dap_chain_datum_tx_add_in_cond_item(&l_tx, &l_final_tx_hash, l_prev_cond_idx, -1) != 1) {
+        log_it(L_ERROR, "Can't compose the transaction conditional input");
+        m_tx_fail(ERROR_COMPOSE, "Cant add conditionsl input");
+    }
+
+    uint256_t l_value_back = {};
+    if(SUM_256_256(l_cond_prev->header.value, a_value, &l_value_back)) {
+        m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer");
+    }
+
+    dap_chain_tx_out_cond_t *l_out_cond = DAP_DUP_SIZE(l_cond_prev, sizeof(dap_chain_tx_out_cond_t) + l_cond_prev->tsd_size);
+    if (!l_out_cond)
+        m_tx_fail(ERROR_MEMORY, c_error_memory_alloc);
+    l_out_cond->header.value = l_value_back;
+    if (dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_out_cond) < 0) {
+        m_tx_fail(ERROR_COMPOSE, "Cant add refill cond output");
+        DAP_DELETE(l_out_cond);
+    }
+    DAP_DELETE(l_out_cond);
+
+    // add track for refill from conditional value
+    dap_chain_tx_tsd_t *l_refill_tsd = dap_chain_datum_tx_item_tsd_create(&a_value, DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_REFILL, sizeof(uint256_t));
+    if (dap_chain_datum_tx_add_item(&l_tx, l_refill_tsd) != 1) {
+        DAP_DELETE(l_refill_tsd);
+        m_tx_fail(ERROR_COMPOSE, "Can't add TSD section item with withdraw value");
+    }
+    DAP_DELETE(l_refill_tsd);
+
+    //add other tsd if available
+    for ( dap_list_t *l_tsd = tsd_items; l_tsd; l_tsd = l_tsd->next ) {
+        if ( dap_chain_datum_tx_add_item(&l_tx, l_tsd->data) != 1 )
+        m_tx_fail(ERROR_COMPOSE, "Can't add custom TSD section item ");
+    }
+
+    // coin back
+    SUBTRACT_256_256(l_value_transfer, l_value, &l_value_back);
+    if (!IS_ZERO_256(l_value_back)) {
+        int rc = l_refill_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_owner_addr, l_value_back)
+                                   : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_value_back, l_tx_ticker);
+        if (rc != 1)
+            m_tx_fail(ERROR_COMPOSE, "Cant add coin back output");
+    }
+
+    // add fee items
+    if (l_net_fee_used) {
+        int rc = l_refill_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_net_fee_addr, l_net_fee)
+                                   : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_net_fee_addr, l_net_fee, a_net->pub.native_ticker);
+        if (rc != 1)
+            m_tx_fail(ERROR_COMPOSE, "Cant add net fee output");
+    }
+    if (!IS_ZERO_256(a_fee) && dap_chain_datum_tx_add_fee_item(&l_tx, a_fee) != 1)
+        m_tx_fail(ERROR_COMPOSE, "Cant add validator fee output");
+
+    if (!l_refill_native) {
+        uint256_t l_fee_back = {};
+        // fee coin back
+        SUBTRACT_256_256(l_fee_transfer, l_fee_total, &l_fee_back);
+        if (!IS_ZERO_256(l_fee_back) && dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_fee_back, a_net->pub.native_ticker) != 1)
+            m_tx_fail(ERROR_COMPOSE, "Cant add fee back output");
+    }
 
     // add 'sign' item
     if (dap_chain_datum_tx_add_sign_item(&l_tx, a_enc_key) != 1)
@@ -290,8 +437,13 @@ static bool s_is_key_present(dap_chain_tx_out_cond_t *a_cond, dap_enc_key_t *a_e
 }
 
 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, dap_list_t* tsd_items)
+    dap_chain_addr_t *a_to_addr, uint256_t *a_value, uint32_t a_addr_count /*!not change type!*/, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* tsd_items)
 {
+    dap_return_val_if_pass(!a_to_addr, NULL);
+    dap_return_val_if_pass(!a_value, NULL);
+    dap_return_val_if_pass(!a_addr_count, NULL);
+    dap_return_val_if_pass(!a_enc_key, NULL);
+    dap_return_val_if_pass(!a_tx_in_hash, NULL);
     // create empty transaction
     dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create();
 
@@ -299,10 +451,18 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje
     const char *l_tx_ticker = dap_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, a_tx_in_hash);
     bool l_taking_native = !dap_strcmp(a_net->pub.native_ticker, l_tx_ticker);
 
-    uint256_t l_value = a_value, l_fee_transfer = {}; // how many coins to transfer
+    uint256_t l_value = {}, l_fee_transfer = {}; // how many coins to transfer
     uint256_t l_net_fee, l_fee_total = a_fee;
     dap_chain_addr_t l_net_fee_addr;
 
+    for (size_t i = 0; i < a_addr_count; ++i) {
+        if(IS_ZERO_256(a_value[i])) {
+            m_tx_fail(ERROR_VALUE, "Format -value <256 bit integer> and not equal zero");
+        }
+        if (SUM_256_256(l_value, a_value[i], &l_value))
+            m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer");
+    }
+
     bool l_net_fee_used = dap_chain_net_tx_get_fee(a_net->pub.id, &l_net_fee, &l_net_fee_addr);
     if (l_net_fee_used && SUM_256_256(l_fee_total, l_net_fee, &l_fee_total))
         m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer");
@@ -310,7 +470,7 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje
     dap_chain_addr_t l_owner_addr;
     dap_chain_addr_fill_from_key(&l_owner_addr, a_enc_key, a_net->pub.id);
     dap_list_t *l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, a_net->pub.native_ticker,
-                                                                      &l_owner_addr, l_fee_total, &l_fee_transfer);
+                            &l_owner_addr, l_fee_total, &l_fee_transfer);
     if (!l_list_fee_out)
         m_tx_fail(ERROR_FUNDS, "Nothing to pay for fee (not enough funds)");
     // add 'in' items to pay fee
@@ -344,22 +504,31 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje
     }
 
     // add 'out' or 'out_ext' item for emission
-    int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, a_addr_to, a_value) :
-                               dap_chain_datum_tx_add_out_ext_item(&l_tx, a_addr_to, a_value, l_tx_ticker);
-    if (rc != 1)
-        m_tx_fail(ERROR_COMPOSE, "Cant add emission output");
+    for (size_t i = 0; i < a_addr_count; ++i) {
+        int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, a_to_addr + i, a_value[i]) :
+            dap_chain_datum_tx_add_out_ext_item(&l_tx, a_to_addr + i, a_value[i], l_tx_ticker);
+        if (rc != 1)
+            m_tx_fail(ERROR_COMPOSE, "Cant add tx output");
+    }
 
     // coin back
     uint256_t l_value_back = {};
     SUBTRACT_256_256(l_cond_prev->header.value, l_value, &l_value_back);
-    if (!IS_ZERO_256(l_value_back)) {
-        dap_chain_tx_out_cond_t *l_out_cond = DAP_DUP_SIZE(l_cond_prev, sizeof(dap_chain_tx_out_cond_t) + l_cond_prev->tsd_size);
-        if (!l_out_cond)
-            m_tx_fail(ERROR_COMPOSE, c_error_memory_alloc);
-        l_out_cond->header.value = l_value_back;
-        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_chain_tx_out_cond_t *l_out_cond = DAP_DUP_SIZE(l_cond_prev, sizeof(dap_chain_tx_out_cond_t) + l_cond_prev->tsd_size);
+    if (!l_out_cond)
+        m_tx_fail(ERROR_MEMORY, c_error_memory_alloc);
+    l_out_cond->header.value = l_value_back;
+    
+    if (-1 == dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_out_cond)) {
         DAP_DELETE(l_out_cond);
+        m_tx_fail(ERROR_COMPOSE, "Cant add emission cond output");
+    }
+    DAP_DELETE(l_out_cond);
+
+    if (a_addr_count > 1) {
+        dap_chain_tx_tsd_t * l_addr_cnt_tsd = dap_chain_datum_tx_item_tsd_create(&a_addr_count, DAP_CHAIN_DATUM_TRANSFER_TSD_TYPE_OUT_COUNT, sizeof(uint32_t));
+        if (!l_addr_cnt_tsd || dap_chain_datum_tx_add_item(&l_tx, l_addr_cnt_tsd) != 1 )
+            m_tx_fail(ERROR_COMPOSE, "Can't add TSD section item with addr count");
     }
 
     // add track for takeoff from conditional value
@@ -377,7 +546,7 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje
     // add fee items
     if (l_net_fee_used) {
         int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_net_fee_addr, l_net_fee)
-                                 : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_net_fee_addr, l_net_fee, a_net->pub.native_ticker);
+            : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_net_fee_addr, l_net_fee, a_net->pub.native_ticker);
         if (rc != 1)
             m_tx_fail(ERROR_COMPOSE, "Cant add net fee output");
     }
@@ -388,10 +557,10 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje
     // fee coin back
     SUBTRACT_256_256(l_fee_transfer, l_fee_total, &l_fee_back);
     if (!IS_ZERO_256(l_fee_back)) {
-            int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_owner_addr, l_fee_back)
-                                     : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_fee_back, a_net->pub.native_ticker);
-            if (rc != 1)
-                m_tx_fail(ERROR_COMPOSE, "Cant add fee back output");
+        int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_owner_addr, l_fee_back)
+            : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_fee_back, a_net->pub.native_ticker);
+        if (rc != 1)
+            m_tx_fail(ERROR_COMPOSE, "Cant add fee back output");
     }
 
     // add 'sign' item
@@ -401,6 +570,7 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje
     return l_tx;
 }
 
+
 #undef m_tx_fail
 
 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)
@@ -433,7 +603,7 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_sign(json_object
     }
     dap_chain_datum_tx_t *l_tx = DAP_DUP_SIZE(a_tx_in, dap_chain_datum_tx_get_size(a_tx_in));
     if (!l_tx)
-        m_sign_fail(ERROR_FUNDS, c_error_memory_alloc);
+        m_sign_fail(ERROR_MEMORY, c_error_memory_alloc);
     // add 'sign' item
     if (dap_chain_datum_tx_add_sign_item(&l_tx, a_enc_key) != 1)
         m_sign_fail(ERROR_COMPOSE, "Can't add sign output");
@@ -444,7 +614,14 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_sign(json_object
 
 static int s_cli_hold(int a_argc, char **a_argv, int a_arg_index, json_object **a_json_arr_reply, dap_chain_net_t *a_net, dap_chain_t *a_chain, const char *a_hash_out_type)
 {
-    const char *l_token_str = NULL, *l_value_str = NULL, *l_wallet_str = NULL, *l_fee_str = NULL, *l_signs_min_str = NULL, *l_pkeys_str = NULL;
+    const char *l_token_str = NULL, 
+                *l_value_str = NULL, 
+                *l_wallet_str = NULL, 
+                *l_fee_str = NULL, 
+                *l_signs_min_str = NULL, 
+                *l_pkeys_str = NULL,
+                *l_tag_str = NULL;
+
     dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-token", &l_token_str);
     if (!l_token_str) {
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation holding requires parameter -token");
@@ -461,7 +638,7 @@ static int s_cli_hold(int a_argc, char **a_argv, int a_arg_index, json_object **
     }
     uint256_t l_value = dap_chain_balance_scan(l_value_str);
     if (IS_ZERO_256(l_value)) {
-        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -value <256 bit integer>");
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -value <256 bit integer> and not equal zero");
         return ERROR_VALUE;
     }
     dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-fee", &l_fee_str);
@@ -471,7 +648,7 @@ static int s_cli_hold(int a_argc, char **a_argv, int a_arg_index, json_object **
     }
     uint256_t l_fee = dap_chain_balance_scan(l_fee_str);
     if (IS_ZERO_256(l_fee)) {
-        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -fee <256 bit integer>");
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -fee <256 bit integer> and not equal zer");
         return ERROR_VALUE;
     }
     dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-signs_minimum", &l_signs_min_str);
@@ -489,11 +666,15 @@ static int s_cli_hold(int a_argc, char **a_argv, int a_arg_index, json_object **
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation holding requires parameter -w");
         return ERROR_PARAM;
     }
+
     dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config), NULL);
     if (!l_wallet) {
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Specified wallet %s not found", l_wallet_str);
         return ERROR_VALUE;
     }
+
+    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-tag", &l_tag_str);
+
     const char *l_sign_str = dap_chain_wallet_check_sign(l_wallet);
     dap_enc_key_t *l_enc_key = dap_chain_wallet_get_key(l_wallet, 0);
     dap_chain_wallet_close(l_wallet);
@@ -524,6 +705,13 @@ static int s_cli_hold(int a_argc, char **a_argv, int a_arg_index, json_object **
             DAP_DEL_MULTY(l_enc_key, l_pkey_hashes);
             return ERROR_VALUE;
         }
+        for (size_t j = 0; j < i; ++j) {
+            if (!memcmp(l_pkey_hashes + j, l_pkey_hashes + i, sizeof(dap_chain_hash_fast_t))){
+                dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Find pkey hash %s dublicate", l_hash_str_buf);
+                DAP_DEL_MULTY(l_enc_key, l_pkey_hashes);
+                return ERROR_VALUE;
+            }
+        }
         if (*l_cur_ptr == 0) {
             l_hashes_count = i + 1;
             break;
@@ -541,7 +729,7 @@ static int s_cli_hold(int a_argc, char **a_argv, int a_arg_index, json_object **
         return ERROR_VALUE;
     }
     // Create conditional transaction for delegated emissions
-    dap_chain_datum_tx_t *l_tx = s_emitting_tx_create(*a_json_arr_reply, a_net, l_enc_key, l_token_str, l_value, l_fee, l_signs_min, l_pkey_hashes, l_hashes_count);
+    dap_chain_datum_tx_t *l_tx = s_emitting_tx_create(*a_json_arr_reply, a_net, l_enc_key, l_token_str, l_value, l_fee, l_signs_min, l_pkey_hashes, l_hashes_count, l_tag_str);
     DAP_DEL_MULTY(l_enc_key, l_pkey_hashes);
     if (!l_tx) {
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_CREATE, "Can't compose transaction for delegated emission");
@@ -563,12 +751,39 @@ static int s_cli_hold(int a_argc, char **a_argv, int a_arg_index, json_object **
     return DAP_NO_ERROR;
 }
 
-static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object **a_json_arr_reply, dap_chain_net_t *a_net, dap_chain_t *a_chain, const char *a_hash_out_type)
+static int s_cli_refill(int a_argc, char **a_argv, int a_arg_index, json_object **a_json_arr_reply, dap_chain_net_t *a_net, dap_chain_t *a_chain, const char *a_hash_out_type)
 {
-    const char *l_tx_in_hash_str = NULL, *l_addr_str = NULL, *l_value_str = NULL, *l_wallet_str = NULL, *l_fee_str = NULL;
+    const char *l_token_str = NULL, *l_value_str = NULL, *l_wallet_str = NULL, *l_fee_str = NULL, *l_tx_in_hash_str = NULL;
+    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-value", &l_value_str);
+    if (!l_value_str) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Refill command requires parameter -value");
+        return ERROR_PARAM;
+    }
+    uint256_t l_value = dap_chain_balance_scan(l_value_str);
+    if (IS_ZERO_256(l_value)) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -value <256 bit integer> and not equal zero");
+        return ERROR_VALUE;
+    }
+    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-fee", &l_fee_str);
+    if (!l_fee_str) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Refill command requires parameter -fee");
+        return ERROR_PARAM;
+    }
+    uint256_t l_fee = dap_chain_balance_scan(l_fee_str);
+    if (IS_ZERO_256(l_fee)) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -fee <256 bit integer> and not equal zer");
+        return ERROR_VALUE;
+    }
+
+    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-w", &l_wallet_str);
+    if (!l_wallet_str) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Refill command requires parameter -w");
+        return ERROR_PARAM;
+    }
+
     dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-tx", &l_tx_in_hash_str);
     if (!l_tx_in_hash_str) {
-        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -tx");
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Refill command requires parameter -tx");
         return ERROR_PARAM;
     }
     dap_hash_fast_t l_tx_in_hash;
@@ -580,16 +795,66 @@ static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object **
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "TX %s not found in ledger", l_tx_in_hash_str);
         return ERROR_VALUE;
     }
-    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-value", &l_value_str);
-    if (!l_value_str) {
-        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -value");
+
+
+    dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config), NULL);
+    if (!l_wallet) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Specified wallet %s not found", l_wallet_str);
+        return ERROR_VALUE;
+    }
+    const char *l_sign_str = dap_chain_wallet_check_sign(l_wallet);
+    dap_enc_key_t *l_enc_key = dap_chain_wallet_get_key(l_wallet, 0);
+    dap_chain_wallet_close(l_wallet);
+
+    // Create conditional transaction for refill
+    dap_chain_datum_tx_t *l_tx = dap_chain_net_srv_emit_delegate_refilling_tx_create(*a_json_arr_reply, a_net, l_enc_key, l_value, l_fee, &l_tx_in_hash, NULL);
+    DAP_DELETE(l_enc_key);
+    if (!l_tx) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_CREATE, "Can't compose transaction for refill shared funds tx");
+        return ERROR_CREATE;
+    }
+    char *l_tx_hash_str = s_tx_put(l_tx, a_chain, a_hash_out_type);
+    DAP_DELETE(l_tx);
+    if (!l_tx_hash_str) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PLACE, "Can't place transaction for refill shared funds tx in mempool");
+        return ERROR_PLACE;
+    }
+    json_object * l_json_obj_create_val = json_object_new_object();
+    json_object_object_add(l_json_obj_create_val, "status", json_object_new_string("success"));
+    if (dap_strcmp(l_sign_str, ""))
+        json_object_object_add(l_json_obj_create_val, "sign", json_object_new_string(l_sign_str));
+    json_object_object_add(l_json_obj_create_val, "tx_hash", json_object_new_string(l_tx_hash_str));
+    json_object_array_add(*a_json_arr_reply, l_json_obj_create_val);
+    DAP_DELETE(l_tx_hash_str);
+    return DAP_NO_ERROR;
+}
+
+static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object **a_json_arr_reply, dap_chain_net_t *a_net, dap_chain_t *a_chain, const char *a_hash_out_type)
+{
+    const char *l_tx_in_hash_str = NULL, *l_addr_str = NULL, *l_value_str = NULL, *l_wallet_str = NULL, *l_fee_str = NULL;
+    
+    uint256_t *l_value = NULL;
+    dap_chain_addr_t *l_to_addr = NULL;
+    uint32_t
+        l_addr_el_count = 0,  // not change type! use in batching TSD section
+        l_value_el_count = 0;
+    dap_list_t *l_tsd_list = NULL;
+    
+    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-tx", &l_tx_in_hash_str);
+    if (!l_tx_in_hash_str) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -tx");
         return ERROR_PARAM;
     }
-    uint256_t l_value = dap_chain_balance_scan(l_value_str);
-    if (IS_ZERO_256(l_value)) {
-        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -value <256 bit integer>");
+    dap_hash_fast_t l_tx_in_hash;
+    if (dap_chain_hash_fast_from_str(l_tx_in_hash_str, &l_tx_in_hash)) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Can't recognize %s as a hex or base58 format hash", l_tx_in_hash_str);
+        return ERROR_VALUE;
+    }
+    if (!dap_ledger_tx_find_by_hash(a_net->pub.ledger, &l_tx_in_hash)) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "TX %s not found in ledger", l_tx_in_hash_str);
         return ERROR_VALUE;
     }
+
     dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-fee", &l_fee_str);
     if (!l_fee_str) {
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -fee");
@@ -597,7 +862,7 @@ static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object **
     }
     uint256_t l_fee = dap_chain_balance_scan(l_fee_str);
     if (IS_ZERO_256(l_fee)) {
-        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -fee <256 bit integer>");
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -fee <256 bit integer> and not equal zer");
         return ERROR_VALUE;
     }
 
@@ -614,21 +879,55 @@ static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object **
     const char *l_sign_str = dap_chain_wallet_check_sign(l_wallet);
     dap_enc_key_t *l_enc_key = dap_chain_wallet_get_key(l_wallet, 0);
     dap_chain_wallet_close(l_wallet);
-    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-addr_to", &l_addr_str);
+
+    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-value", &l_value_str);
     if (!l_value_str) {
-        DAP_DELETE(l_enc_key);
-        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -addr_to");
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -value");
         return ERROR_PARAM;
     }
-    dap_chain_addr_t *l_addr = dap_chain_addr_from_str(l_addr_str);
-    if (!l_addr) {
+    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-to_addr", &l_addr_str);
+    if (!l_addr_str) {
         DAP_DELETE(l_enc_key);
-        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Incorrect addr format for string %s", l_addr_str);
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -to_addr");
+        return ERROR_PARAM;
+    }
+
+    l_addr_el_count = dap_chain_addr_from_str_array(l_addr_str, &l_to_addr);
+    l_value_el_count = dap_str_symbol_count(l_value_str, ',') + 1;
+
+    if (l_addr_el_count != l_value_el_count) {
+        DAP_DELETE(l_to_addr);
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "num of '-to_addr' and '-value' should be equal");
         return ERROR_VALUE;
     }
-     // Create emission from conditional transaction
-    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, NULL);
-    DAP_DEL_MULTY(l_enc_key, l_addr);
+
+    l_value = DAP_NEW_Z_COUNT(uint256_t, l_value_el_count);
+    if (!l_value) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_MEMORY, c_error_memory_alloc);
+        return ERROR_MEMORY;
+    }
+    char **l_value_array = dap_strsplit(l_value_str, ",", l_value_el_count);
+    if (!l_value_array) {
+        DAP_DELETE(l_value);
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Can't read '-to_addr' arg");
+        return ERROR_PARAM;
+    }
+    for (size_t i = 0; i < l_value_el_count; ++i) {
+        l_value[i] = dap_chain_balance_scan(l_value_array[i]);
+        if(IS_ZERO_256(l_value[i])) {
+            DAP_DELETE(l_value);
+            dap_strfreev(l_value_array);
+            dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -value <256 bit integer> and not equal zero");
+            return ERROR_VALUE;
+        }
+    }
+    dap_strfreev(l_value_array);
+
+    // Create emission from conditional transaction
+    
+    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_to_addr, l_value, l_addr_el_count, l_fee, &l_tx_in_hash, l_tsd_list);
+    DAP_DEL_MULTY(l_value, l_to_addr, l_enc_key);
+    dap_list_free_full(l_tsd_list, NULL);
     if (!l_tx) {
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_CREATE, "Can't compose transaction for delegated emission");
         return ERROR_CREATE;
@@ -651,7 +950,7 @@ static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object **
 
 static int s_cli_sign(int a_argc, char **a_argv, int a_arg_index, json_object **a_json_arr_reply, dap_chain_net_t *a_net, dap_chain_t *a_chain, const char *a_hash_out_type)
 {
-    const char *l_tx_in_hash_str = NULL, *l_wallet_str = NULL;
+    const char *l_tx_in_hash_str = NULL, *l_wallet_str = NULL, *l_cert_str = NULL;
     dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-tx", &l_tx_in_hash_str);
     if (!l_tx_in_hash_str) {
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -tx");
@@ -667,19 +966,37 @@ static int s_cli_sign(int a_argc, char **a_argv, int a_arg_index, json_object **
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "TX %s not found in mempool", l_tx_in_hash_str);
         return ERROR_VALUE;
     }
+
+    dap_enc_key_t *l_enc_key = NULL;
+    const char *l_sign_str = NULL;
+
     dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-w", &l_wallet_str);
-    if (!l_wallet_str) {
-        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -w");
+    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-cert", &l_cert_str);
+    if (!l_wallet_str && !l_cert_str) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation sign requires parameter -w or -cert");
         return ERROR_PARAM;
     }
-    dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config), NULL);
-    if (!l_wallet) {
-        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Specified wallet %s not found", l_wallet_str);
-        return ERROR_VALUE;
+    if (l_wallet_str) {
+        dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config), NULL);
+        if (!l_wallet) {
+            dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Specified wallet %s not found", l_wallet_str);
+            return ERROR_VALUE;
+        }
+        l_sign_str = dap_chain_wallet_check_sign(l_wallet);
+        l_enc_key = dap_chain_wallet_get_key(l_wallet, 0);
+        dap_chain_wallet_close(l_wallet);
+    } else if (l_cert_str) {
+        dap_cert_t *l_cert = dap_cert_find_by_name(l_cert_str);
+        if (!l_cert) {
+            dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Specified certificate %s not found", l_cert_str);
+            return ERROR_VALUE;
+        }
+        if (dap_sign_type_is_depricated(dap_sign_type_from_key_type(l_cert->enc_key->type)))
+            l_sign_str = "The Bliss, Picnic and Tesla signatures is deprecated. We recommend you to create a new wallet with another available signature and transfer funds there.\n";
+        else
+            l_sign_str = "";
+        l_enc_key = dap_cert_get_keys_from_certs(&l_cert, 1, 0);
     }
-    const char *l_sign_str = dap_chain_wallet_check_sign(l_wallet);
-    dap_enc_key_t *l_enc_key = dap_chain_wallet_get_key(l_wallet, 0);
-    dap_chain_wallet_close(l_wallet);
 
      // Create emission from conditional transaction
     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);
@@ -707,6 +1024,70 @@ static int s_cli_sign(int a_argc, char **a_argv, int a_arg_index, json_object **
     return DAP_NO_ERROR;
 }
 
+static int s_cli_info(int a_argc, char **a_argv, int a_arg_index, json_object **a_json_arr_reply, dap_chain_net_t *a_net, dap_chain_t *a_chain, const char *a_hash_out_type)
+{
+    const char *l_tx_hash_str = NULL, *l_wallet_str = NULL;
+    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-tx", &l_tx_hash_str);
+    if (!l_tx_hash_str) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -tx");
+        return ERROR_PARAM;
+    }
+    dap_hash_fast_t l_tx_hash;
+    if (dap_chain_hash_fast_from_str(l_tx_hash_str, &l_tx_hash)) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Can't recognize %s as a hex or base58 format hash", l_tx_hash_str);
+        return ERROR_VALUE;
+    }
+    dap_hash_fast_t l_final_tx_hash = dap_ledger_get_final_chain_tx_hash(a_net->pub.ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_EMIT_DELEGATE, &l_tx_hash, false);
+    dap_chain_datum_tx_t *l_tx = dap_ledger_tx_find_by_hash(a_net->pub.ledger, &l_final_tx_hash);
+    dap_chain_tx_out_cond_t *l_cond = dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_EMIT_DELEGATE, NULL);
+    if (!l_cond) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_TX_MISMATCH, "Can't find final tx_out_cond");
+        return ERROR_TX_MISMATCH;
+    }
+
+    const char *l_tx_ticker = dap_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, &l_final_tx_hash);
+    const char *l_balance_coins, *l_balance_datoshi = dap_uint256_to_char(l_cond->header.value, &l_balance_coins);
+    
+    json_object *l_jobj_balance = json_object_new_object();
+    json_object *l_jobj_token = json_object_new_object();
+    json_object *l_jobj_take_verify = json_object_new_object();
+    json_object *l_jobj_pkey_hashes = json_object_new_array();
+    json_object *l_jobj_tags = json_object_new_array();
+    json_object *l_json_jobj_info = json_object_new_object();
+
+    bool l_is_base_hash_type = dap_strcmp(a_hash_out_type, "hex");
+    // tocken block
+    const char *l_description =  dap_ledger_get_description_by_ticker(a_net->pub.ledger, l_tx_ticker);
+    json_object *l_jobj_description = l_description ? json_object_new_string(l_description)
+                                                    : json_object_new_null();
+    json_object_object_add(l_jobj_token, "ticker", json_object_new_string(l_tx_ticker));
+    json_object_object_add(l_jobj_token, "description", l_jobj_description);
+    // balance block
+    json_object_object_add(l_jobj_balance, "coins", json_object_new_string(l_balance_coins));
+    json_object_object_add(l_jobj_balance, "datoshi", json_object_new_string(l_balance_datoshi));
+    // verify block
+    json_object_object_add(l_jobj_take_verify, "signs_minimum", json_object_new_uint64(l_cond->subtype.srv_emit_delegate.signers_minimum));
+    dap_tsd_t *l_tsd = NULL; size_t l_tsd_size = 0;
+    dap_tsd_iter(l_tsd, l_tsd_size, l_cond->tsd, l_cond->tsd_size) {
+        if (l_tsd->type == DAP_CHAIN_TX_OUT_COND_TSD_HASH && l_tsd->size == sizeof(dap_hash_fast_t)) {
+            json_object_array_add(l_jobj_pkey_hashes, json_object_new_string(l_is_base_hash_type ? dap_enc_base58_encode_hash_to_str_static((const dap_chain_hash_fast_t *)l_tsd->data) : dap_hash_fast_to_str_static((const dap_chain_hash_fast_t *)l_tsd->data)));
+        }
+        if (l_tsd->type == DAP_CHAIN_TX_OUT_COND_TSD_STR) {
+            json_object_array_add(l_jobj_tags, json_object_new_string((char*)(l_tsd->data)));
+        }
+    }
+    json_object_object_add(l_jobj_take_verify, "owner_hashes", l_jobj_pkey_hashes);
+    // result block
+    json_object_object_add(l_json_jobj_info, "tx_hash", json_object_new_string(l_is_base_hash_type ? dap_enc_base58_encode_hash_to_str_static(&l_tx_hash) : dap_hash_fast_to_str_static(&l_tx_hash)));
+    json_object_object_add(l_json_jobj_info, "tx_hash_final", json_object_new_string(l_is_base_hash_type ? dap_enc_base58_encode_hash_to_str_static(&l_final_tx_hash) : dap_hash_fast_to_str_static(&l_final_tx_hash)));
+    json_object_object_add(l_json_jobj_info, "tags", l_jobj_tags);
+    json_object_object_add(l_json_jobj_info, "balance", l_jobj_balance);
+    json_object_object_add(l_json_jobj_info, "take_verify", l_jobj_take_verify);
+    json_object_object_add(l_json_jobj_info, "token", l_jobj_token);
+    json_object_array_add(*a_json_arr_reply, l_json_jobj_info);
+    return DAP_NO_ERROR;
+}
+
 /**
  * @brief s_cli_stake_lock
  * @param a_argc
@@ -717,9 +1098,6 @@ static int s_cli_sign(int a_argc, char **a_argv, int a_arg_index, json_object **
 static int s_cli_emit_delegate(int a_argc, char **a_argv, void **a_str_reply)
 {
     json_object **a_json_arr_reply = (json_object **)a_str_reply;
-    enum {
-        CMD_NONE, CMD_HOLD, CMD_TAKE, CMD_SIGN
-    };
     int l_arg_index = 1;
     dap_chain_net_t *l_net = NULL;
     dap_chain_t *l_chain = NULL;
@@ -727,7 +1105,7 @@ static int s_cli_emit_delegate(int a_argc, char **a_argv, void **a_str_reply)
     dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-H", &l_hash_out_type);
     if (!l_hash_out_type)
         l_hash_out_type = "hex";
-    else if (dap_strcmp(l_hash_out_type," hex") && dap_strcmp(l_hash_out_type, "base58")) {
+    else if (dap_strcmp(l_hash_out_type,"hex") && dap_strcmp(l_hash_out_type, "base58")) {
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM,
                                 "Invalid parameter -H, valid values: -H <hex | base58>");
         return ERROR_PARAM;
@@ -736,13 +1114,21 @@ static int s_cli_emit_delegate(int a_argc, char **a_argv, void **a_str_reply)
     if (l_err_net_chain)
         return l_err_net_chain;
 
-    int l_cmd_num = CMD_NONE;
+    if (dap_chain_net_get_load_mode(l_net)) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_NETWORK, "Can't apply command while network in load mode");
+        return ERROR_NETWORK;
+    }
+
     if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "hold", NULL))
         return s_cli_hold(a_argc, a_argv, l_arg_index + 1, a_json_arr_reply, l_net, l_chain, l_hash_out_type);
+    else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "refill", NULL))
+        return s_cli_refill(a_argc, a_argv, l_arg_index + 1, a_json_arr_reply, l_net, l_chain, l_hash_out_type);
     else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "take", NULL))
         return s_cli_take(a_argc, a_argv, l_arg_index + 1, a_json_arr_reply, l_net, l_chain, l_hash_out_type);
     else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "sign", NULL))
         return s_cli_sign(a_argc, a_argv, l_arg_index + 1, a_json_arr_reply, l_net, l_chain, l_hash_out_type);
+    else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "info", NULL))
+        return s_cli_info(a_argc, a_argv, l_arg_index + 1, a_json_arr_reply, l_net, l_chain, l_hash_out_type);
     else {
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_SUBCOMMAND, "Subcommand %s not recognized", a_argv[l_arg_index]);
         return ERROR_SUBCOMMAND;
@@ -753,13 +1139,43 @@ int dap_chain_net_srv_emit_delegate_init()
 {
     dap_ledger_verificator_add(DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_EMIT_DELEGATE, s_emit_delegate_verificator, NULL, NULL);
     dap_cli_server_cmd_add("emit_delegate", s_cli_emit_delegate, "Emitting delegation service commands",
-                "emit_delegate hold -net <net_name> -w <wallet_name> -token <ticker> -value <value> -fee <value>"
-                            "-signs_minimum <value_int> -pkey_hashes <hash1[,hash2,...,hashN]> [-chain <chain_name>] [-H {hex(default) | base58}]\n"
-                "emit_delegate take -net <net_name> -w <wallet_name> -tx <transaction_hash> -addr_to <addr> -value <value> -fee <value> [-chain <chain_name>] [-H {hex(default) | base58}]\n"
-                "emit_delegate sign -net <net_name> -w <wallet_name> -tx <transaction_hash> [-chain <chain_name>] [-H {hex(default) | base58}]\n\n"
-                            "Hint:\n"
-                            "\texample value_coins (only natural) 1.0 123.4567\n"
-                            "\texample value_datoshi (only integer) 1 20 0.4321e+4\n"
+                "emit_delegate hold - to create new delegation\n"
+                "\t-net <net_name>\n"
+                "\t-w <wallet_name> - wallet to writeoff value, pay fee and sign tx\n"
+                "\t-token <ticker> - token ticker to hold\n"
+                "\t-value <value> - value to hold\n"
+                "\t-fee <value> - fee value\n"
+                "\t-signs_minimum <value_int> - minimum signs count needed to verify take datum\n"
+                "\t-pkey_hashes <hash1[,hash2,...,hashN]> - owners pkey hashes, who can sign take datum\n"
+                "\t[-tag \"<str>\"] - additional info about tx\n"
+                "\t[-H {hex(default) | base58}] - datum hash return format\n"
+                "emit_delegate refill - to refill value\n"
+                "\t-net <net_name>\n"
+                "\t-w <wallet_name> - wallet to writeoff value and pay fee\n"
+                "\t-value <value> - value to refill\n"
+                "\t-fee <value> - fee value\n"
+                "\t-tx <transaction_hash> - shared funds tx hash to refill\n"
+                "\t[-H {hex(default) | base58}] - datum hash return format\n"
+                "emit_delegate take - create take datum to writeoff value from0 shared funds tx\n"
+                "\t-net <net_name>\n"
+                "\t-w <wallet_name> - wallet to pay fee\n"
+                "\t-tx <transaction_hash> - shared funds tx hash to writeoff\n"
+                "\t-to_addr <addr1[,addr2,...,addrN]> - recipient addresses, count should be equal values count\n"
+                "\t-value <value1[,value2,...,valueN]> - value sent to each recipient, count should be equal addresses count\n"
+                "\t-fee <value> - fee value\n"
+                "\t[-H {hex(default) | base58}] - datum hash return format\n"
+                "emit_delegate sign - add wallet sign to take datum\n"
+                "\t-net <net_name>\n"
+                "\t-w <wallet_name> | -cert <cert_name> - wallet or cert to sign\n"
+                "\t-tx <transaction_hash> - shared funds tx hash to sign\n"
+                "\t[-H {hex(default) | base58}] - datum hash return format\n"
+                "emit_delegate info - get info about shared funds tx by hash\n"
+                "\t-net <net_name>\n"
+                "\t-tx <transaction_hash> - shared funds tx hash to get info\n"
+                "\t[-H {hex(default) | base58}] - tx hash format\n"
+                "Hint:\n"
+                "\texample value_coins (only natural) 1.0 123.4567\n"
+                "\texample value_datoshi (only integer) 1 20 0.4321e+4\n"
     );
 
     dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_EMIT_DELEGATE_ID };
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 8cca1e2faa..d0545c22eb 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
@@ -2,6 +2,7 @@
 
 #define DAP_CHAIN_NET_SRV_EMIT_DELEGATE_ID 0x07
 #define DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF 0x14
+#define DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_REFILL 0x15
 
 #include "dap_chain_datum_tx.h"
 #include "dap_chain_mempool.h"
@@ -12,6 +13,8 @@ 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_list_t *tsd_items);
+                                                dap_chain_addr_t *a_addr_to, uint256_t *a_value, uint32_t a_addr_count, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t *tsd_items);
+dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_refilling_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key,
+                                                    uint256_t a_value, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* tsd_items);
 
 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/wallet/dap_chain_wallet.c b/modules/wallet/dap_chain_wallet.c
index 0438874c44..b6abfef6d9 100644
--- a/modules/wallet/dap_chain_wallet.c
+++ b/modules/wallet/dap_chain_wallet.c
@@ -1101,7 +1101,7 @@ const char* dap_chain_wallet_check_sign(dap_chain_wallet_t *a_wallet) {
     for (size_t i = 0; i < l_wallet_internal->certs_count; ++i) {
         dap_return_val_if_pass(!l_wallet_internal->certs[i], "The wallet contains an undefined certificate.\n");
         dap_sign_type_t l_sign_type = dap_sign_type_from_key_type(l_wallet_internal->certs[i]->enc_key->type);
-        if (SIG_TYPE_BLISS == l_sign_type.type || SIG_TYPE_PICNIC == l_sign_type.type || SIG_TYPE_TESLA == l_sign_type.type) {
+        if (dap_sign_type_is_depricated(l_sign_type)) {
             return "The Bliss, Picnic and Tesla signatures is deprecated. We recommend you to create a new wallet with another available signature and transfer funds there.\n";
         }
     }
diff --git a/modules/wallet/dap_chain_wallet_cache.c b/modules/wallet/dap_chain_wallet_cache.c
index f4a70a606b..2acea49e37 100644
--- a/modules/wallet/dap_chain_wallet_cache.c
+++ b/modules/wallet/dap_chain_wallet_cache.c
@@ -678,7 +678,7 @@ static int s_save_tx_cache_for_addr(dap_chain_t *a_chain, dap_chain_addr_t *a_ad
         dap_chain_addr_t l_addr;
         uint256_t l_value;
         uint8_t *l_prev_item = NULL;
-        int l_prev_idx;
+        int l_prev_idx = 0;
 
         switch(*l_tx_item) {
         case TX_ITEM_TYPE_IN: {
-- 
GitLab