Skip to content

Commit 2c4e485

Browse files
authored
Merge pull request #2210 from NablaFinance/update-nablaFinance-hyperEvmAndMonad
Add yield support for Nabla Finance deployments on HyperEVM and Monad
2 parents 6dccbc1 + 0e7c720 commit 2c4e485

File tree

1 file changed

+117
-4
lines changed

1 file changed

+117
-4
lines changed

src/adaptors/nabla-finance/index.js

Lines changed: 117 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ const graphUrls = {
99
base: 'https://subgraph.satsuma-prod.com/9b84d9926bf3/nabla-finance--3958960/nabla-mainnetAlpha-base/api',
1010
berachain:
1111
'https://subgraph.satsuma-prod.com/9b84d9926bf3/nabla-finance--3958960/nabla-mainnetAlpha-berachain-public/api',
12+
hyperliquid:
13+
'https://api.goldsky.com/api/public/project_cm7aautkjfpbg01v47kya5470/subgraphs/nabla-mainnetAlpha-hyperliquid/v0.0.3/gn',
14+
};
15+
16+
const nablaIndexerUrls = {
17+
monad:
18+
'https://indexer.nabla.fi/bsps/0x11B06EF8Adc5ea73841023CB39Be614f471213cc',
1219
};
1320

1421
const query = gql`
@@ -32,7 +39,96 @@ const apr7dToApy = (apr) => {
3239
return (1 + aprDay) ** 365 - 1;
3340
};
3441

35-
const poolsFunction = async (chain) => {
42+
// Process Nabla indexer response
43+
const getNablaIndexerPoolsMetrics = async (chain) => {
44+
try {
45+
const response = await superagent.get(nablaIndexerUrls[chain]);
46+
const data = response.body;
47+
48+
if (!data.bsps || data.bsps.length === 0) {
49+
console.log(`No BSPs found for chain: ${chain}`);
50+
return [];
51+
}
52+
53+
const allPools = [];
54+
55+
for (const bsp of data.bsps) {
56+
const coveredPools = bsp.coveredSwapPools || [];
57+
58+
if (coveredPools.length === 0) continue;
59+
60+
// Collect all unique token addresses
61+
const tokens = [...new Set(coveredPools.map((pool) => pool.asset))];
62+
63+
const priceKeys = tokens.map((address) => getPriceKey(address, chain));
64+
65+
let usdPrices = {};
66+
try {
67+
const priceResponse = await superagent.get(
68+
`https://coins.llama.fi/prices/current/${priceKeys
69+
.join(',')
70+
.toLowerCase()}`
71+
);
72+
usdPrices = priceResponse.body.coins || {};
73+
} catch (err) {
74+
console.error(`Failed fetching prices for chain ${chain}:`, err);
75+
continue;
76+
}
77+
78+
for (const pool of coveredPools) {
79+
const {
80+
address: poolAddress,
81+
asset: tokenAddress,
82+
asset_symbol,
83+
asset_decimals,
84+
total_liabilities,
85+
weekly_apr,
86+
} = pool;
87+
88+
const key = getPriceKey(tokenAddress, chain).toLowerCase();
89+
const priceData = usdPrices[key];
90+
91+
if (!priceData) {
92+
console.log(`No price data found for token: ${key}`);
93+
continue;
94+
}
95+
96+
const { price } = priceData;
97+
const decimals = asset_decimals || 18;
98+
99+
// Calculate TVL from total_liabilities
100+
const tvlNormalized = BigNumber(total_liabilities || 0).div(
101+
10 ** decimals
102+
);
103+
const tvlUsd = tvlNormalized.times(price).toNumber();
104+
105+
// Convert weekly APR to APY (weekly_apr is already in %)
106+
const aprDecimal = Number(weekly_apr || 0) / 100;
107+
const apyBase = apr7dToApy(aprDecimal) * 100;
108+
109+
allPools.push({
110+
pool: `${poolAddress}-${chain}`,
111+
chain: utils.formatChain(chain),
112+
project: 'nabla-finance',
113+
symbol: utils.formatSymbol(asset_symbol),
114+
underlyingTokens: [tokenAddress],
115+
tvlUsd: tvlUsd,
116+
apyBase: apyBase,
117+
});
118+
}
119+
}
120+
121+
return allPools;
122+
} catch (error) {
123+
console.error(
124+
`Error fetching pools from Monad indexer for chain ${chain}:`,
125+
error
126+
);
127+
return [];
128+
}
129+
};
130+
131+
const getGraphPoolsMetrics = async (chain) => {
36132
try {
37133
const swapPools = (await request(graphUrls[chain], query)).swapPools;
38134

@@ -97,15 +193,32 @@ const poolsFunction = async (chain) => {
97193
};
98194

99195
const poolsOnAllChains = async () => {
100-
const chains = Object.keys(graphUrls);
196+
const graphChains = Object.keys(graphUrls);
197+
const nablaIndexerChains = Object.keys(nablaIndexerUrls);
101198

102-
const allPoolsPromises = chains.map((chain) =>
103-
poolsFunction(chain).catch((error) => {
199+
// Fetch from GraphQL subgraphs
200+
const graphPoolsPromises = graphChains.map((chain) =>
201+
getGraphPoolsMetrics(chain).catch((error) => {
104202
console.error(`Failed to fetch pools for chain ${chain}:`, error);
105203
return [];
106204
})
107205
);
108206

207+
// Fetch from Nabla indexer
208+
const nablaIndexerPoolsPromises = nablaIndexerChains.map((chain) =>
209+
getNablaIndexerPoolsMetrics(chain).catch((error) => {
210+
console.error(
211+
`Failed to fetch pools from indexer for chain ${chain}:`,
212+
error
213+
);
214+
return [];
215+
})
216+
);
217+
218+
const allPoolsPromises = [
219+
...graphPoolsPromises,
220+
...nablaIndexerPoolsPromises,
221+
];
109222
const allPools = await Promise.all(allPoolsPromises);
110223
return allPools.flat();
111224
};

0 commit comments

Comments
 (0)