/// <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); }
/// <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); } }