private void ResultMessageHandler(MessageEnvelope envelope) { lock (processedEffectsMessages) { if (AccountData == null || !(envelope.Message is IEffectsContainer effectsMessage) || processedEffectsMessages.Any(r => r == envelope.Message.MessageId)) { return; } RegisterNewEffectsMessage(envelope.Message.MessageId); try { foreach (var effect in effectsMessage.Effects) { switch (effect) { case NonceUpdateEffect nonceUpdateEffect: AccountData.Nonce = nonceUpdateEffect.Nonce; break; case BalanceCreateEffect balanceCreateEffect: AccountData.AddBalance(balanceCreateEffect.Asset, constellation); break; case BalanceUpdateEffect balanceUpdateEffect: AccountData.UpdateBalance(balanceUpdateEffect.Asset, balanceUpdateEffect.Amount); break; case OrderPlacedEffect orderPlacedEffect: { AccountData.AddOrder(orderPlacedEffect.OrderId, orderPlacedEffect.Amount, orderPlacedEffect.Price, constellation); var decodedId = OrderIdConverter.Decode(orderPlacedEffect.OrderId); if (decodedId.Side == OrderSide.Buy) { AccountData.UpdateLiabilities(0, orderPlacedEffect.QuoteAmount); } else { AccountData.UpdateLiabilities(decodedId.Asset, orderPlacedEffect.Amount); } } break; case OrderRemovedEffect orderRemoveEffect: { AccountData.RemoveOrder(orderRemoveEffect.OrderId); var decodedId = OrderIdConverter.Decode(orderRemoveEffect.OrderId); if (decodedId.Side == OrderSide.Buy) { AccountData.UpdateLiabilities(0, -orderRemoveEffect.QuoteAmount); } else { AccountData.UpdateLiabilities(decodedId.Asset, -orderRemoveEffect.Amount); } } break; case TradeEffect tradeEffect: { AccountData.UpdateOrder(tradeEffect.OrderId, tradeEffect.AssetAmount); var decodedId = OrderIdConverter.Decode(tradeEffect.OrderId); if (decodedId.Side == OrderSide.Buy) { if (!tradeEffect.IsNewOrder) { AccountData.UpdateLiabilities(0, -tradeEffect.QuoteAmount); } AccountData.UpdateBalance(0, -tradeEffect.QuoteAmount); AccountData.UpdateBalance(decodedId.Asset, tradeEffect.AssetAmount); } else { if (!tradeEffect.IsNewOrder) { AccountData.UpdateLiabilities(decodedId.Asset, -tradeEffect.AssetAmount); } AccountData.UpdateBalance(decodedId.Asset, -tradeEffect.AssetAmount); AccountData.UpdateBalance(0, tradeEffect.QuoteAmount); } } break; case WithdrawalCreateEffect withdrawalCreateEffect: foreach (var withdrawalItem in withdrawalCreateEffect.Items) { AccountData.UpdateLiabilities(withdrawalItem.Asset, withdrawalItem.Amount); } break; case WithdrawalRemoveEffect withdrawalRemoveEffect: foreach (var withdrawalItem in withdrawalRemoveEffect.Items) { if (withdrawalRemoveEffect.IsSuccessful) { AccountData.UpdateBalance(withdrawalItem.Asset, -withdrawalItem.Amount); } AccountData.UpdateLiabilities(withdrawalItem.Asset, -withdrawalItem.Amount); } break; default: break; } } OnAccountUpdate?.Invoke(AccountData); } catch (Exception exc) { OnException?.Invoke(exc); } } }