private HttpRequestMessage CreateRequest(HttpMethod httpMethod, BinanceEndpointData endpoint, string args = null)
        {
            if (endpoint.IsSigned)
            {
                var timestamp = DateTimeOffset.UtcNow.AddMilliseconds(TimestampOffset.TotalMilliseconds)
                                .ToUnixTimeMilliseconds()
                                .ToString();
                var argEnding         = $"recvWindow=60000&timestamp={timestamp}";
                var adjustedSignature = !string.IsNullOrEmpty(args) ? $"{args}&{argEnding}" : $"{argEnding}";

                var signature = CreateSignature(adjustedSignature);

                var completeUri =
                    new Uri($"{Constant.BinanceRestRootUrl}{endpoint.Endpoint}?{adjustedSignature}&signature={signature}");

                var request = new HttpRequestMessage(httpMethod, completeUri);

                return(request);
            }
            else
            {
                var completeUri = $"{Constant.BinanceRestRootUrl}{endpoint.Endpoint}?{args}";

                var request = new HttpRequestMessage(httpMethod, completeUri);

                return(request);
            }
        }
 // TODO: move to interceptor
 private void CacheResponse(BinanceEndpointData endpoint, Type type, BaseResponse response)
 {
     if (endpoint.IsCacheable)
     {
         response.IsCached   = true;
         ResponseCache[type] = response;
     }
 }
        private Task <T> GetCachedResponse <T>(BinanceEndpointData endpoint) where T : class, new()
        {
            return(Task.Run(() =>
            {
                var val = ResponseCache.Get(typeof(T)) as T;

                if (!endpoint.IsCacheable || val == null)
                {
                    return new T();
                }

                return val;
            }));
        }
        private async Task <T> GetResponse <T>(HttpRequestMessage req, BinanceEndpointData endpoint) where T : class, new()
        {
            if (RequestLimitExceeded)
            {
                return(null);
            }

            currentWeigth += endpoint.Weight;
            lastWeigth     = endpoint.Weight;

            if (!endpoint.ShouldByPassThrottle)
            {
                RequestThrottleResetEvent.WaitOne();
                ThrottleIfNecessary();
            }

            string content = null;

            try
            {
                HttpResponseMessage response = null;

                if (req.Method == HttpMethod.Get)
                {
                    response = await HttpClient.GetAsync(req.RequestUri);
                }
                else if (req.Method == HttpMethod.Post)
                {
                    response = await HttpClient.PostAsync(req.RequestUri, req.Content);
                }
                else
                {
                    throw new ArgumentOutOfRangeException(req.Method.ToString());
                }

                content = await response.Content.ReadAsStringAsync();

                if (!response.IsSuccessStatusCode)
                {
                    if (response.StatusCode == (HttpStatusCode)418)
                    {
                        Logger.LogFatal("Binance Rate LIMIT EXCEEDED! IP Banned.");

                        SetRequestLimitExceeded();
                    }
                    else if (response.StatusCode == (HttpStatusCode)429)
                    {
                        Logger.LogFatal("Binance Rate LIMIT EXCEEDED!");

                        SetRequestLimitExceeded();
                    }
                    else
                    {
                        Logger.LogProxy(
                            $"Url: {req.RequestUri.AbsoluteUri} Status: {response.StatusCode} Content: {response.Content} Error: {content}");
                    }

                    return(null);
                }

                RequestLimitExceeded = false;

                return(JsonConvert.DeserializeObject <T>(content));
            }
            catch (Exception ex)
            {
                Logger.LogError($"UnknownError fetching Url: {req.RequestUri.AbsoluteUri} Content: {content}", ex);

                return(null);
            }
        }