From acaf3f7346ab0664c24c7fb1679769e75e0c71a2 Mon Sep 17 00:00:00 2001 From: cryptooda Date: Sat, 17 Aug 2024 07:57:14 +0700 Subject: [PATCH] Refact multicall --- src/Managing.Api.Workers/Program.cs | 22 +- .../Discord/DiscordHelpers.cs | 36 +-- .../Discord/DiscordService.cs | 1 - .../Services/Gmx/GmxV2Service.cs | 277 ++++++++++-------- 4 files changed, 176 insertions(+), 160 deletions(-) diff --git a/src/Managing.Api.Workers/Program.cs b/src/Managing.Api.Workers/Program.cs index dffbfb5..034bb25 100644 --- a/src/Managing.Api.Workers/Program.cs +++ b/src/Managing.Api.Workers/Program.cs @@ -102,17 +102,17 @@ builder.Services.AddSwaggerGen(options => }); builder.WebHost.SetupDiscordBot(); -builder.Services.AddHostedService(); -// builder.Services.AddHostedService(); -// builder.Services.AddHostedService(); -// builder.Services.AddHostedService(); -builder.Services.AddHostedService(); -builder.Services.AddHostedService(); -// builder.Services.AddHostedService(); -builder.Services.AddHostedService(); -// builder.Services.AddHostedService(); -builder.Services.AddHostedService(); -builder.Services.AddHostedService(); +// builder.Services.AddHostedService(); +// // builder.Services.AddHostedService(); +// // builder.Services.AddHostedService(); +// // builder.Services.AddHostedService(); +// builder.Services.AddHostedService(); +// builder.Services.AddHostedService(); +// // builder.Services.AddHostedService(); +// builder.Services.AddHostedService(); +// // builder.Services.AddHostedService(); +// builder.Services.AddHostedService(); +// builder.Services.AddHostedService(); builder.Services.AddHostedService(); // App diff --git a/src/Managing.Infrastructure.Messengers/Discord/DiscordHelpers.cs b/src/Managing.Infrastructure.Messengers/Discord/DiscordHelpers.cs index dc841e4..feb53c6 100644 --- a/src/Managing.Infrastructure.Messengers/Discord/DiscordHelpers.cs +++ b/src/Managing.Infrastructure.Messengers/Discord/DiscordHelpers.cs @@ -24,7 +24,7 @@ public static class DiscordHelpers var embed = new EmbedBuilder { Author = new EmbedAuthorBuilder() { Name = "GMX v2" }, - Title = $"{title} {DateTime.UtcNow:d}", + Title = $"{title} {DateTime.UtcNow:g}", Color = Color.Gold, Fields = fields, }.Build(); @@ -36,17 +36,10 @@ public static class DiscordHelpers { var fields = new List(); - decimal ratePerYear = fundingRate.Rate; // Rate per year - decimal ratePerDay = ratePerYear / 365; // Rate per day - decimal ratePerMonth = ratePerYear / 12; // Rate per month - decimal ratePerHour = ratePerDay / 24; // Rate per hour - + var (ratePerYear, ratePerDay, ratePerMonth, ratePerHour) = GetRates(fundingRate); if (oldRate != null) { - var oldRatePerYear = oldRate.Rate; // Rate per year - var oldRatePerDay = oldRatePerYear / 365; // Rate per day - var oldRatePerMonth = oldRatePerYear / 12; // Rate per month - var oldRatePerHour = oldRatePerDay / 24; // Rate per hour + var (oldRatePerYear, oldRatePerDay, oldRatePerMonth, oldRatePerHour) = GetRates(oldRate); fields.Add(new EmbedFieldBuilder { @@ -66,7 +59,7 @@ public static class DiscordHelpers var embed = new EmbedBuilder { Author = new EmbedAuthorBuilder() { Name = "GMX" }, - Title = $"{title} {DateTime.UtcNow:d}", + Title = $"{title} {DateTime.UtcNow:g}", Color = Color.DarkGreen, Fields = fields, }.Build(); @@ -115,7 +108,7 @@ public static class DiscordHelpers var embed = new EmbedBuilder { Author = new EmbedAuthorBuilder() { Name = "GMX" }, - Title = $"{title} {DateTime.UtcNow:d}", + Title = $"{title} {DateTime.UtcNow:g}", Color = Color.DarkBlue, Fields = fields, }.Build(); @@ -129,11 +122,7 @@ public static class DiscordHelpers foreach (var fundingRate in fundingRates) { - decimal ratePerYear = fundingRate.Rate; // Rate per year - decimal ratePerDay = ratePerYear / 365; // Rate per day - decimal ratePerMonth = ratePerYear / 12; // Rate per month - decimal ratePerHour = ratePerDay / 24; // Rate per hour - + var (ratePerYear, ratePerDay, ratePerMonth, ratePerHour) = GetRates(fundingRate); fields.Add(new EmbedFieldBuilder { Name = $"{fundingRate.Ticker}", @@ -145,11 +134,22 @@ public static class DiscordHelpers var embed = new EmbedBuilder { Author = new EmbedAuthorBuilder() { Name = "GMX" }, - Title = $"Best Funding Rate {DateTime.UtcNow:d}", + Title = $"Best Funding Rate {DateTime.UtcNow:g}", Color = Color.DarkGreen, Fields = fields, }.Build(); return embed; } + + private static (decimal ratePerYear, decimal ratePerDay, decimal ratePerMonth, decimal ratePerHour) GetRates( + FundingRate fundingRate) + { + decimal ratePerHour = fundingRate.Rate; // Rate per hour + decimal ratePerDay = ratePerHour * 24; // Rate per day + decimal ratePerMonth = ratePerDay * 30; // Rate per month + decimal ratePerYear = ratePerDay * 365; // Rate per year + + return (ratePerYear, ratePerDay, ratePerMonth, ratePerHour); + } } \ No newline at end of file diff --git a/src/Managing.Infrastructure.Messengers/Discord/DiscordService.cs b/src/Managing.Infrastructure.Messengers/Discord/DiscordService.cs index ce0283e..1fd833c 100644 --- a/src/Managing.Infrastructure.Messengers/Discord/DiscordService.cs +++ b/src/Managing.Infrastructure.Messengers/Discord/DiscordService.cs @@ -99,7 +99,6 @@ namespace Managing.Infrastructure.Messengers.Discord // Discord started as a game chat service, so it has the option to show what games you are playing // Here the bot will display "Playing dead" while listening await _client.SetGameAsync(_settings.BotActivity, "https://moon.com", ActivityType.Playing); - _logger.LogInformation(JsonConvert.SerializeObject(_settings, Formatting.Indented)); if (!_settings.HandleUserAction) return; List applicationCommandProperties = new(); diff --git a/src/Managing.Infrastructure.Web3/Services/Gmx/GmxV2Service.cs b/src/Managing.Infrastructure.Web3/Services/Gmx/GmxV2Service.cs index 4501a2b..c31e931 100644 --- a/src/Managing.Infrastructure.Web3/Services/Gmx/GmxV2Service.cs +++ b/src/Managing.Infrastructure.Web3/Services/Gmx/GmxV2Service.cs @@ -181,147 +181,164 @@ public class GmxV2Service } public async Task> GetMarketInfosAsync(Web3 web3) +{ + var markets = await GetMarketsAsync(web3); + var readerResult = new List(); + var readerCalls = new List(); + var datastoreCalls = new List(); + markets = markets.Where(m => !m.IsSpotOnly).ToList(); + + foreach (var market in markets) { - var markets = await GetMarketsAsync(web3); - var readerResult = new List(); - foreach (var market in markets) + var tokensData = await GetTokensData(web3); + var marketPrices = GmxHelpers.GetContractMarketPrices(tokensData, market); + var marketProps = new MarketsProps() { - var tokensData = await GetTokensData(web3); - var marketPrices = GmxHelpers.GetContractMarketPrices(tokensData, market); - var marketProps = new MarketsProps() - { - MarketToken = market.MarketToken, - IndexToken = market.IndexToken, - LongToken = market.LongToken, - ShortToken = market.ShortToken - }; - var getMarketInfoCallData = new GetMarketInfoFunction - { - DataStore = Arbitrum.AddressV2.DataStore, - Prices = marketPrices, - MarketKey = market.MarketToken - }.GetCallData(); - var getMarketInfoCall = new Call - { - Target = Arbitrum.AddressV2.Reader, - CallData = getMarketInfoCallData - }; - var getMarketTokenPriceCallData = new GetMarketTokenPriceFunction - { - DataStore = Arbitrum.AddressV2.DataStore, - Market = marketProps, - IndexTokenPrice = marketPrices.IndexTokenPrice, - LongTokenPrice = marketPrices.LongTokenPrice, - ShortTokenPrice = marketPrices.ShortTokenPrice, - PnlFactorType = _helpers.HashString(Constants.GMX.MAX_PNL_FACTOR_FOR_TRADERS), - Maximize = true - }.GetCallData(); - var getMarketTokenPriceCall = new Call - { - Target = Arbitrum.AddressV2.Reader, - CallData = getMarketTokenPriceCallData - }; - var getMarketTokenPriceMinCallData = new GetMarketTokenPriceFunction - { - DataStore = Arbitrum.AddressV2.DataStore, - Market = marketProps, - IndexTokenPrice = marketPrices.IndexTokenPrice, - LongTokenPrice = marketPrices.LongTokenPrice, - ShortTokenPrice = marketPrices.ShortTokenPrice, - PnlFactorType = _helpers.HashString(Constants.GMX.MAX_PNL_FACTOR_FOR_TRADERS), - Maximize = false - }.GetCallData(); - var getMarketTokenPriceMinCall = new Call - { - Target = Arbitrum.AddressV2.Reader, - CallData = getMarketTokenPriceMinCallData - }; + MarketToken = market.MarketToken, + IndexToken = market.IndexToken, + LongToken = market.LongToken, + ShortToken = market.ShortToken + }; - var readerMulticall = new AggregateFunction(); - readerMulticall.Calls = new List(); - readerMulticall.Calls.Add(getMarketInfoCall); - readerMulticall.Calls.Add(getMarketTokenPriceCall); - readerMulticall.Calls.Add(getMarketTokenPriceMinCall); + var getMarketInfoCallData = new GetMarketInfoFunction + { + DataStore = Arbitrum.AddressV2.DataStore, + Prices = marketPrices, + MarketKey = market.MarketToken + }.GetCallData(); + var getMarketInfoCall = new Call + { + Target = Arbitrum.AddressV2.Reader, + CallData = getMarketInfoCallData + }; - var queryHandler = web3.Eth.GetContractQueryHandler(); - var readerCallResults = await queryHandler - .QueryDeserializingToObjectAsync(readerMulticall, Arbitrum.AddressV2.Multicall) - .ConfigureAwait(false); + var getMarketTokenPriceCallData = new GetMarketTokenPriceFunction + { + DataStore = Arbitrum.AddressV2.DataStore, + Market = marketProps, + IndexTokenPrice = marketPrices.IndexTokenPrice, + LongTokenPrice = marketPrices.LongTokenPrice, + ShortTokenPrice = marketPrices.ShortTokenPrice, + PnlFactorType = _helpers.HashString(Constants.GMX.MAX_PNL_FACTOR_FOR_TRADERS), + Maximize = true + }.GetCallData(); + var getMarketTokenPriceCall = new Call + { + Target = Arbitrum.AddressV2.Reader, + CallData = getMarketTokenPriceCallData + }; - var marketInfo = new GetMarketInfoOutputDTO().DecodeOutput(readerCallResults.ReturnData[0].ToHex()); - var marketTokenPriceMax = - new GetMarketTokenPriceOutputDTO().DecodeOutput(readerCallResults.ReturnData[1].ToHex()); - var marketTokenPriceMin = - new GetMarketTokenPriceOutputDTO().DecodeOutput(readerCallResults.ReturnData[2].ToHex()); + var getMarketTokenPriceMinCallData = new GetMarketTokenPriceFunction + { + DataStore = Arbitrum.AddressV2.DataStore, + Market = marketProps, + IndexTokenPrice = marketPrices.IndexTokenPrice, + LongTokenPrice = marketPrices.LongTokenPrice, + ShortTokenPrice = marketPrices.ShortTokenPrice, + PnlFactorType = _helpers.HashString(Constants.GMX.MAX_PNL_FACTOR_FOR_TRADERS), + Maximize = false + }.GetCallData(); + var getMarketTokenPriceMinCall = new Call + { + Target = Arbitrum.AddressV2.Reader, + CallData = getMarketTokenPriceMinCallData + }; - // Get hashed key to call datastore - var marketKeys = GmxKeysService.GetMarketKeys(market.MarketToken); - if (marketKeys == null) - continue; + readerCalls.Add(getMarketInfoCall); + readerCalls.Add(getMarketTokenPriceCall); + readerCalls.Add(getMarketTokenPriceMinCall); - var longInterestUsingLongTokenCallData = new GetUintFunction() - { - Key = marketKeys.LongInterestUsingLongToken.HexToByteArray() - }.GetCallData(); - var longInterestUsingLongTokenCall = new Call - { - Target = Arbitrum.AddressV2.DataStore, - CallData = longInterestUsingLongTokenCallData - }; - var longInterestUsingShortTokenCallData = new GetUintFunction() - { - Key = marketKeys.LongInterestUsingShortToken.HexToByteArray() - }.GetCallData(); - var longInterestUsingShortTokenCall = new Call - { - Target = Arbitrum.AddressV2.DataStore, - CallData = longInterestUsingShortTokenCallData - }; - var shortInterestUsingLongTokenCallData = new GetUintFunction() - { - Key = marketKeys.ShortInterestUsingLongToken.HexToByteArray() - }.GetCallData(); - var shortInterestUsingLongTokenCall = new Call - { - Target = Arbitrum.AddressV2.DataStore, - CallData = shortInterestUsingLongTokenCallData - }; - var shortInterestUsingShortTokenCallData = new GetUintFunction() - { - Key = marketKeys.ShortInterestUsingShortToken.HexToByteArray() - }.GetCallData(); - var shortInterestUsingShortTokenCall = new Call - { - Target = Arbitrum.AddressV2.DataStore, - CallData = shortInterestUsingShortTokenCallData - }; + var marketKeys = GmxKeysService.GetMarketKeys(market.MarketToken); + if (marketKeys == null) + continue; - var dataStoreMulticall = new AggregateFunction(); - dataStoreMulticall.Calls = new List(); - dataStoreMulticall.Calls.Add(longInterestUsingLongTokenCall); - dataStoreMulticall.Calls.Add(longInterestUsingShortTokenCall); - dataStoreMulticall.Calls.Add(shortInterestUsingLongTokenCall); - dataStoreMulticall.Calls.Add(shortInterestUsingShortTokenCall); + var longInterestUsingLongTokenCallData = new GetUintFunction + { + Key = marketKeys.LongInterestUsingLongToken.HexToByteArray() + }.GetCallData(); + var longInterestUsingLongTokenCall = new Call + { + Target = Arbitrum.AddressV2.DataStore, + CallData = longInterestUsingLongTokenCallData + }; + var longInterestUsingShortTokenCallData = new GetUintFunction + { + Key = marketKeys.LongInterestUsingShortToken.HexToByteArray() + }.GetCallData(); + var longInterestUsingShortTokenCall = new Call + { + Target = Arbitrum.AddressV2.DataStore, + CallData = longInterestUsingShortTokenCallData + }; + var shortInterestUsingLongTokenCallData = new GetUintFunction + { + Key = marketKeys.ShortInterestUsingLongToken.HexToByteArray() + }.GetCallData(); + var shortInterestUsingLongTokenCall = new Call + { + Target = Arbitrum.AddressV2.DataStore, + CallData = shortInterestUsingLongTokenCallData + }; + var shortInterestUsingShortTokenCallData = new GetUintFunction + { + Key = marketKeys.ShortInterestUsingShortToken.HexToByteArray() + }.GetCallData(); + var shortInterestUsingShortTokenCall = new Call + { + Target = Arbitrum.AddressV2.DataStore, + CallData = shortInterestUsingShortTokenCallData + }; - // Call datastore to get market info - var dataStoreQueryHandler = web3.Eth.GetContractQueryHandler(); - var dataStoreCallResults = await dataStoreQueryHandler - .QueryDeserializingToObjectAsync(dataStoreMulticall, Arbitrum.AddressV2.Multicall) - .ConfigureAwait(false); - - var marketInfos = GmxMappers.Map(marketInfo.ReturnValue1); - readerResult.Add(new GmxMarketInfo() - { - Market = marketInfos, - Infos = DecodeFundingRateOutput(dataStoreCallResults, marketInfos.IsSameCollaterals), - MarketTokenPriceMax = GmxMappers.Map(marketTokenPriceMax), - MarketTokenPriceMin = GmxMappers.Map(marketTokenPriceMin) - }); - } - - return readerResult; + datastoreCalls.Add(longInterestUsingLongTokenCall); + datastoreCalls.Add(longInterestUsingShortTokenCall); + datastoreCalls.Add(shortInterestUsingLongTokenCall); + datastoreCalls.Add(shortInterestUsingShortTokenCall); } + var readerMulticall = new AggregateFunction { Calls = readerCalls }; + var datastoreMulticall = new AggregateFunction { Calls = datastoreCalls }; + + var queryHandler = web3.Eth.GetContractQueryHandler(); + var readerCallResults = await queryHandler + .QueryDeserializingToObjectAsync(readerMulticall, Arbitrum.AddressV2.Multicall) + .ConfigureAwait(false); + var datastoreCallResults = await queryHandler + .QueryDeserializingToObjectAsync(datastoreMulticall, Arbitrum.AddressV2.Multicall) + .ConfigureAwait(false); + + int readerCallIndex = 0; + int datastoreCallIndex = 0; + foreach (var market in markets) + { + var marketInfo = new GetMarketInfoOutputDTO().DecodeOutput(readerCallResults.ReturnData[readerCallIndex++].ToHex()); + var marketTokenPriceMax = new GetMarketTokenPriceOutputDTO().DecodeOutput(readerCallResults.ReturnData[readerCallIndex++].ToHex()); + var marketTokenPriceMin = new GetMarketTokenPriceOutputDTO().DecodeOutput(readerCallResults.ReturnData[readerCallIndex++].ToHex()); + + var marketKeys = GmxKeysService.GetMarketKeys(market.MarketToken); + if (marketKeys == null) + continue; + + var longInterestUsingLongToken = new GetUintOutputDTO().DecodeOutput(datastoreCallResults.ReturnData[datastoreCallIndex++].ToHex()).ReturnValue1; + var longInterestUsingShortToken = new GetUintOutputDTO().DecodeOutput(datastoreCallResults.ReturnData[datastoreCallIndex++].ToHex()).ReturnValue1; + var shortInterestUsingLongToken = new GetUintOutputDTO().DecodeOutput(datastoreCallResults.ReturnData[datastoreCallIndex++].ToHex()).ReturnValue1; + var shortInterestUsingShortToken = new GetUintOutputDTO().DecodeOutput(datastoreCallResults.ReturnData[datastoreCallIndex++].ToHex()).ReturnValue1; + + var marketInfos = GmxMappers.Map(marketInfo.ReturnValue1); + readerResult.Add(new GmxMarketInfo + { + Market = marketInfos, + Infos = new GmxMarketInfos + { + LongInterestUsd = longInterestUsingLongToken + longInterestUsingShortToken, + ShortInterestUsd = shortInterestUsingLongToken + shortInterestUsingShortToken + }, + MarketTokenPriceMax = GmxMappers.Map(marketTokenPriceMax), + MarketTokenPriceMin = GmxMappers.Map(marketTokenPriceMin) + }); + } + + return readerResult; +} private GmxMarketInfos DecodeFundingRateOutput(AggregateOutputDTO results, bool isSameCollaterals) { var marketDivisor = new BigInteger(isSameCollaterals ? 2 : 1);