public void WithdrawLimitScenario15Test_ChecksIfTheScenarioProceedsAsExpected_VerifiesThroughReturnedValue()
        {
            // Check to see the withheld amount
            IWithdrawLimitEvaluationService withdrawLimitEvaluationService = new WithdrawLimitEvaluationService();

            decimal dailyLimit   = 1000;
            decimal monthlyLimit = 5000;
            // We have suficient balance for this case
            decimal availableBalance = 1000 + 100;
            decimal currentBalance   = 1000 + 110;

            List <Withdraw> withdraws          = new List <Withdraw>();
            WithdrawLimit   withdrawLimit      = new WithdrawLimit("Tier0", dailyLimit, monthlyLimit);
            bool            evaluationResponse = withdrawLimitEvaluationService.EvaluateMaximumWithdrawLimit(900, withdraws,
                                                                                                             withdrawLimit, availableBalance, currentBalance);

            Assert.IsTrue(evaluationResponse);

            Assert.AreEqual(1000, withdrawLimitEvaluationService.DailyLimit);
            Assert.AreEqual(5000, withdrawLimitEvaluationService.MonthlyLimit);
            Assert.AreEqual(0, withdrawLimitEvaluationService.DailyLimitUsed);
            Assert.AreEqual(0, withdrawLimitEvaluationService.MonthlyLimitUsed);
            Assert.AreEqual(1000, withdrawLimitEvaluationService.MaximumWithdraw);
            Assert.AreEqual(currentBalance - availableBalance, withdrawLimitEvaluationService.WithheldAmount);
        }
        public void WithdrawLimitScenario2NotEnoughBalanceTest_ChecksIfTheScenarioProceedsAsExpected_VerifiesThroughReturnedValue()
        {
            // Balance is less than the evaluated Maximum Withdrawal threshold
            IWithdrawLimitEvaluationService withdrawLimitEvaluationService = new WithdrawLimitEvaluationService();

            decimal dailyLimit   = 1000;
            decimal monthlyLimit = 5000;

            // Balance is less than the calculated maximum threshold
            decimal availableBalance = 1000 - 1.09m;
            decimal currentBalance   = 1000 - 1.09m;

            List <Withdraw> ledgers            = new List <Withdraw>();
            WithdrawLimit   withdrawLimit      = new WithdrawLimit("Tier0", dailyLimit, monthlyLimit);
            bool            evaluationResponse = withdrawLimitEvaluationService.EvaluateMaximumWithdrawLimit(999, ledgers,
                                                                                                             withdrawLimit, availableBalance, currentBalance);

            Assert.IsFalse(evaluationResponse);

            Assert.AreEqual(1000, withdrawLimitEvaluationService.DailyLimit);
            Assert.AreEqual(5000, withdrawLimitEvaluationService.MonthlyLimit);
            Assert.AreEqual(0, withdrawLimitEvaluationService.DailyLimitUsed);
            Assert.AreEqual(0, withdrawLimitEvaluationService.MonthlyLimitUsed);
            Assert.AreEqual(Math.Round(availableBalance, 5), withdrawLimitEvaluationService.MaximumWithdraw);
            Assert.AreEqual(0, withdrawLimitEvaluationService.WithheldAmount);
        }
        public void WithdrawLimitScenario3Test_ChecksIfTheScenarioProceedsAsExpected_VerifiesThroughReturnedValue()
        {
            // Scenario: DailyLimit = 0/1000, MonthlyLimit = 0/5000
            IWithdrawLimitEvaluationService withdrawLimitEvaluationService = new WithdrawLimitEvaluationService();
            Currency  currency     = new Currency("XBT");
            string    withdrawId   = "withdrawid123";
            AccountId accountId    = new AccountId(123);
            decimal   dailyLimit   = 1000;
            decimal   monthlyLimit = 5000;
            // Balance is less than the calculated maximum threshold
            decimal availableBalance = 1000 - 1.09m;
            decimal currentBalance   = 1000 - 1.09m;

            List <Withdraw> withdraws = new List <Withdraw>();
            Withdraw        withdraw  = new Withdraw(currency, "withdrawid123", DateTime.Now.AddDays(-40), WithdrawType.Bitcoin, 500,
                                                     0.001m, TransactionStatus.Pending, accountId,
                                                     new BitcoinAddress("bitcoin123"));

            withdraws.Add(withdraw);
            WithdrawLimit withdrawLimit      = new WithdrawLimit("Tier0", dailyLimit, monthlyLimit);
            bool          evaluationResponse = withdrawLimitEvaluationService.EvaluateMaximumWithdrawLimit(999, withdraws,
                                                                                                           withdrawLimit, availableBalance, currentBalance);

            Assert.IsFalse(evaluationResponse);

            Assert.AreEqual(1000, withdrawLimitEvaluationService.DailyLimit);
            Assert.AreEqual(5000, withdrawLimitEvaluationService.MonthlyLimit);
            Assert.AreEqual(0, withdrawLimitEvaluationService.DailyLimitUsed);
            Assert.AreEqual(0, withdrawLimitEvaluationService.MonthlyLimitUsed);
            Assert.AreEqual(Math.Round(availableBalance, 5), withdrawLimitEvaluationService.MaximumWithdraw);
            Assert.AreEqual(0, withdrawLimitEvaluationService.WithheldAmount);
        }
        public void ValidationForOrderFailTest_TestsIfValidationOfFundsFailsAsExpected_VerifiesThroughTheResponseReturned()
        {
            var mockFundsRepository                = new MockFundsRepository();
            var mockBalanceRepository              = new MockBalanceRepository();
            var mockFeeCalculationService          = new MockFeeCalculationService();
            var mockWithdrawFeesRepository         = new MockWithdrawFeesRepository();
            var mockWithdrawIdGeneratorService     = new MockWithdrawIdGeneratorService();
            var depositLimitEvaluationService      = new DepositLimitEvaluationService();
            var mockLedgerRepository               = new MockLedgerRepository();
            var mockDepositLimitRepository         = new MockDepositLimitRepository();
            var mockWithdrawLimitEvaluationService = new WithdrawLimitEvaluationService();
            var mockWithdrawLimitRepository        = new MockWithdrawLimitRepository();
            var mockTierLevelRetrievalService      = new MockTierLevelRetrievalService();
            var mockWithdrawRepository             = new MockWithdrawRepository();
            var tierValidationService              = new TierValidationService();
            var mockBboRetrievalService            = new MockBboRetrievalService();
            var mockLimitsConfigurationService     = new LimitsConfigurationService(mockDepositLimitRepository,
                                                                                    depositLimitEvaluationService, mockWithdrawLimitRepository, mockWithdrawLimitEvaluationService, mockBboRetrievalService);
            TransactionService transactionService = new TransactionService(mockFundsRepository, new MockLedgerGeneratorService(),
                                                                           mockLimitsConfigurationService);
            FundsValidationService fundsValidationService = new FundsValidationService(transactionService,
                                                                                       mockFundsRepository, mockBalanceRepository, mockFeeCalculationService, mockWithdrawFeesRepository,
                                                                                       mockWithdrawIdGeneratorService, mockLedgerRepository, depositLimitEvaluationService,
                                                                                       mockDepositLimitRepository, mockWithdrawLimitEvaluationService, mockWithdrawLimitRepository,
                                                                                       mockTierLevelRetrievalService, mockWithdrawRepository, tierValidationService, mockLimitsConfigurationService);

            bool validateFundsForOrder = fundsValidationService.ValidateFundsForOrder(new AccountId(123),
                                                                                      new Currency("XBT", true), new Currency("USD"), 300, 101, "buy", "order123");

            Assert.IsFalse(validateFundsForOrder);
        }
        public void WithdrawFailTest_TestsIfWithdrawValidationisReturnedTrueWhenSufficientBalanceIsNotAvailable_VerifiesThroughReturnedValue()
        {
            var mockFundsRepository                = new MockFundsRepository();
            var mockBalanceRepository              = new MockBalanceRepository();
            var mockFeeCalculationService          = new MockFeeCalculationService();
            var mockWithdrawFeesRepository         = new MockWithdrawFeesRepository();
            var mockWithdrawIdGeneratorService     = new MockWithdrawIdGeneratorService();
            var depositLimitEvaluationService      = new DepositLimitEvaluationService();
            var mockLedgerRepository               = new MockLedgerRepository();
            var mockDepositLimitRepository         = new MockDepositLimitRepository();
            var mockWithdrawLimitEvaluationService = new WithdrawLimitEvaluationService();
            var mockWithdrawLimitRepository        = new MockWithdrawLimitRepository();
            var mockTierLevelRetrievalService      = new MockTierLevelRetrievalService();
            var mockWithdrawRepository             = new MockWithdrawRepository();
            var tierValidationService              = new TierValidationService();
            var mockBboRetrievalService            = new MockBboRetrievalService();
            var mockLimitsConfigurationService     = new LimitsConfigurationService(mockDepositLimitRepository,
                                                                                    depositLimitEvaluationService, mockWithdrawLimitRepository, mockWithdrawLimitEvaluationService, mockBboRetrievalService);
            TransactionService transactionService = new TransactionService(mockFundsRepository, new MockLedgerGeneratorService(),
                                                                           mockLimitsConfigurationService);
            FundsValidationService fundsValidationService = new FundsValidationService(transactionService,
                                                                                       mockFundsRepository, mockBalanceRepository, mockFeeCalculationService, mockWithdrawFeesRepository,
                                                                                       mockWithdrawIdGeneratorService, mockLedgerRepository, depositLimitEvaluationService,
                                                                                       mockDepositLimitRepository, mockWithdrawLimitEvaluationService, mockWithdrawLimitRepository,
                                                                                       mockTierLevelRetrievalService, mockWithdrawRepository, tierValidationService, mockLimitsConfigurationService);
            Balance balance = new Balance(new Currency("XBT", true), new AccountId(123), 100, 100);

            mockBalanceRepository.AddBalance(balance);

            Withdraw withdrawalResponse = fundsValidationService.ValidateFundsForWithdrawal(balance.AccountId, balance.Currency,
                                                                                            100.0002M, new TransactionId("transaction123"), new BitcoinAddress("bitcoinid123"));

            Assert.IsNull(withdrawalResponse);
        }
        public void WithdrawLimitScenario14Test_ChecksIfTheScenarioProceedsAsExpected_VerifiesThroughReturnedValue()
        {
            // Scenario: DailyLimit = 500/1000, MonthlyLimit = 4500/5000  with insufficient balance
            IWithdrawLimitEvaluationService withdrawLimitEvaluationService = new WithdrawLimitEvaluationService();
            Currency  currency     = new Currency("XBT");
            AccountId accountId    = new AccountId(123);
            decimal   dailyLimit   = 1000;
            decimal   monthlyLimit = 5000;
            // Balance is less than the calculated maximum threshold foor the remaining quantity from the daily limit used
            decimal availableBalance = 500 - 0.09m;
            decimal currentBalance   = 500 - 0.09m;
            // Amount that can be safely withdrawn
            decimal safeAmount = availableBalance;
            decimal fee        = 0.001m;

            List <Withdraw> withdraws = new List <Withdraw>();
            Withdraw        withdraw  = new Withdraw(currency, "withdrawid123", DateTime.Now.AddDays(-29), WithdrawType.Bitcoin,
                                                     4000, fee, TransactionStatus.Pending, accountId,
                                                     new BitcoinAddress("bitcoin123"));
            Withdraw withdraw2 = new Withdraw(currency, "withdrawid123", DateTime.Now.AddMinutes(-29), WithdrawType.Bitcoin,
                                              500, fee, TransactionStatus.Pending, accountId,
                                              new BitcoinAddress("bitcoin123"));

            withdraws.Add(withdraw);
            withdraws.Add(withdraw2);

            WithdrawLimit withdrawLimit      = new WithdrawLimit("Tier0", dailyLimit, monthlyLimit);
            bool          evaluationResponse = withdrawLimitEvaluationService.EvaluateMaximumWithdrawLimit(500, withdraws,
                                                                                                           withdrawLimit, availableBalance, currentBalance);

            Assert.IsFalse(evaluationResponse);

            Assert.AreEqual(1000, withdrawLimitEvaluationService.DailyLimit);
            Assert.AreEqual(5000, withdrawLimitEvaluationService.MonthlyLimit);
            Assert.AreEqual(500 + fee, withdrawLimitEvaluationService.DailyLimitUsed);
            Assert.AreEqual(4500 + fee * 2, withdrawLimitEvaluationService.MonthlyLimitUsed);
            Assert.AreEqual(Math.Round(availableBalance, 5), withdrawLimitEvaluationService.MaximumWithdraw);
            Assert.AreEqual(0, withdrawLimitEvaluationService.WithheldAmount);

            // Withdraw below the threshold limit
            evaluationResponse = withdrawLimitEvaluationService.EvaluateMaximumWithdrawLimit(safeAmount - 10, withdraws,
                                                                                             withdrawLimit, availableBalance, currentBalance);
            Assert.IsTrue(evaluationResponse);

            Assert.AreEqual(1000, withdrawLimitEvaluationService.DailyLimit);
            Assert.AreEqual(5000, withdrawLimitEvaluationService.MonthlyLimit);
            Assert.AreEqual(500 + fee, withdrawLimitEvaluationService.DailyLimitUsed);
            Assert.AreEqual(4500 + fee * 2, withdrawLimitEvaluationService.MonthlyLimitUsed);
            Assert.AreEqual(Math.Round(availableBalance, 5), withdrawLimitEvaluationService.MaximumWithdraw);
            Assert.AreEqual(0, withdrawLimitEvaluationService.WithheldAmount);
        }
        public void WithdrawLimitScenario7Test_ChecksIfTheScenarioProceedsAsExpected_VerifiesThroughReturnedValue()
        {
            // Scenario: DailyLimit = 500/1000, MonthlyLimit = 4000/5000
            IWithdrawLimitEvaluationService withdrawLimitEvaluationService = new WithdrawLimitEvaluationService();
            Currency  currency     = new Currency("XBT");
            AccountId accountId    = new AccountId(123);
            decimal   dailyLimit   = 1000;
            decimal   monthlyLimit = 5000;

            decimal availableBalance = 1000;
            decimal currentBalance   = 1000;
            decimal fee = 0.001m;

            List <Withdraw> withdraws = new List <Withdraw>();
            Withdraw        withdraw  = new Withdraw(currency, "withdrawid123", DateTime.Now.AddDays(-29), WithdrawType.Bitcoin,
                                                     3500, fee, TransactionStatus.Pending, accountId,
                                                     new BitcoinAddress("bitcoin123"));
            Withdraw withdraw2 = new Withdraw(currency, "withdrawid123", DateTime.Now.AddMinutes(-5), WithdrawType.Bitcoin,
                                              500, fee, TransactionStatus.Pending, accountId,
                                              new BitcoinAddress("bitcoin123"));

            withdraws.Add(withdraw);
            withdraws.Add(withdraw2);

            WithdrawLimit withdrawLimit      = new WithdrawLimit("Tier0", dailyLimit, monthlyLimit);
            bool          evaluationResponse = withdrawLimitEvaluationService.EvaluateMaximumWithdrawLimit(600 - fee * 2, withdraws,
                                                                                                           withdrawLimit, availableBalance, currentBalance);

            Assert.IsFalse(evaluationResponse);

            Assert.AreEqual(1000, withdrawLimitEvaluationService.DailyLimit);
            Assert.AreEqual(5000, withdrawLimitEvaluationService.MonthlyLimit);
            Assert.AreEqual(500 + fee, withdrawLimitEvaluationService.DailyLimitUsed);
            Assert.AreEqual(4000 + fee * 2, withdrawLimitEvaluationService.MonthlyLimitUsed);
            Assert.AreEqual(500 - fee, withdrawLimitEvaluationService.MaximumWithdraw);
            Assert.AreEqual(0, withdrawLimitEvaluationService.WithheldAmount);

            // Withdraw below the threshold limit
            evaluationResponse = withdrawLimitEvaluationService.EvaluateMaximumWithdrawLimit(500 - fee * 2, withdraws,
                                                                                             withdrawLimit, availableBalance, currentBalance);
            Assert.IsTrue(evaluationResponse);

            Assert.AreEqual(1000, withdrawLimitEvaluationService.DailyLimit);
            Assert.AreEqual(5000, withdrawLimitEvaluationService.MonthlyLimit);
            Assert.AreEqual(500 + fee, withdrawLimitEvaluationService.DailyLimitUsed);
            Assert.AreEqual(4000 + fee * 2, withdrawLimitEvaluationService.MonthlyLimitUsed);
            Assert.AreEqual(500 - fee, withdrawLimitEvaluationService.MaximumWithdraw);
            Assert.AreEqual(0, withdrawLimitEvaluationService.WithheldAmount);
        }
        public void WithdrawConfirmedTest_TestIfWithdrawalConfirmationExecutesAsExpected_TestsThroughReturnedValue()
        {
            var mockFundsRepository                = new MockFundsRepository();
            var mockBalanceRepository              = new MockBalanceRepository();
            var mockFeeCalculationService          = new MockFeeCalculationService();
            var mockWithdrawFeesRepository         = new MockWithdrawFeesRepository();
            var mockWithdrawIdGeneratorService     = new MockWithdrawIdGeneratorService();
            var depositLimitEvaluationService      = new DepositLimitEvaluationService();
            var mockLedgerRepository               = new MockLedgerRepository();
            var mockDepositLimitRepository         = new MockDepositLimitRepository();
            var mockWithdrawLimitEvaluationService = new WithdrawLimitEvaluationService();
            var mockWithdrawLimitRepository        = new MockWithdrawLimitRepository();
            var mockTierLevelRetrievalService      = new MockTierLevelRetrievalService();
            var mockWithdrawRepository             = new MockWithdrawRepository();
            var tierValidationService              = new TierValidationService();
            var mockBboRetrievalService            = new MockBboRetrievalService();
            var mockLimitsConfigurationService     = new LimitsConfigurationService(mockDepositLimitRepository,
                                                                                    depositLimitEvaluationService, mockWithdrawLimitRepository, mockWithdrawLimitEvaluationService, mockBboRetrievalService);
            TransactionService transactionService = new TransactionService(mockFundsRepository, new MockLedgerGeneratorService(),
                                                                           mockLimitsConfigurationService);
            FundsValidationService fundsValidationService = new FundsValidationService(transactionService,
                                                                                       mockFundsRepository, mockBalanceRepository, mockFeeCalculationService, mockWithdrawFeesRepository,
                                                                                       mockWithdrawIdGeneratorService, mockLedgerRepository, depositLimitEvaluationService,
                                                                                       mockDepositLimitRepository, mockWithdrawLimitEvaluationService, mockWithdrawLimitRepository,
                                                                                       mockTierLevelRetrievalService, mockWithdrawRepository, tierValidationService, mockLimitsConfigurationService);
            Withdraw withdraw = new Withdraw(new Currency("XBT", true), "123", DateTime.Now, WithdrawType.Bitcoin, 0.4m,
                                             0.001m, TransactionStatus.Pending,
                                             new AccountId(123), new BitcoinAddress("bitcoin123"));

            Balance balance = new Balance(withdraw.Currency, withdraw.AccountId, 400, 800);

            mockBalanceRepository.AddBalance(balance);

            Withdraw withdrawalResponse = fundsValidationService.ValidateFundsForWithdrawal(withdraw.AccountId,
                                                                                            withdraw.Currency, withdraw.Amount, withdraw.TransactionId, withdraw.BitcoinAddress);

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

            Assert.IsTrue(withdrawalExecuted);

            Assert.AreEqual(5, mockFundsRepository.GetNumberOfObjects());
        }
        public void DepositAmountTest_TestsIfDepositTransactionProceedsAsExpected_VerifiesThroughReturnedValue()
        {
            var mockDepositIdGeneratorService      = new MockDepositIdGeneratorService();
            var mockDepositRepository              = new MockDepositRepository();
            var mockFundsRepository                = new MockFundsRepository();
            var mockBalanceRepository              = new MockBalanceRepository();
            var mockFeeCalculationService          = new MockFeeCalculationService();
            var mockWithdrawFeesRepository         = new MockWithdrawFeesRepository();
            var mockWithdrawIdGeneratorService     = new MockWithdrawIdGeneratorService();
            var depositLimitEvaluationService      = new DepositLimitEvaluationService();
            var mockLedgerRepository               = new MockLedgerRepository();
            var mockDepositLimitRepository         = new MockDepositLimitRepository();
            var mockWithdrawLimitEvaluationService = new WithdrawLimitEvaluationService();
            var mockWithdrawLimitRepository        = new MockWithdrawLimitRepository();
            var mockTierLevelRetrievalService      = new MockTierLevelRetrievalService();
            var mockWithdrawRepository             = new MockWithdrawRepository();
            var tierValidationService              = new TierValidationService();
            var mockBboRetrievalService            = new MockBboRetrievalService();
            var mockLimitsConfigurationService     = new LimitsConfigurationService(mockDepositLimitRepository,
                                                                                    depositLimitEvaluationService, mockWithdrawLimitRepository, mockWithdrawLimitEvaluationService, mockBboRetrievalService);
            TransactionService transactionService = new TransactionService(mockFundsRepository, new MockLedgerGeneratorService(),
                                                                           mockLimitsConfigurationService);
            FundsValidationService fundsValidationService = new FundsValidationService(transactionService,
                                                                                       mockFundsRepository, mockBalanceRepository, mockFeeCalculationService, mockWithdrawFeesRepository,
                                                                                       mockWithdrawIdGeneratorService, mockLedgerRepository, depositLimitEvaluationService,
                                                                                       mockDepositLimitRepository, mockWithdrawLimitEvaluationService, mockWithdrawLimitRepository,
                                                                                       mockTierLevelRetrievalService, mockWithdrawRepository, tierValidationService, mockLimitsConfigurationService);
            Balance balance = new Balance(new Currency("XBT", true), new AccountId(123), 100, 100);

            mockBalanceRepository.AddBalance(balance);

            Deposit deposit = new Deposit(balance.Currency, mockDepositIdGeneratorService.GenerateId(), DateTime.Now,
                                          DepositType.Default, 1.5m, 0, TransactionStatus.Pending, balance.AccountId, new TransactionId("123"),
                                          new BitcoinAddress("123"));

            deposit.IncrementConfirmations(7);
            mockDepositRepository.Save(deposit);
            bool response = fundsValidationService.DepositConfirmed(deposit);

            Assert.IsTrue(response);
            // 3 Object: 1 = Balance, 2 = Deposit, 3 = Ledger
            Assert.AreEqual(3, mockFundsRepository.GetNumberOfObjects());
        }