/// <summary>
        /// Get older (non-compressed) trades.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="apiKey"></param>
        /// <param name="symbol"></param>
        /// <param name="fromId">TradeId to fetch from. Default gets most recent trades.</param>
        /// <param name="limit">Default 500; max 500.</param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static async Task <string> GetTradesAsync(this IBinanceHttpClient client, string apiKey, string symbol, long fromId = BinanceApi.NullId, int limit = default, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));
            Throw.IfNullOrWhiteSpace(symbol, nameof(symbol));

            if (client.RateLimiter != null)
            {
                await client.RateLimiter.DelayAsync(5, token)
                .ConfigureAwait(false);
            }

            var request = new BinanceHttpRequest("/api/v1/historicalTrades")
            {
                ApiKey = apiKey
            };

            request.AddParameter("symbol", symbol.FormatSymbol());

            if (fromId >= 0)
            {
                request.AddParameter("fromId", fromId);
            }

            if (limit > 0)
            {
                request.AddParameter("limit", limit);
            }

            return(await client.GetAsync(request, token)
                   .ConfigureAwait(false));
        }
Beispiel #2
0
        /// <summary>
        /// Get current account information.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="user"></param>
        /// <param name="recvWindow"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static async Task <string> GetAccountInfoAsync(this IBinanceHttpClient client, IBinanceApiUser user, long recvWindow = default, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));
            Throw.IfNull(user, nameof(user));

            if (recvWindow <= 0)
            {
                recvWindow = client.Options.RecvWindowDefault ?? 0;
            }

            if (client.RateLimiter != null)
            {
                await client.RateLimiter.DelayAsync(5, token)
                .ConfigureAwait(false);
            }

            var request = new BinanceHttpRequest("/api/v3/account")
            {
                ApiKey = user.ApiKey
            };

            if (recvWindow > 0)
            {
                request.AddParameter("recvWindow", recvWindow);
            }

            await client.SignAsync(request, user, token)
            .ConfigureAwait(false);

            return(await client.GetAsync(request, token)
                   .ConfigureAwait(false));
        }
Beispiel #3
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="orderBookSerializer"></param>
        /// <param name="orderBookTopSerializer"></param>
        /// <param name="aggregateTradeSerializer"></param>
        /// <param name="candlestickSerializer"></param>
        /// <param name="symbolPriceSerializer"></param>
        /// <param name="symbolStatisticsSerializer"></param>
        /// <param name="accountTradeSerializer"></param>
        /// <param name="tradeSerializer"></param>
        /// <param name="orderSerializer"></param>
        /// <param name="logger"></param>
        public BinanceApi(
            IBinanceHttpClient client,
            IOrderBookSerializer orderBookSerializer               = null,
            IOrderBookTopSerializer orderBookTopSerializer         = null,
            IAggregateTradeSerializer aggregateTradeSerializer     = null,
            ICandlestickSerializer candlestickSerializer           = null,
            ISymbolPriceSerializer symbolPriceSerializer           = null,
            ISymbolStatisticsSerializer symbolStatisticsSerializer = null,
            IAccountTradeSerializer accountTradeSerializer         = null,
            ITradeSerializer tradeSerializer = null,
            IOrderSerializer orderSerializer = null,
            ILogger <BinanceApi> logger      = null)
        {
            Throw.IfNull(client, nameof(client));

            HttpClient = client;

            _orderBookSerializer        = orderBookSerializer ?? new OrderBookSerializer();
            _orderBookTopSerializer     = orderBookTopSerializer ?? new OrderBookTopSerializer();
            _aggregateTradeSerializer   = aggregateTradeSerializer ?? new AggregateTradeSerializer();
            _candlestickSerializer      = candlestickSerializer ?? new CandlestickSerializer();
            _symbolPriceSerializer      = symbolPriceSerializer ?? new SymbolPriceSerializer();
            _symbolStatisticsSerializer = symbolStatisticsSerializer ?? new SymbolStatisticsSerializer();
            _accountTradeSerializer     = accountTradeSerializer ?? new AccountTradeSerializer();
            _tradeSerializer            = tradeSerializer ?? new TradeSerializer();
            _orderSerializer            = orderSerializer ?? new OrderSerializer();

            _logger = logger;
        }
