From c8b2b745e8b15ec94102218df2145cb4002a467a Mon Sep 17 00:00:00 2001 From: Oche Date: Mon, 9 Dec 2024 07:49:31 +0100 Subject: [PATCH] feat: update nimbora pools list (#184) * feat: add nimbora yield dex protocol * fix: fix build error * feat: add nimbora aggregator and liquity pools * feat: delete nimbora aggregator store * feat: delete nimbora liquity * refac: minor changes * refac: minor changes * nimbora dex add category stable --------- Co-authored-by: Akira <156126180+akiraonstarknet@users.noreply.github.com> --- next.config.mjs | 4 + src/constants.ts | 5 + src/store/nimbora.store.ts | 45 --------- src/store/nimboradex.store.ts | 174 ++++++++++++++++++++++++++++++++++ src/store/protocols.ts | 15 +-- 5 files changed, 191 insertions(+), 52 deletions(-) delete mode 100755 src/store/nimbora.store.ts create mode 100644 src/store/nimboradex.store.ts diff --git a/next.config.mjs b/next.config.mjs index ce4ebb7a..6b472b2f 100755 --- a/next.config.mjs +++ b/next.config.mjs @@ -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() { diff --git a/src/constants.ts b/src/constants.ts index 4bc9a75d..5a5fe3b6 100755 --- a/src/constants.ts +++ b/src/constants.ts @@ -33,6 +33,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', }, diff --git a/src/store/nimbora.store.ts b/src/store/nimbora.store.ts deleted file mode 100755 index e98e1631..00000000 --- a/src/store/nimbora.store.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { PoolInfo, ProtocolAtoms, StrkLendingIncentivesAtom } from './pools'; -import { atom } from 'jotai'; -import { AtomWithQueryResult } from 'jotai-tanstack-query'; -import { LendingSpace } from './lending.base'; -import { IDapp } from './IDapp.store'; - -export class Nimbora extends IDapp { - name = 'Nimbora'; - link = 'https://app.nimbora.io/'; - logo = - 'https://assets-global.website-files.com/64f0518cbb38bb59ddd7a331/64f1ea84a753c1ed93b2c920_faviconn.png'; - - incentiveDataKey = 'Nimbora'; - - _computePoolsInfo(data: any) { - return LendingSpace.computePoolsInfo( - data, - this.incentiveDataKey, - { - name: this.name, - link: this.link, - logo: this.logo, - }, - this.commonVaultFilter, - ); - } - - getBaseAPY( - p: PoolInfo, - data: AtomWithQueryResult, - ) { - return LendingSpace.getBaseAPY(p, data); - } -} - -export const nimbora = new Nimbora(); -const NimboraAtoms: ProtocolAtoms = { - pools: atom((get) => { - const poolsInfo = get(StrkLendingIncentivesAtom); - const empty: PoolInfo[] = []; - if (poolsInfo.data) return nimbora._computePoolsInfo(poolsInfo.data); - return empty; - }), -}; -export default NimboraAtoms; diff --git a/src/store/nimboradex.store.ts b/src/store/nimboradex.store.ts new file mode 100644 index 00000000..28a72177 --- /dev/null +++ b/src/store/nimboradex.store.ts @@ -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 NimboraDexDoc { + name: string; + symbol: string; + protocols: string[]; + points: [ + { + protocol: string; + multiplier: string; + description: string; + }, + ]; + description: string; + token: string; + tokenManager: string; + underlying: string; + underlyingSymbol: string; + underlyingPrice: string; + l1Strategy: string; + decimals: string; + epoch: string; + epochDelay: string; + tvl: string; + aprBreakdown: { + base: string; + boost: string; + incentives: string; + }; + apr: string; + shareRatio: string; + remainingDepositAvailable: string; + totalAssets: string; + limit: string; + performanceFee: string; +} + +export class NimboraDex extends IDapp { + name = 'Nimbora'; + link = 'https://app.nimbora.io/referral/?ref=u4j7y0c8'; + logo = + 'https://assets-global.website-files.com/64f0518cbb38bb59ddd7a331/64f1ea84a753c1ed93b2c920_faviconn.png'; + + incentiveDataKey = 'isNimboraDex'; + + _computePoolsInfo(data: any) { + try { + if (!data) return []; + const pools: PoolInfo[] = []; + + Object.keys(data) + .filter(this.commonVaultFilter) + .forEach((poolName) => { + const poolData: NimboraDexDoc = data[poolName]; + let category = Category.Others; + const riskFactor = 0.75; + + if (poolName == 'USDC') { + category = Category.Stable; + } + + 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: `${poolName} with ${poolData.symbol}`, + logos: [logo], + }, + protocol: { + name: this.name, + link: this.link, + logo: this.logo, + }, + apr, + 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.Derivatives, + 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 = ['USDC', 'ETH', 'DAI']; + return supportedPools.includes(poolName); + } +} + +export const nimboraDex = new NimboraDex(); + +export const NimboraDexAtom = atomWithQuery((get) => ({ + queryKey: ['isNimboraDex'], + queryFn: async ({ queryKey }) => { + const fetchPools = async (): Promise => { + const res = await fetchWithRetry( + CONSTANTS.NIMBORA.DEX_APR_API, + {}, + 'Failed to fetch Nimbora Yield Dex 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]: NimboraDexDoc }>((acc, pool) => { + acc[pool.underlyingSymbol] = pool; + return acc; + }, {}); + }, +})); + +const NimboraDexAtoms: ProtocolAtoms = { + pools: atom((get) => { + const poolsInfo = get(NimboraDexAtom); + return poolsInfo.data ? nimboraDex._computePoolsInfo(poolsInfo.data) : []; + }), +}; + +export default NimboraDexAtoms; diff --git a/src/store/protocols.ts b/src/store/protocols.ts index 356ac19c..12f7b789 100644 --- a/src/store/protocols.ts +++ b/src/store/protocols.ts @@ -8,14 +8,15 @@ import MySwapAtoms, { mySwap } from './myswap.store'; import NostraDegenAtoms, { nostraDegen } from './nostradegen.store'; import NostraDexAtoms, { nostraDex } from './nostradex.store'; import NostraLendingAtoms, { nostraLending } from './nostralending.store'; +import VesuAtoms, { vesu } from './vesu.store'; +import ZkLendAtoms, { zkLend } from './zklend.store'; +import NimboraDexAtoms, { nimboraDex } from './nimboradex.store'; import { Category, PoolInfo, PoolType } from './pools'; import { getLiveStatusEnum } from './strategies.atoms'; import STRKFarmAtoms, { strkfarm, STRKFarmStrategyAPIResult, } from './strkfarm.atoms'; -import VesuAtoms, { vesu } from './vesu.store'; -import ZkLendAtoms, { zkLend } from './zklend.store'; import EndurAtoms, { endur } from './endur.store'; export const PROTOCOLS = [ @@ -99,11 +100,11 @@ export const PROTOCOLS = [ class: vesu, atoms: VesuAtoms, }, - // { - // name: nimbora.name, - // class: nimbora, - // atoms: NimboraAtoms, - // } + { + name: nimboraDex.name, + class: nimboraDex, + atoms: NimboraDexAtoms, + }, ]; export const ALL_FILTER = 'All';