Beispiel #1
0
        /// <summary>Helper for POSTs</summary>
        private async Task <JToken> PostData(string method, string command, CancellationToken?cancel, Params parameters = null)
        {
            // If called from the UI thread, disable the SynchronisationContext
            // to prevent deadlocks when waiting for Async results.
            using (Task_.NoSyncContext())
            {
                // Poloniex requires the 'nonce' values to be strictly increasing.
                // That means all POSTs must be serialised to avoid a race condition
                // when POSTing two messages in quick succession.
                var cancel_token = CancellationTokenSource.CreateLinkedTokenSource(Shutdown, cancel ?? CancellationToken.None).Token;
                using (RequestThrottle.Lock(cancel_token))                 // Limit requests to the required rate
                {
                    await RequestThrottle.Wait(cancel_token);

                    // Add the command parameter
                    parameters            = parameters ?? new Params();
                    parameters["command"] = command;
                    parameters["nonce"]   = Misc.Nonce;

                    // Create the content to POST
                    var post_data_string = Http_.UrlEncode(parameters).TrimStart('?');
                    var content          = new StringContent(post_data_string, Encoding.UTF8, "application/x-www-form-urlencoded");
                    var msg_hash         = Hasher.ComputeHash(Encoding.UTF8.GetBytes(post_data_string));
                    var signature        = Misc.ToStringHex(msg_hash);
                    content.Headers.Add("Sign", signature);

                    var url = $"{Client.BaseAddress}{method}{Http_.UrlEncode(parameters)}";

                    // Submit the request
                    // Result Codes:
                    //  - 422 Un-processable Entity:
                    //    Status code is directly reported by Poloniex server. It means the server understands the content type of the request entity,
                    //    and the syntax of the request entity is correct, but was unable to process the contained instructions.
                    var response = await Client.PostAsync(url, content, cancel_token);

                    if (!response.IsSuccessStatusCode)
                    {
                        throw new HttpException((int)response.StatusCode, response.ReasonPhrase);
                    }

                    // Interpret the reply
                    var reply = await response.Content.ReadAsStringAsync();

                    return(JToken.Parse(reply));
                }
            }
        }
Beispiel #2
0
        /// <summary>Helper for GETs</summary>
        private async Task <JToken> GetData(string method, string command, CancellationToken?cancel, Params parameters = null)
        {
            // If called from the UI thread, disable the SynchronisationContext
            // to prevent deadlocks when waiting for Async results.
            using (Task_.NoSyncContext())
            {
                var cancel_token = CancellationTokenSource.CreateLinkedTokenSource(Shutdown, cancel ?? CancellationToken.None).Token;
                using (RequestThrottle.Lock(cancel_token))                 // Limit requests to the required rate
                {
                    await RequestThrottle.Wait(cancel_token);

                    // Add the API key for non-public methods
                    parameters = parameters ?? new Params();
                    if (method != Method.Public)
                    {
                        parameters["apikey"] = Key;
                        parameters["nonce"]  = Misc.Nonce;
                    }

                    // Create the URL for the command + parameters
                    var url = $"{UrlRestAddress}api/v1.1/{method}/{command}{Http_.UrlEncode(parameters)}";

                    // Construct the GET request
                    var req = new HttpRequestMessage(HttpMethod.Get, url);
                    if (method != Method.Public)
                    {
                        var hash = Hasher.ComputeHash(Encoding.UTF8.GetBytes(url));
                        req.Headers.Add("apisign", Misc.ToStringHex(hash));
                    }

                    // Submit the request
                    var response = await Client.SendAsync(req, cancel_token);

                    if (!response.IsSuccessStatusCode)
                    {
                        throw new HttpException((int)response.StatusCode, response.ReasonPhrase);
                    }

                    // Interpret the reply
                    var reply = await response.Content.ReadAsStringAsync();

                    return(JToken.Parse(reply));
                }
            }
        }