Beispiel #4
0
        /// <summary>
        /// Get current account information.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="user"></param>
        /// <param name="recvWindow"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static async Task <string> GetAccountInfoAsync(this IBinanceHttpClient client, IBinanceApiUser user, long recvWindow = default, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));
            Throw.IfNull(user, nameof(user));

            if (recvWindow <= 0)
            {
                recvWindow = client.Options.RecvWindowDefault ?? 0;
            }

            var request = new BinanceHttpRequest($"/api/v3/account")
            {
                ApiKey = user.ApiKey
            };

            var timestamp = await client.GetTimestampAsync(token)
                            .ConfigureAwait(false);

            request.AddParameter("timestamp", timestamp);

            if (recvWindow > 0)
            {
                request.AddParameter("recvWindow", recvWindow);
            }

            var signature = user.Sign(request.QueryString);

            request.AddParameter("signature", signature);

            return(await client.GetAsync(request, token)
                   .ConfigureAwait(false));
        }
Beispiel #5
0
        /// <summary>
        /// Get candlesticks for a symbol. Candlesticks/K-Lines are uniquely identified by their open time.
        /// If startTime and endTime are not sent, the most recent candlesticks are returned.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="symbol"></param>
        /// <param name="interval"></param>
        /// <param name="limit">Default 500; max 500.</param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static async Task <string> GetCandlesticksAsync(this IBinanceHttpClient client, string symbol, CandlestickInterval interval, int limit = default, long startTime = default, long endTime = default, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));
            Throw.IfNullOrWhiteSpace(symbol, nameof(symbol));

            if (client.RateLimiter != null)
            {
                await client.RateLimiter.DelayAsync(token : token)
                .ConfigureAwait(false);
            }

            var request = new BinanceHttpRequest("/api/v1/klines");

            request.AddParameter("symbol", symbol.FormatSymbol());
            request.AddParameter("interval", interval.AsString());

            if (limit > 0)
            {
                request.AddParameter("limit", limit);
            }

            if (startTime > 0)
            {
                request.AddParameter("startTime", startTime);
            }

            if (endTime > 0)
            {
                request.AddParameter("endTime", endTime);
            }

            return(await client.GetAsync(request, token)
                   .ConfigureAwait(false));
        }
