Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update nimbora pools list #184

Merged
merged 11 commits into from
Dec 9, 2024
4 changes: 4 additions & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ const nextConfig = {
source: '/myswap/:path*',
destination: 'https://myswap-cl-charts.s3.amazonaws.com/:path*',
},
{
source: '/nimbora/:path*',
destination: 'https://stats.nimbora.io/:path*',
},
];
},
async redirects() {
Expand Down
5 changes: 5 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ const CONSTANTS = {
ZKLEND: {
BASE_APR_API: '/zklend/api/pools',
},
NIMBORA: {
DEX_APR_API: '/nimbora/yield-dex/strategies',
AGGREGATOR_APR_API: '/nimbora/aggregator/strategies',
LIQUIDITY_APR_API: '/nimbora/liquity/strategies',
},
JEDI: {
BASE_API: '/jediswap/graphql',
},
Expand Down
45 changes: 0 additions & 45 deletions src/store/nimbora.store.ts

This file was deleted.

174 changes: 174 additions & 0 deletions src/store/nimboraaggregator.store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import CONSTANTS from '@/constants';
import { Category, PoolType } from './pools';
import { atom } from 'jotai';
import { PoolInfo, ProtocolAtoms } from './pools';
import { atomWithQuery } from 'jotai-tanstack-query';
import { StrategyLiveStatus } from '@/strategies/IStrategy';
import fetchWithRetry from '@/utils/fetchWithRetry';
import { IDapp } from './IDapp.store';

interface NimboraAggregatorDoc {
name: string;
symbol: string;
protocols: string[];
points: [
{
protocol: string;
multiplier: string;
description: string;
},
];
description: string;
vault: string;
underlying: string;
underlyingSymbol: string;
underlyingPrice: string;
decimals: string;
tvl: string;
aprBreakdown: {
base: string;
boost: string;
incentives: string;
};
apr: string;
shareRatio: string;
remainingDepositAvailable: string;
totalAssets: string;
limit: string;
performanceFee: string;
}

export class NimboraAggregator extends IDapp<NimboraAggregatorDoc> {
name = 'Nimbora';
link = 'https://app.nimbora.io/';
logo =
'https://assets-global.website-files.com/64f0518cbb38bb59ddd7a331/64f1ea84a753c1ed93b2c920_faviconn.png';

incentiveDataKey = 'isNimboraAggregator';

_computePoolsInfo(data: any) {
try {
if (!data) return [];
const pools: PoolInfo[] = [];

Object.keys(data)
.filter(this.commonVaultFilter)
.forEach((poolName) => {
const poolData: NimboraAggregatorDoc = data[poolName];
let category = Category.Others;
const riskFactor = 3;
akiraonstarknet marked this conversation as resolved.
Show resolved Hide resolved
if (poolName === 'STRK') {
category = Category.STRK;
}

const logo =
CONSTANTS.LOGOS[poolName as keyof typeof CONSTANTS.LOGOS];

const baseApr = Number(poolData.aprBreakdown.base) / 100;
const boostApr = Number(poolData.aprBreakdown.boost) / 100;
const rewardApr = Number(poolData.aprBreakdown.incentives) / 100;

const apr = baseApr + boostApr + rewardApr;

const poolInfo: PoolInfo = {
pool: {
id: this.getPoolId(this.name, poolName),
name: `Earn ${poolName} with ${poolData.symbol}`,
logos: [logo],
},
protocol: {
name: this.name,
link: this.link,
logo: this.logo,
},
apr: apr ?? 0,
tvl: Number(poolData.tvl),
aprSplits: [
{
apr: baseApr ?? 0,
title: 'Base APR',
description: '',
},
{
apr: boostApr ?? 0,
title: 'Boost',
description: '',
},
{
apr: rewardApr ?? 0,
title: 'STRK DeFi Spring rewards',
description: '',
},
],
category,
type: PoolType.DEXV2,
akiraonstarknet marked this conversation as resolved.
Show resolved Hide resolved
lending: {
collateralFactor: 0,
},
borrow: {
borrowFactor: 0,
apr: 0,
},
additional: {
tags: [StrategyLiveStatus.ACTIVE],
riskFactor,
isAudited: false, // TODO: Update this
},
};
pools.push(poolInfo);
});

return pools;
} catch (err) {
console.error('Error fetching pools', err);
throw err;
}
}

commonVaultFilter(poolName: string) {
const supportedPools = ['STRK'];
return supportedPools.includes(poolName);
}
}

export const nimboraAggregator = new NimboraAggregator();

export const NimboraAggregatorAtom = atomWithQuery((get) => ({
queryKey: ['isNimboraAggregator'],
queryFn: async ({ queryKey }) => {
const fetchPools = async (): Promise<NimboraAggregatorDoc[]> => {
const res = await fetchWithRetry(
CONSTANTS.NIMBORA.AGGREGATOR_APR_API,
{},
'Failed to fetch Nimbora Aggregator data',
);

if (!res) {
return [];
}
let data = await res.text();
data = data.replaceAll('NaN', '0');
return JSON.parse(data);
};

const pools = await fetchPools();
return pools.reduce<{ [key: string]: NimboraAggregatorDoc }>(
(acc, pool) => {
acc[pool.underlyingSymbol] = pool;
return acc;
},
{},
);
},
}));

const NimboraAggregatorAtoms: ProtocolAtoms = {
pools: atom((get) => {
const poolsInfo = get(NimboraAggregatorAtom);
return poolsInfo.data
? nimboraAggregator._computePoolsInfo(poolsInfo.data)
: [];
}),
};

export default NimboraAggregatorAtoms;
Loading
Loading