Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/components/commons/Logo/EthLogo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Icon, IconProps } from '@chakra-ui/react';
import React from 'react';

export const EthLogo: React.FC<IconProps> = (props) => (
<Icon viewBox="0 0 32 32" {...props}>
<g fill="none" fillRule="evenodd">
<circle cx="16" cy="16" r="16" fill="#627EEA" />
<g fill="#FFF" fillRule="nonzero">
<path fillOpacity=".602" d="M16.498 4v8.87l7.497 3.35z" />
<path d="M16.498 4L9 16.22l7.498-3.35z" />
<path fillOpacity=".602" d="M16.498 21.968v6.027L24 17.616z" />
<path d="M16.498 27.995v-6.028L9 17.616z" />
<path fillOpacity=".2" d="M16.498 20.573l7.497-4.353-7.497-3.348z" />
<path fillOpacity=".602" d="M9 16.22l7.498 4.353v-7.701z" />
</g>
</g>
</Icon>
);
2 changes: 1 addition & 1 deletion src/components/navigation/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export const useNavigationConfig = (): NavigationConfig => {
],
},
{
label: 'Staking',
label: 'Stake',
path: '/staking',
},
{
Expand Down
24 changes: 24 additions & 0 deletions src/pages/stakingPage/components/BoldGrix.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Text } from '@chakra-ui/react';
import React from 'react';

type BoldGrixProps = {
text: string;
};

export const BoldGrix: React.FC<BoldGrixProps> = ({ text }) => {
const parts = text.split(/(GRIX|esGRIX)/g);
return (
<>
{parts.map((part, index) => {
if (part === 'GRIX' || part === 'esGRIX') {
return (
<Text as="b" key={index}>
{part}
</Text>
);
}
return part;
})}
</>
);
};
49 changes: 26 additions & 23 deletions src/pages/stakingPage/components/RewardsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useCallback, useEffect, useState } from 'react';
import { useAccount } from 'wagmi';

import { GrixLogo } from '@/components/commons/Logo';
import { EthLogo } from '@/components/commons/Logo/EthLogo';
import { claim, compound } from '@/web3Config/staking/hooks';

