protected override async Task ProcessRequestAsync(HttpWebRequest request, Dictionary <string, object> payload)
 {
     if (CanMakeAuthenticatedRequest(payload))
     {
         string payloadForm = CryptoUtility.GetFormForPayload(payload, false);
         request.Headers["API-Key"] = PublicApiKey.ToUnsecureString();
         request.Headers["Sign"]    = CryptoUtility.SHA256Sign(payloadForm, PrivateApiKey.ToBytes()).ToUpperInvariant();
         await request.WriteToRequestAsync(payloadForm);
     }
 }
示例#2
0
 protected override async Task ProcessRequestAsync(HttpWebRequest request, Dictionary <string, object> payload)
 {
     if (CanMakeAuthenticatedRequest(payload))
     {
         string form = CryptoUtility.GetFormForPayload(payload);
         request.Headers["Key"]  = PublicApiKey.ToUnsecureString();
         request.Headers["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))
     {
         // 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    = HttpUtility.ParseQueryString(url.Query);
         string newQuery = "timestamp=" + payload["nonce"].ToStringInvariant() + (query.Count == 0 ? string.Empty : "&" + query.ToString()) +
                           (payload.Count > 1 ? "&" + CryptoUtility.GetFormForPayload(payload, false) : string.Empty);
         string signature = CryptoUtility.SHA256Sign(newQuery, CryptoUtility.ToBytes(PrivateApiKey));
         newQuery += "&signature=" + signature;
         url.Query = newQuery;
         return(url.Uri);
     }
     return(base.ProcessRequestUrl(url, payload, method));
 }
        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);
            }
        }
示例#5
0
        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);
                }
            }
        }
示例#6
0
        /// <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 symbol = null)
        {
            // Find order detail
            ExchangeOrderResult order = await GetOrderDetailsAsync(orderId, symbol);

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

            var payload = await OnGetNoncePayloadAsync();

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

            payload["amount"] = order.Amount;
            payload["price"]  = order.Price;
            payload["symbol"] = order.Symbol;
            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
        }
示例#8
0
        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);
        }
示例#9
0
        protected override async Task ProcessRequestAsync(HttpWebRequest 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.ToBytes(PrivateApiKey)).ToLower();
                request.Headers.Add("Sign", sig);
                request.Headers.Add("Key", PublicApiKey.ToUnsecureString());

                using (Stream stream = await request.GetRequestStreamAsync())
                {
                    byte[] content = Encoding.UTF8.GetBytes(msg);
                    stream.Write(content, 0, content.Length);
                }
            }
        }
示例#10
0
        protected override async Task <IEnumerable <ExchangeOrderResult> > OnGetCompletedOrderDetailsAsync(string symbol = 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 OnGetNoncePayloadAsync();

            if (symbol != null)
            {
                payload["symbol"] = symbol;
            }

            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);
        }
示例#11
0
        protected override async Task ProcessRequestAsync(HttpWebRequest request, Dictionary <string, object> payload)
        {
            if (CanMakeAuthenticatedRequest(payload))
            {
                request.Headers.Add("KC-API-KEY", PublicApiKey.ToUnsecureString());
                request.Headers.Add("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(Encoding.UTF8.GetBytes(message)), PrivateApiKey.ToUnsecureString());

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

                if (request.Method == "POST")
                {
                    string msg = CryptoUtility.GetFormForPayload(payload, false);
                    using (Stream stream = await request.GetRequestStreamAsync())
                    {
                        byte[] content = Encoding.UTF8.GetBytes(msg);
                        stream.Write(content, 0, content.Length);
                    }
                }
            }
        }
示例#12
0
        protected override async Task <IEnumerable <ExchangeOrderResult> > OnGetOpenOrderDetailsAsync(string symbol = 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 OnGetNoncePayloadAsync();

            if (symbol != null)
            {
                payload["symbol"] = symbol;
            }

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

            if (token != null && token.HasValues)
            {
                foreach (JToken order in token["BUY"])
                {
                    orders.Add(ParseOpenOrder(order));
                }
                foreach (JToken order in token["SELL"])
                {
                    orders.Add(ParseOpenOrder(order));
                }
            }
            return(orders);
        }
示例#13
0
        /// <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="symbol"></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 symbol, int periodSeconds, DateTime?startDate = null, DateTime?endDate = null, int?limit = null)
        {
            List <MarketCandle> candles = new List <MarketCandle>();

            string periodString;

            if (periodSeconds <= 60)
            {
                periodString = "1"; periodSeconds = 60;
            }
            else if (periodSeconds <= 300)
            {
                periodString = "5"; periodSeconds = 300;
            }
            else if (periodSeconds <= 900)
            {
                periodString = "15"; periodSeconds = 900;
            }
            else if (periodSeconds <= 1800)
            {
                periodString = "30"; periodSeconds = 1800;
            }
            else if (periodSeconds <= 3600)
            {
                periodString = "60"; periodSeconds = 3600;
            }
            else if (periodSeconds <= 86400)
            {
                periodString = "D"; periodSeconds = 86400;
            }
            else
            {
                periodString = "W"; periodSeconds = 604800;
            }

            endDate   = endDate ?? DateTime.UtcNow;
            startDate = startDate ?? DateTime.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 OnGetNoncePayloadAsync();

            payload.Add("symbol", symbol);
            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            = symbol,
                        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>(),
                        ConvertedVolume = token["v"][i].ConvertInvariant <decimal>(),
                        BaseVolume      = token["v"][i].ConvertInvariant <decimal>() * token["c"][i].ConvertInvariant <decimal>()
                    });
                }
            }
            return(candles);
        }
        protected override async Task <IEnumerable <ExchangeTransaction> > OnGetDepositHistoryAsync(string symbol)
        {
            symbol = NormalizeSymbol(symbol);
            List <ExchangeTransaction> deposits = new List <ExchangeTransaction>();

            var payload = await OnGetNoncePayloadAsync();

            payload.Add("start", DateTime.UtcNow.AddYears(-1).UnixTimestampFromDateTimeMilliseconds()); // required. Arbitrarily going with 1 year
            payload.Add("end", DateTime.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 OnGetNoncePayloadAsync());

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

            return(deposits);
        }
        /// <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)
        {
            symbol = NormalizeSymbol(symbol);
            List <ExchangeOrderResult> orders = new List <ExchangeOrderResult>();
            var payload = await OnGetNoncePayloadAsync();

            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 OnGetNoncePayloadAsync());

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

            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 OnGetNoncePayloadAsync());

            foreach (JToken order in token)
            {
                orders.Add(ParseClientOrder(order));
            }
            return(orders);
        }