diff --git a/apps/web/src/composables/breakdownMetrics.ts b/apps/web/src/composables/breakdownMetrics.ts index 17c5152d0..dabb2b566 100644 --- a/apps/web/src/composables/breakdownMetrics.ts +++ b/apps/web/src/composables/breakdownMetrics.ts @@ -65,19 +65,25 @@ export default function useBreakdownMetrics() { addresses.forEach(address => {userEventTotalsPromises.push(getContractEventsTotalsByAddress(address, eigenManager))}) const userEventTotals = await Promise.all(userEventTotalsPromises) as Array const userEventTotalsSum = userEventTotals.reduce((acc, curr) => { - const { StakeDeposited, WithdrawalInitiated } = curr + const { StakeDeposited, WithdrawalInitiated, WithdrawalRequested, WithdrawalFulfilled } = curr return { StakeDeposited: acc.StakeDeposited + (StakeDeposited || 0), WithdrawalInitiated: acc.WithdrawalInitiated + (WithdrawalInitiated || 0), + WithdrawalRequested: acc.WithdrawalRequested + (WithdrawalRequested || 0), + WithdrawalFulfilled: acc.WithdrawalFulfilled + (WithdrawalFulfilled || 0) } - }, { StakeDeposited: 0, WithdrawalInitiated: 0 } as { StakeDeposited: number; WithdrawalInitiated: number }) + }, { StakeDeposited: 0, WithdrawalInitiated: 0, WithdrawalRequested: 0, WithdrawalFulfilled: 0 } as { StakeDeposited: number; WithdrawalInitiated: number, WithdrawalRequested: number, WithdrawalFulfilled: number }) const stakedDepositedETH = userEventTotalsSum.StakeDeposited const withdrawalInitiatedETH = userEventTotalsSum.WithdrawalInitiated + const withdrawalRequestedETH = userEventTotalsSum.WithdrawalRequested + const withdrawalFulfilledETH = userEventTotalsSum.WithdrawalFulfilled + + + /* Get User's All Time Rewards */ + const currentUserStakeMinusEvents = currentUserStakeETH - stakedDepositedETH + ((withdrawalInitiatedETH) + (withdrawalRequestedETH) + (withdrawalFulfilledETH)) - /* Get User's All Time Rewards by Subtracting (StakeDeposited + WithdrawalInitiated) from CurrentStake */ - const currentUserStakeMinusEvents = currentUserStakeETH - (stakedDepositedETH as number) - (withdrawalInitiatedETH as number) return { eth: `${formatNumber(currentUserStakeMinusEvents)} ETH`, usd: `$${formatNumber(currentUserStakeMinusEvents * (await getCurrentPrice({ coin: 'ETH', currency: 'USD' })))}` @@ -96,7 +102,9 @@ export default function useBreakdownMetrics() { const eventList = [ 'StakeDeposited', 'StakeRebalanced', - 'WithdrawalInitiated' + 'WithdrawalInitiated', + 'WithdrawalRequested', + 'WithdrawalFulfilled' ] const eventFilters = eventList.map(event => { if (event === 'StakeRebalanced') return (manager as CasimirManager).filters[event]() @@ -120,14 +128,15 @@ export default function useBreakdownMetrics() { userEventTotals[event as string] += amountInEth } } - - return userEventTotals + return userEventTotals as ContractEventsByAddress } catch (err) { console.error(`There was an error in getContractEventsTotalsByAddress: ${err}`) return { StakeDeposited: 0, StakeRebalanced: 0, - WithdrawalInitiated: 0 + WithdrawalInitiated: 0, + WithdrawalRequested: 0, + WithdrawalFulfilled: 0 } } } diff --git a/apps/web/src/composables/staking.ts b/apps/web/src/composables/staking.ts index 4d2b79761..8acd072fe 100644 --- a/apps/web/src/composables/staking.ts +++ b/apps/web/src/composables/staking.ts @@ -90,6 +90,26 @@ export default function useStaking() { } } + async function getWithdrawableBalance({walletProvider, type}: {walletProvider: ProviderString, type: 'default' | 'eigen'}) { + let signer + if (ethersProviderList.includes(walletProvider)) { + signer = getEthersBrowserSigner(walletProvider) + } else if (walletProvider === 'WalletConnect') { + await getWalletConnectSignerV2() + } else if (walletProvider === 'Ledger') { + getEthersLedgerSigner() + } else if (walletProvider === 'Trezor') { + getEthersTrezorSigner() + } else { + throw new Error(`Invalid wallet provider: ${walletProvider}`) + } + const manager = type === 'default' ? defaultManager : eigenManager + const managerSigner = (manager as CasimirManager).connect(signer as ethers.Signer) + const withdrawableBalance = await managerSigner.getWithdrawableBalance() + const withdrawableBalanceEther = ethers.utils.formatEther(withdrawableBalance) + return withdrawableBalanceEther + } + async function withdraw({ amount, walletProvider, type }: { amount: string, walletProvider: ProviderString, type: 'default' | 'eigen' }) { let signer if (ethersProviderList.includes(walletProvider)) { @@ -106,14 +126,7 @@ export default function useStaking() { const manager = type === 'default' ? defaultManager : eigenManager const managerSigner = (manager as CasimirManager).connect(signer as ethers.Signer) const value = ethers.utils.parseEther(amount) - // const withdrawableBalance = await (manager as CasimirManager).getWithdrawableBalance() - const bufferedBalance = await managerSigner.getBufferedBalance() - const bufferedBalanceNumber = parseFloat(ethers.utils.formatEther(bufferedBalance)) - const result = await managerSigner.requestWithdrawal(value) - return { - result, - bufferedBalance: bufferedBalanceNumber - } + return await managerSigner.requestWithdrawal(value) } return { @@ -122,6 +135,7 @@ export default function useStaking() { deposit, getDepositFees, getUserStake, + getWithdrawableBalance, withdraw } } \ No newline at end of file diff --git a/apps/web/src/pages/overview/components/Staking.vue b/apps/web/src/pages/overview/components/Staking.vue index 2ee6a1e10..b7fe914db 100644 --- a/apps/web/src/pages/overview/components/Staking.vue +++ b/apps/web/src/pages/overview/components/Staking.vue @@ -11,7 +11,7 @@ import confetti from 'canvas-confetti' import TermsOfService from '@/components/TermsOfService.vue' -const { stakingComposableInitialized, deposit, initializeStakingComposable, withdraw } = useStaking() +const { stakingComposableInitialized, deposit, initializeStakingComposable, withdraw, getWithdrawableBalance } = useStaking() const { getEthersBalance } = useEthers() const { convertString } = useFormat() const { getCurrentPrice } = usePrice() @@ -24,7 +24,7 @@ const stakeType = ref<'default' | 'eigen'>('default') const currentUserStake = ref(0) const estimatedFees = ref('-') const estimatedAPY = ref('4.00') -const formattedAmountToStake = ref('') +const formattedAmountToStakeOrWithdraw = ref('') const formattedWalletOptions = ref>([]) const selectedStakingProvider = ref('') const selectedWalletAddress = ref(null as null | string) @@ -97,7 +97,7 @@ const handleInputOnAmountToStake = (event: any) => { } // Update the model value - formattedAmountToStake.value = parts.join('.') + formattedAmountToStakeOrWithdraw.value = parts.join('.') } const selectAmountInput = () => { @@ -131,15 +131,15 @@ const aggregateAddressesByProvider = () => { // empty out staking comp selectedStakingProvider.value = '' selectedWalletAddress.value = null - formattedAmountToStake.value = '' + formattedAmountToStakeOrWithdraw.value = '' addressBalance.value = null currentUserStake.value = 0 } } -watch(formattedAmountToStake, async () => { - if (formattedAmountToStake.value) { - const floatAmount = parseFloat(formattedAmountToStake.value?.replace(/,/g, '')) +watch(formattedAmountToStakeOrWithdraw, async () => { + if (formattedAmountToStakeOrWithdraw.value) { + const floatAmount = parseFloat(formattedAmountToStakeOrWithdraw.value?.replace(/,/g, '')) let maxAmount // minAmount is 0.0001 ETH let minAmount = 0.0001 @@ -186,7 +186,7 @@ watch(user, async () => { } else { selectedStakingProvider.value = '' selectedWalletAddress.value = null - formattedAmountToStake.value = '' + formattedAmountToStakeOrWithdraw.value = '' addressBalance.value = null // currentUserStake.value = 0 } @@ -248,12 +248,12 @@ const handleDeposit = async () => { // const activeAddress = await detectActiveWalletAddress(selectedStakingProvider.value) // if (activeAddress !== selectedWalletAddress.value) { - // formattedAmountToStake.value = '' + // formattedAmountToStakeOrWithdraw.value = '' // return alert(`The account you selected is not the same as the one that is active in your ${selectedStakingProvider.value} wallet. Please open your browser extension and select the account that you want to log in with.`) // } const result = await deposit({ - amount: formattedAmountToStake.value, + amount: formattedAmountToStakeOrWithdraw.value, walletProvider: selectedStakingProvider.value, type: stakeType.value }) @@ -263,7 +263,7 @@ const handleDeposit = async () => { setTimeout(() =>{ stakeButtonText.value = 'Stake' - formattedAmountToStake.value = '' + formattedAmountToStakeOrWithdraw.value = '' }, 1000) if (result) { @@ -286,24 +286,33 @@ const handleWithdraw = async () => { // const activeAddress = await detectActiveWalletAddress(selectedStakingProvider.value) // if (activeAddress !== selectedWalletAddress.value) { - // formattedAmountToStake.value = '' + // formattedAmountToStakeOrWithdraw.value = '' // return alert(`The account you selected is not the same as the one that is active in your ${selectedStakingProvider.value} wallet. Please open your browser extension and select the account that you want to log in with.`) // } - const { result, bufferedBalance } = await withdraw({ - amount: formattedAmountToStake.value, + const withdrawableBalance = await getWithdrawableBalance({ + walletProvider: selectedStakingProvider.value, + type: stakeType.value + }) + + if (withdrawableBalance < formattedAmountToStakeOrWithdraw.value) { + stakeButtonText.value = 'Withdraw' + formattedAmountToStakeOrWithdraw.value = '' + return alert(`You can currently withdraw up to ${withdrawableBalance} ETH. Please try again with a smaller amount.`) + } + + const result = await withdraw({ + amount: formattedAmountToStakeOrWithdraw.value, walletProvider: selectedStakingProvider.value, type: stakeType.value }) - console.log('result :>> ', result) - console.log('bufferedBalance :>> ', bufferedBalance) if (!result) stakeButtonText.value = 'Failed!' stakeButtonText.value = 'Withdrawn!' setTimeout(() =>{ stakeButtonText.value = 'Withdraw' - formattedAmountToStake.value = '' + formattedAmountToStakeOrWithdraw.value = '' }, 1000) if (result) { @@ -322,7 +331,7 @@ const handleWithdraw = async () => { function setStakeOrWithdraw(option: 'stake' | 'withdraw') { stakeOrWithdraw.value = option - formattedAmountToStake.value = '' + formattedAmountToStakeOrWithdraw.value = '' stakeButtonText.value = option === 'stake' ? 'Stake' : 'Withdraw' } @@ -438,7 +447,7 @@ function setStakeOrWithdraw(option: 'stake' | 'withdraw') {
@@ -528,7 +537,7 @@ function setStakeOrWithdraw(option: 'stake' | 'withdraw') { class="toggle_button" :style="{ 'background-color': toggleBackgroundColor }" :class="{ 'toggle-on': eigenIsToggled }" - :disabled="!(termsOfServiceCheckbox && selectedWalletAddress && formattedAmountToStake && !errorMessage)" + :disabled="!(termsOfServiceCheckbox && selectedWalletAddress && formattedAmountToStakeOrWithdraw && !errorMessage)" >
@@ -538,7 +547,7 @@ function setStakeOrWithdraw(option: 'stake' | 'withdraw') {