@@ -238,6 +238,67 @@ async function calculateAPRFromRewards(poolAddress, poolTVLUsd, chain) {
238238 }
239239}
240240
241+ /** USD price of 1 pegged token using this market's minter + collateral feed. */
242+ async function resolveMarketPeggedPriceUsd (
243+ chain ,
244+ market ,
245+ peggedTokenSymbol ,
246+ defaultFeedKey ,
247+ cache = { }
248+ ) {
249+ const feedKey = market . collateralPriceFeed || defaultFeedKey ;
250+ const cacheKey = `${ market . minterAddress || 'none' } :${ feedKey } ` ;
251+ if ( cache [ cacheKey ] !== undefined ) {
252+ return cache [ cacheKey ] ;
253+ }
254+
255+ let peggedTokenPriceInUnderlying = 0 ;
256+ if ( market . minterAddress ) {
257+ try {
258+ const minterPriceResult = await sdk . api . abi . call ( {
259+ target : market . minterAddress ,
260+ abi : MINTER_ABI . find ( ( m ) => m . name === 'peggedTokenPrice' ) ,
261+ chain,
262+ } ) ;
263+ if ( minterPriceResult ?. output ) {
264+ peggedTokenPriceInUnderlying = Number ( minterPriceResult . output ) / 1e18 ;
265+ }
266+ } catch ( error ) {
267+ // fall through to default peg ratio
268+ }
269+ }
270+
271+ if ( peggedTokenPriceInUnderlying === 0 ) {
272+ peggedTokenPriceInUnderlying = 1 ;
273+ } else if ( market . marketLabel ) {
274+ console . log (
275+ ` [${ chain } ] ${ market . marketLabel } peggedTokenPrice: ${ peggedTokenPriceInUnderlying . toFixed ( 6 ) } ${ UNDERLYING_ASSET_DISPLAY [ peggedTokenSymbol ] || 'collateral units' } `
276+ ) ;
277+ }
278+
279+ let underlyingAssetPriceUSD = 0 ;
280+ try {
281+ underlyingAssetPriceUSD = await getCollateralUsdPrice ( chain , feedKey ) ;
282+ if ( underlyingAssetPriceUSD > 0 && market . marketLabel ) {
283+ console . log (
284+ ` [${ chain } ] ${ market . marketLabel } ${ feedKey } : $${ underlyingAssetPriceUSD . toLocaleString ( undefined , { minimumFractionDigits : 2 , maximumFractionDigits : 2 } ) } `
285+ ) ;
286+ }
287+ } catch ( error ) {
288+ console . log ( ` [${ chain } ] Failed to get ${ feedKey } price:` , error . message ) ;
289+ }
290+
291+ const peggedTokenPriceUSD = peggedTokenPriceInUnderlying * underlyingAssetPriceUSD ;
292+ if ( peggedTokenPriceUSD > 0 && market . marketLabel ) {
293+ console . log (
294+ ` [${ chain } ] ${ market . marketLabel } ${ peggedTokenSymbol } price: $${ peggedTokenPriceUSD . toLocaleString ( undefined , { minimumFractionDigits : 2 , maximumFractionDigits : 2 } ) } `
295+ ) ;
296+ }
297+
298+ cache [ cacheKey ] = peggedTokenPriceUSD ;
299+ return peggedTokenPriceUSD ;
300+ }
301+
241302async function fetchPoolsFromChain ( ) {
242303 const marketsByChainToken = { } ;
243304 for ( const market of activeMarkets ) {
@@ -258,8 +319,6 @@ async function fetchPoolsFromChain() {
258319 let totalTVL = 0 ;
259320
260321 try {
261- let peggedTokenPriceInUnderlying = 0 ;
262- let underlyingAssetPriceUSD = 0 ;
263322 let decimals = 18 ;
264323
265324 const defaultFeedKey = TOKEN_CHAINLINK_FEED_MAP [ peggedTokenSymbol ] ;
@@ -269,84 +328,6 @@ async function fetchPoolsFromChain() {
269328 ) ;
270329 }
271330
272- let pricingMarket = tokenMarkets . find (
273- ( m ) => m . minterAddress && m . collateralPriceFeed
274- ) ;
275-
276- if ( pricingMarket ) {
277- try {
278- const minterPriceResult = await sdk . api . abi . call ( {
279- target : pricingMarket . minterAddress ,
280- abi : MINTER_ABI . find ( ( m ) => m . name === 'peggedTokenPrice' ) ,
281- chain,
282- } ) ;
283- if ( minterPriceResult ?. output ) {
284- peggedTokenPriceInUnderlying = Number ( minterPriceResult . output ) / 1e18 ;
285- console . log (
286- ` [${ chain } ] peggedTokenPrice from ${ pricingMarket . marketLabel || 'market' } minter: ${ peggedTokenPriceInUnderlying . toFixed ( 6 ) } ${ UNDERLYING_ASSET_DISPLAY [ peggedTokenSymbol ] || 'collateral units' } `
287- ) ;
288- }
289- } catch ( error ) {
290- pricingMarket = null ;
291- }
292- }
293-
294- if ( peggedTokenPriceInUnderlying === 0 ) {
295- const hasAnyFeedMarket = tokenMarkets . some ( ( m ) => m . collateralPriceFeed ) ;
296- for ( const market of tokenMarkets ) {
297- if ( ! market . minterAddress || ( hasAnyFeedMarket && ! market . collateralPriceFeed ) ) {
298- continue ;
299- }
300- try {
301- const minterPriceResult = await sdk . api . abi . call ( {
302- target : market . minterAddress ,
303- abi : MINTER_ABI . find ( ( m ) => m . name === 'peggedTokenPrice' ) ,
304- chain,
305- } ) ;
306- if ( minterPriceResult ?. output ) {
307- peggedTokenPriceInUnderlying = Number ( minterPriceResult . output ) / 1e18 ;
308- pricingMarket = market ;
309- console . log (
310- ` [${ chain } ] peggedTokenPrice from ${ market . marketLabel || 'market' } minter: ${ peggedTokenPriceInUnderlying . toFixed ( 6 ) } ${ UNDERLYING_ASSET_DISPLAY [ peggedTokenSymbol ] || 'collateral units' } `
311- ) ;
312- break ;
313- }
314- } catch ( error ) {
315- continue ;
316- }
317- }
318- }
319-
320- if ( peggedTokenPriceInUnderlying === 0 ) {
321- peggedTokenPriceInUnderlying = 1 ;
322- console . log (
323- ` [${ chain } ] Using default peg ratio: 1.0 ${ UNDERLYING_ASSET_DISPLAY [ peggedTokenSymbol ] || 'UNDERLYING' } `
324- ) ;
325- }
326-
327- const priceFeedKey =
328- pricingMarket ?. collateralPriceFeed ||
329- tokenMarkets . find ( ( m ) => m . collateralPriceFeed ) ?. collateralPriceFeed ||
330- defaultFeedKey ;
331-
332- try {
333- underlyingAssetPriceUSD = await getCollateralUsdPrice ( chain , priceFeedKey ) ;
334- if ( underlyingAssetPriceUSD > 0 ) {
335- console . log (
336- ` [${ chain } ] ${ priceFeedKey } price in USD: $${ underlyingAssetPriceUSD . toLocaleString ( undefined , { minimumFractionDigits : 2 , maximumFractionDigits : 2 } ) } `
337- ) ;
338- }
339- } catch ( error ) {
340- console . log ( ` [${ chain } ] Failed to get ${ priceFeedKey } price:` , error . message ) ;
341- }
342-
343- const peggedTokenPriceUSD = peggedTokenPriceInUnderlying * underlyingAssetPriceUSD ;
344- if ( peggedTokenPriceUSD > 0 ) {
345- console . log (
346- ` [${ chain } ] Final ${ peggedTokenSymbol } price: $${ peggedTokenPriceUSD . toLocaleString ( undefined , { minimumFractionDigits : 2 , maximumFractionDigits : 2 } ) } `
347- ) ;
348- }
349-
350331 try {
351332 const decimalsResult = await sdk . api . abi . call ( {
352333 target : peggedTokenAddress ,
@@ -358,6 +339,8 @@ async function fetchPoolsFromChain() {
358339 console . log ( ` [${ chain } ] Decimals lookup failed, using default 18` ) ;
359340 }
360341
342+ const priceCache = { } ;
343+
361344 for ( const market of tokenMarkets ) {
362345 const { collateralPoolAddress, sailPoolAddress, marketLabel } = market ;
363346
@@ -366,6 +349,14 @@ async function fetchPoolsFromChain() {
366349 ` [${ chain } ] ${ peggedTokenSymbol } ${ marketLabel || '' } - Collateral: ${ collateralPoolAddress } , Sail: ${ sailPoolAddress } `
367350 ) ;
368351
352+ const peggedTokenPriceUSD = await resolveMarketPeggedPriceUsd (
353+ chain ,
354+ market ,
355+ peggedTokenSymbol ,
356+ defaultFeedKey ,
357+ priceCache
358+ ) ;
359+
369360 const [ collateralTVLResult , sailTVLResult ] = await Promise . all ( [
370361 sdk . api . abi . call ( {
371362 target : collateralPoolAddress ,
0 commit comments