11const sdk = require ( '@defillama/sdk' ) ;
2+ const axios = require ( 'axios' ) ;
23const utils = require ( '../utils' ) ;
34
45const API_URL = 'https://yield.accountable.capital/api/loan' ;
6+ const MERKL_API_URL = 'https://api.merkl.xyz/v4/opportunities?explorerAddress=' ;
57const chainIdToName = { 143 : 'monad' } ;
68const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' ;
79
@@ -11,7 +13,7 @@ const abis = {
1113} ;
1214
1315const basisPointsToPercent = ( value ) => Number ( value ) / 1e4 ;
14- const formatAmountWithDecimlas = ( value , decimals ) => value / 10 ** decimals ;
16+ const formatAmount = ( value , decimals = 18 ) => ( value == null ? null : Number ( value ) / 10 ** decimals ) ;
1517
1618const fetchVaultsByLoanIds = async ( loanIds ) => {
1719 const results = await Promise . allSettled (
@@ -80,17 +82,45 @@ const getVaultStats = async(vaults, chain = 'monad') => {
8082
8183 const totalAssets = totalAssetsRes . output . map ( ( o ) => o . output ) ;
8284 const liquidity = liquidityRes . output . map ( ( o ) => o . output ) ;
83- console . log ( totalAssets , liquidity ) ;
8485 return vaults . reduce ( ( acc , address , i ) => {
8586 acc [ address ] = {
8687 totalSupplied : supplies [ i ] ,
87- totalBorrowed : totalAssets [ i ] - liquidity [ i ] ,
88+ totalBorrowed : Number ( totalAssets [ i ] ) - Number ( liquidity [ i ] || 0 ) ,
8889 tvl : liquidity [ i ] ,
8990 } ;
9091 return acc ;
9192 } , { } ) ;
9293} ;
9394
95+ const fetchMerklRewards = async ( vaultAddress ) => {
96+ try {
97+ const { data } = await axios . get ( `${ MERKL_API_URL } ${ vaultAddress } ` ) ;
98+ const opp =
99+ Array . isArray ( data ) &&
100+ ( data . find ( ( item ) => item ?. explorerAddress ?. toLowerCase ( ) === vaultAddress . toLowerCase ( ) ) || data [ 0 ] ) ;
101+ if ( ! opp ) return [ ] ;
102+ return (
103+ opp . rewardsRecord ?. breakdowns
104+ ?. map ( ( b ) => b ?. token ?. address ?. toLowerCase ( ) )
105+ . filter ( Boolean ) || [ ]
106+ ) ;
107+ } catch ( e ) {
108+ return [ ] ;
109+ }
110+ } ;
111+
112+ const fetchBreakdowns = async ( loanIds ) => {
113+ const results = await Promise . allSettled (
114+ loanIds . map ( ( id ) => utils . getData ( `${ API_URL } /${ id } /apy/breakdown` ) )
115+ ) ;
116+
117+ return results . reduce ( ( acc , res , idx ) => {
118+ if ( res . status !== 'fulfilled' ) return acc ;
119+ acc [ loanIds [ idx ] ] = res . value || { } ;
120+ return acc ;
121+ } , { } ) ;
122+ } ;
123+
94124const apy = async ( ) => {
95125 const { items } = await utils . getData ( API_URL ) ;
96126 const activeLoans = items . filter ( ( item ) => item . loan_state === 3 ) ;
@@ -99,27 +129,46 @@ const apy = async() => {
99129 const loanVaultMap = await fetchVaultsByLoanIds ( loanIds ) ;
100130 const vaultAddresses = Object . values ( loanVaultMap ) ;
101131 const vaultStats = await getVaultStats ( vaultAddresses ) ;
102-
103- return activeLoans . map ( ( item ) => {
104- const chainName = chainIdToName [ item . chain_id ] || 'unknown' ;
105- const vaultAddress = loanVaultMap [ item . id ] ;
106- const stats = vaultAddress ? vaultStats [ vaultAddress ] || { } : { } ;
107-
108- return {
109- pool : `${ item . loan_address } -${ chainName } ` . toLowerCase ( ) ,
110- chain : chainName ,
111- project : 'accountable' ,
112- symbol : utils . formatSymbol ( item . asset_symbol ) ,
113- tvlUsd : formatAmountWithDecimlas ( stats . tvl , 6 ) ,
114- apyBase : basisPointsToPercent ( item . net_apy ) ,
115- url : `https://yield.accountable.capital/vaults/${ item . loan_address } ` ,
116- totalSupplyUsd : formatAmountWithDecimlas ( stats . totalSupplied , 6 ) ,
117- totalBorrowUsd : formatAmountWithDecimlas ( stats . totalBorrowed , 6 ) ,
118- } ;
119- } ) ;
132+ const breakdowns = await fetchBreakdowns ( loanIds ) ;
133+
134+ return Promise . all (
135+ activeLoans . map ( async ( item ) => {
136+ const chainName = chainIdToName [ item . chain_id ] || 'unknown' ;
137+ const vaultAddress = loanVaultMap [ item . id ] ;
138+ const stats = vaultAddress ? vaultStats [ vaultAddress ] || { } : { } ;
139+ const pointBoosts = item ?. all_points_apy_boost ?. boosts_by_points || [ ] ;
140+ const pointRewardApy = pointBoosts . reduce ( ( sum , b ) => sum + Number ( b ?. apy_boost_percent || 0 ) , 0 ) ;
141+ const pointRewardTokens = pointBoosts . map ( ( b ) => b ?. point_name ) . filter ( Boolean ) ;
142+
143+ const breakdown = breakdowns [ item . id ] || { } ;
144+ const merklApy = breakdown ?. merkle_apy ?? 0 ;
145+ const nativeApy = breakdown ?. native_apy ?? basisPointsToPercent ( item . apy ) ;
146+ const perfFee = breakdown ?. performance_fee ?? 0 ;
147+
148+ const totalApyReward = ( merklApy ?? 0 ) + pointRewardApy || null ;
149+ const merklTokens = vaultAddress ? await fetchMerklRewards ( vaultAddress ) : [ ] ;
150+ const combinedRewardTokens = Array . from (
151+ new Set ( [ ...( merklTokens || [ ] ) , ...pointRewardTokens ] )
152+ ) ;
153+
154+ return {
155+ pool : `${ item . loan_address } -${ chainName } ` . toLowerCase ( ) ,
156+ chain : utils . formatChain ( chainName ) ,
157+ project : 'accountable' ,
158+ symbol : utils . formatSymbol ( item . asset_symbol ) ,
159+ tvlUsd : formatAmount ( stats . tvl , 6 ) ,
160+ apyBase : nativeApy + perfFee ,
161+ apyReward : totalApyReward ,
162+ rewardTokens : combinedRewardTokens ,
163+ url : `https://yield.accountable.capital/vaults/${ item . loan_address } ` ,
164+ totalSupplyUsd : formatAmount ( stats . totalSupplied , 6 ) ,
165+ totalBorrowUsd : formatAmount ( stats . totalBorrowed , 6 ) ,
166+ } ;
167+ } )
168+ ) ;
120169} ;
121170
122171module . exports = {
123172 timetravel : false ,
124173 apy,
125- } ;
174+ } ;
0 commit comments