diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c
index 5c35ea33a5d2e8924b249f57c1cc131bcc959d80..d620ee7c64fad6d3771446b9fecb7ac5a57ad36f 100644
--- a/modules/service/xchange/dap_chain_net_srv_xchange.c
+++ b/modules/service/xchange/dap_chain_net_srv_xchange.c
@@ -22,6 +22,7 @@
     along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+#include <math.h>
 #include "dap_string.h"
 #include "dap_chain_common.h"
 #include "dap_chain_node_cli.h"
@@ -49,19 +50,19 @@ int dap_chain_net_srv_xchange_init()
 {
         dap_chain_node_cli_cmd_item_create("srv_xchange", s_cli_srv_xchange, NULL, "eXchange service commands",
         "srv_xchange price create -net_sell <net name> -token_sell <token ticker> -net_buy <net_name> -token_buy <token ticker>"
-                                            "-wallet <name> -datoshi_sell <value> -rate <value>\n"
-            "\tCreate a new price with specified amounts of datoshi to exchange\n"
+                                            "-wallet <name> -coins <value> -rate <value>\n"
+            "\tCreate a new price with specified amount of datoshi to exchange with specified rate (sell : buy)\n"
         "srv_xchange price remove -net_sell <net name> -token_sell <token ticker> -net_buy <net_name> -token_buy <token ticker>\n"
              "\tRemove price with specified tickers within specified net names\n"
         "srv_xchange price list\n"
              "\tList all active prices\n"
         "srv_xchange price update -net_sell <net name> -token_sell <token ticker> -net_buy <net_name> -token_buy <token ticker>"
-                                            "{-datoshi_sell <value> | rate <value> | -wallet <name>}\n"
+                                            "{-coins <value> | rate <value> | -wallet <name>}\n"
              "\tUpdate price with specified tickers within specified net names\n"
         "srv_xchange orders -net <net name>\n"
              "\tGet the exchange orders list within specified net name\n"
-        "srv_xchange purchase -order <order hash> -net <net name> -wallet <wallet_name>\n"
-             "\tExchange tokens with specified order within specified net name\n"
+        "srv_xchange purchase -order <order hash> -net <net name> -wallet <wallet_name> -coins <value>\n"
+             "\tExchange tokens with specified order within specified net name. Specify how datoshies to buy\n"
         "srv_xchange enable\n"
              "\tEnable eXchange service\n"
         "srv_xchange disable\n"
@@ -104,18 +105,27 @@ bool dap_chain_net_srv_xchange_verificator(dap_chain_tx_out_cond_t *a_cond, dap_
         return true;
     } else {
         dap_list_t *l_list_out = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT_EXT, NULL);
-
-        uint64_t l_out_val = 0;
-        for (dap_list_t *l_list_tmp = l_list_out;l_list_tmp;  l_list_tmp = l_list_tmp->next) {
+        long double l_seller_rate = (long double)a_cond->header.value / a_cond->subtype.srv_xchange.value;
+        uint64_t l_out_val = 0, l_back_val = 0;
+        char *l_ticker_ctrl = NULL;
+        for (dap_list_t *l_list_tmp = l_list_out; l_list_tmp;  l_list_tmp = l_list_tmp->next) {
             dap_chain_tx_out_ext_t *l_tx_out = (dap_chain_tx_out_ext_t *)l_list_tmp->data;
-            if (memcmp(&l_tx_out->addr, &a_cond->params, sizeof(dap_chain_addr_t)) ||
-                    strcmp(l_tx_out->token, a_cond->subtype.srv_xchange.token)) {
+            if (memcmp(&l_tx_out->addr, &a_cond->params, sizeof(dap_chain_addr_t))) {
                 continue;
             }
-            l_out_val += l_tx_out->header.value;
+            if (strcmp(l_tx_out->token, a_cond->subtype.srv_xchange.token)) {
+                if (l_ticker_ctrl && strcmp(l_ticker_ctrl, l_tx_out->token)) {
+                    return false;   // too many tokens
+                }
+                l_ticker_ctrl = l_tx_out->token;
+                l_back_val += l_tx_out->header.value;
+            } else {                // buying token
+                l_out_val += l_tx_out->header.value;
+            }
         }
-        if (l_out_val != a_cond->subtype.srv_xchange.value) {
-            return false;
+        long double l_buyer_rate = (a_cond->header.value - l_back_val) / (long double)l_out_val;
+        if (l_seller_rate < l_buyer_rate) {
+            return false;           // wrong changing rate
         }
     }
     return true;
@@ -276,7 +286,7 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha
         if (dap_chain_datum_tx_add_out_ext_item(&l_tx, l_seller_addr, a_price->datoshi_buy, a_price->token_buy) == -1) {
             dap_chain_datum_tx_delete(l_tx);
             DAP_DELETE(l_seller_addr);
-            log_it(L_ERROR, "Cant add buying coins output");
+            log_it(L_ERROR, "Can't add buying coins output");
             return NULL;
         }
         DAP_DELETE(l_seller_addr);
@@ -284,10 +294,10 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha
         uint64_t l_buying_value = l_tx_out_cond->header.value;
         l_value_back = l_buying_value - a_price->datoshi_buy;
         if (l_value_back) {
-            //if (dap_chain_datum_tx_add_out_ext_item(&l_tx, l_buyer_addr, l_value_back, a_price->token_buy) == -1) {
-                log_it(L_WARNING, "Partial exchange not allowed");
+            if (dap_chain_datum_tx_add_out_ext_item(&l_tx, l_buyer_addr, l_value_back, a_price->token_buy) == -1) {
+                log_it(L_WARNING, "Can't add buying coins back output (cashback)");
                 return NULL;
-            //}
+            }
         }
     }
 
@@ -491,14 +501,14 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c
                 return -7;
             }
             const char *l_val_sell_str = NULL, *l_val_rate_str = NULL, *l_wallet_str = NULL;
-            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-datoshi_sell", &l_val_sell_str);
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-coins", &l_val_sell_str);
             if (!l_val_sell_str) {
-                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'price create' required parameter -datoshi_sell");
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'price create' required parameter -coins");
                 return -8;
             }
             uint64_t l_datoshi_sell = strtoull(l_val_sell_str, NULL, 10);
             if (!l_datoshi_sell) {
-                dap_chain_node_cli_set_reply_text(a_str_reply, "Format -datoshi_sell <unsigned long long>");
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Format -coins <unsigned long long>");
                 return -9;
             }
             dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-rate", &l_val_rate_str);
@@ -597,11 +607,11 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c
                     uint64_t l_datoshi_sell = 0;
                     long double l_rate = 0;
                     dap_chain_wallet_t *l_wallet = NULL;
-                    dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-datoshi_sell", &l_val_sell_str);
+                    dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-coins", &l_val_sell_str);
                     if (l_val_sell_str) {
                         l_datoshi_sell = strtoull(l_val_sell_str, NULL, 10);
                         if (!l_datoshi_sell) {
-                            dap_chain_node_cli_set_reply_text(a_str_reply, "Format -datoshi_sell <unsigned long long>");
+                            dap_chain_node_cli_set_reply_text(a_str_reply, "Format -coins <unsigned long long>");
                             return -9;
                         }
                     }
@@ -773,7 +783,7 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void *a_arg_func, char *
             *a_str_reply = dap_string_free(l_reply_str, false);
         } break;
         case CMD_PURCHASE: {
-            const char *l_net_str = NULL, *l_wallet_str = NULL, *l_order_hash_str = NULL;
+            const char *l_net_str = NULL, *l_wallet_str = NULL, *l_order_hash_str = NULL, *l_val_buy_str = NULL;
             l_arg_index++;
             dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str);
             if (!l_net_str) {
@@ -800,9 +810,24 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void *a_arg_func, char *
                 dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'purchase' required parameter -order");
                 return -12;
             }
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-coins", &l_val_buy_str);
+            if (!l_val_buy_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'price create' required parameter -coins");
+                return -8;
+            }
+            uint64_t l_datoshi_buy = strtoull(l_val_buy_str, NULL, 10);
+            if (!l_datoshi_buy) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Format -coins <unsigned long long>");
+                return -9;
+            }
             dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_str);
             if (l_order) {
                 dap_chain_net_srv_xchange_price_t *l_price = s_xchange_price_from_order(l_net, l_order);
+                if (l_price->datoshi_buy != l_datoshi_buy) {
+                    long double l_rate = (long double)l_price->datoshi_buy / l_price->datoshi_sell;
+                    l_price->datoshi_buy = l_datoshi_buy;
+                    l_price->datoshi_sell = ceill(l_datoshi_buy * l_rate);
+                 }
                 // Create conditional transaction
                 dap_chain_datum_tx_t *l_tx = s_xchange_tx_create_exchange(l_price, &l_order->tx_cond_hash, l_wallet);
                 if (l_tx && s_xchange_tx_put(l_tx, l_net)) {