/// <summary> /// Adds effect processor to container /// </summary> /// <param name="effectProcessor"></param> public void Add(IEffectProcessor <Effect> effectProcessor) { Effects.Add(effectProcessor.Effect); effectProcessor.CommitEffect(); this.Aggregate(Envelope, effectProcessor.Effect); if (effectProcessor.Effect.Account != 0) { AffectedAccounts.Add(effectProcessor.Effect.Account); } }
/// <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()).Select(a => new AccountWrapper(a, settings.RequestRateLimits)); var accountStorage = new AccountStorage(accounts); var withdrawals = await GetWithdrawals(accountStorage, settings); var orders = await GetOrders(accountStorage); var exchange = await GetRestoredExchange(orders); var withdrawalsStorage = new WithdrawalStorage(withdrawals); var batchSize = 1000; var effects = new List <Effect>(); while (true) { var quanta = await storage.LoadQuantaAboveApex(apex, batchSize); effects.AddRange(quanta.SelectMany(q => q.ToQuantumContainer(accountStorage).Effects)); if (quanta.Count < batchSize) { break; } } for (var i = effects.Count - 1; i >= 0; i--) { var currentEffect = effects[i]; var account = currentEffect.AccountWrapper; IEffectProcessor <Effect> processor = null; switch (currentEffect) { case AccountCreateEffect accountCreateEffect: processor = new AccountCreateEffectProcessor(accountCreateEffect, accountStorage, settings.RequestRateLimits); 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 lastQuantumData = (await storage.LoadQuantum(apex)).ToQuantumContainer(); //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).ToList(), TxCursor = stellarData?.TxCursor ?? 0, Orders = allOrders.OrderBy(o => o.OrderId).ToList(), Settings = settings, Withdrawals = withdrawalsStorage.GetAll().OrderBy(w => w.Apex).ToList(), LastHash = lastQuantumData.Quantum.Message.ComputeHash() }); }
/// <summary> /// Adds effect processor to container /// </summary> /// <param name="effectProcessor"></param> public void Add(IEffectProcessor <Effect> effectProcessor) { Effects.Add(effectProcessor.Effect); effectProcessor.CommitEffect(); this.Aggregate(Envelope, effectProcessor.Effect, Effects.Count - 1); }