From 557b6543caecc4dfdde8a171725992d2950558ba Mon Sep 17 00:00:00 2001 From: Zak Date: Thu, 31 Oct 2024 13:26:22 +0000 Subject: [PATCH 1/4] feat: move to legacy WIP --- src/App.css | 8 +- src/App.jsx | 6 +- .../tst-staking/ClaimingRewardsModal.jsx | 182 ++++++++++ src/components/tst-staking/StakingAssets.jsx | 112 ++++++ .../tst-staking/StakingDecreaseModal.jsx | 292 +++++++++++++++ .../tst-staking/StakingIncrease.jsx | 335 ++++++++++++++++++ src/components/tst-staking/StakingRewards.jsx | 194 ++++++++++ src/components/ui/SideNav.jsx | 43 +-- src/pages/legacy-pools/LegacyPools.jsx | 63 ++++ src/pages/tst-staking/TstStaking.jsx | 184 ++++++++++ 10 files changed, 1394 insertions(+), 25 deletions(-) create mode 100644 src/components/tst-staking/ClaimingRewardsModal.jsx create mode 100644 src/components/tst-staking/StakingAssets.jsx create mode 100644 src/components/tst-staking/StakingDecreaseModal.jsx create mode 100644 src/components/tst-staking/StakingIncrease.jsx create mode 100644 src/components/tst-staking/StakingRewards.jsx create mode 100644 src/pages/legacy-pools/LegacyPools.jsx create mode 100644 src/pages/tst-staking/TstStaking.jsx diff --git a/src/App.css b/src/App.css index 11169d4..78b7344 100644 --- a/src/App.css +++ b/src/App.css @@ -605,7 +605,9 @@ button.btn.btn-success:not(:disabled) { } .btn.btn-primary:hover, -button.btn.btn-primary:hover { +button.btn.btn-primary:hover, +.btn.btn-primary.active, +button.btn.btn-primary.active { color: rgb(var(--btn-solid-color)); background: rgba(var(--primary-color), 1); box-shadow: var(--btn-solid-outline-hover), @@ -667,7 +669,9 @@ button.btn.btn-outline:not(:disabled) { } .btn.btn-outline:hover, -button.btn.btn-outline:hover { +button.btn.btn-outline:hover, +.btn.btn-outline.active, +button.btn.btn-outline.active { color: var(--alt-btn-txt-color); background: rgba(255,255,255, 0.1); box-shadow: var(--btn-outline-outline-hover), diff --git a/src/App.jsx b/src/App.jsx index fd891e8..cb1470a 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -10,7 +10,8 @@ import Vaults from './pages/vaults/Vaults'; import Vault from './pages/vault/Vault'; import VaultHistory from './pages/vault/VaultHistory'; import LiquidationPools from './pages/liquidation-pools/LiquidationPools'; -import StakingPool from './pages/staking-pool/StakingPool'; +import TstStaking from './pages/tst-staking/TstStaking'; +import LegacyPools from './pages/legacy-pools/LegacyPools'; import TermsOfUse from './pages/TermsOfUse'; import Dex from './pages/dex/Dex'; @@ -30,8 +31,9 @@ function App() { } /> } /> } /> + } /> } /> - } /> + } /> } /> } /> } /> diff --git a/src/components/tst-staking/ClaimingRewardsModal.jsx b/src/components/tst-staking/ClaimingRewardsModal.jsx new file mode 100644 index 0000000..ad9d7c4 --- /dev/null +++ b/src/components/tst-staking/ClaimingRewardsModal.jsx @@ -0,0 +1,182 @@ +import { useState, useEffect, useRef } from "react"; +import { + useWriteContract, + useChainId, +} from "wagmi"; +import { arbitrumSepolia } from "wagmi/chains"; +import { toast } from 'react-toastify'; + +import { + useStakingPoolv2AddressStore, + useStakingPoolv2AbiStore +} from "../../store/Store"; + +import Button from "../ui/Button"; +import Modal from "../ui/Modal"; +import Typography from "../ui/Typography"; +import CenterLoader from "../ui/CenterLoader"; +import Checkbox from "../ui/Checkbox"; + +const ClaimingRewardsModal = ({ + isOpen, + handleCloseModal, +}) => { + const { + arbitrumSepoliaStakingPoolv2Address, + arbitrumStakingPoolv2Address, + } = useStakingPoolv2AddressStore(); + const { stakingPoolv2Abi } = useStakingPoolv2AbiStore(); + const [claimLoading, setClaimLoading] = useState(false); + const [showError, setShowError] = useState(false); + const [compound, setCompound] = useState(false); + const chainId = useChainId(); + + const stakingPoolv2Address = chainId === arbitrumSepolia.id ? arbitrumSepoliaStakingPoolv2Address : + arbitrumStakingPoolv2Address; + + const { writeContract, isError, isPending, isSuccess, error } = useWriteContract(); + + const handleApproveClaim = async () => { + try { + writeContract({ + abi: stakingPoolv2Abi, + address: stakingPoolv2Address, + functionName: "claim", + args: [compound], + }); + } catch (error) { + let errorMessage = ''; + if (error && error.shortMessage) { + errorMessage = error.shortMessage; + } + toast.error(errorMessage || 'There was an error'); + } + }; + + useEffect(() => { + if (isPending) { + setClaimLoading(true); + } else if (isSuccess) { + toast.success('Success!'); + setClaimLoading(false); + handleCloseModal(); + } else if (isError) { + setShowError(true) + setClaimLoading(false); + } + }, [ + isPending, + isSuccess, + isError, + error, + ]); + + if (showError) { + return ( + <> + { + setShowError(false); + handleCloseModal(); + }} + > + <> + {claimLoading ? ( + <> + + Claiming Your Rewards + + + + ) : ( + <> +
+ + Reward Claim Unsuccessful + + + There was a problem processing your reward claim request. + +
+ + + + + )} + +
+ + ) + } + + return ( + <> + { + handleCloseModal(); + }} + > + <> + {claimLoading ? ( + <> + + Claiming Your Rewards + + + + ) : ( + <> +
+ + Claim Your Rewards + + + Claiming your rewards will end your current staking period and restart a new one. + + + By opting to compound your EUROs rewards, those EUROs will be added to the EUROs in your new stake. + +
+ setCompound(!compound)} + label="I would like to compound my EUROs rewards" + /> +
+
+ + + + )} + +
+ + ) +}; + +export default ClaimingRewardsModal; \ No newline at end of file diff --git a/src/components/tst-staking/StakingAssets.jsx b/src/components/tst-staking/StakingAssets.jsx new file mode 100644 index 0000000..264eafb --- /dev/null +++ b/src/components/tst-staking/StakingAssets.jsx @@ -0,0 +1,112 @@ +import { useState } from "react"; + +import { ethers } from "ethers"; + +import Button from "../ui/Button"; +import Card from "../ui/Card"; +import Typography from "../ui/Typography"; +import CenterLoader from "../ui/CenterLoader"; + +import StakingDecreaseModal from "./StakingDecreaseModal"; + +const StakingAssets = ({ + positions, +}) => { + const [open, setOpen] = useState(false); + + if (!positions) { + return ( + +
+ +
+
+ ) + } + + const tstAmount = positions[1] || 0; + const eurosAmount = positions[2] || 0; + + const useRows = [ + { + asset: 'TST', + amount: tstAmount || 0 + }, + { + asset: 'EUROs', + amount: eurosAmount || 0 + }, + ] + + const handleCloseModal = () => { + setOpen(false) + }; + + const rows = useRows || []; + + let noStaked = true; + if (rows.some(e => e.amount > 0)) { + noStaked = false; + } + + return ( + +
+ + Staked Assets + + +
+ + + + + + + + {!positions ? (null) : ( + + {rows.map(function(asset, index) { + const amount = asset?.amount; + const decimals = asset?.dec; + const symbol = asset?.asset; + + return( + + + + + )} + )} + + )} +
AssetAmount
+ {symbol} + + {ethers.formatUnits(amount, decimals)} +
+ {!positions ? ( + + ) : (null)} +
+ +
+ +
+ +
+
+ ) +}; + +export default StakingAssets; diff --git a/src/components/tst-staking/StakingDecreaseModal.jsx b/src/components/tst-staking/StakingDecreaseModal.jsx new file mode 100644 index 0000000..415383e --- /dev/null +++ b/src/components/tst-staking/StakingDecreaseModal.jsx @@ -0,0 +1,292 @@ +import { useState, useEffect, useRef } from "react"; +import { toast } from 'react-toastify'; + +import { + useWriteContract, + useChainId, +} from "wagmi"; +import { arbitrumSepolia } from "wagmi/chains"; +import { formatEther, parseEther } from "viem"; + +import { + useStakingPoolv2AddressStore, + useStakingPoolv2AbiStore +} from "../../store/Store"; + +import Button from "../ui/Button"; +import Modal from "../ui/Modal"; +import Typography from "../ui/Typography"; +import Input from "../ui/Input"; +import CenterLoader from "../ui/CenterLoader"; + +const StakingDecreaseModal = ({ + stakedPositions, + isOpen, + handleCloseModal, +}) => { + const { + arbitrumSepoliaStakingPoolv2Address, + arbitrumStakingPoolv2Address, + } = useStakingPoolv2AddressStore(); + const { stakingPoolv2Abi } = useStakingPoolv2AbiStore(); + const [claimLoading, setClaimLoading] = useState(false); + const [showError, setShowError] = useState(false); + const [tstWithdrawAmount, setTstWithdrawAmount] = useState(0); + const [eurosWithdrawAmount, setEurosWithdrawAmount] = useState(0); + const chainId = useChainId(); + + const tstInputRef = useRef(null); + const eurosInputRef = useRef(null); + + const tstPosition = stakedPositions?.find((item) => item.asset === 'TST'); + const eurosPosition = stakedPositions?.find((item) => item.asset === 'EUROs'); + + const tstStakedAmount = tstPosition?.amount; + const eurosStakedAmount = eurosPosition?.amount; + + const useTstStakedAmount = formatEther(tstStakedAmount.toString()); + const useEurosStakedAmount = formatEther(eurosStakedAmount.toString()); + + const stakingPoolv2Address = chainId === arbitrumSepolia.id ? arbitrumSepoliaStakingPoolv2Address : + arbitrumStakingPoolv2Address; + + const { writeContract, isError, isPending, isSuccess, error } = useWriteContract(); + + const handleApproveWithdraw = async () => { + try { + writeContract({ + abi: stakingPoolv2Abi, + address: stakingPoolv2Address, + functionName: "decreaseStake", + args: [ + tstWithdrawAmount, + eurosWithdrawAmount, + ], + }); + } catch (error) { + let errorMessage = ''; + if (error && error.shortMessage) { + errorMessage = error.shortMessage; + } + toast.error(errorMessage || 'There was a problem'); + } + }; + + useEffect(() => { + if (isPending) { + setClaimLoading(true); + } else if (isSuccess) { + toast.success('Success!'); + setClaimLoading(false); + setTstWithdrawAmount(0); + setEurosWithdrawAmount(0); + handleCloseModal(); + } else if (isError) { + setShowError(true) + setClaimLoading(false); + setTstWithdrawAmount(0); + setEurosWithdrawAmount(0); + } + }, [ + isPending, + isSuccess, + isError, + error, + ]); + + const handleTstAmount = (e) => { + if (Number(e.target.value) < 10n ** 21n) { + setTstWithdrawAmount(parseEther(e.target.value.toString())); + } + }; + + const handleTstInputMax = () => { + const formatBalance = formatEther(tstStakedAmount); + tstInputRef.current.value = formatBalance; + handleTstAmount({target: {value: formatBalance}}); + } + + const handleEurosAmount = (e) => { + if (Number(e.target.value) < 10n ** 21n) { + setEurosWithdrawAmount(parseEther(e.target.value.toString())); + } + }; + + const handleEurosInputMax = () => { + const formatBalance = formatEther(eurosStakedAmount); + eurosInputRef.current.value = formatBalance; + handleEurosAmount({target: {value: formatBalance}}); + } + + if (showError) { + return ( + <> + { + setShowError(false); + handleCloseModal(); + }} + > +
+ {claimLoading ? ( + <> + + Withdrawing Your Tokens + + + + ) : ( + <> +
+ + Withdraw Unsuccessful + + + There was a problem processing your withdraw request. + + + It is possible that your withdraw request exceeds the amount of tokens you have staked. + +
+ +
+ + +
+ + )} +
+
+ + ) + } + + return ( + <> + { + handleCloseModal(); + }} + > + <> + {claimLoading ? ( + <> + + Claiming Your Rewards + + + + ) : ( + <> +
+ + Withdraw Your Tokens + + + Here you can reduce your position by withdrawing your tokens. + + + Any withdrawals will automatically claim your existing rewards, ending your current staking period and restarting a new one. + +
+
+ +
+ + Available TST: + + + {useTstStakedAmount || '0'} + +
+
+ + Available EUROs: + + + {useEurosStakedAmount || '0'} + +
+ +
+ + + Withdraw Amounts: + +
+ + +
+
+ + +
+ + + + )} + +
+ + ) +}; + +export default StakingDecreaseModal; diff --git a/src/components/tst-staking/StakingIncrease.jsx b/src/components/tst-staking/StakingIncrease.jsx new file mode 100644 index 0000000..62659a6 --- /dev/null +++ b/src/components/tst-staking/StakingIncrease.jsx @@ -0,0 +1,335 @@ +import { useRef, useState, useEffect } from "react"; +import { toast } from 'react-toastify'; + +import { + useAccount, + useReadContracts, + useWriteContract, + useChainId, + useWatchBlockNumber, +} from "wagmi"; +import { arbitrumSepolia } from "wagmi/chains"; +import { ethers } from "ethers"; + +import { + useTstAddressStore, + useErc20AbiStore, + usesEuroAddressStore, + useStakingPoolv2AbiStore, + useStakingPoolv2AddressStore, +} from "../../store/Store.jsx"; + +import Card from "../ui/Card"; +import Typography from "../ui/Typography"; +import Button from "../ui/Button"; +import Input from "../ui/Input"; + +const StakingIncrease = () => { + const chainId = useChainId(); + const { + arbitrumTstAddress, + arbitrumSepoliaTstAddress, + } = useTstAddressStore(); + const { + arbitrumsEuroAddress, + arbitrumSepoliasEuroAddress, + } = usesEuroAddressStore(); + const { + arbitrumSepoliaStakingPoolv2Address, + arbitrumStakingPoolv2Address, + } = useStakingPoolv2AddressStore(); + const { address } = useAccount(); + const { erc20Abi } = useErc20AbiStore(); + const { stakingPoolv2Abi } = useStakingPoolv2AbiStore(); + const [tstStakeAmount, setTstStakeAmount] = useState(0); + const [eurosStakeAmount, setEurosStakeAmount] = useState(0); + const [stage, setStage] = useState(''); + const [helpOpen, setHelpOpen] = useState(false); + + const tstInputRef = useRef(null); + const eurosInputRef = useRef(null); + + const tstAddress = chainId === arbitrumSepolia.id ? + arbitrumSepoliaTstAddress : + arbitrumTstAddress; + + const eurosAddress = chainId === arbitrumSepolia.id ? + arbitrumSepoliasEuroAddress : + arbitrumsEuroAddress; + + const stakingPoolv2Address = chainId === arbitrumSepolia.id ? arbitrumSepoliaStakingPoolv2Address : + arbitrumStakingPoolv2Address; + + const tstContract = { + address: tstAddress, + abi: erc20Abi, + } + + const { data: tstData, refetch: refetchTst } = useReadContracts({ + contracts: [{ + ... tstContract, + functionName: "allowance", + args: [address, stakingPoolv2Address] + },{ + ... tstContract, + functionName: "balanceOf", + args: [address] + }], + }); + + const eurosContract = { + address: eurosAddress, + abi: erc20Abi, + } + + const { data: eurosData, refetch: refetchEuros } = useReadContracts({ + contracts: [{ + ... eurosContract, + functionName: "allowance", + args: [address, stakingPoolv2Address] + },{ + ... eurosContract, + functionName: "balanceOf", + args: [address] + }], + }); + + useWatchBlockNumber({ + onBlockNumber() { + refetchTst(); + refetchEuros(); + }, + }) + + const existingTstAllowance = tstData && tstData[0].result; + const tstBalance = tstData && tstData[1].result; + + const existingEurosAllowance = eurosData && eurosData[0].result; + const eurosBalance = eurosData && eurosData[1].result; + + const { writeContract, isError, isPending, isSuccess, error } = useWriteContract(); + + const handleApproveTst = async () => { + setStage('APPROVE_TST'); + try { + writeContract({ + abi: erc20Abi, + address: tstAddress, + functionName: "approve", + args: [stakingPoolv2Address, tstStakeAmount], + }); + } catch (error) { + let errorMessage = ''; + if (error && error.shortMessage) { + errorMessage = error.shortMessage; + } + toast.error(errorMessage || 'There was a problem'); + } + }; + + const handleApproveEuros = async () => { + setStage('APPROVE_EUROS'); + setTimeout(() => { + try { + writeContract({ + abi: erc20Abi, + address: eurosAddress, + functionName: "approve", + args: [stakingPoolv2Address, eurosStakeAmount], + }); + + } catch (error) { + let errorMessage = ''; + if (error && error.shortMessage) { + errorMessage = error.shortMessage; + } + toast.error(errorMessage || 'There was a problem'); + } + }, 1000); + }; + + const handleDepositToken = async () => { + setStage('DEPOSIT_TOKEN'); + setTimeout(() => { + try { + writeContract({ + abi: stakingPoolv2Abi, + address: stakingPoolv2Address, + functionName: "increaseStake", + args: [ + tstStakeAmount, + eurosStakeAmount + ], + }); + } catch (error) { + let errorMessage = ''; + if (error && error.shortMessage) { + errorMessage = error.shortMessage; + } + toast.error(errorMessage || 'There was a problem'); + } + }, 1000); + }; + + const handleLetsStake = async () => { + if (existingTstAllowance < tstStakeAmount) { + handleApproveTst(); + } else { + if (existingEurosAllowance < eurosStakeAmount) { + handleApproveEuros(); + } else { + handleDepositToken(); + } + } + }; + + useEffect(() => { + if (stage === 'APPROVE_TST') { + if (isPending) { + // + } else if (isSuccess) { + setStage(''); + toast.success('TST Approved'); + handleApproveEuros(); + } else if (isError) { + setStage(''); + toast.error('There was a problem'); + } + } + if (stage === 'APPROVE_EUROS') { + if (isPending) { + // + } else if (isSuccess) { + setStage(''); + toast.success('EUROs Approved'); + handleDepositToken(); + } else if (isError) { + setStage(''); + toast.error('There was a problem'); + } + } + if (stage === 'DEPOSIT_TOKEN') { + if (isPending) { + // + } else if (isSuccess) { + setStage(''); + toast.success('Deposited Successfully!'); + eurosInputRef.current.value = ""; + tstInputRef.current.value = ""; + setTstStakeAmount(0); + setEurosStakeAmount(0); + } else if (isError) { + setStage(''); + toast.error('There was a problem'); + eurosInputRef.current.value = ""; + tstInputRef.current.value = ""; + setTstStakeAmount(0); + setEurosStakeAmount(0); + } + } + }, [ + isPending, + isSuccess, + isError, + error + ]); + + const handleTstAmount = (e) => { + if (Number(e.target.value) < 10n ** 21n) { + setTstStakeAmount(ethers.parseEther(e.target.value.toString())); + } + }; + + const handleTstInputMax = () => { + const formatBalance = ethers.formatEther(tstBalance); + tstInputRef.current.value = formatBalance; + handleTstAmount({target: {value: formatBalance}}); + } + + const handleEurosAmount = (e) => { + if (Number(e.target.value) < 10n ** 21n) { + setEurosStakeAmount(ethers.parseEther(e.target.value.toString())); + } + }; + + const handleEurosInputMax = () => { + const formatBalance = ethers.formatEther(eurosBalance); + eurosInputRef.current.value = formatBalance; + handleEurosAmount({target: {value: formatBalance}}); + } + + return ( + <> + +
+ + Deposit + + + Increase your TST position to earn EUROs rewards, and increase your EUROs position to earn an assortment of other tokens. + + + Depositing will automatically claim your existing rewards & compound any EUROs, ending your current staking period and restarting a new one. + +
+
+ + TST Deposit Amount: + +
+ + +
+ + EUROs Deposit Amount: + +
+ + +
+
+ +
+
+
+
+ + ); +}; + +export default StakingIncrease; \ No newline at end of file diff --git a/src/components/tst-staking/StakingRewards.jsx b/src/components/tst-staking/StakingRewards.jsx new file mode 100644 index 0000000..bfab1a9 --- /dev/null +++ b/src/components/tst-staking/StakingRewards.jsx @@ -0,0 +1,194 @@ +import { useState } from "react"; +import { ethers } from "ethers"; +import { + useReadContracts, +} from "wagmi"; + +import { + useErc20AbiStore, +} from "../../store/Store"; + +import Button from "../ui/Button"; +import Card from "../ui/Card"; +import Typography from "../ui/Typography"; +import CenterLoader from "../ui/CenterLoader"; + +import ClaimingRewardsModal from "./ClaimingRewardsModal"; + +const StakingRewards = ({ + stakedSince, + rewardRate, + sEuroAmount, + collaterals, + poolRewardsLoading, + sEuroDaily, + collatDaily, +}) => { + const [open, setOpen] = useState(false); + const { erc20Abi } = useErc20AbiStore(); + + if (poolRewardsLoading) { + return ( + +
+ +
+
+ ) + } + + const { data: rewardDecimals } = useReadContracts({ + contracts:collaterals.map((item) =>({ + address: item.token, + abi: erc20Abi, + functionName: "decimals", + args: [], + })) + }) + + const { data: rewardSymbols } = useReadContracts({ + contracts:collaterals.map((item) =>({ + address: item.token, + abi: erc20Abi, + functionName: "symbol", + args: [], + })) + }) + + const rewardData = collaterals?.map((item, index) => { + const amount = item.amount; + let decimals = 18; + if (rewardDecimals) { + if (rewardDecimals[index]) { + if (rewardDecimals[index].result) { + decimals = rewardDecimals[index].result; + } + } + } + let symbol = 'ETH'; + if (rewardSymbols) { + if (rewardSymbols[index]) { + if (rewardSymbols[index].result) { + symbol = rewardSymbols[index].result; + } + } + } + let useDailyReward = 0n; + + const rewardItem = collatDaily?.find((reward) => reward.token === item.token); + + if (rewardItem && rewardItem.amount) { + useDailyReward = rewardItem.amount; + } + + return { + key: index, + asset: symbol, + amount: amount, + decimals: decimals, + dailyReward: useDailyReward, + } + }); + + const useRows = [ + { + key: 'EUROs', + asset: 'EUROs', + amount: sEuroAmount, + decimals: 18, + dailyReward: sEuroDaily, + }, + ...rewardData + ] + + const handleCloseModal = () => { + setOpen(false) + }; + + const rows = useRows || []; + + let noRewards = true; + if (rows.some(e => e.amount > 0)) { + noRewards = false; + } + + return ( + +
+ + Projected Rewards + +
+ + You can earn rewards every 24 hours after your staking period begins. + + + Your reward rates are based on a the number of tokens you have staked. + + {stakedSince ? ( + + Staked Since: + {stakedSince} + + ) : null} +
+ +
+ + + + + + + + + {poolRewardsLoading ? (null) : ( + + {rows.map(function(asset, index) { + const amount = asset?.amount; + const decimals = asset?.decimals; + const symbol = asset?.asset; + const dailyReward = asset?.dailyReward; + + return( + + + + + + )} + )} + + )} +
AssetAmountDaily Reward Per Token
+ {symbol} + + {ethers.formatUnits(amount, decimals)} + + {ethers.formatUnits(dailyReward, decimals)} + / {symbol === 'EUROs' ? ('TST') : ('EUROs')} +
+ {poolRewardsLoading ? ( + + ) : (null)} +
+ +
+ +
+ +
+
+ ) +}; + +export default StakingRewards; diff --git a/src/components/ui/SideNav.jsx b/src/components/ui/SideNav.jsx index a1b8043..d516600 100644 --- a/src/components/ui/SideNav.jsx +++ b/src/components/ui/SideNav.jsx @@ -8,7 +8,8 @@ import { BanknotesIcon, XMarkIcon, Square3Stack3DIcon, - ArrowPathRoundedSquareIcon + ArrowPathRoundedSquareIcon, + ArchiveBoxIcon } from '@heroicons/react/24/outline'; import { @@ -82,30 +83,30 @@ const SideNav = (props) => { isActive || - location.pathname.includes('/liquidation-pools') ? + location.pathname.includes('/dex') ? 'navbar-item active' : 'navbar-item' } > - - - Liquidation Pools - + + Cross-Chain Dex isActive || - location.pathname.includes('/dex') ? + location.pathname.includes('/legacy-pools') ? 'navbar-item active' : 'navbar-item' } > - - Cross-Chain Dex + + + Legacy Pools + @@ -154,40 +155,40 @@ const SideNav = (props) => { isActive || - location.pathname.includes('/liquidation-pools') ? + location.pathname.includes('/dex') ? 'navbar-item active' : 'navbar-item' } > - + - Liquidation Pools + Cross-Chain Dex isActive || - location.pathname.includes('/dex') ? + location.pathname.includes('/legacy-pools') ? 'navbar-item active' : 'navbar-item' } > - + - Cross-Chain Dex + Legacy Pools diff --git a/src/pages/legacy-pools/LegacyPools.jsx b/src/pages/legacy-pools/LegacyPools.jsx new file mode 100644 index 0000000..071d542 --- /dev/null +++ b/src/pages/legacy-pools/LegacyPools.jsx @@ -0,0 +1,63 @@ +import { useState } from "react"; + +import LiquidationPools from '../liquidation-pools/LiquidationPools'; +import StakingPool from '../staking-pool/StakingPool'; + +import Card from "../../components/ui/Card"; +import Typography from "../../components/ui/Typography"; +import Button from "../../components/ui/Button"; + +const LegacyPools = (props) => { + const [ showPool, setShowPool ] = useState('STAKE-EUROSTST'); + + return ( +
+ + +
+ + Legacy Pools + + + + These pools have been depreciated and will no longer be generating new rewards. + + + + We recommend collecting any outstanding rewards and withdrawing your staked tokens. + + +
+ + +
+ + +
+
+ +
+ {showPool === 'STAKE-EUROSTST' ? ( + + ) : (null)} + {showPool === 'LIQUIDITY-POOL' ? ( + + ) : (null)} +
+ +
+ ); +}; + +export default LegacyPools; \ No newline at end of file diff --git a/src/pages/tst-staking/TstStaking.jsx b/src/pages/tst-staking/TstStaking.jsx new file mode 100644 index 0000000..a5fb0f1 --- /dev/null +++ b/src/pages/tst-staking/TstStaking.jsx @@ -0,0 +1,184 @@ +import { useState } from "react"; +import moment from 'moment'; +import { + useReadContract, + useAccount, + useChainId, + useWatchBlockNumber +} from "wagmi"; +import { arbitrumSepolia } from "wagmi/chains"; +import { + ArrowTrendingUpIcon, + BanknotesIcon, + Square3Stack3DIcon, +} from '@heroicons/react/24/outline'; + +import { + useStakingPoolv2AbiStore, + useStakingPoolv2AddressStore, +} from "../../store/Store"; + +import StakingIncrease from "../../components/tst-staking/StakingIncrease"; +import StakingAssets from "../../components/tst-staking/StakingAssets"; +import StakingRewards from "../../components/tst-staking/StakingRewards"; + +import Card from "../../components/ui/Card"; +import CenterLoader from "../../components/ui/CenterLoader"; +import Typography from "../../components/ui/Typography"; +import Button from "../../components/ui/Button"; + +const TstStaking = (props) => { + const { stakingPoolv2Abi } = useStakingPoolv2AbiStore(); + const [showValue, setShowValue] = useState(false); + + const { + arbitrumSepoliaStakingPoolv2Address, + arbitrumStakingPoolv2Address, + } = useStakingPoolv2AddressStore(); + + const { address } = useAccount(); + const chainId = useChainId(); + + const stakingPoolv2Address = + chainId === arbitrumSepolia.id + ? arbitrumSepoliaStakingPoolv2Address + : arbitrumStakingPoolv2Address; + + const { data: poolPositions, refetch: refetchPositions } = useReadContract({ + address: stakingPoolv2Address, + abi: stakingPoolv2Abi, + functionName: "positions", + args: [address], + }); + + const { data: poolRewards, isLoading: poolRewardsLoading, refetch: refetchRewards } = useReadContract({ + address: stakingPoolv2Address, + abi: stakingPoolv2Abi, + functionName: "projectedEarnings", + args: [address], + }); + + const { data: dailyYield, refetch: refetchDailyReward } = useReadContract({ + address: stakingPoolv2Address, + abi: stakingPoolv2Abi, + functionName: "dailyYield", + args: [], + }); + + useWatchBlockNumber({ + onBlockNumber() { + refetchPositions(); + refetchRewards(); + refetchDailyReward(); + }, + }) + + const positions = poolPositions; + const rewards = poolRewards; + const dailyRewards = dailyYield; + + + let sEuroAmount = 0n; + let collaterals = []; + + if (rewards && rewards[0]) { + sEuroAmount = rewards[0] || 0n; + } + if (rewards && rewards[1]) { + collaterals = rewards[1] || []; + } + + let sEuroDaily = 0n; + let collatDaily = []; + + if (dailyRewards && dailyRewards[0]) { + sEuroDaily = dailyRewards[0] || 0n; + } + if (dailyRewards && dailyRewards[1]) { + collatDaily = dailyRewards[1] || []; + } + + let stakedSince = 0; + if (positions && positions[0]) { + stakedSince = positions[0] || 0; + } + + let useStakedSince; + if (stakedSince) { + useStakedSince = moment.unix(Number(stakedSince)).format('Do MMM YYYY'); + } + + return ( + <> + +
+ + + Staking Pool + + + + These pools have been depreciated and will no longer be generating new rewards. + + + + We recommend collecting any outstanding rewards and withdrawing your staked tokens. + + +
+ + +
+ + +
+
+ +
+ +
+ +
+ +
+ +
+ +
+ {poolRewardsLoading ? ( + +
+ +
+
+ ) : ( + + )} +
+ +
+ + + ); +}; + +export default TstStaking; \ No newline at end of file From 8ac9f906adaaf4dc47e3befa65b05cfe8383a565 Mon Sep 17 00:00:00 2001 From: Zak Date: Thu, 31 Oct 2024 14:52:00 +0000 Subject: [PATCH 2/4] feat: remove unused from legacy pools --- src/pages/legacy-pools/LegacyPools.jsx | 3 +- .../liquidation-pools/LiquidationPools.jsx | 74 ------------------- src/pages/staking-pool/StakingPool.jsx | 52 +------------ 3 files changed, 3 insertions(+), 126 deletions(-) diff --git a/src/pages/legacy-pools/LegacyPools.jsx b/src/pages/legacy-pools/LegacyPools.jsx index 071d542..128d413 100644 --- a/src/pages/legacy-pools/LegacyPools.jsx +++ b/src/pages/legacy-pools/LegacyPools.jsx @@ -31,13 +31,14 @@ const LegacyPools = (props) => { diff --git a/src/pages/liquidation-pools/LiquidationPools.jsx b/src/pages/liquidation-pools/LiquidationPools.jsx index 8f3af1c..ccadfdd 100644 --- a/src/pages/liquidation-pools/LiquidationPools.jsx +++ b/src/pages/liquidation-pools/LiquidationPools.jsx @@ -5,12 +5,7 @@ import { useChainId, useWatchBlockNumber } from "wagmi"; -import axios from "axios"; import { arbitrumSepolia } from "wagmi/chains"; -import { - ArrowTrendingUpIcon, - BanknotesIcon, -} from '@heroicons/react/24/outline'; import { useLiquidationPoolAbiStore, @@ -19,11 +14,6 @@ import { import StakedAssets from "../../components/liquidation-pools/StakedAssets"; import ClaimTokens from "../../components/liquidation-pools/ClaimTokens"; -import VolumeChart from "../../components/liquidation-pools/VolumeChart"; -import ValueChart from "../../components/liquidation-pools/ValueChart"; -import Card from "../../components/ui/Card"; -import Typography from "../../components/ui/Typography"; -import Button from "../../components/ui/Button"; const LiquidationPools = () => { const [chartData, setChartData] = useState(undefined); @@ -60,37 +50,8 @@ const LiquidationPools = () => { const pending = liquidationPool && liquidationPool[1]; const rewards = liquidationPool && liquidationPool[2]; - const getChartData = async () => { - try { - const response = await axios.get( - `https://smart-vault-api.thestandard.io/liquidation_pools/${address}` - ); - setChartData(response?.data); - } catch (error) { - console.log(error); - } - }; - - useEffect(() => { - getChartData(); - }, []); - return ( <> - -
-
- - Changes With Earning Fees & New Staking Pool - - - With the recent release of our new & improved Staking Pool, from 17th June '24, we will be moving all earnable fees over to it. -
- The existing Liquidation Pool will continue to exist past this date so you can withdraw your staked assets and claim any outstanding rewards. -
-
-
-
{ rewards={rewards || []} />
-
- -
- - {showValue ? ( - 'Liquidation Pool Asset Value' - ) : ( - 'Liquidation Pool Asset Totals' - )} - - - {showValue ? ( - <> - - - ) : ( - <> - - - )} -
-
-
); diff --git a/src/pages/staking-pool/StakingPool.jsx b/src/pages/staking-pool/StakingPool.jsx index 09380d4..dbdbcc3 100644 --- a/src/pages/staking-pool/StakingPool.jsx +++ b/src/pages/staking-pool/StakingPool.jsx @@ -7,26 +7,17 @@ import { useWatchBlockNumber } from "wagmi"; import { arbitrumSepolia } from "wagmi/chains"; -import { - ArrowTrendingUpIcon, - BanknotesIcon, -} from '@heroicons/react/24/outline'; import { useStakingPoolv2AbiStore, useStakingPoolv2AddressStore, } from "../../store/Store"; -import StakingIncrease from "../../components/staking-pool/StakingIncrease"; import StakingAssets from "../../components/staking-pool/StakingAssets"; import StakingRewards from "../../components/staking-pool/StakingRewards"; -import VolumeChart from "../../components/staking-pool/VolumeChart"; -import ValueChart from "../../components/staking-pool/ValueChart"; import Card from "../../components/ui/Card"; import CenterLoader from "../../components/ui/CenterLoader"; -import Typography from "../../components/ui/Typography"; -import Button from "../../components/ui/Button"; const StakingPool = (props) => { const { stakingPoolv2Abi } = useStakingPoolv2AbiStore(); @@ -111,52 +102,12 @@ const StakingPool = (props) => { return (
-
- -
-
- -
- - {showValue ? ( - 'Asset Value' - ) : ( - 'Asset Totals' - )} - - - {showValue ? ( - <> - - - ) : ( - <> - - - )} -
-
-
- -
- {poolRewardsLoading ? ( + {poolRewardsLoading ? (
@@ -174,7 +125,6 @@ const StakingPool = (props) => { /> )}
-
); }; From 6fb11d9d0554f5ccf8570bdaefbff6c8a4d47699 Mon Sep 17 00:00:00 2001 From: Zak Date: Thu, 31 Oct 2024 15:50:32 +0000 Subject: [PATCH 3/4] feat: update abis and functions to just TST --- src/abis/stakingPoolV3.jsx | 130 +++++++++++++++ .../tst-staking/ClaimingRewardsModal.jsx | 34 ++-- src/components/tst-staking/StakingAssets.jsx | 5 - .../tst-staking/StakingDecreaseModal.jsx | 100 +++-------- .../tst-staking/StakingIncrease.jsx | 157 +++++------------- src/components/tst-staking/StakingRewards.jsx | 22 +-- src/pages/tst-staking/TstStaking.jsx | 80 +++------ src/store/Store.jsx | 18 ++ 8 files changed, 252 insertions(+), 294 deletions(-) create mode 100644 src/abis/stakingPoolV3.jsx diff --git a/src/abis/stakingPoolV3.jsx b/src/abis/stakingPoolV3.jsx new file mode 100644 index 0000000..52029fd --- /dev/null +++ b/src/abis/stakingPoolV3.jsx @@ -0,0 +1,130 @@ +export const abi = [ + { + "inputs": [], + "name": "claim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "dailyYield", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct StakingTST.Reward[]", + "name": "_rewards", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tst", + "type": "uint256" + } + ], + "name": "decreaseStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tst", + "type": "uint256" + } + ], + "name": "increaseStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "positions", + "outputs": [ + { + "internalType": "uint256", + "name": "start", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "TST", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_holder", + "type": "address" + } + ], + "name": "projectedEarnings", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct StakingTST.Reward[]", + "name": "_rewards", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "start", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] + +export default abi; \ No newline at end of file diff --git a/src/components/tst-staking/ClaimingRewardsModal.jsx b/src/components/tst-staking/ClaimingRewardsModal.jsx index ad9d7c4..1e7b3f0 100644 --- a/src/components/tst-staking/ClaimingRewardsModal.jsx +++ b/src/components/tst-staking/ClaimingRewardsModal.jsx @@ -7,42 +7,40 @@ import { arbitrumSepolia } from "wagmi/chains"; import { toast } from 'react-toastify'; import { - useStakingPoolv2AddressStore, - useStakingPoolv2AbiStore + useStakingPoolv3AddressStore, + useStakingPoolv3AbiStore } from "../../store/Store"; import Button from "../ui/Button"; import Modal from "../ui/Modal"; import Typography from "../ui/Typography"; import CenterLoader from "../ui/CenterLoader"; -import Checkbox from "../ui/Checkbox"; const ClaimingRewardsModal = ({ isOpen, handleCloseModal, }) => { const { - arbitrumSepoliaStakingPoolv2Address, - arbitrumStakingPoolv2Address, - } = useStakingPoolv2AddressStore(); - const { stakingPoolv2Abi } = useStakingPoolv2AbiStore(); + arbitrumSepoliaStakingPoolv3Address, + arbitrumStakingPoolv3Address, + } = useStakingPoolv3AddressStore(); + const { stakingPoolv3Abi } = useStakingPoolv3AbiStore(); const [claimLoading, setClaimLoading] = useState(false); const [showError, setShowError] = useState(false); - const [compound, setCompound] = useState(false); const chainId = useChainId(); - const stakingPoolv2Address = chainId === arbitrumSepolia.id ? arbitrumSepoliaStakingPoolv2Address : - arbitrumStakingPoolv2Address; + const stakingPoolv3Address = chainId === arbitrumSepolia.id ? arbitrumSepoliaStakingPoolv3Address : + arbitrumStakingPoolv3Address; const { writeContract, isError, isPending, isSuccess, error } = useWriteContract(); const handleApproveClaim = async () => { try { writeContract({ - abi: stakingPoolv2Abi, - address: stakingPoolv2Address, + abi: stakingPoolv3Abi, + address: stakingPoolv3Address, functionName: "claim", - args: [compound], + args: [], }); } catch (error) { let errorMessage = ''; @@ -148,16 +146,6 @@ const ClaimingRewardsModal = ({ Claiming your rewards will end your current staking period and restart a new one. - - By opting to compound your EUROs rewards, those EUROs will be added to the EUROs in your new stake. - -
- setCompound(!compound)} - label="I would like to compound my EUROs rewards" - /> -
-
- - -
diff --git a/src/components/tst-staking/StakingIncrease.jsx b/src/components/tst-staking/StakingIncrease.jsx index 62659a6..e4684db 100644 --- a/src/components/tst-staking/StakingIncrease.jsx +++ b/src/components/tst-staking/StakingIncrease.jsx @@ -15,8 +15,8 @@ import { useTstAddressStore, useErc20AbiStore, usesEuroAddressStore, - useStakingPoolv2AbiStore, - useStakingPoolv2AddressStore, + useStakingPoolv3AbiStore, + useStakingPoolv3AddressStore, } from "../../store/Store.jsx"; import Card from "../ui/Card"; @@ -35,30 +35,24 @@ const StakingIncrease = () => { arbitrumSepoliasEuroAddress, } = usesEuroAddressStore(); const { - arbitrumSepoliaStakingPoolv2Address, - arbitrumStakingPoolv2Address, - } = useStakingPoolv2AddressStore(); + arbitrumSepoliaStakingPoolv3Address, + arbitrumStakingPoolv3Address, + } = useStakingPoolv3AddressStore(); const { address } = useAccount(); const { erc20Abi } = useErc20AbiStore(); - const { stakingPoolv2Abi } = useStakingPoolv2AbiStore(); + const { stakingPoolv3Abi } = useStakingPoolv3AbiStore(); const [tstStakeAmount, setTstStakeAmount] = useState(0); - const [eurosStakeAmount, setEurosStakeAmount] = useState(0); const [stage, setStage] = useState(''); const [helpOpen, setHelpOpen] = useState(false); const tstInputRef = useRef(null); - const eurosInputRef = useRef(null); const tstAddress = chainId === arbitrumSepolia.id ? arbitrumSepoliaTstAddress : arbitrumTstAddress; - const eurosAddress = chainId === arbitrumSepolia.id ? - arbitrumSepoliasEuroAddress : - arbitrumsEuroAddress; - - const stakingPoolv2Address = chainId === arbitrumSepolia.id ? arbitrumSepoliaStakingPoolv2Address : - arbitrumStakingPoolv2Address; + const stakingPoolv3Address = chainId === arbitrumSepolia.id ? arbitrumSepoliaStakingPoolv3Address : + arbitrumStakingPoolv3Address; const tstContract = { address: tstAddress, @@ -69,7 +63,7 @@ const StakingIncrease = () => { contracts: [{ ... tstContract, functionName: "allowance", - args: [address, stakingPoolv2Address] + args: [address, stakingPoolv3Address] },{ ... tstContract, functionName: "balanceOf", @@ -77,36 +71,15 @@ const StakingIncrease = () => { }], }); - const eurosContract = { - address: eurosAddress, - abi: erc20Abi, - } - - const { data: eurosData, refetch: refetchEuros } = useReadContracts({ - contracts: [{ - ... eurosContract, - functionName: "allowance", - args: [address, stakingPoolv2Address] - },{ - ... eurosContract, - functionName: "balanceOf", - args: [address] - }], - }); - useWatchBlockNumber({ onBlockNumber() { refetchTst(); - refetchEuros(); }, }) const existingTstAllowance = tstData && tstData[0].result; const tstBalance = tstData && tstData[1].result; - const existingEurosAllowance = eurosData && eurosData[0].result; - const eurosBalance = eurosData && eurosData[1].result; - const { writeContract, isError, isPending, isSuccess, error } = useWriteContract(); const handleApproveTst = async () => { @@ -116,7 +89,7 @@ const StakingIncrease = () => { abi: erc20Abi, address: tstAddress, functionName: "approve", - args: [stakingPoolv2Address, tstStakeAmount], + args: [stakingPoolv3Address, tstStakeAmount], }); } catch (error) { let errorMessage = ''; @@ -127,38 +100,16 @@ const StakingIncrease = () => { } }; - const handleApproveEuros = async () => { - setStage('APPROVE_EUROS'); - setTimeout(() => { - try { - writeContract({ - abi: erc20Abi, - address: eurosAddress, - functionName: "approve", - args: [stakingPoolv2Address, eurosStakeAmount], - }); - - } catch (error) { - let errorMessage = ''; - if (error && error.shortMessage) { - errorMessage = error.shortMessage; - } - toast.error(errorMessage || 'There was a problem'); - } - }, 1000); - }; - const handleDepositToken = async () => { setStage('DEPOSIT_TOKEN'); setTimeout(() => { try { writeContract({ - abi: stakingPoolv2Abi, - address: stakingPoolv2Address, + abi: stakingPoolv3Abi, + address: stakingPoolv3Address, functionName: "increaseStake", args: [ tstStakeAmount, - eurosStakeAmount ], }); } catch (error) { @@ -175,11 +126,7 @@ const StakingIncrease = () => { if (existingTstAllowance < tstStakeAmount) { handleApproveTst(); } else { - if (existingEurosAllowance < eurosStakeAmount) { - handleApproveEuros(); - } else { - handleDepositToken(); - } + handleDepositToken(); } }; @@ -190,23 +137,11 @@ const StakingIncrease = () => { } else if (isSuccess) { setStage(''); toast.success('TST Approved'); - handleApproveEuros(); - } else if (isError) { - setStage(''); - toast.error('There was a problem'); - } - } - if (stage === 'APPROVE_EUROS') { - if (isPending) { - // - } else if (isSuccess) { - setStage(''); - toast.success('EUROs Approved'); handleDepositToken(); } else if (isError) { setStage(''); toast.error('There was a problem'); - } + } } if (stage === 'DEPOSIT_TOKEN') { if (isPending) { @@ -214,17 +149,13 @@ const StakingIncrease = () => { } else if (isSuccess) { setStage(''); toast.success('Deposited Successfully!'); - eurosInputRef.current.value = ""; tstInputRef.current.value = ""; setTstStakeAmount(0); - setEurosStakeAmount(0); } else if (isError) { setStage(''); toast.error('There was a problem'); - eurosInputRef.current.value = ""; tstInputRef.current.value = ""; setTstStakeAmount(0); - setEurosStakeAmount(0); } } }, [ @@ -246,16 +177,10 @@ const StakingIncrease = () => { handleTstAmount({target: {value: formatBalance}}); } - const handleEurosAmount = (e) => { - if (Number(e.target.value) < 10n ** 21n) { - setEurosStakeAmount(ethers.parseEther(e.target.value.toString())); - } - }; + let maxTst = 0; - const handleEurosInputMax = () => { - const formatBalance = ethers.formatEther(eurosBalance); - eurosInputRef.current.value = formatBalance; - handleEurosAmount({target: {value: formatBalance}}); + if (tstBalance) { + maxTst = ethers.formatEther(tstBalance.toString()); } return ( @@ -266,16 +191,29 @@ const StakingIncrease = () => { Deposit - Increase your TST position to earn EUROs rewards, and increase your EUROs position to earn an assortment of other tokens. + Increase your TST position to earn USDs & more rewards. - Depositing will automatically claim your existing rewards & compound any EUROs, ending your current staking period and restarting a new one. + Depositing will automatically claim your existing rewards, ending your current staking period and restarting a new one. -
- - TST Deposit Amount: - + {/* + TST Deposit Amount + */} +
+ + TST Deposit Amount + + + Available: {maxTst || '0'} + +
@@ -294,32 +232,11 @@ const StakingIncrease = () => { Max
- - EUROs Deposit Amount: - -
- - -
- -
- -
@@ -149,10 +125,9 @@ const TstStaking = (props) => {
-
- -
- +
+ +
@@ -166,13 +141,12 @@ const TstStaking = (props) => { )} +
diff --git a/src/store/Store.jsx b/src/store/Store.jsx index dae70f6..53b9331 100644 --- a/src/store/Store.jsx +++ b/src/store/Store.jsx @@ -7,6 +7,7 @@ import smartVaultV4ABI from "../abis/smartVaultV4"; import stakingAbi from "../abis/staking"; import liquidationPoolAbi from "../abis/liquidationPool"; import stakingPoolv2Abi from "../abis/stakingPoolV2"; +import stakingPoolv3Abi from "../abis/stakingPoolV3"; export const useCurrentWagmiConfig = create( (set) => ({ @@ -110,6 +111,15 @@ export const useStakingPoolv2AddressStore = create()( }) ); +export const useStakingPoolv3AddressStore = create()( + (set) => ({ + arbitrumStakingPoolv3Address: "0xA27A9F6Bac7f3C530EAF324Ae45F33Bc113c1E83", + arbitrumSepoliaStakingPoolv3Address: "0x9bfEADec553110AbB9e2fbE54ccD9AD903f21961", + getStakingPoolv3Address: (arbitrumStakingPoolv3Address) => + set(() => ({ stakingPoolv3Address: arbitrumStakingPoolv3Address })), + }) +); + export const useChainlinkAbiStore = create() ( (set) => ({ chainlinkAbi: chainlinkAbi, @@ -180,6 +190,14 @@ export const useStakingPoolv2AbiStore = create()( }) ); +export const useStakingPoolv3AbiStore = create()( + (set) => ({ + stakingPoolv3Abi: stakingPoolv3Abi, + getLiquidationPoolAbi: (stakingPoolv3Abi) => + set(() => ({ stakingPoolv3Abi: stakingPoolv3Abi })), + }) +); + export const useErc20AbiStore = create() ( (set) => ({ erc20Abi: erc20Abi, From 636db4c2de08f8ca5032a2b36178889f6c33947b Mon Sep 17 00:00:00 2001 From: Zak Date: Thu, 31 Oct 2024 13:34:45 +0000 Subject: [PATCH 4/4] feat: add more explanation to yield ratio explanation --- .../vault/yield/YieldDepositModal.jsx | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/components/vault/yield/YieldDepositModal.jsx b/src/components/vault/yield/YieldDepositModal.jsx index 26b1acb..f0322d6 100644 --- a/src/components/vault/yield/YieldDepositModal.jsx +++ b/src/components/vault/yield/YieldDepositModal.jsx @@ -161,18 +161,33 @@ const YieldDepositModal = (props) => { > - Choose Stable Ratio + Choose Your Allocation + + + + Balancing Stability & Growth Potential - Choose how much volatile collateral you want to use to earn a yield, and what percentage you would like in safer, correlated, stable asset yield strategies. -
- Recommended 10% stable. + Volatile pools (like {assetYield.pair[0]}/{assetYield.pair[1]}) can unlock high returns from UNISWAP trading fees, though short-term price shifts may temporarily impact returns. Over time, fees often outpace impermanent loss (IL) fluctuations, leading to positive yields.
+ + We require at least 10% of your collateral in the correlated stable pool (USDs/USDC). Stable pools provide consistent, lower-risk yields, shielding a portion of your assets from the effects of impermanent loss. You can increase this allocation for even more stability. + + + + By choosing your mix, you're setting up for both the potential rewards of volatility and the steady benefits of stability. +