7.1 KiB
7.1 KiB
🔌 Integration Guide
Step-by-step guide for integrating DeFi protocols into your application.
📋 Table of Contents
- Aave v3 Integration
- Uniswap v3 Integration
- Protocolink Integration
- Compound III Integration
- Cross-Protocol Strategies
🏦 Aave v3 Integration
1️⃣ Setup
import { createWalletRpcClient } from '../src/utils/chain-config.js';
import { getAavePoolAddress } from '../src/utils/addresses.js';
const CHAIN_ID = 1; // Mainnet
const walletClient = createWalletRpcClient(CHAIN_ID, privateKey);
const poolAddress = getAavePoolAddress(CHAIN_ID);
2️⃣ Supply Collateral
// 1. Approve token
await walletClient.writeContract({
address: tokenAddress,
abi: ERC20_ABI,
functionName: 'approve',
args: [poolAddress, amount],
});
// 2. Supply
await walletClient.writeContract({
address: poolAddress,
abi: POOL_ABI,
functionName: 'supply',
args: [asset, amount, account, 0],
});
// 3. Enable as collateral
await walletClient.writeContract({
address: poolAddress,
abi: POOL_ABI,
functionName: 'setUserUseReserveAsCollateral',
args: [asset, true],
});
3️⃣ Borrow
// Note: Use variable rate (2), stable rate is deprecated in v3.3+
await walletClient.writeContract({
address: poolAddress,
abi: POOL_ABI,
functionName: 'borrow',
args: [debtAsset, borrowAmount, 2, 0, account],
});
4️⃣ Flash Loans
Single Asset
await walletClient.writeContract({
address: poolAddress,
abi: POOL_ABI,
functionName: 'flashLoanSimple',
args: [receiverAddress, asset, amount, params, 0],
});
Multi-Asset
await walletClient.writeContract({
address: poolAddress,
abi: POOL_ABI,
functionName: 'flashLoan',
args: [receiverAddress, assets, amounts, modes, account, params, 0],
});
⚠️ Important: Your flash loan receiver contract must:
- ✅ Receive the loaned tokens
- ✅ Perform desired operations
- ✅ Approve the pool for
amount + premium- ✅ Return
truefromexecuteOperation
🔄 Uniswap v3 Integration
1️⃣ Setup
import { getUniswapSwapRouter02 } from '../src/utils/addresses.js';
const routerAddress = getUniswapSwapRouter02(CHAIN_ID);
2️⃣ Get Quote
// Use QuoterV2 contract to get expected output
const quote = await publicClient.readContract({
address: quoterAddress,
abi: QUOTER_ABI,
functionName: 'quoteExactInputSingle',
args: [{
tokenIn: tokenInAddress,
tokenOut: tokenOutAddress,
fee: 3000, // 0.3% fee tier
amountIn: amountIn,
sqrtPriceLimitX96: 0,
}],
});
3️⃣ Execute Swap
// 1. Approve token
await walletClient.writeContract({
address: tokenInAddress,
abi: ERC20_ABI,
functionName: 'approve',
args: [routerAddress, amountIn],
});
// 2. Execute swap
await walletClient.writeContract({
address: routerAddress,
abi: SWAP_ROUTER_ABI,
functionName: 'exactInputSingle',
args: [{
tokenIn: tokenInAddress,
tokenOut: tokenOutAddress,
fee: 3000,
recipient: account,
deadline: BigInt(Math.floor(Date.now() / 1000) + 600),
amountIn: amountIn,
amountOutMinimum: amountOutMin, // Apply slippage protection
sqrtPriceLimitX96: 0,
}],
});
4️⃣ TWAP Oracle
// Always use TWAP, not spot prices, to protect against manipulation
// See examples/ts/uniswap-v3-oracle.ts for implementation
🔗 Protocolink Integration
1️⃣ Setup
import * as api from '@protocolink/api';
import * as common from '@protocolink/common';
const CHAIN_ID = common.ChainId.mainnet;
2️⃣ Build Logics
// Swap logic
const swapQuotation = await api.protocols.uniswapv3.getSwapTokenQuotation(CHAIN_ID, {
input: { token: USDC, amount: '1000' },
tokenOut: WBTC,
slippage: 100,
});
const swapLogic = api.protocols.uniswapv3.newSwapTokenLogic(swapQuotation);
// Supply logic
const supplyQuotation = await api.protocols.aavev3.getSupplyQuotation(CHAIN_ID, {
input: swapQuotation.output,
});
const supplyLogic = api.protocols.aavev3.newSupplyLogic(supplyQuotation);
3️⃣ Execute
const routerData = await api.router.getRouterData(CHAIN_ID, {
account,
logics: [swapLogic, supplyLogic],
});
await walletClient.sendTransaction({
to: routerData.router,
data: routerData.data,
value: BigInt(routerData.estimation.value || '0'),
gas: BigInt(routerData.estimation.gas),
});
🏛️ Compound III Integration
1️⃣ Setup
import { getCompound3Comet } from '../src/utils/addresses.js';
const cometAddress = getCompound3Comet(CHAIN_ID);
2️⃣ Supply Collateral
// 1. Approve collateral
await walletClient.writeContract({
address: collateralAddress,
abi: ERC20_ABI,
functionName: 'approve',
args: [cometAddress, amount],
});
// 2. Supply
await walletClient.writeContract({
address: cometAddress,
abi: COMET_ABI,
functionName: 'supply',
args: [collateralAddress, amount],
});
3️⃣ Borrow Base Asset
// In Compound III, you "borrow" by withdrawing the base asset
const baseToken = await publicClient.readContract({
address: cometAddress,
abi: COMET_ABI,
functionName: 'baseToken',
});
await walletClient.writeContract({
address: cometAddress,
abi: COMET_ABI,
functionName: 'withdraw',
args: [baseToken, borrowAmount],
});
🔄 Cross-Protocol Strategies
⚡ Flash Loan Arbitrage
Strategy Flow:
- ⚡ Flash loan asset from Aave
- 🔄 Swap on Uniswap (or other DEX)
- 🔄 Swap on different DEX/pool
- ✅ Repay flash loan + premium
- 💰 Keep profit
📖 See
examples/ts/flashloan-arbitrage.tsfor conceptual example.
📈 Supply-Borrow-Swap
Strategy Flow:
- 💰 Supply collateral to Aave
- 💸 Borrow asset
- 🔄 Swap borrowed asset
- 💰 Supply swapped asset back to Aave
📖 See
examples/ts/supply-borrow-swap.tsfor implementation.
💡 Best Practices
| Practice | Description | Status |
|---|---|---|
| 🛡️ Slippage Protection | Always set minimum output amounts | ✅ |
| ⛽ Gas Costs | Check gas costs for complex transactions | ✅ |
| 🔮 TWAP Oracles | Never rely on spot prices alone | ✅ |
| 🧪 Test on Testnets | Always test before mainnet | ✅ |
| ⚠️ Error Handling | Handle errors gracefully | ✅ |
| 📊 Monitor Positions | Track liquidation risks | ✅ |
| 🔐 Use Permit2 | Save gas on approvals when possible | ✅ |
🎯 Next Steps
- 📖 Review Security Best Practices
- 🔗 Check Chain Configuration for adding new chains
- 📜 Explore example contracts in
contracts/examples/ - 🧪 Run tests in
test/