321 lines
7.1 KiB
Markdown
321 lines
7.1 KiB
Markdown
|
|
# 🔌 Integration Guide
|
|||
|
|
|
|||
|
|
> Step-by-step guide for integrating DeFi protocols into your application.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📋 Table of Contents
|
|||
|
|
|
|||
|
|
1. [Aave v3 Integration](#-aave-v3-integration)
|
|||
|
|
2. [Uniswap v3 Integration](#-uniswap-v3-integration)
|
|||
|
|
3. [Protocolink Integration](#-protocolink-integration)
|
|||
|
|
4. [Compound III Integration](#-compound-iii-integration)
|
|||
|
|
5. [Cross-Protocol Strategies](#-cross-protocol-strategies)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🏦 Aave v3 Integration
|
|||
|
|
|
|||
|
|
### 1️⃣ Setup
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
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
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 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
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 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
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
await walletClient.writeContract({
|
|||
|
|
address: poolAddress,
|
|||
|
|
abi: POOL_ABI,
|
|||
|
|
functionName: 'flashLoanSimple',
|
|||
|
|
args: [receiverAddress, asset, amount, params, 0],
|
|||
|
|
});
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### Multi-Asset
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
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:
|
|||
|
|
> 1. ✅ Receive the loaned tokens
|
|||
|
|
> 2. ✅ Perform desired operations
|
|||
|
|
> 3. ✅ Approve the pool for `amount + premium`
|
|||
|
|
> 4. ✅ Return `true` from `executeOperation`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🔄 Uniswap v3 Integration
|
|||
|
|
|
|||
|
|
### 1️⃣ Setup
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
import { getUniswapSwapRouter02 } from '../src/utils/addresses.js';
|
|||
|
|
|
|||
|
|
const routerAddress = getUniswapSwapRouter02(CHAIN_ID);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2️⃣ Get Quote
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 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
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 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
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// Always use TWAP, not spot prices, to protect against manipulation
|
|||
|
|
// See examples/ts/uniswap-v3-oracle.ts for implementation
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🔗 Protocolink Integration
|
|||
|
|
|
|||
|
|
### 1️⃣ Setup
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
import * as api from '@protocolink/api';
|
|||
|
|
import * as common from '@protocolink/common';
|
|||
|
|
|
|||
|
|
const CHAIN_ID = common.ChainId.mainnet;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2️⃣ Build Logics
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 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
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
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
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
import { getCompound3Comet } from '../src/utils/addresses.js';
|
|||
|
|
|
|||
|
|
const cometAddress = getCompound3Comet(CHAIN_ID);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2️⃣ Supply Collateral
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 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
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 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:**
|
|||
|
|
|
|||
|
|
1. ⚡ Flash loan asset from Aave
|
|||
|
|
2. 🔄 Swap on Uniswap (or other DEX)
|
|||
|
|
3. 🔄 Swap on different DEX/pool
|
|||
|
|
4. ✅ Repay flash loan + premium
|
|||
|
|
5. 💰 Keep profit
|
|||
|
|
|
|||
|
|
> 📖 See `examples/ts/flashloan-arbitrage.ts` for conceptual example.
|
|||
|
|
|
|||
|
|
### 📈 Supply-Borrow-Swap
|
|||
|
|
|
|||
|
|
**Strategy Flow:**
|
|||
|
|
|
|||
|
|
1. 💰 Supply collateral to Aave
|
|||
|
|
2. 💸 Borrow asset
|
|||
|
|
3. 🔄 Swap borrowed asset
|
|||
|
|
4. 💰 Supply swapped asset back to Aave
|
|||
|
|
|
|||
|
|
> 📖 See `examples/ts/supply-borrow-swap.ts` for 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](./SECURITY.md)
|
|||
|
|
- 🔗 Check [Chain Configuration](./CHAIN_CONFIG.md) for adding new chains
|
|||
|
|
- 📜 Explore example contracts in `contracts/examples/`
|
|||
|
|
- 🧪 Run tests in `test/`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📚 Related Documentation
|
|||
|
|
|
|||
|
|
- 🔐 [Security Best Practices](./SECURITY.md)
|
|||
|
|
- 🔗 [Chain Configuration](./CHAIN_CONFIG.md)
|
|||
|
|
- 🧪 [Strategy Testing Guide](./STRATEGY_TESTING.md)
|
|||
|
|
- ⚙️ [Environment Setup](./ENV_SETUP.md)
|