@@ -36,7 +36,6 @@ const ADDRESSES = {
3636// Epoch timing
3737const WEEK_SECONDS = 7 * 24 * 60 * 60 ;
3838const YEAR_IN_SECONDS = 31_536_000 ;
39- const INCENTIVE_OFFSET = 12 * 60 * 60 ; // Incentives start 12 hours after activePeriod
4039
4140// ============================================================================
4241// EPOCH CONTEXT
@@ -46,7 +45,8 @@ interface EpochContext {
4645 currentBlock : number ;
4746 timestamp : number | null ;
4847 epochStartTime : number ; // from getIncentiveStartTime()
49- epochStartBlock : number ; // from getEpochStartBlock()
48+ epochEndTime : number ; // from getIncentiveStartTime() + WEEK_SECONDS
49+ epochStartBlock : number ;
5050}
5151
5252// ============================================================================
@@ -55,56 +55,11 @@ interface EpochContext {
5555
5656/**
5757 * Get incentive epoch start time for a given timestamp/block
58- * This is activePeriod + 12 hours (incentives are start at 12:00 UTC)
5958 */
60- const getIncentiveStartTime = async ( timestamp = null , block = null ) => {
61- try {
62- const result = await sdk . api . abi . call ( {
63- target : ADDRESSES . BASE_V2_MINTER ,
64- abi : 'function activePeriod() external view returns (uint256)' ,
65- chain : CHAIN ,
66- block,
67- } ) ;
68- return parseInt ( result . output ) + INCENTIVE_OFFSET ;
69- } catch ( e ) {
70- // Fallback: compute manually using provided timestamp or current time
71- const referenceTime = timestamp || Math . floor ( Date . now ( ) / 1000 ) ;
72- return (
73- Math . floor ( referenceTime / WEEK_SECONDS ) * WEEK_SECONDS + INCENTIVE_OFFSET
74- ) ;
75- }
76- } ;
77-
78- /**
79- * Get the block number when the current epoch started by querying the most recent Mint event
80- */
81- const getEpochStartBlock = async ( currentBlock ) => {
82- try {
83- const mintTopic = ethers . utils . id ( 'Mint(uint256,uint256,uint256,uint256)' ) ;
84-
85- // Look back ~2 weeks and find the most recent Mint event
86- const fromBlock = currentBlock - 5000000 ;
87-
88- const logs = await sdk . api . util . getLogs ( {
89- target : ADDRESSES . BASE_V2_MINTER ,
90- topic : '' ,
91- toBlock : currentBlock ,
92- fromBlock : fromBlock > 0 ? fromBlock : 1 ,
93- keys : [ ] ,
94- chain : CHAIN ,
95- topics : [ mintTopic ] ,
96- } ) ;
97-
98- if ( logs . output && logs . output . length > 0 ) {
99- // Return the block number of the most recent Mint event
100- return logs . output [ logs . output . length - 1 ] . blockNumber ;
101- }
59+ const getIncentiveStartTime = async ( timestamp = null ) => {
60+ const referenceTime = timestamp || Math . floor ( Date . now ( ) / 1000 ) ;
10261
103- // Fallback: use ~1 week lookback
104- return currentBlock - 2400000 ;
105- } catch ( e ) {
106- return currentBlock - 2400000 ;
107- }
62+ return Math . trunc ( ( referenceTime - 43200 ) / 604800 ) * 604800 + 43200 ;
10863} ;
10964
11065/**
@@ -114,11 +69,21 @@ const getEpochContext = async (
11469 timestamp : number | null ,
11570 currentBlock : number
11671) : Promise < EpochContext > => {
117- const [ epochStartTime , epochStartBlock ] = await Promise . all ( [
118- getIncentiveStartTime ( timestamp , currentBlock ) ,
119- getEpochStartBlock ( currentBlock ) ,
120- ] ) ;
121- return { currentBlock, timestamp, epochStartTime, epochStartBlock } ;
72+ const epochStartTime = await getIncentiveStartTime ( timestamp ) ;
73+ const [ epochStartBlock ] = await utils . getBlocksByTime (
74+ [ epochStartTime ] ,
75+ CHAIN
76+ ) ;
77+
78+ const epochEndTime = epochStartTime + WEEK_SECONDS ;
79+
80+ return {
81+ currentBlock,
82+ timestamp,
83+ epochStartTime,
84+ epochEndTime,
85+ epochStartBlock,
86+ } ;
12287} ;
12388
12489/**
@@ -506,44 +471,29 @@ const getGaugeAllocation = async (gaugeAddress, block = null) => {
506471 * Get incentive data from QueueRewards events on FlywheelGaugeRewards emitted at epoch start
507472 */
508473const getIncentiveFromEvents = async (
509- gaugeAddress : string ,
474+ incentiveId : string ,
510475 epochContext : EpochContext
511476) => {
512477 try {
513- // QueueRewards event topic
514- const queueRewardsTopic = ethers . utils . id ( 'QueueRewards(address,uint256)' ) ;
515-
516- // Filter by gauge address
517- const gaugeAddressPadded = ethers . utils
518- . hexZeroPad ( gaugeAddress , 32 )
519- . toLowerCase ( ) ;
520-
521- const logs = await sdk . api . util . getLogs ( {
522- target : ADDRESSES . FLYWHEEL_GAUGE_REWARDS ,
523- topic : '' ,
524- toBlock : epochContext . currentBlock ,
525- fromBlock : epochContext . epochStartBlock ,
526- keys : [ ] ,
478+ const result = await sdk . api . abi . call ( {
479+ target : ADDRESSES . UNISWAP_V3_STAKER ,
480+ abi : 'function incentives(bytes32 incentiveId) external view returns (uint256 totalRewardUnclaimed, uint160 totalSecondsClaimedX128, uint96 numberOfStakes)' ,
481+ params : [ incentiveId ] ,
527482 chain : CHAIN ,
528- topics : [ queueRewardsTopic , gaugeAddressPadded ] ,
483+ block : epochContext . epochStartBlock ,
529484 } ) ;
530485
531- if ( ! logs . output || logs . output . length === 0 ) {
532- return null ;
533- }
534-
535- // Get most recent QueueRewards event for this gauge
536- const latestLog = logs . output [ logs . output . length - 1 ] ;
537-
538- // rewardAmount is in topics[2] (indexed parameter)
539- const rewardBigInt = BigInt ( latestLog . topics [ 2 ] ) ;
540- const reward = parseFloat (
541- ethers . utils . formatUnits ( rewardBigInt . toString ( ) , 18 )
486+ const totalRewardUnclaimed = BigInt (
487+ result . output . totalRewardUnclaimed || 0
542488 ) ;
543489
544490 // Use epoch timing from context
545491 const endTime = epochContext . epochStartTime + WEEK_SECONDS ;
546492
493+ const reward = parseFloat (
494+ ethers . utils . formatUnits ( totalRewardUnclaimed . toString ( ) , 18 )
495+ ) ;
496+
547497 return { startTime : epochContext . epochStartTime , endTime, reward } ;
548498 } catch ( e ) {
549499 console . error ( 'Error getting incentive from events:' , e . message ) ;
@@ -811,7 +761,8 @@ const getPools = async (timestamp = null) => {
811761
812762 // Fetch all prices
813763 const tokens = Array . from ( tokenSet ) ;
814- const prices = ( await utils . getPrices ( tokens , CHAIN , timestamp ) ) . pricesByAddress ;
764+ const prices = ( await utils . getPrices ( tokens , CHAIN , timestamp ) )
765+ . pricesByAddress ;
815766
816767 // Extract HERMES price
817768 const hermesPrice = prices [ ADDRESSES . HERMES . toLowerCase ( ) ] || 0 ;
@@ -838,7 +789,7 @@ const getPools = async (timestamp = null) => {
838789
839790 // Get incentive data from QueueRewards events
840791 const incentiveData = await getIncentiveFromEvents (
841- gaugeAddress ,
792+ incentiveId ,
842793 epochContext
843794 ) ;
844795
@@ -879,8 +830,8 @@ const getPools = async (timestamp = null) => {
879830 incentiveData . reward ,
880831 hermesPrice ,
881832 activeLiquidityUSD ,
882- incentiveData . startTime ,
883- incentiveData . endTime ,
833+ epochContext . epochStartTime ,
834+ epochContext . epochEndTime ,
884835 timestamp
885836 ) ;
886837 }
0 commit comments