예제 #1
0
        /// <summary>
        /// Construct an <see cref="IBinanceApiUser"/> instance providing an API
        /// key and optional API secret. The API secret is not required for
        /// the user stream methods, but is required for other account methods.
        /// </summary>
        /// <param name="apiKey">The user's API key.</param>
        /// <param name="apiSecret">The user's API secret (optional, but required for signing).</param>
        /// <param name="rateLimiter">The rate limiter (auto-configured).</param>
        /// <param name="options">The JSON API options.</param>
        public BinanceApiUser(string apiKey, string apiSecret = null, IApiRateLimiter rateLimiter = null, IOptions <BinanceApiOptions> options = null)
        {
            Throw.IfNullOrWhiteSpace(apiKey, nameof(apiKey));

            ApiKey = apiKey;

            if (!string.IsNullOrWhiteSpace(apiSecret))
            {
                _hmac = new HMACSHA256(Encoding.UTF8.GetBytes(apiSecret));
            }

            RateLimiter = rateLimiter;
            _options    = options?.Value ?? new BinanceApiOptions();

            // Configure order rate limiter.
            RateLimiter?.Configure(TimeSpan.FromDays(_options.OrderRateLimit.DurationDays), _options.OrderRateLimit.Count);
            // Configure order burst rate limiter.
            RateLimiter?.Configure(TimeSpan.FromSeconds(_options.OrderRateLimit.BurstDurationSeconds), _options.OrderRateLimit.BurstCount);
        }
예제 #2
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="timestampProvider">The timestamp provider.</param>
        /// <param name="rateLimiter">The rate limiter (auto configured).</param>
        /// <param name="options">The options.</param>
        /// <param name="logger">The logger.</param>
        internal BinanceHttpClient(ITimestampProvider timestampProvider = null, IApiRateLimiter rateLimiter = null, IOptions <BinanceApiOptions> options = null, ILogger <BinanceHttpClient> logger = null)
            : base(logger)
        {
            TimestampProvider = timestampProvider ?? new TimestampProvider();
            RateLimiter       = rateLimiter ?? new ApiRateLimiter();
            _options          = options?.Value ?? new BinanceApiOptions();

            DefaultRecvWindow = _options.RecvWindowDefault ?? default;

            TimestampProvider.TimestampOffsetRefreshPeriod = TimeSpan.FromMinutes(_options.TimestampOffsetRefreshPeriodMinutes);

            try
            {
                // Configure request rate limiter.
                RateLimiter.Configure(TimeSpan.FromMinutes(_options.RequestRateLimit.DurationMinutes), _options.RequestRateLimit.Count);
                // Configure request burst rate limiter.
                RateLimiter.Configure(TimeSpan.FromSeconds(_options.RequestRateLimit.BurstDurationSeconds), _options.RequestRateLimit.BurstCount);
            }
            catch (Exception e)
            {
                var message = $"{nameof(BinanceHttpClient)}: Failed to configure request rate limiter.";
                Logger?.LogError(e, message);
                throw new BinanceApiException(message, e);
            }

            var uri = new Uri(EndpointUrl);

            try
            {
                _httpClient = new HttpClient
                {
                    BaseAddress = uri,
                    Timeout     = TimeSpan.FromSeconds(_options.HttpClientTimeoutDefaultSeconds)
                };
            }
            catch (Exception e)
            {
                var message = $"{nameof(BinanceHttpClient)}: Failed to create HttpClient.";
                Logger?.LogError(e, message);
                throw new BinanceApiException(message, e);
            }

            if (_options.ServicePointManagerConnectionLeaseTimeoutMilliseconds > 0)
            {
                try
                {
                    // FIX: Singleton HttpClient doesn't respect DNS changes.
                    // https://github.com/dotnet/corefx/issues/11224
                    var sp = ServicePointManager.FindServicePoint(uri);
                    sp.ConnectionLeaseTimeout = _options.ServicePointManagerConnectionLeaseTimeoutMilliseconds;
                }
                catch (Exception e)
                {
                    var message = $"{nameof(BinanceHttpClient)}: Failed to set {nameof(ServicePointManager)}.ConnectionLeaseTimeout.";
                    Logger?.LogError(e, message);
                    throw new BinanceApiException(message, e);
                }
            }

            try
            {
                var version = GetType().Assembly.GetName().Version;

                var versionString = $"{version.Major}.{version.Minor}.{version.Build}{(version.Revision > 0 ? $".{version.Revision}" : string.Empty)}";

                _httpClient.DefaultRequestHeaders.Add("User-Agent", $"Binance/{versionString} (.NET; +https://github.com/sonvister/Binance)");
            }
            catch (Exception e)
            {
                var message = $"{nameof(BinanceHttpClient)}: Failed to set User-Agent.";
                Logger?.LogError(e, message);
                throw new BinanceApiException(message, e);
            }
        }