예제 #1
0
 public static Order ToOrder(this OrderModel order, AccountStorage accountStorage)
 {
     return(new Order
     {
         Amount = order.Amount,
         QuoteAmount = order.QuoteAmount,
         OrderId = unchecked ((ulong)order.Id),
         Price = order.Price,
         AccountWrapper = accountStorage.GetAccount(order.Account)
     });
 }
        public static QuantumContainer ToQuantumContainer(this QuantumModel quantum, AccountStorage accountStorage = null)
        {
            if (quantum == null)
            {
                throw new ArgumentNullException(nameof(quantum));
            }

            var quantumContainer = XdrConverter.Deserialize <QuantumContainer>(quantum.Bin);

            if (accountStorage != null)
            {
                foreach (var effect in quantumContainer.Effects)
                {
                    if (effect.Account == 0)
                    {
                        continue;
                    }
                    effect.AccountWrapper = accountStorage.GetAccount(effect.Account);
                }
            }

            return(quantumContainer);
        }
예제 #3
0
        public static void TryAssignAccountWrapper(this MessageEnvelope envelope, AccountStorage accountStorage)
        {
            var requestMessage = default(RequestMessage);

            if (envelope.Message is RequestQuantum)
            {
                requestMessage = ((RequestQuantum)envelope.Message).RequestMessage;
            }
            else if (envelope.Message is RequestMessage)
            {
                requestMessage = (RequestMessage)envelope.Message;
            }
            else
            {
                return;
            }

            if (accountStorage == null)
            {
                throw new ArgumentNullException(nameof(accountStorage));
            }
            requestMessage.AccountWrapper = accountStorage.GetAccount(requestMessage.Account);
        }
예제 #4
0
        /// <summary>
        /// Builds snapshot for specified apex
        /// </summary>
        /// <param name="apex"></param>
        /// <returns></returns>
        public async Task <Snapshot> GetSnapshot(long apex)
        {
            if (apex < 0)
            {
                throw new ArgumentException("Apex cannot be less than zero.");
            }

            var lastApex = await GetLastApex();

            if (lastApex < apex)
            {
                throw new InvalidOperationException("Requested apex is greater than the last known one.");
            }

            //some auditors can have capped db
            var minRevertApex = await GetMinRevertApex();

            if (minRevertApex == -1 && apex != lastApex || apex < minRevertApex)
            {
                throw new InvalidOperationException($"Lack of data to revert to {apex} apex.");
            }

            var settings = await GetConstellationSettings(apex);

            if (settings == null)
            {
                return(null);
            }

            var stellarData = await storage.LoadConstellationState();

            var accounts = await GetAccounts();

            var accountStorage = new AccountStorage(accounts, settings.RequestRateLimits);

            var withdrawals = await GetWithdrawals(accountStorage, settings);

            var orders = await GetOrders(accountStorage);

            var exchange = await GetRestoredExchange(orders);

            var withdrawalsStorage = new WithdrawalStorage(withdrawals, false);

            var accountEffectModels = await storage.LoadEffectsAboveApex(apex);

            var effectModels           = new Effect[accountEffectModels.Sum(a => a.Effects.Count)];
            var currentApexIndexOffset = 0;

            foreach (var quantumEffect in accountEffectModels.GroupBy(a => a.Apex))
            {
                var effectsCount = 0;
                foreach (var accountEffects in quantumEffect)
                {
                    var account = accountStorage.GetAccount(accountEffects.Account);
                    if (account == null)
                    {
                        throw new Exception($"Account {accountEffects.Account} is not found.");
                    }
                    foreach (var rawEffect in accountEffects.Effects)
                    {
                        var effect = rawEffect.ToEffect(account);
                        effectModels[currentApexIndexOffset + rawEffect.ApexIndex] = effect;
                        effectsCount++;
                    }
                }
                currentApexIndexOffset += effectsCount;
            }
            for (var i = effectModels.Length - 1; i >= 0; i--)
            {
                var currentEffect = effectModels[i];
                var account       = currentEffect.AccountWrapper;
                IEffectProcessor <Effect> processor = null;
                switch (currentEffect)
                {
                case AccountCreateEffect accountCreateEffect:
                    processor = new AccountCreateEffectProcessor(accountCreateEffect, accountStorage);
                    break;

                case NonceUpdateEffect nonceUpdateEffect:
                    processor = new NonceUpdateEffectProcessor(nonceUpdateEffect);
                    break;

                case BalanceCreateEffect balanceCreateEffect:
                    processor = new BalanceCreateEffectProcessor(balanceCreateEffect);
                    break;

                case BalanceUpdateEffect balanceUpdateEffect:
                    processor = new BalanceUpdateEffectProcesor(balanceUpdateEffect);
                    break;

                case RequestRateLimitUpdateEffect requestRateLimitUpdateEffect:
                    processor = new RequestRateLimitUpdateEffectProcessor(requestRateLimitUpdateEffect, settings.RequestRateLimits);
                    break;

                case OrderPlacedEffect orderPlacedEffect:
                {
                    var orderBook = exchange.GetOrderbook(orderPlacedEffect.OrderId);
                    var order     = exchange.OrderMap.GetOrder(orderPlacedEffect.OrderId);
                    processor = new OrderPlacedEffectProcessor(orderPlacedEffect, orderBook, order);
                }
                break;

                case OrderRemovedEffect orderRemovedEffect:
                {
                    var orderBook = exchange.GetOrderbook(orderRemovedEffect.OrderId);
                    processor = new OrderRemovedEffectProccessor(orderRemovedEffect, orderBook);
                }
                break;

                case TradeEffect tradeEffect:
                {
                    var order = exchange.OrderMap.GetOrder(tradeEffect.OrderId);
                    if (order == null)         //no need to revert trade if no order was created
                    {
                        continue;
                    }
                    processor = new TradeEffectProcessor(tradeEffect, order);
                }
                break;

                case WithdrawalCreateEffect withdrawalCreate:
                {
                    var withdrawal = withdrawalsStorage.GetWithdrawal(withdrawalCreate.Apex);
                    processor = new WithdrawalCreateEffectProcessor(withdrawalCreate, withdrawal, withdrawalsStorage);
                }
                break;

                case WithdrawalRemoveEffect withdrawalRemove:
                {
                    var withdrawal = withdrawalsStorage.GetWithdrawal(withdrawalRemove.Apex);
                    processor = new WithdrawalRemoveEffectProcessor(withdrawalRemove, withdrawal, withdrawalsStorage);
                }
                break;

                default:
                    throw new NotImplementedException();
                }

                processor.RevertEffect();
            }

            var lastQuantum = (await storage.LoadQuantum(apex)).ToMessageEnvelope();

            //TODO: refactor restore exchange
            //we need to clean all order links to be able to restore exchange
            var allOrders = exchange.OrderMap.GetAllOrders();

            foreach (var order in orders)
            {
                order.Next = null;
                order.Prev = null;
            }

            return(new Snapshot
            {
                Apex = apex,
                Accounts = accountStorage.GetAll().OrderBy(a => a.Account.Id).Select(a => a.Account).ToList(),
                TxCursor = stellarData?.TxCursor ?? 0,
                Orders = allOrders.OrderBy(o => o.OrderId).ToList(),
                Settings = settings,
                Withdrawals = withdrawalsStorage.GetAll().OrderBy(w => w.Apex).ToList(),
                LastHash = lastQuantum.Message.ComputeHash()
            });
        }