type RewardsCardProps = {
Expand All @@ -16,7 +17,9 @@ type RewardsCardProps = {
};

type DexScreenerResponse = {
pairs?: { priceUsd?: string }[];
grix: {
usd: number;
};
};

export const RewardsCard = ({ data, refetchData }: RewardsCardProps): JSX.Element => {
Expand All @@ -26,15 +29,13 @@ export const RewardsCard = ({ data, refetchData }: RewardsCardProps): JSX.Elemen
const [grixPrice, setGrixPrice] = useState<number | null>(null);
const toast = useToast();

// Fetch GRIX price from dexscreener
// Fetch GRIX price from CoinGecko
useEffect(() => {
const fetchPrice = async () => {
try {
const res = await fetch(
'https://api.dexscreener.com/latest/dex/pairs/arbitrum/0x25d3ce097e413eeab09bbda72cd87d8972e673d4'
);
const res = await fetch('https://api.coingecko.com/api/v3/simple/price?ids=grix&vs_currencies=usd');
const json = (await res.json()) as DexScreenerResponse;
const price = json?.pairs?.[0]?.priceUsd ? parseFloat(json.pairs[0].priceUsd) : null;
const price = json.grix.usd;
setGrixPrice(price);
} catch {
setGrixPrice(null);
Expand Down Expand Up @@ -100,49 +101,49 @@ export const RewardsCard = ({ data, refetchData }: RewardsCardProps): JSX.Elemen
return (
<Box
bg="gray.950"
borderRadius="lg"
p={6}
borderRadius="md"
p={4}
height="fit-content"
border="1px solid"
borderColor="gray.900"
_hover={{ borderColor: 'gray.800' }}
>
<VStack spacing={4} align="stretch">
<VStack spacing={3} align="stretch">
<HStack justify="space-between">
<HStack spacing={2}>
<Text fontSize="lg">🔷</Text>
<Text color="white" fontWeight="500">
<EthLogo boxSize="16px" />
<Text color="white" fontWeight="600" fontSize="sm" letterSpacing="-0.01em">
WETH
</Text>
</HStack>
<Text color="gray.400" fontSize="sm">
<Text color="gray.400" fontSize="sm" fontWeight="500">
≤{(0.0001).toFixed(4)} WETH (≤${(0.01).toFixed(2)})
</Text>
</HStack>

<HStack justify="space-between">
<HStack spacing={2}>
<GrixLogo boxSize="20px" />
<Text color="white" fontWeight="500">
<GrixLogo boxSize="16px" />
<Text color="white" fontWeight="600" fontSize="sm" letterSpacing="-0.01em">
Staked Amount
</Text>
</HStack>
<Text color="gray.400" fontSize="sm">
<Text color="gray.400" fontSize="sm" fontWeight="500">
{data?.stakedAmount ? Number(data.stakedAmount).toFixed(4) : '0.0000'} GRIX
</Text>
</HStack>

<HStack justify="space-between">
<HStack spacing={2}>
<GrixLogo boxSize="20px" />
<Text color="white" fontWeight="500">
<GrixLogo boxSize="16px" />
<Text color="white" fontWeight="600" fontSize="sm" letterSpacing="-0.01em">
Claimable Rewards
</Text>
</HStack>
<Text color="gray.400" fontSize="sm">
<Text color="gray.400" fontSize="sm" fontWeight="500">
{data?.claimable ? Number(data.claimable).toFixed(4) : '0.0000'} esGRIX
{grixPrice && data?.claimable && (
<Text as="span" color="green.300" fontWeight="500" fontSize="sm">
<Text as="span" color="green.300" fontWeight="600" fontSize="sm" letterSpacing="-0.01em">
&nbsp;($
{(Number(data.claimable) * grixPrice).toLocaleString(undefined, {
minimumFractionDigits: 2,
Expand All @@ -159,9 +160,10 @@ export const RewardsCard = ({ data, refetchData }: RewardsCardProps): JSX.Elemen
loadingText="Claiming"
bg="teal.400"
color="white"
size="lg"
size="md"
width="full"
height="48px"
height="40px"
fontSize="sm"
isDisabled={!data?.claimable || Number(data?.claimable) <= 0}
_hover={{ bg: 'teal.500' }}
_active={{ bg: 'teal.600' }}
Expand All @@ -175,9 +177,10 @@ export const RewardsCard = ({ data, refetchData }: RewardsCardProps): JSX.Elemen
loadingText="Compounding"
bg="teal.400"
color="white"
size="lg"
size="md"
width="full"
height="48px"
height="40px"
fontSize="sm"
_hover={{ bg: 'teal.500' }}
_active={{ bg: 'teal.600' }}
>
Expand Down
16 changes: 7 additions & 9 deletions src/pages/stakingPage/components/StakingCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { StakingCardContent } from './StakingCardContent.js';
type StakingCardProps = {
title: string;
description: string;
type: 'gs' | 'esgs';
type: 'gx' | 'esgx';
refreshTrigger: number;
onActionComplete: () => void;
};
Expand All @@ -45,7 +45,7 @@ export const StakingCard: React.FC<StakingCardProps> = ({
const [apr, setApr] = useState(0);
const [_showError, setShowError] = useState(false);
const toast = useToast();
const tokenAddress = type === 'gs' ? stakingContracts.grixToken.address : stakingContracts.esGRIXToken.address;
const tokenAddress = type === 'gx' ? stakingContracts.grixToken.address : stakingContracts.esGRIXToken.address;

const showToast = useCallback(
(title: string, description: string, status: 'success' | 'error') => {
Expand All @@ -64,7 +64,7 @@ export const StakingCard: React.FC<StakingCardProps> = ({
if (!address) return;

try {
if (type === 'esgs') {
if (type === 'esgx') {
const staked = await getEsGrixStakedAmount(address);
setStakedAmount(staked);
} else {
Expand Down Expand Up @@ -107,7 +107,7 @@ export const StakingCard: React.FC<StakingCardProps> = ({
}, [fetchBalance, fetchStakedAmount, fetchAPR, refreshTrigger]);

const handleMaxClick = () => {
if (type === 'esgs') {
if (type === 'esgx') {
setAmount(stakedAmount);
} else {
setAmount(availableBalance);
Expand Down Expand Up @@ -169,9 +169,7 @@ export const StakingCard: React.FC<StakingCardProps> = ({
[fetchBalance, fetchStakedAmount, fetchAPR, onActionComplete]
);

// Add a useEffect to handle refreshTrigger changes without causing infinite loops
useEffect(() => {
// Skip the initial render
if (refreshTrigger > 0) {
void refreshAllData(false);
}
Expand Down Expand Up @@ -209,7 +207,7 @@ export const StakingCard: React.FC<StakingCardProps> = ({
setIsStaking(true);
const amountBigInt = parseEther(amount);

if (type === 'gs') {
if (type === 'gx') {
await stakeGs(amountBigInt);
} else {
await stakeEsGs(amountBigInt);
Expand All @@ -231,7 +229,7 @@ export const StakingCard: React.FC<StakingCardProps> = ({
if (!amount || !address) return;

try {
const currentStaked = type === 'gs' ? await getStakedAmount(address) : await getEsGrixStakedAmount(address);
const currentStaked = type === 'gx' ? await getStakedAmount(address) : await getEsGrixStakedAmount(address);

if (Number(amount) > Number(currentStaked)) {
showToast('Invalid Amount', 'Amount exceeds staked balance', 'error');
Expand All @@ -242,7 +240,7 @@ export const StakingCard: React.FC<StakingCardProps> = ({
setIsUnstaking(true);
const amountBigInt = parseEther(amount);

if (type === 'gs') {
if (type === 'gx') {
await unstakeGs(amountBigInt);
} else {
await unstakeEsGs(amountBigInt);
Expand Down
10 changes: 7 additions & 3 deletions src/pages/stakingPage/components/StakingCardContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import React from 'react';
import { GrixLogo } from '@/components/commons/Logo';

import { formatBalance } from '../utils/formatters';
import { BoldGrix } from './BoldGrix';

type StakingCardContentProps = {
title: string;
Expand Down Expand Up @@ -69,10 +70,10 @@ export const StakingCardContent: React.FC<StakingCardContentProps> = ({
<GrixLogo boxSize={8} mr={3} />
<div>
<Heading size="md" color="white" mb={1} fontWeight="600">
{title}
<BoldGrix text={title} />
</Heading>
<Text color="gray.400" fontSize="sm">
{description}
<BoldGrix text={description} />
</Text>
</div>
</Flex>
Expand Down Expand Up @@ -100,7 +101,10 @@ export const StakingCardContent: React.FC<StakingCardContentProps> = ({
<Text fontSize="sm" color="gray.500" mb={1}>
APR
</Text>
<Text fontSize="xl" fontWeight="700" color="white">
<Text fontSize="xl" fontWeight="700" color="green.200" display="flex" alignItems="center" gap={2}>
<Text as="span" color="green.300">
</Text>
{apr.toFixed(2)}%
</Text>
</VStack>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/stakingPage/components/VestingCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ export const VestingCard: React.FC<VestingCardProps> = ({ onActionComplete }) =>
<VStack spacing={4} align="stretch">
<InputGroup size="lg">
<Input
placeholder="Enter amount"
placeholder="Enter esGrix amount"
value={amount}
onChange={handleAmountChange}
type="text"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import { Flex, Heading, Text } from '@chakra-ui/react';
import { Heading, Text, VStack } from '@chakra-ui/react';
import React from 'react';

import { GrixLogo } from '@/components/commons/Logo';
import { BoldGrix } from '../BoldGrix';

export const VestingHeader: React.FC = () => (
<Flex align="center" mb={5}>
<GrixLogo boxSize={8} mr={3} />
<div>
<Heading size="md" color="white" mb={1} fontWeight="600">
Vesting
</Heading>
<Text color="gray.400" fontSize="sm">
Convert esGRIX tokens to GRIX Token
</Text>
</div>
</Flex>
<VStack align="stretch" mb={4}>
<Heading size="sm" color="white" fontWeight="700" letterSpacing="-0.01em">
Vesting
</Heading>
<Text color="gray.400" fontSize="sm" fontWeight="500">
<BoldGrix text="Convert esGRIX tokens to GRIX Token" />
</Text>
</VStack>
);
18 changes: 6 additions & 12 deletions src/pages/stakingPage/components/VestingComponents/VestingInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
import { Text, VStack } from '@chakra-ui/react';
import React from 'react';

type VestingInfoProps = {
_vestingData?: {
claimable: string;
totalVested: string;
maxVestableAmount: string;
} | null;
};
import { BoldGrix } from '../BoldGrix';

export const VestingInfo: React.FC<VestingInfoProps> = ({ _vestingData }) => (
export const VestingInfo: React.FC = () => (
<VStack align="stretch" spacing={1}>
<Text fontSize="sm" color="gray.500" mb={1}>
<Text color="gray.400" fontSize="sm" fontWeight="600" letterSpacing="-0.01em">
About Vesting
</Text>
<Text fontSize="sm" color="gray.400">
Convert your esGRIX tokens to GRIX Token through the vesting process. Vested tokens are claimable on an ongoing
basis.
<Text color="gray.400" fontSize="sm" fontWeight="500">
<BoldGrix text="Convert your esGRIX tokens to GRIX Token through the vesting process. Vested tokens are claimable on an ongoing basis." />
</Text>
</VStack>
);
Loading