Beispiel #6
0
        public BinanceHttpClientExtensionsTest()
        {
            // Configure services.
            var serviceProvider = new ServiceCollection()
                                  .AddBinance().BuildServiceProvider();

            // Get IBinanceHttpClient service.
            _client = serviceProvider.GetService <IBinanceHttpClient>();
        }
        /// <summary>
        /// Cancel an active order.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="user"></param>
        /// <param name="symbol"></param>
        /// <param name="orderId"></param>
        /// <param name="origClientOrderId"></param>
        /// <param name="newClientOrderId">Used to uniquely identify this cancel. Automatically generated by default.</param>
        /// <param name="recvWindow"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static async Task <string> CancelOrderAsync(this IBinanceHttpClient client, IBinanceApiUser user, string symbol, long orderId = BinanceApi.NullId, string origClientOrderId = null, string newClientOrderId = null, long recvWindow = default, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));
            Throw.IfNull(user, nameof(user));
            Throw.IfNullOrWhiteSpace(symbol, nameof(symbol));

            if (orderId < 0 && string.IsNullOrWhiteSpace(origClientOrderId))
            {
                throw new ArgumentException($"Either '{nameof(orderId)}' or '{nameof(origClientOrderId)}' must be provided, but both were invalid.");
            }

            if (recvWindow == default)
            {
                recvWindow = client.DefaultRecvWindow;
            }

            if (user.RateLimiter != null)
            {
                await user.RateLimiter.DelayAsync(token : token)
                .ConfigureAwait(false);
            }

            var request = new BinanceHttpRequest("/api/v3/order")
            {
                ApiKey = user.ApiKey
            };

            request.AddParameter("symbol", symbol.FormatSymbol());

            if (orderId >= 0)
            {
                request.AddParameter("orderId", orderId);
            }

            if (!string.IsNullOrWhiteSpace(origClientOrderId))
            {
                request.AddParameter("origClientOrderId", origClientOrderId);
            }

            if (!string.IsNullOrWhiteSpace(newClientOrderId))
            {
                request.AddParameter("newClientOrderId", newClientOrderId);
            }

            if (recvWindow > 0)
            {
                request.AddParameter("recvWindow", recvWindow);
            }

            await client.SignAsync(request, user, token)
            .ConfigureAwait(false);

            return(await client.DeleteAsync(request, token)
                   .ConfigureAwait(false));
        }
        /// <summary>
        /// Get best price/quantity on the order book for a symbol.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="symbol"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static Task <string> GetOrderBookTopAsync(this IBinanceHttpClient client, string symbol, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));
            Throw.IfNullOrWhiteSpace(symbol, nameof(symbol));

            var request = new BinanceHttpRequest("/api/v1/ticker/bookTicker");

            request.AddParameter("symbol", symbol.FormatSymbol());

            return(client.GetAsync(request, token));
        }
        /// <summary>
        /// Start a new user data stream.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="apiKey"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static Task <string> UserStreamStartAsync(this IBinanceHttpClient client, string apiKey, CancellationToken token = default)
        {
            Throw.IfNullOrWhiteSpace(apiKey, nameof(apiKey));

            var request = new BinanceHttpRequest("/api/v1/userDataStream")
            {
                ApiKey = apiKey
            };

            return(client.PostAsync(request, token));
        }
        /// <summary>
        /// Submit a withdraw request.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="user"></param>
        /// <param name="asset"></param>
        /// <param name="address"></param>
        /// <param name="addressTag"></param>
        /// <param name="amount"></param>
        /// <param name="name">A description of the address (optional).</param>
        /// <param name="recvWindow"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static async Task <string> WithdrawAsync(this IBinanceHttpClient client, IBinanceApiUser user, string asset, string address, string addressTag, decimal amount, string name = null, long recvWindow = default, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));
            Throw.IfNull(user, nameof(user));
            Throw.IfNullOrWhiteSpace(asset, nameof(asset));
            Throw.IfNullOrWhiteSpace(address, nameof(address));

            if (amount <= 0)
            {
                throw new ArgumentException("Withdraw amount must be greater than 0.", nameof(amount));
            }

            if (recvWindow == default)
            {
                recvWindow = client.DefaultRecvWindow;
            }

            if (client.RateLimiter != null)
            {
                await client.RateLimiter.DelayAsync(token : token)
                .ConfigureAwait(false);
            }

            var request = new BinanceHttpRequest("/wapi/v3/withdraw.html")
            {
                ApiKey = user.ApiKey
            };

            request.AddParameter("asset", asset.FormatSymbol());
            request.AddParameter("address", address);
            request.AddParameter("amount", amount);

            if (!string.IsNullOrWhiteSpace(addressTag))
            {
                request.AddParameter("addressTag", addressTag);
            }

            if (!string.IsNullOrWhiteSpace(name))
            {
                request.AddParameter("name", name);
            }

            if (recvWindow > 0)
            {
                request.AddParameter("recvWindow", recvWindow);
            }

            await client.SignAsync(request, user, token)
            .ConfigureAwait(false);

            return(await client.PostAsync(request, token)
                   .ConfigureAwait(false));
        }
