public void Properties() { var user = new BinanceApiUser("api-key"); var commissions = new AccountCommissions(10, 10, 0, 0); var status = new AccountStatus(true, true, true); var time = DateTimeOffset.FromUnixTimeMilliseconds(DateTime.UtcNow.ToTimestamp()).UtcDateTime; var balances = new[] { new AccountBalance("BTC", 0.1m, 0.2m) }; var account = new AccountInfo(user, commissions, status, time); Assert.Equal(commissions, account.Commissions); Assert.Equal(status, account.Status); Assert.Equal(time, account.Time); Assert.NotNull(account.Balances); Assert.Empty(account.Balances); account = new AccountInfo(user, commissions, status, time, balances); Assert.Equal(commissions, account.Commissions); Assert.Equal(status, account.Status); Assert.Equal(time, account.Time); Assert.NotNull(account.Balances); Assert.NotEmpty(account.Balances); Assert.Equal(balances[0].Asset, account.Balances.First().Asset); }
public void Properties() { var user = new BinanceApiUser("api-key"); var commissions = new AccountCommissions(10, 10, 0, 0); var status = new AccountStatus(true, true, true); long updateTime = 1234567890; var balances = new[] { new AccountBalance("BTC", 0.1m, 0.2m) }; var account = new AccountInfo(user, commissions, status, updateTime); Assert.Equal(commissions, account.Commissions); Assert.Equal(status, account.Status); Assert.Equal(updateTime, account.Timestamp); Assert.NotNull(account.Balances); Assert.Empty(account.Balances); account = new AccountInfo(user, commissions, status, updateTime, balances); Assert.Equal(commissions, account.Commissions); Assert.Equal(status, account.Status); Assert.Equal(updateTime, account.Timestamp); Assert.NotNull(account.Balances); Assert.NotEmpty(account.Balances); Assert.Equal(balances[0].Asset, account.Balances.First().Asset); }
public void Throws() { var user = new BinanceApiUser("api-key"); var commissions = new AccountCommissions(10, 10, 0, 0); var time = DateTimeOffset.FromUnixTimeMilliseconds(DateTime.UtcNow.ToTimestamp()).UtcDateTime; var status = new AccountStatus(true, true, true); Assert.Throws <ArgumentNullException>("user", () => new AccountInfo(null, commissions, status, time)); Assert.Throws <ArgumentNullException>("commissions", () => new AccountInfo(user, null, status, time)); Assert.Throws <ArgumentNullException>("status", () => new AccountInfo(user, commissions, null, time)); }
public void Throws() { var user = new BinanceApiUser("api-key"); var commissions = new AccountCommissions(10, 10, 0, 0); long updateTime = 1234567890; var status = new AccountStatus(true, true, true); Assert.Throws <ArgumentNullException>("user", () => new AccountInfo(null, commissions, status, updateTime)); Assert.Throws <ArgumentNullException>("commissions", () => new AccountInfo(user, null, status, updateTime)); Assert.Throws <ArgumentNullException>("status", () => new AccountInfo(user, commissions, null, updateTime)); Assert.Throws <ArgumentException>("updateTime", () => new AccountInfo(user, commissions, status, -1)); Assert.Throws <ArgumentException>("updateTime", () => new AccountInfo(user, commissions, status, 0)); }
public void Properties() { var maker = 10; var taker = 20; var buyer = 30; var seller = 40; var commissions = new AccountCommissions(maker, taker, buyer, seller); Assert.Equal(maker, commissions.Maker); Assert.Equal(taker, commissions.Taker); Assert.Equal(buyer, commissions.Buyer); Assert.Equal(seller, commissions.Seller); }
public void Properties() { var user = new BinanceApiUser("api-key"); var commissions = new AccountCommissions(10, 10, 0, 0); var status = new AccountStatus(true, true, true); long updateTime = 1234567890; var balances = new[] { new AccountBalance("BTC", 0.1m, 0.2m) }; var accountInfo = new AccountInfo(user, commissions, status, updateTime, balances); var args = new AccountInfoCacheEventArgs(accountInfo); Assert.Equal(accountInfo, args.AccountInfo); }
public void Properties() { var user = new BinanceApiUser("api-key"); var commissions = new AccountCommissions(10, 10, 0, 0); var status = new AccountStatus(true, true, true); var time = DateTimeOffset.FromUnixTimeMilliseconds(DateTime.UtcNow.ToTimestamp()).UtcDateTime; var balances = new[] { new AccountBalance("BTC", 0.1m, 0.2m) }; var accountInfo = new AccountInfo(user, commissions, status, time, balances); var args = new AccountInfoCacheEventArgs(accountInfo); Assert.Equal(accountInfo, args.AccountInfo); }
public void Throws() { var user = new BinanceApiUser("api-key"); var commissions = new AccountCommissions(10, 10, 0, 0); var status = new AccountStatus(true, true, true); var time = DateTimeOffset.FromUnixTimeMilliseconds(DateTime.UtcNow.ToTimestamp()).UtcDateTime; var balances = new[] { new AccountBalance("BTC", 0.1m, 0.2m) }; var account = new AccountInfo(user, commissions, status, time, balances); using (var cts = new CancellationTokenSource()) { Assert.Throws <ArgumentNullException>("accountInfo", () => new AccountUpdateEventArgs(time, cts.Token, null)); } }
public void Properties() { var user = new BinanceApiUser("api-key"); var commissions = new AccountCommissions(10, 10, 0, 0); var status = new AccountStatus(true, true, true); var time = DateTimeOffset.FromUnixTimeMilliseconds(DateTime.UtcNow.ToTimestamp()).UtcDateTime; var balances = new[] { new AccountBalance("BTC", 0.1m, 0.2m) }; var account = new AccountInfo(user, commissions, status, time, balances); using (var cts = new CancellationTokenSource()) { var args = new AccountUpdateEventArgs(time, cts.Token, account); Assert.Equal(time, args.Time); Assert.Equal(account, args.AccountInfo); } }
public void Serialization() { var maker = 10; var taker = 20; var buyer = 30; var seller = 40; var commissions = new AccountCommissions(maker, taker, buyer, seller); var json = JsonConvert.SerializeObject(commissions); commissions = JsonConvert.DeserializeObject <AccountCommissions>(json); Assert.Equal(maker, commissions.Maker); Assert.Equal(taker, commissions.Taker); Assert.Equal(buyer, commissions.Buyer); Assert.Equal(seller, commissions.Seller); }
/// <summary> /// Deserialize JSON and raise <see cref="UserDataEventArgs"/> event. /// </summary> /// <param name="json"></param> /// <param name="token"></param> /// <param name="callback"></param> /// <returns></returns> protected override void DeserializeJsonAndRaiseEvent(string json, CancellationToken token, Action <UserDataEventArgs> callback = null) { Throw.IfNullOrWhiteSpace(json, nameof(json)); Logger?.LogDebug($"{nameof(UserDataWebSocketClient)}: \"{json}\""); try { var jObject = JObject.Parse(json); var eventType = jObject["e"].Value <string>(); var eventTime = jObject["E"].Value <long>(); // ReSharper disable once ConvertIfStatementToSwitchStatement if (eventType == "outboundAccountInfo") { var commissions = new AccountCommissions( jObject["m"].Value <int>(), // maker jObject["t"].Value <int>(), // taker jObject["b"].Value <int>(), // buyer jObject["s"].Value <int>()); // seller var status = new AccountStatus( jObject["T"].Value <bool>(), // can trade jObject["W"].Value <bool>(), // can withdraw jObject["D"].Value <bool>()); // can deposit var balances = jObject["B"] .Select(entry => new AccountBalance( entry["a"].Value <string>(), // asset entry["f"].Value <decimal>(), // free amount entry["l"].Value <decimal>())) // locked amount .ToList(); var eventArgs = new AccountUpdateEventArgs(eventTime, token, new AccountInfo(User, commissions, status, jObject["u"].Value <long>(), balances)); try { callback?.Invoke(eventArgs); AccountUpdate?.Invoke(this, eventArgs); } catch (OperationCanceledException) { } catch (Exception e) { if (!token.IsCancellationRequested) { Logger?.LogError(e, $"{nameof(UserDataWebSocketClient)}: Unhandled account update event handler exception."); } } } else if (eventType == "executionReport") { var order = new Order(User); FillOrder(order, jObject); var executionType = ConvertOrderExecutionType(jObject["x"].Value <string>()); var rejectedReason = ConvertOrderRejectedReason(jObject["r"].Value <string>()); var newClientOrderId = jObject["c"].Value <string>(); if (executionType == OrderExecutionType.Trade) // trade update event. { var trade = new AccountTrade( jObject["s"].Value <string>(), // symbol jObject["t"].Value <long>(), // ID jObject["i"].Value <long>(), // order ID jObject["L"].Value <decimal>(), // price (price of last filled trade) jObject["z"].Value <decimal>(), // quantity (accumulated quantity of filled trades) jObject["n"].Value <decimal>(), // commission jObject["N"].Value <string>(), // commission asset jObject["T"].Value <long>(), // timestamp order.Side == OrderSide.Buy, // is buyer jObject["m"].Value <bool>(), // is buyer maker jObject["M"].Value <bool>()); // is best price var quantityOfLastFilledTrade = jObject["l"].Value <decimal>(); var eventArgs = new AccountTradeUpdateEventArgs(eventTime, token, order, rejectedReason, newClientOrderId, trade, quantityOfLastFilledTrade); try { callback?.Invoke(eventArgs); TradeUpdate?.Invoke(this, eventArgs); } catch (OperationCanceledException) { } catch (Exception e) { if (!token.IsCancellationRequested) { Logger?.LogError(e, $"{nameof(UserDataWebSocketClient)}: Unhandled trade update event handler exception."); } } } else // order update event. { var eventArgs = new OrderUpdateEventArgs(eventTime, token, order, executionType, rejectedReason, newClientOrderId); try { callback?.Invoke(eventArgs); OrderUpdate?.Invoke(this, eventArgs); } catch (OperationCanceledException) { } catch (Exception e) { if (!token.IsCancellationRequested) { Logger?.LogError(e, $"{nameof(UserDataWebSocketClient)}: Unhandled order update event handler exception."); } } } } else { Logger?.LogWarning($"{nameof(UserDataWebSocketClient)}.{nameof(DeserializeJsonAndRaiseEvent)}: Unexpected event type ({eventType}) - \"{json}\""); } } catch (OperationCanceledException) { } catch (Exception e) { if (!token.IsCancellationRequested) { Logger?.LogError(e, $"{nameof(UserDataWebSocketClient)}.{nameof(DeserializeJsonAndRaiseEvent)}"); } } }
protected override void HandleMessage(IEnumerable <Action <UserDataEventArgs> > callbacks, string stream, string json) { if (!Users.ContainsKey(stream)) { Logger?.LogError($"{nameof(UserDataClient)}.{nameof(HandleMessage)}: Unknown listen key (\"{stream}\"). [thread: {Thread.CurrentThread.ManagedThreadId}]"); return; // ignore. } var user = Users[stream]; try { var jObject = JObject.Parse(json); var eventType = jObject["e"].Value <string>(); var eventTime = jObject["E"].Value <long>().ToDateTime(); // ReSharper disable once ConvertIfStatementToSwitchStatement if (eventType == "outboundAccountInfo") { var commissions = new AccountCommissions( jObject["m"].Value <int>(), // maker jObject["t"].Value <int>(), // taker jObject["b"].Value <int>(), // buyer jObject["s"].Value <int>()); // seller var status = new AccountStatus( jObject["T"].Value <bool>(), // can trade jObject["W"].Value <bool>(), // can withdraw jObject["D"].Value <bool>()); // can deposit var balances = jObject["B"] .Select(entry => new AccountBalance( entry["a"].Value <string>(), // asset entry["f"].Value <decimal>(), // free amount entry["l"].Value <decimal>())) // locked amount .ToList(); var eventArgs = new AccountUpdateEventArgs(eventTime, new AccountInfo(user, commissions, status, jObject["u"].Value <long>().ToDateTime(), balances)); try { // ReSharper disable once InconsistentlySynchronizedField if (_accountUpdateSubscribers.TryGetValue(stream, out var subscribers)) { foreach (var subcriber in subscribers) { subcriber(eventArgs); } } if (callbacks != null) { foreach (var callback in callbacks) { callback(eventArgs); } } AccountUpdate?.Invoke(this, eventArgs); } catch (OperationCanceledException) { /* ignore */ } catch (Exception e) { Logger?.LogWarning(e, $"{nameof(UserDataClient)}.{nameof(HandleMessage)}: Unhandled account update event handler exception."); } } else if (eventType == "executionReport") { var order = new Order(user); FillOrder(order, jObject); var executionType = ConvertOrderExecutionType(jObject["x"].Value <string>()); var rejectedReason = jObject["r"].Value <string>(); var newClientOrderId = jObject["c"].Value <string>(); if (executionType == OrderExecutionType.Trade) // trade update event. { var trade = new AccountTrade( jObject["s"].Value <string>(), // symbol jObject["t"].Value <long>(), // ID jObject["i"].Value <long>(), // order ID jObject["L"].Value <decimal>(), // price (price of last filled trade) jObject["z"].Value <decimal>(), // quantity (accumulated quantity of filled trades) jObject["n"].Value <decimal>(), // commission jObject["N"].Value <string>(), // commission asset jObject["T"].Value <long>() .ToDateTime(), // time order.Side == OrderSide.Buy, // is buyer jObject["m"].Value <bool>(), // is buyer maker jObject["M"].Value <bool>()); // is best price var quantityOfLastFilledTrade = jObject["l"].Value <decimal>(); var eventArgs = new AccountTradeUpdateEventArgs(eventTime, order, rejectedReason, newClientOrderId, trade, quantityOfLastFilledTrade); try { // ReSharper disable once InconsistentlySynchronizedField if (_accountTradeUpdateSubscribers.TryGetValue(stream, out var subscribers)) { foreach (var subcriber in subscribers) { subcriber(eventArgs); } } if (callbacks != null) { foreach (var callback in callbacks) { callback(eventArgs); } } TradeUpdate?.Invoke(this, eventArgs); } catch (OperationCanceledException) { /* ignore */ } catch (Exception e) { Logger?.LogWarning(e, $"{nameof(UserDataClient)}.{nameof(HandleMessage)}: Unhandled trade update event handler exception."); } } else // order update event. { var eventArgs = new OrderUpdateEventArgs(eventTime, order, executionType, rejectedReason, newClientOrderId); try { // ReSharper disable once InconsistentlySynchronizedField if (_orderUpdateSubscribers.TryGetValue(stream, out var subscribers)) { foreach (var subcriber in subscribers) { subcriber(eventArgs); } } if (callbacks != null) { foreach (var callback in callbacks) { callback(eventArgs); } } OrderUpdate?.Invoke(this, eventArgs); } catch (OperationCanceledException) { /* ignore */ } catch (Exception e) { Logger?.LogWarning(e, $"{nameof(UserDataClient)}.{nameof(HandleMessage)}: Unhandled order update event handler exception."); } } } else { Logger?.LogWarning($"{nameof(UserDataClient)}.{nameof(HandleMessage)}: Unexpected event type ({eventType})."); } } catch (OperationCanceledException) { /* ignore */ } catch (Exception e) { Logger?.LogError(e, $"{nameof(UserDataClient)}.{nameof(HandleMessage)}"); } }