@@ -291,17 +291,19 @@ export interface SubnetEarnings {
291291}
292292
293293/**
294- * All-time Morpheus subnet earnings: every USDC transfer from the final split
295- * to the treasury. The paged inflows feed above is a window and cannot sum
296- * honestly; this asks Alchemy for exactly the split→treasury lane and walks
297- * every page (the claim history is tiny). `null` = could not determine —
298- * the KPI card renders a dash, never a fabricated 0.
294+ * All-time Morpheus subnet earnings. Splits pay through the warehouse (see the
295+ * SPLITS_WAREHOUSE note above — the split address is never the `from`), so
296+ * this walks every warehouse→treasury USDC transfer and keeps the ones whose
297+ * transaction the subnet's final split emitted in, the same attribution rule
298+ * the inflows ledger uses. The paged inflows feed above is a window and cannot
299+ * sum honestly; this lane's full history is tiny, and the per-tx receipts are
300+ * immutable and day-cached. `null` = could not determine — the KPI card
301+ * renders a dash, never a fabricated 0.
299302 */
300303export const loadSubnetEarnings = cache ( async ( ) : Promise < SubnetEarnings | null > => {
301304 if ( ! ALCHEMY_KEY ) return null ;
302305 try {
303- let totalUsdc = 0 ;
304- let claimCount = 0 ;
306+ const transfers : Array < { value : number ; hash : string } > = [ ] ;
305307 let pageKey : string | undefined ;
306308 do {
307309 const res = await fetch ( `https://base-mainnet.g.alchemy.com/v2/${ ALCHEMY_KEY } ` , {
@@ -313,7 +315,7 @@ export const loadSubnetEarnings = cache(async (): Promise<SubnetEarnings | null>
313315 method : "alchemy_getAssetTransfers" ,
314316 params : [
315317 {
316- fromAddress : SUBNET_FINAL_SPLIT ,
318+ fromAddress : SPLITS_WAREHOUSE ,
317319 toAddress : DAO_ADDRESSES . treasury ,
318320 contractAddresses : [ USDC ] ,
319321 category : [ "erc20" ] ,
@@ -327,16 +329,27 @@ export const loadSubnetEarnings = cache(async (): Promise<SubnetEarnings | null>
327329 } ) ;
328330 if ( ! res . ok ) throw new Error ( `Alchemy ${ res . status } ` ) ;
329331 const json = ( await res . json ( ) ) as {
330- result ?: { transfers ?: Array < { value : number | null } > ; pageKey ?: string } ;
332+ result ?: {
333+ transfers ?: Array < { value : number | null ; hash ?: string } > ;
334+ pageKey ?: string ;
335+ } ;
331336 error ?: { message ?: string } ;
332337 } ;
333338 if ( json . error ) throw new Error ( json . error . message ?? "Alchemy error" ) ;
334339 for ( const t of json . result ?. transfers ?? [ ] ) {
335- totalUsdc += t . value ?? 0 ;
336- claimCount += 1 ;
340+ if ( t . hash ) transfers . push ( { value : t . value ?? 0 , hash : t . hash } ) ;
337341 }
338342 pageKey = json . result ?. pageKey ;
339343 } while ( pageKey ) ;
344+
345+ const sources = await Promise . all ( transfers . map ( ( t ) => splitSourceForTx ( t . hash ) ) ) ;
346+ let totalUsdc = 0 ;
347+ let claimCount = 0 ;
348+ for ( let i = 0 ; i < transfers . length ; i += 1 ) {
349+ if ( sources [ i ] !== "subnet" ) continue ;
350+ totalUsdc += transfers [ i ] . value ;
351+ claimCount += 1 ;
352+ }
340353 return { totalUsdc, claimCount } ;
341354 } catch {
342355 return null ;
0 commit comments