Skip to content

Commit

Permalink
Add repay and withdraw buttons
Browse files Browse the repository at this point in the history
Add repay and withdraw buttons
  • Loading branch information
jazz-cb authored Sep 17, 2024
2 parents bec728e + 417eb0b commit a578d6d
Show file tree
Hide file tree
Showing 3 changed files with 208 additions and 11 deletions.
90 changes: 90 additions & 0 deletions app/api/aave/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,96 @@ export async function POST(request: Request) {
}
}

if (action === 'repay') {
try {
const amountToRepay = parseUnits(amount, 6);

// First, approve USDC spend
const approveContract = await wallet.invokeContract({
contractAddress: USDC_ADDRESS,
method: "approve",
args: {
spender: AAVE_POOL_ADDRESS,
value: amountToRepay.toString()
},
abi: usdcAbi,
});

const approveTx = await approveContract.wait();
if (!approveTx) {
throw new Error('Failed to approve USDC spend');
}

console.log('USDC spend approved for repayment:', approveTx);

// Now, repay the loan
const repayContract = await wallet.invokeContract({
contractAddress: AAVE_POOL_ADDRESS,
method: "repay",
args: {
asset: USDC_ADDRESS,
amount: amountToRepay.toString(),
interestRateMode: "2",
onBehalfOf: address.getId()
},
abi: aaveAbi,
});

const repayTx = await repayContract.wait();
if (!repayTx) {
throw new Error('Failed to repay USDC to Aave');
}

console.log('USDC repaid to Aave:', repayTx);

return NextResponse.json({success: true, txHash: repayTx.getTransactionHash()});
} catch (error) {
console.error('Failed to repay loan:', error);
return NextResponse.json({
error: 'Failed to repay loan',
details: error instanceof Error ? error.message : String(error)
}, {status: 500});
}
}

if (action === 'withdraw') {
try {
const amountToWithdraw = parseUnits(amount, 6); // Assuming USDC has 6 decimals

console.log('Attempting to withdraw:', {
asset: USDC_ADDRESS,
amount: amountToWithdraw.toString(),
to: address.getId()
});

const withdrawContract = await wallet.invokeContract({
contractAddress: AAVE_POOL_ADDRESS,
method: "withdraw",
args: {
asset: USDC_ADDRESS,
amount: amountToWithdraw.toString(),
to: address.getId()
},
abi: aaveAbi,
});

const withdrawTx = await withdrawContract.wait();
if (!withdrawTx) {
throw new Error('Failed to withdraw USDC from Aave');
}

console.log('Withdraw transaction sent, hash:', withdrawTx.getTransactionHash());

return NextResponse.json({ success: true, txHash: withdrawTx.getTransactionHash() });
} catch (error) {
console.error('Failed to withdraw:', error);
return NextResponse.json({
error: 'Failed to withdraw',
details: error instanceof Error ? error.message : String(error)
}, { status: 500 });
}
}

return NextResponse.json({ error: 'Invalid action' }, { status: 400 });
}

Expand Down
127 changes: 117 additions & 10 deletions app/usdcflow/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,25 @@ export default function AaveInteraction() {
const [accountData, setAccountData] = useState<any>(null);
const [supplyAmount, setSupplyAmount] = useState<string>('');
const [borrowAmount, setBorrowAmount] = useState<string>('');
const [repayAmount, setRepayAmount] = useState<string>('');
const [withdrawAmount, setWithdrawAmount] = useState<string>('');
const [isLoading, setIsLoading] = useState<boolean>(true);
const [isSupplying, setIsSupplying] = useState<boolean>(false);
const [isBorrowing, setIsBorrowing] = useState<boolean>(false);
const [isRepaying, setIsRepaying] = useState<boolean>(false);
const [isWithdrawing, setIsWithdrawing] = useState<boolean>(false);
const [error, setError] = useState<string>('');

const [supplyOutput, setSupplyOutput] = useState<{ amount: string, txHash: string } | null>(null);
const [borrowOutput, setBorrowOutput] = useState<{ amount: string, txHash: string } | null>(null);
const [repayOutput, setRepayOutput] = useState<{ amount: string, txHash: string } | null>(null);
const [withdrawOutput, setWithdrawOutput] = useState<{ amount: string, txHash: string } | null>(null);

const clearTransactionData = () => {
setSupplyOutput(null);
setBorrowOutput(null);
setRepayOutput(null);
setWithdrawOutput(null);
setError('');
};

Expand Down Expand Up @@ -85,6 +93,51 @@ export default function AaveInteraction() {
}
};

const repayToAave = async () => {
if (!repayAmount) return;
clearTransactionData();
setIsRepaying(true);
try {
const response = await fetch('/api/aave', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({action: 'repay', amount: repayAmount}),
});
if (!response.ok) throw new Error('Failed to repay loan');
const data = await response.json();
setRepayOutput({ amount: repayAmount, txHash: data.txHash });
getUserAccountData();
} catch (err) {
console.error('Failed to repay loan:', err);
setError('Failed to repay loan. Please try again.');
} finally {
setIsRepaying(false);
}
};

const withdrawFromAave = async () => {
if (!withdrawAmount) return;
clearTransactionData();
setIsWithdrawing(true);
try {
const response = await fetch('/api/aave', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({action: 'withdraw', amount: withdrawAmount}),
});
if (!response.ok) throw new Error('Failed to withdraw assets');
const data = await response.json();
setWithdrawOutput({ amount: withdrawAmount, txHash: data.txHash });
getUserAccountData();
} catch (err) {
console.error('Failed to withdraw from Aave:', err);
setError('Failed to withdraw assets. Please try again.');
} finally {
setIsWithdrawing(false);
}
};


