Beispiel #1
0
        protected override async Task ProcessRequestAsync(IHttpWebRequest request, Dictionary <string, object> payload)
        {
            await inited.Task;
            var query = request.RequestUri.Query.TrimStart('?');

            if (CanMakeAuthenticatedRequest(payload))
            {
                var nonce = payload["nonce"];
                payload.Remove("nonce");
                var body = string.Empty;
                if (payload.Count > 0)
                {
                    body = CryptoUtility.GetFormForPayload(payload);
                    if (query.Length > 0)
                    {
                        query += '&';
                    }
                    query += body;
                }
                string signature = CryptoUtility.SHA256Sign(query, CryptoUtility.ToUnsecureBytesUTF8(PrivateApiKey));
                request.AddHeader("ACCESS-KEY", PublicApiKey.ToUnsecureString());
                request.AddHeader("ACCESS-SIGN", signature);
                request.AddHeader("ACCESS-TIMESTAMP", nonce.ToStringInvariant());
                if (timeWindow != null)
                {
                    request.AddHeader("ACCESS-RECV-WINDOW", timeWindow);
                }

                if (request.Method == "POST")
                {
                    await CryptoUtility.WriteToRequestAsync(request, body);
                }
            }
        }
        //private async Task<IEnumerable<ExchangeOrderResult>> QueryClosedOrdersAsync(string symbol, string path)
        //{
        //    List<ExchangeOrderResult> orders = new List<ExchangeOrderResult>();
        //    JToken result = await MakeJsonRequestAsync<JToken>(path, null, await GetNoncePayloadAsync());
        //    //result = result["closed"];
        //    foreach (JProperty order in result)
        //    {
        //        orders.Add(ParseOrder(order.Name, order.Value));
        //    }


        //    //if (exchangeSymbolToNormalizedSymbol.TryGetValue(symbol, out string normalizedSymbol))
        //    //{
        //    //    foreach (JProperty order in result)
        //    //    {
        //    //        if (normalizedSymbol == null || order.Value["descr"]["pair"].ToStringInvariant() == normalizedSymbol.ToUpperInvariant())
        //    //        {
        //    //            orders.Add(ParseOrder(order.Name, order.Value));
        //    //        }
        //    //    }
        //    //}

        //    return orders;
        //}


        protected override async Task ProcessRequestAsync(IHttpWebRequest request, Dictionary <string, object> payload)
        {
            if (payload == null || PrivateApiKey == null || PublicApiKey == null || !payload.ContainsKey("nonce"))
            {
                await CryptoUtility.WritePayloadFormToRequestAsync(request, payload);
            }
            else
            {
                string nonce = payload["nonce"].ToStringInvariant();
                payload.Remove("nonce");
                string form = CryptoUtility.GetFormForPayload(payload);
                // nonce must be first on Kraken
                form = "nonce=" + nonce + (string.IsNullOrWhiteSpace(form) ? string.Empty : "&" + form);
                using (SHA256 sha256 = SHA256Managed.Create())
                {
                    string hashString  = nonce + form;
                    byte[] sha256Bytes = sha256.ComputeHash(hashString.ToBytesUTF8());
                    byte[] pathBytes   = request.RequestUri.AbsolutePath.ToBytesUTF8();
                    byte[] sigBytes    = new byte[sha256Bytes.Length + pathBytes.Length];
                    pathBytes.CopyTo(sigBytes, 0);
                    sha256Bytes.CopyTo(sigBytes, pathBytes.Length);
                    byte[] privateKey = System.Convert.FromBase64String(CryptoUtility.ToUnsecureString(PrivateApiKey));
                    using (System.Security.Cryptography.HMACSHA512 hmac = new System.Security.Cryptography.HMACSHA512(privateKey))
                    {
                        string sign = System.Convert.ToBase64String(hmac.ComputeHash(sigBytes));
                        request.AddHeader("API-Sign", sign);
                    }
                }
                request.AddHeader("API-Key", CryptoUtility.ToUnsecureString(PublicApiKey));
                await CryptoUtility.WriteToRequestAsync(request, form);
            }
        }
        protected override async Task <IEnumerable <ExchangeOrderResult> > OnGetCompletedOrderDetailsAsync(string marketSymbol = null, DateTime?afterDate = null)
        {
            List <ExchangeOrderResult> orders = new List <ExchangeOrderResult>();
            // "datas": [ {"createdAt": 1508219588000, "amount": 92.79323381, "dealValue": 0.00927932, "dealPrice": 0.0001, "fee": 1e-8,"feeRate": 0, "oid": "59e59ac49bd8d31d09f85fa8", "orderOid": "59e59ac39bd8d31d093d956a", "coinType": "KCS", "coinTypePair": "BTC", "direction": "BUY", "dealDirection": "BUY" }, ... ]
            var payload = await GetNoncePayloadAsync();

            if (string.IsNullOrWhiteSpace(marketSymbol))
            {
                payload["limit"] = 100;
            }
            else
            {
                payload["symbol"] = marketSymbol;
                payload["limit"]  = 20;
            }

            JToken token = await MakeJsonRequestAsync <JToken>("/order/dealt?" + CryptoUtility.GetFormForPayload(payload, false), null, payload);

            if (token != null && token.HasValues)
            {
                foreach (JToken order in token["datas"])
                {
                    orders.Add(ParseCompletedOrder(order));
                }
            }
            return(orders);
        }
