diff --git a/src/app/stake/page.js b/src/app/stake/page.js
index ceca21d..2d1d30d 100644
--- a/src/app/stake/page.js
+++ b/src/app/stake/page.js
@@ -1,9 +1,6 @@
'use client';
import { useEffect, useState, useMemo } from 'react';
-import { Image } from '@chakra-ui/react';
-import Lottie from 'react-lottie-player';
-import lottieJson from '@/assets/animations/PE2.json';
import XeonStakingPoolABI from '@/abi/XeonStakingPool.abi.json';
import { Constants } from '@/abi/constants';
import Header from '@/components/Header';
@@ -20,13 +17,19 @@ import {
useDisclosure,
} from '@chakra-ui/react';
import BookmarkAdded from '@/components/BookmarkAdded';
+import { useActiveAccount } from 'thirdweb/react';
function Page() {
- const [voteValue, setVoteValue] = useState(5); // state for user buyback vote value
- // todo: for mainnet, ensure currentPercentage is proper default
- const [currentPercentage, setCurrentPercentage] = useState(5); // state for current buyback percentage
const [loading, setLoading] = useState(false);
const [message, setMessage] = useState('');
+ const [epoch, setEpoch] = useState('0.00'); // todo: app doesn't set epoch, only reads it (value is whole number integer)
+ const [ethInPool, setEthInPool] = useState('0.00');
+ const [buyBackPercentage, setBuyBackPercentage] = useState('0.00');
+ const [teamPercentage, setTeamPercentage] = useState('0.00');
+ const [walletXeonBalance, setWalletXeonBalance] = useState('0.00'); // todo: display user's contract balance
+ const [stakedXeonBalance, setStakedXeonBalance] = useState('0.00'); // todo: display user's staked balance
+ const wallet = useActiveAccount();
+ const connectedAddress = wallet?.address;
const [provider, setProvider] = useState(null);
const [signer, setSigner] = useState(null);
const { isOpen, onOpen, onClose } = useDisclosure();
@@ -55,6 +58,58 @@ function Page() {
);
}, [provider, signer]);
+ const XeonToken = useMemo(() => {
+ if (!provider || !signer) return null;
+ return new ethers.Contract(
+ Constants.testnet.XeonToken,
+ XeonStakingPoolABI,
+ signer
+ );
+ }, [provider, signer]);
+ const WETH = useMemo(() => {
+ if (!provider) return null;
+ return new ethers.Contract(
+ Constants.testnet.WETH,
+ XeonStakingPoolABI,
+ provider
+ );
+ }, [provider]);
+ useEffect(() => {
+ const fetchData = async () => {
+ try {
+ if (!XeonStakingPool || !WETH || !XeonToken || !connectedAddress)
+ return;
+
+ const epoch = await XeonStakingPool.epoch();
+ setEpoch(ethers.utils.formatUnits(epoch, 0));
+
+ const ethBalance = await WETH.balanceOf(
+ Constants.testnet.XeonStakingPool
+ );
+ setEthInPool(ethers.utils.formatEther(ethBalance));
+
+ const buyBackPercentage = await XeonStakingPool.buyBackPercentage();
+ setBuyBackPercentage(ethers.utils.formatUnits(buyBackPercentage, 0));
+
+ const teamPercentage = await XeonStakingPool.teamPercentage();
+ setTeamPercentage(ethers.utils.formatUnits(teamPercentage, 0));
+
+ const xeonBalance = await XeonToken.balanceOf(connectedAddress);
+ setWalletXeonBalance(ethers.utils.formatEther(xeonBalance));
+
+ const stakedXeonBalance =
+ await XeonStakingPool.balanceOf(connectedAddress);
+ setStakedXeonBalance(ethers.utils.formatEther(stakedXeonBalance));
+ } catch (error) {
+ console.error('Error fetching asset values:', error);
+ }
+ };
+
+ if (connectedAddress) {
+ fetchData();
+ }
+ }, [connectedAddress, XeonStakingPool, XeonToken, WETH]);
+
useEffect(() => {
// fetch current buyback percentage from contract
const fetchBuybackPercentage = async () => {
@@ -72,157 +127,47 @@ function Page() {
fetchBuybackPercentage();
}, [XeonStakingPool]);
- // handle increment and decrement of vote value
- // todo: for mainnet, ensure vote value is clamped to contract min/max
- const handleIncrement = () => {
- setVoteValue((prevValue) => Math.min(prevValue + 1, 100));
- };
-
- const handleDecrement = () => {
- setVoteValue((prevValue) => Math.max(prevValue - 1, 1));
- };
-
- const handleVote = async () => {
- if (!XeonStakingPool || voteValue < 1 || voteValue > 100) {
- setMessage('Please enter a value between 1 and 100');
- return;
- }
-
- setLoading(true);
- onOpen();
-
- try {
- const tx = await XeonStakingPool.voteForBuybackPercentage(voteValue);
- await tx.wait();
- setLoading(false);
- setMessage(`Vote successful for ${voteValue}% buyback`);
- } catch (error) {
- console.error('Vote failed', error);
- setLoading(false);
- setMessage('Vote failed, please try again.');
- }
- };
-
- // handle vote value change
- const handleVoteChange = (e) => {
- const value = parseInt(e.target.value);
- if (Number.isNaN(value)) {
- setVoteValue(1);
- } else {
- setVoteValue(Math.min(Math.max(value, 1), 100));
- }
- };
-
return (
-
-
-
Stake
-
- Xeon
-
-
-
-
-
-
-
+
+
+
Stake your XEON tokens in just two simple steps.
-
-
+
+
Stake XEON tokens to be eligible for revenue sharing. The staking
window opens for 3 days at the end of each epoch, at which time
XEON can be staked or unstaked. Protocol revenue is deposited is
deposited into the staking pool.
-
-
-
-
-
-
-
-
-
- Settle
-
-
- Close expired positions and collect fess into the staking pool
-
-
-
- Settle
-
+
-
-
-
- $XEON Buyback
-
-
- What percentage of protocol revenue should be used to buyback
- $XEON token?
-
-
-
- -
-
-
-
-
-
- +
-
-
- Vote
-
+
+
Epoch # {epoch}
+
{ethInPool} ETH in pool
+
+ $XEON Buyback: {buyBackPercentage}%
+
+
+ Team Percentage: {teamPercentage}%
+
-
- Current Buyback Percentage: {currentPercentage}%
-
+
+
+
+
diff --git a/src/components/staking/UserAssets.js b/src/components/staking/UserAssets.js
index aa6e061..36b3d7b 100644
--- a/src/components/staking/UserAssets.js
+++ b/src/components/staking/UserAssets.js
@@ -15,13 +15,12 @@ import {
} from '@chakra-ui/react';
import { motion } from 'framer-motion';
import { useState, useEffect, useMemo } from 'react';
-import { FaEthereum } from 'react-icons/fa';
-import AssetsValues from '../wallet/AssetsValues';
-import { useActiveAccount } from 'thirdweb/react';
+
import { ethers } from 'ethers';
import XeonStakingPoolABI from '@/abi/XeonStakingPool.abi.json';
import { Constants } from '@/abi/constants';
import BookmarkAdded from '../BookmarkAdded';
+import { useActiveAccount } from 'thirdweb/react';
function UserAssets() {
const [isSwitched, setIsSwitched] = useState(false);
@@ -33,17 +32,13 @@ function UserAssets() {
const [loading, setLoading] = useState(false);
const [message, setMessage] = useState('');
const [status, setStatus] = useState('');
- const [epoch, setEpoch] = useState('0.00'); // todo: app doesn't set epoch, only reads it (value is whole number integer)
- const [ethInPool, setEthInPool] = useState('0.00');
- const [buyBackPercentage, setBuyBackPercentage] = useState('0.00');
- const [teamPercentage, setTeamPercentage] = useState('0.00');
- const [walletXeonBalance, setWalletXeonBalance] = useState('0.00'); // todo: display user's contract balance
- const [stakedXeonBalance, setStakedXeonBalance] = useState('0.00'); // todo: display user's staked balance
const { isOpen, onOpen, onClose } = useDisclosure();
- const wallet = useActiveAccount();
- const connectedAddress = wallet?.address;
const [provider, setProvider] = useState(null);
const [signer, setSigner] = useState(null);
+ const wallet = useActiveAccount();
+ const [voteValue, setVoteValue] = useState(5); // state for user buyback vote value
+ // todo: for mainnet, ensure currentPercentage is proper default
+ const [currentPercentage, setCurrentPercentage] = useState(5); // state for current buyback percentage
useEffect(() => {
if (typeof window !== 'undefined' && window.ethereum) {
@@ -72,51 +67,6 @@ function UserAssets() {
);
}, [provider, signer]);
- const WETH = useMemo(() => {
- if (!provider) return null;
- return new ethers.Contract(
- Constants.testnet.WETH,
- XeonStakingPoolABI,
- provider
- );
- }, [provider]);
-
- useEffect(() => {
- const fetchData = async () => {
- try {
- if (!XeonStakingPool || !WETH || !XeonToken || !connectedAddress)
- return;
-
- const epoch = await XeonStakingPool.epoch();
- setEpoch(ethers.utils.formatUnits(epoch, 0));
-
- const ethBalance = await WETH.balanceOf(
- Constants.testnet.XeonStakingPool
- );
- setEthInPool(ethers.utils.formatEther(ethBalance));
-
- const buyBackPercentage = await XeonStakingPool.buyBackPercentage();
- setBuyBackPercentage(ethers.utils.formatUnits(buyBackPercentage, 0));
-
- const teamPercentage = await XeonStakingPool.teamPercentage();
- setTeamPercentage(ethers.utils.formatUnits(teamPercentage, 0));
-
- const xeonBalance = await XeonToken.balanceOf(connectedAddress);
- setWalletXeonBalance(ethers.utils.formatEther(xeonBalance));
-
- const stakedXeonBalance =
- await XeonStakingPool.balanceOf(connectedAddress);
- setStakedXeonBalance(ethers.utils.formatEther(stakedXeonBalance));
- } catch (error) {
- console.error('Error fetching asset values:', error);
- }
- };
-
- if (connectedAddress) {
- fetchData();
- }
- }, [connectedAddress, XeonStakingPool, XeonToken, WETH]);
-
useEffect(() => {
if (wallet && XeonToken && XeonStakingPool) {
XeonToken.balanceOf(wallet.address).then((balance) => {
@@ -145,6 +95,10 @@ function UserAssets() {
const handleApprove = async () => {
setLoading(true);
try {
+ if (parseFloat(stakeAmount) > parseFloat(walletBalance)) {
+ throw new Error('Amount exceeds wallet balance');
+ }
+
if (!isApproved && XeonToken) {
const tx = await XeonToken.approve(
XeonStakingPool.address,
@@ -158,7 +112,7 @@ function UserAssets() {
}
} catch (error) {
setStatus('error');
- setMessage('Approval failed.');
+ setMessage(error.message || 'Approval failed.');
console.error('Approval failed', error);
} finally {
setLoading(false);
@@ -169,6 +123,10 @@ function UserAssets() {
const handleStake = async () => {
setLoading(true);
try {
+ if (parseFloat(stakeAmount) > parseFloat(walletBalance)) {
+ throw new Error('Amount exceeds wallet balance');
+ }
+
if (isApproved && XeonStakingPool) {
const tx = await XeonStakingPool.stake(
ethers.utils.parseEther(stakeAmount)
@@ -179,7 +137,7 @@ function UserAssets() {
}
} catch (error) {
setStatus('error');
- setMessage('Staking failed.');
+ setMessage(error.message || 'Staking failed.');
console.error('Staking failed', error);
} finally {
setLoading(false);
@@ -220,125 +178,218 @@ function UserAssets() {
const handleStakeAmountChange = (e) => {
const value = e.target.value;
- if (isSwitched && parseFloat(value) > parseFloat(stakedBalance)) {
- alert('Unstake amount exceeds your staked balance');
- } else if (!isSwitched && parseFloat(value) > parseFloat(walletBalance)) {
- alert('Amount exceeds wallet balance');
+ setStakeAmount(value);
+ };
+ // handle increment and decrement of vote value
+ // todo: for mainnet, ensure vote value is clamped to contract min/max
+ const handleIncrement = () => {
+ setVoteValue((prevValue) => Math.min(prevValue + 1, 100));
+ };
+
+ const handleDecrement = () => {
+ setVoteValue((prevValue) => Math.max(prevValue - 1, 1));
+ };
+
+ const handleVote = async () => {
+ if (!XeonStakingPool || voteValue < 1 || voteValue > 100) {
+ setMessage('Please enter a value between 1 and 100');
+ return;
+ }
+
+ setLoading(true);
+ onOpen();
+
+ try {
+ const tx = await XeonStakingPool.voteForBuybackPercentage(voteValue);
+ await tx.wait();
+ setLoading(false);
+ setMessage(`Vote successful for ${voteValue}% buyback`);
+ } catch (error) {
+ console.error('Vote failed', error);
+ setLoading(false);
+ setMessage('Vote failed, please try again.');
+ }
+ };
+
+ // handle vote value change
+ const handleVoteChange = (e) => {
+ const value = parseInt(e.target.value);
+ if (Number.isNaN(value)) {
+ setVoteValue(1);
} else {
- setStakeAmount(value);
+ setVoteValue(Math.min(Math.max(value, 1), 100));
}
};
return (
-
-
-
-
-
- {isSwitched ? 'Unstaking mode' : 'Staking mode'}
-
-
-
- {isSwitched ? 'Unstake Tokens' : 'Stake Tokens'}
+
+
+
+ {isSwitched ? 'Unstake' : 'Stake'}
- {isSwitched ? (
-
-
-
-
- {loading ? : 'Unstake'}
-
-
-
- ) : (
-
-
-
+
+ {isSwitched ? (
+
+
+
+
+
+ Staked: {stakedBalance} $XEON
+
+
-
-
- {loading ? : buttonText}
-
+
+
+ Wallet: {walletBalance} $XEON
+
+
+
+
+
+
+
+
+ {loading ? : 'Unstake'}
+
+
+
+
+
+
-
-
- )}
-
+
+ ) : (
+
+
+
+
+
+ Staked: {stakedBalance} $XEON
+
+
+
+
+
+ Wallet: {walletBalance} $XEON
+
+
+
+
+
-
-
-
-
-
-
- {wallet?.address.slice(0, 6) +
- '...' +
- wallet?.address.slice(-4)}
+
+
+ {loading ? : buttonText}
+
+
+
+
+
+
+
+
+ )}
+
+
+
+
+
+
Settle
+
+
+ Close expired positions and collect fess into the staking pool
+
+
+ Settle
+
+
+
+
+ $XEON Buyback
+
+
+
+ What percentage of protocol revenue should be used to buyback
+ $XEON token?
+
+
+
+ -
+
-
-
-
-
-
Staked
-
-
$XEON {stakedBalance}
-
-
+
-
-
Wallet
-
-
$XEON {walletBalance}
-
+
+ +
+
+
+ Vote
+
+
+ Current Buyback Percentage: {currentPercentage}%
+