@@ -1253,138 +1253,137 @@ describe("Envio Celo indexer handlers", () => {
12531253 // Self-heal: backfill referenceRateFeedID on subsequent events
12541254 // ---------------------------------------------------------------------------
12551255
1256- it ( "self-heals empty referenceRateFeedID on next Swap event" , async function ( ) {
1257- this . timeout ( 10_000 ) ;
1258-
1259- const POOL_ADDR = "0x00000000000000000000000000000000000000dd" ;
1260- const HEALED_FEED = "0xf47172ce00522cc7db02109634a92ce866a15fcc" ;
1261- const HEALED_EXPIRY = 3720n ;
1262- const CHAIN_ID = 42220 ;
1263-
1264- // 1. Deploy pool (referenceRateFeedID will be "" because no mock is set
1265- // for the RPC call during deployment — simulating the transient failure)
1266- let mockDb = MockDb . createMockDb ( ) ;
1267-
1268- const deployEvent = FPMMFactory . FPMMDeployed . createMockEvent ( {
1269- token0 : "0x0000000000000000000000000000000000000003" ,
1270- token1 : "0x0000000000000000000000000000000000000004" ,
1271- fpmmProxy : POOL_ADDR ,
1272- fpmmImplementation : "0x00000000000000000000000000000000000000bc" ,
1273- mockEventData : {
1274- chainId : CHAIN_ID ,
1275- logIndex : 10 ,
1276- srcAddress : "0x00000000000000000000000000000000000000cc" ,
1277- block : { number : 100 , timestamp : 1_700_000_000 } ,
1278- } ,
1256+ describe ( "self-heal referenceRateFeedID" , ( ) => {
1257+ afterEach ( ( ) => {
1258+ _clearMockRateFeedIDs ( ) ;
1259+ _clearMockReportExpiry ( ) ;
1260+ } ) ;
1261+
1262+ it ( "self-heals empty referenceRateFeedID on next Swap event" , async function ( ) {
1263+ this . timeout ( 10_000 ) ;
1264+
1265+ const POOL_ADDR = "0x00000000000000000000000000000000000000dd" ;
1266+ const HEALED_FEED = "0xf47172ce00522cc7db02109634a92ce866a15fcc" ;
1267+ const HEALED_EXPIRY = 3720n ;
1268+ const CHAIN_ID = 42220 ;
1269+
1270+ // 1. Deploy pool — mock null to explicitly simulate transient RPC failure
1271+ _setMockRateFeedID ( CHAIN_ID , POOL_ADDR , null ) ;
1272+ let mockDb = MockDb . createMockDb ( ) ;
1273+
1274+ const deployEvent = FPMMFactory . FPMMDeployed . createMockEvent ( {
1275+ token0 : "0x0000000000000000000000000000000000000003" ,
1276+ token1 : "0x0000000000000000000000000000000000000004" ,
1277+ fpmmProxy : POOL_ADDR ,
1278+ fpmmImplementation : "0x00000000000000000000000000000000000000bc" ,
1279+ mockEventData : {
1280+ chainId : CHAIN_ID ,
1281+ logIndex : 10 ,
1282+ srcAddress : "0x00000000000000000000000000000000000000cc" ,
1283+ block : { number : 100 , timestamp : 1_700_000_000 } ,
1284+ } ,
1285+ } ) ;
1286+ mockDb = await FPMMFactory . FPMMDeployed . processEvent ( {
1287+ event : deployEvent ,
1288+ mockDb,
1289+ } ) ;
1290+
1291+ // Verify the pool was created with empty referenceRateFeedID
1292+ const poolBefore = mockDb . entities . Pool . get ( POOL_ADDR ) as PoolEntity ;
1293+ assert . ok ( poolBefore , "Pool must exist after deploy" ) ;
1294+ assert . equal (
1295+ poolBefore . referenceRateFeedID ,
1296+ "" ,
1297+ "referenceRateFeedID should be empty after failed initial fetch" ,
1298+ ) ;
1299+ assert . equal (
1300+ poolBefore . oracleExpiry ,
1301+ 0n ,
1302+ "oracleExpiry should be 0 when referenceRateFeedID is empty" ,
1303+ ) ;
1304+
1305+ // 2. Set up mocks so the self-heal RPC calls succeed
1306+ _setMockRateFeedID ( CHAIN_ID , POOL_ADDR , HEALED_FEED ) ;
1307+ _setMockReportExpiry ( CHAIN_ID , HEALED_FEED , HEALED_EXPIRY ) ;
1308+
1309+ // 3. Process a Swap event — should trigger self-heal
1310+ const swapEvent = FPMM . Swap . createMockEvent ( {
1311+ sender : "0x0000000000000000000000000000000000000099" ,
1312+ to : "0x0000000000000000000000000000000000000098" ,
1313+ amount0In : 1000n ,
1314+ amount1In : 0n ,
1315+ amount0Out : 0n ,
1316+ amount1Out : 990n ,
1317+ mockEventData : {
1318+ chainId : CHAIN_ID ,
1319+ logIndex : 20 ,
1320+ srcAddress : POOL_ADDR ,
1321+ block : { number : 200 , timestamp : 1_700_001_000 } ,
1322+ } ,
1323+ } ) ;
1324+ mockDb = await FPMM . Swap . processEvent ( { event : swapEvent , mockDb } ) ;
1325+
1326+ // 4. Verify self-heal populated the fields
1327+ const poolAfter = mockDb . entities . Pool . get ( POOL_ADDR ) as PoolEntity ;
1328+ assert . ok ( poolAfter , "Pool must exist after Swap" ) ;
1329+ assert . equal (
1330+ poolAfter . referenceRateFeedID ,
1331+ HEALED_FEED ,
1332+ "referenceRateFeedID should be healed after Swap event" ,
1333+ ) ;
1334+ assert . equal (
1335+ poolAfter . oracleExpiry ,
1336+ HEALED_EXPIRY ,
1337+ "oracleExpiry should be healed after Swap event" ,
1338+ ) ;
1339+ } ) ;
1340+
1341+ it ( "does NOT self-heal when referenceRateFeedID is already populated" , async function ( ) {
1342+ this . timeout ( 10_000 ) ;
1343+
1344+ const POOL_ADDR = "0x00000000000000000000000000000000000000ee" ;
1345+ const EXISTING_FEED = "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ;
1346+ const CHAIN_ID = 42220 ;
1347+
1348+ // 1. Seed pool with an existing referenceRateFeedID
1349+ let mockDb = await seedPoolWithFeed ( MockDb . createMockDb ( ) , {
1350+ poolId : POOL_ADDR ,
1351+ feedId : EXISTING_FEED ,
1352+ oracleExpiry : 600n ,
1353+ } ) ;
1354+
1355+ // 2. Set up a different mock — should NOT be used because feed is already set
1356+ _setMockRateFeedID (
1357+ CHAIN_ID ,
1358+ POOL_ADDR ,
1359+ "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" ,
1360+ ) ;
1361+
1362+ // 3. Process a Swap event
1363+ const swapEvent = FPMM . Swap . createMockEvent ( {
1364+ sender : "0x0000000000000000000000000000000000000099" ,
1365+ to : "0x0000000000000000000000000000000000000098" ,
1366+ amount0In : 500n ,
1367+ amount1In : 0n ,
1368+ amount0Out : 0n ,
1369+ amount1Out : 495n ,
1370+ mockEventData : {
1371+ chainId : CHAIN_ID ,
1372+ logIndex : 30 ,
1373+ srcAddress : POOL_ADDR ,
1374+ block : { number : 400 , timestamp : 1_700_002_000 } ,
1375+ } ,
1376+ } ) ;
1377+ mockDb = await FPMM . Swap . processEvent ( { event : swapEvent , mockDb } ) ;
1378+
1379+ // 4. Verify feed was NOT changed
1380+ const pool = mockDb . entities . Pool . get ( POOL_ADDR ) as PoolEntity ;
1381+ assert . ok ( pool , "Pool must exist after Swap" ) ;
1382+ assert . equal (
1383+ pool . referenceRateFeedID ,
1384+ EXISTING_FEED ,
1385+ "referenceRateFeedID should remain unchanged when already populated" ,
1386+ ) ;
12791387 } ) ;
1280- mockDb = await FPMMFactory . FPMMDeployed . processEvent ( {
1281- event : deployEvent ,
1282- mockDb,
1283- } ) ;
1284-
1285- // Verify the pool was created with empty referenceRateFeedID
1286- const poolBefore = mockDb . entities . Pool . get ( POOL_ADDR ) as PoolEntity ;
1287- assert . ok ( poolBefore , "Pool must exist after deploy" ) ;
1288- assert . equal (
1289- poolBefore . referenceRateFeedID ,
1290- "" ,
1291- "referenceRateFeedID should be empty after failed initial fetch" ,
1292- ) ;
1293- assert . equal (
1294- poolBefore . oracleExpiry ,
1295- 0n ,
1296- "oracleExpiry should be 0 when referenceRateFeedID is empty" ,
1297- ) ;
1298-
1299- // 2. Set up mocks so the self-heal RPC calls succeed
1300- _setMockRateFeedID ( CHAIN_ID , POOL_ADDR , HEALED_FEED ) ;
1301- _setMockReportExpiry ( CHAIN_ID , HEALED_FEED , HEALED_EXPIRY ) ;
1302-
1303- // 3. Process a Swap event — should trigger self-heal
1304- const swapEvent = FPMM . Swap . createMockEvent ( {
1305- sender : "0x0000000000000000000000000000000000000099" ,
1306- to : "0x0000000000000000000000000000000000000098" ,
1307- amount0In : 1000n ,
1308- amount1In : 0n ,
1309- amount0Out : 0n ,
1310- amount1Out : 990n ,
1311- mockEventData : {
1312- chainId : CHAIN_ID ,
1313- logIndex : 20 ,
1314- srcAddress : POOL_ADDR ,
1315- block : { number : 200 , timestamp : 1_700_001_000 } ,
1316- } ,
1317- } ) ;
1318- mockDb = await FPMM . Swap . processEvent ( { event : swapEvent , mockDb } ) ;
1319-
1320- // 4. Verify self-heal populated the fields
1321- const poolAfter = mockDb . entities . Pool . get ( POOL_ADDR ) as PoolEntity ;
1322- assert . ok ( poolAfter , "Pool must exist after Swap" ) ;
1323- assert . equal (
1324- poolAfter . referenceRateFeedID ,
1325- HEALED_FEED ,
1326- "referenceRateFeedID should be healed after Swap event" ,
1327- ) ;
1328- assert . equal (
1329- poolAfter . oracleExpiry ,
1330- HEALED_EXPIRY ,
1331- "oracleExpiry should be healed after Swap event" ,
1332- ) ;
1333-
1334- // Cleanup
1335- _clearMockRateFeedIDs ( ) ;
1336- _clearMockReportExpiry ( ) ;
1337- } ) ;
1338-
1339- it ( "does NOT self-heal when referenceRateFeedID is already populated" , async function ( ) {
1340- this . timeout ( 10_000 ) ;
1341-
1342- const POOL_ADDR = "0x00000000000000000000000000000000000000ee" ;
1343- const EXISTING_FEED = "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ;
1344- const CHAIN_ID = 42220 ;
1345-
1346- // 1. Seed pool with an existing referenceRateFeedID
1347- let mockDb = await seedPoolWithFeed ( MockDb . createMockDb ( ) , {
1348- poolId : POOL_ADDR ,
1349- feedId : EXISTING_FEED ,
1350- oracleExpiry : 600n ,
1351- } ) ;
1352-
1353- // 2. Set up a different mock — should NOT be used because feed is already set
1354- _setMockRateFeedID (
1355- CHAIN_ID ,
1356- POOL_ADDR ,
1357- "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" ,
1358- ) ;
1359-
1360- // 3. Process a Swap event
1361- const swapEvent = FPMM . Swap . createMockEvent ( {
1362- sender : "0x0000000000000000000000000000000000000099" ,
1363- to : "0x0000000000000000000000000000000000000098" ,
1364- amount0In : 500n ,
1365- amount1In : 0n ,
1366- amount0Out : 0n ,
1367- amount1Out : 495n ,
1368- mockEventData : {
1369- chainId : CHAIN_ID ,
1370- logIndex : 30 ,
1371- srcAddress : POOL_ADDR ,
1372- block : { number : 400 , timestamp : 1_700_002_000 } ,
1373- } ,
1374- } ) ;
1375- mockDb = await FPMM . Swap . processEvent ( { event : swapEvent , mockDb } ) ;
1376-
1377- // 4. Verify feed was NOT changed
1378- const pool = mockDb . entities . Pool . get ( POOL_ADDR ) as PoolEntity ;
1379- assert . ok ( pool , "Pool must exist after Swap" ) ;
1380- assert . equal (
1381- pool . referenceRateFeedID ,
1382- EXISTING_FEED ,
1383- "referenceRateFeedID should remain unchanged when already populated" ,
1384- ) ;
1385-
1386- // Cleanup
1387- _clearMockRateFeedIDs ( ) ;
1388- _clearMockReportExpiry ( ) ;
13891388 } ) ;
13901389} ) ;
0 commit comments