Web-Ethereum-DeFi (eth_defi
) Python package provides high level modules for smart
contracts, with prepackaged ABI files for DeFi protocol integration,
wallet management, JSON-RPC providers and automated test suites. The
package aims for robustness, high quality of the code and documentation.
- Use cases
- Prerequisites
- Install
- Code examples
- How to use the library in your Python project
- Documentation
- Version history
- Support
- Social media
- History
- License
- Supported blockchains include Ethereum, BNB Chain, Polygon, Avalanche C-chain, Arbitrum and many other EVM-compatible blockchains.
- Supported DeFi protocols include Uniswap with its clones, Aave, USDC, other Circle stablecoin tokens, Enzyme, Chainlink and many others.
Use cases for this package include
- Trading and bots
- Data research, extraction, transformation and loading
- Portfolio management and accounting
- System integrations and backends
Features include e.g.
- High-quality API documentation
- Fully type hinted for good developer experience
- MEV protection
- Mainnet forking with Anvil
- Revert reasons and stack traces for Solidity errors
- Swap, slippage and price impact estimation
- ERC-20 token issuance and transfers
- EIP-712, EIP-3009 support
Web3-Ethereum-Defi supports
- Uniswap (both v2 and v3)
- Sushi
- Aave
- Enzyme Protocol
- dHEDGE Protocol
- More integrations to come
- Built-in integration for over 600 smart contracts with precompiled Solidity ABI files
Read the full API documentation). For code examples please see below.
To use this package you need to
- Have Python 3.10, Python 3.11, or Python 3.12 (no other versions tested)
- macOS, Linux or Windows Subsystem for Linux (WSL) needed, Microsoft Windows is not officially supported
- Be proficient in Python programming
- Understand of Web3.py library
- Understand Pytest basics
With pip
:
pip install "web3-ethereum-defi[data]"
With poetry
:
# Poetry version
poetry add -E data web3-ethereum-defi
With poetry
- master Git branch:
git clone git@github.com:tradingstrategy-ai/web3-ethereum-defi.git
cd web3-ethereum-defi
poetry shell
poetry install --all-extras
See the tutorials section in the documentation for full code examples.
-
This example shows how to read the live trades of PancakeSwap, and other Uniswap v2 compatible forks on BNB Smart Chain
-
See the instructions and full example source code in Tutorials
import os
import time
from functools import lru_cache
from web3 import HTTPProvider, Web3
from eth_defi.abi import get_contract
from eth_defi.chain import install_chain_middleware
from eth_defi.event_reader.filter import Filter
from eth_defi.event_reader.logresult import decode_log
from eth_defi.event_reader.reader import read_events, LogResult
from eth_defi.uniswap_v2.pair import fetch_pair_details, PairDetails
QUOTE_TOKENS = ["BUSD", "USDC", "USDT"]
@lru_cache(maxsize=100)
def fetch_pair_details_cached(web3: Web3, pair_address: str) -> PairDetails:
return fetch_pair_details(web3, pair_address)
def main():
json_rpc_url = os.environ.get("JSON_RPC_BINANCE", "https://bsc-dataseed.binance.org/")
web3 = Web3(HTTPProvider(json_rpc_url))
web3.middleware_onion.clear()
install_chain_middleware(web3)
# Read the prepackaged ABI files and set up event filter
# for any Uniswap v2 like pool on BNB Smart Chain (not just PancakeSwap).
#
# We use ABI files distributed by SushiSwap project.
#
Pair = get_contract(web3, "sushi/UniswapV2Pair.json")
filter = Filter.create_filter(address=None, event_types=[Pair.events.Swap])
latest_block = web3.eth.block_number
# Keep reading events as they land
while True:
start = latest_block
end = web3.eth.block_number
evt: LogResult
for evt in read_events(
web3,
start_block=start,
end_block=end,
filter=filter,
):
decoded = decode_log(evt)
# Swap() events are generated by UniswapV2Pool contracts
pair = fetch_pair_details_cached(web3, decoded["address"])
token0 = pair.token0
token1 = pair.token1
block_number = evt["blockNumber"]
# Determine the human-readable order of token tickers
if token0.symbol in QUOTE_TOKENS:
base = token1 # token
quote = token0 # stablecoin/BNB
base_amount = decoded["args"]["amount1Out"] - decoded["args"]["amount1In"]
quote_amount = decoded["args"]["amount0Out"] - decoded["args"]["amount0In"]
else:
base = token0 # stablecoin/BNB
quote = token1 # token
base_amount = decoded["args"]["amount0Out"] - decoded["args"]["amount0Out"]
quote_amount = decoded["args"]["amount1Out"] - decoded["args"]["amount1Out"]
# Calculate the price in Python Decimal class
if base_amount and quote_amount:
human_base_amount = base.convert_to_decimals(base_amount)
human_quote_amount = quote.convert_to_decimals(quote_amount)
price = human_quote_amount / human_base_amount
if human_quote_amount > 0:
# We define selling when the stablecoin amount increases
# in the swap
direction = "sell"
else:
direction = "buy"
price = abs(price)
print(f"Swap block:{block_number:,} tx:{evt['transactionHash']} {direction} price:{price:,.8f} {base.symbol}/{quote.symbol}")
else:
# Swap() event from DEX that is not Uniswap v2 compatible
# print(f"Swap block:{block_number:,} tx:{evt['transactionHash']} could not decode")
pass
else:
# No event detected between these blocks
print(".")
latest_block = end
time.sleep(1)
if __name__ == "__main__":
main()
Add web3-ethereum-defi
as a development dependency:
Using Poetry:
# Data optional dependencies include pandas and gql, needed to fetch Uniswap v3 data
poetry add -D "web3-ethereum-defi[data]"
MIT.