11import { Address , BigDecimal , BigInt , log } from '@graphprotocol/graph-ts'
22
3- import { AggregatorHook } from '../types/PoolManager/AggregatorHook'
3+ import { AggregatorHook , HookSwap as HookSwapEvent } from '../types/PoolManager/AggregatorHook'
44import { Swap as SwapEvent } from '../types/PoolManager/PoolManager'
55import { Bundle , Pool , PoolManager , Swap , Token } from '../types/schema'
66import { getSubgraphConfig , getUSDStableStableHookAddresses , SubgraphConfig } from '../utils/chains'
@@ -24,6 +24,128 @@ export function handleSwap(event: SwapEvent): void {
2424 handleSwapHelper ( event )
2525}
2626
27+ export function handleHookSwap ( event : HookSwapEvent ) : void {
28+ const usdStableStableHookAddresses = getUSDStableStableHookAddresses ( )
29+ const bundle = Bundle . load ( '1' )
30+
31+ if ( bundle === null ) {
32+ return
33+ }
34+
35+ const poolId = event . params . poolId . toHexString ( )
36+ const pool = Pool . load ( poolId )
37+ if ( pool === null ) {
38+ log . warning ( 'Pool not found for HookSwap: {}' , [ poolId ] )
39+ return
40+ }
41+
42+ if ( ! usdStableStableHookAddresses . includes ( pool . hooks . toLowerCase ( ) ) ) {
43+ return
44+ }
45+
46+ const token0 = Token . load ( pool . token0 )
47+ const token1 = Token . load ( pool . token1 )
48+ if ( token0 === null || token1 === null ) {
49+ return
50+ }
51+
52+ const amount0 = convertTokenToDecimal ( event . params . amount0 , token0 . decimals )
53+ const amount1 = convertTokenToDecimal ( event . params . amount1 , token1 . decimals )
54+ const amount0Abs = amount0 . lt ( ZERO_BD ) ? amount0 . times ( BigDecimal . fromString ( '-1' ) ) : amount0
55+ const amount1Abs = amount1 . lt ( ZERO_BD ) ? amount1 . times ( BigDecimal . fromString ( '-1' ) ) : amount1
56+
57+ const amountTotalUSDTracked = amount0Abs . plus ( amount1Abs ) . div ( BigDecimal . fromString ( '2' ) )
58+ const amountTotalUSDUntracked = amountTotalUSDTracked
59+
60+ pool . feeTier = BigInt . fromI32 ( event . params . swapFee )
61+
62+ const feesUSD = amountTotalUSDTracked . times ( pool . feeTier . toBigDecimal ( ) ) . div ( BigDecimal . fromString ( '1000000' ) )
63+
64+ pool . volumeToken0 = pool . volumeToken0 . plus ( amount0Abs )
65+ pool . volumeToken1 = pool . volumeToken1 . plus ( amount1Abs )
66+ pool . volumeUSD = pool . volumeUSD . plus ( amountTotalUSDTracked )
67+ pool . untrackedVolumeUSD = pool . untrackedVolumeUSD . plus ( amountTotalUSDUntracked )
68+ pool . feesUSD = pool . feesUSD . plus ( feesUSD )
69+
70+ token0 . volume = token0 . volume . plus ( amount0Abs )
71+ token0 . volumeUSD = token0 . volumeUSD . plus ( amountTotalUSDTracked )
72+ token0 . untrackedVolumeUSD = token0 . untrackedVolumeUSD . plus ( amountTotalUSDUntracked )
73+ token0 . feesUSD = token0 . feesUSD . plus ( feesUSD )
74+
75+ token1 . volume = token1 . volume . plus ( amount1Abs )
76+ token1 . volumeUSD = token1 . volumeUSD . plus ( amountTotalUSDTracked )
77+ token1 . untrackedVolumeUSD = token1 . untrackedVolumeUSD . plus ( amountTotalUSDUntracked )
78+ token1 . feesUSD = token1 . feesUSD . plus ( feesUSD )
79+
80+ const poolDayData = updatePoolDayData ( poolId , event )
81+ const poolHourData = updatePoolHourData ( poolId , event )
82+ const token0DayData = updateTokenDayData ( token0 , event )
83+ const token1DayData = updateTokenDayData ( token1 , event )
84+ const token0HourData = updateTokenHourData ( token0 , event )
85+ const token1HourData = updateTokenHourData ( token1 , event )
86+
87+ // HookSwap volume is internal to the aggregator hook, so we intentionally do not
88+ // update global protocol aggregates (PoolManager / UniswapDayData) here.
89+
90+ poolDayData . volumeUSD = poolDayData . volumeUSD . plus ( amountTotalUSDTracked )
91+ poolDayData . volumeToken0 = poolDayData . volumeToken0 . plus ( amount0Abs )
92+ poolDayData . volumeToken1 = poolDayData . volumeToken1 . plus ( amount1Abs )
93+ poolDayData . feesUSD = poolDayData . feesUSD . plus ( feesUSD )
94+
95+ poolHourData . volumeUSD = poolHourData . volumeUSD . plus ( amountTotalUSDTracked )
96+ poolHourData . volumeToken0 = poolHourData . volumeToken0 . plus ( amount0Abs )
97+ poolHourData . volumeToken1 = poolHourData . volumeToken1 . plus ( amount1Abs )
98+ poolHourData . feesUSD = poolHourData . feesUSD . plus ( feesUSD )
99+
100+ token0DayData . volume = token0DayData . volume . plus ( amount0Abs )
101+ token0DayData . volumeUSD = token0DayData . volumeUSD . plus ( amountTotalUSDTracked )
102+ token0DayData . untrackedVolumeUSD = token0DayData . untrackedVolumeUSD . plus ( amountTotalUSDTracked )
103+ token0DayData . feesUSD = token0DayData . feesUSD . plus ( feesUSD )
104+
105+ token0HourData . volume = token0HourData . volume . plus ( amount0Abs )
106+ token0HourData . volumeUSD = token0HourData . volumeUSD . plus ( amountTotalUSDTracked )
107+ token0HourData . untrackedVolumeUSD = token0HourData . untrackedVolumeUSD . plus ( amountTotalUSDTracked )
108+ token0HourData . feesUSD = token0HourData . feesUSD . plus ( feesUSD )
109+
110+ token1DayData . volume = token1DayData . volume . plus ( amount1Abs )
111+ token1DayData . volumeUSD = token1DayData . volumeUSD . plus ( amountTotalUSDTracked )
112+ token1DayData . untrackedVolumeUSD = token1DayData . untrackedVolumeUSD . plus ( amountTotalUSDTracked )
113+ token1DayData . feesUSD = token1DayData . feesUSD . plus ( feesUSD )
114+
115+ token1HourData . volume = token1HourData . volume . plus ( amount1Abs )
116+ token1HourData . volumeUSD = token1HourData . volumeUSD . plus ( amountTotalUSDTracked )
117+ token1HourData . untrackedVolumeUSD = token1HourData . untrackedVolumeUSD . plus ( amountTotalUSDTracked )
118+ token1HourData . feesUSD = token1HourData . feesUSD . plus ( feesUSD )
119+
120+ const transaction = loadTransaction ( event )
121+ // Persist HookSwap as Swap. Fields not emitted by HookSwap are set to zero.
122+ const swap = new Swap ( transaction . id + '-' + event . logIndex . toString ( ) )
123+ swap . transaction = transaction . id
124+ swap . timestamp = transaction . timestamp
125+ swap . pool = pool . id
126+ swap . token0 = pool . token0
127+ swap . token1 = pool . token1
128+ swap . sender = event . params . sender
129+ swap . origin = event . transaction . from
130+ swap . amount0 = amount0
131+ swap . amount1 = amount1
132+ swap . amountUSD = amountTotalUSDTracked
133+ swap . tick = BigInt . zero ( )
134+ swap . sqrtPriceX96 = BigInt . zero ( )
135+ swap . logIndex = event . logIndex
136+
137+ pool . save ( )
138+ token0 . save ( )
139+ token1 . save ( )
140+ swap . save ( )
141+ poolDayData . save ( )
142+ poolHourData . save ( )
143+ token0DayData . save ( )
144+ token1DayData . save ( )
145+ token0HourData . save ( )
146+ token1HourData . save ( )
147+ }
148+
27149export function handleSwapHelper ( event : SwapEvent , subgraphConfig : SubgraphConfig = getSubgraphConfig ( ) ) : void {
28150 const poolManagerAddress = subgraphConfig . poolManagerAddress
29151 const stablecoinWrappedNativePoolId = subgraphConfig . stablecoinWrappedNativePoolId
@@ -56,7 +178,7 @@ export function handleSwapHelper(event: SwapEvent, subgraphConfig: SubgraphConfi
56178
57179 // Update the pool feeTier with the fee from the swap event
58180 // This is important for dynamic fee pools where we want to keep store the actual last fee rather storing the dynamic flag (8388608)
59- pool . feeTier = BigInt . fromI32 ( event . params . fee as i32 )
181+ pool . feeTier = BigInt . fromI32 ( event . params . fee )
60182
61183 // need absolute amounts for volume
62184 let amount0Abs = amount0
@@ -117,7 +239,7 @@ export function handleSwapHelper(event: SwapEvent, subgraphConfig: SubgraphConfi
117239 // Update the pool with the new active liquidity, price, and tick.
118240 pool . liquidity = event . params . liquidity
119241 pool . sqrtPrice = event . params . sqrtPriceX96
120- pool . tick = BigInt . fromI32 ( event . params . tick as i32 )
242+ pool . tick = BigInt . fromI32 ( event . params . tick )
121243 if ( ! isUSDStableStableHookPool ) {
122244 pool . totalValueLockedToken0 = pool . totalValueLockedToken0 . plus ( amount0 )
123245 pool . totalValueLockedToken1 = pool . totalValueLockedToken1 . plus ( amount1 )
@@ -183,23 +305,6 @@ export function handleSwapHelper(event: SwapEvent, subgraphConfig: SubgraphConfi
183305 token0 . totalValueLockedUSD = token0 . totalValueLocked . times ( token0 . derivedETH ) . times ( bundle . ethPriceUSD )
184306 token1 . totalValueLockedUSD = token1 . totalValueLocked . times ( token1 . derivedETH ) . times ( bundle . ethPriceUSD )
185307
186- // create Swap event
187- const transaction = loadTransaction ( event )
188- const swap = new Swap ( transaction . id + '-' + event . logIndex . toString ( ) )
189- swap . transaction = transaction . id
190- swap . timestamp = transaction . timestamp
191- swap . pool = pool . id
192- swap . token0 = pool . token0
193- swap . token1 = pool . token1
194- swap . sender = event . params . sender
195- swap . origin = event . transaction . from
196- swap . amount0 = amount0
197- swap . amount1 = amount1
198- swap . amountUSD = amountTotalUSDTracked
199- swap . tick = BigInt . fromI32 ( event . params . tick as i32 )
200- swap . sqrtPriceX96 = event . params . sqrtPriceX96
201- swap . logIndex = event . logIndex
202-
203308 // interval data
204309 const uniswapDayData = updateUniswapDayData ( event , poolManagerAddress )
205310 const poolDayData = updatePoolDayData ( event . params . id . toHexString ( ) , event )
@@ -244,14 +349,33 @@ export function handleSwapHelper(event: SwapEvent, subgraphConfig: SubgraphConfi
244349 token1HourData . untrackedVolumeUSD = token1HourData . untrackedVolumeUSD . plus ( amountTotalUSDTracked )
245350 token1HourData . feesUSD = token1HourData . feesUSD . plus ( feesUSD )
246351
247- swap . save ( )
248352 token0DayData . save ( )
249353 token1DayData . save ( )
250354 uniswapDayData . save ( )
251355 poolDayData . save ( )
252356 poolHourData . save ( )
253357 token0HourData . save ( )
254358 token1HourData . save ( )
359+ if ( ! isUSDStableStableHookPool ) {
360+ // For aggregator hook pools, HookSwap emits the canonical swap amounts, so skip
361+ // persisting the PoolManager Swap entity to avoid duplicate swap records.
362+ const transaction = loadTransaction ( event )
363+ const swap = new Swap ( transaction . id + '-' + event . logIndex . toString ( ) )
364+ swap . transaction = transaction . id
365+ swap . timestamp = transaction . timestamp
366+ swap . pool = pool . id
367+ swap . token0 = pool . token0
368+ swap . token1 = pool . token1
369+ swap . sender = event . params . sender
370+ swap . origin = event . transaction . from
371+ swap . amount0 = amount0
372+ swap . amount1 = amount1
373+ swap . amountUSD = amountTotalUSDTracked
374+ swap . tick = BigInt . fromI32 ( event . params . tick )
375+ swap . sqrtPriceX96 = event . params . sqrtPriceX96
376+ swap . logIndex = event . logIndex
377+ swap . save ( )
378+ }
255379 poolManager . save ( )
256380 pool . save ( )
257381 token0 . save ( )
0 commit comments