Files
237-combo/docs/INTEGRATION_GUIDE.md
2026-02-09 21:51:30 -08:00

7.1 KiB
Raw Blame History

🔌 Integration Guide

Step-by-step guide for integrating DeFi protocols into your application.


📋 Table of Contents

  1. Aave v3 Integration
  2. Uniswap v3 Integration
  3. Protocolink Integration
  4. Compound III Integration
  5. 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:

  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

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

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:

  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