-
Notifications
You must be signed in to change notification settings - Fork 3
Add liqudate button on borrower table #307
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| import { useCallback } from 'react'; | ||
| import { Button } from '@/components/ui/button'; | ||
| import { useLiquidateTransaction } from '@/hooks/useLiquidateTransaction'; | ||
| import type { Market } from '@/utils/types'; | ||
|
|
||
| type Borrower = { | ||
| userAddress: string; | ||
| borrowAssets: string; | ||
| collateral: string; | ||
| ltv: number; | ||
| }; | ||
|
|
||
| type LiquidateButtonProps = { | ||
| market: Market; | ||
| borrower: Borrower; | ||
| onSuccess?: () => void; | ||
| }; | ||
|
|
||
| export function LiquidateButton({ market, borrower, onSuccess }: LiquidateButtonProps) { | ||
| // Seize all collateral - Morpho will calculate the appropriate repayment | ||
| const seizedAssets = BigInt(borrower.collateral); | ||
|
|
||
| const { isApproved, isLoading, approveAndLiquidate, signAndLiquidate } = useLiquidateTransaction({ | ||
| market, | ||
| borrower, | ||
| seizedAssets, | ||
| onSuccess, | ||
| }); | ||
|
Comment on lines
+19
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No check for liquidation eligibility. The button is rendered for all borrowers regardless of whether they're actually liquidatable (LTV > LLTV). Attempting to liquidate a healthy position will fail on-chain. Consider disabling the button or checking eligibility: Suggested approach export function LiquidateButton({ market, borrower, onSuccess }: LiquidateButtonProps) {
+ const maxLtv = Number(market.lltv) / 1e18;
+ const isLiquidatable = borrower.ltv > maxLtv * 100;
+
// Seize all collateral - Morpho will calculate the appropriate repayment
const seizedAssets = BigInt(borrower.collateral);
// ... hook call ...
return (
<Button
variant="ghost"
size="sm"
className="h-7 px-2 text-xs"
onClick={handleClick}
- disabled={isLoading}
+ disabled={isLoading || !isLiquidatable}
>
- {isLoading ? 'Processing...' : 'Liquidate'}
+ {isLoading ? 'Processing...' : isLiquidatable ? 'Liquidate' : 'Healthy'}
</Button>
);
}🤖 Prompt for AI Agents |
||
|
|
||
| const handleClick = useCallback(() => { | ||
| if (isApproved) { | ||
| void signAndLiquidate(); | ||
| } else { | ||
| void approveAndLiquidate(); | ||
| } | ||
| }, [isApproved, approveAndLiquidate, signAndLiquidate]); | ||
|
|
||
| return ( | ||
| <Button | ||
| variant="default" | ||
| size="sm" | ||
| className="h-7 px-2 text-xs" | ||
| onClick={handleClick} | ||
| disabled={isLoading} | ||
| > | ||
| {isLoading ? 'Processing...' : 'Liquidate'} | ||
| </Button> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| import { useCallback } from 'react'; | ||
| import { type Address, encodeFunctionData } from 'viem'; | ||
| import { useConnection, useSwitchChain } from 'wagmi'; | ||
| import morphoAbi from '@/abis/morpho'; | ||
| import type { Market } from '@/utils/types'; | ||
| import { useTransactionWithToast } from './useTransactionWithToast'; | ||
|
|
||
| type UseAccrueInterestProps = { | ||
| market: Market | undefined; | ||
| onSuccess?: () => void; | ||
| }; | ||
|
|
||
| export function useAccrueInterest({ market, onSuccess }: UseAccrueInterestProps) { | ||
| const { address: account } = useConnection(); | ||
| const { mutateAsync: switchChainAsync } = useSwitchChain(); | ||
|
|
||
| const { sendTransaction, isConfirming } = useTransactionWithToast({ | ||
| toastId: 'accrue-interest', | ||
| pendingText: 'Accruing Interest', | ||
| successText: 'Interest Accrued', | ||
| errorText: 'Failed to accrue interest', | ||
| chainId: market?.morphoBlue.chain.id, | ||
| pendingDescription: 'Accruing interest...', | ||
| successDescription: 'Interest has been accrued', | ||
| onSuccess, | ||
| }); | ||
|
|
||
| const accrueInterest = useCallback(async () => { | ||
| if (!market) return; | ||
|
|
||
| await switchChainAsync({ chainId: market.morphoBlue.chain.id }); | ||
|
|
||
| const morphoAddress = market.morphoBlue.address as Address; | ||
|
|
||
| sendTransaction({ | ||
| to: morphoAddress, | ||
| account, | ||
| data: encodeFunctionData({ | ||
| abi: morphoAbi, | ||
| functionName: 'accrueInterest', | ||
| args: [ | ||
| { | ||
| loanToken: market.loanAsset.address as Address, | ||
| collateralToken: market.collateralAsset.address as Address, | ||
| oracle: market.oracleAddress as Address, | ||
| irm: market.irmAddress as Address, | ||
| lltv: BigInt(market.lltv), | ||
| }, | ||
| ], | ||
| }), | ||
| chainId: market.morphoBlue.chain.id, | ||
| }); | ||
| }, [market, account, switchChainAsync, sendTransaction]); | ||
antoncoding marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| return { | ||
| accrueInterest, | ||
| isLoading: isConfirming, | ||
| }; | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.