Beispiel #11
0
        /// <summary>
        /// Get the deposit history.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="user"></param>
        /// <param name="asset"></param>
        /// <param name="status"></param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <param name="recvWindow"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static async Task <string> GetDepositsAsync(this IBinanceHttpClient client, IBinanceApiUser user, string asset = null, DepositStatus?status = null, long startTime = default, long endTime = default, long recvWindow = default, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));
            Throw.IfNull(user, nameof(user));

            if (recvWindow <= 0)
            {
                recvWindow = client.Options.RecvWindowDefault ?? 0;
            }

            if (client.RateLimiter != null)
            {
                await client.RateLimiter.DelayAsync(token : token)
                .ConfigureAwait(false);
            }

            var request = new BinanceHttpRequest("/wapi/v3/depositHistory.html")
            {
                ApiKey = user.ApiKey
            };

            if (!string.IsNullOrWhiteSpace(asset))
            {
                request.AddParameter("asset", asset.FormatSymbol());
            }

            if (status.HasValue)
            {
                request.AddParameter("status", (int)status);
            }

            if (startTime > 0)
            {
                request.AddParameter("startTime", startTime);
            }

            if (endTime > 0)
            {
                request.AddParameter("endTime", endTime);
            }

            if (recvWindow > 0)
            {
                request.AddParameter("recvWindow", recvWindow);
            }

            await client.SignAsync(request, user, token)
            .ConfigureAwait(false);

            return(await client.GetAsync(request, token)
                   .ConfigureAwait(false));
        }
Beispiel #12
0
        /// <summary>
        /// Get the withdrawal history.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="user"></param>
        /// <param name="asset"></param>
        /// <param name="status"></param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <param name="recvWindow"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static async Task <string> GetWithdrawalsAsync(this IBinanceHttpClient client, IBinanceApiUser user, string asset = null, WithdrawalStatus?status = null, long startTime = default, long endTime = default, long recvWindow = default, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));
            Throw.IfNull(user, nameof(user));

            if (recvWindow <= 0)
            {
                recvWindow = client.Options.RecvWindowDefault ?? 0;
            }

            var request = new BinanceHttpRequest($"/wapi/v3/withdrawHistory.html")
            {
                ApiKey = user.ApiKey
            };

            var timestamp = await client.GetTimestampAsync(token)
                            .ConfigureAwait(false);

            request.AddParameter("timestamp", timestamp);

            if (!string.IsNullOrWhiteSpace(asset))
            {
                request.AddParameter("asset", asset.FormatSymbol());
            }

            if (status.HasValue)
            {
                request.AddParameter("status", (int)status);
            }

            if (startTime > 0)
            {
                request.AddParameter("startTime", startTime);
            }

            if (endTime > 0)
            {
                request.AddParameter("endTime", endTime);
            }

            if (recvWindow > 0)
            {
                request.AddParameter("recvWindow", recvWindow);
            }

            var signature = user.Sign(request.QueryString);

            request.AddParameter("signature", signature);

            return(await client.GetAsync(request, token)
                   .ConfigureAwait(false));
        }
        /// <summary>
        /// Extension allowing candlestick interval as a string.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="symbol"></param>
        /// <param name="interval"></param>
        /// <param name="limit"></param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static async Task <string> GetCandlesticksAsync(this IBinanceHttpClient client, string symbol, string interval, int limit = default, DateTime startTime = default, DateTime endTime = default, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));

            if (client.RateLimiter != null)
            {
                await client.RateLimiter.DelayAsync(token : token)
                .ConfigureAwait(false);
            }

            return(await client.GetCandlesticksAsync(symbol, interval.ToCandlestickInterval(), limit, startTime, endTime, token)
                   .ConfigureAwait(false));
        }
        /// <summary>
        /// Get system status.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static async Task <string> GetSystemStatusAsync(this IBinanceHttpClient client, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));

            if (client.RateLimiter != null)
            {
                await client.RateLimiter.DelayAsync(token : token)
                .ConfigureAwait(false);
            }

            return(await client.GetAsync("/wapi/v3/systemStatus.html", token)
                   .ConfigureAwait(false));
        }
        /// <summary>
        /// Get latest price for a symbol or all symbols.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="symbol"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static Task <string> GetPriceAsync(this IBinanceHttpClient client, string symbol = null, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));

            var request = new BinanceHttpRequest("/api/v3/ticker/price");

            if (!string.IsNullOrWhiteSpace(symbol))
            {
                request.AddParameter("symbol", symbol.FormatSymbol());
            }

            return(client.GetAsync(request, token));
        }
        /// <summary>
        /// Get best price/quantity on the order book for all symbols.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static async Task <string> GetOrderBookTopsAsync(this IBinanceHttpClient client, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));

            if (client.RateLimiter != null)
            {
                await client.RateLimiter.DelayAsync(token : token)
                .ConfigureAwait(false);
            }

            return(await client.GetAsync("/api/v1/ticker/bookTicker", token)
                   .ConfigureAwait(false));
        }
