From d32a4b624b1cc31fb0367280a2c46bab00edd801 Mon Sep 17 00:00:00 2001
From: "Dmitriy A. Gerasimov" <dmitriy.gerasimov@demlabs.net>
Date: Tue, 5 Nov 2019 14:32:20 +0700
Subject: [PATCH] [*] Fixed small bugs [+] Added 'price_token' and 'direction'
 fields to order

---
 dap_chain_net_srv.c        | 96 ++++++++++++++++++++++++++++++++------
 dap_chain_net_srv_common.h |  7 +++
 dap_chain_net_srv_order.c  | 25 ++++++++--
 dap_chain_net_srv_order.h  | 13 ++++--
 4 files changed, 118 insertions(+), 23 deletions(-)

diff --git a/dap_chain_net_srv.c b/dap_chain_net_srv.c
index 5012e43..e89a225 100755
--- a/dap_chain_net_srv.c
+++ b/dap_chain_net_srv.c
@@ -83,15 +83,15 @@ int dap_chain_net_srv_init(void)
         return -1;
 
     dap_chain_node_cli_cmd_item_create ("net_srv", s_cli_net_srv, "Network services managment",
-        "net_srv -net <chain net name> order find [-srv_uid <Service UID>] [-srv_class <Service Class>] [-price_unit <price unit>]\\\n"
-        "                                         [-price_min <Price minimum>] [-price_max <Price maximum>]\n"
+        "net_srv -net <chain net name> order find [-direction <sell|buy>][-srv_uid <Service UID>] [-srv_class <Service Class>] [-price_unit <price unit>]\\\n"
+        "                                         [-price_token <Token ticker>] [-price_min <Price minimum>] [-price_max <Price maximum>]\n"
         "\tOrders list, all or by UID and/or class\n"
         "net_srv -net <chain net name> order delete -hash <Order hash>\n"
         "\tOrder delete\n"
         "net_srv -net <chain net name> order dump -hash <Order hash>\n"
         "\tOrder dump info\n"
-        "net_srv -net <chain net name> order create -srv_uid <Service UID> -srv_class <Service Class> -price <Price>\\\n"
-        "        -price_unit <Price Unit> -node_addr <Node Address> -tx_cond <TX Cond Hash> \\\n"
+        "net_srv -net <chain net name> order create -direction <sell|buy> -srv_uid <Service UID> -srv_class <Service Class> -price <Price>\\\n"
+        "        -price_unit <Price Unit> -price_ticker <Token ticker> -node_addr <Node Address> -tx_cond <TX Cond Hash> \\\n"
         "        [-expires <Unix time when expires>]\\\n"
         "\tOrder create\n" );
 
@@ -128,7 +128,14 @@ static int s_cli_net_srv( int argc, char **argv, char **a_str_reply)
         dap_string_t *l_string_ret = dap_string_new("");
         const char *l_order_str = NULL;
         dap_chain_node_cli_find_option_val(argv, arg_index, argc, "order", &l_order_str);
