Skip to content
Snippets Groups Projects
Commit a03e3d26 authored by Roman Khlopkov's avatar Roman Khlopkov 🔜
Browse files

[+] Database for pricelist

parent e82bd23e
No related branches found
No related tags found
1 merge request!92features-2844
...@@ -37,6 +37,7 @@ static int s_callback_requested(dap_chain_net_srv_t *a_srv, uint32_t a_usage_id, ...@@ -37,6 +37,7 @@ 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_t *a_srv_client, const void *a_data, size_t a_data_size); static int s_callback_response_success(dap_chain_net_srv_t *a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_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_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_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_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_t *a_srv_client, const void *a_data, size_t a_data_size);
static dap_chain_net_srv_xchange_price_t *s_xchange_db_load(char *a_key, uint8_t *a_item);
static dap_chain_net_srv_xchange_t *s_srv_xchange; static dap_chain_net_srv_xchange_t *s_srv_xchange;
...@@ -71,9 +72,16 @@ int dap_chain_net_srv_xchange_init() ...@@ -71,9 +72,16 @@ int dap_chain_net_srv_xchange_init()
dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_XCHANGE_ID }; dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_XCHANGE_ID };
dap_chain_net_srv_t* l_srv = dap_chain_net_srv_add(l_uid, s_callback_requested, s_callback_response_success, dap_chain_net_srv_t* l_srv = dap_chain_net_srv_add(l_uid, s_callback_requested, s_callback_response_success,
s_callback_response_error, s_callback_receipt_next_success); s_callback_response_error, s_callback_receipt_next_success);
s_srv_xchange = DAP_NEW_Z(dap_chain_net_srv_xchange_t); s_srv_xchange = DAP_NEW_Z(dap_chain_net_srv_xchange_t);
l_srv->_inhertor = s_srv_xchange; l_srv->_inhertor = s_srv_xchange;
s_srv_xchange->enabled = false; s_srv_xchange->enabled = false;
size_t l_prices_count = 0;
dap_global_db_obj_t *l_prices = dap_chain_global_db_gr_load(GROUP_LOCAL_XCHANGE, &l_prices_count);
for (size_t i = 0; i < l_prices_count; i++) {
dap_chain_net_srv_xchange_price_t *l_price = s_xchange_db_load(l_prices[i].key, l_prices[i].value);
HASH_ADD_KEYPTR(hh, s_srv_xchange->pricelist, l_price->key_ptr, strlen(l_price->key_ptr), l_price);
}
dap_chain_global_db_objs_delete(l_prices, l_prices_count);
return 0; return 0;
} }
...@@ -135,11 +143,12 @@ static dap_chain_datum_tx_receipt_t *s_xchage_receipt_create(dap_chain_net_srv_x ...@@ -135,11 +143,12 @@ static dap_chain_datum_tx_receipt_t *s_xchage_receipt_create(dap_chain_net_srv_x
{ {
uint32_t l_ext_size = sizeof(uint64_t) + DAP_CHAIN_TICKER_SIZE_MAX; 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); uint8_t *l_ext = DAP_NEW_SIZE(uint8_t, l_ext_size);
dap_lendian_put64(l_ext, a_price->datoshi_sell); uint64_t l_datoshi_buy = (long double)a_price->datoshi_sell / a_price->rate;
strcpy((char *)&l_ext[sizeof(uint64_t)], a_price->token_sell); dap_lendian_put64(l_ext, l_datoshi_buy);
strcpy((char *)&l_ext[sizeof(uint64_t)], a_price->token_buy);
dap_chain_net_srv_price_unit_uid_t l_unit = { .uint32 = SERV_UNIT_UNDEFINED}; 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_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, dap_chain_datum_tx_receipt_t *l_receipt = dap_chain_datum_tx_receipt_create(l_uid, l_unit, 0, a_price->datoshi_sell,
l_ext, l_ext_size); l_ext, l_ext_size);
return l_receipt; return l_receipt;
} }
...@@ -223,13 +232,14 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha ...@@ -223,13 +232,14 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha
// create empty transaction // create empty transaction
dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create();
dap_ledger_t *l_ledger = dap_chain_ledger_by_net_name(a_price->net_sell->pub.name); dap_ledger_t *l_ledger = dap_chain_ledger_by_net_name(a_price->net_buy->pub.name);
dap_chain_addr_t *l_seller_addr = (dap_chain_addr_t *) dap_chain_wallet_get_addr(a_wallet, a_price->net_sell->pub.id); dap_chain_addr_t *l_seller_addr = (dap_chain_addr_t *)dap_chain_wallet_get_addr(a_wallet, a_price->net_buy->pub.id);
dap_enc_key_t *l_seller_key = dap_chain_wallet_get_key(a_wallet, 0); dap_enc_key_t *l_seller_key = dap_chain_wallet_get_key(a_wallet, 0);
uint64_t l_value_sell = 0; // how many coins to transfer uint64_t l_value_buy = 0; // how many coins to transfer
// list of transaction with 'out' items to sell // list of transaction with 'out' items to sell
dap_list_t *l_list_used_out = dap_chain_ledger_get_list_tx_outs_with_val(l_ledger, a_price->token_sell, uint64_t l_datoshi_buy = ceill(a_price->datoshi_sell / a_price->rate);
l_seller_addr, a_price->datoshi_sell, &l_value_sell); dap_list_t *l_list_used_out = dap_chain_ledger_get_list_tx_outs_with_val(l_ledger, a_price->token_buy,
l_seller_addr, l_datoshi_buy, &l_value_buy);
if(!l_list_used_out) { if(!l_list_used_out) {
dap_chain_datum_tx_delete(l_tx); dap_chain_datum_tx_delete(l_tx);
log_it(L_WARNING, "Nothing to change (not enough funds)"); log_it(L_WARNING, "Nothing to change (not enough funds)");
...@@ -243,7 +253,7 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha ...@@ -243,7 +253,7 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha
// add 'in' items to sell // 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); 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); dap_list_free_full(l_list_used_out, free);
if (l_value_to_items != l_value_sell) { if (l_value_to_items != l_value_buy) {
dap_chain_datum_tx_delete(l_tx); dap_chain_datum_tx_delete(l_tx);
DAP_DELETE(l_seller_addr); DAP_DELETE(l_seller_addr);
log_it(L_ERROR, "Can't compose the transaction input"); log_it(L_ERROR, "Can't compose the transaction input");
...@@ -266,16 +276,16 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha ...@@ -266,16 +276,16 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha
{ {
// transfer selling coins // transfer selling coins
const dap_chain_addr_t *l_buyer_addr = (dap_chain_addr_t *)l_tx_out_cond->params; const dap_chain_addr_t *l_buyer_addr = (dap_chain_addr_t *)l_tx_out_cond->params;
if (dap_chain_datum_tx_add_out_ext_item(&l_tx, l_buyer_addr, a_price->datoshi_sell, a_price->token_sell) == -1) { if (dap_chain_datum_tx_add_out_ext_item(&l_tx, l_buyer_addr, l_datoshi_buy, a_price->token_buy) == -1) {
dap_chain_datum_tx_delete(l_tx); dap_chain_datum_tx_delete(l_tx);
DAP_DELETE(l_seller_addr); DAP_DELETE(l_seller_addr);
log_it(L_ERROR, "Can't add selling coins output"); log_it(L_ERROR, "Can't add selling coins output");
return NULL; return NULL;
} }
// coin back // coin back
uint64_t l_value_back = l_value_sell - a_price->datoshi_sell; uint64_t l_value_back = l_value_buy - l_datoshi_buy;
if (l_value_back) { if (l_value_back) {
if (dap_chain_datum_tx_add_out_ext_item(&l_tx, l_seller_addr, l_value_back, a_price->token_sell) == -1) { if (dap_chain_datum_tx_add_out_ext_item(&l_tx, l_seller_addr, l_value_back, a_price->token_buy) == -1) {
dap_chain_datum_tx_delete(l_tx); dap_chain_datum_tx_delete(l_tx);
DAP_DELETE(l_seller_addr); DAP_DELETE(l_seller_addr);
log_it(L_ERROR, "Can't add selling coins back output"); log_it(L_ERROR, "Can't add selling coins back output");
...@@ -283,7 +293,7 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha ...@@ -283,7 +293,7 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha
} }
} }
//transfer buying coins //transfer buying coins
if (dap_chain_datum_tx_add_out_ext_item(&l_tx, l_seller_addr, a_price->datoshi_buy, a_price->token_buy) == -1) { if (dap_chain_datum_tx_add_out_ext_item(&l_tx, l_seller_addr, a_price->datoshi_sell, a_price->token_sell) == -1) {
dap_chain_datum_tx_delete(l_tx); dap_chain_datum_tx_delete(l_tx);
DAP_DELETE(l_seller_addr); DAP_DELETE(l_seller_addr);
log_it(L_ERROR, "Can't add buying coins output"); log_it(L_ERROR, "Can't add buying coins output");
...@@ -292,9 +302,9 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha ...@@ -292,9 +302,9 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha
DAP_DELETE(l_seller_addr); DAP_DELETE(l_seller_addr);
//transfer unbuying coins (partial exchange) //transfer unbuying coins (partial exchange)
uint64_t l_buying_value = l_tx_out_cond->header.value; uint64_t l_buying_value = l_tx_out_cond->header.value;
l_value_back = l_buying_value - a_price->datoshi_buy; l_value_back = l_buying_value - a_price->datoshi_sell;
if (l_value_back) { if (l_value_back) {
if (dap_chain_datum_tx_add_out_ext_item(&l_tx, l_buyer_addr, l_value_back, a_price->token_buy) == -1) { if (dap_chain_datum_tx_add_out_ext_item(&l_tx, l_buyer_addr, l_value_back, a_price->token_sell) == -1) {
log_it(L_WARNING, "Can't add buying coins back output (cashback)"); log_it(L_WARNING, "Can't add buying coins back output (cashback)");
return NULL; return NULL;
} }
...@@ -337,8 +347,8 @@ static bool s_xchage_tx_invalidate(dap_chain_net_srv_xchange_price_t *a_price, d ...@@ -337,8 +347,8 @@ static bool s_xchage_tx_invalidate(dap_chain_net_srv_xchange_price_t *a_price, d
// create empty transaction // create empty transaction
dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create();
dap_ledger_t *l_ledger = dap_chain_ledger_by_net_name(a_price->net_sell->pub.name); dap_ledger_t *l_ledger = dap_chain_ledger_by_net_name(a_price->net_buy->pub.name);
dap_chain_addr_t *l_seller_addr = (dap_chain_addr_t *) dap_chain_wallet_get_addr(a_wallet, a_price->net_sell->pub.id); dap_chain_addr_t *l_seller_addr = (dap_chain_addr_t *)dap_chain_wallet_get_addr(a_wallet, a_price->net_buy->pub.id);
dap_enc_key_t *l_seller_key = dap_chain_wallet_get_key(a_wallet, 0); dap_enc_key_t *l_seller_key = dap_chain_wallet_get_key(a_wallet, 0);
// create and add reciept // create and add reciept
...@@ -380,7 +390,7 @@ static bool s_xchage_tx_invalidate(dap_chain_net_srv_xchange_price_t *a_price, d ...@@ -380,7 +390,7 @@ static bool s_xchage_tx_invalidate(dap_chain_net_srv_xchange_price_t *a_price, d
log_it( L_ERROR, "Can't add sign output"); log_it( L_ERROR, "Can't add sign output");
return false; return false;
} }
if (!s_xchange_tx_put(l_tx, a_price->net_sell)) { if (!s_xchange_tx_put(l_tx, a_price->net_buy)) {
return false; return false;
} }
return true; return true;
...@@ -399,8 +409,9 @@ char *s_xchange_order_create(dap_chain_net_srv_xchange_price_t *a_price, dap_cha ...@@ -399,8 +409,9 @@ char *s_xchange_order_create(dap_chain_net_srv_xchange_price_t *a_price, dap_cha
dap_chain_node_addr_t *l_node_addr = dap_chain_net_get_cur_addr(a_price->net_sell); dap_chain_node_addr_t *l_node_addr = dap_chain_net_get_cur_addr(a_price->net_sell);
dap_chain_net_srv_price_unit_uid_t l_unit = { .uint32 = SERV_UNIT_UNDEFINED}; 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_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_XCHANGE_ID };
uint64_t l_datoshi_buy = ceill(a_price->datoshi_sell / a_price->rate);
char *l_order_hash_str = dap_chain_net_srv_order_create(a_price->net_buy, SERV_DIR_SELL, l_uid, *l_node_addr, char *l_order_hash_str = dap_chain_net_srv_order_create(a_price->net_buy, SERV_DIR_SELL, l_uid, *l_node_addr,
l_tx_hash, a_price->datoshi_buy, l_unit, a_price->token_buy, 0, l_tx_hash, l_datoshi_buy, l_unit, a_price->token_buy, 0,
(uint8_t *)&l_ext, l_ext_size, NULL, 0); (uint8_t *)&l_ext, l_ext_size, NULL, 0);
return l_order_hash_str; return l_order_hash_str;
} }
...@@ -408,14 +419,49 @@ char *s_xchange_order_create(dap_chain_net_srv_xchange_price_t *a_price, dap_cha ...@@ -408,14 +419,49 @@ char *s_xchange_order_create(dap_chain_net_srv_xchange_price_t *a_price, dap_cha
dap_chain_net_srv_xchange_price_t *s_xchange_price_from_order(dap_chain_net_t *a_net, dap_chain_net_srv_order_t *a_order) dap_chain_net_srv_xchange_price_t *s_xchange_price_from_order(dap_chain_net_t *a_net, dap_chain_net_srv_order_t *a_order)
{ {
dap_chain_net_srv_xchange_price_t *l_price = DAP_NEW_Z(dap_chain_net_srv_xchange_price_t); dap_chain_net_srv_xchange_price_t *l_price = DAP_NEW_Z(dap_chain_net_srv_xchange_price_t);
l_price->net_sell = a_net;
strcpy(l_price->token_sell, a_order->price_ticker);
l_price->datoshi_sell = a_order->price;
dap_srv_xchange_order_ext_t *l_ext = (dap_srv_xchange_order_ext_t *)a_order->ext; dap_srv_xchange_order_ext_t *l_ext = (dap_srv_xchange_order_ext_t *)a_order->ext;
dap_chain_net_id_t l_net_buy_id = { .uint64 = dap_lendian_get64((uint8_t *)&l_ext->net_sell_id) }; dap_chain_net_id_t l_net_buy_id = { .uint64 = dap_lendian_get64((uint8_t *)&l_ext->net_sell_id) };
l_price->net_buy = dap_chain_net_by_id(l_net_buy_id); l_price->net_sell = dap_chain_net_by_id(l_net_buy_id);
l_price->datoshi_buy = dap_lendian_get64((uint8_t *)&l_ext->datoshi_sell); l_price->datoshi_sell = dap_lendian_get64((uint8_t *)&l_ext->datoshi_sell);
strcpy(l_price->token_buy, l_ext->token_sell); strcpy(l_price->token_sell, l_ext->token_sell);
l_price->net_buy = a_net;
strcpy(l_price->token_buy, a_order->price_ticker);
l_price->rate = (long double)l_price->datoshi_sell / a_order->price;
return l_price;
}
static bool s_xchange_db_add(dap_chain_net_srv_xchange_price_t *a_price)
{
size_t l_size = sizeof(dap_chain_net_srv_xchange_db_item_t) + strlen(a_price->wallet_str) + 1;
dap_chain_net_srv_xchange_db_item_t *l_item = DAP_NEW_Z_SIZE(dap_chain_net_srv_xchange_db_item_t, l_size);
strcpy(l_item->token_sell, a_price->token_sell);
strcpy(l_item->token_buy, a_price->token_buy);
l_item->net_sell_id = a_price->net_sell->pub.id.uint64;
l_item->net_buy_id = a_price->net_buy->pub.id.uint64;
l_item->datoshi_sell = a_price->datoshi_sell;
l_item->rate = a_price->rate;
memcpy(&l_item->tx_hash, &a_price->tx_hash, sizeof(dap_chain_hash_fast_t));
memcpy(&l_item->order_hash, &a_price->order_hash, sizeof(dap_chain_hash_fast_t));
strcpy(l_item->wallet_str, a_price->wallet_str);
return dap_chain_global_db_gr_set(dap_strdup(a_price->key_ptr), (uint8_t *)l_item, l_size, GROUP_LOCAL_XCHANGE);
}
static dap_chain_net_srv_xchange_price_t *s_xchange_db_load(char *a_key, uint8_t *a_item)
{
dap_chain_net_srv_xchange_db_item_t *l_item = (dap_chain_net_srv_xchange_db_item_t *)a_item;
dap_chain_net_srv_xchange_price_t *l_price = DAP_NEW_Z(dap_chain_net_srv_xchange_price_t);
strcpy(l_price->key_ptr, a_key);
strcpy(l_price->token_sell, l_item->token_sell);
strcpy(l_price->token_buy, l_item->token_buy);
dap_chain_net_id_t l_id = { .uint64 = l_item->net_sell_id};
l_price->net_sell = dap_chain_net_by_id(l_id);
l_id.uint64 = l_item->net_buy_id;
l_price->net_buy = dap_chain_net_by_id(l_id);
l_price->datoshi_sell = l_item->datoshi_sell;
l_price->rate = l_item->rate;
memcpy(&l_price->tx_hash, &l_item->tx_hash, sizeof(dap_chain_hash_fast_t));
memcpy(&l_price->order_hash, &l_item->order_hash, sizeof(dap_chain_hash_fast_t));
strcpy(l_price->wallet_str, l_item->wallet_str);
return l_price; return l_price;
} }
...@@ -545,24 +591,30 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c ...@@ -545,24 +591,30 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c
l_price->net_buy = l_net_buy; l_price->net_buy = l_net_buy;
l_price->key_ptr = l_strkey; l_price->key_ptr = l_strkey;
l_price->datoshi_sell = l_datoshi_sell; l_price->datoshi_sell = l_datoshi_sell;
l_price->datoshi_buy = l_datoshi_sell / l_rate; l_price->rate = l_rate;
// Create conditional transaction // Create conditional transaction
dap_chain_datum_tx_t *l_tx = s_xchange_tx_create_request(l_price, l_wallet); dap_chain_datum_tx_t *l_tx = s_xchange_tx_create_request(l_price, l_wallet);
dap_chain_wallet_close(l_wallet); dap_chain_wallet_close(l_wallet);
if (!l_tx) { if (!l_tx) {
dap_chain_node_cli_set_reply_text(a_str_reply, "Can't compose the conditional transaction"); dap_chain_node_cli_set_reply_text(a_str_reply, "Can't compose the conditional transaction");
DAP_DELETE(l_price); DAP_DELETE(l_price);
break; return -14;
} }
// Create the order & put it to GDB // Create the order & put it to GDB
char *l_order_hash_str = s_xchange_order_create(l_price, l_tx); char *l_order_hash_str = s_xchange_order_create(l_price, l_tx);
if (l_order_hash_str) { if (l_order_hash_str) {
dap_chain_str_to_hash_fast(l_order_hash_str, &l_price->order_hash); dap_chain_str_to_hash_fast(l_order_hash_str, &l_price->order_hash);
if(!s_xchange_tx_put(l_tx, l_net_buy)) { if(!s_xchange_tx_put(l_tx, l_net_buy)) {
dap_chain_node_cli_set_reply_text(a_str_reply, "Can't put transaction to mempool/chains"); dap_chain_node_cli_set_reply_text(a_str_reply, "Can't put transaction to mempool");
dap_chain_net_srv_order_delete_by_hash_str(l_net_buy, l_order_hash_str);
DAP_DELETE(l_order_hash_str);
return -15;
}
if (!s_xchange_db_add(l_price)) {
dap_chain_node_cli_set_reply_text(a_str_reply, "Can't save price in database");
dap_chain_net_srv_order_delete_by_hash_str(l_net_buy, l_order_hash_str); dap_chain_net_srv_order_delete_by_hash_str(l_net_buy, l_order_hash_str);
DAP_DELETE(l_order_hash_str); DAP_DELETE(l_order_hash_str);
break; return -16;
} }
dap_chain_node_cli_set_reply_text(a_str_reply, "Successfully created order %s", l_order_hash_str); dap_chain_node_cli_set_reply_text(a_str_reply, "Successfully created order %s", l_order_hash_str);
DAP_DELETE(l_order_hash_str); DAP_DELETE(l_order_hash_str);
...@@ -578,121 +630,127 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c ...@@ -578,121 +630,127 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c
case CMD_UPDATE: { case CMD_UPDATE: {
dap_chain_net_srv_xchange_price_t *l_price = NULL; dap_chain_net_srv_xchange_price_t *l_price = NULL;
HASH_FIND_STR(s_srv_xchange->pricelist, l_strkey, l_price); HASH_FIND_STR(s_srv_xchange->pricelist, l_strkey, l_price);
if (l_price) { if (!l_price) {
if (l_cmd_num == CMD_REMOVE) { dap_chain_node_cli_set_reply_text(a_str_reply, "Price with provided pair of token ticker + net name is not exist");
dap_string_t *l_str_reply = dap_string_new(""); return -1;
HASH_DEL(s_srv_xchange->pricelist, l_price); }
dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_price->wallet_str, dap_chain_wallet_get_path(g_config)); if (l_cmd_num == CMD_REMOVE) {
bool l_ret = s_xchage_tx_invalidate(l_price, l_wallet); dap_string_t *l_str_reply = dap_string_new("");
dap_chain_wallet_close(l_wallet); HASH_DEL(s_srv_xchange->pricelist, l_price);
if (!l_ret) { dap_chain_global_db_gr_del(l_price->key_ptr, GROUP_LOCAL_XCHANGE);
char *l_tx_hash_str = dap_chain_hash_fast_to_str_new(&l_price->tx_hash); dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_price->wallet_str, dap_chain_wallet_get_path(g_config));
dap_string_append_printf(l_str_reply, "Can't invalidate transaction %s\n", l_tx_hash_str); bool l_ret = s_xchage_tx_invalidate(l_price, l_wallet);
DAP_DELETE(l_tx_hash_str); dap_chain_wallet_close(l_wallet);
} if (!l_ret) {
char *l_order_hash_str = dap_chain_hash_fast_to_str_new(&l_price->order_hash); char *l_tx_hash_str = dap_chain_hash_fast_to_str_new(&l_price->tx_hash);
if (dap_chain_net_srv_order_delete_by_hash_str(l_price->net_buy, l_order_hash_str)) { dap_string_append_printf(l_str_reply, "Can't invalidate transaction %s\n", l_tx_hash_str);
dap_string_append_printf(l_str_reply, "Can't remove order %s\n", l_order_hash_str); DAP_DELETE(l_tx_hash_str);
} }
DAP_DELETE(l_order_hash_str); char *l_order_hash_str = dap_chain_hash_fast_to_str_new(&l_price->order_hash);
DAP_DELETE(l_price->key_ptr); if (dap_chain_net_srv_order_delete_by_hash_str(l_price->net_buy, l_order_hash_str)) {
DAP_DELETE(l_price->wallet_str); dap_string_append_printf(l_str_reply, "Can't remove order %s\n", l_order_hash_str);
DAP_DELETE(l_price); }
if (!l_str_reply->len) { DAP_DELETE(l_order_hash_str);
dap_string_append(l_str_reply, "Price successfully removed"); DAP_DELETE(l_price->wallet_str);
} DAP_DELETE(l_price);
*a_str_reply = dap_string_free(l_str_reply, false); if (!l_str_reply->len) {
} else { // CMD_UPDATE dap_string_append(l_str_reply, "Price successfully removed");
const char *l_val_sell_str = NULL, *l_val_rate_str = NULL, *l_wallet_str = NULL, *l_new_wallet_str = NULL; }
uint64_t l_datoshi_sell = 0; *a_str_reply = dap_string_free(l_str_reply, false);
long double l_rate = 0; } else { // CMD_UPDATE
dap_chain_wallet_t *l_wallet = NULL; const char *l_val_sell_str = NULL, *l_val_rate_str = NULL, *l_wallet_str = NULL, *l_new_wallet_str = NULL;
dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-coins", &l_val_sell_str); uint64_t l_datoshi_sell = 0;
if (l_val_sell_str) { long double l_rate = 0;
l_datoshi_sell = strtoull(l_val_sell_str, NULL, 10); dap_chain_wallet_t *l_wallet = NULL;
if (!l_datoshi_sell) { dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-coins", &l_val_sell_str);
dap_chain_node_cli_set_reply_text(a_str_reply, "Format -coins <unsigned long long>"); if (l_val_sell_str) {
return -9; l_datoshi_sell = strtoull(l_val_sell_str, NULL, 10);
} if (!l_datoshi_sell) {
} dap_chain_node_cli_set_reply_text(a_str_reply, "Format -coins <unsigned long long>");
dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-rate", &l_val_rate_str); return -9;
if (l_val_rate_str) {
l_rate = strtold(l_val_rate_str, NULL);
if (!l_rate) {
dap_chain_node_cli_set_reply_text(a_str_reply, "Format -rate <long double> = sell / buy");
return -9;
}
}
dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-wallet", &l_new_wallet_str);
l_wallet_str = l_new_wallet_str ? l_new_wallet_str : l_price->wallet_str;
l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config));
if (!l_wallet) {
dap_chain_node_cli_set_reply_text(a_str_reply, "Specified wallet not found");
return -11;
}
if (!l_val_sell_str && !l_val_rate_str && !l_wallet_str) {
dap_chain_node_cli_set_reply_text(a_str_reply, "At least one of updating parameters is mandatory");
return -13;
}
if (l_datoshi_sell && dap_chain_wallet_get_balance(l_wallet, l_net_sell->pub.id, l_token_sell_str) < l_datoshi_sell) {
dap_chain_node_cli_set_reply_text(a_str_reply, "Not enough cash in specified wallet");
dap_chain_wallet_close(l_wallet);
return -12;
}
if (l_val_sell_str) {
l_price->datoshi_sell = l_datoshi_sell;
} }
if (l_val_rate_str) { }
l_price->datoshi_buy = l_price->datoshi_sell / l_rate; dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-rate", &l_val_rate_str);
if (l_val_rate_str) {
l_rate = strtold(l_val_rate_str, NULL);
if (!l_rate) {
dap_chain_node_cli_set_reply_text(a_str_reply, "Format -rate <long double> = sell / buy");
return -9;
} }
// Update the transaction }
dap_chain_datum_tx_t *l_tx = s_xchange_tx_create_request(l_price, l_wallet); dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-wallet", &l_new_wallet_str);
if (l_new_wallet_str) { l_wallet_str = l_new_wallet_str ? l_new_wallet_str : l_price->wallet_str;
l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config));
if (!l_wallet) {
dap_chain_node_cli_set_reply_text(a_str_reply, "Specified wallet not found");
return -11;
}
if (!l_val_sell_str && !l_val_rate_str && !l_wallet_str) {
dap_chain_node_cli_set_reply_text(a_str_reply, "At least one of updating parameters is mandatory");
return -13;
}
if (l_datoshi_sell && dap_chain_wallet_get_balance(l_wallet, l_net_sell->pub.id, l_token_sell_str) < l_datoshi_sell) {
dap_chain_node_cli_set_reply_text(a_str_reply, "Not enough cash in specified wallet");
dap_chain_wallet_close(l_wallet); dap_chain_wallet_close(l_wallet);
l_wallet = dap_chain_wallet_open(l_price->wallet_str, dap_chain_wallet_get_path(g_config)); return -12;
DAP_DELETE(l_price->wallet_str); }
l_price->wallet_str = dap_strdup(l_new_wallet_str); if (l_val_sell_str) {
} l_price->datoshi_sell = l_datoshi_sell;
if (!l_tx) { }
dap_chain_node_cli_set_reply_text(a_str_reply, "Can't compose the conditional transaction"); if (l_val_rate_str) {
break; l_price->rate = l_rate;
} }
HASH_DEL(s_srv_xchange->pricelist, l_price); // Update the transaction
bool l_ret = s_xchage_tx_invalidate(l_price, l_wallet); // may be changed to old price later dap_chain_datum_tx_t *l_tx = s_xchange_tx_create_request(l_price, l_wallet);
if (l_new_wallet_str) {
dap_chain_wallet_close(l_wallet); dap_chain_wallet_close(l_wallet);
if (!l_ret) { l_wallet = dap_chain_wallet_open(l_price->wallet_str, dap_chain_wallet_get_path(g_config));
char *l_tx_hash_str = dap_chain_hash_fast_to_str_new(&l_price->tx_hash); DAP_DELETE(l_price->wallet_str);
dap_chain_node_cli_set_reply_text(a_str_reply, "Can't invalidate transaction %s\n", l_tx_hash_str); l_price->wallet_str = dap_strdup(l_new_wallet_str);
DAP_DELETE(l_tx_hash_str); }
break; if (!l_tx) {
dap_chain_node_cli_set_reply_text(a_str_reply, "Can't compose the conditional transaction");
return -14;
}
HASH_DEL(s_srv_xchange->pricelist, l_price);
dap_chain_global_db_gr_del(l_price->key_ptr, GROUP_LOCAL_XCHANGE);
bool l_ret = s_xchage_tx_invalidate(l_price, l_wallet); // may be changed to old price later
dap_chain_wallet_close(l_wallet);
if (!l_ret) {
char *l_tx_hash_str = dap_chain_hash_fast_to_str_new(&l_price->tx_hash);
dap_chain_node_cli_set_reply_text(a_str_reply, "Can't invalidate transaction %s\n", l_tx_hash_str);
DAP_DELETE(l_tx_hash_str);
return -17;
}
// Update the order
char *l_order_hash_str = dap_chain_hash_fast_to_str_new(&l_price->order_hash);
dap_chain_net_srv_order_delete_by_hash_str(l_price->net_buy, l_order_hash_str);
DAP_DELETE(l_order_hash_str);
l_order_hash_str = s_xchange_order_create(l_price, l_tx);
if (l_order_hash_str) {
dap_chain_str_to_hash_fast(l_order_hash_str, &l_price->order_hash);
if(!s_xchange_tx_put(l_tx, l_net_buy)) {
dap_chain_node_cli_set_reply_text(a_str_reply, "Can't put transaction to mempool");
dap_chain_net_srv_order_delete_by_hash_str(l_net_buy, l_order_hash_str);
DAP_DELETE(l_order_hash_str);
return -15;
} }
// Update the order if (!s_xchange_db_add(l_price)) {
char *l_order_hash_str = dap_chain_hash_fast_to_str_new(&l_price->order_hash); dap_chain_node_cli_set_reply_text(a_str_reply, "Can't save price in database");
dap_chain_net_srv_order_delete_by_hash_str(l_price->net_buy, l_order_hash_str); dap_chain_net_srv_order_delete_by_hash_str(l_net_buy, l_order_hash_str);
DAP_DELETE(l_order_hash_str);
l_order_hash_str = s_xchange_order_create(l_price, l_tx);
if (l_order_hash_str) {
dap_chain_str_to_hash_fast(l_order_hash_str, &l_price->order_hash);
if(!s_xchange_tx_put(l_tx, l_net_buy)) {
dap_chain_node_cli_set_reply_text(a_str_reply, "Can't put transaction to mempool/chains");
dap_chain_net_srv_order_delete_by_hash_str(l_net_buy, l_order_hash_str);
break;
} else {
dap_chain_node_cli_set_reply_text(a_str_reply, "Successfully created order %s", l_order_hash_str);
}
DAP_DELETE(l_order_hash_str); DAP_DELETE(l_order_hash_str);
} else { return -16;
dap_chain_node_cli_set_reply_text(a_str_reply, "Can't compose the order");
DAP_DELETE(l_price->key_ptr);
DAP_DELETE(l_price);
break;
} }
// Update the pricelist dap_chain_node_cli_set_reply_text(a_str_reply, "Successfully created order %s", l_order_hash_str);
HASH_ADD_KEYPTR(hh, s_srv_xchange->pricelist, l_price->key_ptr, strlen(l_price->key_ptr), l_price); DAP_DELETE(l_order_hash_str);
} else {
dap_chain_node_cli_set_reply_text(a_str_reply, "Can't compose the order");
DAP_DELETE(l_price->key_ptr);
DAP_DELETE(l_price);
return -18;
} }
} else { // Update the pricelist
dap_chain_node_cli_set_reply_text(a_str_reply, "Price with provided pair of token ticker + net name is not exist"); HASH_ADD_KEYPTR(hh, s_srv_xchange->pricelist, l_price->key_ptr, strlen(l_price->key_ptr), l_price);
return -1;
} }
} break; } break;
case CMD_LIST: { case CMD_LIST: {
...@@ -700,10 +758,9 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c ...@@ -700,10 +758,9 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c
dap_string_t *l_reply_str = dap_string_new(""); dap_string_t *l_reply_str = dap_string_new("");
HASH_ITER(hh, s_srv_xchange->pricelist, l_price, l_tmp) { HASH_ITER(hh, s_srv_xchange->pricelist, l_price, l_tmp) {
char *l_order_hash_str = dap_chain_hash_fast_to_str_new(&l_price->order_hash); char *l_order_hash_str = dap_chain_hash_fast_to_str_new(&l_price->order_hash);
long double l_rate = (long double)l_price->datoshi_sell / l_price->datoshi_buy;
dap_string_append_printf(l_reply_str, "%s\t%s\t%s\t%s\t%s\t%lu\t%ld\t%s\n", l_order_hash_str, l_price->token_sell, dap_string_append_printf(l_reply_str, "%s\t%s\t%s\t%s\t%s\t%lu\t%ld\t%s\n", l_order_hash_str, l_price->token_sell,
l_price->net_sell->pub.name, l_price->token_buy, l_price->net_buy->pub.name, l_price->net_sell->pub.name, l_price->token_buy, l_price->net_buy->pub.name,
l_price->datoshi_sell, l_rate, l_price->wallet_str); l_price->datoshi_sell, l_price->rate, l_price->wallet_str);
DAP_DELETE(l_order_hash_str); DAP_DELETE(l_order_hash_str);
} }
if (!l_reply_str->len) { if (!l_reply_str->len) {
...@@ -769,10 +826,9 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void *a_arg_func, char * ...@@ -769,10 +826,9 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void *a_arg_func, char *
continue; continue;
// TODO add filters to list (tokens, network, etc.) // TODO add filters to list (tokens, network, etc.)
l_price = s_xchange_price_from_order(l_net, l_order); l_price = s_xchange_price_from_order(l_net, l_order);
long double l_rate = (long double)l_price->datoshi_buy / l_price->datoshi_sell; dap_string_append_printf(l_reply_str, "%s\t%s\t%s\t%s\t%s\t%lu\t%ld\n", l_orders[i].key, l_price->token_sell,
dap_string_append_printf(l_reply_str, "%s\t%s\t%s\t%s\t%s\t%lu\t%ld\n", l_orders[i].key, l_price->token_buy, l_price->net_sell->pub.name, l_price->token_buy, l_price->net_buy->pub.name,
l_price->net_buy->pub.name, l_price->token_sell, l_price->net_sell->pub.name, l_price->datoshi_sell, l_price->rate);
l_price->datoshi_buy, l_rate);
DAP_DELETE(l_price); DAP_DELETE(l_price);
} }
dap_chain_global_db_objs_delete(l_orders, l_orders_count); dap_chain_global_db_objs_delete(l_orders, l_orders_count);
...@@ -783,7 +839,7 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void *a_arg_func, char * ...@@ -783,7 +839,7 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void *a_arg_func, char *
*a_str_reply = dap_string_free(l_reply_str, false); *a_str_reply = dap_string_free(l_reply_str, false);
} break; } break;
case CMD_PURCHASE: { case CMD_PURCHASE: {
const char *l_net_str = NULL, *l_wallet_str = NULL, *l_order_hash_str = NULL, *l_val_buy_str = NULL; const char *l_net_str = NULL, *l_wallet_str = NULL, *l_order_hash_str = NULL, *l_val_sell_str = NULL;
l_arg_index++; l_arg_index++;
dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str); dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str);
if (!l_net_str) { if (!l_net_str) {
...@@ -810,28 +866,24 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void *a_arg_func, char * ...@@ -810,28 +866,24 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void *a_arg_func, char *
dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'purchase' required parameter -order"); dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'purchase' required parameter -order");
return -12; return -12;
} }
dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-coins", &l_val_buy_str); dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-coins", &l_val_sell_str);
if (!l_val_buy_str) { if (!l_val_sell_str) {
dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'price create' required parameter -coins"); dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'price create' required parameter -coins");
return -8; return -8;
} }
uint64_t l_datoshi_buy = strtoull(l_val_buy_str, NULL, 10); uint64_t l_datoshi_sell = strtoull(l_val_sell_str, NULL, 10);
if (!l_datoshi_buy) { if (!l_datoshi_sell) {
dap_chain_node_cli_set_reply_text(a_str_reply, "Format -coins <unsigned long long>"); dap_chain_node_cli_set_reply_text(a_str_reply, "Format -coins <unsigned long long>");
return -9; return -9;
} }
dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_str); dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_str);
if (l_order) { if (l_order) {
dap_chain_net_srv_xchange_price_t *l_price = s_xchange_price_from_order(l_net, l_order); dap_chain_net_srv_xchange_price_t *l_price = s_xchange_price_from_order(l_net, l_order);
if (l_price->datoshi_buy != l_datoshi_buy) { l_price->datoshi_sell = l_datoshi_sell;
long double l_rate = (long double)l_price->datoshi_buy / l_price->datoshi_sell;
l_price->datoshi_buy = l_datoshi_buy;
l_price->datoshi_sell = ceill(l_datoshi_buy * l_rate);
}
// Create conditional transaction // Create conditional transaction
dap_chain_datum_tx_t *l_tx = s_xchange_tx_create_exchange(l_price, &l_order->tx_cond_hash, l_wallet); dap_chain_datum_tx_t *l_tx = s_xchange_tx_create_exchange(l_price, &l_order->tx_cond_hash, l_wallet);
if (l_tx && s_xchange_tx_put(l_tx, l_net)) { if (l_tx && s_xchange_tx_put(l_tx, l_net)) {
// TODO send request to seller to delete order & price // TODO send request to seller to update / delete order & price
dap_chain_net_srv_order_delete_by_hash_str(l_price->net_buy, l_order_hash_str); dap_chain_net_srv_order_delete_by_hash_str(l_price->net_buy, l_order_hash_str);
} }
DAP_DELETE(l_price); DAP_DELETE(l_price);
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "dap_chain_net_srv_order.h" #include "dap_chain_net_srv_order.h"
#define DAP_CHAIN_NET_SRV_XCHANGE_ID 0x2 #define DAP_CHAIN_NET_SRV_XCHANGE_ID 0x2
#define GROUP_LOCAL_XCHANGE "local.xchange"
typedef struct dap_chain_net_srv_xchange_price { typedef struct dap_chain_net_srv_xchange_price {
char *wallet_str; char *wallet_str;
...@@ -36,13 +37,26 @@ typedef struct dap_chain_net_srv_xchange_price { ...@@ -36,13 +37,26 @@ typedef struct dap_chain_net_srv_xchange_price {
uint64_t datoshi_sell; uint64_t datoshi_sell;
dap_chain_net_t *net_buy; dap_chain_net_t *net_buy;
char token_buy[DAP_CHAIN_TICKER_SIZE_MAX]; char token_buy[DAP_CHAIN_TICKER_SIZE_MAX];
uint64_t datoshi_buy; long double rate;
dap_chain_hash_fast_t tx_hash; dap_chain_hash_fast_t tx_hash;
dap_chain_hash_fast_t order_hash; dap_chain_hash_fast_t order_hash;
char *key_ptr; char *key_ptr;
UT_hash_handle hh; UT_hash_handle hh;
} dap_chain_net_srv_xchange_price_t; } dap_chain_net_srv_xchange_price_t;
typedef struct dap_chain_net_srv_xchange_db_item {
char token_sell[DAP_CHAIN_TICKER_SIZE_MAX];
char token_buy[DAP_CHAIN_TICKER_SIZE_MAX];
uint8_t padding[4];
uint64_t net_sell_id;
uint64_t net_buy_id;
uint64_t datoshi_sell;
long double rate;
dap_chain_hash_fast_t tx_hash;
dap_chain_hash_fast_t order_hash;
char wallet_str[];
} DAP_ALIGN_PACKED dap_chain_net_srv_xchange_db_item_t;
typedef struct dap_srv_xchange_order_ext { typedef struct dap_srv_xchange_order_ext {
uint64_t net_sell_id; uint64_t net_sell_id;
uint64_t datoshi_sell; uint64_t datoshi_sell;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment