This document outlines the design and implementation of a DeFi (Decentralized Finance) Agent built on top of OpenCode without forking the original codebase. The agent provides intelligent analysis and interaction capabilities for DeFi protocols using Python-based tools and OpenCode's extensibility features.
- Create a functional DeFi agent using OpenCode's AGENTS.md and custom commands
- Implement Python-based tools for DeFi operations with mock data
- Design a modular, extensible architecture following best practices
- Enable easy transition from mock to real blockchain data
- Liquidity pool analysis across multiple protocols
- Yield farming opportunity identification
- Portfolio position monitoring
- Token swap simulation with slippage calculation
- Risk assessment and impermanent loss calculation
.
├── .opencode/
│ └── commands/ # Custom OpenCode commands
│ ├── check-liquidity.md
│ ├── analyze-yield.md
│ ├── monitor-positions.md
│ └── execute-swap.md
├── src/
│ ├── tools/ # Python DeFi tools
│ │ ├── __init__.py
│ │ ├── blockchain.py
│ │ ├── defi_protocols.py
│ │ ├── price_feeds.py
│ │ └── analytics.py
│ ├── mocks/ # Mock implementations
│ │ ├── __init__.py
│ │ ├── mock_data.py
│ │ └── data/
│ │ └── defi_data.json
│ ├── utils/ # Utility functions
│ │ ├── __init__.py
│ │ ├── formatters.py
│ │ ├── validators.py
│ │ └── constants.py
│ └── main.py # Entry point
├── tests/ # Test files
│ ├── test_blockchain.py
│ ├── test_defi_protocols.py
│ └── test_analytics.py
├── docs/
│ ├── API.md
│ ├── TOOLS.md
│ └── EXAMPLES.md
├── .env.example
├── .gitignore
├── AGENTS.md # OpenCode agent configuration
├── opencode.json # OpenCode settings
├── requirements.txt # Python dependencies
├── Makefile # Build automation
├── README.md
└── pyproject.toml # Python project config
Python modules that provide the core DeFi functionality:
blockchain.py
class BlockchainTool:
"""Handles blockchain interactions"""
- get_block_number() -> int
- get_gas_price() -> GasPrice
- get_balance(address: str) -> Balance
- get_transaction_history(address: str) -> List[Transaction]
- estimate_gas(from_addr: str, to_addr: str, value: Decimal) -> intdefi_protocols.py
class DeFiProtocolsTool:
"""Manages DeFi protocol interactions"""
- get_liquidity_pools() -> List[LiquidityPool]
- get_pool_stats(pool_id: str) -> PoolStats
- get_yield_farms() -> List[YieldFarm]
- get_user_positions(address: str) -> List[Position]
- simulate_swap(token_from: str, token_to: str, amount: Decimal) -> SwapResultprice_feeds.py
class PriceFeedsTool:
"""Provides token price data"""
- get_token_price(symbol: str) -> Decimal
- get_price_history(symbol: str, period: str) -> List[PricePoint]
- calculate_slippage(token_a: str, token_b: str, amount: Decimal) -> Decimalanalytics.py
class AnalyticsTool:
"""Advanced DeFi analytics"""
- calculate_apy(pool: LiquidityPool) -> Decimal
- analyze_impermanent_loss(position: Position) -> ImpermanentLossReport
- find_arbitrage_opportunities() -> List[ArbitrageOpp]
- generate_portfolio_report(address: str) -> PortfolioReportProvides realistic test data without blockchain connections:
mock_data.py
class MockDataProvider:
"""Manages mock data for all tools"""
- load_mock_data() -> Dict
- get_mock_pools() -> List[Dict]
- get_mock_prices() -> Dict[str, Decimal]
- generate_mock_transaction() -> DictShared utilities and helpers:
validators.py
- is_valid_address(address: str) -> bool
- is_valid_token_symbol(symbol: str) -> bool
- validate_amount(amount: Decimal) -> boolformatters.py
- format_address(address: str) -> str
- format_amount(amount: Decimal, decimals: int) -> str
- format_percentage(value: Decimal) -> str
- wei_to_ether(wei: int) -> Decimalconstants.py
# Common constants
ETHEREUM_DECIMALS = 18
STABLE_COINS = ["USDC", "USDT", "DAI", "BUSD"]
HIGH_RISK_APY_THRESHOLD = Decimal("50")
LOW_LIQUIDITY_THRESHOLD = Decimal("1000000") # $1MThe AGENTS.md file provides OpenCode with context about the DeFi agent:
# DeFi Agent Configuration
## Agent Purpose
This agent specializes in DeFi analysis and operations using Python-based tools.
## Available Tools
- blockchain.py: Blockchain interaction (block info, gas, balances)
- defi_protocols.py: Protocol interactions (pools, yields, swaps)
- price_feeds.py: Token pricing and slippage calculation
- analytics.py: Advanced DeFi analytics and reporting
## Key Behaviors
1. Always validate Ethereum addresses before operations
2. Use Decimal type for all financial calculations
3. Include risk warnings for high APY opportunities (>50%)
4. Format large numbers with appropriate units (K, M, B)
5. Consider gas costs in profitability calculations
## Error Handling
- Wrap all tool calls in try-except blocks
- Provide user-friendly error messages
- Log detailed errors for debugging
- Suggest alternatives when operations fail
## Response Format
- Use tables for comparing multiple options
- Highlight important metrics (APY, TVL, Risk)
- Include actionable recommendations
- Provide context for technical terms# Check Liquidity Pools
Analyze liquidity across all tracked DeFi protocols.
RUN python -m src.tools.defi_protocols analyze_liquidity
Display:
1. Top 10 pools by TVL
2. Pools with highest APY
3. New pools (last 24h)
4. Low liquidity warnings
5. Protocol distribution# Analyze Yield Opportunities
Find best yield farming opportunities based on risk/reward.
RUN python -m src.tools.analytics find_yield_opportunities --min-apy $MIN_APY --max-risk $RISK_LEVEL
Analyze:
1. Risk-adjusted returns
2. Impermanent loss projections
3. Historical stability
4. Gas cost considerations- Use type hints throughout
- Follow PEP 8 style guide
- Use dataclasses for data structures
- Implement proper logging
- Write docstrings for all public methods
{
"liquidity_pools": [
{
"id": "uniswap-v3-eth-usdc",
"name": "ETH/USDC",
"protocol": "Uniswap V3",
"tvl": 245000000,
"apy": 5.2,
"volume_24h": 89000000,
"fees_24h": 267000
}
],
"token_prices": {
"ETH": {
"current": 2350.45,
"change_24h": 2.3
}
}
}def get_pool_stats(pool_id: str) -> PoolStats:
"""Get statistics for a specific pool"""
try:
# Validate input
if not pool_id:
raise ValueError("Pool ID is required")
# Get data
pool_data = self.mock_provider.get_pool(pool_id)
if not pool_data:
raise PoolNotFoundError(f"Pool {pool_id} not found")
# Process and return
return PoolStats.from_dict(pool_data)
except Exception as e:
logger.error(f"Error getting pool stats: {e}")
raise DeFiToolError(f"Failed to get pool stats: {str(e)}")- Unit tests for each tool module
- Integration tests for command execution
- Mock data validation tests
- Error handling tests
- Performance tests for large datasets
init: # Complete setup (install deps, create commands, init mocks)
install: # Install Python dependencies
setup-commands: # Create OpenCode custom commands
setup-mocks: # Initialize mock data
test: # Run pytest
lint: # Run flake8 and black
start: # Launch OpenCode with agent
clean: # Remove generated files-
Initial Setup
make init
-
Development Cycle
- Edit Python tools in
src/tools/ - Update mock data as needed
- Test with
make test - Run agent with
make start
- Edit Python tools in
-
Adding New Features
- Create new tool in
src/tools/ - Add corresponding mock data
- Create custom command in
.opencode/commands/ - Update AGENTS.md with new capabilities
- Write tests
- Create new tool in
- Replace
MockDataProviderwith Web3 provider - Implement wallet connection (e.g.,
web3.py) - Add transaction signing capabilities
- Implement proper RPC endpoint management
- Add retry logic for network failures
- Implement caching for frequently accessed data
- Never store private keys in code
- Use environment variables for sensitive data
- Implement transaction simulation before execution
- Add confirmation prompts for high-value operations
- Log all operations for audit trail
-
Caching Strategy
- Cache token prices (5-minute TTL)
- Cache pool data (1-minute TTL)
- Cache user positions (30-second TTL)
-
Batch Operations
- Batch RPC calls when possible
- Use multicall contracts
- Implement connection pooling
-
Data Processing
- Use pandas for large dataset analysis
- Implement pagination for list operations
- Use async operations where beneficial
import logging
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('defi_agent.log'),
logging.StreamHandler()
]
)-
Functionality
- All commands execute without errors
- Mock data covers edge cases
- Error messages are helpful
-
Performance
- Commands complete in <2 seconds
- Can handle 1000+ pools
- Memory usage stays below 100MB
-
Usability
- Clear documentation
- Intuitive command structure
- Helpful error recovery
This design provides a robust foundation for a DeFi agent that:
- Works seamlessly with OpenCode without forking
- Uses Python for familiar, powerful tooling
- Provides realistic mock data for development
- Can easily transition to production use
- Follows software engineering best practices
The modular architecture ensures easy maintenance and extension while the comprehensive mock system enables thorough testing without blockchain dependencies.