public void AssignWithdrawLimitsTest_TestsIfWithdrawLimitsGetAsignedProperlyWhenTier1IsNotVerified_VerifiesThroughReturnedValue()
        {
            IWithdrawApplicationService   withdrawApplicationService = (IWithdrawApplicationService)ContextRegistry.GetContext()["WithdrawApplicationService"];
            IWithdrawLimitRepository      withdrawLimitRepository    = (IWithdrawLimitRepository)ContextRegistry.GetContext()["WithdrawLimitRepository"];
            IWithdrawFeesRepository       withdrawFeesRepository     = (IWithdrawFeesRepository)ContextRegistry.GetContext()["WithdrawFeesRepository"];
            StubTierLevelRetrievalService tierLevelRetrievalService  = (ITierLevelRetrievalService)ContextRegistry.GetContext()["TierLevelRetrievalService"] as StubTierLevelRetrievalService;

            Assert.IsNotNull(tierLevelRetrievalService);
            tierLevelRetrievalService.SetTierLevel(TierConstants.TierLevel0);
            AccountId     accountId     = new AccountId(123);
            Currency      currency      = new Currency("BTC", true);
            WithdrawLimit withdrawLimit = withdrawLimitRepository.GetLimitByTierLevelAndCurrency("Tier 1", LimitsCurrency.Default.ToString());

            Assert.IsNotNull(withdrawLimit);

            WithdrawFees withdrawFees = withdrawFeesRepository.GetWithdrawFeesByCurrencyName(currency.Name);

            Assert.IsNotNull(withdrawFees);

            WithdrawLimitRepresentation withdrawLimitRepresentation = withdrawApplicationService.GetWithdrawLimitThresholds(accountId.Value, currency.Name);

            Assert.IsNotNull(withdrawLimitRepresentation);
            Assert.AreEqual(currency.Name, withdrawLimitRepresentation.Currency);
            Assert.AreEqual(accountId.Value, withdrawLimitRepresentation.AccountId);
            Assert.AreEqual(0, withdrawLimitRepresentation.DailyLimit);
            Assert.AreEqual(0, withdrawLimitRepresentation.MonthlyLimit);
            Assert.AreEqual(0, withdrawLimitRepresentation.DailyLimitUsed);
            Assert.AreEqual(0, withdrawLimitRepresentation.MonthlyLimitUsed);
            Assert.AreEqual(0, withdrawLimitRepresentation.CurrentBalance);
            Assert.AreEqual(withdrawFees.Fee, withdrawLimitRepresentation.Fee);
            Assert.AreEqual(withdrawFees.MinimumAmount, withdrawLimitRepresentation.MinimumAmount);
            Assert.AreEqual(0, withdrawLimitRepresentation.Withheld);
            Assert.AreEqual(0, withdrawLimitRepresentation.MaximumWithdraw);
        }
        public void SaveWithdrawFeesAndRetreiveByCurrencyNameTest_SavesAnObjectToDatabaseAndManipulatesIt_ChecksIfItIsUpdatedAsExpected()
        {
            WithdrawFees retrievedWithdrawFees = _withdrawFeesRepository.GetWithdrawFeesByCurrencyName("LTC");

            Assert.IsNotNull(retrievedWithdrawFees);

            Assert.Greater(retrievedWithdrawFees.MinimumAmount, 0);
            Assert.Greater(retrievedWithdrawFees.Fee, 0);
        }
