/// <summary> /// Initializes a new instance of the <see cref="T:System.Object"/> class. /// </summary> public FundsValidationService(ITransactionService transactionService, IFundsPersistenceRepository fundsPersistenceRepository, IBalanceRepository balanceRepository, IFeeCalculationService feeCalculationService, IWithdrawFeesRepository withdrawFeesRepository, IWithdrawIdGeneratorService withdrawIdGeneratorService, ILedgerRepository ledgerRepository, IDepositLimitEvaluationService depositLimitEvaluationService, IDepositLimitRepository depositLimitRepository, IWithdrawLimitEvaluationService withdrawLimitEvaluationService, IWithdrawLimitRepository withdrawLimitRepository, ITierLevelRetrievalService tierLevelRetrievalService, IWithdrawRepository withdrawRepository, ITierValidationService tierValidationService, ILimitsConfigurationService limitsConfigurationService) { _transactionService = transactionService; _fundsPersistenceRepository = fundsPersistenceRepository; _balanceRepository = balanceRepository; _feeCalculationService = feeCalculationService; _withdrawFeesRepository = withdrawFeesRepository; _withdrawIdGeneratorService = withdrawIdGeneratorService; _ledgerRepository = ledgerRepository; _depositLimitEvaluationService = depositLimitEvaluationService; _depositLimitRepository = depositLimitRepository; _withdrawLimitEvaluationService = withdrawLimitEvaluationService; _withdrawLimitRepository = withdrawLimitRepository; _tierLevelRetrievalService = tierLevelRetrievalService; _withdrawRepository = withdrawRepository; _tierValidationService = tierValidationService; _limitsConfigurationService = limitsConfigurationService; }
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 Setup() { _withdrawFeesRepository = (IWithdrawFeesRepository)ContextRegistry.GetContext()["WithdrawFeesRepository"]; _persistanceRepository = (IFundsPersistenceRepository)ContextRegistry.GetContext()["FundsPersistenceRepository"]; var connection = ConfigurationManager.ConnectionStrings["MySql"].ToString(); _databaseUtility = new DatabaseUtility(connection); _databaseUtility.Create(); _databaseUtility.Populate(); }
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 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); }
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); }
public void ValidateOrderAndHandleTradeTest_CheksIfEnoughBalanceIsAvailableForAnOrderToBeSentAndHandlesTradeWhenItExectues_VerifiesThroughDatabaseQueryAndValueReturned() { 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"]; Currency baseCurrency = new Currency("BTC"); Currency quoteCurrency = new Currency("USD"); decimal volume = 1.4m; decimal price = 590m; string buyOrderId = "buy123"; string sellOrderId = "sell123"; string buy = "buy"; string sell = "sell"; AccountId buyAccountId = new AccountId(1); AccountId sellAccountId = new AccountId(2); Balance buyBaseBalance = new Balance(baseCurrency, buyAccountId, 20, 20); Balance buyQuoteBalance = new Balance(quoteCurrency, buyAccountId, 15000, 15000); Balance sellBaseBalance = new Balance(baseCurrency, sellAccountId, 20, 20); Balance sellQuoteBalance = new Balance(quoteCurrency, sellAccountId, 15000, 15000); fundsPersistenceRepository.SaveOrUpdate(buyBaseBalance); fundsPersistenceRepository.SaveOrUpdate(buyQuoteBalance); fundsPersistenceRepository.SaveOrUpdate(sellBaseBalance); fundsPersistenceRepository.SaveOrUpdate(sellQuoteBalance); bool validationResponse = fundsValidationService.ValidateFundsForOrder(buyAccountId, baseCurrency, quoteCurrency, volume, price, buy, buyOrderId); Assert.IsTrue(validationResponse); validationResponse = fundsValidationService.ValidateFundsForOrder(sellAccountId, baseCurrency, quoteCurrency, volume, price, sell, sellOrderId); Assert.IsTrue(validationResponse); buyBaseBalance = balanceRepository.GetBalanceByCurrencyAndAccountId(baseCurrency, buyAccountId); Assert.AreEqual(20, buyBaseBalance.AvailableBalance); Assert.AreEqual(20, buyBaseBalance.CurrentBalance); Assert.AreEqual(0, buyBaseBalance.PendingBalance); buyQuoteBalance = balanceRepository.GetBalanceByCurrencyAndAccountId(quoteCurrency, buyAccountId); Assert.AreEqual(15000 - (price * volume), buyQuoteBalance.AvailableBalance); Assert.AreEqual(15000, buyQuoteBalance.CurrentBalance); Assert.AreEqual(price * volume, buyQuoteBalance.PendingBalance); sellBaseBalance = balanceRepository.GetBalanceByCurrencyAndAccountId(baseCurrency, sellAccountId); Assert.AreEqual(20 - volume, sellBaseBalance.AvailableBalance); Assert.AreEqual(20, sellBaseBalance.CurrentBalance); Assert.AreEqual(volume, sellBaseBalance.PendingBalance); sellQuoteBalance = balanceRepository.GetBalanceByCurrencyAndAccountId(quoteCurrency, sellAccountId); Assert.AreEqual(15000, sellQuoteBalance.AvailableBalance); Assert.AreEqual(15000, sellQuoteBalance.CurrentBalance); Assert.AreEqual(0, sellQuoteBalance.PendingBalance); string tradeId = "tradeid123"; bool tradeExecutedResponse = fundsValidationService.TradeExecuted(baseCurrency.Name, quoteCurrency.Name, volume, price, DateTime.Now, tradeId, buyAccountId.Value, sellAccountId.Value, buyOrderId, sellOrderId); Assert.IsTrue(tradeExecutedResponse); decimal buySideFee = feeCalculationService.GetFee(baseCurrency, quoteCurrency, buyAccountId, volume, price); decimal sellSidefee = feeCalculationService.GetFee(baseCurrency, quoteCurrency, sellAccountId, volume, price); buyBaseBalance = balanceRepository.GetBalanceByCurrencyAndAccountId(baseCurrency, buyAccountId); Assert.AreEqual(20 + volume, buyBaseBalance.AvailableBalance); Assert.AreEqual(20 + volume, buyBaseBalance.CurrentBalance); Assert.AreEqual(0, buyBaseBalance.PendingBalance); buyQuoteBalance = balanceRepository.GetBalanceByCurrencyAndAccountId(quoteCurrency, buyAccountId); Assert.AreEqual(15000 - (price * volume) - buySideFee, buyQuoteBalance.AvailableBalance); Assert.AreEqual(15000 - (price * volume) - buySideFee, buyQuoteBalance.CurrentBalance); Assert.AreEqual(0, buyQuoteBalance.PendingBalance); sellBaseBalance = balanceRepository.GetBalanceByCurrencyAndAccountId(baseCurrency, sellAccountId); Assert.AreEqual(20 - volume, sellBaseBalance.AvailableBalance); Assert.AreEqual(20 - volume, sellBaseBalance.CurrentBalance); Assert.AreEqual(0, sellBaseBalance.PendingBalance); sellQuoteBalance = balanceRepository.GetBalanceByCurrencyAndAccountId(quoteCurrency, sellAccountId); Assert.AreEqual(15000 + (price * volume) - sellSidefee, sellQuoteBalance.AvailableBalance); Assert.AreEqual(15000 + (price * volume) - sellSidefee, sellQuoteBalance.CurrentBalance); Assert.AreEqual(0, sellQuoteBalance.PendingBalance); }
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); }