162 lines
4.9 KiB
TypeScript
162 lines
4.9 KiB
TypeScript
/**
|
|
* Aave v3: Supply collateral, enable as collateral, and borrow
|
|
*
|
|
* This example demonstrates:
|
|
* 1. Supplying assets to Aave v3
|
|
* 2. Enabling supplied asset as collateral
|
|
* 3. Borrowing against collateral
|
|
*
|
|
* Note: In Aave v3.3+, stable-rate borrowing has been deprecated. Use variable rate (mode = 2).
|
|
*/
|
|
|
|
import { createWalletRpcClient } from '../../src/utils/chain-config.js';
|
|
import { getAavePoolAddress } from '../../src/utils/addresses.js';
|
|
import { getTokenMetadata, parseTokenAmount } from '../../src/utils/tokens.js';
|
|
import { waitForTransaction } from '../../src/utils/rpc.js';
|
|
import { parseUnits } from 'viem';
|
|
|
|
const CHAIN_ID = 1; // Mainnet (change to 8453 for Base, 42161 for Arbitrum, etc.)
|
|
const PRIVATE_KEY = process.env.PRIVATE_KEY as `0x${string}`;
|
|
|
|
// ABI for Aave Pool
|
|
const POOL_ABI = [
|
|
{
|
|
name: 'supply',
|
|
type: 'function',
|
|
stateMutability: 'nonpayable',
|
|
inputs: [
|
|
{ name: 'asset', type: 'address' },
|
|
{ name: 'amount', type: 'uint256' },
|
|
{ name: 'onBehalfOf', type: 'address' },
|
|
{ name: 'referralCode', type: 'uint16' },
|
|
],
|
|
outputs: [],
|
|
},
|
|
{
|
|
name: 'setUserUseReserveAsCollateral',
|
|
type: 'function',
|
|
stateMutability: 'nonpayable',
|
|
inputs: [
|
|
{ name: 'asset', type: 'address' },
|
|
{ name: 'useAsCollateral', type: 'bool' },
|
|
],
|
|
outputs: [],
|
|
},
|
|
{
|
|
name: 'borrow',
|
|
type: 'function',
|
|
stateMutability: 'nonpayable',
|
|
inputs: [
|
|
{ name: 'asset', type: 'address' },
|
|
{ name: 'amount', type: 'uint256' },
|
|
{ name: 'interestRateMode', type: 'uint256' },
|
|
{ name: 'referralCode', type: 'uint16' },
|
|
{ name: 'onBehalfOf', type: 'address' },
|
|
],
|
|
outputs: [],
|
|
},
|
|
] as const;
|
|
|
|
// ERC20 ABI for approvals
|
|
const ERC20_ABI = [
|
|
{
|
|
name: 'approve',
|
|
type: 'function',
|
|
stateMutability: 'nonpayable',
|
|
inputs: [
|
|
{ name: 'spender', type: 'address' },
|
|
{ name: 'amount', type: 'uint256' },
|
|
],
|
|
outputs: [{ name: '', type: 'bool' }],
|
|
},
|
|
{
|
|
name: 'allowance',
|
|
type: 'function',
|
|
stateMutability: 'view',
|
|
inputs: [
|
|
{ name: 'owner', type: 'address' },
|
|
{ name: 'spender', type: 'address' },
|
|
],
|
|
outputs: [{ name: '', type: 'uint256' }],
|
|
},
|
|
] as const;
|
|
|
|
async function supplyAndBorrow() {
|
|
const walletClient = createWalletRpcClient(CHAIN_ID, PRIVATE_KEY);
|
|
const publicClient = walletClient as any;
|
|
const account = walletClient.account?.address;
|
|
|
|
if (!account) {
|
|
throw new Error('No account available');
|
|
}
|
|
|
|
const poolAddress = getAavePoolAddress(CHAIN_ID);
|
|
|
|
// Token configuration
|
|
const collateralToken = getTokenMetadata(CHAIN_ID, 'USDC');
|
|
const debtToken = getTokenMetadata(CHAIN_ID, 'USDT');
|
|
|
|
// Amounts
|
|
const supplyAmount = parseTokenAmount('1000', collateralToken.decimals);
|
|
const borrowAmount = parseTokenAmount('500', debtToken.decimals);
|
|
|
|
console.log(`Supplying ${supplyAmount} ${collateralToken.symbol}`);
|
|
console.log(`Borrowing ${borrowAmount} ${debtToken.symbol}`);
|
|
console.log(`Pool: ${poolAddress}`);
|
|
console.log(`Account: ${account}`);
|
|
|
|
// Step 1: Approve token spending
|
|
console.log('\n1. Approving token spending...');
|
|
const approveTx = await walletClient.writeContract({
|
|
address: collateralToken.address,
|
|
abi: ERC20_ABI,
|
|
functionName: 'approve',
|
|
args: [poolAddress, supplyAmount],
|
|
});
|
|
await waitForTransaction(publicClient, approveTx);
|
|
console.log(`Approved: ${approveTx}`);
|
|
|
|
// Step 2: Supply collateral
|
|
console.log('\n2. Supplying collateral...');
|
|
const supplyTx = await walletClient.writeContract({
|
|
address: poolAddress,
|
|
abi: POOL_ABI,
|
|
functionName: 'supply',
|
|
args: [collateralToken.address, supplyAmount, account, 0],
|
|
});
|
|
await waitForTransaction(publicClient, supplyTx);
|
|
console.log(`Supplied: ${supplyTx}`);
|
|
|
|
// Step 3: Enable as collateral
|
|
console.log('\n3. Enabling as collateral...');
|
|
const enableCollateralTx = await walletClient.writeContract({
|
|
address: poolAddress,
|
|
abi: POOL_ABI,
|
|
functionName: 'setUserUseReserveAsCollateral',
|
|
args: [collateralToken.address, true],
|
|
});
|
|
await waitForTransaction(publicClient, enableCollateralTx);
|
|
console.log(`Enabled collateral: ${enableCollateralTx}`);
|
|
|
|
// Step 4: Borrow (variable rate = 2, stable rate is deprecated)
|
|
console.log('\n4. Borrowing...');
|
|
const borrowTx = await walletClient.writeContract({
|
|
address: poolAddress,
|
|
abi: POOL_ABI,
|
|
functionName: 'borrow',
|
|
args: [debtToken.address, borrowAmount, 2, 0, account], // mode 2 = variable
|
|
});
|
|
await waitForTransaction(publicClient, borrowTx);
|
|
console.log(`Borrowed: ${borrowTx}`);
|
|
|
|
console.log('\n✅ Supply and borrow completed successfully!');
|
|
}
|
|
|
|
// Run if executed directly
|
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
supplyAndBorrow().catch(console.error);
|
|
}
|
|
|
|
export { supplyAndBorrow };
|
|
|