From a40d78f605377b27f260ea14ca4a50db8c4b0f4b Mon Sep 17 00:00:00 2001 From: Dmitry Puzyrkov <dmitry.puzyrkov@demlabs.net> Date: Sat, 17 Feb 2024 16:13:59 +0000 Subject: [PATCH] [*] dex improvments. --- modules/common/include/dap_chain_common.h | 6 + .../xchange/dap_chain_net_srv_xchange.c | 202 ++++++++++++------ .../include/dap_chain_net_srv_xchange.h | 12 ++ 3 files changed, 154 insertions(+), 66 deletions(-) diff --git a/modules/common/include/dap_chain_common.h b/modules/common/include/dap_chain_common.h index 1cd03fdc77..6a34b334be 100644 --- a/modules/common/include/dap_chain_common.h +++ b/modules/common/include/dap_chain_common.h @@ -319,6 +319,7 @@ DAP_STATIC_INLINE uint256_t dap_chain_uint256_from_uint128(uint128_t a_from) return GET_256_FROM_128(a_from); } + uint64_t dap_chain_uint128_to(uint128_t a_from); // 256 uint64_t dap_chain_uint256_to(uint256_t a_from); @@ -328,6 +329,11 @@ uint64_t dap_chain_uint256_to(uint256_t a_from); #define dap_chain_balance_to_coins(a) dap_uint256_decimal_to_char(a) #define dap_chain_coins_to_balance(a) dap_uint256_scan_decimal(a) +DAP_STATIC_INLINE uint64_t dap_chain_balance_to_coins_uint(uint256_t val) +{ + DIV_256_COIN(val, dap_chain_coins_to_balance("1000000000000000000.0"), &val); + return val._lo.a; +} /** * @brief dap_chain_hash_to_str diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c index 65c57e1311..709bf6b816 100644 --- a/modules/service/xchange/dap_chain_net_srv_xchange.c +++ b/modules/service/xchange/dap_chain_net_srv_xchange.c @@ -85,7 +85,7 @@ static int s_callback_receipt_next_success(dap_chain_net_srv_t *a_srv, uint32_t static xchange_tx_type_t s_xchange_tx_get_type (dap_chain_net_t * a_net, dap_chain_datum_tx_t * a_tx, dap_chain_tx_out_cond_t **a_out_cond_item, int *a_item_idx, dap_chain_tx_out_cond_t **a_out_prev_cond_item); static int s_tx_check_for_open_close(dap_chain_net_t * a_net, dap_chain_datum_tx_t * a_tx); static bool s_string_append_tx_cond_info( dap_string_t * a_reply_str, dap_chain_net_t * a_net, dap_chain_datum_tx_t * a_tx, tx_opt_status_t a_filter_by_status, bool a_append_prev_hash, bool a_print_status,bool a_print_ts); -static bool s_srv_xchange_get_fee(dap_chain_net_id_t a_net_id, uint256_t *a_fee, dap_chain_addr_t *a_addr, uint16_t *a_type); +dap_chain_net_srv_xchange_price_t *s_xchange_price_from_order(dap_chain_net_t *a_net, dap_chain_datum_tx_t *a_order, uint256_t *a_fee, bool a_ret_is_invalid); static dap_chain_net_srv_xchange_t *s_srv_xchange; static bool s_debug_more = true; @@ -218,7 +218,7 @@ static bool s_xchange_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_ dap_chain_addr_t l_service_fee_addr, *l_seller_addr = &a_tx_out_cond->subtype.srv_xchange.seller_addr; uint16_t l_service_fee_type; dap_chain_net_t *l_net = a_ledger->net; - bool l_service_fee_used = s_srv_xchange_get_fee(l_net->pub.id, &l_service_fee_val, &l_service_fee_addr, &l_service_fee_type); + bool l_service_fee_used = dap_chain_net_srv_xchange_get_fee(l_net->pub.id, &l_service_fee_val, &l_service_fee_addr, &l_service_fee_type); const char *l_native_ticker = l_net->pub.native_ticker; const char *l_service_ticker = (l_service_fee_type == SERVICE_FEE_OWN_FIXED || l_service_fee_type == SERVICE_FEE_OWN_PERCENT) ? l_buy_ticker : l_native_ticker; @@ -345,7 +345,7 @@ static void s_callback_decree (dap_chain_net_srv_t * a_srv, dap_chain_net_t *a_n // pthread_rwlock_unlock(&s_service_fees_rwlock); } -static bool s_srv_xchange_get_fee(dap_chain_net_id_t a_net_id, uint256_t *a_fee, dap_chain_addr_t *a_addr, uint16_t *a_type) +bool dap_chain_net_srv_xchange_get_fee(dap_chain_net_id_t a_net_id, uint256_t *a_fee, dap_chain_addr_t *a_addr, uint16_t *a_type) { pthread_rwlock_wrlock(&s_service_fees_rwlock); dap_chain_net_srv_fee_item_t *l_fee = NULL; @@ -539,7 +539,7 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha if (l_net_fee_used) SUM_256_256(l_net_fee, a_price->fee, &l_total_fee); uint16_t l_service_fee_type; - bool l_service_fee_used = s_srv_xchange_get_fee(a_price->net->pub.id, &l_service_fee, &l_service_fee_addr, &l_service_fee_type); + bool l_service_fee_used = dap_chain_net_srv_xchange_get_fee(a_price->net->pub.id, &l_service_fee, &l_service_fee_addr, &l_service_fee_type); if (l_service_fee_used) { switch (l_service_fee_type) { case SERIVCE_FEE_NATIVE_PERCENT: @@ -757,7 +757,112 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha return l_tx; } +int dap_chain_net_srv_xchange_get_order_completion_rate(dap_chain_net_t *a_net, dap_hash_fast_t a_order_tx_hash) +{ + + dap_chain_datum_tx_t * l_tx = dap_ledger_tx_find_by_hash(a_net->pub.ledger, &a_order_tx_hash); + if (!l_tx){ + log_it(L_ERROR, "Cant find such tx in ledger"); + return 0; + } + + dap_chain_tx_out_cond_t *l_out_cond = dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE , NULL); + if (!l_out_cond || l_out_cond->header.srv_uid.uint64 != DAP_CHAIN_NET_SRV_XCHANGE_ID){ + log_it(L_ERROR, "It's not an order"); + return 0; + } + // TODO add filters to list (tokens, network, etc.) + dap_chain_net_srv_xchange_price_t * l_price = NULL; + l_price = s_xchange_price_from_order(a_net, l_tx, NULL, true); + if( !l_price ){ + log_it(L_ERROR, "Can't get price from order"); + return 0; + } + + dap_hash_fast_t * l_last_tx_hash = dap_ledger_get_final_chain_tx_hash(a_net->pub.ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_price->tx_hash); + if(!l_last_tx_hash){ + log_it(L_ERROR, " Can't get last tx cond hash from order"); + return 0; + } + + dap_chain_datum_tx_t * l_last_tx = dap_ledger_tx_find_by_hash(a_net->pub.ledger, l_last_tx_hash); + if(!l_last_tx_hash){ + log_it(L_ERROR, "Can't find last tx"); + return 0; + } + + uint256_t l_percent_completed = {}; + dap_chain_tx_out_cond_t *l_out_cond_last_tx = dap_chain_datum_tx_out_cond_get(l_last_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE , NULL); + + if(l_out_cond_last_tx){ + + SUBTRACT_256_256(l_out_cond->header.value, l_out_cond_last_tx->header.value, &l_percent_completed); + DIV_256_COIN(l_percent_completed, l_out_cond->header.value, &l_percent_completed); + MULT_256_COIN(l_percent_completed, dap_chain_coins_to_balance("100.0"), &l_percent_completed); + } else { + dap_chain_tx_out_cond_t *l_out_prev_cond_item = NULL; + xchange_tx_type_t tx_type = s_xchange_tx_get_type(a_net, l_last_tx, NULL, NULL, &l_out_prev_cond_item); + if (tx_type == TX_TYPE_EXCHANGE){ + SUBTRACT_256_256(l_out_cond->header.value, uint256_0, &l_percent_completed); + DIV_256_COIN(l_percent_completed, l_out_cond->header.value, &l_percent_completed); + MULT_256_COIN(l_percent_completed, dap_chain_coins_to_balance("100.0"), &l_percent_completed); + } else if (tx_type == TX_TYPE_INVALIDATE){ + SUBTRACT_256_256(l_out_cond->header.value, l_out_prev_cond_item->header.value, &l_percent_completed); + DIV_256_COIN(l_percent_completed, l_out_cond->header.value, &l_percent_completed); + MULT_256_COIN(l_percent_completed, dap_chain_coins_to_balance("100.0"), &l_percent_completed); + } + } + + return dap_chain_balance_to_coins_uint(l_percent_completed); +} + +enum dap_chain_net_srv_xchange_order_status dap_chain_net_srv_xchange_get_order_status(dap_chain_net_t *a_net, dap_hash_fast_t a_order_tx_hash) +{ + dap_chain_datum_tx_t * l_tx = dap_ledger_tx_find_by_hash(a_net->pub.ledger, &a_order_tx_hash); + if (!l_tx){ + log_it(L_ERROR, "Cant find such tx in ledger"); + return -1; + } + + dap_chain_tx_out_cond_t *l_out_cond = dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE , NULL); + if (!l_out_cond || l_out_cond->header.srv_uid.uint64 != DAP_CHAIN_NET_SRV_XCHANGE_ID){ + log_it(L_ERROR, "It's not an order"); + return -1; + } + + // TODO add filters to list (tokens, network, etc.) + dap_chain_net_srv_xchange_price_t * l_price = NULL; + l_price = s_xchange_price_from_order(a_net, l_tx, NULL, true); + if( !l_price ){ + log_it(L_ERROR, "Can't get price from order"); + return -1; + } + + dap_hash_fast_t * l_last_tx_hash = dap_ledger_get_final_chain_tx_hash(a_net->pub.ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_price->tx_hash); + if(!l_last_tx_hash){ + log_it(L_ERROR, " Can't get last tx cond hash from order"); + return -1; + } + + dap_chain_datum_tx_t * l_last_tx = dap_ledger_tx_find_by_hash(a_net->pub.ledger, l_last_tx_hash); + if(!l_last_tx_hash){ + log_it(L_ERROR, "Can't find last tx"); + return -1; + } + + dap_chain_tx_out_cond_t *l_out_cond_last_tx = dap_chain_datum_tx_out_cond_get(l_last_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE , NULL); + if (!l_out_cond_last_tx || IS_ZERO_256(l_out_cond_last_tx->header.value)){ + DAP_DEL_Z(l_price); + return XCHANGE_ORDER_STATUS_CLOSED; + } else { + DAP_DEL_Z(l_price); + return XCHANGE_ORDER_STATUS_OPENED; + } + DAP_DEL_Z(l_price); + return XCHANGE_ORDER_STATUS_UNKNOWN; + +} // Put the transaction to mempool static char* s_xchange_tx_put(dap_chain_datum_tx_t *a_tx, dap_chain_net_t *a_net) @@ -944,6 +1049,7 @@ dap_chain_net_srv_xchange_price_t *s_xchange_price_from_order(dap_chain_net_t *a dap_hash_fast_t l_tx_hash = {}; dap_hash_fast(a_order, dap_chain_datum_tx_get_size(a_order), &l_tx_hash); + l_price->order_hash = l_tx_hash; const char *l_token_sell = dap_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, &l_tx_hash); if (!l_token_sell){ log_it(L_CRITICAL, "Can't find tx token"); @@ -1348,6 +1454,19 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c return -18; } + switch (dap_chain_net_srv_xchange_get_order_status(l_net, l_order_tx_hash)) + { + case XCHANGE_ORDER_STATUS_OPENED: + l_status_order = "OPENED"; + break; + case XCHANGE_ORDER_STATUS_CLOSED: + l_status_order = "CLOSED"; + break; + default: + l_status_order = "UNKNOWN"; + break; + }; + dap_chain_tx_out_cond_t *l_out_cond_last_tx = dap_chain_datum_tx_out_cond_get(l_last_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE , NULL); if (!l_out_cond_last_tx || IS_ZERO_256(l_out_cond_last_tx->header.value)){ l_status_order = "CLOSED"; @@ -1361,51 +1480,28 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c char *l_amount_coins_str = l_out_cond_last_tx ? dap_chain_balance_to_coins(l_out_cond_last_tx->header.value) : NULL; char *l_amount_datoshi_str = l_out_cond_last_tx ? dap_chain_balance_print(l_out_cond_last_tx->header.value) : NULL; - char *l_percent_completed_str = NULL; - - uint256_t l_percent_completed = {}; - if(l_out_cond_last_tx){ - - SUBTRACT_256_256(l_out_cond->header.value, l_out_cond_last_tx->header.value, &l_percent_completed); - DIV_256_COIN(l_percent_completed, l_out_cond->header.value, &l_percent_completed); - MULT_256_COIN(l_percent_completed, dap_chain_coins_to_balance("100.0"), &l_percent_completed); - } else { - dap_chain_tx_out_cond_t *l_out_prev_cond_item = NULL; - xchange_tx_type_t tx_type = s_xchange_tx_get_type(l_net, l_last_tx, NULL, NULL, &l_out_prev_cond_item); - if (tx_type == TX_TYPE_EXCHANGE){ - SUBTRACT_256_256(l_out_cond->header.value, uint256_0, &l_percent_completed); - DIV_256_COIN(l_percent_completed, l_out_cond->header.value, &l_percent_completed); - MULT_256_COIN(l_percent_completed, dap_chain_coins_to_balance("100.0"), &l_percent_completed); - } else if (tx_type == TX_TYPE_INVALIDATE){ - SUBTRACT_256_256(l_out_cond->header.value, l_out_prev_cond_item->header.value, &l_percent_completed); - DIV_256_COIN(l_percent_completed, l_out_cond->header.value, &l_percent_completed); - MULT_256_COIN(l_percent_completed, dap_chain_coins_to_balance("100.0"), &l_percent_completed); - } - } - - l_percent_completed_str = dap_chain_balance_to_coins(l_percent_completed); - size_t l_str_len = strlen(l_percent_completed_str); - char* l_dot_pos = strstr(l_percent_completed_str, "."); - if (l_dot_pos && (l_str_len - (l_dot_pos - l_percent_completed_str)) > 2){ - *(char*)(l_dot_pos + 3) = '\0'; - } - + + + uint64_t l_percent_completed = dap_chain_net_srv_xchange_get_order_completion_rate(l_net, l_order_tx_hash); + + //l_percent_completed_str = dap_chain_balance_to_coins(l_percent_completed); + char l_tmp_buf[70] = {}; dap_time_t l_ts_create = (dap_time_t)l_tx->header.ts_created; dap_ctime_r(&l_ts_create, l_tmp_buf); l_tmp_buf[strlen(l_tmp_buf) - 1] = '\0'; - dap_cli_server_cmd_set_reply_text(a_str_reply, "orderHash: %s\n ts_created: %s (%"DAP_UINT64_FORMAT_U")\n Status: %s, amount: %s (%s) %s, filled: %s%%, rate (%s/%s): %s, net: %s\n\n", l_tx_hash_str, + dap_cli_server_cmd_set_reply_text(a_str_reply, "orderHash: %s\n ts_created: %s (%"DAP_UINT64_FORMAT_U")\n Status: %s, amount: %s (%s) %s, filled: %u%%, rate (%s/%s): %s, net: %s\n\n", l_tx_hash_str, l_tmp_buf, l_ts_create, l_status_order, l_amount_coins_str ? l_amount_coins_str : "0.0", l_amount_datoshi_str ? l_amount_datoshi_str : "0", - l_price->token_sell, l_percent_completed_str, + l_price->token_sell, l_percent_completed, l_price->token_buy, l_price->token_sell, l_cp_rate = dap_chain_balance_to_coins(l_price->rate), l_price->net->pub.name); DAP_DEL_Z(l_tx_hash_str); - DAP_DEL_Z(l_percent_completed_str); + DAP_DEL_Z(l_amount_coins_str); DAP_DEL_Z(l_amount_datoshi_str); DAP_DEL_Z(l_cp_rate); @@ -1907,34 +2003,8 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **reply) char *l_amount_coins_str = l_out_cond_last_tx ? dap_chain_balance_to_coins(l_out_cond_last_tx->header.value) : NULL; char *l_amount_datoshi_str = l_out_cond_last_tx ? dap_chain_balance_print(l_out_cond_last_tx->header.value) : NULL; - char *l_percent_completed_str = NULL; - - uint256_t l_percent_completed = {}; - if(l_out_cond_last_tx){ - SUBTRACT_256_256(l_out_cond->header.value, l_out_cond_last_tx->header.value, &l_percent_completed); - DIV_256_COIN(l_percent_completed, l_out_cond->header.value, &l_percent_completed); - MULT_256_COIN(l_percent_completed, dap_chain_coins_to_balance("100.0"), &l_percent_completed); - } else { - dap_chain_tx_out_cond_t *l_out_prev_cond_item = NULL; - xchange_tx_type_t tx_type = s_xchange_tx_get_type(l_net, l_last_tx, NULL, NULL, &l_out_prev_cond_item); - if (tx_type == TX_TYPE_EXCHANGE){ - SUBTRACT_256_256(l_out_cond->header.value, uint256_0, &l_percent_completed); - DIV_256_COIN(l_percent_completed, l_out_cond->header.value, &l_percent_completed); - MULT_256_COIN(l_percent_completed, dap_chain_coins_to_balance("100.0"), &l_percent_completed); - } else if (tx_type == TX_TYPE_INVALIDATE){ - SUBTRACT_256_256(l_out_cond->header.value, l_out_prev_cond_item->header.value, &l_percent_completed); - DIV_256_COIN(l_percent_completed, l_out_cond->header.value, &l_percent_completed); - MULT_256_COIN(l_percent_completed, dap_chain_coins_to_balance("100.0"), &l_percent_completed); - } - } - - l_percent_completed_str = dap_chain_balance_to_coins(l_percent_completed); - size_t l_str_len = strlen(l_percent_completed_str); - char* l_dot_pos = strstr(l_percent_completed_str, "."); - if (l_dot_pos && (l_str_len - (l_dot_pos - l_percent_completed_str)) > 2){ - *(char*)(l_dot_pos + 3) = '\0'; - } + uint64_t l_percent_completed = dap_chain_net_srv_xchange_get_order_completion_rate(l_net, l_tx_hash); char l_tmp_buf[70] = {}; dap_time_t l_ts_create = (dap_time_t)l_tx->header.ts_created; @@ -1942,11 +2012,11 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **reply) l_tmp_buf[strlen(l_tmp_buf) - 1] = '\0'; l_printed_orders_count++; - dap_string_append_printf(l_reply_str, "orderHash: %s\n ts_created: %s (%"DAP_UINT64_FORMAT_U")\n Status: %s, amount: %s (%s) %s, filled: %s%%, rate (%s/%s): %s, net: %s\n\n", l_tx_hash_str, + dap_string_append_printf(l_reply_str, "orderHash: %s\n ts_created: %s (%"DAP_UINT64_FORMAT_U")\n Status: %s, amount: %s (%s) %s, filled: %u%%, rate (%s/%s): %s, net: %s\n\n", l_tx_hash_str, l_tmp_buf, l_ts_create, l_status_order, l_amount_coins_str ? l_amount_coins_str : "0.0", l_amount_datoshi_str ? l_amount_datoshi_str : "0", - l_price->token_sell, l_percent_completed_str, + l_price->token_sell, l_percent_completed, l_price->token_buy, l_price->token_sell, l_cp_rate = dap_chain_balance_to_coins(l_price->rate), l_price->net->pub.name); @@ -2406,7 +2476,7 @@ void dap_chain_net_srv_xchange_print_fee(dap_chain_net_t *a_net, dap_string_t *a uint256_t l_fee = {0}; dap_chain_addr_t l_addr = {0}; uint16_t l_type = 0; - if (s_srv_xchange_get_fee(a_net->pub.id, &l_fee, &l_addr, &l_type)) { + if (dap_chain_net_srv_xchange_get_fee(a_net->pub.id, &l_fee, &l_addr, &l_type)) { char *l_fee_balance = dap_chain_balance_print(l_fee); char *l_fee_coins = dap_chain_balance_to_coins(l_fee); char *l_addr_str = dap_chain_addr_to_str(&l_addr); diff --git a/modules/service/xchange/include/dap_chain_net_srv_xchange.h b/modules/service/xchange/include/dap_chain_net_srv_xchange.h index 9345c079de..48293e9fbe 100644 --- a/modules/service/xchange/include/dap_chain_net_srv_xchange.h +++ b/modules/service/xchange/include/dap_chain_net_srv_xchange.h @@ -105,3 +105,15 @@ enum dap_chain_net_srv_xchange_purchase_error_list{ }; int dap_chain_net_srv_xchange_purchase(dap_chain_net_t *a_net, dap_hash_fast_t *a_order_hash, uint256_t a_value, uint256_t a_fee, dap_chain_wallet_t *a_wallet, char **a_hash_out); + +int dap_chain_net_srv_xchange_get_order_completion_rate(dap_chain_net_t *a_net, dap_hash_fast_t a_order_tx_hash); + +enum dap_chain_net_srv_xchange_order_status{ + XCHANGE_ORDER_STATUS_OPENED = 0, + XCHANGE_ORDER_STATUS_CLOSED, + XCHANGE_ORDER_STATUS_UNKNOWN, +}; + + +enum dap_chain_net_srv_xchange_order_status dap_chain_net_srv_xchange_get_order_status(dap_chain_net_t *a_net, dap_hash_fast_t a_order_tx_hash); +bool dap_chain_net_srv_xchange_get_fee(dap_chain_net_id_t a_net_id, uint256_t *a_fee, dap_chain_addr_t *a_addr, uint16_t *a_type); \ No newline at end of file -- GitLab