const closeIntro = () => {
setShowIntro(false);
};
Expand Down Expand Up @@ -164,23 +217,23 @@ export default function AaveInteraction() {
<AlertDescription>{error}</AlertDescription>
</Alert>
)}
<Button onClick={getUserAccountData} className="mb-4 bg-blue-600 hover:bg-blue-700 text-white">
Refresh Account Data
<Button onClick={getUserAccountData} className="mb-4 bg-gradient-to-r from-lavender-400 to-blue-500 hover:from-lavender-500 hover:to-blue-600 text-white transition-all duration-300">
Refresh Account Data
</Button>
{accountData && (
<div className="bg-lavender-50 p-4 rounded-lg">
<p className="mb-1">Wallet Address: {accountData.walletAddress}</p>
<p className="mb-1">Wallet Balance: {parseFloat(accountData.usdcBalance).toFixed(2)} USDC</p>
<p className="mb-1">Total Deposited: {accountData.totalDeposited} USDC</p>
<p className="mb-1">Total Debt: {accountData.totalDebtBase} USDC</p>
<p className="mb-1">Total Supplied: {accountData.totalDeposited} USDC</p>
<p className="mb-1">Total Borrowed: {accountData.totalDebtBase} USDC</p>
<p className="mb-1">Available to borrow: {accountData.availableBorrowsBase} USDC</p>
</div>
)}
</CardContent>
</Card>

<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
<Card className="bg-white shadow-lg">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
<Card className="bg-white shadow-lg">
<CardHeader>
<CardTitle className="text-xl text-blue-600">Supply Assets</CardTitle>
</CardHeader>
Expand All @@ -195,9 +248,9 @@ export default function AaveInteraction() {
}}
className="mb-4"
/>
<Button onClick={supplyToAave} disabled={isSupplying} className="w-full bg-blue-600 hover:bg-blue-700 text-white">
<Button onClick={supplyToAave} disabled={isSupplying} className="w-full bg-gradient-to-r from-lavender-400 to-blue-500 hover:from-lavender-500 hover:to-blue-600 text-white transition-all duration-300">
{isSupplying && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
Supply to Aave
Supply Assets
</Button>
</CardContent>
{supplyOutput && (
Expand All @@ -220,9 +273,9 @@ export default function AaveInteraction() {
onChange={(e) => setBorrowAmount(e.target.value)}
className="mb-4"
/>
<Button onClick={borrowFromAave} disabled={isBorrowing} className="w-full bg-blue-600 hover:bg-blue-700 text-white">
<Button onClick={borrowFromAave} disabled={isBorrowing} className="w-full bg-gradient-to-r from-lavender-400 to-blue-500 hover:from-lavender-500 hover:to-blue-600 text-white transition-all duration-300">
{isBorrowing && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
Borrow from Aave
Borrow Assets
</Button>
</CardContent>
{borrowOutput && (
Expand All @@ -232,6 +285,60 @@ export default function AaveInteraction() {
</CardFooter>
)}
</Card>

<Card className="bg-white shadow-lg">
<CardHeader>
<CardTitle className="text-xl text-blue-600">Repay Assets</CardTitle>
</CardHeader>
<CardContent>
<Input
type="number"
placeholder="Amount to repay (USDC)"
value={repayAmount}
onChange={(e) => setRepayAmount(e.target.value)}
className="mb-4"
/>
<Button
onClick={repayToAave}
disabled={isRepaying}
className="w-full bg-gradient-to-r from-lavender-400 to-blue-500 hover:from-lavender-500 hover:to-blue-600 text-white transition-all duration-300"
>
{isRepaying && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
Repay Assets
</Button>
</CardContent>
{repayOutput && (
<CardFooter className="flex flex-col items-start">
<p className="mb-2">Repaid Amount: {repayOutput.amount} USDC</p>
<p>Transaction Hash: {repayOutput.txHash}</p>
</CardFooter>
)}
</Card>
<Card className="bg-white shadow-lg">
<CardHeader>
<CardTitle className="text-xl text-blue-600">Withdraw Assets</CardTitle>
</CardHeader>
<CardContent>
<Input
type="number"
placeholder="Amount to withdraw (USDC)"
value={withdrawAmount}
onChange={(e) => setWithdrawAmount(e.target.value)}
className="mb-4"
/>
<Button onClick={withdrawFromAave} disabled={isWithdrawing}
className="w-full bg-gradient-to-r from-lavender-400 to-blue-500 hover:from-lavender-500 hover:to-blue-600 text-white transition-all duration-300">
{isWithdrawing && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
Withdraw Assets
</Button>
</CardContent>
{withdrawOutput && (
<CardFooter className="flex flex-col items-start">
<p className="mb-2">Withdrawn Amount: {withdrawOutput.amount} USDC</p>
<p className="text-sm break-all">Transaction Hash: {withdrawOutput.txHash}</p>
</CardFooter>
)}
</Card>
</div>
</>
)}
Expand Down
2 changes: 1 addition & 1 deletion vercel.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"value": "usdcflow.xyz"
}
],
"destination": "/usdcflow/:path*"
"destination": "https://www.cdp-sdk.xyz/usdcflow"
}
]
}

0 comments on commit a578d6d

Please sign in to comment.