public void SavePendingTransactionsTest_SavesObjectsToPendingTransactionsList_ChecksIfTheyAreAsExpected()
        {
            Balance balance = new Balance(new Currency("LTC", true), new AccountId(1), 5000, 5000);

            _persistanceRepository.SaveOrUpdate(balance);
            bool addPendingTransaction = balance.AddPendingTransaction("withdrawid123", PendingTransactionType.Withdraw, -500);

            Assert.IsTrue(addPendingTransaction);

            _persistanceRepository.SaveOrUpdate(balance);

            Balance retrievedBalance = _balanceRepository.GetBalanceByCurrencyAndAccountId(balance.Currency, balance.AccountId);

            Assert.IsNotNull(retrievedBalance);

            Assert.AreEqual(4500, retrievedBalance.AvailableBalance);
            Assert.AreEqual(5000, retrievedBalance.CurrentBalance);
            Assert.AreEqual(500, retrievedBalance.PendingBalance);

            retrievedBalance.ConfirmPendingTransaction("withdrawid123", PendingTransactionType.Withdraw, -500);

            _persistanceRepository.SaveOrUpdate(retrievedBalance);
            retrievedBalance = _balanceRepository.GetBalanceByCurrencyAndAccountId(balance.Currency, balance.AccountId);
            Assert.IsNotNull(retrievedBalance);
            Assert.AreEqual(4500, retrievedBalance.AvailableBalance);
            Assert.AreEqual(4500, retrievedBalance.CurrentBalance);
            Assert.AreEqual(0, retrievedBalance.PendingBalance);
        }
        public bool ValidateFundsForOrder(AccountId accountId, Currency baseCurrency, Currency quoteCurrency,
                                          decimal volume, decimal price, string orderSide, string orderId)
        {
            Balance baseCurrencyBalance  = GetBalanceForAccountId(accountId, baseCurrency);
            Balance quoteCurrencyBalance = GetBalanceForAccountId(accountId, quoteCurrency);

            if (baseCurrencyBalance != null && quoteCurrency != null)
            {
                if (orderSide.Equals("buy", StringComparison.OrdinalIgnoreCase))
                {
                    // If the order is a buy order, then we need to figure out if we have enough balance in the quote
                    // currency of the currency pairto carry out the order. If we are trading XBT/USD,
                    // If 1 XBT = 101 USD, then if we want to buy 8 XBT coins, then, 8 XBT = 8*101 USD
                    // So we need askPrice(XBT/USD) * Volume(Volume of the order)
                    // Also, we need to check the Available Balance(balance that does not contain pending balance)
                    if (quoteCurrencyBalance.AvailableBalance >= price * volume)
                    {
                        quoteCurrencyBalance.AddPendingTransaction(orderId, PendingTransactionType.Order, -(price * volume));
                        _fundsPersistenceRepository.SaveOrUpdate(quoteCurrencyBalance);
                        return(true);
                    }
                }
                else if (orderSide.Equals("sell", StringComparison.OrdinalIgnoreCase))
                {
                    // If we are trading for XBT/USD and want to sell XBT, then we need to check if the Available
                    // balance(does not contain pending balance) for XBT is enough for the order to take place
                    if (baseCurrencyBalance.AvailableBalance >= volume)
                    {
                        baseCurrencyBalance.AddPendingTransaction(orderId, PendingTransactionType.Order, -volume);
                        _fundsPersistenceRepository.SaveOrUpdate(baseCurrencyBalance);
                        return(true);
                    }
                }
            }
            return(false);
        }
        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));
            }
        }