Beispiel #17
0
        /// <summary>
        /// Get compressed, aggregate trades. Trades that fill at the time, from the same order, with the same price will have the quantity aggregated.
        /// If fromdId, startTime, and endTime are not sent, the most recent aggregate trades will be returned.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="symbol"></param>
        /// <param name="fromId">ID to get aggregate trades from INCLUSIVE.</param>
        /// <param name="limit">Default 500; max 500.</param>
        /// <param name="startTime">Timestamp in ms to get aggregate trades from INCLUSIVE.</param>
        /// <param name="endTime">Timestamp in ms to get aggregate trades until INCLUSIVE.</param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static async Task <string> GetAggregateTradesAsync(this IBinanceHttpClient client, string symbol, long fromId = BinanceApi.NullId, int limit = default, long startTime = default, long endTime = default, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));
            Throw.IfNullOrWhiteSpace(symbol, nameof(symbol));

            if (client.RateLimiter != null)
            {
                await client.RateLimiter.DelayAsync(token : token)
                .ConfigureAwait(false);
            }

            var request = new BinanceHttpRequest("/api/v1/aggTrades");

            request.AddParameter("symbol", symbol.FormatSymbol());

            if (fromId >= 0)
            {
                request.AddParameter("fromId", fromId);
            }

            if (startTime > 0)
            {
                request.AddParameter("startTime", startTime);
            }

            if (endTime > 0)
            {
                request.AddParameter("endTime", endTime);
            }

            if (startTime <= 0 || endTime <= 0)
            {
                if (limit > 0)
                {
                    request.AddParameter("limit", limit);
                }
            }
            else
            {
                var start = DateTimeOffset.FromUnixTimeMilliseconds(startTime);
                var end   = DateTimeOffset.FromUnixTimeMilliseconds(endTime);

                if ((end - start).Duration() >= TimeSpan.FromHours(24))
                {
                    throw new ArgumentException($"The interval between {nameof(startTime)} and {nameof(endTime)} must be less than 24 hours.", nameof(endTime));
                }
            }

            return(await client.GetAsync(request, token)
                   .ConfigureAwait(false));
        }
        /// <summary>
        /// Get 24 hour price change statistics for a symbol or all symbols.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="symbol"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static Task <string> Get24HourStatisticsAsync(this IBinanceHttpClient client, string symbol = null, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));

            // When symbol is not provided use number of symbols that are TRADING for weight.
            var request = new BinanceHttpRequest("/api/v1/ticker/24hr", string.IsNullOrWhiteSpace(symbol) ? Symbol.Cache.Values.Count(s => s.Status == SymbolStatus.Trading) : 1);

            if (!string.IsNullOrWhiteSpace(symbol))
            {
                request.AddParameter("symbol", symbol.FormatSymbol());
            }

            return(client.GetAsync(request, token));
        }
        /// <summary>
        /// Close out a user data stream.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="apiKey"></param>
        /// <param name="listenKey"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static Task <string> UserStreamCloseAsync(this IBinanceHttpClient client, string apiKey, string listenKey, CancellationToken token = default)
        {
            Throw.IfNullOrWhiteSpace(apiKey, nameof(apiKey));
            Throw.IfNullOrWhiteSpace(listenKey, nameof(listenKey));

            var request = new BinanceHttpRequest("/api/v1/userDataStream")
            {
                ApiKey = apiKey
            };

            request.AddParameter("listenKey", listenKey);

            return(client.DeleteAsync(request, token));
        }