Beispiel #4
0
        protected override Uri ProcessRequestUrl(UriBuilder url, Dictionary <string, object> payload, string method)
        {
            if (CanMakeAuthenticatedRequest(payload))
            {
                // must sort case sensitive
                var dict = new SortedDictionary <string, object>(StringComparer.Ordinal)
                {
                    ["Timestamp"]        = CryptoUtility.UnixTimeStampToDateTimeMilliseconds(payload["nonce"].ConvertInvariant <long>()).ToString("s"),
                    ["AccessKeyId"]      = PublicApiKey.ToUnsecureString(),
                    ["SignatureMethod"]  = "HmacSHA256",
                    ["SignatureVersion"] = "2"
                };

                if (method == "GET")
                {
                    foreach (var kv in payload)
                    {
                        dict.Add(kv.Key, kv.Value);
                    }
                }

                string msg    = CryptoUtility.GetFormForPayload(dict, false, false, false);
                string toSign = $"{method}\n{url.Host}\n{url.Path}\n{msg}";

                // calculate signature
                var sign = CryptoUtility.SHA256SignBase64(toSign, PrivateApiKey.ToUnsecureBytesUTF8()).UrlEncode();

                // append signature to end of message
                msg += $"&Signature={sign}";

                url.Query = msg;
            }
            return(url.Uri);
        }
        protected override async Task <IEnumerable <ExchangeOrderResult> > OnGetCompletedOrderDetailsAsync(string marketSymbol = null, DateTime?afterDate = null)
        {
            List <ExchangeOrderResult> orders = new List <ExchangeOrderResult>();
            var payload = await GetNoncePayloadAsync();

            payload["status"] = "done";
            if (string.IsNullOrWhiteSpace(marketSymbol))
            {
            }
            else
            {
                payload["symbol"] = marketSymbol;
            }

            JToken token = await MakeJsonRequestAsync <JToken>("/orders?" + CryptoUtility.GetFormForPayload(payload, false, false), null, payload);

            if (token != null && token.HasValues)
            {
                foreach (JToken order in token["items"])
                {
                    orders.Add(ParseCompletedOrder(order));
                }
            }
            return(orders);
        }
        private string GetPayloadForm(Dictionary <string, object> payload)
        {
            payload["api_key"] = PublicApiKey.ToUnsecureString();
            string form = CryptoUtility.GetFormForPayload(payload, false);
            string sign = form + "&secret_key=" + PrivateApiKey.ToUnsecureString();

            sign = CryptoUtility.MD5Sign(sign);
            return(form + "&sign=" + sign);
        }
 protected override async Task ProcessRequestAsync(IHttpWebRequest request, Dictionary <string, object> payload)
 {
     if (CanMakeAuthenticatedRequest(payload))
     {
         string payloadForm = CryptoUtility.GetFormForPayload(payload, false);
         request.AddHeader("API-Key", PublicApiKey.ToUnsecureString());
         request.AddHeader("Sign", CryptoUtility.SHA256Sign(payloadForm, PrivateApiKey.ToBytesUTF8()).ToUpperInvariant());
         await request.WriteToRequestAsync(payloadForm);
     }
 }
 protected override async Task ProcessRequestAsync(IHttpWebRequest request, Dictionary <string, object> payload)
 {
     if (CanMakeAuthenticatedRequest(payload))
     {
         string form = CryptoUtility.GetFormForPayload(payload);
         request.AddHeader("Key", PublicApiKey.ToUnsecureString());
         request.AddHeader("Sign", CryptoUtility.SHA512Sign(form, PrivateApiKey.ToUnsecureString()));
         request.Method = "POST";
         await CryptoUtility.WriteToRequestAsync(request, form);
     }
 }
        protected override Uri ProcessRequestUrl(UriBuilder url, Dictionary <string, object> payload, string method)
        {
            if (CanMakeAuthenticatedRequest(payload))
            {
                if (!payload.ContainsKey("method"))
                {
                    return(url.Uri);
                }
                method = payload["method"].ToStringInvariant();
                payload.Remove("method");

                var dict = new Dictionary <string, object>
                {
                    ["Timestamp"]        = DateTime.UtcNow.ToString("s"),
                    ["AccessKeyId"]      = PublicApiKey.ToUnsecureString(),
                    ["SignatureMethod"]  = "HmacSHA256",
                    ["SignatureVersion"] = "2"
                };

                string msg = null;
                if (method == "GET")
                {
                    dict = dict.Concat(payload).ToDictionary(x => x.Key, x => x.Value);
                }

                msg = CryptoUtility.GetFormForPayload(dict, false);

                // must sort case sensitive
                msg = string.Join("&", new SortedSet <string>(msg.Split('&'), StringComparer.Ordinal));

                StringBuilder sb = new StringBuilder();
                sb.Append(method).Append("\n")
                .Append(url.Host).Append("\n")
                .Append(url.Path).Append("\n")
                .Append(msg);

                var sign    = CryptoUtility.SHA256SignBase64(sb.ToString(), PrivateApiKey.ToBytesUTF8());
                var signUrl = sign.UrlEncode();
                msg += $"&Signature={signUrl}";

                /*
                 * // Huobi rolled this back, it is no longer needed. Leaving it here in case they change their minds again.
                 * // https://github.com/huobiapi/API_Docs_en/wiki/Signing_API_Requests
                 * // API Authentication Change
                 * var privateSign = GetPrivateSignatureStr(Passphrase.ToUnsecureString(), sign);
                 * var privateSignUrl = privateSign.UrlEncode();
                 * msg += $"&PrivateSignature={privateSignUrl}";
                 */

                url.Query = msg;
            }
            return(url.Uri);
        }