Пример #3
0
        public void DepositAndWithdrawTest_TestsIfThingsGoAsExpectedWhenWithdrawIsMadeAfterDeposit_ChecksBalanceToVerify()
        {
            // Scenario: Confirmed Deposit --> Withdraw --> Check Balance
            IFundsValidationService     fundsValidationService     = (IFundsValidationService)ContextRegistry.GetContext()["FundsValidationService"];
            IFundsPersistenceRepository fundsPersistenceRepository = (IFundsPersistenceRepository)ContextRegistry.GetContext()["FundsPersistenceRepository"];
            IBalanceRepository          balanceRepository          = (IBalanceRepository)ContextRegistry.GetContext()["BalanceRepository"];
            IDepositIdGeneratorService  depositIdGeneratorService  = (IDepositIdGeneratorService)ContextRegistry.GetContext()["DepositIdGeneratorService"];
            IWithdrawFeesRepository     withdrawFeesRepository     = (IWithdrawFeesRepository)ContextRegistry.GetContext()["WithdrawFeesRepository"];

            AccountId accountId = new AccountId(123);
            Currency  currency  = new Currency("BTC", true);

            // Deposit
            Deposit deposit = new Deposit(currency, depositIdGeneratorService.GenerateId(), DateTime.Now,
                                          DepositType.Default, 1.4m, 0, TransactionStatus.Pending, accountId,
                                          new TransactionId("123"), new BitcoinAddress("bitcoin123"));

            deposit.IncrementConfirmations(7);
            fundsPersistenceRepository.SaveOrUpdate(deposit);

            // Retrieve balance
            Balance balance = balanceRepository.GetBalanceByCurrencyAndAccountId(currency, accountId);

            Assert.IsNull(balance);
            bool depositResponse = fundsValidationService.DepositConfirmed(deposit);

            Assert.IsTrue(depositResponse);

            // Check balance
            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(currency, accountId);
            Assert.IsNotNull(balance);
            Assert.AreEqual(balance.CurrentBalance, deposit.Amount);
            Assert.AreEqual(balance.AvailableBalance, deposit.Amount);
            Assert.AreEqual(balance.PendingBalance, 0);

            // Withdraw
            Withdraw validateFundsForWithdrawal = fundsValidationService.ValidateFundsForWithdrawal(accountId, currency,
                                                                                                    1.3M, new TransactionId("transaction123"), new BitcoinAddress("bitcoin123"));

            Assert.IsNotNull(validateFundsForWithdrawal);
            bool withdrawalExecuted = fundsValidationService.WithdrawalExecuted(validateFundsForWithdrawal);

            Assert.IsTrue(withdrawalExecuted);

            WithdrawFees withdrawFee = withdrawFeesRepository.GetWithdrawFeesByCurrencyName(currency.Name);

            // Check balance
            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(currency, accountId);
            Assert.IsNotNull(balance);
            Assert.AreEqual(Math.Round(1.4M - 1.3M, 5), Math.Round(balance.CurrentBalance, 5));
            Assert.AreEqual(Math.Round(1.4M - 1.3M, 5), Math.Round(balance.AvailableBalance, 5));
            Assert.AreEqual(0, balance.PendingBalance);
        }
        public void SaveWithdrawFeesAndRetreiveByCurrencyNameTest_SavesAnObjectToDatabaseAndManipulatesIt_ChecksIfItIsUpdatedAsExpected()
        {
            WithdrawFees withdrawFees = new WithdrawFees(new Currency("LTC", true), 4000, 500);

            _persistanceRepository.SaveOrUpdate(withdrawFees);

            WithdrawFees retrievedWithdrawFees = _withdrawFeesRepository.GetWithdrawFeesByCurrencyName("LTC");

            Assert.IsNotNull(retrievedWithdrawFees);

            Assert.AreEqual(withdrawFees.MinimumAmount, retrievedWithdrawFees.MinimumAmount);
            Assert.AreEqual(withdrawFees.Fee, retrievedWithdrawFees.Fee);
        }
        public void WithdrawSuccessfulTest_TestsIfWithdrawIsSuccessfulWhenTierLevelIsHighEnough_VerifiesThroughDatabaseQueries()
        {
            IWithdrawApplicationService   withdrawApplicationService = (IWithdrawApplicationService)ContextRegistry.GetContext()["WithdrawApplicationService"];
            IWithdrawRepository           withdrawRepository         = (IWithdrawRepository)ContextRegistry.GetContext()["WithdrawRepository"];
            IFundsPersistenceRepository   fundsPersistenceRepository = (IFundsPersistenceRepository)ContextRegistry.GetContext()["FundsPersistenceRepository"];
            IBalanceRepository            balanceRepository          = (IBalanceRepository)ContextRegistry.GetContext()["BalanceRepository"];
            IWithdrawFeesRepository       withdrawFeesRepository     = (IWithdrawFeesRepository)ContextRegistry.GetContext()["WithdrawFeesRepository"];
            StubTierLevelRetrievalService tierLevelRetrievalService  = (ITierLevelRetrievalService)ContextRegistry.GetContext()["TierLevelRetrievalService"] as StubTierLevelRetrievalService;
            IWithdrawLimitRepository      withdrawLimitRepository    = (IWithdrawLimitRepository)ContextRegistry.GetContext()["WithdrawLimitRepository"];

            Assert.IsNotNull(tierLevelRetrievalService);
            tierLevelRetrievalService.SetTierLevel(TierConstants.TierLevel1);
            AccountId      accountId      = new AccountId(123);
            Currency       currency       = new Currency("BTC", true);
            BitcoinAddress bitcoinAddress = new BitcoinAddress("bitcoinaddress1");
            WithdrawLimit  withdrawLimit  = withdrawLimitRepository.GetLimitByTierLevelAndCurrency(TierConstants.TierLevel1, LimitsCurrency.Default.ToString());

            Assert.IsNotNull(withdrawLimit);
            decimal amount = withdrawLimit.DailyLimit;

            Balance balance = new Balance(currency, accountId, amount + 1, amount + 1);

            fundsPersistenceRepository.SaveOrUpdate(balance);

            CommitWithdrawResponse commitWithdrawResponse = withdrawApplicationService.CommitWithdrawal(new CommitWithdrawCommand(accountId.Value, currency.Name, currency.IsCryptoCurrency, bitcoinAddress.Value, amount));

            Assert.IsNotNull(commitWithdrawResponse);
            Assert.IsTrue(commitWithdrawResponse.CommitSuccessful);

            Withdraw withdraw = withdrawRepository.GetWithdrawByWithdrawId(commitWithdrawResponse.WithdrawId);

            Assert.IsNotNull(withdraw);
            Assert.AreEqual(accountId.Value, withdraw.AccountId.Value);
            Assert.AreEqual(currency.Name, withdraw.Currency.Name);
            Assert.AreEqual(currency.IsCryptoCurrency, withdraw.Currency.IsCryptoCurrency);
            Assert.AreEqual(amount - withdraw.Fee, withdraw.Amount);
            Assert.AreEqual(TransactionStatus.Pending, withdraw.Status);

            WithdrawFees withdrawFees = withdrawFeesRepository.GetWithdrawFeesByCurrencyName(currency.Name);

            Assert.IsNotNull(withdrawFees);

            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(currency, accountId);
            Assert.IsNotNull(balance);
            Assert.AreEqual((amount + 1) - (amount), balance.AvailableBalance);
            Assert.AreEqual(amount + 1, balance.CurrentBalance);
            Assert.AreEqual(amount, balance.PendingBalance);
        }
        public void AssignWithdrawLimitsTest_TestsIfWithdrawLimitsGetAsignedProperlyWhenInvalidTierLevelIsSpecified_VerifiesThroughReturnedValue()
        {
            IWithdrawApplicationService   withdrawApplicationService = (IWithdrawApplicationService)ContextRegistry.GetContext()["WithdrawApplicationService"];
            IWithdrawFeesRepository       withdrawFeesRepository     = (IWithdrawFeesRepository)ContextRegistry.GetContext()["WithdrawFeesRepository"];
            StubTierLevelRetrievalService tierLevelRetrievalService  = (ITierLevelRetrievalService)ContextRegistry.GetContext()["TierLevelRetrievalService"] as StubTierLevelRetrievalService;

            Assert.IsNotNull(tierLevelRetrievalService);
            tierLevelRetrievalService.SetTierLevel("Tier 6");
            AccountId accountId = new AccountId(123);
            Currency  currency  = new Currency("BTC", true);

            WithdrawFees withdrawFees = withdrawFeesRepository.GetWithdrawFeesByCurrencyName(currency.Name);

            Assert.IsNotNull(withdrawFees);

            withdrawApplicationService.GetWithdrawLimitThresholds(accountId.Value, currency.Name);
        }
        /// <summary>
        /// Gets the limits allowed for the withdrawal, along with the amount that has been used by the user
        /// </summary>
        /// <param name="accountId"></param>
        /// <param name="currency"></param>
        /// <returns></returns>
        public AccountWithdrawLimits GetWithdrawThresholds(AccountId accountId, Currency currency)
        {
            Balance balance = GetBalanceForAccountId(accountId, currency);

            WithdrawFees withdrawFees = _withdrawFeesRepository.GetWithdrawFeesByCurrencyName(currency.Name);
            // Get all the Withdraw Ledgers
            IList <Withdraw> withdrawLedgers = GetWithdrawalLedgers(currency, accountId);
            // Get the Current Tier Level for this user using the cross bounded context Tier retrieval service
            string currentTierLevel = _tierLevelRetrievalService.GetCurrentTierLevel(accountId.Value);

            // Get the withdraw fee and minimum amount
            decimal withdrawFee   = 0;
            decimal minimumAmount = 0;

            if (withdrawFees != null)
            {
                withdrawFee   = withdrawFees.Fee;
                minimumAmount = withdrawFees.MinimumAmount;
            }
            // Get the current and available balance
            decimal availableBalance = 0;
            decimal currentBalance   = 0;

            if (balance != null)
            {
                availableBalance = balance.AvailableBalance;
                currentBalance   = balance.CurrentBalance;
            }

            // Evaluate if the current withdrawal is within the limits of the maximum withdrawal allowed and
            // the balance available
            _limitsConfigurationService.AssignWithdrawLimits(currency.Name, currentTierLevel, withdrawLedgers,
                                                             availableBalance, currentBalance);


            return(new AccountWithdrawLimits(currency, accountId, _withdrawLimitEvaluationService.DailyLimit,
                                             _withdrawLimitEvaluationService.DailyLimitUsed,
                                             _withdrawLimitEvaluationService.MonthlyLimit,
                                             _withdrawLimitEvaluationService.MonthlyLimitUsed,
                                             availableBalance,
                                             _withdrawLimitEvaluationService.MaximumWithdraw,
                                             _withdrawLimitEvaluationService.WithheldAmount,
                                             withdrawFee, minimumAmount));
        }
        public Withdraw ValidateFundsForWithdrawal(AccountId accountId, Currency currency, decimal amount, TransactionId
                                                   transactionId, BitcoinAddress bitcoinAddress)
        {
            Tuple <bool, string> isTierVerified = IsTierVerified(accountId.Value, currency.IsCryptoCurrency);

            if (isTierVerified.Item1)
            {
                //if (currency.IsCryptoCurrency)
                //{
                WithdrawFees withdrawFees = _withdrawFeesRepository.GetWithdrawFeesByCurrencyName(currency.Name);
                if (withdrawFees != null)
                {
                    // Check if the current withdrawal amount is greater than the amount required mentioned with the Fees
                    if (amount >= withdrawFees.MinimumAmount)
                    {
                        Balance balance = GetBalanceForAccountId(accountId, currency);
                        if (balance != null)
                        {
                            // Get all the Withdraw Ledgers
                            IList <Withdraw> withdrawals = GetWithdrawalLedgers(currency, accountId);

                            // Evaluate if the current withdrawal is within the limits of the maximum withdrawal allowed and
                            // the balance available
                            if (_limitsConfigurationService.EvaluateWithdrawLimits(currency.Name, isTierVerified.Item2,
                                                                                   amount, withdrawals, balance.AvailableBalance, balance.CurrentBalance))
                            {
                                Withdraw withdraw = new Withdraw(currency, _withdrawIdGeneratorService.GenerateNewId(),
                                                                 DateTime.Now, GetWithdrawType(currency.Name),
                                                                 amount - withdrawFees.Fee,
                                                                 withdrawFees.Fee,
                                                                 TransactionStatus.Pending, accountId,
                                                                 bitcoinAddress);
                                // Set amount In US Dollars, which will be used in later calculations regarding withdrawals
                                withdraw.SetAmountInUsd(_limitsConfigurationService.ConvertCurrencyToFiat(currency.Name, amount));
                                _fundsPersistenceRepository.SaveOrUpdate(withdraw);
                                balance.AddPendingTransaction(withdraw.WithdrawId, PendingTransactionType.Withdraw,
                                                              -(withdraw.Amount + withdrawFees.Fee));
                                _fundsPersistenceRepository.SaveOrUpdate(balance);
                                return(withdraw);
                            }
                            else
                            {
                                throw new InvalidOperationException("Not enough balance or withdraw limit reached");
                            }
                        }
                        else
                        {
                            throw new InvalidOperationException(string.Format("No balance available AccountID = {0} | Currency = {1}", accountId.Value, currency.Name));
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException(string.Format("Withdraw amount less than Minimum Amount: " +
                                                                          "AccountID = {0} | Currency = {1}", accountId.Value, currency.Name));
                    }
                }
                else
                {
                    throw new InstanceNotFoundException(string.Format("No Withdraw Fees Found: " +
                                                                      "AccountID = {0} | Currency = {1}", accountId.Value, currency.Name));
                }
            }
            else
            {
                throw new InvalidOperationException(string.Format("Required Tier not verified for Withdraw: Account ID = {0}",
                                                                  accountId.Value));
            }
        }
Пример #9
0
        public void Scenario1Test_TestsFundsValidationServiceOperationsInaRandomOrderToProceedInTheDesiredExpectenacy_VerifiesThroughDatabaseQuery()
        {
            // Deposit --> Order Validations --> Trade --> Withdraw
            IFundsValidationService     fundsValidationService     = (IFundsValidationService)ContextRegistry.GetContext()["FundsValidationService"];
            IFundsPersistenceRepository fundsPersistenceRepository = (IFundsPersistenceRepository)ContextRegistry.GetContext()["FundsPersistenceRepository"];
            IBalanceRepository          balanceRepository          = (IBalanceRepository)ContextRegistry.GetContext()["BalanceRepository"];
            IDepositIdGeneratorService  depositIdGeneratorService  = (IDepositIdGeneratorService)ContextRegistry.GetContext()["DepositIdGeneratorService"];
            IWithdrawFeesRepository     withdrawFeesRepository     = (IWithdrawFeesRepository)ContextRegistry.GetContext()["WithdrawFeesRepository"];
            IFeeCalculationService      feeCalculationService      = (IFeeCalculationService)ContextRegistry.GetContext()["FeeCalculationService"];
            IFeeRepository feeRepository = (IFeeRepository)ContextRegistry.GetContext()["FeeRepository"];

            Tuple <string, string> splittedCurrencyPair = CurrencySplitterService.SplitCurrencyPair(feeRepository.GetAllFees().First().CurrencyPair);
            Currency baseCurrency  = new Currency(splittedCurrencyPair.Item1);
            Currency quoteCurrency = new Currency(splittedCurrencyPair.Item2);

            AccountId user1Account       = new AccountId(1);
            AccountId user2Account       = new AccountId(2);
            decimal   baseDepositAmount  = 1.4m;
            decimal   quoteDepositAmount = 1000;

            Balance user1QuoteInitialBalance = new Balance(quoteCurrency, user1Account, quoteDepositAmount, quoteDepositAmount);
            Balance user2QuoteInitialBalance = new Balance(quoteCurrency, user2Account, quoteDepositAmount, quoteDepositAmount);

            fundsPersistenceRepository.SaveOrUpdate(user1QuoteInitialBalance);
            fundsPersistenceRepository.SaveOrUpdate(user2QuoteInitialBalance);

            // Deposit
            Deposit deposit1 = new Deposit(baseCurrency, depositIdGeneratorService.GenerateId(), DateTime.Now,
                                           DepositType.Default, baseDepositAmount, 0, TransactionStatus.Pending, user1Account,
                                           new TransactionId("1"), new BitcoinAddress("bitcoin1"));

            deposit1.IncrementConfirmations(7);
            fundsPersistenceRepository.SaveOrUpdate(deposit1);

            Deposit deposit2 = new Deposit(baseCurrency, depositIdGeneratorService.GenerateId(), DateTime.Now,
                                           DepositType.Default, baseDepositAmount, 0, TransactionStatus.Pending, user2Account,
                                           new TransactionId("3"), new BitcoinAddress("bitcoin3"));

            deposit2.IncrementConfirmations(7);
            fundsPersistenceRepository.SaveOrUpdate(deposit2);

            // Retrieve Base Currency balance for user 1
            bool depositResponse = fundsValidationService.DepositConfirmed(deposit1);

            Assert.IsTrue(depositResponse);
            Balance balance = balanceRepository.GetBalanceByCurrencyAndAccountId(baseCurrency, user1Account);

            Assert.IsNotNull(balance);
            Assert.AreEqual(deposit1.Amount, balance.CurrentBalance);
            Assert.AreEqual(deposit1.Amount, balance.AvailableBalance);
            Assert.AreEqual(balance.PendingBalance, 0);

            // Retrieve Quote Currency balance for user 1
            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(quoteCurrency, user1Account);
            Assert.IsNotNull(balance);
            Assert.AreEqual(user1QuoteInitialBalance.CurrentBalance, balance.CurrentBalance);
            Assert.AreEqual(user1QuoteInitialBalance.AvailableBalance, balance.AvailableBalance);
            Assert.AreEqual(0, balance.PendingBalance);

            // Retrieve BTC balance for user 2
            depositResponse = fundsValidationService.DepositConfirmed(deposit2);
            Assert.IsTrue(depositResponse);
            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(baseCurrency, user2Account);
            Assert.IsNotNull(balance);
            Assert.AreEqual(deposit2.Amount, balance.CurrentBalance);
            Assert.AreEqual(deposit2.Amount, balance.AvailableBalance);
            Assert.AreEqual(balance.PendingBalance, 0);

            // Retrieve USD balance for user 2
            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(quoteCurrency, user2Account);
            Assert.IsNotNull(balance);
            Assert.AreEqual(user2QuoteInitialBalance.CurrentBalance, balance.CurrentBalance);
            Assert.AreEqual(user2QuoteInitialBalance.AvailableBalance, balance.AvailableBalance);
            Assert.AreEqual(0, balance.PendingBalance);

            // Order Validation for User 1's Account
            decimal volume             = 1.2m;
            decimal price              = 590;
            string  buy                = "buy";
            string  sell               = "sell";
            string  buyOrderId         = "buy123";
            string  sellOrderId        = "sell123";
            bool    validationResponse = fundsValidationService.ValidateFundsForOrder(user1Account, baseCurrency, quoteCurrency,
                                                                                      volume, price, buy, buyOrderId);

            Assert.IsTrue(validationResponse);

            decimal user1Fee = feeCalculationService.GetFee(baseCurrency, quoteCurrency, user1Account, volume, price);
            decimal user2Fee = feeCalculationService.GetFee(baseCurrency, quoteCurrency, user2Account, volume, price);

            // Base Currency Balance for User Account 1
            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(baseCurrency, user1Account);
            Assert.IsNotNull(balance);
            Assert.AreEqual(baseDepositAmount, balance.AvailableBalance);
            Assert.AreEqual(baseDepositAmount, balance.CurrentBalance);
            Assert.AreEqual(0, balance.PendingBalance);

            // Quote Currency Balance for User Account 1
            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(quoteCurrency, user1Account);
            Assert.IsNotNull(balance);
            Assert.AreEqual(quoteDepositAmount - (volume * price), balance.AvailableBalance);
            Assert.AreEqual(quoteDepositAmount, balance.CurrentBalance);
            Assert.AreEqual(volume * price, balance.PendingBalance);

            // Validation of User 2's order
            validationResponse = fundsValidationService.ValidateFundsForOrder(user2Account, baseCurrency, quoteCurrency,
                                                                              volume, price, sell, sellOrderId);
            Assert.IsTrue(validationResponse);

            // Base Currency Balance for User Account 2
            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(baseCurrency, user2Account);
            Assert.IsNotNull(balance);
            Assert.AreEqual(baseDepositAmount - volume, balance.AvailableBalance);
            Assert.AreEqual(baseDepositAmount, balance.CurrentBalance);
            Assert.AreEqual(volume, balance.PendingBalance);

            // Quote Currency Balance for User Account 2
            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(quoteCurrency, user2Account);
            Assert.IsNotNull(balance);
            Assert.AreEqual(quoteDepositAmount, balance.AvailableBalance);
            Assert.AreEqual(quoteDepositAmount, balance.CurrentBalance);
            Assert.AreEqual(0, balance.PendingBalance);

            string tradeId = "tradeid123";
            bool   tradeExecutedResponse = fundsValidationService.TradeExecuted(baseCurrency.Name, quoteCurrency.Name,
                                                                                volume, price, DateTime.Now, tradeId, user1Account.Value, user2Account.Value, buyOrderId, sellOrderId);

            Assert.IsTrue(tradeExecutedResponse);

            // Base Currency Balance for User Account 1
            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(baseCurrency, user1Account);
            Assert.IsNotNull(balance);
            Assert.AreEqual(baseDepositAmount + volume, balance.AvailableBalance);
            Assert.AreEqual(baseDepositAmount + volume, balance.CurrentBalance);
            Assert.AreEqual(0, balance.PendingBalance);

            // Quote Currency Balance for User Account 1
            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(quoteCurrency, user1Account);
            Assert.IsNotNull(balance);
            Assert.AreEqual(quoteDepositAmount - (volume * price) - user1Fee, balance.AvailableBalance);
            Assert.AreEqual(quoteDepositAmount - (volume * price) - user1Fee, balance.CurrentBalance);
            Assert.AreEqual(0, balance.PendingBalance);

            // Base Currency Balance for User Account 2
            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(baseCurrency, user2Account);
            Assert.IsNotNull(balance);
            Assert.AreEqual(baseDepositAmount - (volume), balance.AvailableBalance);
            Assert.AreEqual(baseDepositAmount - (volume), balance.CurrentBalance);
            Assert.AreEqual(0, balance.PendingBalance);

            // Quote Currency Balance for User Account 2
            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(quoteCurrency, user2Account);
            Assert.IsNotNull(balance);
            Assert.AreEqual(quoteDepositAmount + (volume * price) - user2Fee, balance.AvailableBalance);
            Assert.AreEqual(quoteDepositAmount + (volume * price) - user2Fee, balance.CurrentBalance);
            Assert.AreEqual(0, balance.PendingBalance);

            decimal withdrawAmount = 0.3M;
            // Withdraw Base Currency
            Withdraw validateFundsForWithdrawal = fundsValidationService.ValidateFundsForWithdrawal(user1Account,
                                                                                                    baseCurrency, withdrawAmount, new TransactionId("transaction123"), new BitcoinAddress("bitcoin123"));

            Assert.IsNotNull(validateFundsForWithdrawal);
            WithdrawFees withdrawFee = withdrawFeesRepository.GetWithdrawFeesByCurrencyName(baseCurrency.Name);

            // Base Currency Balance for User Account 1
            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(baseCurrency, user1Account);
            Assert.IsNotNull(balance);
            Assert.AreEqual(baseDepositAmount + volume - withdrawAmount, balance.AvailableBalance);
            Assert.AreEqual(baseDepositAmount + volume, balance.CurrentBalance);
            Assert.AreEqual(withdrawAmount, balance.PendingBalance);

            bool withdrawalExecuted = fundsValidationService.WithdrawalExecuted(validateFundsForWithdrawal);

            Assert.IsTrue(withdrawalExecuted);

            // Base Currency Balance for User Account 1
            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(baseCurrency, user1Account);
            Assert.IsNotNull(balance);
            Assert.AreEqual(baseDepositAmount + volume - withdrawAmount, balance.AvailableBalance);
            Assert.AreEqual(baseDepositAmount + volume - withdrawAmount, balance.CurrentBalance);
            Assert.AreEqual(0, balance.PendingBalance);

            // EXCEPTION OCCURS HERE when the user tries to withdraw more than their remaining limit
            // Withdraw will fail because the amount requested is greater than the maximum limit threshold
            validateFundsForWithdrawal = fundsValidationService.ValidateFundsForWithdrawal(user1Account,
                                                                                           baseCurrency, baseDepositAmount + volume /*Excluding previous withdrawal amount*/,
                                                                                           new TransactionId("transaction123"), new BitcoinAddress("bitcoin123"));
            Assert.IsNull(validateFundsForWithdrawal);

            // Base Currency for User Account 1
            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(baseCurrency, user1Account);
            Assert.IsNotNull(balance);
            Assert.AreEqual(baseDepositAmount + volume - withdrawAmount, balance.AvailableBalance);
            Assert.AreEqual(baseDepositAmount + volume - withdrawAmount, balance.CurrentBalance);
            Assert.AreEqual(0, balance.PendingBalance);
        }
Пример #10
0
        public void DepositAndWithdrawTest2_TestsByMakingDepositsAndWIthdrawalsRandomly_VerifiesThroughDatabasequeriesAndReturnValues()
        {
            // Scenario: Withdraw(fail due to insufficient balance) -->
            // Deposit(Confirm) --> Withdraw(Pending) --> Withdraw(Fail due to insufficient available and enough
            // pending balance) --> Withdraw(Success) --> Deposit(Fail due to over the limit)
            IFundsValidationService     fundsValidationService     = (IFundsValidationService)ContextRegistry.GetContext()["FundsValidationService"];
            IFundsPersistenceRepository fundsPersistenceRepository = (IFundsPersistenceRepository)ContextRegistry.GetContext()["FundsPersistenceRepository"];
            IBalanceRepository          balanceRepository          = (IBalanceRepository)ContextRegistry.GetContext()["BalanceRepository"];
            IDepositIdGeneratorService  depositIdGeneratorService  = (IDepositIdGeneratorService)ContextRegistry.GetContext()["DepositIdGeneratorService"];
            IWithdrawFeesRepository     withdrawFeesRepository     = (IWithdrawFeesRepository)ContextRegistry.GetContext()["WithdrawFeesRepository"];

            AccountId accountId = new AccountId(123);
            Currency  currency  = new Currency("BTC", true);

            Deposit deposit = new Deposit(currency, depositIdGeneratorService.GenerateId(), DateTime.Now,
                                          DepositType.Default, 1.4m, 0, TransactionStatus.Pending, accountId,
                                          new TransactionId("123"), new BitcoinAddress("bitcoin123"));

            deposit.IncrementConfirmations(7);
            fundsPersistenceRepository.SaveOrUpdate(deposit);

            // Retrieve balance
            Balance balance = balanceRepository.GetBalanceByCurrencyAndAccountId(currency, accountId);

            Assert.IsNull(balance);

            // Deposit
            bool depositResponse = fundsValidationService.DepositConfirmed(deposit);

            Assert.IsTrue(depositResponse);

            // Check balance
            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(currency, accountId);
            Assert.IsNotNull(balance);
            Assert.AreEqual(deposit.Amount, balance.CurrentBalance);
            Assert.AreEqual(deposit.Amount, balance.AvailableBalance);
            Assert.AreEqual(balance.PendingBalance, 0);

            WithdrawFees withdrawFee = withdrawFeesRepository.GetWithdrawFeesByCurrencyName(currency.Name);

            // Withdraw
            Withdraw withdrawal = fundsValidationService.ValidateFundsForWithdrawal(accountId, currency,
                                                                                    1.3M, new TransactionId("transaction123"), new BitcoinAddress("bitcoin123"));

            Assert.IsNotNull(withdrawal);
            Assert.AreEqual(TransactionStatus.Pending, withdrawal.Status);

            // Check balance
            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(currency, accountId);
            Assert.IsNotNull(balance);
            Assert.AreEqual(Math.Round(1.4M - 1.3M, 5), Math.Round(balance.AvailableBalance, 5));
            Assert.AreEqual(Math.Round(1.4M, 5), Math.Round(balance.CurrentBalance, 5));
            Assert.AreEqual(1.3m, balance.PendingBalance);

            // Withdraw # 1 Confirmed
            bool withdrawalExecuted = fundsValidationService.WithdrawalExecuted(withdrawal);

            Assert.IsTrue(withdrawalExecuted);
            Assert.AreEqual(TransactionStatus.Confirmed, withdrawal.Status);

            // Check balance
            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(currency, accountId);
            Assert.IsNotNull(balance);
            Assert.AreEqual(Math.Round(1.4M - 1.3M, 5), Math.Round(balance.CurrentBalance, 5));
            Assert.AreEqual(Math.Round(1.4M - 1.3M, 5), Math.Round(balance.AvailableBalance, 5));
            Assert.AreEqual(0, balance.PendingBalance);

            // Withdraw # 2: Exception Expected
            withdrawal = fundsValidationService.ValidateFundsForWithdrawal(accountId, currency,
                                                                           0.7M, new TransactionId("transaction123"), new BitcoinAddress("bitcoin123"));
            Assert.IsNull(withdrawal);

            // Check balance
            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(currency, accountId);
            Assert.IsNotNull(balance);
            Assert.AreEqual(Math.Round(1.4M - 1.3M, 5), Math.Round(balance.CurrentBalance, 5));
            Assert.AreEqual(Math.Round(1.4M - 1.3M, 5), Math.Round(balance.AvailableBalance, 5));
            Assert.AreEqual(0, balance.PendingBalance);

            // Withdraw # 3
            withdrawal = fundsValidationService.ValidateFundsForWithdrawal(accountId, currency,
                                                                           0.098M, new TransactionId("transaction123"), new BitcoinAddress("bitcoin123"));
            Assert.IsNotNull(withdrawal);
            Assert.AreEqual(TransactionStatus.Pending, withdrawal.Status);
            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(currency, accountId);
            Assert.IsNotNull(balance);
            Assert.AreEqual(Math.Round(1.4M - 1.3M - 0.1M - (withdrawFee.Fee * 2), 5), Math.Round(balance.AvailableBalance, 5));
            Assert.AreEqual(Math.Round(1.4M - 1.3M, 5), Math.Round(balance.CurrentBalance, 5));
            Assert.AreEqual(0.1M, balance.PendingBalance);

            // Withdraw # 3 Confirmed
            withdrawalExecuted = fundsValidationService.WithdrawalExecuted(withdrawal);
            Assert.IsTrue(withdrawalExecuted);
            Assert.AreEqual(TransactionStatus.Confirmed, withdrawal.Status);

            // Check balance
            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(currency, accountId);
            Assert.IsNotNull(balance);
            Assert.AreEqual(Math.Round(1.4M - 1.3M - 0.1M - (withdrawFee.Fee * 2), 5), Math.Round(balance.CurrentBalance, 5));
            Assert.AreEqual(Math.Round(1.4M - 1.3M - 0.1M - (withdrawFee.Fee * 2), 5), Math.Round(balance.AvailableBalance, 5));
            Assert.AreEqual(0, balance.PendingBalance);

            // Over the limit Deposit
            deposit = new Deposit(currency, depositIdGeneratorService.GenerateId(), DateTime.Now,
                                  DepositType.Default, 1.4m, 0, TransactionStatus.Pending, accountId,
                                  new TransactionId("123"), new BitcoinAddress("bitcoin123"));
            deposit.IncrementConfirmations(7);
            fundsPersistenceRepository.SaveOrUpdate(deposit);

            fundsValidationService.DepositConfirmed(deposit);
            // Check balance
            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(currency, accountId);
            Assert.IsNotNull(balance);
            Assert.AreEqual(Math.Round(1.4M - 1.3M - 0.1M - (withdrawFee.Fee * 2), 5), Math.Round(balance.CurrentBalance, 5));
            Assert.AreEqual(Math.Round(1.4M - 1.3M - 0.1M - (withdrawFee.Fee * 2), 5), Math.Round(balance.AvailableBalance, 5));
            Assert.IsTrue(balance.IsFrozen);
        }
        public void WithdrawExecutedEventTest_ChecksThatTheEventIsProperlyRaisedAndHandledWhenWithdrawIsSubmittedToTheNetwork_VerifiesThroughRaisedEvent()
        {
            // Withdraw is submitted and upon submission to network an event is raised confirming withdrawal execution which
            // is handled and balance is updated. This whole process of events firing and balance validation is checked by this
            // test case
            IWithdrawApplicationService   withdrawApplicationService = (IWithdrawApplicationService)ContextRegistry.GetContext()["WithdrawApplicationService"];
            IWithdrawRepository           withdrawRepository         = (IWithdrawRepository)ContextRegistry.GetContext()["WithdrawRepository"];
            IFundsPersistenceRepository   fundsPersistenceRepository = (IFundsPersistenceRepository)ContextRegistry.GetContext()["FundsPersistenceRepository"];
            IBalanceRepository            balanceRepository          = (IBalanceRepository)ContextRegistry.GetContext()["BalanceRepository"];
            IWithdrawFeesRepository       withdrawFeesRepository     = (IWithdrawFeesRepository)ContextRegistry.GetContext()["WithdrawFeesRepository"];
            IWithdrawLimitRepository      withdrawLimitRepository    = (IWithdrawLimitRepository)ContextRegistry.GetContext()["WithdrawLimitRepository"];
            IClientInteractionService     clientInteractionService   = (IClientInteractionService)ContextRegistry.GetContext()["ClientInteractionService"];
            StubTierLevelRetrievalService tierLevelRetrievalService  = (ITierLevelRetrievalService)ContextRegistry.GetContext()["TierLevelRetrievalService"] as StubTierLevelRetrievalService;

            Assert.IsNotNull(tierLevelRetrievalService);
            tierLevelRetrievalService.SetTierLevel(TierConstants.TierLevel1);
            AccountId      accountId      = new AccountId(123);
            Currency       currency       = new Currency(CurrencyConstants.Btc, true);
            BitcoinAddress bitcoinAddress = new BitcoinAddress("bitcoinaddress1");
            WithdrawLimit  withdrawLimit  = withdrawLimitRepository.GetLimitByTierLevelAndCurrency(TierConstants.TierLevel1, LimitsCurrency.Default.ToString());

            Assert.IsNotNull(withdrawLimit);
            decimal amount = withdrawLimit.DailyLimit;

            Balance balance = new Balance(currency, accountId, amount + 1, amount + 1);

            fundsPersistenceRepository.SaveOrUpdate(balance);
            bool             withdrawEventRaised = false;
            ManualResetEvent manualResetEvent    = new ManualResetEvent(false);
            Withdraw         receivedWithdraw    = null;

            clientInteractionService.WithdrawExecuted += delegate(Withdraw incomingWithdraw)
            {
                withdrawEventRaised = true;
                receivedWithdraw    = incomingWithdraw;
                manualResetEvent.Set();
            };

            CommitWithdrawResponse commitWithdrawResponse = withdrawApplicationService.CommitWithdrawal(new CommitWithdrawCommand(accountId.Value, currency.Name, currency.IsCryptoCurrency, bitcoinAddress.Value, amount));

            Assert.IsNotNull(commitWithdrawResponse);
            Assert.IsTrue(commitWithdrawResponse.CommitSuccessful);
            manualResetEvent.WaitOne();

            // Apply assertions after event has been handled
            Assert.IsTrue(withdrawEventRaised);
            Assert.IsNotNull(receivedWithdraw);
            Withdraw withdraw = withdrawRepository.GetWithdrawByWithdrawId(commitWithdrawResponse.WithdrawId);

            Assert.IsNotNull(withdraw);
            Assert.AreEqual(accountId.Value, withdraw.AccountId.Value);
            Assert.AreEqual(currency.Name, withdraw.Currency.Name);
            Assert.AreEqual(currency.IsCryptoCurrency, withdraw.Currency.IsCryptoCurrency);
            Assert.AreEqual(amount - withdraw.Fee, withdraw.Amount);
            Assert.AreEqual(TransactionStatus.Confirmed, withdraw.Status);

            Assert.AreEqual(receivedWithdraw.AccountId.Value, withdraw.AccountId.Value);
            Assert.AreEqual(receivedWithdraw.TransactionId.Value, withdraw.TransactionId.Value);
            Assert.AreEqual(receivedWithdraw.BitcoinAddress.Value, withdraw.BitcoinAddress.Value);
            Assert.AreEqual(receivedWithdraw.Currency.Name, withdraw.Currency.Name);
            Assert.AreEqual(TransactionStatus.Confirmed, withdraw.Status);
            Assert.AreEqual(receivedWithdraw.Amount, withdraw.Amount);
            Assert.AreEqual(receivedWithdraw.WithdrawId, withdraw.WithdrawId);

            WithdrawFees withdrawFees = withdrawFeesRepository.GetWithdrawFeesByCurrencyName(currency.Name);

            Assert.IsNotNull(withdrawFees);

            balance = balanceRepository.GetBalanceByCurrencyAndAccountId(currency, accountId);
            Assert.IsNotNull(balance);
            Assert.AreEqual((amount + 1) - (amount), balance.AvailableBalance);
            Assert.AreEqual((amount + 1) - (amount), balance.CurrentBalance);
            Assert.AreEqual(0, balance.PendingBalance);
        }