diff --git a/modules/common/dap_chain_common.c b/modules/common/dap_chain_common.c index b210b2806228484a3dffb7c10fdecfc3c32654a1..c611a4ddf75f81c38a50ddd29a313fad3efdbea7 100644 --- a/modules/common/dap_chain_common.c +++ b/modules/common/dap_chain_common.c @@ -213,17 +213,17 @@ int dap_chain_addr_check_sum(const dap_chain_addr_t *a_addr) return memcmp(a_addr->checksum.raw, l_checksum.raw, sizeof(l_checksum.raw)); } -void s_set_offset_limit_json(json_object * a_json_obj_out, size_t *a_start, size_t *a_and, size_t a_limit, size_t a_offset, size_t a_and_count) +void dap_chain_set_offset_limit_json(json_object * a_json_obj_out, size_t *a_start, size_t *a_and, size_t a_limit, size_t a_offset, size_t a_and_count) { json_object* json_obj_lim = json_object_new_object(); if (a_offset > 0) { *a_start = a_offset; - json_object_object_add(json_obj_lim, "offset", json_object_new_int(*a_start)); + json_object_object_add(json_obj_lim, "offset", json_object_new_uint64(*a_start)); } *a_and = a_and_count; if (a_limit > 0) { *a_and = *a_start + a_limit; - json_object_object_add(json_obj_lim, "limit", json_object_new_int(*a_and - *a_start)); + json_object_object_add(json_obj_lim, "limit", json_object_new_uint64(*a_and - *a_start)); } else json_object_object_add(json_obj_lim, "limit", json_object_new_string("unlimit")); diff --git a/modules/common/include/dap_chain_common.h b/modules/common/include/dap_chain_common.h index c180ed725ddbb9c2741d5ebb32a678d30f21e905..69bc2c00fc68f50e450738672c1e607d3df5152d 100644 --- a/modules/common/include/dap_chain_common.h +++ b/modules/common/include/dap_chain_common.h @@ -234,7 +234,7 @@ int dap_chain_addr_fill_from_key(dap_chain_addr_t *a_addr, dap_enc_key_t *a_key, int dap_chain_addr_fill_from_sign(dap_chain_addr_t *a_addr, dap_sign_t *a_sign, dap_chain_net_id_t a_net_id); int dap_chain_addr_check_sum(const dap_chain_addr_t *a_addr); -void s_set_offset_limit_json(json_object * a_json_obj_out, size_t *a_start, size_t *a_and, size_t a_limit, size_t a_offset, size_t a_and_count); +void dap_chain_set_offset_limit_json(json_object * a_json_obj_out, size_t *a_start, size_t *a_and, size_t a_limit, size_t a_offset, size_t a_and_count); DAP_STATIC_INLINE bool dap_chain_addr_compare(const dap_chain_addr_t *a_addr1, const dap_chain_addr_t *a_addr2) { diff --git a/modules/net/dap_chain_ledger.c b/modules/net/dap_chain_ledger.c index e3d7e092756367532273ec343c85792f6454e693..5d15b33d5dda7a08e8d98310bf2aca0fb9546946 100644 --- a/modules/net/dap_chain_ledger.c +++ b/modules/net/dap_chain_ledger.c @@ -1952,7 +1952,7 @@ json_object *dap_ledger_threshold_info(dap_ledger_t *a_ledger, size_t a_limit, s uint32_t l_counter = 0; size_t l_arr_start = 0; size_t l_arr_end = 0; - s_set_offset_limit_json(json_arr_out, &l_arr_start, &l_arr_end, a_limit, a_offset, HASH_COUNT(l_ledger_pvt->threshold_txs)); + dap_chain_set_offset_limit_json(json_arr_out, &l_arr_start, &l_arr_end, a_limit, a_offset, HASH_COUNT(l_ledger_pvt->threshold_txs)); pthread_rwlock_rdlock(&l_ledger_pvt->threshold_txs_rwlock); if (a_threshold_hash) { @@ -2021,7 +2021,7 @@ json_object *dap_ledger_balance_info(dap_ledger_t *a_ledger, size_t a_limit, siz dap_ledger_wallet_balance_t *l_balance_item, *l_balance_tmp; size_t l_arr_start = 0; size_t l_arr_end = 0; - s_set_offset_limit_json(json_arr_out, &l_arr_start, &l_arr_end, a_limit, a_offset, HASH_COUNT(l_ledger_pvt->balance_accounts)); + dap_chain_set_offset_limit_json(json_arr_out, &l_arr_start, &l_arr_end, a_limit, a_offset, HASH_COUNT(l_ledger_pvt->balance_accounts)); size_t i_tmp = 0; if (a_head) diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c index 9cea97c5224afea5a87951b58ec9fd51bcf8ad59..d69cb85a27b7da5cf2d98b1b645035383cb1cbd8 100644 --- a/modules/net/dap_chain_node_cli_cmd.c +++ b/modules/net/dap_chain_node_cli_cmd.c @@ -4412,11 +4412,11 @@ static int s_parse_additional_token_decl_arg(int a_argc, char ** a_argv, json_ob static int s_token_decl_check_params(int a_argc, char **a_argv, void **a_str_reply, dap_sdk_cli_params *a_params, bool a_update_token) { - int l_parse_params = s_parse_common_token_decl_arg(a_argc,a_argv,a_str_reply,a_params, a_update_token); + int l_parse_params = s_parse_common_token_decl_arg(a_argc,a_argv, *(json_object**)a_str_reply,a_params, a_update_token); if (l_parse_params) return l_parse_params; - l_parse_params = s_parse_additional_token_decl_arg(a_argc,a_argv,a_str_reply,a_params, a_update_token); + l_parse_params = s_parse_additional_token_decl_arg(a_argc,a_argv, *(json_object**)a_str_reply, a_params, a_update_token); if (l_parse_params) return l_parse_params; diff --git a/modules/net/dap_chain_node_cli_cmd_tx.c b/modules/net/dap_chain_node_cli_cmd_tx.c index afb5d99d285584e3c32b8d6df9ea5a7c21057b63..eade51cfdaebae0687ca4d96a748af0c31328e35 100644 --- a/modules/net/dap_chain_node_cli_cmd_tx.c +++ b/modules/net/dap_chain_node_cli_cmd_tx.c @@ -343,7 +343,7 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t bool look_for_unknown_service = (a_srv && strcmp(a_srv,"unknown") == 0); size_t l_arr_start = 0; size_t l_arr_end = 0; - s_set_offset_limit_json(json_obj_datum, &l_arr_start, &l_arr_end, a_limit, a_offset, a_chain->callback_count_tx(a_chain)); + dap_chain_set_offset_limit_json(json_obj_datum, &l_arr_start, &l_arr_end, a_limit, a_offset, a_chain->callback_count_tx(a_chain)); size_t i_tmp = 0; size_t @@ -821,7 +821,7 @@ json_object *dap_db_history_tx_all(json_object* a_json_arr_reply, dap_chain_t *a json_object * json_tx_history = NULL; size_t l_arr_start = 0; size_t l_arr_end = 0; - s_set_offset_limit_json(json_arr_out, &l_arr_start, &l_arr_end, a_limit, a_offset, a_chain->callback_count_tx(a_chain)); + dap_chain_set_offset_limit_json(json_arr_out, &l_arr_start, &l_arr_end, a_limit, a_offset, a_chain->callback_count_tx(a_chain)); bool look_for_unknown_service = (a_srv && strcmp(a_srv,"unknown") == 0); // load transactions diff --git a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c index 581c26b64c10618639aece02164585574be2ae29..2d6760c62d2f98feaf3e812a3853ebd7670f73ba 100644 --- a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c +++ b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c @@ -3514,7 +3514,7 @@ static json_object* s_dap_chain_net_srv_stake_reward_all(json_object* a_json_arr size_t l_arr_start = 0; size_t l_arr_end = 0; - s_set_offset_limit_json(json_obj_reward, &l_arr_start, &l_arr_end, a_limit, a_offset, a_chain->callback_count_tx(a_chain)); + dap_chain_set_offset_limit_json(json_obj_reward, &l_arr_start, &l_arr_end, a_limit, a_offset, a_chain->callback_count_tx(a_chain)); if (a_node_info){ json_object* json_obj_addr = json_object_new_object(); diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c index c38d0f19f14d9484f49af4277c7ae8f38a858f55..234d5cff8076ba01a54bbd75277cb4fda9bcdae5 100644 --- a/modules/service/xchange/dap_chain_net_srv_xchange.c +++ b/modules/service/xchange/dap_chain_net_srv_xchange.c @@ -118,8 +118,12 @@ static int s_callback_requested(dap_chain_net_srv_t *a_srv, uint32_t a_usage_id, static int s_callback_response_success(dap_chain_net_srv_t *a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_remote_t *a_srv_client, const void *a_data, size_t a_data_size); static int s_callback_response_error(dap_chain_net_srv_t *a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_remote_t *a_srv_client, const void *a_data, size_t a_data_size); static int s_callback_receipt_next_success(dap_chain_net_srv_t *a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_remote_t *a_srv_client, const void *a_data, size_t a_data_size); + static dap_chain_net_srv_xchange_order_status_t 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_addr_t *a_owner_addr, dap_chain_addr_t *a_buyer_addr, dap_chain_datum_tx_t * a_tx, dap_hash_fast_t *a_tx_hash, tx_opt_status_t a_filter_by_status, bool a_append_prev_hash, bool a_print_status,bool a_print_ts); +static bool s_string_append_tx_cond_info_json(json_object * a_json_out, dap_chain_net_t *a_net, dap_chain_addr_t *a_owner_addr, dap_chain_addr_t *a_buyer_addr, + dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, tx_opt_status_t a_filter_by_status, + bool a_append_prev_hash, bool a_print_status, bool a_print_ts); + 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, dap_hash_fast_t *a_order_hash, uint256_t *a_fee, bool a_ret_is_invalid); static void s_ledger_tx_add_notify(void *a_arg, dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, dap_chan_ledger_notify_opcodes_t a_opcode); @@ -237,7 +241,7 @@ int dap_chain_net_srv_xchange_init() "srv_xchange token_pair -net <net_name> list all [-limit <limit>] [-offset <offset>]\n" "\tList of all token pairs\n" - "srv_xchange token_pair -net <net_name> rate average -token_from <token_ticker> -token_to <token_ticker>\n" + "srv_xchange token_pair -net <net_name> rate average [-time_from <From_time>] [-time_to <To_time>]\n" "\tGet average rate for token pair <token from>:<token to> from <From time> to <To time> \n" "srv_xchange token_pair -net <net_name> rate history -token_from <token_ticker> -token_to <token_ticker> [-time_from <From_time>] [-time_to <To_time>] [-limit <limit>] [-offset <offset>]\n" "\tPrint rate history for token pair <token from>:<token to> from <From time> to <To time>\n" @@ -1263,7 +1267,7 @@ dap_chain_net_srv_xchange_price_t *s_xchange_price_from_order(dap_chain_net_t *a * @param a_str_reply * @return */ -static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, void **a_str_reply) +static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, json_object **a_json_arr_reply) { enum { CMD_NONE, CMD_CREATE, CMD_REMOVE, CMD_UPDATE, CMD_HISTORY, CMD_STATUS @@ -1290,63 +1294,72 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, v case CMD_CREATE: { dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str); if (!l_net_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'order create' requires parameter -net"); - return -2; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_REQ_PARAM_NET_ERR, "Command 'order create' requires parameter -net"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_REQ_PARAM_NET_ERR; } l_net = dap_chain_net_by_name(l_net_str); if (!l_net) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Network %s not found", l_net_str); - return -3; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_NET_NOT_FOUND_ERR, "Command 'order create' requires parameter -net"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_NET_NOT_FOUND_ERR; } dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-token_sell", &l_token_sell_str); if (!l_token_sell_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'order create' requires parameter -token_sell"); - return -5; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_PARAM_TOKEN_SELL_ERR, + "Command 'order create' requires parameter -token_sell"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_PARAM_TOKEN_SELL_ERR; } dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-token_buy", &l_token_buy_str); if (!l_token_buy_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'order create' requires parameter -token_buy"); - return -5; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_PARAM_TOKEN_BUY_ERR, + "Command 'order create' requires parameter -token_buy"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_PARAM_TOKEN_BUY_ERR; } if (!dap_ledger_token_ticker_check(l_net->pub.ledger, l_token_buy_str)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Token ticker %s not found", l_token_buy_str); - return -6; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_PARAM_TICKR_NOTF_ERR, + "Token ticker %s not found", l_token_buy_str); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_PARAM_TICKR_NOTF_ERR; } if (!strcmp(l_token_sell_str, l_token_buy_str)){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "token_buy and token_sell must be different!"); - return -7; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_TOKEN_EQUAL_ERR, + "token_buy and token_sell must be different!"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_TOKEN_EQUAL_ERR; } const char *l_val_sell_str = NULL, *l_val_rate_str = NULL; dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-value", &l_val_sell_str); if (!l_val_sell_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'order create' requires parameter -value"); - return -8; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_CRTE_REQ_PARAM_VALUE_ERR, + "Command 'order create' requires parameter -value"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_CRTE_REQ_PARAM_VALUE_ERR; } uint256_t l_datoshi_sell = dap_chain_balance_scan(l_val_sell_str); dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-rate", &l_val_rate_str); if (!l_val_rate_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'order create' requires parameter -rate"); - return -8; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_CRTE_REQ_PARAM_RATE_ERR, + "Command 'order create' requires parameter -rate"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_CRTE_REQ_PARAM_RATE_ERR; } uint256_t l_rate = dap_chain_coins_to_balance(l_val_rate_str); const char *l_fee_str = NULL; dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-fee", &l_fee_str); if (!l_fee_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'order create' requires parameter -fee"); - return -20; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_CRTE_REQ_PARAM_FEE_ERR, + "Command 'order create' requires parameter -fee"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_CRTE_REQ_PARAM_FEE_ERR; } uint256_t l_fee = dap_chain_balance_scan(l_fee_str); dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-w", &l_wallet_str); if (!l_wallet_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'order create' requires parameter -w"); - return -10; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_CRTE_REQ_PARAM_W_ERR, + "Command 'order create' requires parameter -w"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_CRTE_REQ_PARAM_W_ERR; } 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_cli_server_cmd_set_reply_text(a_str_reply, "Specified wallet not found"); - return -11; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_CRTE_WALLET_NOT_FOUND_ERR, + "Specified wallet not found"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_CRTE_WALLET_NOT_FOUND_ERR; } const char* l_sign_str = dap_chain_wallet_check_sign(l_wallet); char *l_hash_ret = NULL; @@ -1354,72 +1367,91 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, v dap_chain_wallet_close(l_wallet); switch (ret_code) { case XCHANGE_CREATE_ERROR_OK: { - dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nSuccessfully created order %s", l_sign_str, l_hash_ret); + json_object* json_obj_order = json_object_new_object(); + json_object_object_add(json_obj_order, "status", json_object_new_string("Successfully created")); + json_object_object_add(json_obj_order, "sign", json_object_new_string(l_sign_str)); + json_object_object_add(json_obj_order, "hash", json_object_new_string(l_hash_ret)); + json_object_array_add(*a_json_arr_reply, json_obj_order); DAP_DELETE(l_hash_ret); - return 0; + return DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_OK; } case XCHANGE_CREATE_ERROR_INVALID_ARGUMENT: { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Some parameters could not be set during a function call"); - return -24; + dap_json_rpc_error_add(*a_json_arr_reply, XCHANGE_CREATE_ERROR_INVALID_ARGUMENT, + "Some parameters could not be set during a function call"); + return -XCHANGE_CREATE_ERROR_INVALID_ARGUMENT; } case XCHANGE_CREATE_ERROR_TOKEN_TICKER_SELL_IS_NOT_FOUND_LEDGER: { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Token ticker %s not found", l_token_sell_str); - return -6; + dap_json_rpc_error_add(*a_json_arr_reply, XCHANGE_CREATE_ERROR_TOKEN_TICKER_SELL_IS_NOT_FOUND_LEDGER, + "Token ticker %s not found", l_token_sell_str); + return -XCHANGE_CREATE_ERROR_TOKEN_TICKER_SELL_IS_NOT_FOUND_LEDGER; } case XCHANGE_CREATE_ERROR_TOKEN_TICKER_BUY_IS_NOT_FOUND_LEDGER: { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Token ticker %s not found", l_token_buy_str); - return -6; + dap_json_rpc_error_add(*a_json_arr_reply, XCHANGE_CREATE_ERROR_TOKEN_TICKER_BUY_IS_NOT_FOUND_LEDGER, + "Token ticker %s not found", l_token_buy_str); + return -XCHANGE_CREATE_ERROR_TOKEN_TICKER_BUY_IS_NOT_FOUND_LEDGER; } case XCHANGE_CREATE_ERROR_RATE_IS_ZERO: { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Format -rate n.n = buy / sell (eg: 1.0, 1.135)"); - return -9; + dap_json_rpc_error_add(*a_json_arr_reply, XCHANGE_CREATE_ERROR_RATE_IS_ZERO, + "Format -rate n.n = buy / sell (eg: 1.0, 1.135)"); + return -XCHANGE_CREATE_ERROR_RATE_IS_ZERO; } case XCHANGE_CREATE_ERROR_FEE_IS_ZERO: { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Format -value <unsigned integer 256>"); - return -21; + dap_json_rpc_error_add(*a_json_arr_reply, XCHANGE_CREATE_ERROR_FEE_IS_ZERO, + "Format -value <unsigned integer 256>"); + return -XCHANGE_CREATE_ERROR_FEE_IS_ZERO; } case XCHANGE_CREATE_ERROR_VALUE_SELL_IS_ZERO: { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Format -value <unsigned integer 256>"); - return -9; + dap_json_rpc_error_add(*a_json_arr_reply, XCHANGE_CREATE_ERROR_VALUE_SELL_IS_ZERO, + "Format -value <unsigned integer 256>"); + return -XCHANGE_CREATE_ERROR_VALUE_SELL_IS_ZERO; } case XCHANGE_CREATE_ERROR_INTEGER_OVERFLOW_WITH_SUM_OF_VALUE_AND_FEE: { log_it(L_ERROR, "Integer overflow with sum of value and fee"); - dap_cli_server_cmd_set_reply_text(a_str_reply, "Integer overflow with sum of value and fee"); - return -22; + dap_json_rpc_error_add(*a_json_arr_reply, XCHANGE_CREATE_ERROR_INTEGER_OVERFLOW_WITH_SUM_OF_VALUE_AND_FEE, + "Integer overflow with sum of value and fee"); + return -XCHANGE_CREATE_ERROR_INTEGER_OVERFLOW_WITH_SUM_OF_VALUE_AND_FEE; } case XCHANGE_CREATE_ERROR_NOT_ENOUGH_CASH_FOR_FEE_IN_SPECIFIED_WALLET: { - dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nNot enough cash for fee in specified wallet", l_sign_str); - return -23; + dap_json_rpc_error_add(*a_json_arr_reply, XCHANGE_CREATE_ERROR_NOT_ENOUGH_CASH_FOR_FEE_IN_SPECIFIED_WALLET, + "%s\nNot enough cash for fee in specified wallet", l_sign_str); + return -XCHANGE_CREATE_ERROR_NOT_ENOUGH_CASH_FOR_FEE_IN_SPECIFIED_WALLET; } case XCHANGE_CREATE_ERROR_NOT_ENOUGH_CASH_IN_SPECIFIED_WALLET: { - dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nNot enough cash in specified wallet", l_sign_str); - return -12; + dap_json_rpc_error_add(*a_json_arr_reply, XCHANGE_CREATE_ERROR_NOT_ENOUGH_CASH_IN_SPECIFIED_WALLET, + "%s\nNot enough cash in specified wallet", l_sign_str); + return -XCHANGE_CREATE_ERROR_NOT_ENOUGH_CASH_IN_SPECIFIED_WALLET; } case XCHANGE_CREATE_ERROR_MEMORY_ALLOCATED: { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Out of memory"); - return -1; + dap_json_rpc_error_add(*a_json_arr_reply, XCHANGE_CREATE_ERROR_MEMORY_ALLOCATED, + "Out of memory"); + return -XCHANGE_CREATE_ERROR_MEMORY_ALLOCATED; } case XCHANGE_CREATE_ERROR_CAN_NOT_COMPOSE_THE_CONDITIONAL_TRANSACTION: { - dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't compose the conditional transaction", l_sign_str); - return -14; + dap_json_rpc_error_add(*a_json_arr_reply, XCHANGE_CREATE_ERROR_CAN_NOT_COMPOSE_THE_CONDITIONAL_TRANSACTION, + "%s\nCan't compose the conditional transaction", l_sign_str); + return -XCHANGE_CREATE_ERROR_CAN_NOT_COMPOSE_THE_CONDITIONAL_TRANSACTION; } case XCHANGE_CREATE_ERROR_CAN_NOT_PUT_TRANSACTION_TO_MEMPOOL: { - dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't compose the conditional transaction", l_sign_str); - return -15; + dap_json_rpc_error_add(*a_json_arr_reply, XCHANGE_CREATE_ERROR_CAN_NOT_PUT_TRANSACTION_TO_MEMPOOL, + "%s\nCan't compose the conditional transaction", l_sign_str); + return -XCHANGE_CREATE_ERROR_CAN_NOT_PUT_TRANSACTION_TO_MEMPOOL; } } } break; case CMD_HISTORY:{ + json_object* l_json_obj_order = NULL; dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str); if (!l_net_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'order history' requires parameter -net"); - return -2; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_REQ_PARAM_NET_ERR, + "Command 'order history' requires parameter -net"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_REQ_PARAM_NET_ERR; } l_net = dap_chain_net_by_name(l_net_str); if (!l_net) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Network %s not found", l_net_str); - return -3; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_NET_NOT_FOUND_ERR, + "Network %s not found", l_net_str); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_NET_NOT_FOUND_ERR; } const char * l_order_hash_str = NULL; @@ -1429,43 +1461,43 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, v dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-addr", &l_addr_hash_str); if (!l_order_hash_str && ! l_addr_hash_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'order history' requires parameter -order or -addr" ); - return -12; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_REQ_PARAM_ORDER_ADDR_ERR, + "Command 'order history' requires parameter -order or -addr" ); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_REQ_PARAM_ORDER_ADDR_ERR; } if(l_addr_hash_str){ dap_chain_addr_t *l_addr = dap_chain_addr_from_str(l_addr_hash_str); if (!l_addr) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Cannot convert " + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_CAN_NOT_CONVERT_ERR, "Cannot convert " "string '%s' to binary address.", l_addr_hash_str); - return -14; + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_CAN_NOT_CONVERT_ERR; } if (dap_chain_addr_check_sum(l_addr) != 0 ) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Incorrect address wallet"); - return -15; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_INCORRECT_ADDR_ERR, "Incorrect address wallet"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_INCORRECT_ADDR_ERR; } if (l_addr->net_id.uint64 != l_net->pub.id.uint64) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Address %s does not belong to the %s network.", + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_DOES_NOT_BELONG_ERR, "Address %s does not belong to the %s network.", l_addr_hash_str, l_net->pub.name); - return -16; + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_DOES_NOT_BELONG_ERR; } dap_hash_fast_t l_hash_curr ={}; bool l_from_wallet_cache = dap_chain_wallet_cache_tx_find(l_addr, NULL, NULL, &l_hash_curr, NULL) == 0 ? true : false; l_hash_curr = (dap_hash_fast_t){0}; size_t l_total = 0; - if(l_from_wallet_cache){ - dap_string_t * l_str_reply = dap_string_new(""); - + if(l_from_wallet_cache) { xchange_orders_cache_net_t* l_cache = NULL; if(s_xchange_cache_state == XCHANGE_CACHE_ENABLED){ l_cache = s_get_xchange_cache_by_net_id(l_net->pub.id); if(!l_cache){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "No history"); + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_DOES_NO_HISTORY_ERR, "No history"); break; } } + l_json_obj_order = json_object_new_object(); dap_chain_wallet_cache_iter_t *l_iter = dap_chain_wallet_cache_iter_create(*l_addr); for(dap_chain_datum_tx_t *l_datum_tx = dap_chain_wallet_cache_iter_get(l_iter, DAP_CHAIN_WALLET_CACHE_GET_FIRST); l_datum_tx; l_datum_tx = dap_chain_wallet_cache_iter_get(l_iter, DAP_CHAIN_WALLET_CACHE_GET_NEXT)) @@ -1479,45 +1511,50 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, v HASH_FIND(hh, l_cache->cache, l_iter->cur_hash, sizeof(dap_hash_fast_t), l_item); if (!l_item) continue; - - if (s_string_append_tx_cond_info(l_str_reply, l_net, &l_item->seller_addr, + + if (s_string_append_tx_cond_info_json(l_json_obj_order, l_net, &l_item->seller_addr, l_item->tx_type == TX_TYPE_EXCHANGE ? &l_item->tx_info.exchange_info.buyer_addr : NULL, l_datum_tx, l_iter->cur_hash, TX_STATUS_ALL, true, true, false)) l_total++; } else { - if (s_string_append_tx_cond_info(l_str_reply, l_net, NULL, NULL, l_datum_tx, l_iter->cur_hash, TX_STATUS_ALL, true, true, false)) + if (s_string_append_tx_cond_info_json(l_json_obj_order, l_net, NULL, NULL, l_datum_tx, l_iter->cur_hash, TX_STATUS_ALL, true, true, false)) l_total++; } } dap_chain_wallet_cache_iter_delete(l_iter); if(!l_total) - dap_cli_server_cmd_set_reply_text(a_str_reply, "No history"); + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_DOES_NO_HISTORY_ERR, "No history"); else { - dap_string_append_printf(l_str_reply, "Found %"DAP_UINT64_FORMAT_U, l_total); - *a_str_reply = dap_string_free(l_str_reply, false); + char *l_orders = dap_strdup_printf("Found %"DAP_UINT64_FORMAT_U, l_total); + json_object_object_add(l_json_obj_order, "number of orders", json_object_new_string(l_orders)); + DAP_DELETE(l_orders); } + json_object_array_add(*a_json_arr_reply, l_json_obj_order); } else { dap_list_t *l_tx_list = dap_chain_net_get_tx_cond_all_for_addr(l_net,l_addr, c_dap_chain_net_srv_xchange_uid ); - dap_string_t * l_str_reply = dap_string_new(""); if (l_tx_list){ dap_list_t *l_tx_list_temp = l_tx_list; - dap_string_append_printf(l_str_reply, "Wallet %s history:\n\n", l_addr_hash_str); + l_json_obj_order = json_object_new_object(); + json_object_object_add(l_json_obj_order, "wallet", json_object_new_string(l_addr_hash_str)); while(l_tx_list_temp ){ dap_chain_datum_tx_t * l_tx_cur = (dap_chain_datum_tx_t*) l_tx_list_temp->data; dap_hash_fast_t l_hash = {}; dap_hash_fast(l_tx_cur, dap_chain_datum_tx_get_size(l_tx_cur), &l_hash); - if (s_string_append_tx_cond_info(l_str_reply, l_net, NULL, NULL, l_tx_cur, &l_hash, TX_STATUS_ALL, true, true, false)) + if ( s_string_append_tx_cond_info_json(l_json_obj_order, l_net, NULL, NULL, l_tx_cur, &l_hash, TX_STATUS_ALL, true, true, false) ) l_total++; l_tx_list_temp = l_tx_list_temp->next; } dap_list_free(l_tx_list); - dap_string_append_printf(l_str_reply, "Found %"DAP_UINT64_FORMAT_U, l_total); - *a_str_reply = dap_string_free(l_str_reply, false); + + char *l_orders = dap_strdup_printf("Found %"DAP_UINT64_FORMAT_U, l_total); + json_object_object_add(l_json_obj_order, "number of orders", json_object_new_string(l_orders)); + json_object_array_add(*a_json_arr_reply, l_json_obj_order); + DAP_DELETE(l_orders); }else{ - dap_cli_server_cmd_set_reply_text(a_str_reply, "No history"); + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_DOES_NO_HISTORY_ERR, "No history"); } } DAP_DELETE(l_addr); @@ -1527,51 +1564,51 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, v if(l_order_hash_str){ dap_hash_fast_t l_order_tx_hash = {}; dap_chain_hash_fast_from_str(l_order_hash_str, &l_order_tx_hash); + l_json_obj_order = json_object_new_object(); if(s_xchange_cache_state == XCHANGE_CACHE_DISABLED){ dap_chain_datum_tx_t* l_tx = dap_chain_net_get_tx_by_hash(l_net, &l_order_tx_hash, TX_SEARCH_TYPE_NET); if( l_tx){ xchange_tx_type_t l_tx_type = dap_chain_net_srv_xchange_tx_get_type(l_net->pub.ledger, l_tx, NULL, NULL, NULL); char *l_tx_hash = dap_chain_hash_fast_to_str_new(&l_order_tx_hash); if(l_tx_type != TX_TYPE_ORDER){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "Datum with hash %s is not order. Check hash.", l_tx_hash); + json_object_object_add(l_json_obj_order, "datum status", json_object_new_string("is not order")); + json_object_object_add(l_json_obj_order, "datum hash", json_object_new_string(l_tx_hash)); } else { dap_chain_net_srv_xchange_order_status_t l_rc = s_tx_check_for_open_close(l_net,l_tx); if(l_rc == XCHANGE_ORDER_STATUS_UNKNOWN){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "WRONG TX %s", l_tx_hash); + json_object_object_add(l_json_obj_order, "WRONG TX", json_object_new_string(l_tx_hash)); }else{ - dap_string_t * l_str_reply = dap_string_new(""); - dap_string_append_printf(l_str_reply, "Order %s history:\n\n", l_order_hash_str); + json_object_object_add(l_json_obj_order, "history for order", json_object_new_string(l_order_hash_str)); dap_list_t *l_tx_list = dap_chain_net_get_tx_cond_chain(l_net, &l_order_tx_hash, c_dap_chain_net_srv_xchange_uid ); dap_list_t *l_tx_list_temp = l_tx_list; while(l_tx_list_temp ){ dap_chain_datum_tx_t * l_tx_cur = (dap_chain_datum_tx_t*) l_tx_list_temp->data; dap_hash_fast_t l_hash = {}; dap_hash_fast(l_tx_cur, dap_chain_datum_tx_get_size(l_tx_cur), &l_hash); - s_string_append_tx_cond_info(l_str_reply, l_net, NULL, NULL, l_tx_cur, &l_hash, TX_STATUS_ALL, true, true, false); + s_string_append_tx_cond_info_json(l_json_obj_order, l_net, NULL, NULL, l_tx_cur, &l_hash, TX_STATUS_ALL, true, true, false); l_tx_list_temp = l_tx_list_temp->next; } dap_list_free(l_tx_list); - *a_str_reply = dap_string_free(l_str_reply, false); } } DAP_DELETE(l_tx_hash); }else{ - dap_cli_server_cmd_set_reply_text(a_str_reply, "No history"); + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_DOES_NO_HISTORY_ERR, "No history"); } } else { - dap_string_t * l_str_reply = dap_string_new(""); xchange_orders_cache_net_t* l_cache = NULL; dap_list_t *l_tx_cache_list = NULL; l_cache = s_get_xchange_cache_by_net_id(l_net->pub.id); xchange_tx_cache_t* l_item = NULL; dap_hash_fast_t l_cur_hash = l_order_tx_hash; + l_json_obj_order = json_object_new_object(); HASH_FIND(hh, l_cache->cache, &l_cur_hash, sizeof(dap_hash_fast_t), l_item); if (!l_item){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "No history"); - return -18; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_DOES_NO_HISTORY_ERR, "No history"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_DOES_NO_HISTORY_ERR; } while(l_item){ - s_string_append_tx_cond_info(l_str_reply, l_net, &l_item->seller_addr, + s_string_append_tx_cond_info_json(l_json_obj_order, l_net, &l_item->seller_addr, l_item->tx_type == TX_TYPE_EXCHANGE ? &l_item->tx_info.exchange_info.buyer_addr : NULL, l_item->tx, &l_item->hash, TX_STATUS_ALL, true, true, false); switch(l_item->tx_type){ @@ -1590,49 +1627,55 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, v break; HASH_FIND(hh, l_cache->cache, &l_cur_hash, sizeof(dap_hash_fast_t), l_item); } - *a_str_reply = dap_string_free(l_str_reply, false); } } + json_object_array_add(*a_json_arr_reply, l_json_obj_order); } break; case CMD_REMOVE: { const char * l_order_hash_str = NULL; const char * l_fee_str = NULL; + json_object* json_obj_order = NULL; dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str); if (!l_net_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'order %s' requires parameter -net", + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_RMOVE_REQ_PARAM_NET_ERR, "Command 'order %s' requires parameter -net", l_cmd_num == CMD_REMOVE ? "remove" : "update"); - return -2; + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_RMOVE_REQ_PARAM_NET_ERR; } dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_str); if (!l_net) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Network %s not found", l_net_str); - return -3; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_RMOVE_NET_NOT_FOUND_ERR, + "Network %s not found", l_net_str); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_RMOVE_NET_NOT_FOUND_ERR; } dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-w", &l_wallet_str); if (!l_wallet_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'order %s' requires parameter -w", + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_RMOVE_REQ_PARAM_W_ERR, + "Command 'order %s' requires parameter -w", l_cmd_num == CMD_REMOVE ? "remove" : "update"); - return -10; + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_RMOVE_REQ_PARAM_W_ERR; } 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_cli_server_cmd_set_reply_text(a_str_reply, "Specified wallet not found"); - return -11; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_RMOVE_WALLET_NOT_FOUND_ERR, + "Specified wallet not found"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_RMOVE_WALLET_NOT_FOUND_ERR; } const char* l_sign_str = dap_chain_wallet_check_sign(l_wallet); dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-order", &l_order_hash_str); if (!l_order_hash_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'order %s' requires parameter -order", + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_RMOVE_REQ_PARAM_ORDER_ADDR_ERR, + "Command 'order %s' requires parameter -order", l_cmd_num == CMD_REMOVE ? "remove" : "update"); - return -12; + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_RMOVE_REQ_PARAM_ORDER_ADDR_ERR; } dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-fee", &l_fee_str); if (!l_fee_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'order %s' requires parameter -fee", + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_RMOVE_REQ_PARAM_FEE_ERR, + "Command 'order %s' requires parameter -fee", l_cmd_num == CMD_REMOVE ? "remove" : "update"); - return -12; + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_RMOVE_REQ_PARAM_FEE_ERR; } uint256_t l_fee = dap_chain_balance_scan(l_fee_str); dap_hash_fast_t l_tx_hash = {}; @@ -1640,29 +1683,33 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, v char *l_tx_hash_ret = NULL; int l_ret_code = dap_chain_net_srv_xchange_remove(l_net, &l_tx_hash, l_fee, l_wallet, &l_tx_hash_ret); dap_chain_wallet_close(l_wallet); + switch (l_ret_code) { case XCHANGE_REMOVE_ERROR_OK: - dap_cli_server_cmd_set_reply_text(a_str_reply, "Order successfully removed. Created inactivate tx with hash %s", l_tx_hash_ret); + json_obj_order = json_object_new_object(); + json_object_object_add(json_obj_order, "status", json_object_new_string("Order successfully removed")); + json_object_object_add(json_obj_order, "Created inactivate tx with hash", json_object_new_string(l_tx_hash_ret)); + json_object_array_add(*a_json_arr_reply, json_obj_order); DAP_DELETE(l_tx_hash_ret); break; case XCHANGE_REMOVE_ERROR_CAN_NOT_FIND_TX: - dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nSpecified order not found", l_sign_str); + dap_json_rpc_error_add(*a_json_arr_reply, XCHANGE_REMOVE_ERROR_CAN_NOT_FIND_TX, "%s\nSpecified order not found", l_sign_str); break; case XCHANGE_REMOVE_ERROR_CAN_NOT_CREATE_PRICE: - dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't create price object from order", l_sign_str); + dap_json_rpc_error_add(*a_json_arr_reply, XCHANGE_REMOVE_ERROR_CAN_NOT_CREATE_PRICE, "%s\nCan't create price object from order", l_sign_str); break; case XCHANGE_REMOVE_ERROR_FEE_IS_ZERO: - dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't get fee value."); + dap_json_rpc_error_add(*a_json_arr_reply, XCHANGE_REMOVE_ERROR_FEE_IS_ZERO, "Can't get fee value."); break; case XCHANGE_REMOVE_ERROR_CAN_NOT_INVALIDATE_TX: { dap_chain_datum_tx_t *l_cond_tx = dap_ledger_tx_find_by_hash(l_net->pub.ledger, &l_tx_hash); dap_chain_net_srv_xchange_price_t *l_price = s_xchange_price_from_order(l_net, l_cond_tx, &l_tx_hash, &l_fee, false); const char *l_final_tx_hash_str = dap_chain_hash_fast_to_str_static(&l_price->tx_hash); - dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't create invalidate transaction from: %s\n", l_final_tx_hash_str); + dap_json_rpc_error_add(*a_json_arr_reply, XCHANGE_REMOVE_ERROR_CAN_NOT_INVALIDATE_TX, "Can't create invalidate transaction from: %s\n", l_final_tx_hash_str); DAP_DELETE(l_price); } break; default: - dap_cli_server_cmd_set_reply_text(a_str_reply, "An error occurred with an unknown code: %d.", l_ret_code); + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_RMOVE_UNKNOWN_ERR, "An error occurred with an unknown code: %d.", l_ret_code); break; } return l_ret_code; @@ -1671,30 +1718,28 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, v case CMD_STATUS: { dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str); if (!l_net_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'order status' requires parameter -net"); - return -2; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_REQ_PARAM_NET_ERR, + "Command 'order status' requires parameter -net"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_REQ_PARAM_NET_ERR; } l_net = dap_chain_net_by_name(l_net_str); if (!l_net) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Network %s not found", l_net_str); - return -3; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_NET_NOT_FOUND_ERR, + "Network %s not found", l_net_str); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_NET_NOT_FOUND_ERR; } const char * l_order_hash_str = NULL; dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-order", &l_order_hash_str); if (!l_order_hash_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'order history' requires parameter -order or -addr" ); - return -12; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_REQ_PARAM_ORDER_ADDR_ERR, + "Command 'order status' requires parameter -order or -addr" ); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_REQ_PARAM_ORDER_ADDR_ERR; } dap_hash_fast_t l_order_tx_hash = {}; dap_chain_hash_fast_from_str(l_order_hash_str, &l_order_tx_hash); - char *l_cp_rate; - char* l_status_order = NULL; - const char *l_token_buy = NULL; - const char *l_token_sell = NULL; - const char *l_owner_addr = NULL; - const char *l_amount_coins_str = NULL, *l_amount_datoshi_str = NULL, - *l_proposed_coins_str = NULL, *l_proposed_datoshi_str = NULL; + char *l_status_order = NULL, *l_token_buy = NULL, *l_token_sell = NULL, *l_owner_addr = NULL; + const char *l_cp_rate, *l_amount_coins_str = NULL, *l_amount_datoshi_str = NULL, *l_proposed_coins_str = NULL, *l_proposed_datoshi_str = NULL; uint64_t l_percent_completed = 0; dap_chain_datum_tx_t *l_tx = NULL; uint256_t l_amount, l_rate, l_proposed; @@ -1707,13 +1752,15 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, v HASH_FIND(hh, l_cache->cache, &l_order_tx_hash, sizeof(dap_hash_fast_t), l_item); l_tx = l_item ? l_item->tx : NULL; if (!l_tx){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't find order %s", l_order_hash_str); - return -18; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_CANT_FIND_ORDER_ERR, + "Can't find order %s", l_order_hash_str); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_CANT_FIND_ORDER_ERR; } if (l_item->tx_type != TX_TYPE_ORDER){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "It's not an order"); - return -18; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_ITS_NOT_ORDER_ERR, + "Item is not an order"); + return DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_ITS_NOT_ORDER_ERR; } switch (l_item->tx_info.order_info.order_status) @@ -1742,14 +1789,13 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, v MULT_256_COIN(l_completed, dap_chain_coins_to_balance("100.0"), &l_completed); l_percent_completed = dap_chain_balance_to_coins_uint64(l_completed); - - l_amount_datoshi_str = dap_uint256_to_char(l_item->tx_info.order_info.value_ammount, &l_amount_coins_str); - l_owner_addr = dap_chain_addr_to_str_static(&l_item->seller_addr); + l_owner_addr = dap_strdup(dap_chain_addr_to_str(&l_item->seller_addr)); } else { l_tx = dap_ledger_tx_find_by_hash(l_net->pub.ledger, &l_order_tx_hash); if (!l_tx){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't find order %s", l_order_hash_str); - return -18; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_CANT_FIND_ORDER_ERR, + "Can't find order %s", l_order_hash_str); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_CANT_FIND_ORDER_ERR; } // Find SRV_XCHANGE in_cond item @@ -1761,36 +1807,34 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, v dap_chain_tx_out_cond_t *l_out_prev_cond_item = l_prev_tx ? dap_chain_datum_tx_out_cond_get(l_prev_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_prev_cond_idx) : NULL; if(l_out_prev_cond_item){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "It's not an order"); - return -18; - } - - 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){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "It's not an order"); - return -18; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_ITS_NOT_ORDER_ERR, + "Item is not an order"); + return DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_ITS_NOT_ORDER_ERR; } // TODO add filters to list (tokens, network, etc.) dap_chain_net_srv_xchange_price_t *l_price = s_xchange_price_from_order(l_net, l_tx, &l_order_tx_hash, NULL, true); if( !l_price ){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't get price from order"); - return -18; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_CANT_GET_PRICE_ERR, + "Can't get price from order"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_CANT_GET_PRICE_ERR; } dap_ledger_t * l_ledger = dap_ledger_by_net_name(l_net->pub.name); dap_hash_fast_t l_last_tx_hash = dap_ledger_get_final_chain_tx_hash(l_ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_price->tx_hash, false); if( dap_hash_fast_is_blank(&l_last_tx_hash) ){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't get last tx cond hash from order"); - return -18; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_CANT_GET_LAST_TX_ERR, + "Can't get last tx cond hash from order"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_CANT_GET_LAST_TX_ERR; } dap_chain_datum_tx_t * l_last_tx = dap_ledger_tx_find_by_hash(l_ledger, &l_last_tx_hash); log_it(L_INFO, "Last tx hash %s", dap_hash_fast_to_str_static(&l_last_tx_hash)); if (!l_last_tx){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't find last tx"); - return -18; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_CANT_FIND_LAST_TX_ERR, + "Can't find last tx"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_CANT_FIND_LAST_TX_ERR; } 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); @@ -1817,45 +1861,43 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, v break; }; - l_owner_addr = dap_chain_addr_to_str_static(&l_price->creator_addr); - DAP_DEL_Z(l_price); + l_owner_addr = dap_strdup(dap_chain_addr_to_str(&l_price->creator_addr)); + DAP_DELETE(l_price); } char l_tmp_buf[DAP_TIME_STR_SIZE]; dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, l_tx->header.ts_created); - l_amount_datoshi_str = dap_uint256_uninteger_to_char(l_amount); - l_amount_coins_str = dap_uint256_decimal_to_char(l_amount); - l_proposed_coins_str = dap_uint256_decimal_to_char(l_proposed); - l_proposed_datoshi_str = dap_uint256_uninteger_to_char(l_proposed); - l_cp_rate = dap_chain_balance_to_coins(l_rate); - dap_cli_server_cmd_set_reply_text(a_str_reply, "orderHash: %s\n ts_created: %s\n Status: %s, proposed: %s(%s) %s, amount: %s (%s) %s, filled: %lu%%, rate (%s/%s): %s, net: %s\n\n" - "owner addr: %s\n\n", l_order_hash_str, - l_tmp_buf, l_status_order, - l_proposed_coins_str ? l_proposed_coins_str : "0.0", - l_proposed_datoshi_str ? l_proposed_datoshi_str : "0.0", - l_token_sell, - l_amount_coins_str ? l_amount_coins_str : "0.0", - l_amount_datoshi_str ? l_amount_datoshi_str : "0", - l_token_sell, l_percent_completed, - l_token_buy, l_token_sell, - l_cp_rate, - l_net->pub.name, l_owner_addr ? l_owner_addr : "unknown" ); - - if (s_xchange_cache_state != XCHANGE_CACHE_ENABLED){ - DAP_DEL_Z(l_token_sell); - DAP_DEL_Z(l_token_buy); - } - DAP_DEL_Z(l_cp_rate); - DAP_DEL_Z(l_amount_coins_str); - DAP_DEL_Z(l_amount_datoshi_str); - DAP_DEL_Z(l_proposed_coins_str); - DAP_DEL_Z(l_proposed_datoshi_str); + json_object* json_obj_order = json_object_new_object(); + json_object_object_add(json_obj_order, "order_hash", json_object_new_string(l_order_hash_str)); + json_object_object_add(json_obj_order, "ts_created", json_object_new_string(l_tmp_buf)); + json_object_object_add(json_obj_order, "status", json_object_new_string(l_status_order)); + + l_proposed_datoshi_str = dap_uint256_to_char(l_proposed, &l_proposed_coins_str); + json_object_object_add(json_obj_order, "proposed_coins", json_object_new_string(*l_proposed_coins_str ? l_proposed_coins_str : "0.0")); + json_object_object_add(json_obj_order, "proposed_datoshi", json_object_new_string(*l_proposed_datoshi_str ? l_proposed_datoshi_str : "0")); + + l_amount_datoshi_str = dap_uint256_to_char(l_amount, &l_amount_coins_str); + json_object_object_add(json_obj_order, "amount_coins", json_object_new_string(*l_amount_coins_str ? l_amount_coins_str : "0.0")); + json_object_object_add(json_obj_order, "amount_datoshi", json_object_new_string(*l_amount_datoshi_str ? l_amount_datoshi_str : "0")); + json_object_object_add(json_obj_order, "filled_percent", json_object_new_uint64(l_percent_completed)); + json_object_object_add(json_obj_order, "token_buy", json_object_new_string(l_token_buy)); + json_object_object_add(json_obj_order, "token_sell", json_object_new_string(l_token_sell)); + + dap_uint256_to_char(l_rate, &l_cp_rate); + json_object_object_add(json_obj_order, "rate", json_object_new_string(l_cp_rate)); + + json_object_object_add(json_obj_order, "net", json_object_new_string(l_net->pub.name)); + json_object_array_add(*a_json_arr_reply, json_obj_order); + DAP_DELETE(l_owner_addr); + if ( s_xchange_cache_state != XCHANGE_CACHE_ENABLED ) + DAP_DEL_MULTY(l_token_buy, l_token_sell); } break; default: { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Subcommand %s not recognized", a_argv[a_arg_index]); - return -4; + dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_SUB_NOT_FOUND_ERR, + "Subcommand %s not recognized", a_argv[a_arg_index]); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_SUB_NOT_FOUND_ERR; } } return 0; @@ -1998,6 +2040,7 @@ static dap_chain_net_srv_xchange_order_status_t s_tx_check_for_open_close(dap_ch * @param a_net * @param a_tx */ +#if 0 static bool s_string_append_tx_cond_info( dap_string_t * a_reply_str, dap_chain_net_t * a_net, dap_chain_addr_t *a_owner_addr, dap_chain_addr_t *a_buyer_addr, dap_chain_datum_tx_t * a_tx, dap_hash_fast_t *a_tx_hash, @@ -2195,17 +2238,194 @@ static bool s_string_append_tx_cond_info( dap_string_t * a_reply_str, dap_chain_ dap_string_append_printf(a_reply_str, "\n\n"); return true; } +#endif + +/** + * @brief Append tx info to the reply string + * @param a_json_out + * @param a_net + * @param a_tx + */ + +static bool s_string_append_tx_cond_info_json(json_object * a_json_out, dap_chain_net_t *a_net, dap_chain_addr_t *a_owner_addr, dap_chain_addr_t *a_buyer_addr, + dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, tx_opt_status_t a_filter_by_status, + bool a_print_prev_hash, bool a_print_status, bool a_print_ts) +{ + size_t l_tx_size = dap_chain_datum_tx_get_size(a_tx); + const char *l_tx_hash_str = dap_chain_hash_fast_to_str_static(a_tx_hash); + + // Get input token ticker + const char *l_tx_input_ticker = dap_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, a_tx_hash); + if (!l_tx_input_ticker) + return log_it(L_WARNING, "Can't get ticker from TX %s", l_tx_hash_str), false; + + dap_chain_tx_out_cond_t *l_out_prev_cond_item = NULL, *l_out_cond_item = NULL; + int l_cond_idx = 0; + + xchange_tx_type_t l_tx_type = dap_chain_net_srv_xchange_tx_get_type(a_net->pub.ledger, a_tx, &l_out_cond_item, &l_cond_idx, &l_out_prev_cond_item); + + bool l_is_closed = dap_ledger_tx_hash_is_used_out_item(a_net->pub.ledger, a_tx_hash, l_cond_idx, NULL); + if ((a_filter_by_status == TX_STATUS_ACTIVE && l_is_closed) || (a_filter_by_status == TX_STATUS_INACTIVE && !l_is_closed) + || (a_filter_by_status == TX_STATUS_ACTIVE && l_tx_type == TX_TYPE_INVALIDATE)) + return false; + + if (l_out_prev_cond_item && l_out_prev_cond_item->header.subtype != DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE) + return false; + + switch(l_tx_type){ + case TX_TYPE_ORDER:{ + if (!l_out_cond_item) + log_it(L_ERROR, "Can't find conditional output in TX %s", l_tx_hash_str), false; + + json_object_object_add(a_json_out, "hash", json_object_new_string(l_tx_hash_str)); + if (a_print_ts){ + char l_tmp_buf[DAP_TIME_STR_SIZE]; + dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, a_tx->header.ts_created); + json_object_object_add(a_json_out, "ts_created", json_object_new_string(l_tmp_buf)); + } + if (a_print_status) + json_object_object_add(a_json_out, "status", json_object_new_string(l_is_closed ? "inactive" : "active")); + + const char *l_rate_str, *l_amount_str, *l_amount_datoshi_str = dap_uint256_to_char(l_out_cond_item->header.value, &l_amount_str); + json_object_object_add(a_json_out, "proposed_coins", json_object_new_string(l_amount_str)); + json_object_object_add(a_json_out, "proposed_datoshi", json_object_new_string(l_amount_datoshi_str)); + json_object_object_add(a_json_out, "ticker", json_object_new_string(l_tx_input_ticker)); + json_object_object_add(a_json_out, "buy_token", json_object_new_string(l_out_cond_item->subtype.srv_xchange.buy_token)); + dap_uint256_to_char(l_out_cond_item->subtype.srv_xchange.rate, &l_rate_str); + json_object_object_add(a_json_out, "rate", json_object_new_string(l_rate_str)); + json_object_object_add(a_json_out, "net", json_object_new_string(a_net->pub.name)); + dap_chain_addr_t l_owner_addr = a_owner_addr ? *a_owner_addr : + l_out_cond_item ? l_out_cond_item->subtype.srv_xchange.seller_addr : + l_out_prev_cond_item ? l_out_prev_cond_item->subtype.srv_xchange.seller_addr : (dap_chain_addr_t){ }; + json_object_object_add(a_json_out, "owner_addr", json_object_new_string(dap_chain_addr_to_str_static(&l_owner_addr))); + } break; + case TX_TYPE_EXCHANGE:{ + dap_chain_tx_in_cond_t *l_in_cond + = (dap_chain_tx_in_cond_t*)dap_chain_datum_tx_item_get(a_tx, NULL, NULL, TX_ITEM_TYPE_IN_COND , NULL); + char *l_tx_prev_cond_hash_str = dap_hash_fast_to_str_static(&l_in_cond->header.tx_prev_hash); + + if (!l_out_prev_cond_item) + return log_it(L_ERROR, "Can't find previous cond item for tx %s", l_tx_hash_str), false; + + uint256_t l_rate = l_out_cond_item + ? l_out_cond_item->subtype.srv_xchange.rate + : l_out_prev_cond_item->subtype.srv_xchange.rate, + l_value_from = {}, l_value_to = {}; + + if (l_out_cond_item) + SUBTRACT_256_256(l_out_prev_cond_item->header.value, l_out_cond_item->header.value, &l_value_from); + else + l_value_from = l_out_prev_cond_item->header.value; + MULT_256_COIN(l_value_from, l_rate, &l_value_to); + + char *l_buy_ticker = l_out_cond_item + ? l_out_cond_item->subtype.srv_xchange.buy_token + : l_out_prev_cond_item->subtype.srv_xchange.buy_token; + + json_object_object_add(a_json_out, "hash", json_object_new_string(l_tx_hash_str)); + if(a_print_ts){ + char l_tmp_buf[DAP_TIME_STR_SIZE]; + dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, a_tx->header.ts_created); + json_object_object_add(a_json_out, "ts_created", json_object_new_string(l_tmp_buf)); + } + if(a_print_status) + json_object_object_add(a_json_out, "status", json_object_new_string(l_is_closed ? "inactive" : "active")); + + const char *l_value_from_str, *l_value_from_datoshi_str = dap_uint256_to_char(l_value_from, &l_value_from_str); + json_object_object_add(a_json_out, "changed_coins", json_object_new_string(l_value_from_str)); + json_object_object_add(a_json_out, "changed_datoshi", json_object_new_string(l_value_from_datoshi_str)); + json_object_object_add(a_json_out, "ticker", json_object_new_string(l_tx_input_ticker)); + + const char *l_value_to_str, *l_value_to_datoshi_str = dap_uint256_to_char(l_value_to, &l_value_to_str); + json_object_object_add(a_json_out, "for_coins", json_object_new_string(l_value_to_str)); + json_object_object_add(a_json_out, "for_datoshi", json_object_new_string(l_value_to_datoshi_str)); + json_object_object_add(a_json_out, "ticker", json_object_new_string(l_buy_ticker)); + + const char *l_rate_str; dap_uint256_to_char(l_rate, &l_rate_str); + json_object_object_add(a_json_out, "rate", json_object_new_string(l_rate_str)); + + const char *l_amount_str = NULL, + *l_amount_datoshi_str = l_out_cond_item ? dap_uint256_to_char(l_out_cond_item->header.value, &l_amount_str) : "0"; + json_object_object_add(a_json_out, "remain_coins", json_object_new_string(l_amount_str ? l_amount_str : "0.0")); + json_object_object_add(a_json_out, "remain_datoshi", json_object_new_string(l_amount_datoshi_str)); + json_object_object_add(a_json_out, "ticker", json_object_new_string(l_tx_input_ticker)); + json_object_object_add(a_json_out, "net", json_object_new_string(a_net->pub.name)); + if (a_print_prev_hash) + json_object_object_add(a_json_out, "prev_tx", json_object_new_string(l_tx_prev_cond_hash_str)); + + dap_chain_addr_t l_owner_addr = a_owner_addr ? *a_owner_addr : + l_out_cond_item ? l_out_cond_item->subtype.srv_xchange.seller_addr : + l_out_prev_cond_item ? l_out_prev_cond_item->subtype.srv_xchange.seller_addr : (dap_chain_addr_t){ }; + json_object_object_add(a_json_out, "owner_addr", json_object_new_string(dap_chain_addr_to_str_static(&l_owner_addr))); + dap_chain_addr_t l_buyer_addr; + if (a_buyer_addr) + l_buyer_addr = *a_buyer_addr; + else { + dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t*)dap_chain_datum_tx_item_get(a_tx, NULL, NULL, TX_ITEM_TYPE_SIG, NULL)); + dap_enc_key_t *l_key_buyer = dap_sign_to_enc_key(l_sign); + dap_chain_addr_fill_from_key(&l_buyer_addr, l_key_buyer, a_net->pub.id); + dap_enc_key_delete(l_key_buyer); + } + json_object_object_add(a_json_out, "buyer_addr", json_object_new_string(dap_chain_addr_to_str_static(&l_buyer_addr))); + } break; + case TX_TYPE_INVALIDATE:{ + dap_chain_tx_in_cond_t * l_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(a_tx, NULL, NULL, TX_ITEM_TYPE_IN_COND , NULL); + char l_tx_prev_cond_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE]; + dap_hash_fast_to_str(&l_in_cond->header.tx_prev_hash,l_tx_prev_cond_hash_str, sizeof(l_tx_prev_cond_hash_str)); + + if (!l_out_prev_cond_item) + return log_it(L_ERROR, "Can't find previous cond item for tx %s", l_tx_hash_str), false; + + dap_chain_datum_tx_t *l_prev_tx = dap_ledger_tx_find_by_hash(a_net->pub.ledger, &l_in_cond->header.tx_prev_hash); + if (!l_prev_tx) + return false; + + int l_out_num = l_in_cond->header.tx_out_prev_idx; + dap_chain_tx_out_cond_t *l_out_cond = dap_chain_datum_tx_out_cond_get(l_prev_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_out_num); + if (!l_out_cond) + return log_it(L_ERROR, "Can't find OUT_COND in prev tx"), false; + + dap_hash_fast_t l_order_hash = dap_ledger_get_first_chain_tx_hash(a_net->pub.ledger, a_tx, l_out_cond->header.subtype); + if ( dap_hash_fast_is_blank(&l_order_hash) ) + l_order_hash = l_in_cond->header.tx_prev_hash; + + json_object_object_add(a_json_out, "hash", json_object_new_string(l_tx_hash_str)); + if(a_print_ts){ + char l_tmp_buf[DAP_TIME_STR_SIZE]; + dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, a_tx->header.ts_created); + json_object_object_add(a_json_out, "ts_created", json_object_new_string(l_tmp_buf)); + } + if (a_print_status) + json_object_object_add(a_json_out, "status", json_object_new_string("inactive")); + + const char *l_value_from_str, *l_value_from_datoshi_str = dap_uint256_to_char(l_out_prev_cond_item->header.value, &l_value_from_str); + json_object_object_add(a_json_out, "returned_coins", json_object_new_string(l_value_from_str)); + json_object_object_add(a_json_out, "returned_datoshi", json_object_new_string(l_value_from_datoshi_str)); + json_object_object_add(a_json_out, "ticker", json_object_new_string(l_tx_input_ticker)); + json_object_object_add(a_json_out, "order_hash", json_object_new_string( dap_hash_fast_to_str_static(&l_order_hash) )); + if(a_print_prev_hash) + json_object_object_add(a_json_out, "prev cond hash", json_object_new_string(l_tx_prev_cond_hash_str)); + dap_chain_addr_t l_owner_addr = a_owner_addr ? *a_owner_addr : + l_out_cond_item ? l_out_cond_item->subtype.srv_xchange.seller_addr : + l_out_prev_cond_item ? l_out_prev_cond_item->subtype.srv_xchange.seller_addr : (dap_chain_addr_t){ }; + json_object_object_add(a_json_out, "owner_addr", json_object_new_string(dap_chain_addr_to_str_static(&l_owner_addr))); + } break; + default: + return false; + } + return true; +} -static int s_cli_srv_xchange_tx_list_addr(dap_chain_net_t *a_net, dap_time_t a_after, dap_time_t a_before, - dap_chain_addr_t *a_addr, int a_opt_status, void **a_str_reply) +static int s_cli_srv_xchange_tx_list_addr_json(dap_chain_net_t *a_net, dap_time_t a_after, dap_time_t a_before, + dap_chain_addr_t *a_addr, int a_opt_status, json_object* json_obj_out) { - dap_string_t *l_reply_str; + dap_chain_hash_fast_t l_tx_first_hash = {0}; size_t l_tx_total; - if ( !(l_reply_str = dap_string_new("")) ) - return log_it(L_CRITICAL, "%s", c_error_memory_alloc), -ENOMEM; - + memset(&l_tx_first_hash, 0, sizeof(dap_chain_hash_fast_t)); /* Initial hash == zero */ + json_object* json_arr_datum_out = json_object_new_array(); + size_t l_tx_count = 0; dap_hash_fast_t l_hash_curr = {}; bool l_from_wallet_cache = dap_chain_wallet_cache_tx_find(a_addr, NULL, NULL, &l_hash_curr, NULL) == 0 ? true : false; @@ -2224,8 +2444,11 @@ static int s_cli_srv_xchange_tx_list_addr(dap_chain_net_t *a_net, dap_time_t a_a if ( a_before && (l_datum_tx->header.ts_created > a_before) ) continue; - if (s_string_append_tx_cond_info(l_reply_str, a_net, NULL, NULL, l_datum_tx, &l_hash_curr, a_opt_status, false, true, true)) + json_object* json_obj_tx = json_object_new_object(); + if (s_string_append_tx_cond_info_json(json_obj_tx, a_net, NULL, NULL, l_datum_tx, &l_hash_curr, a_opt_status, false, true, true)) { + json_object_array_add(json_arr_datum_out, json_obj_tx); l_tx_count++; + } } } else { int l_ret_code = 0; @@ -2245,15 +2468,19 @@ static int s_cli_srv_xchange_tx_list_addr(dap_chain_net_t *a_net, dap_time_t a_a if ( a_before && (l_datum_tx->header.ts_created > a_before) ) continue; - - if (s_string_append_tx_cond_info(l_reply_str, a_net, NULL, NULL, l_datum_tx, l_iter->cur_hash, a_opt_status, false, true, true)) + json_object* json_obj_tx = json_object_new_object(); + if (s_string_append_tx_cond_info_json(json_obj_tx, a_net, NULL, NULL, l_datum_tx, l_iter->cur_hash, a_opt_status, false, true, true)) { + json_object_array_add(json_arr_datum_out, json_obj_tx); l_tx_count++; + } } dap_chain_wallet_cache_iter_delete(l_iter); } - dap_string_append_printf(l_reply_str, "\nFound %"DAP_UINT64_FORMAT_U" transactions", l_tx_count); - *a_str_reply = dap_string_free(l_reply_str, false); /* Free string descriptor, but keep ASCIZ buffer itself */ + json_object_object_add(json_obj_out, "transactions", json_arr_datum_out); + char *l_transactions = dap_strdup_printf("\nFound %"DAP_UINT64_FORMAT_U" transactions", l_tx_count); + json_object_object_add(json_obj_out, "number of transactions", json_object_new_string(l_transactions)); + DAP_DELETE(l_transactions); /* Free string descriptor, but keep ASCIZ buffer itself */ return 0; } @@ -2273,6 +2500,8 @@ void s_tx_is_order_check(UNUSED_ARG dap_chain_net_t* a_net, dap_chain_datum_tx_t static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) { + json_object **json_arr_reply = (json_object **)a_str_reply; + enum {CMD_NONE = 0, CMD_ORDER, CMD_ORDERS, CMD_PURCHASE, CMD_ENABLE, CMD_DISABLE, CMD_TX_LIST, CMD_TOKEN_PAIR }; int l_arg_index = 1, l_cmd_num = CMD_NONE; @@ -2300,23 +2529,24 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) switch (l_cmd_num) { - case CMD_ORDER: - return s_cli_srv_xchange_order(a_argc, a_argv, l_arg_index + 1, a_str_reply); + case CMD_ORDER: { + int res = s_cli_srv_xchange_order(a_argc, a_argv, l_arg_index + 1, json_arr_reply); + return res; + } case CMD_ORDERS: { const char *l_net_str = NULL; const char *l_status_str = NULL; l_arg_index++; dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str); if (!l_net_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'orders' requires parameter -net"); - return -2; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_REQ_PARAM_NET_ERR, "Command 'orders' requires parameter -net"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_REQ_PARAM_NET_ERR; } dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_str); if (!l_net) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Network %s not found", l_net_str); - return -3; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_NET_NOT_FOUND_ERR, "Network %s not found", l_net_str); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_NET_NOT_FOUND_ERR; } - dap_string_t *l_reply_str = dap_string_new(""); dap_list_t *l_list = NULL; if (s_xchange_cache_state == XCHANGE_CACHE_ENABLED){ @@ -2350,8 +2580,8 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) else if ( dap_strcmp (l_status_str, "all") == 0 ) l_opt_status = 0; else { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Unrecognized '-status %s'", l_status_str); - return -3; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_UNREC_STATUS_ERR, "Unrecognized '-status %s'", l_status_str); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_UNREC_STATUS_ERR; } } @@ -2361,8 +2591,9 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) if(l_token_from_str){ dap_chain_datum_token_t * l_token_from_datum = dap_ledger_token_ticker_check( l_net->pub.ledger, l_token_from_str); if(!l_token_from_datum){ - dap_cli_server_cmd_set_reply_text(a_str_reply,"Can't find \"%s\" token in network \"%s\" for argument '-token_from' ", l_token_from_str, l_net->pub.name); - return -6; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_CANT_FIND_TOKEN_FROM_ERR, + "Can't find \"%s\" token in network \"%s\" for argument '-token_from' ", l_token_from_str, l_net->pub.name); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_CANT_FIND_TOKEN_FROM_ERR; } } @@ -2370,8 +2601,9 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) if(l_token_to_str){ dap_chain_datum_token_t * l_token_to_datum = dap_ledger_token_ticker_check( l_net->pub.ledger, l_token_to_str); if(!l_token_to_datum){ - dap_cli_server_cmd_set_reply_text(a_str_reply,"Can't find \"%s\" token in network \"%s\" for argument '-token_to' ", l_token_to_str, l_net->pub.name); - return -6; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_CANT_FIND_TOKEN_TO_ERR, + "Can't find \"%s\" token in network \"%s\" for argument '-token_to' ", l_token_to_str, l_net->pub.name); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_CANT_FIND_TOKEN_TO_ERR; } } @@ -2389,20 +2621,12 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) size_t l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 1000; size_t l_offset = l_offset_str ? strtoul(l_offset_str, NULL, 10) : 0; size_t l_arr_start = 0; - size_t l_arr_end = dap_list_length(l_list); - size_t l_total_orders = l_arr_end; - if (l_offset > 0) { - l_arr_start = l_offset; - dap_string_append_printf(l_reply_str, "offset: %lu\n", l_arr_start); - } - if (l_limit) { - dap_string_append_printf(l_reply_str, "limit: %lu\n", l_limit); - l_arr_end = l_arr_start + l_limit; - if (l_arr_end > dap_list_length(l_list)) { - l_arr_end = dap_list_length(l_list); - } - } + size_t l_arr_end = 0; + json_object* json_obj_order = json_object_new_object(); + json_object* json_arr_orders_out = json_object_new_array(); + dap_chain_set_offset_limit_json(json_arr_orders_out, &l_arr_start, &l_arr_end, l_limit, l_offset, dap_list_length(l_list)); size_t i_tmp = 0; + // Print all txs for (dap_list_t *it = l_list; it; it = it->next) { dap_chain_datum_tx_t *l_tx = NULL; @@ -2413,7 +2637,7 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) dap_chain_net_srv_xchange_order_status_t l_order_status = XCHANGE_ORDER_STATUS_UNKNOWN; dap_hash_fast_t l_tx_hash = {}; uint64_t l_percent_completed = 0; - const char *l_owner_addr = NULL; + char *l_owner_addr = NULL; uint256_t l_amount = {}, l_proposed; const char *l_amount_coins_str = NULL, *l_amount_datoshi_str = NULL, *l_proposed_coins_str = NULL, *l_proposed_datoshi_str = NULL; @@ -2426,7 +2650,7 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) if (l_addr && dap_chain_addr_compare(&l_item->seller_addr, l_addr) == 0) continue; - l_owner_addr = dap_chain_addr_to_str_static(&l_item->seller_addr); + l_owner_addr = dap_strdup(dap_chain_addr_to_str(&l_item->seller_addr)); l_tx = l_item->tx; l_tx_hash = l_item->hash; memcpy(l_buy_token, l_item->buy_token, strlen(l_item->buy_token)); @@ -2490,7 +2714,7 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) l_rate = l_price->rate; l_percent_completed = dap_chain_net_srv_xchange_get_order_completion_rate(l_net, l_tx_hash); l_amount = l_out_cond_last_tx ? l_out_cond_last_tx->header.value : uint256_0; - l_owner_addr = dap_chain_addr_to_str_static(&l_price->creator_addr); + l_owner_addr = dap_strdup(dap_chain_addr_to_str(&l_price->creator_addr)); l_proposed = l_price->datoshi_sell; DAP_DEL_Z(l_price); } @@ -2519,88 +2743,91 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) } i_tmp++; - const char *l_tx_hash_str = dap_chain_hash_fast_to_str_static(&l_tx_hash); - char l_tmp_buf[DAP_TIME_STR_SIZE]; dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, l_tx->header.ts_created); - char *l_cp_rate; - l_cp_rate = dap_uint256_decimal_to_char(l_rate); - l_amount_datoshi_str = dap_uint256_uninteger_to_char(l_amount); - l_amount_coins_str = dap_uint256_decimal_to_char(l_amount); - l_proposed_coins_str = dap_uint256_decimal_to_char(l_proposed); - l_proposed_datoshi_str = dap_uint256_uninteger_to_char(l_proposed); - - dap_string_append_printf(l_reply_str, "orderHash: %s\n ts_created: %s\n Status: %s, proposed: %s(%s) %s, amount: %s (%s) %s, filled: %lu%%, rate (%s/%s): %s, net: %s\n\n" - "owner addr: %s\n\n", l_tx_hash_str, - l_tmp_buf, l_status_order_str, - l_proposed_coins_str ? l_proposed_coins_str : "0.0", - l_proposed_datoshi_str ? l_proposed_datoshi_str : "0", - l_sell_token, - l_amount_coins_str ? l_amount_coins_str : "0.0", - l_amount_datoshi_str ? l_amount_datoshi_str : "0", - l_sell_token, l_percent_completed, - l_buy_token, l_sell_token, - l_cp_rate, - l_net->pub.name, l_owner_addr ? l_owner_addr : "unknown"); + + json_object* json_obj_order = json_object_new_object(); + json_object_object_add(json_obj_order, "order_hash", json_object_new_string(dap_chain_hash_fast_to_str_static(&l_tx_hash))); + json_object_object_add(json_obj_order, "ts_created", json_object_new_string(l_tmp_buf)); + json_object_object_add(json_obj_order, "status", json_object_new_string(l_status_order_str)); + + l_proposed_datoshi_str = dap_uint256_to_char(l_proposed, &l_proposed_coins_str); + json_object_object_add(json_obj_order, "proposed_coins", json_object_new_string(*l_proposed_coins_str ? l_proposed_coins_str : "0.0")); + json_object_object_add(json_obj_order, "proposed_datoshi", json_object_new_string(*l_proposed_datoshi_str ? l_proposed_datoshi_str : "0")); + + l_amount_datoshi_str = dap_uint256_to_char(l_amount, &l_amount_coins_str); + json_object_object_add(json_obj_order, "amount_coins", json_object_new_string(*l_amount_coins_str ? l_amount_coins_str : "0.0")); + json_object_object_add(json_obj_order, "amount_datoshi", json_object_new_string(*l_amount_datoshi_str ? l_amount_datoshi_str : "0")); + json_object_object_add(json_obj_order, "filled_percent", json_object_new_uint64(l_percent_completed)); + json_object_object_add(json_obj_order, "token_buy", json_object_new_string(l_buy_token)); + json_object_object_add(json_obj_order, "token_sell", json_object_new_string(l_sell_token)); + + const char *l_cp_rate; + dap_uint256_to_char(l_rate, &l_cp_rate); + json_object_object_add(json_obj_order, "rate", json_object_new_string(l_cp_rate)); + + json_object_object_add(json_obj_order, "net", json_object_new_string(l_net->pub.name)); + json_object_array_add(*json_arr_reply, json_obj_order); + DAP_DELETE(l_owner_addr); l_printed_orders_count++; - DAP_DEL_Z(l_cp_rate); - DAP_DEL_Z(l_amount_datoshi_str); - DAP_DEL_Z(l_amount_coins_str); - DAP_DEL_Z(l_proposed_coins_str); - DAP_DEL_Z(l_proposed_datoshi_str); } + json_object_object_add(json_obj_order, "ORDERS", json_arr_orders_out); + json_object_array_add(*json_arr_reply, json_obj_order); if (s_xchange_cache_state == XCHANGE_CACHE_ENABLED){ dap_list_free(l_list); } else { dap_list_free_full(l_list, NULL); } - - dap_string_append_printf(l_reply_str, "Total %"DAP_UINT64_FORMAT_U" orders.\n\r", i_tmp); - if (!l_reply_str->len) { - dap_string_append(l_reply_str, "No orders found"); + char *l_total = dap_strdup_printf("Total %"DAP_UINT64_FORMAT_U" orders.\n\r", i_tmp); + json_object_object_add(json_obj_order, "number of transactions", json_object_new_string(l_total)); + DAP_DELETE(l_total); + + if (!json_object_array_length(json_arr_orders_out)) { + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_UNREC_STATUS_ERR, "No orders found"); } - *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, *l_val_buy_str = NULL, *l_val_fee_str = NULL; - l_arg_index++; + l_arg_index++; dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str); if (!l_net_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'purchase' requires parameter -net"); - return -2; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_REQ_PARAM_NET_ERR, "Command 'purchase' requires parameter -net"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_REQ_PARAM_NET_ERR; } dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_str); if (!l_net) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Network %s not found", l_net_str); - return -3; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_NET_NOT_FOUND_ERR, "Network %s not found", l_net_str); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_NET_NOT_FOUND_ERR; } dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-w", &l_wallet_str); if (!l_wallet_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'purchase' requires parameter -w"); - return -10; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_REQ_PARAM_W_ERR, "Command 'purchase' requires parameter -w"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_REQ_PARAM_W_ERR; } 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_cli_server_cmd_set_reply_text(a_str_reply, "Specified wallet not found"); - return -11; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_WALLET_NOT_FOUND_ERR, "Specified wallet not found"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_WALLET_NOT_FOUND_ERR; } dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-order", &l_order_hash_str); if (!l_order_hash_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'purchase' requires parameter -order"); - return -12; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_REQ_PARAM_ORDER_ERR, + "Command 'purchase' requires parameter -order"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_REQ_PARAM_ORDER_ERR; } dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-value", &l_val_buy_str); if (!l_val_buy_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'purchase' requires parameter -value"); - return -8; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_REQ_PARAM_VALUE_ERR, + "Command 'purchase' requires parameter -value"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_REQ_PARAM_VALUE_ERR; } uint256_t l_datoshi_buy = dap_chain_balance_scan(l_val_buy_str); dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-fee", &l_val_fee_str); if (!l_val_fee_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'purchase' requires parameter -fee"); - return -8; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_REQ_PARAM_FEE_ERR, + "Command 'purchase' requires parameter -fee"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_REQ_PARAM_FEE_ERR; } uint256_t l_datoshi_fee = dap_chain_balance_scan(l_val_fee_str); dap_hash_fast_t l_tx_hash = {}; @@ -2610,33 +2837,43 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) l_wallet, &l_str_ret_hash); switch (l_ret_code) { case XCHANGE_PURCHASE_ERROR_OK: { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Exchange transaction has done. tx hash: %s", l_str_ret_hash); + json_object* json_obj_orders = json_object_new_object(); + json_object_object_add(json_obj_orders, "status", json_object_new_string("Exchange transaction has done")); + json_object_object_add(json_obj_orders, "hash", json_object_new_string(l_str_ret_hash)); + json_object_array_add(*json_arr_reply, json_obj_orders); DAP_DELETE(l_str_ret_hash); return 0; } case XCHANGE_PURCHASE_ERROR_SPECIFIED_ORDER_NOT_FOUND: { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified order not found"); - return -13; + dap_json_rpc_error_add(*json_arr_reply, XCHANGE_PURCHASE_ERROR_SPECIFIED_ORDER_NOT_FOUND,"Specified order not found"); + return -XCHANGE_PURCHASE_ERROR_SPECIFIED_ORDER_NOT_FOUND; } case XCHANGE_PURCHASE_ERROR_CAN_NOT_CREATE_PRICE: { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't create price from order"); - return -13; + dap_json_rpc_error_add(*json_arr_reply, XCHANGE_PURCHASE_ERROR_CAN_NOT_CREATE_PRICE, "Can't create price from order"); + return -XCHANGE_PURCHASE_ERROR_CAN_NOT_CREATE_PRICE; } case XCHANGE_PURCHASE_ERROR_CAN_NOT_CREATE_EXCHANGE_TX: { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Exchange transaction error"); - return -13; + dap_json_rpc_error_add(*json_arr_reply, XCHANGE_PURCHASE_ERROR_CAN_NOT_CREATE_EXCHANGE_TX, "Exchange transaction error"); + return -XCHANGE_PURCHASE_ERROR_CAN_NOT_CREATE_EXCHANGE_TX; } default: { - dap_cli_server_cmd_set_reply_text(a_str_reply, "An error occurred with an unknown code: %d.", l_ret_code); - return -14; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_UNKNOWN_ERR, + "An error occurred with an unknown code: %d.", l_ret_code); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_UNKNOWN_ERR; } } } break; case CMD_ENABLE: { + json_object* json_obj_orders_enable = json_object_new_object(); s_srv_xchange->enabled = true; + json_object_object_add(json_obj_orders_enable, "status", json_object_new_string("enable")); + json_object_array_add(*json_arr_reply, json_obj_orders_enable); } break; case CMD_DISABLE: { + json_object* json_obj_orders_enable = json_object_new_object(); s_srv_xchange->enabled = false; + json_object_object_add(json_obj_orders_enable, "status", json_object_new_string("disable")); + json_object_array_add(*json_arr_reply, json_obj_orders_enable); } break; case CMD_TX_LIST: { const char *l_net_str = NULL, *l_time_begin_str = NULL, *l_time_end_str = NULL; @@ -2670,20 +2907,22 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) else if ( dap_strcmp (l_status_str, "all") == 0 ) l_opt_status = TX_STATUS_ALL; else { - - dap_cli_server_cmd_set_reply_text(a_str_reply, "Unrecognized '-status %s'", l_status_str); - return -3; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_LIST_UNREC_STATUS_ERR, + "Unrecognized '-status %s'", l_status_str); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_LIST_UNREC_STATUS_ERR; } } if(!l_net_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'tx_list' requires parameter -net"); - return -3; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_LIST_REQ_PARAM_NET_ERR, + "Command 'tx_list' requires parameter -net"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_LIST_REQ_PARAM_NET_ERR; } dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_str); if(!l_net) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Network %s not found", l_net_str); - return -4; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_LIST_NET_NOT_FOUND_ERR, + "Network %s not found", l_net_str); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_LIST_NET_NOT_FOUND_ERR; } dap_time_t l_time[2]; @@ -2693,19 +2932,22 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) /* Dispatch request processing to ... */ if ( l_addr_str ) { - if ( !(l_addr = dap_chain_addr_from_str(l_addr_str)) ) - return dap_cli_server_cmd_set_reply_text(a_str_reply, "Cannot convert -addr '%s' to internal representative", l_addr_str), -EINVAL; - - return s_cli_srv_xchange_tx_list_addr (l_net, l_time[0], l_time[1], l_addr, l_opt_status, a_str_reply); + if ( !(l_addr = dap_chain_addr_from_str(l_addr_str)) ) { + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_LIST_CAN_NOT_CONVERT_ERR, + "Cannot convert -addr '%s' to internal representative", l_addr_str); + return -EINVAL; + } + json_object* json_obj_order = json_object_new_object(); + s_cli_srv_xchange_tx_list_addr_json(l_net, l_time[0], l_time[1], l_addr, l_opt_status, json_obj_order); + json_object_array_add(*json_arr_reply, json_obj_order); + return 0; } - // Prepare output string - dap_string_t *l_reply_str = dap_string_new(""); - // Find transactions using filter function s_filter_tx_list() if (s_xchange_cache_state == XCHANGE_CACHE_ENABLED){ xchange_orders_cache_net_t* l_cache = NULL; dap_list_t *l_tx_cache_list = NULL; + json_object* json_arr_bl_out = json_object_new_array(); l_cache = s_get_xchange_cache_by_net_id(l_net->pub.id); xchange_tx_cache_t* l_temp, *l_item; HASH_ITER(hh, l_cache->cache, l_item, l_temp){ @@ -2714,16 +2956,19 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) if (l_time[1] && l_item->tx->header.ts_created > l_time[1]) break; + json_object* json_obj_order = json_object_new_object(); + if (s_string_append_tx_cond_info_json(json_obj_order, l_net, &l_item->seller_addr, + l_item->tx_type == TX_TYPE_EXCHANGE ? &l_item->tx_info.exchange_info.buyer_addr : NULL, + l_item->tx, &l_item->hash, l_opt_status, false, true, true)){ - if (s_string_append_tx_cond_info(l_reply_str, l_net, &l_item->seller_addr, - l_item->tx_type == TX_TYPE_EXCHANGE ? &l_item->tx_info.exchange_info.buyer_addr : NULL, - l_item->tx, &l_item->hash, l_opt_status, false, true, true)) + json_object_array_add(json_arr_bl_out, json_obj_order); l_show_tx_nr++; + } } } else { dap_list_t *l_datum_list0 = dap_chain_datum_list(l_net, NULL, s_filter_tx_list, l_time); size_t l_datum_num = dap_list_length(l_datum_list0); - + json_object* json_arr_bl_out = json_object_new_array(); if (l_datum_num > 0) { dap_list_t *l_datum_list = l_datum_list0; while(l_datum_list) { @@ -2733,23 +2978,25 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) if (l_time[1] && l_datum_tx->header.ts_created > l_time[1]) break; - + json_object* json_obj_order = json_object_new_object(); dap_hash_fast_t l_hash = {}; dap_hash_fast(l_datum_tx, dap_chain_datum_tx_get_size(l_datum_tx), &l_hash); - if (s_string_append_tx_cond_info(l_reply_str, l_net, NULL, NULL, l_datum_tx, &l_hash, l_opt_status, false, true, true)) + if (s_string_append_tx_cond_info_json(json_obj_order, l_net, NULL, NULL, l_datum_tx, &l_hash, l_opt_status, false, true, true)) { + json_object_array_add(json_arr_bl_out, json_obj_order); l_show_tx_nr++; + } l_datum_list = dap_list_next(l_datum_list); } } dap_list_free_full(l_datum_list0, NULL); } + json_object* json_obj_orders = json_object_new_object(); if(l_show_tx_nr) - dap_string_append_printf(l_reply_str, "Found %d transactions", l_show_tx_nr); - else - dap_string_append(l_reply_str, "Transactions not found"); - - *a_str_reply = dap_string_free(l_reply_str, false); + json_object_object_add(json_obj_orders, "number of transactions", json_object_new_int(l_show_tx_nr)); + else + json_object_object_add(json_obj_orders, "number of transactions", json_object_new_string("Transactions not found")); + json_object_array_add(*json_arr_reply, json_obj_orders); } break; // Token pair control case CMD_TOKEN_PAIR: { @@ -2758,13 +3005,15 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) const char *l_net_str = NULL; dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str); if(!l_net_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'token_pair' requires parameter -net"); - return -3; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_REQ_PARAM_NET_ERR, + "Command 'token_pair' requires parameter -net"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_REQ_PARAM_NET_ERR; } dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_str); if(!l_net) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Network %s not found", l_net_str); - return -4; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_NET_NOT_FOUND_ERR, + "Network %s not found", l_net_str); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_NET_NOT_FOUND_ERR; } // Select subcommands @@ -2777,26 +3026,30 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) const char * l_token_from_str = NULL; dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-token_from", &l_token_from_str); if(!l_token_from_str){ - dap_cli_server_cmd_set_reply_text(a_str_reply,"No argument '-token_from'"); - return -5; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_TOKEN_FROM_ARG_ERR, + "No argument '-token_from'"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_TOKEN_FROM_ARG_ERR; } dap_chain_datum_token_t * l_token_from_datum = dap_ledger_token_ticker_check( l_net->pub.ledger, l_token_from_str); if(!l_token_from_datum){ - dap_cli_server_cmd_set_reply_text(a_str_reply,"Can't find \"%s\" token in network \"%s\" for argument '-token_from' ", l_token_from_str, l_net->pub.name); - return -6; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_TOKEN_FROM_ERR, + "Can't find \"%s\" token in network \"%s\" for argument '-token_from' ", l_token_from_str, l_net->pub.name); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_TOKEN_FROM_ERR; } // Check for token_to const char * l_token_to_str = NULL; dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-token_to", &l_token_to_str); if(!l_token_to_str){ - dap_cli_server_cmd_set_reply_text(a_str_reply,"No argument '-token_to'"); - return -5; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_TOKEN_TO_ERR, + "No argument '-token_to'"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_TOKEN_TO_ERR; } dap_chain_datum_token_t * l_token_to_datum = dap_ledger_token_ticker_check( l_net->pub.ledger, l_token_to_str); if(!l_token_to_datum){ - dap_cli_server_cmd_set_reply_text(a_str_reply,"Can't find \"%s\" token in network \"%s\" for argument '-token_to' ", l_token_to_str, l_net->pub.name); - return -6; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_CANT_FIND_TOKEN_ERR, + "Can't find \"%s\" token in network \"%s\" for argument '-token_to' ", l_token_to_str, l_net->pub.name); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_CANT_FIND_TOKEN_ERR; } // Read time_from @@ -2813,7 +3066,6 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) // Check for price subcommand if (strcmp(l_price_subcommand,"average") == 0){ - dap_string_t *l_reply_str = dap_string_new(""); dap_list_t *l_list = NULL; if (s_xchange_cache_state == XCHANGE_CACHE_ENABLED){ @@ -2898,7 +3150,8 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) dap_list_free(l_list); if (IS_ZERO_256(l_total_rates) || IS_ZERO_256(l_rate) || !l_last_rate_time){ - dap_string_append_printf(l_reply_str,"Can't find orders for specified token pair\n"); + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_CANT_FIND_ORDER_ERR, + "Can't find orders for specified token pair\n"); } else { uint256_t l_rate_average = {0}; if (!IS_ZERO_256(l_total_rates_count)) @@ -2907,12 +3160,13 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) char l_tmp_buf[DAP_TIME_STR_SIZE]; dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, l_last_rate_time); const char *l_rate_average_str; dap_uint256_to_char(l_rate_average, &l_rate_average_str); - dap_string_append_printf(l_reply_str,"Average rate: %s\n", l_rate_average_str); + json_object* json_obj_order = json_object_new_object(); + json_object_object_add(json_obj_order, "Average rate", json_object_new_string(l_rate_average_str)); const char *l_last_rate_str; dap_uint256_to_char(l_rate, &l_last_rate_str); - dap_string_append_printf(l_reply_str, "Last rate: %s Last rate time: %s", - l_last_rate_str, l_tmp_buf); + json_object_object_add(json_obj_order, "Last rate", json_object_new_string(l_last_rate_str)); + json_object_object_add(json_obj_order, "Last rate time", json_object_new_string(l_tmp_buf)); + json_object_array_add(*json_arr_reply, json_obj_order); } - *a_str_reply = dap_string_free(l_reply_str, false); break; }else if (strcmp(l_price_subcommand,"history") == 0){ const char *l_limit_str = NULL, *l_offset_str = NULL; @@ -2922,8 +3176,6 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) size_t l_offset = l_offset_str ? strtoul(l_offset_str, NULL, 10) : 0; uint256_t l_token_from_value = {}, l_token_to_value = {}; - - dap_string_t *l_reply_str = dap_string_new(""); dap_list_t *l_list = NULL; dap_time_t l_time[2]; l_time[0] = l_time_from; @@ -2951,16 +3203,16 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) size_t l_datum_num = dap_list_length(l_list); - size_t l_arr_start = 0; - size_t l_arr_end = l_datum_num; - if (l_offset > 0) { - l_arr_start = l_offset; - dap_string_append_printf(l_reply_str, "offset: %lu\n", l_arr_start); - } - if (l_limit) { - l_arr_end = l_arr_start + l_limit; - dap_string_append_printf(l_reply_str, "limit: %lu\n", l_limit); + if (l_datum_num == 0){ + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_CANT_FIND_TX_ERR, + "Can't find transactions"); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_CANT_FIND_TX_ERR; } + json_object* json_arr_bl_cache_out = json_object_new_array(); + size_t l_arr_start = 0; + size_t l_arr_end = 0; + dap_chain_set_offset_limit_json(json_arr_bl_cache_out, &l_arr_start, &l_arr_end, l_limit, l_offset, l_datum_num); + size_t i_tmp = 0; size_t l_total = 0; @@ -3033,45 +3285,38 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) if (i_tmp >= l_arr_end) break; - i_tmp++; + i_tmp++; - - - if(s_string_append_tx_cond_info(l_reply_str, l_net, NULL, NULL, l_tx, &l_tx_hash, TX_STATUS_ALL, false, false, true)){ + json_object* json_obj_out = json_object_new_object(); + if(s_string_append_tx_cond_info_json(json_obj_out, l_net, NULL, NULL, l_tx, &l_tx_hash, TX_STATUS_ALL, false, false, true)){ l_total++; SUM_256_256(l_token_to_value, l_token_curr_to_value, &l_token_to_value); SUM_256_256(l_token_from_value, l_token_curr_from_value, &l_token_from_value); + json_object_array_add(json_arr_bl_cache_out, json_obj_out); } - - l_cur = dap_list_next(l_cur); } - dap_list_free(l_list); - dap_string_append_printf(l_reply_str, "Found %"DAP_UINT64_FORMAT_U" transactions\n", l_total); - - const char *l_token_from_value_coins_str = NULL, *l_token_from_value_datoshi_str = NULL, - *l_token_to_value_coins_str = NULL, *l_token_to_value_datoshi_str = NULL; - l_token_from_value_datoshi_str = dap_chain_balance_print(l_token_from_value); - l_token_from_value_coins_str = dap_chain_balance_to_coins(l_token_from_value); - l_token_to_value_datoshi_str = dap_chain_balance_print(l_token_to_value); - l_token_to_value_coins_str = dap_chain_balance_to_coins(l_token_to_value); - - dap_string_append_printf(l_reply_str, "Traiding value:\n\t%s (%s) %s\n\t%s (%s) %s\n", l_token_from_value_coins_str, l_token_from_value_datoshi_str, l_token_from_str, - l_token_to_value_coins_str, l_token_to_value_datoshi_str, l_token_to_str); + json_object_array_add(*json_arr_reply, json_arr_bl_cache_out); + dap_list_free(l_list); + json_object* json_obj_order = json_object_new_object(); + json_object_object_add(json_obj_order, "tx_count", json_object_new_uint64(l_total)); - DAP_DEL_Z(l_token_from_value_datoshi_str); - DAP_DEL_Z(l_token_from_value_coins_str); - DAP_DEL_Z(l_token_to_value_datoshi_str); - DAP_DEL_Z(l_token_to_value_coins_str); + const char *l_token_from_value_coins_str = NULL, *l_token_from_value_datoshi_str = dap_uint256_to_char(l_token_from_value, &l_token_from_value_coins_str); + json_object_object_add(json_obj_order, "trading_val_from_coins", json_object_new_string(l_token_from_value_coins_str)); + json_object_object_add(json_obj_order, "trading_val_from_datoshi", json_object_new_string(l_token_from_value_datoshi_str)); - *a_str_reply = dap_string_free(l_reply_str, false); + const char *l_token_to_value_coins_str = NULL, *l_token_to_value_datoshi_str = dap_uint256_to_char(l_token_to_value, &l_token_to_value_coins_str); + json_object_object_add(json_obj_order, "trading_val_to_coins", json_object_new_string(l_token_to_value_coins_str)); + json_object_object_add(json_obj_order, "trading_val_to_datoshi", json_object_new_string(l_token_to_value_datoshi_str)); + + json_object_array_add(*json_arr_reply, json_obj_order); break; } else { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Unrecognized subcommand '%s'", - l_price_subcommand); - return -38; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_UNKNOWN_ERR, + "Unrecognized subcommand '%s'", l_price_subcommand); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_UNKNOWN_ERR; } } @@ -3084,18 +3329,17 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-offset", &l_offset_str); size_t l_offset = l_offset_str ? strtoul(l_offset_str, NULL, 10) : 0; size_t l_limit = l_limit_str ? strtoul(l_limit_str, NULL, 10) : 0; - dap_string_t *l_reply_str = dap_string_new(""); + char ** l_tickers = NULL; size_t l_tickers_count = 0; dap_ledger_addr_get_token_ticker_all( l_net->pub.ledger,NULL,&l_tickers,&l_tickers_count); - + json_object* json_obj_out = json_object_new_object(); size_t l_pairs_count = 0; if(l_tickers){ - size_t l_arr_start = l_offset; + size_t l_arr_start = 0; size_t l_arr_end = 0; - if (l_limit) { - l_arr_end = l_arr_start + l_limit - 1; - } + json_object* json_arr_bl_cache_out = json_object_new_array(); + dap_chain_set_offset_limit_json(json_arr_bl_cache_out, &l_arr_start, &l_arr_end, l_limit, l_offset, l_tickers_count); size_t i_tmp = 0; for(size_t i = 0; i< l_tickers_count; i++){ @@ -3107,12 +3351,16 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) continue; } i_tmp++; - dap_string_append_printf(l_reply_str,"%s:%s ", l_tickers[i], l_tickers[j]); + json_object* json_obj_bl = json_object_new_object(); + json_object_object_add(json_obj_bl, "ticker_1",json_object_new_string(l_tickers[i])); + json_object_object_add(json_obj_bl, "ticker_2",json_object_new_string(l_tickers[j])); + json_object_array_add(json_arr_bl_cache_out, json_obj_bl); l_pairs_count++; } } } + json_object_object_add(json_obj_out, "TICKERS PAIR", json_arr_bl_cache_out); // Free tickers array for(size_t i = 0; i< l_tickers_count; i++){ @@ -3120,20 +3368,24 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) } DAP_DELETE(l_tickers); } - dap_string_prepend_printf( l_reply_str,"Tokens count pair: %zd\n", l_pairs_count); - *a_str_reply = dap_string_free(l_reply_str, false); + json_object_object_add(json_obj_out, "pair count", json_object_new_uint64(l_pairs_count)); + json_object_array_add(*json_arr_reply, json_obj_out); break; } } // No subcommand selected - dap_cli_server_cmd_set_reply_text(a_str_reply,"Command 'token pair' requires proper subcommand, please read its manual with command 'help srv_xchange'"); + json_object* json_obj_out = json_object_new_object(); + json_object_object_add(json_obj_out, "token pair status", json_object_new_string("Command 'token pair' requires proper subcommand," + "please read its manual with command 'help srv_xchange'")); + json_object_array_add(*json_arr_reply, json_obj_out); } break; default: { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Command %s not recognized", a_argv[l_arg_index]); - return -1; + dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_UNKNOWN_COMMAND_ERR, + "Command %s not recognized", a_argv[l_arg_index]); + return -DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_UNKNOWN_COMMAND_ERR; } } return 0; 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 bc9d1e927d5e100cbc04ce4bd9a422fb26613b1f..7295c0ea2f8c3c72269f64762d7d7cc7679210ce 100644 --- a/modules/service/xchange/include/dap_chain_net_srv_xchange.h +++ b/modules/service/xchange/include/dap_chain_net_srv_xchange.h @@ -63,6 +63,76 @@ void dap_chain_net_srv_xchange_deinit(); json_object *dap_chain_net_srv_xchange_print_fee_json(dap_chain_net_t *a_net); void dap_chain_net_srv_xchange_print_fee(dap_chain_net_t *a_net, dap_string_t *a_string_ret); +typedef enum s_com_net_srv_xchange_err{ + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_OK = 0, + + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_REQ_PARAM_NET_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_NET_NOT_FOUND_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_UNREC_STATUS_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_CANT_FIND_TOKEN_TO_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_CANT_FIND_TOKEN_FROM_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_PARAM_TOKEN_SELL_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_PARAM_TOKEN_BUY_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_PARAM_TICKR_NOTF_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_TOKEN_EQUAL_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_CRTE_REQ_PARAM_VALUE_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_CRTE_REQ_PARAM_RATE_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_CRTE_REQ_PARAM_FEE_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_CRTE_REQ_PARAM_W_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_CRTE_WALLET_NOT_FOUND_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_REQ_PARAM_NET_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_NET_NOT_FOUND_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_REQ_PARAM_ORDER_ADDR_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_CAN_NOT_CONVERT_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_INCORRECT_ADDR_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_DOES_NOT_BELONG_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_HIST_DOES_NO_HISTORY_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_RMOVE_REQ_PARAM_NET_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_RMOVE_NET_NOT_FOUND_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_RMOVE_REQ_PARAM_W_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_RMOVE_WALLET_NOT_FOUND_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_RMOVE_REQ_PARAM_ORDER_ADDR_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_RMOVE_REQ_PARAM_FEE_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_RMOVE_UNKNOWN_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_REQ_PARAM_NET_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_NET_NOT_FOUND_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_NET_NOT_FOUN_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_REQ_PARAM_ORDER_ADDR_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_CANT_FIND_ORDER_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_ITS_NOT_ORDER_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_CANT_GET_PRICE_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_CANT_GET_LAST_TX_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_STATUS_CANT_FIND_LAST_TX_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_SUB_NOT_FOUND_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_ORDRS_LIST_CAN_NOT_CONVERT_ERR, + + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_REQ_PARAM_NET_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_NET_NOT_FOUND_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_REQ_PARAM_W_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_WALLET_NOT_FOUND_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_REQ_PARAM_ORDER_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_REQ_PARAM_VALUE_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_REQ_PARAM_FEE_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PURCHASE_UNKNOWN_ERR, + + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_LIST_UNREC_STATUS_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_LIST_REQ_PARAM_NET_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_LIST_NET_NOT_FOUND_ERR, + + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_REQ_PARAM_NET_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_NET_NOT_FOUND_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_TOKEN_FROM_ARG_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_TOKEN_FROM_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_TOKEN_TO_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_CANT_FIND_TOKEN_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_CANT_FIND_ORDER_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_CANT_FIND_TX_ERR, + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_PAIR_UNKNOWN_ERR, + + DAP_CHAIN_NODE_CLI_COM_NET_SRV_XCNGE_UNKNOWN_COMMAND_ERR + +} s_com_net_srv_xchange_err_t; + typedef enum dap_chain_net_srv_xchange_create_error_list{ XCHANGE_CREATE_ERROR_OK = 0, XCHANGE_CREATE_ERROR_INVALID_ARGUMENT, @@ -76,7 +146,7 @@ typedef enum dap_chain_net_srv_xchange_create_error_list{ XCHANGE_CREATE_ERROR_NOT_ENOUGH_CASH_IN_SPECIFIED_WALLET, XCHANGE_CREATE_ERROR_MEMORY_ALLOCATED, XCHANGE_CREATE_ERROR_CAN_NOT_COMPOSE_THE_CONDITIONAL_TRANSACTION, - XCHANGE_CREATE_ERROR_CAN_NOT_PUT_TRANSACTION_TO_MEMPOOL, + XCHANGE_CREATE_ERROR_CAN_NOT_PUT_TRANSACTION_TO_MEMPOOL } dap_chain_net_srv_xchange_create_error_t; dap_chain_net_srv_xchange_create_error_t dap_chain_net_srv_xchange_create(dap_chain_net_t *a_net, const char *a_token_buy, const char *a_token_sell, uint256_t a_datoshi_sell, diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c index f12cf616b22d290f9db8cbeb0e3b50bb021a2278..d1050a3fd080fe1dd9fc6486ac8c708d7d501473 100644 --- a/modules/type/blocks/dap_chain_cs_blocks.c +++ b/modules/type/blocks/dap_chain_cs_blocks.c @@ -975,7 +975,7 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) json_object* json_arr_bl_cache_out = json_object_new_array(); size_t l_start_arr = 0; size_t l_arr_end = 0; - s_set_offset_limit_json(json_arr_bl_cache_out, &l_start_arr, &l_arr_end, l_limit, l_offset, PVT(l_blocks)->blocks_count); + dap_chain_set_offset_limit_json(json_arr_bl_cache_out, &l_start_arr, &l_arr_end, l_limit, l_offset, PVT(l_blocks)->blocks_count); size_t i_tmp = 0; dap_chain_block_cache_t *l_block_cache = PVT(l_blocks)->blocks; diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c index 106b2eb8d54036861e7184b33d7496ed7af7adaa..77e8d352a649d4ffe03b5ed3ae4704fd341a5f3b 100644 --- a/modules/type/dag/dap_chain_cs_dag.c +++ b/modules/type/dag/dap_chain_cs_dag.c @@ -1704,7 +1704,7 @@ static int s_cli_dag(int argc, char ** argv, void **a_str_reply) l_objs = dap_global_db_get_all_sync(l_gdb_group_events,&l_objs_count); size_t l_arr_start = 0; size_t l_arr_end = 0; - s_set_offset_limit_json(json_arr_obj_event, &l_arr_start, &l_arr_end, l_limit, l_offset, l_objs_count); + dap_chain_set_offset_limit_json(json_arr_obj_event, &l_arr_start, &l_arr_end, l_limit, l_offset, l_objs_count); json_object_object_add(json_obj_event_list,"net name", json_object_new_string(l_net->pub.name)); json_object_object_add(json_obj_event_list,"chain", json_object_new_string(l_chain->name)); @@ -1729,7 +1729,7 @@ static int s_cli_dag(int argc, char ** argv, void **a_str_reply) pthread_mutex_lock(&PVT(l_dag)->events_mutex); size_t l_arr_start = 0; size_t l_arr_end = 0; - s_set_offset_limit_json(json_arr_obj_event, &l_arr_start, &l_arr_end, l_limit, l_offset, HASH_COUNT(PVT(l_dag)->events)); + dap_chain_set_offset_limit_json(json_arr_obj_event, &l_arr_start, &l_arr_end, l_limit, l_offset, HASH_COUNT(PVT(l_dag)->events)); size_t i_tmp = 0; dap_chain_cs_dag_event_item_t * l_event_item = NULL,*l_event_item_tmp = NULL; @@ -1769,7 +1769,7 @@ static int s_cli_dag(int argc, char ** argv, void **a_str_reply) dap_chain_cs_dag_event_item_t * l_event_item = NULL,*l_event_item_tmp = NULL; size_t l_arr_start = 0; size_t l_arr_end = 0; - s_set_offset_limit_json(json_arr_obj_event, &l_arr_start, &l_arr_end, l_limit, l_offset, HASH_COUNT(PVT(l_dag)->events_treshold)); + dap_chain_set_offset_limit_json(json_arr_obj_event, &l_arr_start, &l_arr_end, l_limit, l_offset, HASH_COUNT(PVT(l_dag)->events_treshold)); size_t i_tmp = 0; if (l_head){