Beispiel #3
0
        /// <summary>Helper for GETs</summary>
        private async Task <JToken> GetData(string method, string command, CancellationToken?cancel, Params parameters = null)
        {
            // If called from the UI thread, disable the SynchronisationContext
            // to prevent deadlocks when waiting for Async results.
            using (Task_.NoSyncContext())
            {
                // Poloniex requires the 'nonce' values to be strictly increasing.
                // That means all POSTs must be serialised to avoid a race condition
                // when POSTing two messages in quick succession.
                var cancel_token = CancellationTokenSource.CreateLinkedTokenSource(Shutdown, cancel ?? CancellationToken.None).Token;
                using (RequestThrottle.Lock(cancel_token))                 // Limit requests to the required rate
                {
                    await RequestThrottle.Wait(cancel_token);

                    // Add the command to the parameters
                    parameters            = parameters ?? new Params();
                    parameters["command"] = command;

                    // Create the URL for the command + parameters
                    var url = $"{UrlRestAddress}{method}{Http_.UrlEncode(parameters)}";

                    // Submit the request
                    var response = await Client.GetAsync(url, cancel_token);

                    if (!response.IsSuccessStatusCode)
                    {
                        throw new HttpException((int)response.StatusCode, response.ReasonPhrase);
                    }

                    // Interpret the reply
                    var reply = await response.Content.ReadAsStringAsync();

                    return(JToken.Parse(reply));
                }
            }
        }
Beispiel #4
0
        /// <summary>Helper for GETs</summary>
        private async Task <JToken> GetData(HttpMethod method, ESecurityType security, string command, CancellationToken?cancel, Params parameters = null, bool timestamp = false, bool log_trace = false)
        {
            // If called from the UI thread, disable the SynchronisationContext
            // to prevent deadlocks when waiting for Async results.
            using (Task_.NoSyncContext())
            {
                // Poloniex requires the 'nonce' values to be strictly increasing.
                // That means all POSTs must be serialised to avoid a race condition
                // when POSTing two messages in quick succession.
                var cancel_token = CancellationTokenSource.CreateLinkedTokenSource(Shutdown, cancel ?? CancellationToken.None).Token;
                using (RequestThrottle.Lock(cancel_token))                 // Limit requests to the required rate
                {
                    await RequestThrottle.Wait(cancel_token);

                    // Add fields to the request based on 'security'
                    parameters = parameters ?? new Params();
                    if (timestamp)
                    {
                        // Needs to be added after waiting on the throttle
                        parameters["timestamp"] = RequestTimestamp;
                    }
                    if (security == ESecurityType.TRADE || security == ESecurityType.USER_DATA)
                    {
                        var query_string = Http_.UrlEncode(parameters).TrimStart('?');
                        var hash         = Hasher.ComputeHash(Encoding.UTF8.GetBytes(query_string));
                        parameters["signature"] = Misc.ToStringHex(hash);
                    }

                    // Create the request
                    var url = $"{UrlRestAddress}{command}{Http_.UrlEncode(parameters)}";
                    var req = new HttpRequestMessage(method, url);
                    if (security == ESecurityType.TRADE || security == ESecurityType.USER_DATA || security == ESecurityType.USER_STREAM || security == ESecurityType.MARKET_DATA)
                    {
                        req.Headers.Add("X-MBX-APIKEY", Key);
                    }

                    if (log_trace)
                    {
                        Log.Write(ELogLevel.Debug, req.ToString());
                    }

                    // Submit the request
                    var sw       = new Stopwatch().StartNow();
                    var response = await Client.SendAsync(req, cancel_token);

                    var reply = await response.Content.ReadAsStringAsync();

                    Log.Write(ELogLevel.Debug, $"Req time: {sw.Elapsed.ToPrettyString(min_unit: TimeSpan_.ETimeUnits.Milliseconds)} - {url}");

                    if (log_trace)
                    {
                        Log.Write(ELogLevel.Debug, reply.ToString());
                    }

                    // Check the API usage weight
                    if (response.Headers.TryGetValues("X-MBX-USED-WEIGHT", out var weights))
                    {
                        RequestThrottle.UsedWeight = long.Parse(weights.First());
                        if (RequestThrottle.UsedWeight > 0.5 * RequestThrottle.WeightLimit)
                        {
                            Debug.Assert(false);
                        }
                    }

                    // Interpret the reply
                    if (!response.IsSuccessStatusCode)
                    {
                        // Check for an error
                        var jobj = reply != null?JObject.Parse(reply) : null;

                        if (jobj != null &&
                            jobj["code"]?.Value <int>() is int code &&
                            jobj["msg"]?.Value <string>() is string msg)
                        {
                            throw new BinanceException((EErrorCode)code, msg);
                        }
                        else
                        {
                            throw new HttpException((int)response.StatusCode, response.ReasonPhrase);
                        }
                    }

                    return(JToken.Parse(reply));
                }
            }