From d7122e0d7cab93b4ff20d9bbb8a99b5e47741d87 Mon Sep 17 00:00:00 2001 From: Roman Khlopkov <roman.khlopkov@demlabs.net> Date: Fri, 22 May 2020 14:45:38 +0300 Subject: [PATCH] [*] eXchange with local node debugged --- modules/chain/dap_chain_ledger.c | 38 +++++---- modules/common/dap_chain_datum_tx_items.c | 12 ++- .../common/include/dap_chain_datum_tx_items.h | 2 +- modules/mempool/dap_chain_mempool.c | 12 ++- modules/net/dap_chain_node.c | 4 +- modules/net/srv/dap_chain_net_srv_order.c | 1 + .../xchange/dap_chain_net_srv_xchange.c | 83 ++++++++++++------- 7 files changed, 96 insertions(+), 56 deletions(-) diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c index 4bce2c45a6..ae594fca2e 100644 --- a/modules/chain/dap_chain_ledger.c +++ b/modules/chain/dap_chain_ledger.c @@ -254,7 +254,7 @@ int dap_chain_ledger_token_ticker_check(dap_ledger_t * a_ledger, const char *a_t } dap_chain_ledger_token_item_t *l_token_item; HASH_FIND_STR(PVT(a_ledger)->tokens, a_token_ticker, l_token_item); - return (int)l_token_item; + return (size_t)l_token_item; } /** @@ -642,7 +642,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t && 3. hash(tx1) == tx2.dap_chain_datump_tx_in.tx_prev_hash && - 4. tx1.dap_chain_datum_tx_out.addr.data.key == tx2.dap_chain_datum_tx_sig.pkey for unconditioned output + 4. tx1.dap_chain_datum_tx_out.addr.data.key == tx2.dap_chain_datum_tx_sig.pkey for unconditional output && 5. tx1.dap_chain_datum_tx_out.condition == verify_svc_type(tx2) for conditional ouput && @@ -680,9 +680,11 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t // find all conditional 'in' items in current transaction dap_list_t *l_list_tmp = dap_chain_datum_tx_items_get((dap_chain_datum_tx_t *)a_tx, TX_ITEM_TYPE_IN_COND, &l_prev_tx_count); - // add conditional input to common list - dap_list_append(l_list_in, l_list_tmp->data); - dap_list_free(l_list_tmp); + if (l_list_tmp) { + // add conditional input to common list + dap_list_append(l_list_in, l_list_tmp->data); + dap_list_free(l_list_tmp); + } l_list_tmp = l_list_in; int l_list_tmp_num = 0; @@ -975,7 +977,7 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx) //log_it ( L_INFO, "dap_chain_ledger_tx_add() check passed for tx %s",l_tx_hash_str); - char * l_token_ticker = NULL; + char * l_token_ticker = NULL, *l_token_ticker_cond = NULL; dap_chain_ledger_tx_item_t *l_item_tmp = NULL; pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock); HASH_FIND(hh, l_ledger_priv->ledger_items, l_tx_hash, sizeof(dap_chain_hash_fast_t), l_item_tmp); // tx_hash already in the hash? @@ -1025,6 +1027,8 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx) /// Mark 'out' item in cache because it used l_tx_prev_hash = &(l_prev_item_out->tx_hash_spent_fast[l_tx_in->header.tx_out_prev_idx]); } else { + if (l_token_ticker_cond == NULL) + l_token_ticker_cond = dap_strdup(l_prev_item_out->token_tiker); // all balance deducts performed with previous conditional transaction dap_chain_tx_in_cond_t *l_tx_in_cond = bound_item->tx_cur_in_cond; /// Mark 'out' item in cache because it used @@ -1069,7 +1073,12 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx) } if (l_list_bound_items) dap_list_free_full(l_list_bound_items, free); - + if (l_token_ticker_cond) { + if (l_token_ticker) { + DAP_DELETE(l_token_ticker); + } + l_token_ticker = dap_strdup(l_token_ticker_cond); + } // Try to find token ticker if wasn't if ( l_token_ticker == NULL){ int l_base_tx_count = 0; @@ -1105,7 +1114,7 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx) wallet_balance = DAP_NEW_Z(dap_ledger_wallet_balance_t); wallet_balance->key = l_wallet_balance_key; wallet_balance->balance += l_out_item->header.value; - dap_stpcpy(wallet_balance->token_ticker, l_token_ticker); + dap_stpcpy(wallet_balance->token_ticker, l_token_ticker_ex); //log_it(L_DEBUG,"!!! Create new balance item: %s %s", l_addr_str, l_token_ticker); HASH_ADD_KEYPTR(hh, PVT(a_ledger)->balance_accounts, wallet_balance->key, strlen(l_wallet_balance_key), wallet_balance); @@ -1179,6 +1188,9 @@ FIN: if (l_token_ticker) { DAP_DELETE(l_token_ticker); } + if (l_token_ticker_cond) { + DAP_DELETE(l_token_ticker_cond); + } DAP_DELETE(l_tx_hash); return ret; } @@ -1445,9 +1457,8 @@ static dap_chain_ledger_tx_item_t* tx_item_find_by_addr(dap_ledger_t *a_ledger, continue; } // Get 'out' items from transaction - dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT, NULL); - dap_list_t *l_list_tmp = l_list_out_items; - while(l_list_tmp) { + dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT, NULL); + for(dap_list_t *l_list_tmp = l_list_out_items; l_list_tmp; l_list_tmp = dap_list_next(l_list_tmp)) { const dap_chain_tx_out_t *l_tx_out = (const dap_chain_tx_out_t*) l_list_tmp->data; assert(l_tx_out); // If a_token is setup we check if its not our token - miss it @@ -1459,10 +1470,9 @@ static dap_chain_ledger_tx_item_t* tx_item_find_by_addr(dap_ledger_t *a_ledger, memcpy(a_tx_first_hash, l_tx_hash, sizeof(dap_chain_hash_fast_t)); is_tx_found = true; break; - } - l_list_tmp = dap_list_next(l_list_tmp); + } } - dap_list_free(l_list_tmp); + dap_list_free(l_list_out_items); // already found transaction if(is_tx_found) break; diff --git a/modules/common/dap_chain_datum_tx_items.c b/modules/common/dap_chain_datum_tx_items.c index 570a2824a0..7d5b9c3b39 100644 --- a/modules/common/dap_chain_datum_tx_items.c +++ b/modules/common/dap_chain_datum_tx_items.c @@ -60,7 +60,7 @@ static size_t dap_chain_tx_out_get_size(const dap_chain_tx_out_t *a_item) static size_t dap_chain_tx_out_cond_get_size(const dap_chain_tx_out_cond_t *a_item) { - return sizeof (a_item->header) + sizeof (a_item->subtype) + a_item->params_size; + return sizeof(dap_chain_tx_out_cond_t) + a_item->params_size; } static size_t dap_chain_tx_pkey_get_size(const dap_chain_tx_pkey_t *a_item) @@ -223,8 +223,7 @@ dap_chain_tx_out_cond_t* dap_chain_datum_tx_item_out_cond_create_srv_pay(dap_enc uint8_t *l_pub_key = dap_enc_key_serealize_pub_key(a_key, &l_pub_key_size); - dap_chain_tx_out_cond_t *l_item = DAP_NEW_Z_SIZE(dap_chain_tx_out_cond_t, - sizeof(l_item->header) + sizeof (l_item->subtype) + a_params_size); + dap_chain_tx_out_cond_t *l_item = DAP_NEW_Z_SIZE(dap_chain_tx_out_cond_t, sizeof(dap_chain_tx_out_cond_t) + a_params_size); l_item->header.item_type = TX_ITEM_TYPE_OUT_COND; l_item->header.value = a_value; l_item->header.subtype = DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY; // By default creatre cond for service pay. Rework with smth more flexible @@ -240,20 +239,19 @@ dap_chain_tx_out_cond_t* dap_chain_datum_tx_item_out_cond_create_srv_pay(dap_enc dap_chain_tx_out_cond_t* dap_chain_datum_tx_item_out_cond_create_srv_xchange(dap_chain_net_srv_uid_t a_srv_uid, dap_chain_net_id_t a_net_id, const char *a_token, uint64_t a_value, - const void *a_params, size_t a_params_size) + const void *a_params, uint32_t a_params_size) { if (!a_token) { return NULL; } - dap_chain_tx_out_cond_t *l_item = DAP_NEW_Z_SIZE(dap_chain_tx_out_cond_t, - sizeof(l_item->header) + sizeof (l_item->subtype) + a_params_size); + dap_chain_tx_out_cond_t *l_item = DAP_NEW_Z_SIZE(dap_chain_tx_out_cond_t, sizeof(dap_chain_tx_out_cond_t) + a_params_size); l_item->header.item_type = TX_ITEM_TYPE_OUT_COND; l_item->header.value = a_value; l_item->header.subtype = DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE; l_item->subtype.srv_xchange.srv_uid = a_srv_uid; l_item->subtype.srv_xchange.net_id = a_net_id; strcpy(l_item->subtype.srv_xchange.token, a_token); - l_item->params_size = (uint32_t)a_params_size; + l_item->params_size = a_params_size; if (a_params_size) { memcpy(l_item->params, a_params, a_params_size); } diff --git a/modules/common/include/dap_chain_datum_tx_items.h b/modules/common/include/dap_chain_datum_tx_items.h index 1d7acfd76f..572117a504 100644 --- a/modules/common/include/dap_chain_datum_tx_items.h +++ b/modules/common/include/dap_chain_datum_tx_items.h @@ -94,7 +94,7 @@ dap_chain_tx_out_cond_t* dap_chain_datum_tx_item_out_cond_create_srv_pay(dap_enc */ dap_chain_tx_out_cond_t* dap_chain_datum_tx_item_out_cond_create_srv_xchange(dap_chain_net_srv_uid_t a_srv_uid, dap_chain_net_id_t a_net_id, const char *a_token, uint64_t a_value, - const void *a_params, size_t a_params_size); + const void *a_params, uint32_t a_params_size); /** * Create item dap_chain_tx_sig_t * diff --git a/modules/mempool/dap_chain_mempool.c b/modules/mempool/dap_chain_mempool.c index b691a6c781..7e02de5440 100644 --- a/modules/mempool/dap_chain_mempool.c +++ b/modules/mempool/dap_chain_mempool.c @@ -343,9 +343,10 @@ int dap_chain_mempool_tx_create_massive( dap_chain_t * a_chain, dap_enc_key_t *a } dap_chain_hash_fast_t* dap_chain_mempool_tx_create_cond_input(dap_chain_net_t * a_net,dap_chain_hash_fast_t *a_tx_prev_hash, - - const dap_chain_addr_t* a_addr_to, dap_enc_key_t *l_key_tx_sign, dap_chain_datum_tx_receipt_t * l_receipt, size_t l_receipt_size) + const dap_chain_addr_t* a_addr_to, dap_enc_key_t *l_key_tx_sign, + dap_chain_datum_tx_receipt_t * l_receipt, size_t l_receipt_size) { + UNUSED(l_receipt_size); dap_ledger_t * l_ledger = a_net ? dap_chain_ledger_by_net_name( a_net->pub.name ) : NULL; if ( ! a_net || ! l_ledger || ! a_addr_to ) return NULL; @@ -360,9 +361,12 @@ dap_chain_hash_fast_t* dap_chain_mempool_tx_create_cond_input(dap_chain_net_t * uint16_t pos=0; dap_chain_datum_tx_add_item(&l_tx, (byte_t*) l_receipt); pos++; + // add 'in_cond' items - // expected only one 'cond out' item, so it idx always should be zero - if (dap_chain_datum_tx_add_in_cond_item(&l_tx,a_tx_prev_hash,0,pos-1) != 0 ){ + int l_prev_cond_idx = 0; + dap_chain_datum_tx_t *l_cond_tx = dap_chain_ledger_tx_find_by_hash(l_ledger, a_tx_prev_hash); + dap_chain_datum_tx_item_get(l_cond_tx, &l_prev_cond_idx, TX_ITEM_TYPE_OUT_COND, NULL); + if (dap_chain_datum_tx_add_in_cond_item(&l_tx, a_tx_prev_hash, l_prev_cond_idx, pos-1) != 0 ){ dap_chain_datum_tx_delete(l_tx); log_it( L_ERROR, "Cant add tx cond input"); return NULL; diff --git a/modules/net/dap_chain_node.c b/modules/net/dap_chain_node.c index 1c639f5094..38cf9d1933 100644 --- a/modules/net/dap_chain_node.c +++ b/modules/net/dap_chain_node.c @@ -251,7 +251,9 @@ int dap_chain_node_mempool_process(dap_chain_t *a_chain) if (l_objs_size) { for (size_t i = 0; i < l_objs_size; i++) { dap_chain_datum_t *l_datum = (dap_chain_datum_t *)l_objs[i].value; - if (l_datum->header.type_id != DAP_CHAIN_DATUM_TX) { + if (l_datum->header.type_id != DAP_CHAIN_DATUM_TX && + l_datum->header.type_id != DAP_CHAIN_DATUM_TOKEN_EMISSION && + l_datum->header.type_id != DAP_CHAIN_DATUM_TOKEN_DECL) { continue; } if (a_chain->callback_datums_pool_proc(a_chain, &l_datum, 1) != 1) { diff --git a/modules/net/srv/dap_chain_net_srv_order.c b/modules/net/srv/dap_chain_net_srv_order.c index c88b08b506..4066893697 100644 --- a/modules/net/srv/dap_chain_net_srv_order.c +++ b/modules/net/srv/dap_chain_net_srv_order.c @@ -227,6 +227,7 @@ char * dap_chain_net_srv_order_create( if (a_ext_size) { l_order = (dap_chain_net_srv_order_t *)DAP_NEW_Z_SIZE(void, sizeof(dap_chain_net_srv_order_t) + a_ext_size); memcpy(l_order->ext, a_ext, a_ext_size); + l_order->ext_size = a_ext_size; } else { l_order = DAP_NEW_Z(dap_chain_net_srv_order_t); diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c index 7d4668c517..3bf646077c 100644 --- a/modules/service/xchange/dap_chain_net_srv_xchange.c +++ b/modules/service/xchange/dap_chain_net_srv_xchange.c @@ -22,6 +22,7 @@ along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. */ +#include "dap_string.h" #include "dap_chain_common.h" #include "dap_chain_node_cli.h" #include "dap_chain_mempool.h" @@ -91,7 +92,7 @@ static bool dap_chain_net_srv_xchange_verificator(dap_chain_tx_out_cond_t *a_con { /* Check only one of following conditions for verification success * 1. addr(a_cond.params).data.key == a_tx.sign.pkey -- for condition owner - * 2. a_cond.srv_xchange.value & token == a_tx.out.value & token -- for exchange + * 2. a_cond.srv_xchange.(value && token && addr) == a_tx.out.(value && token && addr) -- for exchange */ dap_chain_addr_t *l_seller_addr = (dap_chain_addr_t *)a_cond->params; dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_SIG, NULL); @@ -103,20 +104,21 @@ static bool dap_chain_net_srv_xchange_verificator(dap_chain_tx_out_cond_t *a_con return true; } else { dap_list_t *l_list_out = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT, NULL); - dap_list_t *l_list_tmp = l_list_out; + uint64_t l_out_val = 0; - while (l_list_tmp) { + for (dap_list_t *l_list_tmp = l_list_out;l_list_tmp; l_list_tmp = l_list_tmp->next) { dap_chain_tx_out_t *l_tx_out = (dap_chain_tx_out_t *)l_list_tmp->data; - if (!strcmp(l_tx_out->token, a_cond->subtype.srv_xchange.token)) { - l_out_val += l_tx_out->header.value; + if (memcmp(&l_tx_out->addr, &a_cond->params, sizeof(dap_chain_addr_t)) || + strcmp(l_tx_out->token, a_cond->subtype.srv_xchange.token)) { + continue; } - l_list_tmp = l_list_tmp->next; + l_out_val += l_tx_out->header.value; } - if (l_out_val == a_cond->subtype.srv_xchange.value) { - return true; + if (l_out_val != a_cond->subtype.srv_xchange.value) { + return false; } } - return false; + return true; } static dap_chain_datum_tx_t *s_xchange_create_tx_request(dap_chain_net_srv_xchange_price_t *a_price) @@ -143,7 +145,7 @@ static dap_chain_datum_tx_t *s_xchange_create_tx_request(dap_chain_net_srv_xchan // add 'in' items to sell uint64_t l_value_to_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out); dap_list_free_full(l_list_used_out, free); - if (l_value_to_items == l_value_sell) { + if (l_value_to_items != l_value_sell) { dap_chain_datum_tx_delete(l_tx); log_it(L_ERROR, "Can't compose the transaction input"); return NULL; @@ -152,9 +154,9 @@ static dap_chain_datum_tx_t *s_xchange_create_tx_request(dap_chain_net_srv_xchan // add 'out_cond' & 'out' items { dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_XCHANGE_ID }; - dap_chain_tx_out_cond_t *l_tx_out = dap_chain_datum_tx_item_out_cond_create_srv_xchange(l_uid, a_price->net_buy->pub.id, - a_price->token_buy, a_price->datoshi_buy, - (void *)l_seller_addr, sizeof (dap_chain_addr_t)); + dap_chain_tx_out_cond_t *l_tx_out = dap_chain_datum_tx_item_out_cond_create_srv_xchange(l_uid, a_price->net_sell->pub.id, + a_price->token_sell, a_price->datoshi_sell, + (void *)l_seller_addr, sizeof(dap_chain_addr_t)); if (!l_tx_out) { dap_chain_datum_tx_delete(l_tx); log_it(L_ERROR, "Can't compose the transaction conditional output"); @@ -205,23 +207,35 @@ static dap_chain_datum_tx_t *s_xchange_create_tx_exchange(dap_chain_net_srv_xcha return NULL; } + // create and add reciept + uint32_t l_ext_size = sizeof(uint64_t) + DAP_CHAIN_TICKER_SIZE_MAX; + uint8_t *l_ext = DAP_NEW_SIZE(uint8_t, l_ext_size); + dap_lendian_put64(l_ext, a_price->datoshi_sell); + strcpy((char *)&l_ext[sizeof(uint64_t)], a_price->token_sell); + dap_chain_net_srv_price_unit_uid_t l_unit = { .uint32 = SERV_UNIT_UNDEFINED}; + dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_XCHANGE_ID }; + dap_chain_datum_tx_receipt_t *l_receipt = dap_chain_datum_tx_receipt_create(l_uid, l_unit, 0, a_price->datoshi_buy, + l_ext, l_ext_size); + dap_chain_datum_tx_add_item(&l_tx, (byte_t *)l_receipt); + DAP_DELETE(l_receipt); // add 'in' items to sell uint64_t l_value_to_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out); - uint32_t l_next_in_idx = dap_list_length(l_list_used_out); dap_list_free_full(l_list_used_out, free); - if (l_value_to_items == l_value_sell) { + if (l_value_to_items != l_value_sell) { dap_chain_datum_tx_delete(l_tx); log_it(L_ERROR, "Can't compose the transaction input"); return NULL; } // add 'in' item to buy from conditional transaction - dap_chain_datum_tx_add_in_item(&l_tx, a_tx_cond_hash, l_next_in_idx); + int l_prev_cond_idx = 0; + dap_chain_datum_tx_t *l_cond_tx = dap_chain_ledger_tx_find_by_hash(l_ledger, a_tx_cond_hash); + dap_chain_tx_out_cond_t *l_tx_out_cond = (dap_chain_tx_out_cond_t *)dap_chain_datum_tx_item_get( + l_cond_tx, &l_prev_cond_idx, TX_ITEM_TYPE_OUT_COND, NULL); + dap_chain_datum_tx_add_in_cond_item(&l_tx, a_tx_cond_hash, l_prev_cond_idx, 0); // add 'out' items { // transfer selling coins - dap_chain_datum_tx_t* l_cond_tx = dap_chain_ledger_tx_find_by_hash(l_ledger, a_tx_cond_hash); - dap_chain_tx_out_cond_t *l_tx_out_cond = (dap_chain_tx_out_cond_t *)dap_chain_datum_tx_item_get(l_cond_tx, NULL, TX_ITEM_TYPE_OUT_COND, NULL); const dap_chain_addr_t *l_buyer_addr = (dap_chain_addr_t *)l_tx_out_cond->params; uint64_t l_buying_value = l_tx_out_cond->header.value; dap_chain_tx_out_t *l_tx_out = dap_chain_datum_tx_item_out_create(l_buyer_addr, a_price->datoshi_sell, a_price->token_sell); @@ -279,7 +293,10 @@ static bool s_xchange_tx_put(dap_chain_datum_tx_t *a_tx, dap_chain_net_t *a_net) size_t l_tx_size = dap_chain_datum_tx_get_size(a_tx); dap_chain_datum_t *l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_TX, a_tx, l_tx_size); DAP_DELETE(a_tx); - dap_chain_t *l_chain = dap_chain_net_get_chain_by_chain_type(a_net, DAP_CHAIN_DATUM_TX); + dap_chain_t *l_chain = dap_chain_net_get_chain_by_chain_type(a_net, CHAIN_TYPE_TX); + if (!l_chain) { + return false; + } dap_chain_node_role_t l_role = dap_chain_net_get_role(a_net); size_t l_datums_number; switch (l_role.enums) { @@ -391,6 +408,7 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c dap_chain_node_cli_set_reply_text(a_str_reply, "Format -datoshi_sell <unsigned long long>"); return -9; } + dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-datoshi_buy", &l_val_buy_str); if (!l_val_buy_str) { dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'price create' required parameter -datoshi_buy"); return -8; @@ -455,6 +473,7 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c DAP_DELETE(l_order_hash_str); break; } + dap_chain_node_cli_set_reply_text(a_str_reply, "Successfully created order %s", l_order_hash_str); DAP_DELETE(l_order_hash_str); // Add active price to pricelist HASH_ADD_KEYPTR(hh, s_srv_xchange->pricelist, l_price->key_ptr, strlen(l_price->key_ptr), l_price); @@ -471,13 +490,12 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c if (l_cmd_num == CMD_REMOVE) { HASH_DEL(s_srv_xchange->pricelist, l_price); DAP_DELETE(l_price->key_ptr); - DAP_DELETE(l_price); + dap_chain_wallet_close(l_price->wallet); //TODO invalidate transaction //TODO delete order (l_price->order); - DAP_DELETE(l_price); } else { // CMD_UPDATE const char *l_val_sell_str = NULL, *l_val_buy_str = NULL, *l_wallet_str = NULL; @@ -540,17 +558,19 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c } break; case CMD_LIST: { dap_chain_net_srv_xchange_price_t *l_price = NULL, *l_tmp; + dap_string_t *l_reply_str = dap_string_new(""); HASH_ITER(hh, s_srv_xchange->pricelist, l_price, l_tmp) { - *a_str_reply = dap_strdup_printf("%s\t%s\t%s\t%s\t%lu\t%lu\t%s\n", l_price->token_sell, l_price->net_sell->pub.name, - l_price->token_buy, l_price->net_buy->pub.name, l_price->datoshi_sell, - l_price->datoshi_buy, l_price->wallet->name); - } - if (!l_price) { - dap_chain_node_cli_set_reply_text(a_str_reply, "Pricelist is empty"); + char *l_order_hash_str = dap_chain_hash_fast_to_str_new(&l_price->order_hash); + dap_string_append_printf(l_reply_str, "%s\t%s\t%s\t%s\t%lu\t%lu\t%s\t%s\n", l_price->token_sell, l_price->net_sell->pub.name, + l_price->token_buy, l_price->net_buy->pub.name, l_price->datoshi_sell, + l_price->datoshi_buy, l_price->wallet->name, l_order_hash_str); + DAP_DELETE(l_order_hash_str); } + dap_chain_node_cli_set_reply_text(a_str_reply, *l_reply_str->str ? "Pricelist is empty" : l_reply_str->str); + dap_string_free(l_reply_str, true); } break; default: { - dap_chain_node_cli_set_reply_text(a_str_reply, "Subcommand %s not recognized", a_argv[a_arg_index + 1]); + dap_chain_node_cli_set_reply_text(a_str_reply, "Subcommand %s not recognized", a_argv[a_arg_index]); return -4; } } @@ -579,7 +599,7 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void *a_arg_func, char * } switch (l_cmd_num) { case CMD_PRICE: - return s_cli_srv_xchange_price(a_argc, a_argv, l_arg_index, a_str_reply); + return s_cli_srv_xchange_price(a_argc, a_argv, l_arg_index + 1, a_str_reply); case CMD_PURCHASE: { const char *l_net_str = NULL, *l_wallet_str = 0; dap_chain_node_cli_find_option_val(a_argv, ++l_arg_index + 1, a_argc, "-net", &l_net_str); @@ -612,12 +632,17 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void *a_arg_func, char * l_price->net_sell = l_net; strcpy(l_price->token_sell, (char *)&l_order->ext[sizeof(uint64_t)]); l_price->datoshi_sell = dap_lendian_get64(l_order->ext); + l_price->wallet = l_wallet; // Create conditional transaction dap_chain_datum_tx_t *l_tx = s_xchange_create_tx_exchange(l_price, &l_order->tx_cond_hash); if (l_tx) { s_xchange_tx_put(l_tx, l_net); } DAP_DELETE(l_price); + // TODO delete the order + DAP_DELETE(l_order); + dap_chain_node_cli_set_reply_text(a_str_reply, l_tx ? "Exchange transaction has done" : + "Exchange transaction error"); } } break; case CMD_ENABLE: { -- GitLab