Contributing: Adding New Protocols
This guide explains how to add support for new staking pools, lending/borrowing protocols, and other DeFi integrations to eth-portfolio. The system is designed for extensibility, using abstract base classes (ABCs) and a modular protocol architecture.
Choosing the Appropriate Base Class
eth-portfolio supports several types of protocols, each with a corresponding abstract base class. To add a new protocol, first determine which category your integration fits into:
Generic Protocol (ProtocolABC): Use this for most DeFi protocols that do not fit a more specific category. This is the most flexible base class and is suitable for lending, borrowing, or any protocol with custom logic. See: Adding a New Lending/Borrowing or Generic Protocol
Staking Pool (StakingPoolABC): Use this for protocols where users stake tokens to earn rewards, and the pool may have multiple tokens or custom reward logic. See: Adding a New Staking Pool
Single-Token Staking Pool (SingleTokenStakingPoolABC): Use this for staking pools that only accept a single token and have a straightforward staking/reward structure. See: Adding a New Single-Token Staking Pool
Protocol with Staking (ProtocolWithStakingABC): Use this if your protocol combines lending/borrowing or other DeFi features with an integrated staking component. See: Adding a Protocol with Staking
If you are unsure, start with ProtocolABC for lending/borrowing or custom protocols, and use the staking pool base classes for staking integrations. See the subsections below for details and examples.
Adding a New Staking Pool
Subclass StakingPoolABC from eth_portfolio/protocols/_base.py for pools with multiple tokens or custom logic.
Steps: 1. Subclass StakingPoolABC. 2. Implement the _balances method to return a TokenBalances mapping for a given address and block. 3. Implement any required methods such as contract, deploy_block, etc. 4. Register your pool in the appropriate protocol module.
Example:
from eth_portfolio.protocols._base import StakingPoolABC
class MyStakingPool(StakingPoolABC):
def contract(self):
# Return a web3 contract instance for the staking pool
...
async def _balances(self, address, block=None):
# Query the staked balance and rewards for the address
...
See eth_portfolio/protocols/liquity.py for real-world examples.
Adding a New Single-Token Staking Pool
Subclass SingleTokenStakingPoolABC from eth_portfolio/protocols/_base.py for pools that only accept a single token.
Example:
from eth_portfolio.protocols._base import SingleTokenStakingPoolABC
class MySingleTokenStakingPool(SingleTokenStakingPoolABC):
def contract(self):
...
async def _balances(self, address, block=None):
...
See eth_portfolio/protocols/liquity.py and eth_portfolio/protocols/convex.py for examples.
Adding a New Lending/Borrowing or Generic Protocol
Subclass ProtocolABC from eth_portfolio/protocols/_base.py for lending, borrowing, or other custom DeFi protocols.
Steps: 1. Subclass ProtocolABC. 2. Implement the _balances method to return a TokenBalances mapping, including supplied, borrowed, and reward tokens. 3. Register your protocol in the appropriate module.
Example:
from eth_portfolio.protocols._base import ProtocolABC
class MyLendingProtocol(ProtocolABC):
async def _balances(self, address, block=None):
# Query supplied and borrowed balances for the address
...
See eth_portfolio/protocols/dsr.py and eth_portfolio/protocols/lending/ for examples.
Adding a Protocol with Staking
If your protocol combines lending/borrowing with staking, subclass ProtocolWithStakingABC from eth_portfolio/protocols/_base.py.
Example:
from eth_portfolio.protocols._base import ProtocolWithStakingABC
class MyProtocolWithStaking(ProtocolWithStakingABC):
async def _balances(self, address, block=None):
# Query balances and staking positions
...
See eth_portfolio/protocols/convex.py for an example.
Best Practices and Tips
Use Async Methods: All balance queries should be asynchronous for performance.
Handle Edge Cases: Account for protocol-specific quirks, such as non-standard tokens or special reward logic.
Testing: Add tests for your protocol to ensure correctness and compatibility.
Documentation: Document your protocol’s behavior and any configuration requirements.
References
Abstract base classes: eth_portfolio/protocols/_base.py
Example staking pools: eth_portfolio/protocols/liquity.py, eth_portfolio/protocols/convex.py
Example lending protocols: eth_portfolio/protocols/dsr.py, eth_portfolio/protocols/lending/
Protocol registration: eth_portfolio/protocols/__init__.py