-        if ( strcmp( l_order_str, "find" ) == 0 ){
+        if ( l_order_str == NULL){
+            dap_string_append_printf( l_string_ret, "Expected subcommand. Variants: find, dump, create, delete\n");
+            ret=-3;
+        } else if ( strcmp( l_order_str, "find" ) == 0 ){
+
+            // Order direction
+            const char *l_direction_str = NULL;
+            dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-direction", &l_direction_str);
 
             // Select with specified service uid
             const char *l_srv_uid_str = NULL;
@@ -142,6 +149,10 @@ static int s_cli_net_srv( int argc, char **argv, char **a_str_reply)
             const char*  l_price_unit_str = NULL;
             dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-price_unit", &l_price_unit_str);
 
+            // Token ticker
+            const char*  l_price_token_str = NULL;
+            dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-price_token", &l_price_token_str);
+
             // Select with price not more than price_min
             const char*  l_price_min_str = NULL;
             dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-price_min", &l_price_min_str);
@@ -150,19 +161,36 @@ static int s_cli_net_srv( int argc, char **argv, char **a_str_reply)
             const char*  l_price_max_str = NULL;
             dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-price_max", &l_price_max_str);
 
+            dap_chain_net_srv_order_direction_t l_direction = SERV_DIR_UNDEFINED;
             dap_chain_net_srv_uid_t l_srv_uid={{0}};
             dap_chain_net_srv_class_t l_srv_class= SERV_CLASS_UNDEFINED;
             uint64_t l_price_min=0, l_price_max =0 ;
             dap_chain_net_srv_price_unit_uid_t l_price_unit={{0}};
 
-            l_srv_uid.uint64 = (uint128_t) atoll( l_srv_uid_str);
-            l_srv_class = (dap_chain_net_srv_class_t) atoi( l_srv_class_str );
-            l_price_min = (uint64_t) atoll ( l_price_min_str );
-            l_price_max = (uint64_t) atoll ( l_price_max_str );
-            l_price_unit.uint32 = (uint32_t) atol ( l_price_unit_str );
+            if ( l_direction_str ){
+                if ( strcmp(l_direction_str, "sell")==0)
+                    l_direction = SERV_DIR_SELL;
+                else if ( strcmp(l_direction_str, "buy")==0)
+                    l_direction = SERV_DIR_BUY;
+            }
+
+            if ( l_srv_uid_str)
+                l_srv_uid.uint64 = (uint128_t) atoll( l_srv_uid_str);
+
+            if ( l_srv_class_str )
+                l_srv_class = (dap_chain_net_srv_class_t) atoi( l_srv_class_str );
+
+            if ( l_price_min_str )
+                l_price_min = (uint64_t) atoll ( l_price_min_str );
+
+            if ( l_price_max_str )
+                l_price_max = (uint64_t) atoll ( l_price_max_str );
+            if ( l_price_unit_str)
+                l_price_unit.uint32 = (uint32_t) atol ( l_price_unit_str );
+
             dap_chain_net_srv_order_t * l_orders;
             size_t l_orders_size =0;
-            if( dap_chain_net_srv_order_find_all_by( l_net,l_srv_uid,l_srv_class,l_price_unit,l_price_min, l_price_max,&l_orders,&l_orders_size) == 0 ){
+            if( dap_chain_net_srv_order_find_all_by( l_net, l_direction,l_srv_uid,l_srv_class,l_price_unit,l_price_min, l_price_max,&l_orders,&l_orders_size) == 0 ){
                 dap_string_append_printf(l_string_ret,"Found %u orders:\n",l_orders_size);
                 for (size_t i = 0; i< l_orders_size; i++){
                     dap_chain_net_srv_order_dump_to_string(l_orders+i,l_string_ret);
@@ -188,8 +216,28 @@ static int s_cli_net_srv( int argc, char **argv, char **a_str_reply)
                     dap_string_append_printf(l_string_ret,"Can't find order with hash %s\n", l_order_hash_str );
                 }
             } else{
-                ret = -6 ;
-                dap_string_append(l_string_ret,"need -hash param to obtain what the order we need to dump\n");
+
+                dap_chain_net_srv_order_t * l_orders;
+                size_t l_orders_size =0;
+                dap_chain_net_srv_uid_t l_srv_uid={{0}};
+                dap_chain_net_srv_class_t l_srv_class= SERV_CLASS_UNDEFINED;
+                uint64_t l_price_min=0, l_price_max =0 ;
+                dap_chain_net_srv_price_unit_uid_t l_price_unit={{0}};
+                dap_chain_net_srv_order_direction_t l_direction = SERV_DIR_UNDEFINED;
+                char l_price_token[DAP_CHAIN_TICKER_SIZE_MAX]={0};
+
+
+                if( dap_chain_net_srv_order_find_all_by( l_net,l_direction,l_srv_uid,l_srv_class,l_price_unit, l_price_token, l_price_min, l_price_max,&l_orders,&l_orders_size) == 0 ){
+                    dap_string_append_printf(l_string_ret,"Found %u orders:\n",l_orders_size);
+                    for (size_t i = 0; i< l_orders_size; i++){
+                        dap_chain_net_srv_order_dump_to_string(l_orders+i,l_string_ret);
+                        dap_string_append(l_string_ret,"\n");
+                    }
+                    ret = 0;
+                }else{
+                    ret = -5 ;
+                    dap_string_append(l_string_ret,"Can't get orders: some internal error or wrong params\n");
+                }
             }
         }else if( strcmp( l_order_str, "delete" ) == 0 ){
             // Select with specified service uid
@@ -208,6 +256,10 @@ static int s_cli_net_srv( int argc, char **argv, char **a_str_reply)
                 dap_string_append(l_string_ret,"need -hash param to obtain what the order we need to dump\n");
             }
         }else if( strcmp( l_order_str, "create" ) == 0 ){
+            // Order direction
+            const char *l_direction_str = NULL;
+            dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-direction", &l_direction_str);
+
             const char* l_srv_uid_str = NULL;
             dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-srv_uid", &l_srv_uid_str);
 
@@ -229,6 +281,9 @@ static int s_cli_net_srv( int argc, char **argv, char **a_str_reply)
             const char*  l_price_unit_str = NULL;
             dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-price_unit", &l_price_unit_str);
 
+            const char*  l_price_token_str = NULL;
+            dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-price_token", &l_price_token_str);
+
             const char*  l_comments = NULL;
             dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-comments", &l_comments);
 
@@ -239,7 +294,17 @@ static int s_cli_net_srv( int argc, char **argv, char **a_str_reply)
                 dap_chain_hash_fast_t l_tx_cond_hash={{0}};
                 dap_chain_time_t l_expires=0; // TS when the service expires
                 uint64_t l_price=0;
+                char l_price_token[DAP_CHAIN_TICKER_SIZE_MAX]={0};
                 dap_chain_net_srv_price_unit_uid_t l_price_unit={{0}};
+                dap_chain_net_srv_order_direction_t l_direction = SERV_DIR_UNDEFINED;
+                if ( l_direction_str ){
+                    if ( strcmp(l_direction_str, "sell")==0)
+                        l_direction = SERV_DIR_SELL;
+                    else if ( strcmp(l_direction_str, "buy")==0)
+                        l_direction = SERV_DIR_BUY;
+                }
+
+
                 if (l_expires_str)
                     l_expires = (dap_chain_time_t ) atoll( l_expires_str);
                 l_srv_uid.uint64 = (uint64_t) atoll( l_srv_uid_str);
@@ -249,8 +314,9 @@ static int s_cli_net_srv( int argc, char **argv, char **a_str_reply)
                 l_price = (uint64_t) atoll ( l_price_str );
                 l_price_unit.uint32 = (uint32_t) atol ( l_price_unit_str );
 
-                char * l_order_new_hash_str = dap_chain_net_srv_order_create (
-                            l_net, l_srv_uid, l_srv_class, l_node_addr,l_tx_cond_hash, l_price, l_price_unit, l_expires,l_comments);
+                char * l_order_new_hash_str = dap_chain_net_srv_order_create(
+                            l_net,l_direction, l_srv_uid, l_srv_class, l_node_addr,l_tx_cond_hash, l_price, l_price_unit,
+                            l_price_token, l_expires,l_comments);
                 if (l_order_new_hash_str)
                     dap_string_append_printf( l_string_ret, "Created order %s\n", l_order_new_hash_str);
                 else{
diff --git a/dap_chain_net_srv_common.h b/dap_chain_net_srv_common.h
index c2b467a..f8cf389 100755
--- a/dap_chain_net_srv_common.h
+++ b/dap_chain_net_srv_common.h
@@ -61,6 +61,13 @@ typedef enum {
     SERV_CLASS_UNDEFINED = 0
 } dap_chain_net_srv_class_t;
 
+//Service direction
+typedef enum dap_chain_net_srv_order_direction{
+    SERV_DIR_BUY = 0x01,
+    SERV_DIR_SELL = 0x02,
+    SERV_DIR_UNDEFINED = 0x00
+} dap_chain_net_srv_order_direction_t;
+
 //Types of services
 enum {
     SERV_ID_VPN = 1,
diff --git a/dap_chain_net_srv_order.c b/dap_chain_net_srv_order.c
index 642eab1..872a173 100644
--- a/dap_chain_net_srv_order.c
+++ b/dap_chain_net_srv_order.c
@@ -50,12 +50,14 @@ void dap_chain_net_srv_order_deinit()
 
 char* dap_chain_net_srv_order_create(
         dap_chain_net_t * a_net,
+        dap_chain_net_srv_order_direction_t a_direction,
         dap_chain_net_srv_uid_t a_srv_uid, // Service UID
         dap_chain_net_srv_class_t a_srv_class, //Class of service (once or permanent)
         dap_chain_node_addr_t a_node_addr, // Node address that servs the order (if present)
         dap_chain_hash_fast_t a_tx_cond_hash, // Hash index of conditioned transaction attached with order
         uint64_t a_price, //  service price in datoshi, for SERV_CLASS_ONCE ONCE for the whole service, for SERV_CLASS_PERMANENT  for one unit.
         dap_chain_net_srv_price_unit_uid_t a_price_unit, // Unit of service (seconds, megabytes, etc.) Only for SERV_CLASS_PERMANENT
+        char a_price_ticker[DAP_CHAIN_TICKER_SIZE_MAX],
         dap_chain_time_t a_expires, // TS when the service expires
         const char * a_ext
         )
@@ -71,6 +73,7 @@ char* dap_chain_net_srv_order_create(
         memcpy(&l_order->tx_cond_hash, &a_tx_cond_hash, DAP_CHAIN_HASH_FAST_SIZE);
         l_order->price = a_price;
         l_order->price_unit = a_price_unit;
+        strncpy(l_order->price_ticker, a_price_ticker,sizeof(l_order->price_ticker)-1);
         if ( a_ext)
             strncpy(l_order->ext, a_ext, sizeof ( l_order->ext)-1 );
 
@@ -129,8 +132,10 @@ dap_chain_net_srv_order_t * dap_chain_net_srv_order_find_by_hash_str(dap_chain_n
  * @param a_output_orders_count
  * @return
  */
-int dap_chain_net_srv_order_find_all_by(dap_chain_net_t * a_net, dap_chain_net_srv_uid_t a_srv_uid, dap_chain_net_srv_class_t a_srv_class,
-                                        dap_chain_net_srv_price_unit_uid_t a_price_unit, uint64_t a_price_min, uint64_t a_price_max,
+int dap_chain_net_srv_order_find_all_by(dap_chain_net_t * a_net,const dap_chain_net_srv_order_direction_t a_direction,
+                                        const dap_chain_net_srv_uid_t a_srv_uid,const dap_chain_net_srv_class_t a_srv_class,
+                                        const dap_chain_net_srv_price_unit_uid_t a_price_unit,const char a_price_ticker[DAP_CHAIN_TICKER_SIZE_MAX],
+                                        const uint64_t a_price_min, const uint64_t a_price_max,
                                         dap_chain_net_srv_order_t ** a_output_orders, size_t * a_output_orders_count)
 {
     if ( a_net && a_output_orders && a_output_orders_count ){
@@ -142,8 +147,12 @@ int dap_chain_net_srv_order_find_all_by(dap_chain_net_t * a_net, dap_chain_net_s
         size_t l_order_passed_index;
 lb_order_pass:
         l_order_passed_index =0;
-        for (size_t i; i< l_orders_count; i++){
+        for (size_t i=0; i< l_orders_count; i++){
             dap_chain_net_srv_order_t * l_order = (dap_chain_net_srv_order_t *) l_orders[i].value;
+            // Check direction
+            if (a_direction != SERV_DIR_UNDEFINED )
+                if ( l_order->direction == a_direction )
+                    continue;
             // Check srv uid
             if ( a_srv_uid.uint64)
                 if ( l_order->srv_uid.uint64 != a_srv_uid.uint64 )
@@ -164,6 +173,10 @@ lb_order_pass:
             if ( a_price_max )
                 if ( l_order->price > a_price_max )
                     continue;
+            // Check ticker
+            if ( a_price_ticker )
+                if ( strcmp( l_order->price_ticker, a_price_ticker) == 0 )
+                    continue;
             if( !l_order_pass_first ){
                 memcpy(a_output_orders[l_order_passed_index], l_order, sizeof (dap_chain_net_srv_order_t));
             }
@@ -217,6 +230,12 @@ void dap_chain_net_srv_order_dump_to_string(dap_chain_net_srv_order_t *a_order,d
         dap_string_append_printf(a_str_out, "== Order %s ==\n", l_hash_str);
         dap_string_append_printf(a_str_out, "  version:          %u\n", a_order->version );
 
+        switch ( a_order->direction) {
+            case SERV_DIR_UNDEFINED: dap_string_append_printf(a_str_out, "  direction:        SERV_DIR_UNDEFINED\n" ); break;
+            case SERV_DIR_SELL: dap_string_append_printf(a_str_out, "  direction:        SERV_DIR_SELL\n" ); break;
+            case SERV_DIR_BUY: dap_string_append_printf(a_str_out, "  direction:        SERV_DIR_BUY\n" ); break;
+        }
+
         switch ( a_order->srv_class) {
             case SERV_CLASS_ONCE: dap_string_append_printf(a_str_out, "  srv_class:        SERV_CLASS_ONCE\n" ); break;;
             case SERV_CLASS_PERMANENT: dap_string_append_printf(a_str_out, "  srv_class:        SERV_CLASS_PERMANENT\n" ); break;
diff --git a/dap_chain_net_srv_order.h b/dap_chain_net_srv_order.h
index bdbdf1d..bf58ce3 100644
--- a/dap_chain_net_srv_order.h
+++ b/dap_chain_net_srv_order.h
@@ -34,15 +34,16 @@ typedef struct dap_chain_net_srv_order
     uint16_t version;
     dap_chain_net_srv_uid_t srv_uid; // Service UID
     dap_chain_net_srv_class_t srv_class:8; //Class of service (once or permanent)
+    dap_chain_net_srv_order_direction_t direction:8; // Order direction - SELL or PURCHASE
     dap_chain_node_addr_t node_addr; // Node address that servs the order (if present)
     dap_chain_hash_fast_t tx_cond_hash; // Hash index of conditioned transaction attached with order
-    uint64_t price; //  service price in datoshi, for SERV_CLASS_ONCE ONCE for the whole service, for SERV_CLASS_PERMANENT  for one unit.
     dap_chain_net_srv_price_unit_uid_t price_unit; // Unit of service (seconds, megabytes, etc.) Only for SERV_CLASS_PERMANENT
-    char ticker[DAP_CHAIN_TICKER_SIZE_MAX]; // Token ticker to pay for service
     dap_chain_time_t ts_created;
     dap_chain_time_t ts_expires;
+    uint64_t price; //  service price in datoshi, for SERV_CLASS_ONCE ONCE for the whole service, for SERV_CLASS_PERMANENT  for one unit.
+    char price_ticker[DAP_CHAIN_TICKER_SIZE_MAX]; // Token ticker to pay for service
     char ext[128];
-} dap_chain_net_srv_order_t;
+} DAP_ALIGN_PACKED dap_chain_net_srv_order_t;
 
 // Init/deinit should be call only if private
 int dap_chain_net_srv_order_init(void);
@@ -59,8 +60,8 @@ DAP_STATIC_INLINE dap_chain_net_srv_order_t * dap_chain_net_srv_order_find_by_ha
     }
 }
 
-int dap_chain_net_srv_order_find_all_by(dap_chain_net_t * a_net,dap_chain_net_srv_uid_t a_srv_uid, dap_chain_net_srv_class_t a_srv_class,
-                                        dap_chain_net_srv_price_unit_uid_t a_price_unit, uint64_t a_price_min, uint64_t a_price_max,
+int dap_chain_net_srv_order_find_all_by(dap_chain_net_t * a_net,const dap_chain_net_srv_order_direction_t a_direction, const dap_chain_net_srv_uid_t a_srv_uid, const dap_chain_net_srv_class_t a_srv_class,
+                                        const dap_chain_net_srv_price_unit_uid_t a_price_unit, const char a_price_ticker[DAP_CHAIN_TICKER_SIZE_MAX],const uint64_t a_price_min, const uint64_t a_price_max,
                                         dap_chain_net_srv_order_t ** a_output_orders, size_t * a_output_orders_count);
 int dap_chain_net_srv_order_delete_by_hash_str( dap_chain_net_t * a_net,const char * a_hash_str );
 
@@ -79,12 +80,14 @@ DAP_STATIC_INLINE int dap_chain_net_srv_order_delete_by_hash(dap_chain_net_t * a
 
 char* dap_chain_net_srv_order_create(
         dap_chain_net_t * a_net,
+        dap_chain_net_srv_order_direction_t a_direction,
         dap_chain_net_srv_uid_t a_srv_uid, // Service UID
         dap_chain_net_srv_class_t a_srv_class, //Class of service (once or permanent)
         dap_chain_node_addr_t a_node_addr, // Node address that servs the order (if present)
         dap_chain_hash_fast_t a_tx_cond_hash, // Hash index of conditioned transaction attached with order
         uint64_t a_price, //  service price in datoshi, for SERV_CLASS_ONCE ONCE for the whole service, for SERV_CLASS_PERMANENT  for one unit.
         dap_chain_net_srv_price_unit_uid_t a_price_unit, // Unit of service (seconds, megabytes, etc.) Only for SERV_CLASS_PERMANENT
+        char a_price_ticker[DAP_CHAIN_TICKER_SIZE_MAX],
         dap_chain_time_t a_expires, // TS when the service expires
         const char * a_comments
         );
-- 
GitLab