@@ -9,10 +9,11 @@ const { sub } = require('date-fns');
99
1010const { default : BigNumber } = require ( 'bignumber.js' ) ;
1111
12+ const MARKETS_PAGE_SIZE = 100 ;
13+
1214const SUBGRAPH_URL = {
13- arbitrum :
14- 'https://subgraph.satsuma-prod.com/3b2ced13c8d9/gmx/synthetics-arbitrum-stats/api' ,
15- avax : 'https://subgraph.satsuma-prod.com/3b2ced13c8d9/gmx/synthetics-avalanche-stats/api' ,
15+ arbitrum : 'https://gmx.squids.live/gmx-synthetics-arbitrum:prod/api/graphql' ,
16+ avax : 'https://gmx.squids.live/gmx-synthetics-avalanche:prod/api/graphql' ,
1617} ;
1718
1819const CONTRACTS = {
@@ -52,45 +53,43 @@ const MAX_PNL_FACTOR_FOR_DEPOSITS_KEY = hashString(
5253) ;
5354
5455const marketsQuery = gql `
55- query M {
56- marketInfos {
56+ query M($limit: Int!, $offset: Int!) {
57+ marketInfos(limit: $limit, offset: $offset) {
5758 id
58- marketToken
59- indexToken
60- longToken
61- shortToken
59+ marketTokenAddress
60+ indexTokenAddress
61+ longTokenAddress
62+ shortTokenAddress
6263 }
6364 }
6465` ;
6566
6667const marketFeesQuery = ( marketAddress ) => {
6768 return `
68- _${ marketAddress } _lte_start_of_period_: collectedMarketFeesInfos(
69- orderBy:timestampGroup
70- orderDirection:desc
71- where: {
72- marketAddress: "${ marketAddress . toLowerCase ( ) } ",
73- period: "1h",
74- timestampGroup_lte: ${ Math . floor (
75- sub ( new Date ( ) , { days : 7 } ) . valueOf ( ) / 1000
76- ) }
77- },
78- first: 1
79- ) {
80- cumulativeFeeUsdPerPoolValue
81- }
82- _${ marketAddress } _recent: collectedMarketFeesInfos(
83- orderBy: timestampGroup
84- orderDirection: desc
85- where: {
86- marketAddress: "${ marketAddress . toLowerCase ( ) } ",
87- period: "1h"
88- },
89- first: 1
90- ) {
91- cumulativeFeeUsdPerPoolValue
92- }
93- ` ;
69+ _${ marketAddress } _lte_start_of_period_: collectedFeesInfos(
70+ orderBy: timestampGroup_DESC
71+ where: {
72+ address_containsInsensitive: "${ marketAddress . toLowerCase ( ) } "
73+ period_eq: "1h"
74+ timestampGroup_lte: ${ Math . floor (
75+ sub ( new Date ( ) , { days : 7 } ) . valueOf ( ) / 1000
76+ ) }
77+ }
78+ limit: 1
79+ ) {
80+ cumulativeFeeUsdPerPoolValue
81+ }
82+ _${ marketAddress } _recent: collectedFeesInfos(
83+ orderBy: timestampGroup_DESC
84+ where: {
85+ address_containsInsensitive: "${ marketAddress . toLowerCase ( ) } "
86+ period_eq: "1h"
87+ }
88+ limit: 1
89+ ) {
90+ cumulativeFeeUsdPerPoolValue
91+ }
92+ ` ;
9493} ;
9594
9695function bigNumberify ( n ) {
@@ -107,19 +106,40 @@ function expandDecimals(n, decimals) {
107106}
108107
109108const getMarkets = async ( chain ) => {
110- const { marketInfos } = await request ( SUBGRAPH_URL [ chain ] , marketsQuery ) ;
111-
112- const queryBody = marketInfos . reduce (
113- ( acc , market ) => acc + marketFeesQuery ( market . id ) ,
114- ''
115- ) ;
109+ const marketInfos = [ ] ;
110+ let offset = 0 ;
111+ while ( true ) {
112+ const { marketInfos : batch } = await request (
113+ SUBGRAPH_URL [ chain ] ,
114+ marketsQuery ,
115+ { limit : MARKETS_PAGE_SIZE , offset }
116+ ) ;
117+ if ( ! batch ?. length ) break ;
118+ marketInfos . push ( ...batch ) ;
119+ if ( batch . length < MARKETS_PAGE_SIZE ) break ;
120+ offset += MARKETS_PAGE_SIZE ;
121+ }
116122
117- const res = await request (
118- SUBGRAPH_URL [ chain ] ,
119- gql `query M {
123+ if ( ! marketInfos . length ) return [ ] ;
124+
125+ const queryBody = marketInfos . reduce ( ( acc , market ) => {
126+ const marketAddress = (
127+ market . marketTokenAddress ||
128+ market . id ||
129+ ''
130+ ) . toLowerCase ( ) ;
131+ if ( ! marketAddress ) return acc ;
132+ return acc + marketFeesQuery ( marketAddress ) ;
133+ } , '' ) ;
134+
135+ const res = queryBody
136+ ? await request (
137+ SUBGRAPH_URL [ chain ] ,
138+ gql `query M {
120139 ${ queryBody }
121140 }`
122- ) ;
141+ )
142+ : { } ;
123143
124144 const tickers = (
125145 await fetch ( TICKERS_URL [ chain ] ) . then ( ( r ) => r . json ( ) )
@@ -137,16 +157,32 @@ const getMarkets = async (chain) => {
137157
138158 const marketResults = { } ;
139159
140- const marketCall = await Promise . all (
160+ await Promise . all (
141161 marketInfos . map ( async ( market ) => {
162+ const {
163+ marketTokenAddress,
164+ longTokenAddress,
165+ shortTokenAddress,
166+ indexTokenAddress,
167+ } = market ;
168+
169+ if ( ! marketTokenAddress || ! longTokenAddress || ! shortTokenAddress )
170+ return null ;
171+
142172 const marketProps = {
143- marketToken : market . marketToken ,
144- longToken : market . longToken ,
145- shortToken : market . shortToken ,
146- indexToken : market . indexToken ,
173+ marketToken : marketTokenAddress ,
174+ longToken : longTokenAddress ,
175+ shortToken : shortTokenAddress ,
176+ indexToken : indexTokenAddress ,
147177 } ;
148178
149- if ( ! tickers [ market . longToken ?. toLowerCase ( ) ] ) return null ;
179+ const indexTicker =
180+ tickers [ indexTokenAddress ?. toLowerCase ( ) ] || tickers [ WETH [ chain ] ] ;
181+ const longTicker = tickers [ longTokenAddress ?. toLowerCase ( ) ] ;
182+ const shortTicker = tickers [ shortTokenAddress ?. toLowerCase ( ) ] ;
183+
184+ if ( ! indexTicker || ! longTicker || ! shortTicker ) return null ;
185+
150186 const min = (
151187 await sdk . api . abi . call ( {
152188 target : CONTRACTS [ chain ] . syntheticsReader , // synthetix,
@@ -155,9 +191,9 @@ const getMarkets = async (chain) => {
155191 params : [
156192 CONTRACTS [ chain ] . dataStore , //datastore
157193 marketProps ,
158- tickers [ market . indexToken ?. toLowerCase ( ) ] || tickers [ WETH [ chain ] ] ,
159- tickers [ market . longToken ?. toLowerCase ( ) ] ,
160- tickers [ market . shortToken ?. toLowerCase ( ) ] ,
194+ indexTicker ,
195+ longTicker ,
196+ shortTicker ,
161197 MAX_PNL_FACTOR_FOR_DEPOSITS_KEY ,
162198 false ,
163199 ] ,
@@ -171,23 +207,28 @@ const getMarkets = async (chain) => {
171207 params : [
172208 CONTRACTS [ chain ] . dataStore , //datastore
173209 marketProps ,
174- tickers [ market . indexToken ?. toLowerCase ( ) ] || tickers [ WETH [ chain ] ] ,
175- tickers [ market . longToken ?. toLowerCase ( ) ] ,
176- tickers [ market . shortToken ?. toLowerCase ( ) ] ,
210+ indexTicker ,
211+ longTicker ,
212+ shortTicker ,
177213 MAX_PNL_FACTOR_FOR_DEPOSITS_KEY ,
178214 true ,
179215 ] ,
180216 } )
181217 ) . output ;
182218
183219 const supply = await sdk . api . erc20 . totalSupply ( {
184- target : market . marketToken ,
220+ target : marketTokenAddress ,
185221 chain : chain ,
186222 } ) ;
187223
188- const tvl = ( ( supply . output / 1e18 ) * min [ 0 ] ) / 1e30 ;
224+ const tvl = BigNumber ( supply . output || 0 )
225+ . div ( 1e18 )
226+ . times ( BigNumber ( min [ 0 ] || 0 ) )
227+ . div ( 1e30 )
228+ . toNumber ( ) ;
229+ if ( ! Number . isFinite ( tvl ) ) return null ;
189230
190- marketResults [ market . marketToken . toLowerCase ( ) ] = {
231+ marketResults [ marketTokenAddress . toLowerCase ( ) ] = {
191232 totalSupply : supply . output ,
192233 minPrice : min [ 0 ] ,
193234 maxPrice : max [ 0 ] ,
@@ -218,19 +259,25 @@ const getMarkets = async (chain) => {
218259 ) ;
219260 }
220261
221- const marketTokensAPRData = marketInfos . map ( ( market , i ) => {
222- const marketAddress = market . id ;
223- const marketToken = market . marketToken . toLowerCase ( ) ;
224- const marketData = marketResults [ marketToken ] ;
225- const lteStartOfPeriodFees = res [ `_${ marketAddress } _lte_start_of_period_` ] ;
226- const recentFees = res [ `_${ marketAddress } _recent` ] ;
262+ const marketTokensAPRData = marketInfos . map ( ( market ) => {
263+ const marketToken = market . marketTokenAddress ;
264+ const marketAddress = marketToken ?. toLowerCase ( ) ;
265+ if ( ! marketAddress ) return ;
266+
267+ const marketData = marketResults [ marketAddress ] ;
268+ if ( ! marketData ) return ;
269+
270+ const lteStartOfPeriodFees =
271+ res [ `_${ marketAddress } _lte_start_of_period_` ] || [ ] ;
272+ const recentFees = res [ `_${ marketAddress } _recent` ] || [ ] ;
227273
228274 const poolValue1 =
229- bigNumberify ( lteStartOfPeriodFees [ 0 ] ?. cumulativeFeeUsdPerPoolValue ) ??
230- BigNumber . from ( 0 ) ;
231- const poolValue2 = bigNumberify (
232- recentFees [ 0 ] ?. cumulativeFeeUsdPerPoolValue
233- ) ;
275+ bigNumberify ( lteStartOfPeriodFees [ 0 ] ?. cumulativeFeeUsdPerPoolValue ) ||
276+ BigNumber ( 0 ) ;
277+ const poolValue2 =
278+ bigNumberify ( recentFees [ 0 ] ?. cumulativeFeeUsdPerPoolValue ) || BigNumber ( 0 ) ;
279+
280+ if ( poolValue1 . isNaN ( ) || poolValue2 . isNaN ( ) ) return ;
234281
235282 if ( poolValue2 ) {
236283 const incomePercentageForPeriod = poolValue2 . minus ( poolValue1 ) ;
@@ -239,16 +286,19 @@ const getMarkets = async (chain) => {
239286 const apr = incomePercentageForPeriod
240287 . times ( yearMultiplier )
241288 . div ( expandDecimals ( 1 , 26 ) ) ;
289+ const apyBase = apr . div ( 100 ) . toNumber ( ) ;
290+ if ( ! Number . isFinite ( apyBase ) ) return ;
242291
243292 const longSymbol =
244- tickers [ market . longToken . toLowerCase ( ) ] ?. data ?. tokenSymbol ;
293+ tickers [ market . longTokenAddress . toLowerCase ( ) ] ?. data ?. tokenSymbol ;
245294 const shortSymbol =
246- tickers [ market . shortToken . toLowerCase ( ) ] ?. data ?. tokenSymbol ;
295+ tickers [ market . shortTokenAddress . toLowerCase ( ) ] ?. data ?. tokenSymbol ;
247296
248- const tvlUsd = parseFloat ( marketData ?. tvl ) ;
297+ const tvlUsd = Number ( marketData ?. tvl ) ;
298+ if ( ! Number . isFinite ( tvlUsd ) ) return ;
249299
250300 let apyReward ;
251- if ( rewards ) {
301+ if ( rewards && tvlUsd > 0 ) {
252302 const rewardPerYear =
253303 ( rewards [ marketAddress . toLowerCase ( ) ] / 1e18 ) *
254304 52 *
@@ -263,16 +313,15 @@ const getMarkets = async (chain) => {
263313 project : 'gmx-v2-perps' ,
264314 symbol : `${ longSymbol } -${ shortSymbol } ` ,
265315 tvlUsd,
266- apyBase : apr . toString ( ) / 100 ,
316+ apyBase,
267317 apyReward : apyReward ?? null ,
268- underlyingTokens : [ market . longToken , market . shortToken ] ,
318+ underlyingTokens : [ market . longTokenAddress , market . shortTokenAddress ] ,
269319 rewardTokens : apyReward > 0 ? [ ARB ] : [ ] ,
270320 } ;
271321 } else {
272322 return ;
273323 }
274324 } ) ;
275-
276325 return marketTokensAPRData . filter ( Boolean ) . filter ( ( i ) => utils . keepFinite ( i ) ) ;
277326} ;
278327
0 commit comments