Skip to content

Commit

Permalink
fix vesting flow when staking new/existing and unstaking vested posit…
Browse files Browse the repository at this point in the history
…ions
  • Loading branch information
eli-d committed Oct 2, 2024
1 parent a0a66e7 commit 9da028d
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 28 deletions.
11 changes: 8 additions & 3 deletions web/src/app/stake/pool/confirm-withdraw/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,15 +173,20 @@ export default function ConfirmWithdrawLiquidity() {
}
};

// once yield is collected, update position
// once yield is collected or position is divested, update position
useEffect(() => {
if (!collectResult.data || !isWithdrawingEntirePosition) return;
updatePosition(BigInt(positionId));
if (
(isWithdrawingEntirePosition && collectResult.data) ||
(isDivesting && divestPositionResult.data)
)
updatePosition(BigInt(positionId));
}, [
updatePosition,
positionId,
collectResult.data,
isWithdrawingEntirePosition,
isDivesting,
divestPositionResult.data,
]);

const getAmountsAndSetPosition = useCallback(
Expand Down
135 changes: 110 additions & 25 deletions web/src/components/ConfirmStake.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { useContracts } from "@/config/contracts";
import { TokenIcon } from "./TokenIcon";
import { useFeatureFlag } from "@/hooks/useFeatureFlag";
import { usePositions } from "@/hooks/usePostions";
import { superpositionTestnet } from "@/config/chains";

type ConfirmStakeProps =
| {
Expand Down Expand Up @@ -67,9 +68,14 @@ export const ConfirmStake = ({
const fUSDC = useTokens(expectedChainId, "fusdc");
const ammContract = useContracts(expectedChainId, "amm");
const leoContract = useContracts(expectedChainId, "leo");
const ownershipNFTContract = useContracts(expectedChainId, "ownershipNFTs");
const showBoostIncentives = useFeatureFlag("ui show boost incentives");
const showStakeApy = useFeatureFlag("ui show stake apy");

const showLeo =
useFeatureFlag("ui show leo") && chainId === superpositionTestnet.id;
const isDivesting = showLeo && isVested;

useEffect(() => {
if (!address || chainId !== expectedChainId) router.back();
}, [address, expectedChainId, chainId, router]);
Expand Down Expand Up @@ -187,8 +193,16 @@ export const ConfirmStake = ({
writeContractAsync: writeContractDivestPosition,
data: divestPositionData,
error: divestPositionError,
isPending: isDivestPositionPending,
reset: resetDivestPosition,
} = useWriteContract();
const {
writeContractAsync: writeContractApproveOwnershipNFT,
data: approveOwnershipNFTData,
error: approveOwnershipNFTError,
isPending: isApproveOwnershipNFTPending,
reset: resetApproveOwnershipNFT,
} = useWriteContract();

const divestPositionResult = useWaitForTransactionReceipt({
hash: divestPositionData,
Expand Down Expand Up @@ -388,6 +402,11 @@ export const ConfirmStake = ({
hash: updatePositionData,
});

// wait for the approveOwnershipNFT transaction to complete
const approveOwnershipNFTResult = useWaitForTransactionReceipt({
hash: approveOwnershipNFTData,
});

const getAmountsAndSetPosition = useCallback(
function (id: number, tickLower: number, tickUpper: number) {
const position = {
Expand All @@ -398,7 +417,8 @@ export const ConfirmStake = ({
},
lower: tickLower,
upper: tickUpper,
isVested,
// if isVested already, we have to unvest to update the position
isVested: isVesting,
};
getUsdTokenAmountsForPosition(
expectedChainId,
Expand All @@ -423,7 +443,25 @@ export const ConfirmStake = ({
}),
);
},
[expectedChainId, isVested, token0, tokenPrice, updatePositionLocal],
[expectedChainId, isVesting, token0, tokenPrice, updatePositionLocal],
);

const approveOwnershipNFT = useCallback(
() =>
writeContractApproveOwnershipNFT({
address: ownershipNFTContract.address,
abi: ownershipNFTContract.abi,
functionName: "approve",
args: [leoContract.address, BigInt(positionId ?? mintPositionId ?? 0)],
}),
[
writeContractApproveOwnershipNFT,
ownershipNFTContract.address,
ownershipNFTContract.abi,
positionId,
mintPositionId,
leoContract.address,
],
);

const vestPositionResultIdle = useCallback(
Expand Down Expand Up @@ -461,29 +499,24 @@ export const ConfirmStake = ({
]);

useEffect(() => {
if (updatePositionResult.isSuccess) {
// if we're vesting in Leo, do so now
if (isVesting) {
switch (true) {
// haven't yet called vest position, so call it and wait
case vestPositionResult.fetchStatus === "idle" &&
!vestPositionResult.data:
vestPositionResultIdle();
return;
// vest position call is pending, so wait
case isVestPositionPending:
return;
// call has completed, so proceed
default:
break;
}
}
if (updatePositionResult.isSuccess && isVesting) {
approveOwnershipNFT();
}
}, [updatePositionResult.isSuccess, isVesting, approveOwnershipNFT]);

useEffect(() => {
// if we're vesting in Leo, have approved the ownership transfer, but haven't vested the position, do so now
if (
approveOwnershipNFTResult.isSuccess &&
isVesting &&
vestPositionResult.fetchStatus === "idle" &&
!vestPositionResult.data
)
vestPositionResultIdle();
}, [
vestPositionResultIdle,
isVestPositionPending,
isVesting,
updatePositionResult.isSuccess,
approveOwnershipNFTResult.isSuccess,
vestPositionResult.data,
vestPositionResult.fetchStatus,
]);
Expand All @@ -494,6 +527,7 @@ export const ConfirmStake = ({
resetApproveToken1();
resetVestPosition();
resetDivestPosition();
resetApproveOwnershipNFT();
updatePositionResult.refetch();
router.push("/stake");
}, [
Expand All @@ -502,6 +536,7 @@ export const ConfirmStake = ({
resetApproveToken1,
resetVestPosition,
resetDivestPosition,
resetApproveOwnershipNFT,
updatePositionResult,
router,
]);
Expand Down Expand Up @@ -544,7 +579,23 @@ export const ConfirmStake = ({
);
}

// step 3 pending
// step 4 - divest from Leo if position is vested
if (
isDivesting &&
(isDivestPositionPending ||
(divestPositionData && divestPositionResult?.isPending))
) {
return (
<Confirm
text={"Divest Position"}
fromAsset={{ symbol: token0.symbol, amount: token0Amount ?? "0" }}
toAsset={{ symbol: token1.symbol, amount: token1Amount ?? "0" }}
transactionHash={divestPositionData}
/>
);
}

// step 5 pending
if (
isUpdatePositionPending ||
(updatePositionData && updatePositionResult?.isPending)
Expand All @@ -559,6 +610,38 @@ export const ConfirmStake = ({
);
}

// step 6 approving NFT ownership transfer for vesting
if (
isVesting &&
(isApproveOwnershipNFTPending ||
(approveOwnershipNFTData && approveOwnershipNFTResult?.isPending))
) {
return (
<Confirm
text={"Vest Position"}
fromAsset={{ symbol: token0.symbol, amount: token0Amount ?? "0" }}
toAsset={{ symbol: token1.symbol, amount: token1Amount ?? "0" }}
transactionHash={vestPositionData}
/>
);
}

// step 7 vesting position
if (
isVesting &&
(isVestPositionPending ||
(vestPositionData && vestPositionResult?.isPending))
) {
return (
<Confirm
text={"Vest Position"}
fromAsset={{ symbol: token0.symbol, amount: token0Amount ?? "0" }}
toAsset={{ symbol: token1.symbol, amount: token1Amount ?? "0" }}
transactionHash={vestPositionData}
/>
);
}

// success
if (updatePositionResult.data) {
return (
Expand All @@ -576,15 +659,17 @@ export const ConfirmStake = ({
approvalErrorToken1 ||
updatePositionError ||
divestPositionError ||
vestPositionError
vestPositionError ||
approveOwnershipNFTError
) {
const error =
mintError ||
approvalErrorToken0 ||
approvalErrorToken1 ||
updatePositionError ||
divestPositionError ||
vestPositionError;
vestPositionError ||
approveOwnershipNFTError;
return <Fail text={(error as any)?.shortMessage} />;
}

Expand Down Expand Up @@ -838,7 +923,7 @@ export const ConfirmStake = ({
onClick={() => {
mode === "new"
? createPosition()
: isVested
: isDivesting
? divestPosition(BigInt(positionId))
: updatePosition(BigInt(positionId));
}}
Expand Down

0 comments on commit 9da028d

Please sign in to comment.