1
- const { gql, request } = require ( 'graphql-request' ) ;
1
+ const { gql, request } = require ( "graphql-request" ) ;
2
+
3
+ const SUBGRAPH_ENDPOINTS = {
4
+ arbitrum :
5
+ "https://api.0xgraph.xyz/api/public/e2146f32-5728-4755-b1d1-84d17708c119/subgraphs/clamm-arbitrum/prod/gn" ,
6
+ sonic :
7
+ "https://api.0xgraph.xyz/api/public/e2146f32-5728-4755-b1d1-84d17708c119/subgraphs/clamm-sonic/prod/gn" ,
8
+ base : "https://api.0xgraph.xyz/api/public/e2146f32-5728-4755-b1d1-84d17708c119/subgraphs/clamm-base/prod/gn" ,
9
+ blast :
10
+ "https://api.0xgraph.xyz/api/public/e2146f32-5728-4755-b1d1-84d17708c119/subgraphs/clamm-blast/prod/gn" ,
11
+ mantle :
12
+ "https://api.0xgraph.xyz/api/public/e2146f32-5728-4755-b1d1-84d17708c119/subgraphs/clamm-mantle/prod/gn" ,
13
+ } ;
2
14
3
- const endpoint = 'https://api.0xgraph.xyz/subgraphs/name/dopex-v2-clamm-public' ;
4
- const abi = "function slot0() view returns (uint160 sqrtPriceX96, int24 tick, uint16 observationIndex, uint16 observationCardinality, uint16 observationCardinalityNext, uint8 feeProtocol, bool unlocked)"
15
+ const abi =
16
+ "function slot0() view returns (uint160 sqrtPriceX96, int24 tick, uint16 observationIndex, uint16 observationCardinality, uint16 observationCardinalityNext, uint8 feeProtocol, bool unlocked)" ;
5
17
6
18
const query = gql `
7
19
query strikes($limit: Int!, $skip: Int!) {
@@ -13,77 +25,104 @@ const query = gql`
13
25
orderDirection: desc
14
26
) {
15
27
pool
16
- token0 {id}
17
- token1 {id}
28
+ token0 {
29
+ id
30
+ }
31
+ token1 {
32
+ id
33
+ }
18
34
tickLower
19
35
tickUpper
20
36
totalLiquidity
21
37
}
22
38
}
23
39
` ;
24
40
25
- async function fetchStrikes ( limit , skip , allData = [ ] ) {
41
+ async function fetchStrikes ( endpoint , limit , skip , allData = [ ] ) {
26
42
const variables = { limit, skip } ;
27
43
const { strikes } = await request ( endpoint , query , variables ) ;
28
44
allData . push ( ...strikes ) ;
29
45
30
46
if ( strikes . length === limit ) {
31
- return fetchStrikes ( limit , skip + limit , allData ) ;
47
+ return fetchStrikes ( endpoint , limit , skip + limit , allData ) ;
32
48
}
33
49
34
50
return allData ;
35
51
}
36
52
37
53
function addV3PositionBalances ( strike , sqrtPricesMap ) {
38
- const tickToPrice = ( tick ) => 1.0001 ** tick
39
- const token0 = strike . token0 . id
40
- const token1 = strike . token1 . id
41
- const liquidity = strike . totalLiquidity
42
- const bottomTick = + strike . tickLower
43
- const topTick = + strike . tickUpper
44
- const tick = + sqrtPricesMap [ strike . pool . toLowerCase ( ) ] . tick
45
- const sa = tickToPrice ( bottomTick / 2 )
46
- const sb = tickToPrice ( topTick / 2 )
47
-
48
- let amount0 = 0
49
- let amount1 = 0
54
+ const tickToPrice = ( tick ) => 1.0001 ** tick ;
55
+ const token0 = strike . token0 . id ;
56
+ const token1 = strike . token1 . id ;
57
+ const liquidity = strike . totalLiquidity ;
58
+ const bottomTick = + strike . tickLower ;
59
+ const topTick = + strike . tickUpper ;
60
+ const tick = + sqrtPricesMap [ strike . pool . toLowerCase ( ) ] . tick ;
61
+ const sa = tickToPrice ( bottomTick / 2 ) ;
62
+ const sb = tickToPrice ( topTick / 2 ) ;
63
+
64
+ let amount0 = 0 ;
65
+ let amount1 = 0 ;
50
66
51
67
if ( tick < bottomTick ) {
52
- amount0 = liquidity * ( sb - sa ) / ( sa * sb )
68
+ amount0 = ( liquidity * ( sb - sa ) ) / ( sa * sb ) ;
53
69
} else if ( tick < topTick ) {
54
- const price = tickToPrice ( tick )
55
- const sp = price ** 0.5
70
+ const price = tickToPrice ( tick ) ;
71
+ const sp = price ** 0.5 ;
56
72
57
- amount0 = liquidity * ( sb - sp ) / ( sp * sb )
58
- amount1 = liquidity * ( sp - sa )
73
+ amount0 = ( liquidity * ( sb - sp ) ) / ( sp * sb ) ;
74
+ amount1 = liquidity * ( sp - sa ) ;
59
75
} else {
60
- amount1 = liquidity * ( sb - sa )
76
+ amount1 = liquidity * ( sb - sa ) ;
61
77
}
62
78
63
- return { token0, amount0, token1, amount1 }
79
+ return { token0, amount0, token1, amount1 } ;
64
80
}
65
81
66
- async function tvl ( api ) {
67
- const limit = 1000 ;
68
- const allData = await fetchStrikes ( limit , 0 ) ;
69
-
70
- let pools = allData . map ( strike => strike . pool . toLowerCase ( ) )
71
- pools = [ ...new Set ( pools ) ]
72
- const sqrtPrices = await api . multiCall ( { calls : pools , abi } )
73
- const sqrtPricesMap = sqrtPrices . reduce ( ( acc , item , i ) => {
74
- return { ...acc , [ pools [ i ] ] : item , }
75
- } , { } ) ;
76
-
77
- allData . forEach ( ( strike ) => {
78
- const { token0, amount0, token1, amount1 } = addV3PositionBalances ( strike , sqrtPricesMap ) ;
79
- api . add ( token0 , amount0 ) ;
80
- api . add ( token1 , amount1 ) ;
81
- } ) ;
82
+ function tvlByChain ( chain ) {
83
+ return async function ( api ) {
84
+ const endpoint = SUBGRAPH_ENDPOINTS [ chain ] ;
85
+ if ( ! endpoint )
86
+ throw new Error ( `No subgraph endpoint configured for chain: ${ chain } ` ) ;
87
+
88
+ const limit = 1000 ;
89
+ const allData = await fetchStrikes ( endpoint , limit , 0 ) ;
90
+
91
+ let pools = allData . map ( ( strike ) => strike . pool . toLowerCase ( ) ) ;
92
+ pools = [ ...new Set ( pools ) ] ;
93
+ const sqrtPrices = await api . multiCall ( { calls : pools , abi } ) ;
94
+ const sqrtPricesMap = sqrtPrices . reduce ( ( acc , item , i ) => {
95
+ return { ...acc , [ pools [ i ] ] : item } ;
96
+ } , { } ) ;
97
+
98
+ allData . forEach ( ( strike ) => {
99
+ const { token0, amount0, token1, amount1 } = addV3PositionBalances (
100
+ strike ,
101
+ sqrtPricesMap
102
+ ) ;
103
+ api . add ( token0 , amount0 ) ;
104
+ api . add ( token1 , amount1 ) ;
105
+ } ) ;
106
+ } ;
82
107
}
83
108
84
109
module . exports = {
85
- doublecounted : true , // tokens are stored in UNI-V3 pools
86
- arbitrum : { tvl, } ,
110
+ doublecounted : true , // tokens are stored in UNI-V3 pools
111
+ arbitrum : {
112
+ tvl : tvlByChain ( "arbitrum" ) ,
113
+ } ,
114
+ sonic : {
115
+ tvl : tvlByChain ( "sonic" ) ,
116
+ } ,
117
+ base : {
118
+ tvl : tvlByChain ( "base" ) ,
119
+ } ,
120
+ blast : {
121
+ tvl : tvlByChain ( "blast" ) ,
122
+ } ,
123
+ mantle : {
124
+ tvl : tvlByChain ( "mantle" ) ,
125
+ } ,
126
+ methodology :
127
+ "TVL is calculated by summing the value of all tokens in Stryke liquidity positions across supported chains" ,
87
128
} ;
88
-
89
-
0 commit comments