Beispiel #20
0
        /// <summary>
        /// Check an order's status. Either orderId or origClientOrderId must be sent.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="user"></param>
        /// <param name="symbol"></param>
        /// <param name="orderId"></param>
        /// <param name="origClientOrderId"></param>
        /// <param name="recvWindow"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static async Task <string> GetOrderAsync(this IBinanceHttpClient client, IBinanceApiUser user, string symbol, long orderId = BinanceApi.NullId, string origClientOrderId = null, long recvWindow = default, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));
            Throw.IfNull(user, nameof(user));
            Throw.IfNullOrWhiteSpace(symbol, nameof(symbol));

            if (orderId < 0 && string.IsNullOrWhiteSpace(origClientOrderId))
            {
                throw new ArgumentException($"Either '{nameof(orderId)}' or '{nameof(origClientOrderId)}' must be provided, but both were invalid.");
            }

            if (recvWindow <= 0)
            {
                recvWindow = client.Options.RecvWindowDefault ?? 0;
            }

            var request = new BinanceHttpRequest($"/api/v3/order")
            {
                ApiKey = user.ApiKey
            };

            request.AddParameter("symbol", symbol.FormatSymbol());

            if (orderId >= 0)
            {
                request.AddParameter("orderId", orderId);
            }

            if (!string.IsNullOrWhiteSpace(origClientOrderId))
            {
                request.AddParameter("origClientOrderId", origClientOrderId);
            }

            if (recvWindow > 0)
            {
                request.AddParameter("recvWindow", recvWindow);
            }

            var timestamp = await client.GetTimestampAsync(token)
                            .ConfigureAwait(false);

            request.AddParameter("timestamp", timestamp);

            var signature = user.Sign(request.QueryString);

            request.AddParameter("signature", signature);

            return(await client.GetAsync(request, token, user.RateLimiter)
                   .ConfigureAwait(false));
        }
        /// <summary>
        /// Get the account status.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="user"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static async Task <string> GetAccountStatusAsync(this IBinanceHttpClient client, IBinanceApiUser user, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));

            var request = new BinanceHttpRequest("/wapi/v3/accountStatus.html")
            {
                ApiKey = user.ApiKey
            };

            await client.SignAsync(request, user, token)
            .ConfigureAwait(false);

            return(await client.GetAsync(request, token)
                   .ConfigureAwait(false));
        }
Beispiel #22
0
        public async Task <long> GetTimestampAsync(IBinanceHttpClient client, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));

            // Acquire synchronization lock.
            await _syncLock.WaitAsync(token)
            .ConfigureAwait(false);

            try
            {
                if (DateTime.UtcNow - _offsetLastUpdate > TimestampOffsetRefreshPeriod)
                {
                    const long n = 3;

                    long sum   = 0;
                    var  count = n;
                    do
                    {
                        var systemTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();

                        var json = await client.GetServerTimeAsync(token)
                                   .ConfigureAwait(false);

                        systemTime = (systemTime + DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()) / 2;

                        // Calculate timestamp offset to account for time differences.
                        sum += JObject.Parse(json)["serverTime"].Value <long>() - systemTime;

                        await Task.Delay(100, token)
                        .ConfigureAwait(false);
                    } while (--count > 0);

                    // Calculate average offset.
                    TimestampOffset = sum / n;

                    // Record the current system time to determine when to refresh offset.
                    _offsetLastUpdate = DateTime.UtcNow;
                }
            }
            catch (Exception) { /* ignore */ }
            finally
            {
                // Release synchronization lock.
                _syncLock.Release();
            }

            return(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() + TimestampOffset);
        }
        /// <summary>
        /// Get latest (non-compressed) trades.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="symbol"></param>
        /// <param name="limit"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static Task <string> GetTradesAsync(this IBinanceHttpClient client, string symbol, int limit = default, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));
            Throw.IfNullOrWhiteSpace(symbol, nameof(symbol));

            var request = new BinanceHttpRequest("/api/v1/trades");

            request.AddParameter("symbol", symbol.FormatSymbol());

            if (limit > 0)
            {
                request.AddParameter("limit", limit);
            }

            return(client.GetAsync(request, token));
        }
        /// <summary>
        /// Ping a user data stream to prevent a time out.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="apiKey"></param>
        /// <param name="listenKey"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static Task <string> UserStreamKeepAliveAsync(this IBinanceHttpClient client, string apiKey, string listenKey, CancellationToken token = default)
        {
            Throw.IfNullOrWhiteSpace(apiKey, nameof(apiKey));
            Throw.IfNullOrWhiteSpace(listenKey, nameof(listenKey));

            var request = new BinanceHttpRequest("/api/v1/userDataStream")
            {
                ApiKey = apiKey
            };

            request.AddParameter("listenKey", listenKey);

            // TODO
            // A POST will either get back your current stream (and effectively do a PUT) or get back a new stream.
            //return client.PostAsync(request, token);
            return(client.PutAsync(request, token));
        }
