public async Task <GetPortfolioResponse> Handle(GetPortfolioRequest request, CancellationToken cancellationToken) { var member = await _context.Members .Where(x => x.MemberUsername == request.MemberUsername) .Include(a => a.PreferredFiatCurrency) .Include(x => x.PreferredCoinCurrency) .Include(x => x.PreferredTimeFrame) .Include(a => a.Owners) .AsNoTracking() .SingleOrDefaultAsync(cancellationToken); if (member == null) { throw new NotFoundException(nameof(Member), request.MemberUsername); } var result = new GetPortfolioResponse { MemberPreferredFiatCurrencyID = member.PreferredFiatCurrencyID, MemberPreferredFiatCurrencySymbol = member.PreferredFiatCurrency.Symbol, MemberPreferredFiatCurrencyUnitPriceInUSD = member.PreferredFiatCurrency.UnitPriceInUSD, MemberPreferredCoinCurrencyID = member.PreferredCoinCurrencyID, MemberPreferredCoinCurrencySymbol = member.PreferredCoinCurrency.Symbol, MemberPreferredCoinCurrencyUnitPriceInUSD = member.PreferredCoinCurrency.UnitPriceInUSD, MemberPreferredTimeFrameName = member.PreferredTimeFrame.Name }; #region Load Crypto Currencies owned by Member foreach (var owner in member.Owners) { var nonFiatWallets = _context.Wallets .Where(x => x.OwnerID == owner.OwnerID && x.BlockchainID != BlockchainID.Fiat) .AsNoTracking() .ToList(); foreach (var wallet in nonFiatWallets) { var pockets = await _context.Pockets .Where(x => x.WalletID == wallet.WalletID && x.Currency.UnitPriceInUSD > 0) .Include(a => a.Transactions) .AsNoTracking() .ToListAsync(cancellationToken); foreach (var pocket in pockets) { CurrencyDTO currencyDTO = result.Currencies .Where(x => x.CurrencyID == pocket.CurrencyID) .SingleOrDefault(); if (currencyDTO == null) { var currency = await _context.Currencies .Where(x => x.CurrencyID == pocket.CurrencyID) .AsNoTracking() .SingleOrDefaultAsync(cancellationToken); currencyDTO = new CurrencyDTO { CurrencyID = currency.CurrencyID, Symbol = currency.Symbol, Name = currency.Name, UnitPriceInUSD = currency.UnitPriceInUSD, CurrencyType = currency.CurrencyType }; result.Currencies.Add(currencyDTO); } var selectedTransactions = pocket.Transactions .Where(x => x.TransactionType == TransactionType.StartingBalance || x.TransactionType == TransactionType.BuyIN || x.TransactionType == TransactionType.BuyOUT || x.TransactionType == TransactionType.SellIN || x.TransactionType == TransactionType.SellOUT || x.TransactionType == TransactionType.ExternalTransferIN || x.TransactionType == TransactionType.ExternalTransferOUT || x.TransactionType == TransactionType.SyncBalanceImport || x.TransactionType == TransactionType.SyncTransactionIN || x.TransactionType == TransactionType.SyncTransactionOUT) .OrderBy(o => o.TransactionDateTime) .ToList(); foreach (var transaction in selectedTransactions) { TransactionDTO transactionDTO = new TransactionDTO { TransactionID = transaction.TransactionID, Amount = transaction.Amount, TransactionType = transaction.TransactionType, TransactionDateTime = transaction.TransactionDateTime, UnitPriceInUSD = transaction.UnitPriceInUSD }; currencyDTO.Transactions.Add(transactionDTO); } #region TotalPurchaseValueInPreferredFiatCurrency if (result.MemberPreferredFiatCurrencyUnitPriceInUSD > 0) { currencyDTO.TotalPurchaseValueInPreferredFiatCurrency = currencyDTO.TotalPurchaseValueInUSD / result.MemberPreferredFiatCurrencyUnitPriceInUSD; } else { currencyDTO.TotalPurchaseValueInPreferredFiatCurrency = 0m; } #endregion #region CurrentValueInPreferredCoinCurrency if (currencyDTO.CurrencyID == result.MemberPreferredCoinCurrencyID) { currencyDTO.CurrentValueInPreferredCoinCurrency = currencyDTO.TotalAmount; } else { if (result.MemberPreferredCoinCurrencyUnitPriceInUSD > 0) { currencyDTO.CurrentValueInPreferredCoinCurrency = currencyDTO.TotalAmount * (currencyDTO.UnitPriceInUSD / result.MemberPreferredCoinCurrencyUnitPriceInUSD); } else { currencyDTO.CurrentValueInPreferredCoinCurrency = 0m; } } #endregion } } } #endregion var validCurrencies = result.Currencies.Where(x => x.TotalAmount > 0).ToList(); foreach (var currencyDTO in validCurrencies) { // debug why token with amount > 1 USD doesn't occur? _logger.LogDebug($"validCurrencies - Coin Symbol: {currencyDTO.Symbol}"); _logger.LogDebug($"validCurrencies - Coin TotalAmount: {currencyDTO.TotalAmount}"); #region Just For Debug. *Note: Maybe Problems Occur from "Too Many Request from Coin Market Cap" CryptoLatestQuotesResult latestQuotesResult = null; try { latestQuotesResult = await _cryptoService.GetLatestQuoteAsync(currencyDTO.Symbol, result.MemberPreferredFiatCurrencySymbol); } catch (Exception ex) { result.IsSuccessful = false; result.ErrorMessage = ex.Message; } #endregion if (latestQuotesResult != null) { currencyDTO.Price = latestQuotesResult.Price; currencyDTO.Volume24h = latestQuotesResult.Volume24h; currencyDTO.PercentChange1h = latestQuotesResult.PercentChange1h; currencyDTO.PercentChange24h = latestQuotesResult.PercentChange24h; currencyDTO.PercentChange7d = latestQuotesResult.PercentChange7d; // Sekalian update Currency kalau MemberPreferredFiatCurrencySymbol adalah USD if (result.MemberPreferredFiatCurrencySymbol == CurrencySymbol.USD) { var currency = await _context.Currencies .Where(x => x.CurrencyID == currencyDTO.CurrencyID) .SingleAsync(cancellationToken); currency.Rank = latestQuotesResult.Rank; currency.UnitPriceInUSD = latestQuotesResult.Price; currency.Volume24h = latestQuotesResult.Volume24h; currency.PercentChange1h = latestQuotesResult.PercentChange1h; currency.PercentChange24h = latestQuotesResult.PercentChange24h; currency.PercentChange7d = latestQuotesResult.PercentChange7d; currency.LastUpdated = latestQuotesResult.LastUpdated; await _context.SaveChangesAsync(cancellationToken); currencyDTO.UnitPriceInUSD = latestQuotesResult.Price; } } else { //currencyDTO.Price = currencyDTO.UnitPriceInUSD / currencyDTO.Portfolio.MemberPreferredFiatCurrencyUnitPriceInUSD; currencyDTO.Price = currencyDTO.UnitPriceInUSD / result.MemberPreferredFiatCurrencyUnitPriceInUSD; } #region Hitung Percentage Lifetime decimal difference = 0m; #region Kalau pakai Average Unit Price in Preferred Fiat Currency if (currencyDTO.AverageBuyPriceInPreferredFiatCurrency > 0) { difference = currencyDTO.Price - currencyDTO.AverageBuyPriceInPreferredFiatCurrency; currencyDTO.PercentChangeLifetime = Convert.ToSingle(difference / currencyDTO.AverageBuyPriceInPreferredFiatCurrency); } else { currencyDTO.PercentChangeLifetime = 0f; } #endregion #region SelectedPercentChange currencyDTO.SelectedPercentChange = result.MemberPreferredTimeFrameName switch { TimeFrameName.OneHour => currencyDTO.PercentChange1h, TimeFrameName.OneDay => currencyDTO.PercentChange24h, TimeFrameName.OneWeek => currencyDTO.PercentChange7d, _ => currencyDTO.PercentChangeLifetime }; #endregion #region Kalau pakai First Transaction //var firstTransaction = currency.IncomingTransactions.FirstOrDefault(); //if (firstTransaction != null) //{ // decimal firstTransactionUnitPriceInPreferredFiatCurrency = 1m; // if (result.MemberPreferredFiatCurrencySymbol == CurrencySymbol.USD) // { // firstTransactionUnitPriceInPreferredFiatCurrency = firstTransaction.UnitPriceInUSD; // } // else // { // var firstTransactionUnitPriceInPreferredFiatCurrencyPriceConversionResult = _cryptoService.Send(new PriceConversionParameter // { // FromCurrencySymbol = CurrencySymbol.USD, // ToCurrencySymbol = result.MemberPreferredFiatCurrencySymbol, // Amount = firstTransaction.UnitPriceInUSD // }); // firstTransactionUnitPriceInPreferredFiatCurrency = firstTransactionUnitPriceInPreferredFiatCurrencyPriceConversionResult.IsSuccessful ? firstTransactionUnitPriceInPreferredFiatCurrencyPriceConversionResult.Amount : 1m; // } // difference = currency.CurrentUnitPriceInPreferredFiatCurrency - firstTransactionUnitPriceInPreferredFiatCurrency; // currencyDTO.PercentChangeLifetime = difference / firstTransactionUnitPriceInPreferredFiatCurrency; //} //else //{ // currencyDTO.PercentChangeLifetime = 0m; //} #endregion #endregion } return(result); } }
public async Task <CryptoLatestQuotesResult> GetLatestQuoteAsync(string fromCurrencySymbol, string toCurrencySymbol) { var result = new CryptoLatestQuotesResult(); string uri = $"{CryptoServiceProviders.CoinMarketCap.CryptoCurrencyQuotesLatestEndpointURL}?symbol={fromCurrencySymbol}&convert={toCurrencySymbol}"; _logger.LogDebug($"{nameof(GetLatestQuoteAsync)}"); _logger.LogDebug(uri); IDictionary <string, string> additionalHttpHeaders = new Dictionary <string, string> { { "X-CMC_PRO_API_KEY", APIKey } }; try { var cryptoCurrencyQuotesLatestResultJSON = await ExternalWebAPIRequestor.GetAsync <CryptoCurrencyQuotesLatestResultJSON>(uri, additionalHttpHeaders); if (cryptoCurrencyQuotesLatestResultJSON.status.error_code == 0) { foreach (var data in cryptoCurrencyQuotesLatestResultJSON.data) { if (data.Key == fromCurrencySymbol) { foreach (var quote in data.Value.quote) { if (quote.Key == toCurrencySymbol) { result = new CryptoLatestQuotesResult { Rank = data.Value.cmc_rank ?? 0, Price = quote.Value.price, Volume24h = quote.Value.volume_24h ?? 0m, PercentChange1h = quote.Value.percent_change_1h ?? 0f, PercentChange24h = quote.Value.percent_change_24h ?? 0f, PercentChange7d = quote.Value.percent_change_7d ?? 0f, LastUpdated = quote.Value.last_updated, }; } } } } } else { result = null; } } catch (WebException ex) when((ex.Response as HttpWebResponse)?.StatusCode == HttpStatusCode.BadRequest) { //result = null; throw; } catch (WebException ex) when((ex.Response as HttpWebResponse)?.StatusCode != HttpStatusCode.OK) { //result = null; throw; } return(result); }