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); }
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); }
/// <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() }); }