Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

migrate cvx positions #59

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Use ExpandableCard
nathanhleung committed Mar 17, 2022
commit ec05dc9575d8514b02e6ae6cbc04c57bb6289231
292 changes: 147 additions & 145 deletions src/components/pages/Fuse/Modals/CVXMigrateModal.tsx
Original file line number Diff line number Diff line change
@@ -9,12 +9,11 @@ import {
Text,
Flex,
VStack,
Spacer,
HStack,
useToast,
Avatar,
Image,
Center,
Box,
} from "@chakra-ui/react"
import { POOL_156_COMPTROLLER } from "constants/convex"
import { useRari } from "context/RariContext"
@@ -27,8 +26,8 @@ import { useBorrowLimit, useTotalSupply } from "hooks/useBorrowLimit"
import { useFusePoolData } from "hooks/useFusePoolData"
import useHasApproval from "hooks/useHasApproval"
import { useTokensDataAsMap } from "hooks/useTokenData"
import { Button, Card, Heading, StepBubbles } from "rari-components";
import { useEffect, useMemo, useState } from "react"
import { Button, ExpandableCard, Heading } from "rari-components";
import { useEffect, useState } from "react"
import { useQuery } from "react-query"
import { TokensDataMap } from "types/tokens"
import { smallStringUsdFormatter } from "utils/bigUtils"
@@ -44,15 +43,10 @@ export const CVXMigrateModal = ({
onClose: () => void,
}) => {

const { fuse, address } = useRari()
const { address } = useRari()
const cvxBalances = useStakedConvexBalances()
const curveLPBalances = useCurveLPBalances()

// Steppers
const toast = useToast()
const [step, setStep] = useState<1 | 2 | 3 | 4 | 5 | undefined>()
const [activeStep, setActiveStep] = useState<1 | 2 | 3 | 4 | 5 | undefined>()

// Fuse pool Data
const fusePoolData = useFusePoolData("156")
const assets = !fusePoolData ? [] : fusePoolData.assets.filter(a => Object.keys(cvxBalances).includes(a.cToken) || Object.keys(curveLPBalances).includes(a.underlyingToken))
@@ -89,8 +83,6 @@ export const CVXMigrateModal = ({
}
}, {})

const marketBalanceForAsset = marketsBalancesMap[assets[assetIndex]?.cToken]

