Skip to content

Commit

Permalink
Links to banners, TVL Limit, STRK Sensei, Strategies metadata - #71 (#73
Browse files Browse the repository at this point in the history
)

* fix: fix STRK/USDC base apr (#72)

* add TVL limit, standarise stats API, fix strategy metadata issue

* format code

---------

Co-authored-by: Oche <[email protected]>
  • Loading branch information
akiraonstarknet and EjembiEmmanuel authored Jul 18, 2024
1 parent d0da983 commit c92a1af
Show file tree
Hide file tree
Showing 34 changed files with 1,351 additions and 1,218 deletions.
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"argsIgnorePattern": "^_"
}
],
"@typescript-eslint/no-namespace": "off",
"strict": 0,
"no-underscore-dangle": 0,
"no-mixed-requires": 0,
Expand Down
12 changes: 8 additions & 4 deletions next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
// output: 'export',
compiler: {
removeConsole: {
exclude: ['error'],
compiler: {
removeConsole: {
exclude: ['error'],
},
},
},
async rewrites() {
return [
{
Expand Down Expand Up @@ -39,6 +39,10 @@ const nextConfig = {
},
];
},
webpack(config, options) {
if (options.isServer) config.devtool = 'source-map';
return config;
},
};

export default nextConfig;
474 changes: 0 additions & 474 deletions public/banner1_small.svg

This file was deleted.

310 changes: 123 additions & 187 deletions public/banner2.svg → public/banners/ognft.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
File renamed without changes
Binary file added public/banners/seed_grant_small.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
301 changes: 301 additions & 0 deletions public/banners/seed_grant_small.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 11 additions & 28 deletions src/app/api/stats/[address]/route.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { NextResponse } from 'next/server';
import { Contract, RpcProvider, num, uint256 } from 'starknet';
import ERC4626Abi from '@/abi/erc4626.abi.json';
import axios from 'axios';
import { strategies } from '../api-utils';
import { num } from 'starknet';
import { getStrategies } from '@/store/strategies.atoms';

export const revalidate = 0;

Expand All @@ -22,36 +20,21 @@ export async function GET(req: Request, context: any) {
throw new Error('Invalid address');
}

const provider = new RpcProvider({
nodeUrl: process.env.RPC_URL || '',
});
const strategies = getStrategies();
const values = strategies.map(async (strategy) => {
const contract = new Contract(ERC4626Abi, strategy.contract, provider);
const sharesU256: any = await contract.call('balanceOf', [pAddr]);
const shares = uint256.uint256ToBN(sharesU256).toString();

const balanceU256Prom: any = contract.call('convert_to_assets', [
sharesU256,
]);
const priceInfoProm = axios.get(
`https://mainnet-api.ekubo.org/price/${strategy.ekuboPriceKey}`,
);
const [balanceU256, priceInfo] = await Promise.all([
balanceU256Prom,
priceInfoProm,
]);
console.log(balanceU256, 'balanceU256');
const balance = uint256.uint256ToBN(balanceU256).toString();

const price = priceInfo.data.price;
console.log('price', price, balance);
return (Number(balance) * Number(price)) / 10 ** strategy.decimals;
const balanceInfo = await strategy.getUserTVL(pAddr);
return {
id: strategy.id,
usdValue: balanceInfo.usdValue,
amount: balanceInfo.amount.toEtherStr(),
};
});

const result = await Promise.all(values);
const sum = result.reduce((a, b) => a + b, 0);
const sum = result.reduce((acc, item) => acc + item.usdValue, 0);
console.log({ pAddr, sum });
return NextResponse.json({
holdingsUSD: sum,
strategyWise: result,
});
}
23 changes: 0 additions & 23 deletions src/app/api/stats/api-utils.ts

This file was deleted.

