diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c index 64c463ef26a9bb90905582b74c1c95f293def162..5d979b7f03b9ea2615bb0d270cca3b951a81d6de 100644 --- a/modules/chain/dap_chain_ledger.c +++ b/modules/chain/dap_chain_ledger.c @@ -222,6 +222,23 @@ int dap_chain_ledger_token_decl_add_check(dap_ledger_t * a_ledger, dap_chain_da return 0; } +/** + * @brief dap_chain_ledger_token_ticker_check + * @param a_ledger + * @param a_token_ticker + * @return + */ +int dap_chain_ledger_token_ticker_check(dap_ledger_t * a_ledger, const char *a_token_ticker) +{ + if ( !a_ledger){ + log_it(L_WARNING, "NULL ledger, can't find token ticker"); + return -2; + } + 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; +} + /** * @brief dap_chain_ledger_token_add * @param a_token diff --git a/modules/chain/include/dap_chain_ledger.h b/modules/chain/include/dap_chain_ledger.h index 4dbcedb0f5e0069968b5fedc21287e461a30149a..ef12be2f30a35c0b1412588867fc608d065ee002 100644 --- a/modules/chain/include/dap_chain_ledger.h +++ b/modules/chain/include/dap_chain_ledger.h @@ -82,6 +82,13 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx); int dap_chain_ledger_tx_add_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx); +/** + * Check token ticker existance + * + */ + +int dap_chain_ledger_token_ticker_check(dap_ledger_t * a_ledger, const char *a_token_ticker); + /** * Add new token datum * diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c index f59eba9a1eedf47de7567302877dba12581859c3..67283c416ffb87c20b45f6c706fb858a40a03e28 100644 --- a/modules/service/xchange/dap_chain_net_srv_xchange.c +++ b/modules/service/xchange/dap_chain_net_srv_xchange.c @@ -43,14 +43,16 @@ static dap_chain_net_srv_xchange_t *s_srv_xchange; */ int dap_chain_net_srv_xchange_init() { - dap_chain_node_cli_cmd_item_create ("srv_xchange", s_cli_srv_xchange, NULL, "eXchange service commands", - "srv_xchange price create -net_sell <net name> -token_sell <token ticker> -net_buy <net_name> -token_buy <token ticker> -rate <value> -wallet <name>\n" - "\tCreate a new price with rate value = token_sell : token_buy\n" + dap_chain_node_cli_cmd_item_create("srv_xchange", s_cli_srv_xchange, NULL, "eXchange service commands", + "srv_xchange price create -net_sell <net name> -token_sell <token ticker> -net_buy <net_name> -token_buy <token ticker>" + "-wallet <name> -datoshi_sell <value> -datoshi_buy <value>\n" + "\tCreate a new price with specified amounts of datoshi to exchange\n" "srv_xchange price remove -net_sell <net name> -token_sell <token ticker> -net_buy <net_name> -token_buy <token ticker>\n" "\tRemove price with specified tickers within specified net names\n" "srv_xchange price list\n" "\tList all active prices\n" - "srv_xchange price update -net_sell <net name> -token_sell <token ticker> -net_buy <net_name> -token_buy <token ticker> {-rate <value> | -wallet <name>}\n" + "srv_xchange price update -net_sell <net name> -token_sell <token ticker> -net_buy <net_name> -token_buy <token ticker>" + "{-datoshi_sell <value> | datoshi_buy <value> | -wallet <name>}\n" "\tUpdate price with specified tickers within specified net names\n" "srv_xchange purchase <order hash> -net <net name>\n" "\tExchange tokens with specified order within specified net name\n" @@ -96,7 +98,6 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c const char *l_net_sell_str = NULL, *l_net_buy_str = NULL; const char *l_token_sell_str = NULL, *l_token_buy_str = NULL; dap_chain_net_t *l_net_sell = NULL, *l_net_buy = NULL; - char l_token_sell[DAP_CHAIN_TICKER_SIZE_MAX], l_token_buy[DAP_CHAIN_TICKER_SIZE_MAX]; char *l_strkey; if (l_cmd_num == CMD_CREATE || l_cmd_num == CMD_REMOVE || l_cmd_num == CMD_UPDATE) { dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-net_sell", &l_net_sell_str); @@ -127,18 +128,25 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c l_cmd_num == CMD_CREATE ? "create" : (l_cmd_num == CMD_REMOVE ? "remove" : "update")); return -5; } - strncpy(l_token_sell, l_token_sell_str, DAP_CHAIN_TICKER_SIZE_MAX - 1); + if (!dap_chain_ledger_token_ticker_check(l_net_sell->pub.ledger, l_token_sell_str)) { + dap_chain_node_cli_set_reply_text(a_str_reply, "Token ticker %s not found", l_token_sell_str); + return -6; + } dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-token_buy", &l_token_buy_str); if (!l_token_buy_str) { dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'price %s' required parameter -token_buy", l_cmd_num == CMD_CREATE ? "create" : (l_cmd_num == CMD_REMOVE ? "remove" : "update")); return -5; } - strncpy(l_token_buy, l_token_buy_str, DAP_CHAIN_TICKER_SIZE_MAX - 1); - l_strkey = DAP_NEW_SIZE(char, dap_strlen(l_token_sell) + dap_strlen(l_net_sell_str) + dap_strlen(l_token_buy) + dap_strlen(l_net_buy_str) + 1); - dap_stpcpy(l_strkey, l_token_sell); + if (!dap_chain_ledger_token_ticker_check(l_net_sell->pub.ledger, l_token_buy_str)) { + dap_chain_node_cli_set_reply_text(a_str_reply, "Token ticker %s not found", l_token_buy_str); + return -6; + } + l_strkey = DAP_NEW_SIZE(char, dap_strlen(l_token_sell_str) + dap_strlen(l_net_sell_str) + + dap_strlen(l_token_buy_str) + dap_strlen(l_net_buy_str) + 1); + dap_stpcpy(l_strkey, l_token_sell_str); strcat(l_strkey, l_net_sell_str); - strcat(l_strkey, l_token_buy); + strcat(l_strkey, l_token_buy_str); strcat(l_strkey, l_net_buy_str); } switch (l_cmd_num) { @@ -149,19 +157,28 @@ 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, "Price with provided pair of token ticker + net name already exist"); return -7; } - const char *l_rate_str = NULL, *l_wallet_str = NULL; - dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-rate", &l_rate_str); - if (!l_rate_str) { - dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'price create' required parameter -rate"); + const char *l_val_sell_str = NULL, *l_val_buy_str = NULL, *l_wallet_str = NULL; + dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-datoshi_sell", &l_val_sell_str); + if (!l_val_sell_str) { + dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'price create' required parameter -datoshi_sell"); return -8; } - long double l_rate = strtold(l_rate_str, NULL); - if (!l_rate) { - dap_chain_node_cli_set_reply_text(a_str_reply, "Format -rate <long double>"); + uint64_t l_datoshi_sell = strtoull(l_val_sell_str, NULL, 10); + if (!l_datoshi_sell) { + dap_chain_node_cli_set_reply_text(a_str_reply, "Format -datoshi_sell <unsigned long long>"); return -9; } - dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-wallet", &l_rate_str); - if (!l_rate_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; + } + uint64_t l_datoshi_buy = strtoull(l_val_buy_str, NULL, 10); + if (!l_datoshi_buy) { + dap_chain_node_cli_set_reply_text(a_str_reply, "Format -datoshi_buy <unsigned long long>"); + return -9; + } + dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-wallet", &l_wallet_str); + if (!l_wallet_str) { dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'price create' required parameter -wallet"); return -10; } @@ -171,13 +188,20 @@ 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, "Specified wallet not found"); return -11; } + if (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 anough cash in specified wallet"); + dap_chain_wallet_close(l_wallet); + return -12; + } l_price = DAP_NEW_Z(dap_chain_net_srv_xchange_price_t); l_price->wallet = l_wallet; - dap_stpcpy(l_price->token_sell, l_token_sell); + dap_stpcpy(l_price->token_sell, l_token_sell_str); l_price->net_sell = l_net_sell; - dap_stpcpy(l_price->token_buy, l_token_buy); + dap_stpcpy(l_price->token_buy, l_token_buy_str); l_price->net_buy = l_net_buy; l_price->key_ptr = l_strkey; + l_price->datoshi_sell = l_datoshi_sell; + l_price->datoshi_buy = l_datoshi_buy; //TODO create the order HASH_ADD_KEYPTR(hh, s_srv_xchange->pricelist, l_price->key_ptr, strlen(l_price->key_ptr), l_price); } break; @@ -190,10 +214,56 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c HASH_DEL(s_srv_xchange->pricelist, l_price); DAP_DELETE(l_price->key_ptr); dap_chain_wallet_close(l_price->wallet); - dap_cain_net_srv_order_delete(l_price->order); + //TODO delete order (l_price->order); DAP_DELETE(l_price); - } else { - //TODO update price + } else { // CMD_UPDATE + const char *l_val_sell_str = NULL, *l_val_buy_str = NULL, *l_wallet_str = NULL; + uint64_t l_datoshi_sell = 0, l_datoshi_buy = 0; + dap_chain_wallet_t *l_wallet = NULL; + dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-datoshi_sell", &l_val_sell_str); + if (l_val_sell_str) { + l_datoshi_sell = strtoull(l_val_sell_str, NULL, 10); + if (!l_datoshi_sell) { + dap_chain_node_cli_set_reply_text(a_str_reply, "Format -datoshi_sell <unsigned long long>"); + return -9; + } + } + if (l_val_buy_str) { + l_datoshi_buy = strtoull(l_val_buy_str, NULL, 10); + if (!l_datoshi_buy) { + dap_chain_node_cli_set_reply_text(a_str_reply, "Format -datoshi_buy <unsigned long long>"); + return -9; + } + } + dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-wallet", &l_wallet_str); + if (l_wallet_str) { + const char *l_wallets_path = dap_chain_wallet_get_path(g_config); + l_wallet = dap_chain_wallet_open(l_wallet_str, l_wallets_path); + 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_buy_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 anough 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_buy_str) { + l_price->datoshi_buy = l_datoshi_buy; + } + if (l_wallet_str) { + dap_chain_wallet_close(l_price->wallet); + l_price->wallet = l_wallet; + } + //TODO update order } } else { dap_chain_node_cli_set_reply_text(a_str_reply, "Price with provided pair of token ticker + net name is not exist"); 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 a9ea65c49b465a0a671e7bfdd8f23387d0cba5b7..16bfe0dfaccbef2fe3735673147883728966032e 100644 --- a/modules/service/xchange/include/dap_chain_net_srv_xchange.h +++ b/modules/service/xchange/include/dap_chain_net_srv_xchange.h @@ -33,9 +33,10 @@ typedef struct dap_chain_net_srv_xchange_price { dap_chain_wallet_t *wallet; dap_chain_net_t *net_sell; char token_sell[DAP_CHAIN_TICKER_SIZE_MAX]; + uint64_t datoshi_sell; dap_chain_net_t *net_buy; char token_buy[DAP_CHAIN_TICKER_SIZE_MAX]; - long double rate; + uint64_t datoshi_buy; dap_chain_net_srv_order_t *order; char *key_ptr; UT_hash_handle hh; diff --git a/modules/wallet/dap_chain_wallet.c b/modules/wallet/dap_chain_wallet.c index 0b30adb47cf7b59d71787ce167e9df1de6a8b0f6..ac14456bde419486265b174b99dd99f16ae910b8 100644 --- a/modules/wallet/dap_chain_wallet.c +++ b/modules/wallet/dap_chain_wallet.c @@ -412,7 +412,7 @@ dap_chain_wallet_t * dap_chain_wallet_open(const char * a_wallet_name, const cha * @param a_net_id * @return */ -uint64_t dap_chain_wallet_get_balance(dap_chain_wallet_t *a_wallet, dap_chain_net_id_t a_net_id, char *a_token_ticker) +uint64_t dap_chain_wallet_get_balance(dap_chain_wallet_t *a_wallet, dap_chain_net_id_t a_net_id, const char *a_token_ticker) { dap_chain_net_t *l_net = dap_chain_net_by_id(a_net_id); dap_chain_addr_t *l_addr =dap_chain_wallet_get_addr(a_wallet, a_net_id); diff --git a/modules/wallet/include/dap_chain_wallet.h b/modules/wallet/include/dap_chain_wallet.h index c58ca634974a7dc6048d90d9470aba0302ab8f09..86c113f348f7b5dba0fecdb9e64c771d9e804313 100644 --- a/modules/wallet/include/dap_chain_wallet.h +++ b/modules/wallet/include/dap_chain_wallet.h @@ -58,6 +58,6 @@ size_t dap_chain_wallet_get_certs_number( dap_chain_wallet_t * a_wallet); dap_pkey_t * dap_chain_wallet_get_pkey( dap_chain_wallet_t * a_wallet,uint32_t a_key_idx); dap_enc_key_t * dap_chain_wallet_get_key( dap_chain_wallet_t * a_wallet,uint32_t a_key_idx); -uint64_t dap_chain_wallet_get_balance(dap_chain_wallet_t *a_wallet, dap_chain_net_id_t a_net_id, char *a_token_ticker); +uint64_t dap_chain_wallet_get_balance(dap_chain_wallet_t *a_wallet, dap_chain_net_id_t a_net_id, const char *a_token_ticker); int dap_chain_wallet_save_file( dap_chain_wallet_t * a_wallet);