Beispiel #10
0
 protected override async Task ProcessRequestAsync(IHttpWebRequest request, Dictionary <string, object> payload)
 {
     // Only Private APIs are POST and need Authorization
     if (CanMakeAuthenticatedRequest(payload) && request.Method == "POST")
     {
         var msg = CryptoUtility.GetFormForPayload(payload);
         var sig = CryptoUtility.SHA512Sign(msg, PrivateApiKey.ToUnsecureString());
         request.AddHeader("Key", PublicApiKey.ToUnsecureString());
         request.AddHeader("Sign", sig.ToLowerInvariant());
         byte[] content = msg.ToBytesUTF8();
         await request.WriteAllAsync(content, 0, content.Length);
     }
 }
 protected override Uri ProcessRequestUrl(UriBuilder url, Dictionary <string, object> payload, string method)
 {
     if (CanMakeAuthenticatedRequest(payload))
     {
         // payload is ignored, except for the nonce which is added to the url query - bittrex puts all the "post" parameters in the url query instead of the request body
         var    query    = (url.Query ?? string.Empty).Trim('?', '&');
         string newQuery = "timestamp=" + payload["nonce"].ToStringInvariant() + (query.Length != 0 ? "&" + query : string.Empty) +
                           (payload.Count > 1 ? "&" + CryptoUtility.GetFormForPayload(payload, false) : string.Empty);
         string signature = CryptoUtility.SHA256Sign(newQuery, CryptoUtility.ToUnsecureBytesUTF8(PrivateApiKey));
         newQuery += "&signature=" + signature;
         url.Query = newQuery;
         return(url.Uri);
     }
     return(base.ProcessRequestUrl(url, payload, method));
 }
Beispiel #12
0
        protected override async Task ProcessRequestAsync(HttpWebRequest request, Dictionary <string, object> payload)
        {
            if (CanMakeAuthenticatedRequest(payload))
            {
                payload.Remove("nonce");
                payload["api_key"] = PublicApiKey.ToUnsecureString();
                var msg = CryptoUtility.GetFormForPayload(payload, false);
                msg = string.Join("&", new SortedSet <string>(msg.Split('&'), StringComparer.Ordinal));
                var sign = msg + "&secret_key=" + PrivateApiKey.ToUnsecureString();
                sign = CryptoUtility.MD5Sign(sign);
                msg += "&sign=" + sign;

                await CryptoUtility.WriteToRequestAsync(request, msg);
            }
        }
