Ethereum Web3 and DeFi protocols integration for Python applications
Project description
Web3-Ethereum-Defi
Web-Ethereum-DeFi (eth_defi) allows you to integrate EVM-compatible Web3 and DeFi protocols into your Python application.
- Use cases
- Supported protocols, chains and integrations
- Prerequisites
- Install
- Example code
- How to use the library in your Python project
- Documentation
- Development and contributing
- Version history
- Support
- Social media
- License
Use cases
Use cases for this package include
- Trading and bots
- Data research, extraction, transformation and loading
- Portfolio management and accounting
- System integrations and backends
- AI agent interaction for EVM chains
Supported protocols, chains and integrations
| Protocol | Actions | Tutorial and API links |
|---|---|---|
| Uniswap | Token swaps, data research | Tutorial |
| Gnosis Safe | Safe deployment customisation and modules | API |
| Circle USDC | USDC interactions | API |
| ChainLink | Read oracle prices, set up oracles | Tutorial |
| CoW Swap | Swaps, vault integration | Tutorial |
| PancakeSwap | Token swaps, data research | Tutorial |
| GMX | Leveraged trading, spot trading | Tutorial |
| gTrade | Leveraged trading, vaults | API |
| Ostium | Leveraged trading, vaults | API |
| LFG | Token swaps, data research | API |
| Aave | Credit, borrow, read rates | Tutorial |
| BENQI | Credit, borrow, read rates | API |
| Lendle | Credit, borrow, read rates | API |
| Sky (MakerDAO) | Credit, borrow, read rates | API |
| Enzyme | Deposit to vaults, deploy, read vault data | Tutorial |
| Lagoon | Deposit to vaults, deploy, read vault data | API |
| Velvet | Deposit to vaults, deploy, read vault data | API |
| Morpho | Read vault data | Tutorial |
| Euler | Read vault data | Tutorial |
| IPOR | Read vault data | Tutorial |
| 1delta | Open/close leveraged long/short positions | API |
| Yearn | Read vault data | API |
| NashPoint | Read vault data | API |
| Untangle Finance | Read vault data | API |
| Plutus | Read vault data | API |
| D2 Finance | Read vault data | API |
| Umami Finance | Read vault data | API |
| Harvest Finance | Read vault data | API |
| USDAi | Read vault data | API |
| AUTO Finance | Read vault data | API |
| Goat Protocol | Read vault data | API |
| Hypersync | Read historical data fast | API |
| Token Risk | Glider Token Risk API by Hexens | API |
| TokenSniffer | Read token risk core and metricws | API |
| Foundry | Compile, deploy and verify smart contracts | API |
| Etherscan | Deploy and verify smart contracts | API |
| MEVBlocker | Frontrun protection | Tutorial |
| Ethereum mainnet | Frontrun protection, token mapping | Tutorial |
| Base | Frontrun protection, token mapping | Tutorial |
| Arbitrum | Frontrun protection, token mapping | Tutorial |
| Avalanche | Token mapping | API |
| BNB chain | Token mapping | API |
| Polygon | Token mapping | API |
| BNB Chain | Token mapping | API |
| Berachain | Token mapping | API |
| Avalanche | Token mapping | API |
| Hyperliquid | Token mapping | API |
| Mode | Token mapping | API |
| Unichain | Token mapping | API |
| ZKSync | Token mapping | API |
| Soneium | Token mapping | API |
| Google GCloud | Support hardware security module wallets | API |
| Hot wallet | Secure hot wallet handling | API |
| Multicall3 | Chunked and historical data reading | Tutorial |
| Gas | Ethereum gas management | API |
| EIP-4626 | Vault analysis | Tutorial |
| EIP-726 | Message signing and decoding | API |
| ERC-20 | High performance reading, data mappings | API |
| ABI | High performance smart contract ABI management | API |
| Transactions | Stack traces and symbolic revert reasons | API |
| Anvil | Mainnet works and local unit testing | API |
| LlamaNodes | Special RPC support | API |
| Ankr | Special RPC support | API |
| dRPC | Special RPC support | API |
👉 Read the full API documentation.
This is a MIT-licensed open source project. Those who sponsor and contribute get integrations.
Prerequisites
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
Install
With pip:
pip install "web3-ethereum-defi[data]"
N.B. From relase 0.32 this project will use v7 of web3py. To keep using it with v6 after the above setup run the following step as well.
pip install "web3-ethereum-defi[web3v6]"
With poetry:
# Poetry version to use the latest web3py v7
poetry add -E data web3-ethereum-defi
# for web3py v6
poetry add -E web3v6 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
# Additional step To force use web3py v6
poetry install -E web3v6
Example code
See the tutorials section in the documentation for full code examples.
Uniswap swap example
- This example shows how to make a trade on Uniswap v3.
- The example is for Polygon, but works on other chains.
- See tutorials for more Uniswap and other DEX examples
import datetime
import decimal
import os
import sys
from decimal import Decimal
from eth_account import Account
from eth_account.signers.local import LocalAccount
from eth_defi.compat import construct_sign_and_send_raw_middleware
from eth_defi.provider.multi_provider import create_multi_provider_web3
from eth_defi.revert_reason import fetch_transaction_revert_reason
from eth_defi.token import fetch_erc20_details
from eth_defi.confirmation import wait_transactions_to_complete
from eth_defi.uniswap_v3.constants import UNISWAP_V3_DEPLOYMENTS
from eth_defi.uniswap_v3.deployment import fetch_deployment
from eth_defi.uniswap_v3.swap import swap_with_slippage_protection
# The address of a token we are going to swap out
#
# Use https://tradingstrategy.ai/search to find your token
#
# For quote terminology see https://tradingstrategy.ai/glossary/quote-token
#
QUOTE_TOKEN_ADDRESS = "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359" # USDC (native)
# The address of a token we are going to receive
#
# Use https://tradingstrategy.ai/search to find your token
#
# For base terminology see https://tradingstrategy.ai/glossary/base-token
BASE_TOKEN_ADDRESS = "0x7ceb23fd6bc0add59e62ac25578270cff1b9f619" # WETH
# Connect to JSON-RPC node
rpc_env_var_name = "JSON_RPC_POLYGON"
json_rpc_url = os.environ.get(rpc_env_var_name)
assert json_rpc_url, f"You need to give {rpc_env_var_name} node URL. Check ethereumnodes.com for options"
# Create a Web3 provider with ability to retry failed requests
# and supporting fallback JSON-RPC nodes. RPC connections
# are extremely flaky and for production grade usage you need to use multiple
# JSON-RPC nodes.
# create_multi_provider_web3() will also take care of any chain-specific
# RPC setup.
web3 = create_multi_provider_web3(json_rpc_url)
print(f"Connected to blockchain, chain id is {web3.eth.chain_id}. the latest block is {web3.eth.block_number:,}")
# Grab Uniswap v3 smart contract addreses for Polygon.
#
deployment_data = UNISWAP_V3_DEPLOYMENTS["polygon"]
uniswap_v3 = fetch_deployment(
web3,
factory_address=deployment_data["factory"],
router_address=deployment_data["router"],
position_manager_address=deployment_data["position_manager"],
quoter_address=deployment_data["quoter"],
)
print(f"Using Uniwap v3 compatible router at {uniswap_v3.swap_router.address}")
# Read and setup a local private key
private_key = os.environ.get("PRIVATE_KEY")
assert private_key is not None, "You must set PRIVATE_KEY environment variable"
assert private_key.startswith("0x"), "Private key must start with 0x hex prefix"
account: LocalAccount = Account.from_key(private_key)
my_address = account.address
# Enable eth_sendTransaction using this private key
web3.middleware_onion.add(construct_sign_and_send_raw_middleware(account))
# Read on-chain ERC-20 token data (name, symbol, etc.)
base = fetch_erc20_details(web3, BASE_TOKEN_ADDRESS)
quote = fetch_erc20_details(web3, QUOTE_TOKEN_ADDRESS)
# Native token balance
# See https://tradingstrategy.ai/glossary/native-token
gas_balance = web3.eth.get_balance(account.address)
print(f"Your address is {my_address}")
print(f"Your have {base.fetch_balance_of(my_address)} {base.symbol}")
print(f"Your have {quote.fetch_balance_of(my_address)} {quote.symbol}")
print(f"Your have {gas_balance / (10 ** 18)} for gas fees")
assert quote.fetch_balance_of(my_address) > 0, f"Cannot perform swap, as you have zero {quote.symbol} needed to swap"
# Ask for transfer details
decimal_amount = input(f"How many {quote.symbol} tokens you wish to swap to {base.symbol}? ")
# Some input validation
try:
decimal_amount = Decimal(decimal_amount)
except (ValueError, decimal.InvalidOperation) as e:
raise AssertionError(f"Not a good decimal amount: {decimal_amount}") from e
# Fat-fingering check
print(f"Confirm swap amount {decimal_amount} {quote.symbol} to {base.symbol}")
confirm = input("Ok [y/n]?")
if not confirm.lower().startswith("y"):
print("Aborted")
sys.exit(1)
# Convert a human-readable number to fixed decimal with 18 decimal places
raw_amount = quote.convert_to_raw(decimal_amount)
# Each DEX trade is two transactions
# - ERC-20.approve()
# - swap (various functions)
# This is due to bad design of ERC-20 tokens,
# more here https://twitter.com/moo9000/status/1619319039230197760
# Uniswap router must be allowed to spent our quote token
# and we do this by calling ERC20.approve() from our account
# to the token contract.
approve = quote.contract.functions.approve(uniswap_v3.swap_router.address, raw_amount)
tx_1 = approve.build_transaction(
{
# approve() may take more than 500,000 gas on Arbitrum One
"gas": 850_000,
"from": my_address,
}
)
#
# Uniswap v3 may have multiple pools per
# trading pair differetiated by the fee tier. For example
# WETH-USDC has pools of 0.05%, 0.30% and 1%
# fees. Check for different options
# in https://tradingstrategy.ai/search
#
# Here we use 5 BPS fee pool (5/10,000).
#
#
# Build a swap transaction with slippage protection
#
# Slippage protection is very important, or you
# get instantly overrun by MEV bots with
# sandwitch attacks
#
# https://tradingstrategy.ai/glossary/mev
#
#
bound_solidity_func = swap_with_slippage_protection(
uniswap_v3,
base_token=base,
quote_token=quote,
max_slippage=20, # Allow 20 BPS slippage before tx reverts
amount_in=raw_amount,
recipient_address=my_address,
pool_fees=[500], # 5 BPS pool WETH-USDC
)
tx_2 = bound_solidity_func.build_transaction(
{
# Uniswap swap should not take more than 1M gas units.
# We do not use automatic gas estimation, as it is unreliable
# and the number here is the maximum value only.
# Only way to know this number is by trial and error
# and experience.
"gas": 1_000_000,
"from": my_address,
}
)
# Sign and broadcast the transaction using our private key
tx_hash_1 = web3.eth.send_transaction(tx_1)
tx_hash_2 = web3.eth.send_transaction(tx_2)
# This will raise an exception if we do not confirm within the timeout.
# If the timeout occurs the script abort and you need to
# manually check the transaction hash in a blockchain explorer
# whether the transaction completed or not.
tx_wait_minutes = 2.5
print(f"Broadcasted transactions {tx_hash_1.hex()}, {tx_hash_2.hex()}, now waiting {tx_wait_minutes} minutes for it to be included in a new block")
print(f"View your transactions confirming at https://polygonscan/address/{my_address}")
receipts = wait_transactions_to_complete(
web3,
[tx_hash_1, tx_hash_2],
max_timeout=datetime.timedelta(minutes=tx_wait_minutes),
confirmation_block_count=1,
)
# Check if any our transactions failed
# and display the reason
for completed_tx_hash, receipt in receipts.items():
if receipt["status"] == 0:
revert_reason = fetch_transaction_revert_reason(web3, completed_tx_hash)
raise AssertionError(f"Our transaction {completed_tx_hash.hex()} failed because of: {revert_reason}")
print("All ok!")
print(f"After swap, you have {base.fetch_balance_of(my_address)} {base.symbol}")
print(f"After swap, you have {quote.fetch_balance_of(my_address)} {quote.symbol}")
print(f"After swap, you have {gas_balance / (10 ** 18)} native token left")
How to use the library in your Python project
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]"
Documentation
Development and contributing
Version history
Support
Social media
License
MIT.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file web3_ethereum_defi-0.34.tar.gz.
File metadata
- Download URL: web3_ethereum_defi-0.34.tar.gz
- Upload date:
- Size: 58.3 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.4 CPython/3.11.10 Darwin/24.6.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c4ef6a2297a0bf8498a1516d4eb0ae81e1f93bba81e08b1ac207abd4af441185
|
|
| MD5 |
87a56d62bb765af6567fc01db54d68b8
|
|
| BLAKE2b-256 |
a26cf0237883ca4e2a0d22974520f5fe85b990c81569bb065a03f67698151d61
|
File details
Details for the file web3_ethereum_defi-0.34-py3-none-any.whl.
File metadata
- Download URL: web3_ethereum_defi-0.34-py3-none-any.whl
- Upload date:
- Size: 61.4 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.4 CPython/3.11.10 Darwin/24.6.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
66354bec2bcb5cdb29998399efeca0331c236a4ffcb642a9be9c73b35e90d487
|
|
| MD5 |
0075de39a1db87ef1d4c49da252c4907
|
|
| BLAKE2b-256 |
511b457df2a948cfa55a3936de7ac53dd7fd186f315c3bcacf16b6b396a2f49d
|