public async Task <NodeDataHolderDetailedModel> Get([SwaggerParameter("The ERC 725 identity for the node", Required = true)] string nodeId) { TickerInfo tickerInfo = await TickerHelper.GetTickerInfo(_cache); await using (var connection = new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString)) { var profile = await connection.QueryFirstOrDefaultAsync <NodeDataHolderDetailedModel>(DataHolderSql.GetDetailed, new { nodeId = nodeId, userID = User?.Identity?.Name }); if (profile != null) { profile.Identities = (await connection.QueryAsync <NodeDetailedIdentity>( @"SELECT i.Identity, bc.DisplayName BlockchainName, i.Stake, i.StakeReserved FROM otidentity i JOIN blockchains bc ON bc.id = i.blockchainid WHERE i.NodeId = @NodeId", new { nodeId = nodeId })).ToArray(); profile.LiveTracUSDPrice = tickerInfo?.PriceUsd; } return(profile); } }
public MainWindowTest() { InitializeComponent(); helper = new Helper(); tradeSetting = helper.ReadSetting(); //SetGmailSetting(); apiProcessor = new BaseProcessor(tradeSetting, helper); apiProcessor.LogAdded += LogAdded; apiProcessor.LoadMasterContract(); mtmConnect = new MTMConnect(apiProcessor); mtmConnect.OnMTMChanged += UpdateMTM; mtmConnect.OnMTMTargetHit += MTMTargetHit; mtmConnect.OnError += MTMConnectError; tickerConnect = new TickerHelper(apiProcessor); tickerConnect.OnTickerChanged += TickerConnect_OnTickerChanged; tickerConnect.OnError += MTMConnectError; Instrument bankNiftyInst = new Instrument { code = "26009", symbol = "Nifty Bank", exchange = "1" }; tickerConnect.SubscribeToken(bankNiftyInst); CheckToken(); InitializeSetting(); }
public BaseEngine() { helper = new Helper(); tradeSetting = helper.ReadSetting(); apiProcessor = new BaseProcessor(tradeSetting, helper); apiProcessor.LoadMasterContract(); tickerHelper = new TickerHelper(apiProcessor); }
public void TestMethod1() { IEnumerable <string> tickers = TickerHelper.GetConcatenatedTickers(@"C:\StockData\SymbolsTop100.csv", new char[] { '\n', '\r' }, ',', 5); StockObserver stockObserver = new StockObserver(tickers, "*****@*****.**", 0.0, 5, 1); for (int i = 0; i < 2; i++) { stockObserver.Observe(); Thread.Sleep(5000); } }
static void Main(string[] args) { //Dictionary<string, Fields> dict = YahooApi.yahooGetQuotes("AAPL,YHOO",true); //Dictionary<string, Fields> dict1 = YahooApi.yahooGetQuotes("AAPL,YHOO"); Trace.TraceInformation("Starting Stock observing application!"); IEnumerable <string> tickers = TickerHelper.GetConcatenatedTickers(@"C:\StockData\SymbolsTop100.csv", new char[] { '\n', '\r' }, ',', 300); StockObserver stockObserver = new StockObserver(tickers, "[email protected],[email protected]", 5.0, 15, 100); while (true) { stockObserver.Observe(); Thread.Sleep(60000); } //Console.WriteLine(EmailManager.SendEmailAlert("This means emailNotificationManager is working in tradeSystm","[email protected];[email protected];[email protected]")); //Implement log to log emails sent, triggers etc }
public override void ProcessOrder(Order newOrder) { //Access the buy order book of this instrument Container buyBook = parentContainer.ChildContainers["B"]; //Access the sell order book of this instrument Container sellBook = parentContainer.ChildContainers["S"]; //create a event arg object containing reference to newly created //order along with reference to buy and sell order book OrderEventArgs orderArg = new OrderEventArgs(newOrder, buyBook, sellBook); //Invoke the OrderBeforeInsert event which will also notify //the matching business component which will then perform //its internal matching //the order becomes active in this stage orderBook.OnOrderBeforeInsert(orderArg); //Check the quantity of the newly created order //because if the order has been successfully matched by matching //business component then quantity will be 0 if (newOrder.Quantity > 0) { //If order is partially or not at all matched //then it is inserted in the order collection orderDataStore.Add(newOrder); //Re-sort the order collection because of addition //of new order orderDataStore.Sort(orderBook.OrderPriority); TickerHelper th = new TickerHelper(); th.Attach(new LoggerObserver()); th.Attach(new ScreenPrinterObserver()); th.SendTickerData(orderArg); //Invoke the OrderInsert event //which will again notify the matching business component //the order becomes passive in this stage orderBook.OnOrderInsert(orderArg); } }
public async Task <NodesPerYearMonthResponse> GetJobsPerMonth() { if (_cache.TryGetValue("MyNodes-JobsPerMonth-" + User.Identity.Name, out var cached)) { return((NodesPerYearMonthResponse)cached); } TickerInfo ticker = await TickerHelper.GetTickerInfo(_cache); NodesPerYearMonthResponse response = new NodesPerYearMonthResponse(); await using (MySqlConnection connection = new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString)) { JobsPerMonthModel[] data = (await connection.QueryAsync <JobsPerMonthModel>(@"WITH JobsCTE AS ( SELECT mn.DisplayName, i.NodeId, YEAR(o.FinalizedTimestamp) AS 'Year', MONTH(o.FinalizedTimestamp) AS 'Month', SUM(o.TokenAmountPerHolder) AS TokenAmount, COUNT(o.OfferID) AS JobCount, SUM((CASE WHEN u.USDPriceCalculationMode = 0 THEN ticker.Price ELSE @overrideUSDPrice END) * o.TokenAmountPerHolder) AS USDAmount FROM otoffer o JOIN otoffer_holders h ON h.OfferID = o.OfferID AND h.BlockchainID = o.BlockchainID JOIN otidentity i ON i.Identity = h.Holder AND i.BlockchainID = o.BlockchainID JOIN mynodes mn ON mn.NodeID = i.NodeId JOIN users u ON u.ID = mn.UserID LEFT JOIN ticker_trac ticker ON u.USDPriceCalculationMode = 0 AND ticker.Timestamp = ( SELECT MAX(TIMESTAMP) FROM ticker_trac WHERE TIMESTAMP <= o.FinalizedTimestamp) WHERE mn.UserID = @userID GROUP BY i.NodeId, YEAR(o.FinalizedTimestamp), MONTH(o.FinalizedTimestamp) ) SELECT JobsCTE.DisplayName, JobsCTE.NodeId, JobsCTE.Year, JobsCTE.Month, JobsCTE.TokenAmount, JobsCTE.JobCount, JobsCTE.USDAmount FROM JobsCTE ORDER BY JobsCTE.DisplayName, JobsCTE.NodeID, JobsCTE.Year, JobsCTE.Month", new { userID = User.Identity.Name, overrideUSDPrice = ticker?.PriceUsd ?? 0 })).ToArray(); IEnumerable <IGrouping <string, JobsPerMonthModel> > groupedByNodes = data.GroupBy(m => m.NodeId); foreach (IGrouping <string, JobsPerMonthModel> nodeGroup in groupedByNodes) { List <JobsPerYear> years = new List <JobsPerYear>(); IEnumerable <IGrouping <int, JobsPerMonthModel> > groupedByYears = nodeGroup.GroupBy(g => g.Year).OrderBy(g => g.Key); JobsPerMonth lastMonth = null; foreach (IGrouping <int, JobsPerMonthModel> yearGroup in groupedByYears) { Dictionary <int, JobsPerMonthModel> months = yearGroup .ToDictionary(k => k.Month, v => v); JobsPerYear year = new JobsPerYear { Year = yearGroup.Key.ToString(), Active = yearGroup.Key == DateTime.Now.Year }; for (int i = 1; i <= 12; i++) { JobsPerMonth month; if (months.TryGetValue(i, out JobsPerMonthModel monthData)) { month = new JobsPerMonth(monthData); } else { month = new JobsPerMonth { Month = CultureInfo.CurrentCulture.DateTimeFormat.GetAbbreviatedMonthName(i) }; } year.Months.Add(month); if (lastMonth != null) { if (lastMonth.JobCount > month.JobCount || (lastMonth.JobCount == 0 && month.JobCount == 0)) { month.Down = true; } } else { month.Down = true; } lastMonth = month; } years.Add(year); } response.Nodes.Add(new NodeJobsPerYear { NodeId = nodeGroup.Key, DisplayName = nodeGroup.First().DisplayName, Years = years }); } } JobsPerYear[] allYears = response.Nodes.SelectMany(n => n.Years).ToArray(); IEnumerable <IGrouping <string, JobsPerYear> > allGroupedByYear = allYears.GroupBy(a => a.Year); response.AllNodes = new NodeJobsPerYear { DisplayName = "All Nodes", Years = allGroupedByYear.Select(y => new JobsPerYear { Year = y.Key, Active = y.First().Active, Months = y.SelectMany(d => d.Months) .GroupBy(m => m.Month) .Select(m => new JobsPerMonth { Month = m.Key, JobCount = m.Sum(d => d.JobCount), TokenAmount = m.Sum(d => d.TokenAmount), USDAmount = m.Sum(d => d.USDAmount) }) .ToList() }).OrderBy(y => y.Year).ToList() }; JobsPerMonth previousMonth = null; foreach (JobsPerYear year in response.AllNodes.Years) { foreach (JobsPerMonth month in year.Months) { if (previousMonth == null) { month.Down = true; } else { if (previousMonth.JobCount == 0 && month.JobCount == 0) { month.Down = true; } else if (previousMonth.JobCount > month.JobCount) { month.Down = true; } } previousMonth = month; } } _cache.Set("MyNodes-JobsPerMonth-" + User.Identity.Name, response, TimeSpan.FromSeconds(15)); return(response); }
public async Task <NodeStats> GetNodeStats([FromQuery] string nodeID) { TickerInfo ticker = await TickerHelper.GetTickerInfo(_cache); await using (MySqlConnection connection = new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString)) { using (var multi = await connection.QueryMultipleAsync(@" SET @priceMode = (SELECT u.USDPriceCalculationMode FROM users u WHERE u.ID = @userID); CREATE TEMPORARY TABLE JobsCTELocal (SELECT i.NodeId, SUM(o.TokenAmountPerHolder) AS TokenAmount, SUM((CASE WHEN @priceMode = 0 THEN ticker.Price ELSE @overrideUSDPrice END) * o.TokenAmountPerHolder) AS USDAmount, COUNT(o.OfferID) AS JobCount, CASE WHEN mn.ID IS NOT NULL THEN 1 ELSE 0 END AS IsMyNode FROM otoffer o JOIN otoffer_holders h ON h.OfferID = o.OfferID AND h.BlockchainID = o.BlockchainID JOIN otidentity i ON i.Identity = h.Holder AND i.BlockchainID = o.BlockchainID LEFT JOIN mynodes mn ON mn.UserID = @userID AND mn.NodeID = i.NodeId LEFT JOIN ticker_trac ticker ON @priceMode = 0 AND (i.NodeId = @nodeID OR mn.ID IS NOT null) AND ticker.Timestamp = ( SELECT MAX(TIMESTAMP) FROM ticker_trac WHERE TIMESTAMP <= o.FinalizedTimestamp) WHERE i.Version > 0 AND i.NodeId != '0000000000000000000000000000000000000000' GROUP BY i.NodeId); SELECT * FROM ( SELECT l.NodeId , l.IsMyNode ,SUM(l.TokenAmount) RewardTokenAmount ,SUM(l.USDAmount) RewardUSDAmount , ROUND(PERCENT_RANK() OVER ( ORDER BY SUM(l.TokenAmount) ) * 100 ) RewardTokenAmountRank ,SUM(l.JobCount) JobCount , ROUND(PERCENT_RANK() OVER ( ORDER BY SUM(l.JobCount) ) * 100) JobCountRank FROM JobsCTELocal l GROUP BY l.NodeId) X WHERE (@nodeID IS NULL AND X.IsMyNode = 1) OR X.NodeId = @nodeID ; SELECT * FROM ( SELECT i.NodeId ,SUM(i.Stake) StakeTokenAmount ,SUM(i.Stake) * @overrideUSDPrice StakeUSDAmount , ROUND(PERCENT_RANK() OVER ( ORDER BY SUM(i.Stake) ) * 100) StakeTokenAmountRank ,SUM(i.StakeReserved) StakeReservedTokenAmount ,SUM(i.StakeReserved) * @overrideUSDPrice StakeReservedUSDAmount , ROUND(PERCENT_RANK() OVER ( ORDER BY SUM(i.StakeReserved) ) * 100) StakeReservedTokenAmountRank FROM otidentity i WHERE i.NodeId IN (SELECT j.NodeID FROM JobsCTELocal j) AND i.Version > 0 AND i.NodeId != '0000000000000000000000000000000000000000' GROUP BY i.NodeId) X WHERE (@nodeID IS NULL AND X.NodeId IN (SELECT j.NodeID FROM JobsCTELocal j WHERE j.IsMyNode = 1)) OR X.NodeId = @nodeID ", new { userID = User.Identity.Name, overrideUSDPrice = ticker?.PriceUsd ?? 0, nodeID })) { NodeStatsModel1 model1; NodeStatsModel2 model2; if (!String.IsNullOrWhiteSpace(nodeID)) { model1 = multi.ReadFirstOrDefault <NodeStatsModel1>(); model2 = multi.ReadFirstOrDefault <NodeStatsModel2>(); if (model1 == null || model2 == null) { return(null); } } else { var model1rows = multi.Read <NodeStatsModel1>().ToArray(); model1 = new NodeStatsModel1 { JobCount = model1rows.Sum(r => r.JobCount), RewardTokenAmount = model1rows.Sum(r => r.RewardTokenAmount), RewardUSDAmount = model1rows.Sum(r => r.RewardUSDAmount) }; var model2rows = multi.Read <NodeStatsModel2>().ToArray(); model2 = new NodeStatsModel2 { StakeReservedTokenAmount = model2rows.Sum(r => r.StakeReservedTokenAmount), StakeReservedUSDAmount = model2rows.Sum(r => r.StakeReservedUSDAmount), StakeTokenAmount = model2rows.Sum(r => r.StakeTokenAmount), StakeUSDAmount = model2rows.Sum(r => r.StakeUSDAmount) }; } NodeStats stats = new NodeStats { TotalJobs = new NodeStats.NodeStatsNumeric { Value = model1.JobCount, BetterThanActiveNodesPercentage = model1.JobCountRank }, TotalLocked = new NodeStats.NodeStatsToken { TokenAmount = model2.StakeReservedTokenAmount, USDAmount = model2.StakeReservedUSDAmount, BetterThanActiveNodesPercentage = model2.StakeReservedTokenAmountRank }, TotalRewards = new NodeStats.NodeStatsToken { TokenAmount = model1.RewardTokenAmount, USDAmount = model1.RewardUSDAmount, BetterThanActiveNodesPercentage = model1.RewardTokenAmountRank }, TotalStaked = new NodeStats.NodeStatsToken { TokenAmount = model2.StakeTokenAmount, USDAmount = model2.StakeUSDAmount, BetterThanActiveNodesPercentage = model2.StakeTokenAmountRank } }; return(stats); } } }
public async Task <RecentJobsByDay[]> GetRecentJobs([FromQuery] string nodeID) { if (string.IsNullOrWhiteSpace(nodeID)) { nodeID = null; } if (_cache.TryGetValue($"MyNodes-GetRecentJobs-{User.Identity.Name}-{nodeID}", out var cached)) { return((RecentJobsByDay[])cached); } TickerInfo ticker = await TickerHelper.GetTickerInfo(_cache); await using (MySqlConnection connection = new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString)) { var jobs = (await connection.QueryAsync <RecentJobs>(@"SELECT mn.NodeID, mn.DisplayName, o.OfferID, o.HoldingTimeInMinutes, o.TokenAmountPerHolder, o.FinalizedTimestamp, (CASE WHEN u.USDPriceCalculationMode = 0 THEN ticker.Price ELSE @overrideUSDPrice END) * o.TokenAmountPerHolder AS USDAmount, b.DisplayName Blockchain, b.LogoLocation BlockchainLogo FROM mynodes mn JOIN users u ON u.ID = mn.UserID JOIN otidentity i ON i.NodeId = mn.NodeID JOIN otoffer_holders h ON h.Holder = i.Identity AND h.BlockchainID = i.BlockchainID JOIN otoffer o ON o.OfferID = h.OfferID AND o.BlockchainID = i.BlockchainID JOIN blockchains b ON b.ID = o.BlockchainID LEFT JOIN ticker_trac ticker ON u.USDPriceCalculationMode = 0 AND ticker.Timestamp = ( SELECT MAX(TIMESTAMP) FROM ticker_trac WHERE TIMESTAMP <= o.FinalizedTimestamp) WHERE o.FinalizedTimestamp >= DATE_Add(DATE(NOW()), INTERVAL -7 DAY) AND mn.UserID = @userID AND (@nodeID IS NULL OR @nodeID = mn.NodeID) ORDER BY o.FinalizedTimestamp DESC", new { userID = User.Identity.Name, overrideUSDPrice = ticker?.PriceUsd ?? 0, nodeID = nodeID })).ToArray(); List <RecentJobsByDay> days = new List <RecentJobsByDay>(7); DateTime date = DateTime.Now.Date; for (int i = 1; i <= 7; i++) { RecentJobsByDay day = new RecentJobsByDay(); day.Active = i == 1; day.Day = CultureInfo.CurrentCulture.DateTimeFormat.GetAbbreviatedDayName(date.DayOfWeek); day.Jobs = jobs.Where(j => j.FinalizedTimestamp.Date == date).ToArray(); days.Add(day); date = date.AddDays(-1); } var data = days.ToArray(); _cache.Set($"MyNodes-GetRecentJobs-{User.Identity.Name}-{nodeID}", data, TimeSpan.FromSeconds(15)); return(data); } }
public async Task <HomeV3Model> HomeV3([FromQuery] bool excludeBreakdown) { string key = $"HomeV3-{excludeBreakdown}"; if (_cache.TryGetValue(key, out object homeModel)) { return((HomeV3Model)homeModel); } TickerInfo tickerInfo = await TickerHelper.GetTickerInfo(_cache); await using (var connection = new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString)) { HomeV3Model model = new HomeV3Model(); model.Blockchains = (await connection.QueryAsync <HomeV3BlockchainModel>(@"SELECT b.Id BlockchainID, b.GasTicker, b.TokenTicker, b.DisplayName BlockchainName, b.LogoLocation, ( SELECT COUNT(DISTINCT I.NodeId) FROM OTOffer O JOIN OTOffer_Holders H ON H.OfferID = O.OfferId JOIN otidentity I ON I.Identity = H.Holder WHERE O.BlockchainID = b.Id and O.IsFinalized = 1 AND NOW() <= DATE_ADD(O.FinalizedTimeStamp, INTERVAL + O.HoldingTimeInMinutes MINUTE)) ActiveNodes, ( SELECT COUNT(*) FROM otoffer WHERE otoffer.IsFinalized = 1 AND otoffer.BlockchainID = b.Id ) TotalJobs, ( SELECT COALESCE(SUM(CASE WHEN IsFinalized = 1 AND NOW() <= DATE_ADD(FinalizedTimeStamp, INTERVAL +HoldingTimeInMinutes MINUTE) THEN 1 ELSE 0 END), 0) FROM otoffer WHERE blockchainid = b.id) AS ActiveJobs, (select COALESCE(sum(Stake), 0) from otidentity WHERE blockchainid = b.id) StakedTokens, (SELECT COUNT(*) FROM OTOffer WHERE blockchainid = b.id and IsFinalized = 1 AND FinalizedTimeStamp >= DATE_Add(NOW(), INTERVAL -1 DAY)) AS Jobs24H, (SELECT AVG(otoffer.TokenAmountPerHolder) FROM otoffer WHERE blockchainid = b.id and IsFinalized = 1 AND FinalizedTimeStamp >= DATE_Add(NOW(), INTERVAL -1 DAY)) AS JobsReward24H, (SELECT AVG(otoffer.HoldingTimeInMinutes) FROM OTOffer WHERE blockchainid = b.id and IsFinalized = 1 AND FinalizedTimeStamp >= DATE_Add(NOW(), INTERVAL -1 DAY)) AS JobsDuration24H, (SELECT AVG(otoffer.DataSetSizeInBytes) FROM OTOffer WHERE blockchainid = b.id and IsFinalized = 1 AND FinalizedTimeStamp >= DATE_Add(NOW(), INTERVAL -1 DAY)) AS JobsSize24H, (SELECT SUM(otoffer.TokenAmountPerHolder * 6) FROM OTOffer WHERE blockchainid = b.id and IsFinalized = 1 AND FinalizedTimeStamp >= DATE_Add(NOW(), INTERVAL -1 DAY)) AS TokensLocked24H, (SELECT SUM(otcontract_holding_paidout.Amount) FROM otcontract_holding_paidout WHERE blockchainid = b.id and Timestamp >= DATE_Add(NOW(), INTERVAL -1 DAY)) AS TokensPaidout24H, (SELECT MIN(otoffer.EstimatedLambda) FROM otoffer WHERE blockchainid = b.id and IsFinalized = 1 AND FinalizedTimeStamp >= DATE_Add(NOW(), INTERVAL -1 DAY)) AS PriceFactorLow24H, (SELECT MAX(otoffer.EstimatedLambda) FROM otoffer WHERE blockchainid = b.id and IsFinalized = 1 AND FinalizedTimeStamp >= DATE_Add(NOW(), INTERVAL -1 DAY)) AS PriceFactorHigh24H, (SELECT MIN(otoffer.TokenAmountPerHolder) FROM otoffer WHERE blockchainid = b.id and IsFinalized = 1 AND FinalizedTimeStamp >= DATE_Add(NOW(), INTERVAL -1 DAY)) AS JobsRewardLow24H, (SELECT MAX(otoffer.TokenAmountPerHolder) FROM otoffer WHERE blockchainid = b.id and IsFinalized = 1 AND FinalizedTimeStamp >= DATE_Add(NOW(), INTERVAL -1 DAY)) AS JobsRewardHigh24H, (SELECT MIN(otoffer.HoldingTimeInMinutes) FROM OTOffer WHERE blockchainid = b.id and IsFinalized = 1 AND FinalizedTimeStamp >= DATE_Add(NOW(), INTERVAL -1 DAY)) AS JobsDurationLow24H, (SELECT MAX(otoffer.HoldingTimeInMinutes) FROM OTOffer WHERE blockchainid = b.id and IsFinalized = 1 AND FinalizedTimeStamp >= DATE_Add(NOW(), INTERVAL -1 DAY)) AS JobsDurationHigh24H, (SELECT MIN(otoffer.DataSetSizeInBytes) FROM OTOffer WHERE blockchainid = b.id and IsFinalized = 1 AND FinalizedTimeStamp >= DATE_Add(NOW(), INTERVAL -1 DAY)) AS JobsSizeLow24H, (SELECT MAX(otoffer.DataSetSizeInBytes) FROM OTOffer WHERE blockchainid = b.id and IsFinalized = 1 AND FinalizedTimeStamp >= DATE_Add(NOW(), INTERVAL -1 DAY)) AS JobsSizeHigh24H FROM blockchains b order by b.id desc")).ToArray(); foreach (HomeV3BlockchainModel blockchain in model.Blockchains) { blockchain.Fees = (await connection.QueryFirstOrDefaultAsync <HomeFeesModel>(@"SELECT bc.ShowCostInUSD, CAST(AVG((CAST(oc.GasUsed AS DECIMAL(20,4)) * (CAST(oc.GasPrice AS DECIMAL(20,6)) / 1000000000000000000)) * (CASE WHEN bc.ShowCostInUSD AND bc.IsGasStableCoin = 0 THEN ocTicker.Price ELSE 1 END)) AS DECIMAL(20,6)) JobCreationCost, CAST(AVG((CAST(of.GasUsed AS DECIMAL(20,4)) * (CAST(of.GasPrice AS DECIMAL(20,6)) / 1000000000000000000)) * (CASE WHEN bc.ShowCostInUSD AND bc.IsGasStableCoin = 0 THEN ofTicker.Price ELSE 1 END)) AS DECIMAL(20,6)) JobFinalisedCost FROM blockchains bc LEFT JOIN otcontract_holding_offercreated oc ON bc.ID = oc.BlockchainID AND oc.Timestamp >= DATE_Add(NOW(), INTERVAL -1 DAY) LEFT JOIN otcontract_holding_offerfinalized of ON of.OfferID = oc.OfferID AND of.BlockchainID = oc.BlockchainID AND of.Timestamp >= DATE_Add(NOW(), INTERVAL -1 DAY) LEFT JOIN ticker_eth_to_usd ocTicker ON bc.IsGasStableCoin = 0 AND ocTicker.Timestamp = ( SELECT MAX(TIMESTAMP) FROM ticker_eth_to_usd WHERE TIMESTAMP <= oc.Timestamp) LEFT JOIN ticker_eth_to_usd ofTicker ON bc.IsGasStableCoin = 0 AND ofTicker.Timestamp = ( SELECT MAX(TIMESTAMP) FROM ticker_eth_to_usd WHERE TIMESTAMP <= of.Timestamp) WHERE bc.ID = @blockchainID", new { blockchainID = blockchain.BlockchainID })); decimal?payoutFee = (await connection.ExecuteScalarAsync <decimal?>(@"SELECT CAST(AVG((CAST(po.GasUsed AS DECIMAL(20,4)) * (CAST(po.GasPrice as decimal(20,6)) / 1000000000000000000)) * (CASE WHEN bc.ShowCostInUSD AND bc.IsGasStableCoin = 0 THEN ocTicker.Price ELSE 1 END)) AS DECIMAL(20, 8)) PayoutCost FROM blockchains bc LEFT JOIN otcontract_holding_paidout po ON po.BlockchainID = bc.ID AND po.Timestamp >= DATE_Add(NOW(), INTERVAL -1 DAY) LEFT JOIN ticker_eth_to_usd ocTicker ON bc.IsGasStableCoin = 0 AND ocTicker.Timestamp = ( SELECT MAX(TIMESTAMP) FROM ticker_eth_to_usd WHERE TIMESTAMP <= po.Timestamp) WHERE bc.ID = @blockchainID", new { blockchainID = blockchain.BlockchainID })); blockchain.Fees.PayoutCost = payoutFee; if (blockchain.BlockchainName != "Ethereum") { blockchain.HoursTillFirstJob = await connection.ExecuteScalarAsync <int?>(@" WITH CTE AS ( SELECT I.Identity, I.NodeID, ( SELECT o.FinalizedTimestamp FROM otoffer_holders h JOIN otoffer o ON o.OfferID = h.OfferID WHERE h.Holder = i.Identity ORDER BY o.FinalizedTimestamp LIMIT 1 ) FirstOfferDate, bb.Timestamp CreatedDate FROM otidentity i JOIN otcontract_profile_identitycreated ic ON ic.NewIdentity = i.Identity AND ic.BlockchainID = i.BlockchainID JOIN ethblock bb ON bb.BlockchainID = ic.BlockchainID AND bb.BlockNumber = ic.BlockNumber WHERE i.BlockchainID = @id AND i.VERSION > 0 AND ( SELECT o.FinalizedTimestamp FROM otoffer_holders h JOIN otoffer o ON o.OfferID = h.OfferID WHERE h.Holder = i.Identity ORDER BY o.FinalizedTimestamp LIMIT 1 ) >= DATE_Add(NOW(), INTERVAL -7 DAY) ORDER BY FirstOfferDate DESC ) SELECT AVG(TIMESTAMPDIFF(HOUR, CreatedDate, FirstOfferDate)) TimeTillFirstJob FROM CTE", new { id = blockchain.BlockchainID }); } } model.PriceUsd = tickerInfo?.PriceUsd; model.PercentChange24H = tickerInfo?.PercentChange24H; model.CirculatingSupply = tickerInfo?.CirculatingSupply; model.MarketCapUsd = tickerInfo?.MarketCapUsd; model.Volume24HUsd = tickerInfo?.Volume24HUsd; model.PriceBtc = tickerInfo?.PriceBtc; model.All = new HomeV3BlockchainModel { BlockchainID = 0, BlockchainName = "All Blockchains", ActiveJobs = model.Blockchains.Sum(b => b.ActiveJobs), ActiveNodes = model.Blockchains.Sum(b => b.ActiveNodes), Jobs24H = model.Blockchains.Sum(b => b.Jobs24H), JobsDuration24H = (long?)model.Blockchains.Select(b => b.JobsDuration24H).DefaultIfEmpty(null).Average(), JobsReward24H = (decimal?)model.Blockchains.Where(b => b.JobsReward24H.HasValue).Average(b => b.JobsReward24H), JobsSize24H = (long?)model.Blockchains.Where(b => b.JobsSize24H.HasValue).Average(b => b.JobsSize24H), StakedTokens = model.Blockchains.Sum(b => b.StakedTokens), TotalJobs = model.Blockchains.Sum(b => b.TotalJobs), TokenTicker = model.Blockchains.Select(b => b.TokenTicker).Aggregate((a, b) => a + " | " + b), TokensLocked24H = model.Blockchains.Select(b => b.TokensLocked24H).DefaultIfEmpty(null).Sum(), TokensPaidout24H = model.Blockchains.Select(b => b.TokensPaidout24H).DefaultIfEmpty(null).Sum(), PriceFactorLow24H = model.Blockchains.Select(b => b.PriceFactorLow24H).DefaultIfEmpty(null).Min(), PriceFactorHigh24H = model.Blockchains.Select(b => b.PriceFactorHigh24H).DefaultIfEmpty(null).Max(), }; if (excludeBreakdown) { model.Blockchains = null; } _cache.Set(key, model, TimeSpan.FromSeconds(45)); return(model); } }