Ejemplo n.º 1
0
 public void ReportConsolidationValidated(WalletConsolidationTransferEventEntry consolidation, bool validation)
 {
     _logger.LogInformation(
         $"Validation of {consolidation.TransferQty} {consolidation.CoinSymbol} consolidation {(validation ? "successful" : "failed")}");
     EventHistoryRepository.Events().FindOneAndUpdate(
         eventEntry => eventEntry.Id.Equals(consolidation.Id),
         Builders <EventEntry> .Update.Set(
             eventEntry => ((WalletConsolidationTransferEventEntry)eventEntry).Valid,
             validation
             )
         );
 }
Ejemplo n.º 2
0
 public void ReportConsolidationExecuted(WalletConsolidationTransferEventEntry consolidation)
 {
     _logger.LogInformation(
         $"Reported a new executed consolidation of {consolidation.TransferQty} {consolidation.CoinSymbol}, target becomes {consolidation.NewTargetPublicKeyBalance}");
     EventHistoryRepository.Events().FindOneAndUpdate(
         eventEntry => eventEntry.Id.Equals(consolidation.Id),
         Builders <EventEntry> .Update.Set(
             eventEntry => ((WalletConsolidationTransferEventEntry)eventEntry).Executed,
             true
             )
         );
 }
Ejemplo n.º 3
0
        public void ProcessEvent(WalletConsolidationTransferEventEntry eventEntry)
        {
            if (eventEntry.Valid != null)
            {
                // Consolidation was either invalid anyway, or it's already validated
                return;
            }

            // Validate the consolidation's withdrawal - Wallet Server actively waits for this!
            var currentVersionNumberEvents = _eventHistoryService.FindByVersionNumber(eventEntry.VersionNumber)
                                             .ToList();
            var consolidationList = currentVersionNumberEvents.FindAll(e => e is WalletConsolidationTransferEventEntry);
            var withdrawalList    = currentVersionNumberEvents.FindAll(e => e is WalletWithdrawalEventEntry);

            if (withdrawalList.Count == 0)
            {
                throw new Exception("Standalone consolidation not implemented yet");
            }

            var  withdrawal = (WalletWithdrawalEventEntry)withdrawalList.Single();
            bool valid;

            if (withdrawal.Validated.HasValue)
            {
                valid = withdrawal.Validated.Value;
            }
            else
            {
                var(balance, reservedBalance) = _userService
                                                .GetBalanceAndReservedBalance(withdrawal.User, withdrawal.AccountId, withdrawal.CoinSymbol);
                if (!IsValidWithdrawal(withdrawal, balance))
                {
                    valid = false;
                    // Withdrawal is invalid
                    _eventHistoryService.ReportWithdrawalValidation(withdrawal, valid);
                }
                else
                {
                    valid = true;
                    _eventHistoryService.ReportWithdrawalValidation(withdrawal, valid);
                }
            }

            foreach (var consolidationEntry in consolidationList)
            {
                var consolidation = (WalletConsolidationTransferEventEntry)consolidationEntry;
                _eventHistoryService.ReportConsolidationValidated(consolidation, valid);
            }
        }