// Simulates you depositing all your CVX positions into us - to get projected totalSupply & projected borrowLimit
const { data: updatedUserAssets } = useQuery('updated assets for convex user ' + address, async () => {

@@ -132,93 +124,6 @@ export const CVXMigrateModal = ({
const borrowLimit = useBorrowLimit(updatedUserAssets ?? [])
const newTotalSupply = useTotalSupply(updatedUserAssets ?? [])



/* Unstakes and Claims all CVX Staked Positions supported by Fuse */
const handleUnstake = async () => {
const { stakedBalance } = marketBalanceForAsset
try {
setActiveStep(1)
if (stakedBalance.gt(0)) {
const baseRewardPool = cvxBalances[assets[assetIndex].cToken].baseRewardsPool
const res = await unstakeAndWithdrawCVXPool(fuse, baseRewardPool)
setStep(2)

}
} catch (err) {
setActiveStep(undefined)

handleGenericError(err, toast)
}
}

// Approve for stakedBalance + curveBalance
const handleApproveMarket = async () => {
const { cToken, underlyingToken } = assets[assetIndex]
const { total } = marketBalanceForAsset
try {
setActiveStep(2)
const res = await checkAllowanceAndApprove(fuse, address, cToken, underlyingToken, total)
console.log({ res })
setStep(3)
} catch (err) {
setActiveStep(undefined)

handleGenericError(err, toast)
}
}

// Deposit curveBalance
const handleDeposit = async () => {
const { cToken } = assets[assetIndex]
const { curveBalance } = marketBalanceForAsset
try {
setActiveStep(3)
const res = await deposit(fuse, cToken, curveBalance)
console.log({ res })
setStep(4)
} catch (err) {
setActiveStep(undefined)

handleGenericError(err, toast)
}
}

// Collateralize all
const handleCollateralize = async () => {
const markets = Object.keys(marketsBalancesMap)
try {
setActiveStep(4)
const res = await collateralize(fuse, POOL_156_COMPTROLLER, markets)
console.log({ res })
setStep(5)
} catch (err) {
setActiveStep(undefined)

handleGenericError(err, toast)
}
}


// If you've already approved this market, skip
const hasApproval = useHasApproval(assets[assetIndex], marketBalanceForAsset?.total.toString() ?? "0")
const showApproval = !hasApproval
// We show enable as Collateral only if this asset has not yet been anabled
const showEnableAsCollateral = !assets[assetIndex]?.membership
// If you dont have any staked, you dont need to unstake to enter this market
const showUnstake = !marketBalanceForAsset?.stakedBalance?.isZero() ?? true

const activeSymbol = tokenData[assets[assetIndex]?.underlyingToken]?.symbol

// Skip to step conditionally
useEffect(() => {
if (!showUnstake) setStep(2)
else if (hasApproval) setStep(3)
else setStep(undefined)
}, [assetIndex])



return (
<>
<Modal isOpen={isOpen} onClose={onClose}>
@@ -258,48 +163,6 @@ export const CVXMigrateModal = ({
/>
)}
</VStack>
<Spacer />
<Text>
Migrate <b>{activeSymbol}</b> in 3 clicks
</Text>

<VStack py={2} align="stretch">
{showUnstake && (
<Button disabled={!!step && step !== 1} onClick={handleUnstake}>
{
activeStep === 1 ? "Unstaking and Claiming..." : `Unstake ${activeSymbol} and Claim Rewards`
}
</Button>
)}

{showApproval && (
<Button disabled={step !== 2} onClick={handleApproveMarket}>
{
activeStep === 2 ? `Approving ${activeSymbol}...` : ` Approve ${activeSymbol}`
}
</Button>
)}

<Button disabled={step !== 3} onClick={handleDeposit}>
{
activeStep === 3 ? `Depositing ${activeSymbol}...` : ` Deposit ${activeSymbol}`
}
</Button>

{showEnableAsCollateral && step === 4 && <HStack>
<Button disabled={step !== 4} onClick={handleCollateralize}>
{
activeStep === 4 ? `Collateralizing...` : `Collateralize`
}
</Button>
</HStack>}

{step === 5 && <Text>Done!</Text>}
</VStack>

<Center pt={4}>
<StepBubbles activeIndex={(activeStep ?? 1) - 1} steps={4} />
</Center>
</VStack>
</Flex>
</ModalBody>
@@ -335,11 +198,150 @@ const Market = ({
}
}
}) => {
const { address, fuse } = useRari();
const fusePoolData = useFusePoolData("156")
const cvxBalances = useStakedConvexBalances();
const curveLPBalances = useCurveLPBalances()
const assets = !fusePoolData
? []
: fusePoolData.assets.filter(a =>
Object.keys(cvxBalances).includes(a.cToken) ||
Object.keys(curveLPBalances).includes(a.underlyingToken)
)

// Skip to step conditionally
useEffect(() => {
if (!showUnstake) setStep(2)
else if (hasApproval) setStep(3)
else setStep(undefined)
}, [assetIndex])

const marketBalanceForAsset = marketsBalancesMap[assets[assetIndex]?.cToken]

// Steppers
const toast = useToast()
const [step, setStep] = useState<1 | 2 | 3 | 4 | 5 | undefined>()
const [activeStep, setActiveStep] = useState<1 | 2 | 3 | 4 | 5 | undefined>()

/* Unstakes and Claims all CVX Staked Positions supported by Fuse */
const handleUnstake = async () => {
const { stakedBalance } = marketBalanceForAsset
try {
setActiveStep(1)
if (stakedBalance.gt(0)) {
const baseRewardPool = cvxBalances[assets[assetIndex].cToken].baseRewardsPool
const res = await unstakeAndWithdrawCVXPool(fuse, baseRewardPool)
setStep(2)

}
} catch (err) {
setActiveStep(undefined)

handleGenericError(err, toast)
}
}

// Approve for stakedBalance + curveBalance
const handleApproveMarket = async () => {
const { cToken, underlyingToken } = assets[assetIndex]
const { total } = marketBalanceForAsset
try {
setActiveStep(2)
const res = await checkAllowanceAndApprove(fuse, address, cToken, underlyingToken, total)
console.log({ res })
setStep(3)
} catch (err) {
setActiveStep(undefined)

handleGenericError(err, toast)
}
}

// Deposit curveBalance
const handleDeposit = async () => {
const { cToken } = assets[assetIndex]
const { curveBalance } = marketBalanceForAsset
try {
setActiveStep(3)
const res = await deposit(fuse, cToken, curveBalance)
console.log({ res })
setStep(4)
} catch (err) {
setActiveStep(undefined)

handleGenericError(err, toast)
}
}

// Collateralize all
const handleCollateralize = async () => {
const markets = Object.keys(marketsBalancesMap)
try {
setActiveStep(4)
const res = await collateralize(fuse, POOL_156_COMPTROLLER, markets)
console.log({ res })
setStep(5)
} catch (err) {
setActiveStep(undefined)

handleGenericError(err, toast)
}
}

const hasApproval = useHasApproval(assets[assetIndex], marketBalanceForAsset?.total.toString() ?? "0")
const showApproval = !hasApproval
// We show enable as Collateral only if this asset has not yet been anabled
const showEnableAsCollateral = !assets[assetIndex]?.membership
// If you dont have any staked, you dont need to unstake to enter this market
const showUnstake = !marketBalanceForAsset?.stakedBalance?.isZero() ?? true

const activeSymbol = tokensData[assets[assetIndex]?.underlyingToken]?.symbol

return (
<Card
onClick={() => setAssetIndex(i)}
variant={assetIndex === i ? "active" : "light"}
<ExpandableCard
variant="light"
p={3}
expandableChildren={
<Box textAlign="center">
<Text pb={4}>
Migrate <b>{activeSymbol}</b> in 3 clicks
</Text>

<VStack py={2} align="stretch">
{showUnstake && (
<Button disabled={!!step && step !== 1} onClick={handleUnstake}>
{
activeStep === 1 ? "Unstaking and Claiming..." : `Unstake ${activeSymbol} and Claim Rewards`
}
</Button>
)}

{showApproval && (
<Button disabled={step !== 2} onClick={handleApproveMarket}>
{
activeStep === 2 ? `Approving ${activeSymbol}...` : ` Approve ${activeSymbol}`
}
</Button>
)}

<Button disabled={step !== 3} onClick={handleDeposit}>
{
activeStep === 3 ? `Depositing ${activeSymbol}...` : ` Deposit ${activeSymbol}`
}
</Button>

{showEnableAsCollateral && step === 4 && <HStack>
<Button disabled={step !== 4} onClick={handleCollateralize}>
{
activeStep === 4 ? `Collateralizing...` : `Collateralize`
}
</Button>
</HStack>}

{step === 5 && <Text>Done!</Text>}
</VStack>
</Box>
}
>
<VStack>
<HStack key={market}>
@@ -360,7 +362,7 @@ const Market = ({
</Text>
</HStack>
</VStack>
</Card>
</ExpandableCard>
)
}