36 changes: 7 additions & 29 deletions src/app/api/stats/route.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,18 @@
import { NextResponse } from 'next/server';
import { Contract, RpcProvider, uint256 } from 'starknet';
import ERC20Abi from '@/abi/erc20.abi.json';
import axios from 'axios';
import { strategies } from './api-utils';
import { getStrategies } from '@/store/strategies.atoms';

export const revalidate = 60;

export async function GET(req: Request) {
const provider = new RpcProvider({
nodeUrl: process.env.RPC_URL || '',
});
const values = strategies.map(async (strategy) => {
const strategies = getStrategies();
console.log('strategies', strategies.length);
const values = strategies.map(async (strategy, index) => {
let retry = 0;
console.log(strategy, 'strategy');
while (retry < 3) {
try {
const contract = new Contract(ERC20Abi, strategy.token, provider);
const balanceU256Prom: any = contract.call('balanceOf', [
strategy.contract,
]);
console.log(balanceU256Prom, 'balanceU256Prom');
const priceInfoProm = axios.get(
`https://mainnet-api.ekubo.org/price/${strategy.ekuboPriceKey}`,
);
const [balanceU256, priceInfo] = await Promise.all([
balanceU256Prom,
priceInfoProm,
]);
console.log(priceInfo, 'priceInfo');
console.log(balanceU256, 'balanceU256');
const balance = uint256.uint256ToBN(balanceU256).toString();

const price = priceInfo.data.price;
console.log('price', price, balance);
console.log('balance', balance);
return (Number(balance) * Number(price)) / 10 ** strategy.decimals;
const tvlInfo = await strategy.getTVL();
console.log('tvlInfo', index, tvlInfo);
return tvlInfo.usdValue;
} catch (e) {
console.log(e);
if (retry < 3) {
Expand Down
17 changes: 17 additions & 0 deletions src/app/api/strategies/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { NextResponse } from 'next/server';

export const revalidate = 3600; // 1 hr

export async function GET(req: Request) {
try {
return NextResponse.json({
status: true,
});
} catch (err) {
console.error('Error /api/strategies', err);
return NextResponse.json({
status: false,
strategies: [],
});
}
}
77 changes: 47 additions & 30 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import {
import Autoplay from 'embla-carousel-autoplay';
import useEmblaCarousel from 'embla-carousel-react';
import mixpanel from 'mixpanel-browser';
import Image from 'next/image';
import { useRouter, useSearchParams } from 'next/navigation';
import { useEffect, useState } from 'react';
import { isMobile } from 'react-device-detect';
Expand Down Expand Up @@ -72,50 +71,68 @@ export default function Home() {
const { selectedIndex, scrollSnaps, onDotButtonClick } =
useDotButton(emblaApi);

const banner_images = [
{
desktop: '/banners/ognft.svg',
mobile: '/banners/ognft_small.svg',
link: 'https://x.com/strkfarm/status/1788558092109775029',
},
{
desktop: '/banners/seed_grant.svg',
mobile: '/banners/seed_grant_small.jpg',
link: 'https://x.com/strkfarm/status/1787783906982260881',
},
];

return (
<Container maxWidth={'1000px'} margin={'0 auto'}>
<Box padding={'15px 30px'} borderRadius="10px" margin="20px 0px">
<Text fontSize={'35px'} color={'cyan'} textAlign={'center'}>
<Box padding={'15px 30px'} borderRadius="10px" margin={'20px 0px 10px'}>
<Text
fontSize={{ base: '28px', md: '35px' }}
lineHeight={'30px'}
marginBottom={'10px'}
color={'cyan'}
textAlign={'center'}
>
<b>{"Starknet's"} Yield Powerhouse🚀</b>
</Text>
<Text
color="color2"
textAlign={'center'}
fontSize={'18px'}
fontSize={{ base: '16px', md: '18px' }}
marginBottom={'0px'}
>
Identify & Invest in the best $STRK rewarding pools and maximize your
rewards
</Text>
</Box>

<Box className="embla" ref={emblaRef}>
<Box className="embla" ref={emblaRef} margin={0} width={'100%'}>
<Box className="embla__container">
<Box className="embla__slide" position="relative" height={'200px'}>
<Image
src={
(!isMobile && size.width >= 768) || size.width == 0
? '/banner1.svg'
: '/banner1_small.svg'
}
alt="banner2"
fill
style={{ objectFit: 'contain', borderRadius: '12px' }}
/>
</Box>

<Box className="embla__slide" position="relative" height={'200px'}>
<Image
src={
(!isMobile && size.width >= 768) || size.width == 0
? '/banner2.svg'
: '/banner2_small.svg'
}
alt="banner2"
fill
style={{ objectFit: 'contain', borderRadius: '12px' }}
/>
</Box>
{banner_images.map((banner, index) => (
<Box
className="embla__slide"
position="relative"
height={'auto'}
key={index}
padding={'10px'}
>
<Link href={banner.link} isExternal>
<ChakraImage
src={
(!isMobile && size.width > 450) || size.width == 0
? banner.desktop
: banner.mobile
}
height={'auto'}
boxShadow={'0px 0px 2px #484848'}
width="100%"
alt="Banner"
style={{ objectFit: 'cover', borderRadius: '10px' }}
/>
</Link>
</Box>
))}
</Box>
</Box>

Expand Down
6 changes: 3 additions & 3 deletions src/app/strategy/components/Strategy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ const Strategy = () => {
console.log('txs', transactions);
}, [transactions]);
const strategy: StrategyInfo | undefined = useMemo(() => {
const name = searchParams.get('name');
console.log('name', name);
return strategies.find((s) => s.name === name);
const id = searchParams.get('id');
console.log('id', id);
return strategies.find((s) => s.id === id);
}, [searchParams, strategies]);

const setBalQueryEnable = useSetAtom(strategy?.balEnabled || atom(false));
Expand Down
22 changes: 11 additions & 11 deletions src/app/strategy/page.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
import { Container } from '@chakra-ui/react';

import Strategy from './components/Strategy';
import { getStrategies } from '@/store/strategies.atoms';

type Props = {
params: { name: string };
searchParams?: { [key: string]: string | string[] | undefined };
};

export async function generateMetadata({ searchParams }: Props) {
if (searchParams?.name?.includes('STRK')) {
const strategies = getStrategies();
const strategy = strategies.find((s) => s.id === searchParams?.id);
if (strategy) {
return {
title: 'Auto Compounding STRK | STRKFarm',
description:
"Stake your STRK or zkLend's zSTRK token to receive DeFi Spring $STRK rewards every 14 days. The strategy auto-collects your rewards and re-invests them in the zkLend STRK pool, giving you higher return through compounding. You receive frmzSTRK LP token as representation for your stake on STRKFarm. You can withdraw anytime by redeeming your frmzSTRK for zSTRK and see your STRK in zkLend.",
title: `${strategy.name} | STRKFarm`,
description: strategy.description,
};
}

if (searchParams?.name?.includes('USDC')) {
return {
title: 'Auto Compounding USDC | STRKFarm',
description:
"Stake your USDC or zkLend's zUSDC token to receive DeFi Spring $STRK rewards every 14 days. The strategy auto-collects your $STRK rewards, swaps them to USDC and re-invests them in the zkLend USDC pool, giving you higher return through compounding. You receive frmzUSDC LP token as representation for your stake on STRKFarm. You can withdraw anytime by redeeming your frmzUSDC for zUSDC and see your STRK in zkLend.",
};
}
return {
title: 'Yield Strategy | STRKFarm',
description:
"STRKFarm's yield strategies are designed to maximize your yield farming returns. Stake your assets in our strategies to earn passive income while we take care of the rest.",
};
}

export default function StrategyPage() {
Expand Down
Loading

0 comments on commit c92a1af

Please sign in to comment.