Ejemplo n.º 4
0
        private void ProcessEvent(WalletConsolidationTransferEventEntry eventEntry)
        {
            while (eventEntry.Valid == null)
            {
                _logger.LogWarning(
                    $"Consolidation event {eventEntry.Id} is not validated by Trading Service yet, waiting...");
                Task.Delay(1000).Wait();
                eventEntry = (WalletConsolidationTransferEventEntry)_eventHistoryService.FindById(eventEntry.Id);
            }

            if (eventEntry.Valid == false)
            {
                return;
            }

            var oldBalanceSrc    = GetCurrentlyCachedBalance(eventEntry.TransferSourcePublicKey).Result;
            var newBalanceSrc    = oldBalanceSrc - eventEntry.TransferQty - eventEntry.TransferFee;
            var oldBalanceTarget = GetCurrentlyCachedBalance(eventEntry.TransferTargetPublicKey).Result;
            var newBalanceTarget = oldBalanceTarget + eventEntry.TransferQty;

            if (!eventEntry.Executed)
            {
                if (newBalanceSrc == eventEntry.NewSourcePublicKeyBalance &&
                    newBalanceTarget == eventEntry.NewTargetPublicKeyBalance)
                {
                    // Sanity check successful, we can execute the consolidation
                    // We start by expecting the target deposit, not yielding it to user as his own deposit
                    _knownPublicKeyBalances[eventEntry.TransferTargetPublicKey] = newBalanceTarget;

                    // We can unlock source for deposit, and immediately lock it back until withdrawal gets processed,
                    // but we instead expect to be locked throw a fatal error in case withdrawal goes wrong
//                    _knownPublicKeyBalances[eventEntry.TransferSourcePublicKey] = eventEntry.NewSourcePublicKeyBalance;
//                    _lockedPublicKeyBalances[eventEntry.TransferSourcePublicKey] +=
//                        eventEntry.TransferQty + eventEntry.TransferFee;

                    var success = Withdraw(
                        eventEntry.TransferSourcePublicKey,
                        eventEntry.TransferTargetPublicKey,
                        eventEntry.TransferQty
                        ).Result;
                    if (!success)
                    {
                        throw new Exception(
                                  $"Consolidation event id {eventEntry.Id} failed to execute the withdrawal. {GetType().Name} has to stop processing further events, requiring administrator to solve this issue");
                    }

                    EnsureWithdrawn(
                        eventEntry.TransferSourcePublicKey,
                        eventEntry.NewSourcePublicKeyBalance,
                        eventEntry.TransferQty + eventEntry.TransferFee,
                        eventEntry.VersionNumber);

                    // We could unlock the source for deposit if we locked it before withdrawal
//                    _lockedPublicKeyBalances[eventEntry.TransferSourcePublicKey] -=
//                        eventEntry.TransferQty + eventEntry.TransferFee;
                }
                else if (GetBalance(eventEntry.TransferSourcePublicKey).Result == eventEntry.NewSourcePublicKeyBalance &&
                         GetBalance(eventEntry.TransferTargetPublicKey).Result ==
                         eventEntry.NewTargetPublicKeyBalance)
                {
                    // Already seems to be consolidated properly
                    // If the GetBalance call fails, we consider this a fatal error anyway, as else branch does it too
                    _logger.LogError(
                        "Consolidation event already seems to have been successfully finished, even though it was unexpected. Marking the event as executed");
                }
                else
                {
                    throw new Exception(
                              $"{GetType().Name} detected fatal event inconsistency of expected wallet balances during consolidation event id {eventEntry.Id} processing. Expecting source {oldBalanceSrc} -> {newBalanceSrc} to reach {eventEntry.NewSourcePublicKeyBalance}, target {oldBalanceTarget} -> {newBalanceTarget} to reach {eventEntry.NewTargetPublicKeyBalance}");
                }

                _eventHistoryService.ReportConsolidationExecuted(eventEntry);
            }
            // If the transfer was already executed, simply assert expected values and switch cached balances
            else
            {
                if (newBalanceSrc != eventEntry.NewSourcePublicKeyBalance ||
                    newBalanceTarget != eventEntry.NewTargetPublicKeyBalance)
                {
                    throw new Exception(
                              $"{GetType().Name} detected fatal event inconsistency of expected wallet balances during consolidation event id {eventEntry.Id} processing. Expecting source {oldBalanceSrc} to become {newBalanceSrc} and reach {eventEntry.NewSourcePublicKeyBalance}, target {oldBalanceTarget} to become {newBalanceTarget} and reach {eventEntry.NewTargetPublicKeyBalance}");
                }

                // Assume there was a successful target deposit
                _knownPublicKeyBalances[eventEntry.TransferTargetPublicKey] = newBalanceTarget;
            }

            // Unlock balance for a deposit detection
            _knownPublicKeyBalances[eventEntry.TransferSourcePublicKey] = newBalanceSrc;
        }