@@ -181,23 +181,31 @@ async function morBackersByRider(ethUsd: number): Promise<Record<string, OrbitBa
181181 { asset : "usdc" , pool : MORPHEUS_POOLS . usdc . pool , decimals : 6 } ,
182182 ] ;
183183 const pairs = escPools . flatMap ( ( p ) => idWallets . map ( ( [ id , ref ] ) => ( { ...p , id, ref } ) ) ) ;
184- const rows = await Promise . all (
185- pairs . map ( async ( { asset, pool, decimals, id, ref } ) => {
186- const logs = await etherscanReferred ( pool , ref , ETHERSCAN_KEY as string ) ;
187- // Sum the staked amount straight from the events (datacenter-safe, no
188- // extra eth_call that would blow the free rate limit). Withdrawals aren't
189- // subtracted, but the 7-day lock makes that rare.
190- const byUser = new Map < string , bigint > ( ) ;
191- for ( const l of logs ) byUser . set ( l . user . toLowerCase ( ) , ( byUser . get ( l . user . toLowerCase ( ) ) ?? BigInt ( 0 ) ) + l . amount ) ;
192- const out : Array < { id : RiderId ; backer : OrbitBacker } > = [ ] ;
193- for ( const [ userLc , amt ] of byUser ) {
194- const tokens = Number ( formatUnits ( amt , decimals ) ) ;
195- const usd = asset === "steth" ? tokens * ethUsd : tokens ;
196- if ( usd > 0 ) out . push ( { id, backer : { address : getAddress ( userLc ) , amount : usd , kind : "mor" , asset } } ) ;
197- }
198- return out ;
199- } ) ,
200- ) ;
184+ const rows : Array < { id : RiderId ; backer : OrbitBacker } > [ ] = [ ] ;
185+ // Etherscan's free tier caps at ~5 req/s — run the calls in small waves with
186+ // a gap so they don't get rate-limited into empty results. The route caches
187+ // the whole graph for 60s, so this runs at most once a minute.
188+ const BATCH = 4 ;
189+ for ( let i = 0 ; i < pairs . length ; i += BATCH ) {
190+ const wave = await Promise . all (
191+ pairs . slice ( i , i + BATCH ) . map ( async ( { asset, pool, decimals, id, ref } ) => {
192+ const logs = await etherscanReferred ( pool , ref , ETHERSCAN_KEY as string ) ;
193+ // Staked amount straight from the events (no eth_call). Withdrawals
194+ // aren't subtracted, but the 7-day lock makes that rare.
195+ const byUser = new Map < string , bigint > ( ) ;
196+ for ( const l of logs ) byUser . set ( l . user . toLowerCase ( ) , ( byUser . get ( l . user . toLowerCase ( ) ) ?? BigInt ( 0 ) ) + l . amount ) ;
197+ const out : Array < { id : RiderId ; backer : OrbitBacker } > = [ ] ;
198+ for ( const [ userLc , amt ] of byUser ) {
199+ const tokens = Number ( formatUnits ( amt , decimals ) ) ;
200+ const usd = asset === "steth" ? tokens * ethUsd : tokens ;
201+ if ( usd > 0 ) out . push ( { id, backer : { address : getAddress ( userLc ) , amount : usd , kind : "mor" , asset } } ) ;
202+ }
203+ return out ;
204+ } ) ,
205+ ) ;
206+ rows . push ( ...wave ) ;
207+ if ( i + BATCH < pairs . length ) await sleep ( 320 ) ;
208+ }
201209 for ( const { id, backer } of rows . flat ( ) ) ( byRider [ id ] ||= [ ] ) . push ( backer ) ;
202210 return byRider ;
203211 }
0 commit comments