using GraphQL; using GraphQL.Client.Abstractions; using Managing.Core; using Managing.Domain.Candles; using Managing.Infrastructure.Evm.Abstractions; using Managing.Infrastructure.Evm.Services; using Managing.Infrastructure.Evm.Subgraphs.Models; using NBitcoin; using static Managing.Common.Enums; namespace Managing.Infrastructure.Evm.Subgraphs; public class Gbc : ISubgraphPrices { private readonly IGraphQLClient _graphQLClient; public SubgraphProvider GetProvider() => SubgraphProvider.Gbc; public Gbc(IGraphQLClient graphQLHttpClient) { _graphQLClient = graphQLHttpClient ?? throw new ArgumentNullException(nameof(graphQLHttpClient)); } public async Task> GetPrices(Ticker ticker, DateTime startDate, Timeframe timeframe) { var batchSize = 1000; var batchMax = 6; var priceRounds = new List(); var tickerContract = TokenService.GetContractAddress(ticker); var unixTimeframe = timeframe.GetUnixInterval(); var start = startDate.ToUnixTimestamp(); var end = DateTime.UtcNow.ToUnixTimestamp(); var feedCondition = $@"{{ tokenAddress: ""_{tickerContract}"", interval: ""_{unixTimeframe}"", timestamp_gte: {start}, timestamp_lte: {end} }}"; // Fetching prices from graphql ticker for (int i = 0; i < batchMax; i++) { var query = $"{{ pricefeeds(first: {batchSize}, skip: {i * batchSize}, orderBy: timestamp, orderDirection: desc, where: {feedCondition} ) {{ timestamp,o,h,l,c}} }}"; var graphQuery = new GraphQLRequest { Query = query }; var response = await _graphQLClient.SendQueryAsync(graphQuery); priceRounds.AddRange(response.Data.PriceFeeds); } priceRounds.Sort((timeA, timeB) => timeA.Timestamp - timeB.Timestamp); var candles = new List(); var firstRound = priceRounds.FirstOrDefault(); if (firstRound == null) return candles; var previousCandle = BuildCandle(firstRound, ticker, timeframe); // Format response foreach (var price in priceRounds.Skip(1)) { var candle = BuildCandle(price, ticker, timeframe); candle.OpenTime = previousCandle.Date; candles.Add(candle); } return candles; } private Candle BuildCandle(GbcPrice ohlc, Ticker ticker, Timeframe timeframe) { return new Candle() { Date = DateHelpers.GetFromUnixTimestamp(ohlc.Timestamp), Open = FormatPrice(ohlc.O), High = FormatPrice(ohlc.H), Low = FormatPrice(ohlc.L), Close = FormatPrice(ohlc.C), Exchange = TradingExchanges.Evm, Ticker = ticker, Timeframe = timeframe }; } private static decimal FormatPrice(string price) { return (decimal)(double.Parse(price) / 1e30); } public Task GetVolume(Ticker ticker) { throw new NotImplementedException(); } public Task> GetTickers() { var tickers = new List() { Ticker.BTC, Ticker.LINK, Ticker.ETH, Ticker.UNI }; return Task.FromResult(tickers.AsEnumerable()); } }