Beispiel #25
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="orderBookSerializer"></param>
        /// <param name="logger"></param>
        public BinanceApi(
            IBinanceHttpClient client,
            IOrderBookSerializer orderBookSerializer = null,
            ITradeSerializer tradeSerializer         = null,
            IOrderSerializer orderSerializer         = null,
            ILogger <BinanceApi> logger = null)
        {
            Throw.IfNull(client, nameof(client));

            HttpClient = client;

            _orderBookSerializer = orderBookSerializer ?? new OrderBookSerializer();
            _tradeSerializer     = tradeSerializer ?? new TradeSerializer();
            _orderSerializer     = orderSerializer ?? new OrderSerializer();

            _logger = logger;
        }
Beispiel #26
0
        /// <summary>
        /// Get local system timestamp synchronized with server time.
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public static async Task <long> GetTimestampAsync(this IBinanceHttpClient client, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));

            // Acquire synchronization lock.
            await _timestampOffsetSync.WaitAsync(token)
            .ConfigureAwait(false);

            try
            {
                if (DateTime.UtcNow - _timestampOffsetUpdatedAt > TimeSpan.FromMinutes(client.Options.TimestampOffsetRefreshPeriodMinutes))
                {
                    const long N = 3;

                    long sum   = 0;
                    var  count = N;
                    do
                    {
                        var systemTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();

                        var json = await GetServerTimeAsync(client, token)
                                   .ConfigureAwait(false);

                        systemTime = (systemTime + DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()) / 2;

                        // Calculate timestamp offset to account for time differences and delays.
                        sum += JObject.Parse(json)["serverTime"].Value <long>() - systemTime;
                    } while (--count > 0);

                    // Calculate average offset.
                    _timestampOffset = sum / N;

                    // Record the current system time to determine when to refresh offset.
                    _timestampOffsetUpdatedAt = DateTime.UtcNow;
                }
            }
            catch (Exception) { /* ignore */ }
            finally
            {
                // Release synchronization lock.
                _timestampOffsetSync.Release();
            }

            return(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() + _timestampOffset);
        }
