Disclaimer: This repository is a demo / educational prototype. It is not financial advice. Do not use real funds without understanding the risks. Automated trading on DEXs can result in total loss of capital. You are solely responsible for configuration, compliance, and any trades executed.
Python DEX trading automation prototype with multi-chain adapters, Web3 integration, AWS/KMS signing support and continuous market monitoring.
About the repo name: The repository is historically named
dex-bsc. Originally focused on BSC, it is now structured as a multi-chain DEX automation prototype (Ethereum, BSC, Arbitrum, BSC Testnet). The name is kept for continuity; the codebase and docs reflect the broader scope.
- Architecture
- Supported chains / adapters
- Dry-run / simulation mode
- Example dry-run log
- Risk controls
- Security model
- Getting started
- Docker
- Tests
- What is intentionally not included
- License
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Strategy loop │────▶│ DEX connector │────▶│ Web3 provider │
│ (run.py) │ │ (Pancake/Uniswap)│ │ (chains.py) │
└────────┬────────┘ └────────┬─────────┘ └────────┬────────┘
│ │ │
│ ┌────────▼─────────┐ ┌────────▼────────┐
│ │ Signer abstraction│ │ Execution │
└─────────────▶│ local/lambda/kms │────▶│ monitor │
└──────────────────┘ │ (tx receipt) │
└─────────────────┘
| Layer | Module | Responsibility |
|---|---|---|
| Strategy loop | run.py, blockchain/strategy/analyzer.py |
Polls market, evaluates signals, triggers trades |
| DEX connector | blockchain/contracts/dex/, blockchain/bots/ |
Router swaps, quotes, slippage checks |
| Web3 provider | blockchain/chains/chains.py |
RPC connection, gas, nonce, chain ID |
| Signer | blockchain/account/signers.py |
Local key, AWS Lambda, or KMS (optional) |
| Execution monitor | blockchain/chains/chains.py, blockchain/utils/utils.py |
Broadcast, wait for receipt, dry-run simulation |
Flask (app.py) exposes a minimal health API. The strategy loop runs in a separate process when ENABLE_STRATEGY_LOOP=true.
| Chain | Key | RPC (env override) |
|---|---|---|
| Ethereum | ethereum |
ETHEREUM_RPC_URL |
| BNB Smart Chain | binance-smart-chain |
BSC_RPC_URL |
| Arbitrum | arbitrum |
ARBITRUM_RPC_URL |
| BSC Testnet | binance-smart-chain-testnet |
BSC_TESTNET_RPC_URL |
Set active chain via CHAIN_NAME in .env.
| DEX | Module | Status |
|---|---|---|
| PancakeSwap | blockchain/contracts/dex/pancake_contract.py |
Primary — used in main flow |
| Uniswap V3 | blockchain/contracts/dex/uniswap_router.py, uniswap_quoter.py |
Adapter ready |
| Pancake Factory | blockchain/contracts/dex/pancake_factory.py |
Available |
| Scanner | Chain |
|---|---|
Etherscan |
Ethereum |
Bscscan |
BSC mainnet |
Arbiscan |
Arbitrum |
BscscanTestnet |
BSC testnet |
Coingecko, DefiLlama, OpenSeaAPI under blockchain/api/.
By default DRY_RUN=true. In this mode:
- Transactions are signed in simulation and never broadcast
- Logs are prefixed with
[DRY-RUN]at each pipeline step - Safe for local development, CI and portfolio demos
cp .env.example .env
# keep DRY_RUN=true
python run.pySet DRY_RUN=false only when you intend to execute real on-chain transactions.
There is no web dashboard — the bot is CLI/API-driven. The visual reference is terminal output. Below is a representative dry-run session (also saved in docs/examples/sample_output.log):
$ python run.py
2024-06-12 10:00:01 - my_app - INFO - Starting strategy loop [DRY-RUN]
2024-06-12 10:00:01 - my_app - INFO - [DRY-RUN] Chain: BSC Testnet
2024-06-12 10:00:01 - my_app - INFO - [DRY-RUN] Pair: WBNB/USDT
2024-06-12 10:00:01 - strategy - DEBUG - No signal (latest change 1.9802%)
2024-06-12 10:02:03 - my_app - INFO - [DRY-RUN] Quote received
2024-06-12 10:02:03 - my_app - INFO - [DRY-RUN] Slippage check passed (impact=0.0120, limit=0.0300)
2024-06-12 10:02:05 - my_app - INFO - Executing sell: token=120.5000 busd=45.2300 impact=0.0120 dry_run=True
2024-06-12 10:02:05 - my_app - INFO - [DRY-RUN] Transaction simulated - not broadcast
Health check via Flask (python app.py):
$ curl http://localhost:8080/health
{"status": "ok", "dry_run": true, "loop_enabled": false}
Configured via .env (see .env.example):
| Control | Env variable | Default | Description |
|---|---|---|---|
| Max position | MAX_POSITION |
1000 |
Cap token amount per trade |
| Slippage | MAX_SLIPPAGE |
0.03 |
Max price impact (3%) |
| Gas ceiling | MAX_GWEI |
5 |
Upper bound for gas price |
| Gas boost | EXTRA_GWEI |
1 |
Added on top of network gas |
| Retry | TX_RETRY_COUNT |
3 |
Transaction retry attempts (exponential backoff) |
| Cooldown | COOLDOWN_SECONDS |
60 |
Pause between loop iterations |
| Loop interval | LOOP_INTERVAL_SECONDS |
60 |
Strategy polling interval |
Strategy-specific thresholds (min_amount_sell, max_price_impact, etc.) live in config.py — copy from config.example.py.
- No raw keys in git —
.envandconfig.pyare gitignored; use.env.exampleas template - Signer abstraction —
SIGNER_TYPE=local|lambda|kmsviablockchain/account/signers.py - AWS KMS optional —
blockchain/utils/kmsaws.pyfor remote signing (requires custom adapter for full tx signing) - AWS Lambda optional —
blockchain/utils/lambdaaws.pyfor off-box signing on BSC - Dry-run by default — prevents accidental mainnet broadcasts
- Docker isolation — run the bot in a container with secrets injected at runtime
Never commit private keys, API keys, or production contract addresses.
- Python 3.11+
- (Optional) Docker
- (Optional) AWS account for Lambda/KMS signing
git clone <repo-url>
cd dex-bsc
python -m venv venv && source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
cp config.example.py config.py # optional strategy overrides
# Edit .env — use testnet addresses for experimentationpython app.py
# GET http://localhost:8080/health# In .env: ENABLE_STRATEGY_LOOP=true, DRY_RUN=true
python run.pycp .env.example .env
docker compose up --buildThe container starts Flask on port 8080 with DRY_RUN=true by default.
pip install -r requirements.txt
pytest -v16 unit tests — run in CI or locally before any change.
| Area | Test file | What it verifies |
|---|---|---|
| Chain config loading | tests/test_chain_utils.py |
Registered chains, unknown chain raises |
| Web3 utilities | tests/test_web3_utils.py |
Address checksum, validation, wei conversion |
| Signer abstraction | tests/test_signers.py |
Dry-run signer returns stub tx |
| Dry-run transaction path | tests/test_send_transaction.py |
Simulated send, retry on failure |
| Risk / settings | tests/test_settings.py |
DRY_RUN env parsing defaults |
| Strategy analyzer | tests/test_analyzer.py |
Signal threshold logic |
| Scanner adapters | tests/test_scanners.py |
Explorer query building |
This repo is a portfolio-grade prototype, not a production trading system:
- Real strategy profitability — the bundled
CryptoAnalyzeris an educational placeholder; no backtested alpha - Production execution — no MEV protection, no mempool monitoring, no institutional-grade infra
- Private keys in repo — never; all secrets via
.env/ AWS - Guaranteed returns or live trading advice — demo only
- Web dashboard / UI — CLI logs and a minimal Flask health endpoint only
- Full KMS EVM signing — KMS adapter is optional and requires custom wiring for complete tx signing
MIT — see LICENSE.