private async Task <IFund> GetFundAsync(IFundSettings settings, IInvictusFund fund, CurrencyCode currencyCode) { var now = DateTime.UtcNow; var priceData = settings.Tradable ? await ethplorerClient.GetTokenInfoAsync(new EthereumAddress(settings.DataKey)) : null; var navData = await ListPerformanceAsync(settings.Symbol, PriceMode.Close, now.AddDays(-29), now, currencyCode) .ToListAsync(CancellationToken); return(await MapFundAsync( fund, navData .Select(x => x.NetAssetValuePerToken) .ToList(), priceData?.Price, settings.Symbol, currencyCode)); }
private async Task <IFund> MapFundAsync(IInvictusFund fund, IReadOnlyList <decimal> navs, EthplorerPriceSummary priceData, Symbol symbol, CurrencyCode currencyCode) { var dailyNavs = navs.TakeLast(2); var weeklyNavs = navs.TakeLast(8); var netVal = fund.Assets.Any() ? CurrencyConverter.Convert(fund.Assets.Select(x => x.Total.FromPythonString()).Where(x => x > 0).Sum(), currencyCode) : CurrencyConverter.Convert(fund.NetValue.FromPythonString(), currencyCode); var circulatingSupply = fund.CirculatingSupply.FromPythonString(); var fundInfo = GetFundInfo(symbol); var businessFund = new BusinessFund() { Name = fund.Name, Category = fundInfo.Category, Description = fundInfo.Description, FactSheetUri = fundInfo.Links.Fact, LitepaperUri = fundInfo.Links.Lite, InvictusUri = fundInfo.Links.External, Token = new BusinessToken() { Symbol = fundInfo.Symbol, ContractAddress = new EthereumAddress(fundInfo.ContractAddress), Decimals = fundInfo.Decimals }, CirculatingSupply = circulatingSupply, Nav = new BusinessNav() { Value = CurrencyConverter.Convert(fund.NetValue.FromPythonString(), currencyCode), ValuePerToken = CurrencyConverter.Convert(fund.NetAssetValuePerToken.FromPythonString(), currencyCode), DiffDaily = dailyNavs.First().PercentageDiff(dailyNavs.Last()), DiffWeekly = weeklyNavs.First().PercentageDiff(weeklyNavs.Last()), DiffMonthly = navs.First().PercentageDiff(navs.Last()), }, Market = new BusinessMarket() { IsTradable = priceData != null, Cap = priceData?.MarketCap ?? decimal.Zero, Total = CurrencyConverter.Convert((priceData?.MarketValuePerToken ?? decimal.Zero) * circulatingSupply, currencyCode), PricePerToken = CurrencyConverter.Convert(priceData?.MarketValuePerToken ?? decimal.Zero, currencyCode), DiffDaily = priceData?.DiffDaily ?? decimal.Zero, DiffWeekly = priceData?.DiffWeekly ?? decimal.Zero, DiffMonthly = priceData?.DiffMonthly ?? decimal.Zero, Volume = CurrencyConverter.Convert(priceData?.Volume ?? decimal.Zero, currencyCode), VolumeDiffDaily = priceData?.VolumeDiffDaily ?? decimal.Zero, VolumeDiffWeekly = priceData?.VolumeDiffWeekly ?? decimal.Zero, VolumeDiffMonthly = priceData?.VolumeDiffMonthly ?? decimal.Zero } }; var assets = fund.Assets .Select(FromInvictusAsset) .Where(x => x.Total > 0) .ToList(); foreach (var asset in fundInfo.Assets) { assets.Add(await MapFundAssetAsync(asset, netVal, currencyCode)); } businessFund.Assets = assets .OrderByDescending(x => x.Total) .ToList(); return(businessFund); BusinessFundAsset FromInvictusAsset(InvictusAsset asset) { var total = CurrencyConverter.Convert(asset.Total.FromPythonString(), currencyCode); var holding = GetHoldingInfo(asset.Symbol); var isFiat = Enum.IsDefined(typeof(CurrencyCode), asset.Symbol); var sanitisedId = asset.Name.Replace(" ", "-").Replace(".", "-").ToLower().Trim(); var sanitisedName = string.Join(" ", asset.Name.Trim() .Replace("-", " ") .Split(' ') .Select(x => x.Length > 1 ? x.Substring(0, 1).ToUpper() + x.Substring(1) : x.ToUpper())); var coinloreId = GetAssetInfo(asset.Symbol)?.CoinLore ?? sanitisedId; var coinMarketCapId = GetAssetInfo(asset.Symbol)?.CoinMarketCap ?? sanitisedId; var fund = Enum.TryParse(asset.Symbol, out Symbol symbol) ? GetFundInfo(symbol) : null; return(new BusinessFundAsset() { Holding = new BusinessHolding() { Name = sanitisedName, Symbol = asset.Symbol, HexColour = holding?.Colour ?? GetAssetInfo(asset.Symbol)?.Colour, IsCoin = holding == null, Link = holding?.Link ?? fund?.Links?.External ?? (isFiat ? new Uri(string.Format(FiatTemplate, asset.Symbol.ToUpper()), UriKind.Absolute) : new Uri(string.Format(LinkTemplate, coinMarketCapId), UriKind.Absolute)), ImageLink = holding?.ImageLink ?? (fund != null || isFiat ? new Uri($"https://{HostUrl.Host}/resources/{asset.Symbol}.png", UriKind.Absolute) : new Uri(string.Format(ImageTemplate, coinloreId), UriKind.Absolute)), MarketLink = (fund == null || fund.Tradable) && !isFiat && holding == null ? new Uri(string.Format(MarketTemplate, coinloreId, currencyCode), UriKind.Absolute) : null }, Quantity = CurrencyConverter.Convert(asset.Quantity.FromPythonString(), currencyCode), PricePerToken = CurrencyConverter.Convert(asset.PricePerToken.FromPythonString(), currencyCode), Total = total, Share = total / netVal * 100 }); } }