Beispiel #27
0
        /// <summary>
        /// Get trades for a specific account and symbol.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="user"></param>
        /// <param name="symbol"></param>
        /// <param name="fromId">TradeId to fetch from. Default gets most recent trades.</param>
        /// <param name="limit">Default 500; max 500.</param>
        /// <param name="recvWindow"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static async Task <string> GetAccountTradesAsync(this IBinanceHttpClient client, IBinanceApiUser user, string symbol, long fromId = BinanceApi.NullId, int limit = default, long recvWindow = default, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));
            Throw.IfNull(user, nameof(user));
            Throw.IfNullOrWhiteSpace(symbol, nameof(symbol));

            if (recvWindow <= 0)
            {
                recvWindow = client.Options.RecvWindowDefault ?? 0;
            }

            var request = new BinanceHttpRequest($"/api/v3/myTrades")
            {
                ApiKey = user.ApiKey
            };

            request.AddParameter("symbol", symbol.FormatSymbol());

            if (fromId >= 0)
            {
                request.AddParameter("fromId", fromId);
            }

            if (limit > 0)
            {
                request.AddParameter("limit", limit);
            }

            if (recvWindow > 0)
            {
                request.AddParameter("recvWindow", recvWindow);
            }

            var timestamp = await client.GetTimestampAsync(token)
                            .ConfigureAwait(false);

            request.AddParameter("timestamp", timestamp);

            var signature = user.Sign(request.QueryString);

            request.AddParameter("signature", signature);

            return(await client.GetAsync(request, token)
                   .ConfigureAwait(false));
        }
        /// <summary>
        /// Get trades for a specific account and symbol.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="user"></param>
        /// <param name="symbol"></param>
        /// <param name="fromId">TradeId to fetch from. Default gets most recent trades.</param>
        /// <param name="limit">Default 500; max 500.</param>
        /// <param name="recvWindow"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static async Task <string> GetAccountTradesAsync(this IBinanceHttpClient client, IBinanceApiUser user, string symbol, long fromId = BinanceApi.NullId, int limit = default, long recvWindow = default, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));
            Throw.IfNull(user, nameof(user));
            Throw.IfNullOrWhiteSpace(symbol, nameof(symbol));

            if (recvWindow == default)
            {
                recvWindow = client.DefaultRecvWindow;
            }

            if (client.RateLimiter != null)
            {
                await client.RateLimiter.DelayAsync(5, token)
                .ConfigureAwait(false);
            }

            var request = new BinanceHttpRequest("/api/v3/myTrades")
            {
                ApiKey = user.ApiKey
            };

            request.AddParameter("symbol", symbol.FormatSymbol());

            if (fromId >= 0)
            {
                request.AddParameter("fromId", fromId);
            }

            if (limit > 0)
            {
                request.AddParameter("limit", limit);
            }

            if (recvWindow > 0)
            {
                request.AddParameter("recvWindow", recvWindow);
            }

            await client.SignAsync(request, user, token)
            .ConfigureAwait(false);

            return(await client.GetAsync(request, token)
                   .ConfigureAwait(false));
        }
        /// <summary>
        /// Get candlesticks for a symbol. Candlesticks/K-Lines are uniquely identified by their open time.
        /// If startTime and endTime are not sent, the most recent candlesticks are returned.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="symbol"></param>
        /// <param name="interval"></param>
        /// <param name="limit">Default 500; max 500.</param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static async Task <string> GetCandlesticksAsync(this IBinanceHttpClient client, string symbol, CandlestickInterval interval, int limit = default, DateTime startTime = default, DateTime endTime = default, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));
            Throw.IfNullOrWhiteSpace(symbol, nameof(symbol));

            if (client.RateLimiter != null)
            {
                await client.RateLimiter.DelayAsync(token : token)
                .ConfigureAwait(false);
            }

            var request = new BinanceHttpRequest("/api/v1/klines");

            request.AddParameter("symbol", symbol.FormatSymbol());
            request.AddParameter("interval", interval.AsString());

            if (limit > 0)
            {
                request.AddParameter("limit", limit);
            }

            if (startTime != default)
            {
                if (startTime.Kind != DateTimeKind.Utc)
                {
                    throw new ArgumentException("Date/Time must be UTC.", nameof(startTime));
                }

                request.AddParameter("startTime", startTime.ToTimestamp());
            }

            // ReSharper disable once InvertIf
            if (endTime != default)
            {
                if (endTime.Kind != DateTimeKind.Utc)
                {
                    throw new ArgumentException("Date/Time must be UTC.", nameof(endTime));
                }

                request.AddParameter("endTime", endTime.ToTimestamp());
            }

            return(await client.GetAsync(request, token)
                   .ConfigureAwait(false));
        }
        /// <summary>
        /// Get the deposit address for an asset.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="user"></param>
        /// <param name="asset"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static async Task <string> GetDepositAddressAsync(this IBinanceHttpClient client, IBinanceApiUser user, string asset, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));
            Throw.IfNullOrWhiteSpace(asset, nameof(asset));

            var request = new BinanceHttpRequest("/wapi/v3/depositAddress.html")
            {
                ApiKey = user.ApiKey
            };

            request.AddParameter("asset", asset.FormatSymbol());

            await client.SignAsync(request, user, token)
            .ConfigureAwait(false);

            return(await client.GetAsync(request, token)
                   .ConfigureAwait(false));
        }