Beispiel #13
0
        protected override async Task ProcessRequestAsync(IHttpWebRequest request, Dictionary <string, object> payload)
        {
            if (CanMakeAuthenticatedRequest(payload))
            {
                // ensure nonce is the last parameter
                string nonce = payload["nonce"].ToStringInvariant();
                payload.Remove("nonce");

                var msg = CryptoUtility.GetFormForPayload(payload) + "&nonce=" + nonce;
                var sig = CryptoUtility.SHA512Sign(msg, CryptoUtility.ToBytesUTF8(PrivateApiKey)).ToLowerInvariant();
                request.AddHeader("Sign", sig);
                request.AddHeader("Key", PublicApiKey.ToUnsecureString());
                byte[] content = msg.ToBytesUTF8();
                await request.WriteAllAsync(content, 0, content.Length);
            }
        }
        protected override async Task ProcessRequestAsync(HttpWebRequest request, Dictionary <string, object> payload)
        {
            // Only Private APIs are POST and need Authorization
            if (CanMakeAuthenticatedRequest(payload) && request.Method == "POST")
            {
                var msg = CryptoUtility.GetFormForPayload(payload);
                var sig = CryptoUtility.SHA512Sign(msg, PrivateApiKey.ToUnsecureString());
                request.Headers.Add("Key", PublicApiKey.ToUnsecureString());
                request.Headers.Add("Sign", sig.ToLower());

                using (Stream stream = await request.GetRequestStreamAsync())
                {
                    byte[] content = Encoding.UTF8.GetBytes(msg);
                    stream.Write(content, 0, content.Length);
                }
            }
        }
        /// <summary>
        /// This is a private call on Kucoin and therefore requires an API Key + API Secret. Calling this without authorization will cause an exception
        /// </summary>
        /// <param name="marketSymbol"></param>
        /// <param name="periodSeconds"></param>
        /// <param name="startDate"></param>
        /// <param name="endDate"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        protected override async Task <IEnumerable <MarketCandle> > OnGetCandlesAsync(string marketSymbol, int periodSeconds, DateTime?startDate = null, DateTime?endDate = null, int?limit = null)
        {
            List <MarketCandle> candles = new List <MarketCandle>();

            string periodString = PeriodSecondsToString(periodSeconds);

            endDate   = endDate ?? CryptoUtility.UtcNow;
            startDate = startDate ?? CryptoUtility.UtcNow.AddDays(-1);

            // this is a little tricky. The call is private, but not a POST. We need the payload for the sig, but also for the uri
            // so, we'll do both... This is the only ExchangeAPI public call (private on Kucoin) like this.
            var payload = await GetNoncePayloadAsync();

            payload.Add("symbol", marketSymbol);
            payload.Add("resolution", periodString);
            payload.Add("from", (long)startDate.Value.UnixTimestampFromDateTimeSeconds());        // the nonce is milliseconds, this is seconds without decimal
            payload.Add("to", (long)endDate.Value.UnixTimestampFromDateTimeSeconds());            // the nonce is milliseconds, this is seconds without decimal
            var addPayload = CryptoUtility.GetFormForPayload(payload, false);

            // The results of this Kucoin API call are also a mess. 6 different arrays (c,t,v,h,l,o) with the index of each shared for the candle values
            // It doesn't use their standard error format...
            JToken token = await MakeJsonRequestAsync <JToken>("/open/chart/history?" + addPayload, null, payload);

            if (token != null && token.HasValues && token["s"].ToStringInvariant() == "ok")
            {
                int childCount = token["c"].Count();
                for (int i = 0; i < childCount; i++)
                {
                    candles.Add(new MarketCandle
                    {
                        ExchangeName        = this.Name,
                        Name                = marketSymbol,
                        PeriodSeconds       = periodSeconds,
                        Timestamp           = DateTimeOffset.FromUnixTimeSeconds(token["t"][i].ConvertInvariant <long>()).DateTime,
                        ClosePrice          = token["c"][i].ConvertInvariant <decimal>(),
                        HighPrice           = token["h"][i].ConvertInvariant <decimal>(),
                        LowPrice            = token["l"][i].ConvertInvariant <decimal>(),
                        OpenPrice           = token["o"][i].ConvertInvariant <decimal>(),
                        BaseCurrencyVolume  = token["v"][i].ConvertInvariant <double>(),
                        QuoteCurrencyVolume = token["v"][i].ConvertInvariant <double>() * token["c"][i].ConvertInvariant <double>()
                    });
                }
            }
            return(candles);
        }
        /// <summary>
        /// This is a private call on Kucoin and therefore requires an API Key + API Secret. Calling this without authorization will cause an exception
        /// </summary>
        /// <param name="marketSymbol"></param>
        /// <param name="periodSeconds"></param>
        /// <param name="startDate"></param>
        /// <param name="endDate"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        protected override async Task <IEnumerable <MarketCandle> > OnGetCandlesAsync(string marketSymbol, int periodSeconds, DateTime?startDate = null, DateTime?endDate = null, int?limit = null)
        {
            List <MarketCandle> candles = new List <MarketCandle>();

            string periodString = PeriodSecondsToString(periodSeconds);

            endDate   = endDate ?? CryptoUtility.UtcNow;
            startDate = startDate ?? CryptoUtility.UtcNow.AddDays(-1);


            var payload = new Dictionary <string, object>
            {
                { "symbol", marketSymbol },
                { "type", periodString },
                { "startAt", (long)startDate.Value.UnixTimestampFromDateTimeSeconds() },       // the nonce is milliseconds, this is seconds without decimal
                { "endAt", (long)endDate.Value.UnixTimestampFromDateTimeSeconds() }            // the nonce is milliseconds, this is seconds without decimal
            };
            var addPayload = CryptoUtility.GetFormForPayload(payload, false);

            // The results of this Kucoin API call are also a mess. 6 different arrays (c,t,v,h,l,o) with the index of each shared for the candle values
            // It doesn't use their standard error format...
            JToken token = await MakeJsonRequestAsync <JToken>("/market/candles?" + addPayload, null, payload);

            if (token != null && token.HasValues && token[0].ToStringInvariant() != null)
            {
                int childCount = token.Count();
                for (int i = 0; i < childCount; i++)
                {
                    candles.Add(new MarketCandle
                    {
                        ExchangeName        = this.Name,
                        Name                = marketSymbol,
                        PeriodSeconds       = periodSeconds,
                        Timestamp           = DateTimeOffset.FromUnixTimeSeconds(token[i][0].ConvertInvariant <long>()).DateTime,
                        OpenPrice           = token[i][1].ConvertInvariant <decimal>(),
                        ClosePrice          = token[i][2].ConvertInvariant <decimal>(),
                        HighPrice           = token[i][3].ConvertInvariant <decimal>(),
                        LowPrice            = token[i][4].ConvertInvariant <decimal>(),
                        BaseCurrencyVolume  = token[i][5].ConvertInvariant <double>(),
                        QuoteCurrencyVolume = token[i][6].ConvertInvariant <double>()
                    });
                }
            }
            return(candles);
        }
        /// <summary>
        /// Must pass the Original Order ID returned from PlaceOrder, not the OrderID returned from GetOrder
        /// </summary>
        /// <param name="orderId">The Original Order Id return from Place Order</param>
        /// <returns></returns>
        protected override async Task OnCancelOrderAsync(string orderId, string marketSymbol = null)
        {
            // Find order detail
            ExchangeOrderResult order = await GetOrderDetailsAsync(orderId, marketSymbol);

            // There is no order to be cancelled
            if (order == null)
            {
                return;
            }

            var payload = await GetNoncePayloadAsync();

            payload["orderOid"] = order.OrderId;
            payload["symbol"]   = order.MarketSymbol;
            payload["type"]     = order.IsBuy ? "BUY" : "SELL";
            JToken token = await MakeJsonRequestAsync <JToken>("/cancel-order?" + CryptoUtility.GetFormForPayload(payload, false), null, payload, "POST");
        }
        protected override async Task <ExchangeOrderResult> OnPlaceOrderAsync(ExchangeOrderRequest order)
        {
            var payload = await GetNoncePayloadAsync();

            payload["amount"] = order.Amount;
            payload["price"]  = order.Price;
            payload["symbol"] = order.MarketSymbol;
            payload["type"]   = order.IsBuy ? "BUY" : "SELL";
            order.ExtraParameters.CopyTo(payload);

            // {"orderOid": "596186ad07015679730ffa02" }
            JToken token = await MakeJsonRequestAsync <JToken>("/order?" + CryptoUtility.GetFormForPayload(payload, false), null, payload, "POST");

            return(new ExchangeOrderResult()
            {
                OrderId = token["orderOid"].ToStringInvariant()
            });                                                                                         // this is different than the oid created when filled
        }
        protected override async Task ProcessRequestAsync(IHttpWebRequest request, Dictionary <string, object> payload)
        {
            if (payload == null || request.Method == "GET")
            {
                return;
            }

            string secret = this.PrivateApiKey.ToUnsecureString();

            payload.Add("secret_key", secret);

            string body = CryptoUtility.GetFormForPayload(payload);
            string sign = CryptoUtility.MD5Sign(body, PrivateApiKey.ToUnsecureBytesUTF8());

            payload.Remove("secret_key");
            payload.Add("sign", sign);
            body = payload.GetFormForPayload();
            await CryptoUtility.WriteToRequestAsync(request, body);
        }
Beispiel #20
0
        /// <summary>
        ///  Get Order by ID or ClientOrderId
        /// </summary>
        /// <param name="orderId"></param>
        /// <returns></returns>
        protected override async Task <ExchangeOrderResult> OnGetOrderDetailsAsync(string orderId, string marketSymbol = null, bool isClientOrderId = false)
        {
            var payload = await GetNoncePayloadAsync();

            JToken token = await MakeJsonRequestAsync <JToken>(
                $"/orders{(isClientOrderId ? "/client-order" : null)}/{orderId}"
                + CryptoUtility.GetFormForPayload(payload, false), null, payload);

            var isActive = token["isActive"].ToObject <bool>();

            if (isActive)
            {
                return(ParseOpenOrder(token));
            }
            else
            {
                return(ParseCompletedOrder(token));
            }
        }
        protected override Uri ProcessRequestUrl(UriBuilder url, Dictionary <string, object> payload, string method)
        {
            if (CanMakeAuthenticatedRequest(payload))
            {
                if (!payload.ContainsKey("method"))
                {
                    return(url.Uri);
                }
                method = payload["method"].ToStringInvariant();
                payload.Remove("method");

                var dict = new Dictionary <string, object>
                {
                    ["Timestamp"]        = DateTime.UtcNow.ToString("s"),
                    ["AccessKeyId"]      = PublicApiKey.ToUnsecureString(),
                    ["SignatureMethod"]  = "HmacSHA256",
                    ["SignatureVersion"] = "2"
                };

                string msg = null;
                if (method == "GET")
                {
                    dict = dict.Concat(payload).ToDictionary(x => x.Key, x => x.Value);
                }

                msg = CryptoUtility.GetFormForPayload(dict, false);

                // must sort case sensitive
                msg = string.Join("&", new SortedSet <string>(msg.Split('&'), StringComparer.Ordinal));

                StringBuilder sb = new StringBuilder();
                sb.Append(method).Append("\n")
                .Append(url.Host).Append("\n")
                .Append(url.Path).Append("\n")
                .Append(msg);

                var sig = CryptoUtility.SHA256SignBase64(sb.ToString(), PrivateApiKey.ToBytes());
                msg += "&Signature=" + Uri.EscapeDataString(sig);

                url.Query = msg;
            }
            return(url.Uri);
        }
        protected override async Task ProcessRequestAsync(IHttpWebRequest request, Dictionary <string, object> payload)
        {
            if (CanMakeAuthenticatedRequest(payload))
            {
                request.AddHeader("KC-API-KEY", PublicApiKey.ToUnsecureString());
                request.AddHeader("KC-API-NONCE", payload["nonce"].ToStringInvariant());

                var endpoint = request.RequestUri.AbsolutePath;
                var message  = string.Format("{0}/{1}/{2}", endpoint, payload["nonce"], CryptoUtility.GetFormForPayload(payload, false));
                var sig      = CryptoUtility.SHA256Sign(Convert.ToBase64String(message.ToBytesUTF8()), PrivateApiKey.ToUnsecureString());

                request.AddHeader("KC-API-SIGNATURE", sig);

                if (request.Method == "POST")
                {
                    string msg     = CryptoUtility.GetFormForPayload(payload, false);
                    byte[] content = msg.ToBytesUTF8();
                    await request.WriteAllAsync(content, 0, content.Length);
                }
            }
        }
        protected override async Task <IEnumerable <ExchangeOrderResult> > OnGetOpenOrderDetailsAsync(string marketSymbol = null)
        {
            List <ExchangeOrderResult> orders = new List <ExchangeOrderResult>();
            // { "SELL": [{ "oid": "59e59b279bd8d31d093d956e", "type": "SELL", "userOid": null, "coinType": "KCS", "coinTypePair": "BTC", "direction": "SELL","price": 0.1,"dealAmount": 0,"pendingAmount": 100, "createdAt": 1508219688000, "updatedAt": 1508219688000 } ... ],
            //   "BUY":  [{ "oid": "59e42bf09bd8d374c9956caa", "type": "BUY",  "userOid": null, "coinType": "KCS", "coinTypePair": "BTC", "direction": "BUY", "price": 0.00009727,"dealAmount": 31.14503, "pendingAmount": 16.94827, "createdAt": 1508125681000, "updatedAt": 1508125681000 } ... ]
            var payload = await GetNoncePayloadAsync();

            payload["status"] = "active";
            if (marketSymbol != null && marketSymbol != "")
            {
                payload["symbol"] = marketSymbol;
            }

            JToken token = await MakeJsonRequestAsync <JToken>("/orders?&" + CryptoUtility.GetFormForPayload(payload, false), null, payload);

            if (token != null && token.HasValues)
            {
                foreach (JToken order in token["items"])
                {
                    orders.Add(ParseOpenOrder(order));
                }
            }
            return(orders);
        }
        /// <summary>
        /// Limited to the last 100 open orders
        /// </summary>
        /// <param name="symbol"></param>
        /// <returns></returns>
        protected override async Task <IEnumerable <ExchangeOrderResult> > OnGetOpenOrderDetailsAsync(string symbol = null)
        {
            List <ExchangeOrderResult> orders = new List <ExchangeOrderResult>();
            var payload = await GetNoncePayloadAsync();

            payload.Add("openClosed", "OPEM");
            if (symbol != null)
            {
                payload.Add("currencyPair", symbol);
            }

            JToken token = await MakeJsonRequestAsync <JToken>("/exchange/client_orders?" + CryptoUtility.GetFormForPayload(payload, false), null, await GetNoncePayloadAsync());

            foreach (JToken order in token)
            {
                orders.Add(ParseClientOrder(order));
            }
            return(orders);
        }
        protected override async Task <IEnumerable <ExchangeOrderResult> > OnGetCompletedOrderDetailsAsync(string symbol = null, DateTime?afterDate = null)
        {
            // We can increase the number of orders returned by including a limit parameter if desired
            List <ExchangeOrderResult> orders = new List <ExchangeOrderResult>();
            var payload = await GetNoncePayloadAsync();

            payload.Add("openClosed", "CLOSED");   // returns both closed and cancelled
            if (symbol != null)
            {
                payload.Add("currencyPair", symbol);
            }
            if (afterDate != null)
            {
                payload.Add("issuedFrom", ((DateTime)afterDate).UnixTimestampFromDateTimeMilliseconds());
            }

            JToken token = await MakeJsonRequestAsync <JToken>("/exchange/client_orders?" + CryptoUtility.GetFormForPayload(payload, false), null, await GetNoncePayloadAsync());

            foreach (JToken order in token)
            {
                orders.Add(ParseClientOrder(order));
            }
            return(orders);
        }
        protected override async Task <IEnumerable <ExchangeTransaction> > OnGetDepositHistoryAsync(string symbol)
        {
            List <ExchangeTransaction> deposits = new List <ExchangeTransaction>();

            var payload = await GetNoncePayloadAsync();

            payload.Add("start", CryptoUtility.UtcNow.AddYears(-1).UnixTimestampFromDateTimeMilliseconds()); // required. Arbitrarily going with 1 year
            payload.Add("end", CryptoUtility.UtcNow.UnixTimestampFromDateTimeMilliseconds());                // also required
            payload.Add("types", "DEPOSIT,WITHDRAWAL");                                                      // opting to return both deposits and withdraws.

            // We can also include trades and orders with this call (which makes 3 ways to return the same data)
            JToken token = await MakeJsonRequestAsync <JToken>("/exchange/payment/history/transactions?" + CryptoUtility.GetFormForPayload(payload, false), null, await GetNoncePayloadAsync());

            foreach (JToken tx in token)
            {
                deposits.Add(ParseTransaction(tx));
            }

            return(deposits);
        }