uni-exec-engine 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- uni_exec_engine-0.2.0/LICENSE +21 -0
- uni_exec_engine-0.2.0/MANIFEST.in +3 -0
- uni_exec_engine-0.2.0/PKG-INFO +576 -0
- uni_exec_engine-0.2.0/README.md +545 -0
- uni_exec_engine-0.2.0/pyproject.toml +58 -0
- uni_exec_engine-0.2.0/setup.cfg +4 -0
- uni_exec_engine-0.2.0/src/uni_exec_engine.egg-info/PKG-INFO +576 -0
- uni_exec_engine-0.2.0/src/uni_exec_engine.egg-info/SOURCES.txt +93 -0
- uni_exec_engine-0.2.0/src/uni_exec_engine.egg-info/dependency_links.txt +1 -0
- uni_exec_engine-0.2.0/src/uni_exec_engine.egg-info/requires.txt +11 -0
- uni_exec_engine-0.2.0/src/uni_exec_engine.egg-info/top_level.txt +1 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/__init__.py +3 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/analytics/__init__.py +0 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/analytics/il_calculator.py +525 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/analytics/portfolio.py +234 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/analytics/position.py +433 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/analytics/range_suggest.py +270 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/audit.py +194 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/common/__init__.py +0 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/common/approval_cleanup.py +255 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/common/check_balance.py +64 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/common/common.py +804 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/common/deep_link.py +132 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/common/gas.py +141 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/data/auto_trade_policy.example.json +29 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/data/chains.json +135 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/data/common-token-addresses.json +777 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/execute/__init__.py +0 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/execute/_internal/__init__.py +5 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/execute/_internal/constants.py +15 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/execute/_internal/preflight.py +150 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/execute/_internal/pure_signer.py +182 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/execute/_internal/rpc.py +462 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/execute/_internal/signer.py +298 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/execute/_internal/submit.py +73 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/execute/_internal/tx.py +370 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/execute/broadcast.py +380 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/execute/detect.py +52 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/execute/telegram_confirm.py +272 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/lp/compare_pools.py +338 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/lp/v2/__init__.py +0 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/lp/v2/approve.py +100 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/lp/v2/build_tx.py +226 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/lp/v2/flow.py +204 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/lp/v2/pair.py +135 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/lp/v2/positions.py +177 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/lp/v3/__init__.py +0 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/lp/v3/approve.py +109 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/lp/v3/auto_rebalance.py +282 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/lp/v3/build_tx.py +465 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/lp/v3/compound.py +258 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/lp/v3/flow.py +358 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/lp/v3/pool.py +175 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/lp/v3/position.py +112 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/lp/v3/tick.py +75 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/lp/v4/__init__.py +0 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/lp/v4/approve.py +105 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/lp/v4/build_tx.py +669 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/lp/v4/flow.py +368 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/lp/v4/pool.py +174 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/lp/v4/position.py +185 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/policy.py +371 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/price_feed.py +100 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/py.typed +0 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/search/__init__.py +0 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/search/risk.py +200 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/search/search.py +580 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/state_machine.py +315 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/swap/__init__.py +1 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/swap/deep_link.py +69 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/swap/extensions/__init__.py +2 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/swap/extensions/bridge.py +197 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/swap/extensions/limit_order.py +272 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/swap/extensions/slippage.py +123 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/swap/flow.py +693 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/swap/flow_core/__init__.py +2 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/swap/flow_core/artifacts.py +11 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/swap/flow_core/broadcast.py +50 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/swap/flow_core/diagnostics.py +216 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/swap/flow_core/paper.py +113 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/swap/flow_core/policy.py +142 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/swap/links/__init__.py +2 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/swap/links/deep_link.py +69 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/swap/trading_api/permit.py +41 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/swap/trading_api/quote.py +282 -0
- uni_exec_engine-0.2.0/src/uniswap_autopilot/swap/trading_api/swap.py +248 -0
- uni_exec_engine-0.2.0/tests/test_audit.py +66 -0
- uni_exec_engine-0.2.0/tests/test_compound_rebalance.py +364 -0
- uni_exec_engine-0.2.0/tests/test_policy.py +139 -0
- uni_exec_engine-0.2.0/tests/test_risk.py +67 -0
- uni_exec_engine-0.2.0/tests/test_state_machine.py +147 -0
- uni_exec_engine-0.2.0/tests/test_telegram_confirm.py +83 -0
- uni_exec_engine-0.2.0/tests/test_token_cache.py +107 -0
- uni_exec_engine-0.2.0/tests/test_uniswap_lp.py +158 -0
- uni_exec_engine-0.2.0/tests/test_uniswap_trading.py +2177 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 counterfactual5
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,576 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: uni-exec-engine
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Automated swap execution, LP management, and analytics for Uniswap v2/v3/v4
|
|
5
|
+
Author: counterfactual5
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Repository, https://github.com/counterfactual5/uniswap-autopilot
|
|
8
|
+
Project-URL: Issues, https://github.com/counterfactual5/uniswap-autopilot/issues
|
|
9
|
+
Keywords: uniswap,defi,swap,liquidity,lp,ethereum,evm,trading
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Provides-Extra: signer
|
|
23
|
+
Requires-Dist: eth-account>=0.10.0; extra == "signer"
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
26
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
27
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
28
|
+
Provides-Extra: all
|
|
29
|
+
Requires-Dist: eth-account>=0.10.0; extra == "all"
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
<div align="center">
|
|
33
|
+
|
|
34
|
+
# ⚡ Uniswap Autopilot
|
|
35
|
+
|
|
36
|
+
### The execution layer uniswap-ai forgot to build.
|
|
37
|
+
|
|
38
|
+
**Plan swaps with AI → Execute them on-chain. Automatically.**
|
|
39
|
+
|
|
40
|
+
Pure Python · Zero Dependencies · Uniswap v2 / v3 / v4 · 6 Chains · 13K Lines
|
|
41
|
+
|
|
42
|
+
[](https://github.com/counterfactual5/uniswap-autopilot/actions)
|
|
43
|
+
[](https://www.python.org/downloads/)
|
|
44
|
+
[](LICENSE)
|
|
45
|
+
|
|
46
|
+
[Installation](#installation) · [Features](#features) · [Quick Start](#quick-start) · [Architecture](#architecture) · [Comparison](#how-does-this-compare-to-uniswap-ai)
|
|
47
|
+
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
> [!IMPORTANT]
|
|
53
|
+
> **Trading safety.** Broadcast paths run through a shared risk-control policy
|
|
54
|
+
> (amount caps, chain allow-list, address blacklist, slippage, min-output)
|
|
55
|
+
> evaluated between the `PREFLIGHT` and `SIGNED` states. Read
|
|
56
|
+
> **[RISK_POLICY.md](RISK_POLICY.md)** and copy `policy.yaml` to
|
|
57
|
+
> `~/.stageforge/policy.yaml` before going live.
|
|
58
|
+
|
|
59
|
+
## The Problem
|
|
60
|
+
|
|
61
|
+
[uniswap-ai](https://github.com/Uniswap/uniswap-ai) is Uniswap Labs' official project. It teaches AI agents to plan trades and generate deep links. But when the agent actually needs to **execute**? It says:
|
|
62
|
+
|
|
63
|
+
> *"Open this link in your browser."*
|
|
64
|
+
|
|
65
|
+
That's not autonomous. That's a bookmark.
|
|
66
|
+
|
|
67
|
+
**uniswap-autopilot closes the loop.** It takes the plan and does the work — quote, approve, sign, broadcast, receipt — all in Python, no browser needed.
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
You: "Swap 0.1 ETH for USDC on Base"
|
|
71
|
+
|
|
72
|
+
uniswap-ai: "Here's a deep link. Open it in your browser."
|
|
73
|
+
uniswap-autopilot: ✅ Quoted → Approved → Signed → Broadcast → 0xabc123...
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Features
|
|
79
|
+
|
|
80
|
+
### 🔄 LP Auto-Management
|
|
81
|
+
|
|
82
|
+
The largest module at 4,500 lines. Nothing like this exists in any open-source Uniswap Python library.
|
|
83
|
+
|
|
84
|
+
- **Auto-Rebalance** — v3 position goes out of range? Automatically withdraw and redeploy to a new range
|
|
85
|
+
- **Compound** — harvest uncollected fees and reinvest into the same position
|
|
86
|
+
- **v4 PoolManager** — full LP lifecycle for Uniswap v4's new architecture
|
|
87
|
+
- **v2 Classic LP** — add/remove liquidity for traditional AMM pools
|
|
88
|
+
- **Pool Comparison** — compare fee tiers, TVL, and volume to pick the best pool
|
|
89
|
+
|
|
90
|
+
### ⚡ Complete Swap Pipeline
|
|
91
|
+
|
|
92
|
+
Not just quotes. The full chain from "I want to trade" to "tx confirmed on-chain":
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
Quote → Permit/Approval → Sign → Preflight Check → Broadcast → Receipt
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
- **Uniswap Trading API** — direct integration with quote, swap, and permit2 endpoints
|
|
99
|
+
- **Preflight checks** — verifies you have the balance, allowance, and gas *before* signing
|
|
100
|
+
- **Policy engine** — define auto-trading rules in JSON (chain, pair, amount, slippage limits)
|
|
101
|
+
- **Paper trading** — dry-run mode: records everything, executes nothing
|
|
102
|
+
- **Dynamic slippage** — auto-adjusts tolerance based on real-time volatility
|
|
103
|
+
|
|
104
|
+
### 📊 Analytics Suite
|
|
105
|
+
|
|
106
|
+
Quantitative tools that help LPs make real decisions:
|
|
107
|
+
|
|
108
|
+
| Tool | What it does |
|
|
109
|
+
|---|---|
|
|
110
|
+
| IL Calculator | Exact impermanent loss at any price ratio |
|
|
111
|
+
| Range Suggest | Recommends concentrated liquidity ranges from volatility |
|
|
112
|
+
| Position Analysis | Tracks uncollected fees, PnL, and position health |
|
|
113
|
+
| Portfolio Valuation | Aggregate value across multiple positions |
|
|
114
|
+
|
|
115
|
+
### 🔍 Token Search & Risk Scoring
|
|
116
|
+
|
|
117
|
+
- **Multi-source** — DexScreener + GeckoTerminal, deduplicated
|
|
118
|
+
- **Risk assessment** — composite score from liquidity, volume, market cap, and price volatility
|
|
119
|
+
- **Token cache** — local cache with auto-refresh, works offline
|
|
120
|
+
|
|
121
|
+
### 🌉 Extensions
|
|
122
|
+
|
|
123
|
+
- **Cross-chain Bridge** — detect and route cross-chain swaps automatically
|
|
124
|
+
- **Limit Orders** — on-chain limit order logic
|
|
125
|
+
- **Telegram Confirmation** — human-in-the-loop approval via inline buttons
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## How Does This Compare to uniswap-ai?
|
|
130
|
+
|
|
131
|
+
| | uniswap-ai (official) | uniswap-autopilot |
|
|
132
|
+
|---|:---:|:---:|
|
|
133
|
+
| What is it? | 11 markdown docs | 13K lines of Python |
|
|
134
|
+
| Swap quotes | 📄 Documentation | ✅ **Executable API** |
|
|
135
|
+
| Swap execution | 🔗 Generates a deep link | ✅ **Quote → Sign → Broadcast** |
|
|
136
|
+
| LP management | 📄 Planning docs | ✅ **Auto-rebalance + compound** |
|
|
137
|
+
| LP analytics | ❌ | ✅ **IL / ranges / portfolio** |
|
|
138
|
+
| Token risk scoring | ❌ | ✅ **Multi-factor scoring** |
|
|
139
|
+
| Cross-chain bridge | ❌ | ✅ |
|
|
140
|
+
| Limit orders | ❌ | ✅ |
|
|
141
|
+
| Human confirmation | ❌ | ✅ **Telegram buttons** |
|
|
142
|
+
| Dependencies | npm / bun / Foundry | **Zero** |
|
|
143
|
+
| Tests | 0 | **99** |
|
|
144
|
+
| Install | Complex setup | `pip install uniswap-autopilot` |
|
|
145
|
+
|
|
146
|
+
> **They're complementary.** Use uniswap-ai for planning, use this for execution.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Installation
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# Analysis + quotes + LP planning — zero dependencies
|
|
154
|
+
pip install uniswap-autopilot
|
|
155
|
+
|
|
156
|
+
# Add on-chain signing & broadcasting (eth-account)
|
|
157
|
+
pip install uniswap-autopilot[signer]
|
|
158
|
+
|
|
159
|
+
# Development
|
|
160
|
+
pip install -e ".[dev]"
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
That's it. No Foundry. No npm. No web3.py. Pure Python.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Quick Start
|
|
168
|
+
|
|
169
|
+
### 📊 Analyze Impermanent Loss
|
|
170
|
+
|
|
171
|
+
```python
|
|
172
|
+
from uniswap_autopilot.analytics.il_calculator import calculate_il
|
|
173
|
+
|
|
174
|
+
# ETH-USDC pool, 1% fee tier, entry at $3000
|
|
175
|
+
il = calculate_il(
|
|
176
|
+
price_entry=3000.0,
|
|
177
|
+
price_current=3300.0, # 10% up
|
|
178
|
+
tick_lower=-887220, tick_upper=887220,
|
|
179
|
+
decimals0=18, decimals1=6,
|
|
180
|
+
liquidity=1000000000000,
|
|
181
|
+
)
|
|
182
|
+
print(f" IL: {il['ilPct']:.2f}%")
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
Price 1.1x → IL: 0.04%
|
|
187
|
+
Price 1.5x → IL: 0.56%
|
|
188
|
+
Price 2.0x → IL: 2.02%
|
|
189
|
+
Price 3.0x → IL: 5.36%
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### 🎯 Get LP Range Suggestions
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
from uniswap_autopilot.analytics.range_suggest import suggest_ranges
|
|
196
|
+
|
|
197
|
+
ranges = suggest_ranges(
|
|
198
|
+
chain_name="ethereum",
|
|
199
|
+
token_a="ETH", token_b="USDC",
|
|
200
|
+
fee_tier=3000,
|
|
201
|
+
)
|
|
202
|
+
for r in ranges:
|
|
203
|
+
print(f" ${r['lower']:,.0f} — ${r['upper']:,.0f} ({r['profile']})")
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
$2,400 — $3,600 (conservative)
|
|
208
|
+
$2,100 — $4,200 (balanced)
|
|
209
|
+
$1,800 — $4,800 (aggressive)
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### 💱 Get a Swap Quote
|
|
213
|
+
|
|
214
|
+
```python
|
|
215
|
+
from uniswap_autopilot.swap.trading_api.quote import build_quote_payload, summarize_quote
|
|
216
|
+
|
|
217
|
+
quote = build_quote_payload(
|
|
218
|
+
wallet="0x...",
|
|
219
|
+
chain_id=8453,
|
|
220
|
+
api_token_in="ETH",
|
|
221
|
+
api_token_out="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", # USDC on Base
|
|
222
|
+
base_amount="0.1",
|
|
223
|
+
swap_type="EXACT_INPUT",
|
|
224
|
+
slippage="0.5",
|
|
225
|
+
routing_preference="CLASSIC",
|
|
226
|
+
)
|
|
227
|
+
print(summarize_quote(quote))
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
```
|
|
231
|
+
Swap 0.1 ETH → ~175.42 USDC on Base
|
|
232
|
+
Route: ETH → USDC (0.05% fee)
|
|
233
|
+
Estimated gas: ~$0.02
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### 🔍 Search & Score Tokens
|
|
237
|
+
|
|
238
|
+
```python
|
|
239
|
+
from uniswap_autopilot.search.search import search_tokens
|
|
240
|
+
from uniswap_autopilot.search.risk import assess_risk
|
|
241
|
+
|
|
242
|
+
results = search_tokens(query="PEPE", chain="ethereum", limit=3)
|
|
243
|
+
for token in results:
|
|
244
|
+
risk = assess_risk(token["address"], "ethereum")
|
|
245
|
+
print(f" {token['symbol']:8s} risk={risk['level']} ${token['price']:.8f}")
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
```
|
|
249
|
+
PEPE risk= 72/100 $0.00001234
|
|
250
|
+
PEPECOIN risk= 35/100 $0.4521
|
|
251
|
+
PEPECEO risk= 12/100 $0.00000001
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### ⚡ Execute a Trade (with signing)
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
export EXECUTOR_PRIVATE_KEY=0x... # Never written to disk
|
|
258
|
+
export WALLET_ADDRESS=0x...
|
|
259
|
+
export RPC_URL_BASE=https://mainnet.base.org
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
```python
|
|
263
|
+
from uniswap_autopilot.swap.flow import run_trade_flow
|
|
264
|
+
|
|
265
|
+
result = run_trade_flow(
|
|
266
|
+
chain="base",
|
|
267
|
+
input_token="ETH",
|
|
268
|
+
output_token="USDC",
|
|
269
|
+
amount="0.01",
|
|
270
|
+
auto_confirm=True, # skip human confirmation
|
|
271
|
+
)
|
|
272
|
+
print(result["swap"]["transactionHash"])
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
```
|
|
276
|
+
✅ Quoted: 0.01 ETH → 17.54 USDC
|
|
277
|
+
✅ Approved: USDC spender set
|
|
278
|
+
✅ Signed: via eth-account
|
|
279
|
+
✅ Broadcast: 0xabc123...def456
|
|
280
|
+
✅ Confirmed in block 19,847,231
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### 🔄 Auto-Rebalance an LP Position
|
|
284
|
+
|
|
285
|
+
```python
|
|
286
|
+
from uniswap_autopilot.lp.v3.auto_rebalance import execute_rebalance
|
|
287
|
+
|
|
288
|
+
result = execute_rebalance(
|
|
289
|
+
position={"token_id": 123456, "chain": "ethereum"},
|
|
290
|
+
strategy="balanced",
|
|
291
|
+
volatility_pct=30,
|
|
292
|
+
)
|
|
293
|
+
if result["rebalanced"]:
|
|
294
|
+
print(f" Old range: {result['old_range']}")
|
|
295
|
+
print(f" New range: {result['new_range']}")
|
|
296
|
+
print(f" TX: {result['transactionHash']}")
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### 🧪 Paper Trade (Safe Mode)
|
|
300
|
+
|
|
301
|
+
```python
|
|
302
|
+
# Everything runs, nothing executes on-chain
|
|
303
|
+
result = run_trade_flow(
|
|
304
|
+
chain="base",
|
|
305
|
+
input_token="ETH",
|
|
306
|
+
output_token="USDC",
|
|
307
|
+
amount="0.1",
|
|
308
|
+
paper_trade=True, # <--- dry run
|
|
309
|
+
)
|
|
310
|
+
print(result["journal"]) # full trade journal without spending gas
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## Architecture
|
|
316
|
+
|
|
317
|
+
### System Overview
|
|
318
|
+
|
|
319
|
+
```
|
|
320
|
+
┌─────────────────────────────────────────┐
|
|
321
|
+
│ AI Agent / User │
|
|
322
|
+
└──────┬──────────┬──────────┬───────────┘
|
|
323
|
+
│ │ │
|
|
324
|
+
┌──────────▼──┐ ┌────▼─────┐ ┌─▼──────────┐
|
|
325
|
+
│ 🔍 Search │ │ 📊 Ana │ │ 🔄 LP │
|
|
326
|
+
│ & Risk │ │ lytics │ │ Management │
|
|
327
|
+
│ 750 lines │ │ 1500 ln │ │ 4500 lines │
|
|
328
|
+
└──────┬───────┘ └────┬─────┘ └─┬──────────┘
|
|
329
|
+
│ │ │
|
|
330
|
+
└───────┬───────┘ │
|
|
331
|
+
│ │
|
|
332
|
+
┌────────▼─────────┐ │
|
|
333
|
+
│ ⚡ Swap Flow │◄────────┘
|
|
334
|
+
│ 2,500 lines │ (rebalance uses
|
|
335
|
+
│ │ swap internally)
|
|
336
|
+
│ ┌─────────────┐ │
|
|
337
|
+
│ │ flow_core │ │
|
|
338
|
+
│ │ • Policy │ │
|
|
339
|
+
│ │ • Paper │ │
|
|
340
|
+
│ │ • Diag │ │
|
|
341
|
+
│ └──────┬──────┘ │
|
|
342
|
+
└─────────┼─────────┘
|
|
343
|
+
│
|
|
344
|
+
┌─────────▼──────────┐
|
|
345
|
+
│ 🔐 Execute Layer │
|
|
346
|
+
│ 1,900 lines │
|
|
347
|
+
│ │
|
|
348
|
+
│ preflight → sign │
|
|
349
|
+
│ → broadcast → │
|
|
350
|
+
│ receipt │
|
|
351
|
+
└─────────┬──────────┘
|
|
352
|
+
│
|
|
353
|
+
┌───────────────┼────────────────┐
|
|
354
|
+
│ │ │
|
|
355
|
+
┌─────▼─────┐ ┌────▼─────┐ ┌──────▼──────┐
|
|
356
|
+
│ JSON-RPC │ │ eth-acct │ │ Telegram │
|
|
357
|
+
│ (urllib) │ │ signing │ │ confirm │
|
|
358
|
+
└─────┬──────┘ └────┬─────┘ └─────────────┘
|
|
359
|
+
│ │
|
|
360
|
+
└──────┬───────┘
|
|
361
|
+
│
|
|
362
|
+
┌──────▼──────┐
|
|
363
|
+
│ EVM Chain │
|
|
364
|
+
│ ETH·BASE· │
|
|
365
|
+
│ ARB·OP· │
|
|
366
|
+
│ POLY·UNI │
|
|
367
|
+
└─────────────┘
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Data Flow: Swap Execution
|
|
371
|
+
|
|
372
|
+
```
|
|
373
|
+
User Input Uniswap API Local Processing On-Chain
|
|
374
|
+
─────────── ──────────── ───────────────── ─────────
|
|
375
|
+
|
|
376
|
+
"Swap 0.1 quote endpoint Policy check ┌──────┐
|
|
377
|
+
ETH→USDC" ──→ (GET /quote) ──→ Slippage adjust ──→ │ │
|
|
378
|
+
on Base" │ │
|
|
379
|
+
│ EVM │
|
|
380
|
+
swap endpoint Preflight check │ Chain│
|
|
381
|
+
──→ (GET /swap) ──→ balance / allowance ──→ │ │
|
|
382
|
+
│ │
|
|
383
|
+
Sign TX │ │
|
|
384
|
+
──→ (eth-account) ──→ │ │
|
|
385
|
+
│ │
|
|
386
|
+
Broadcast │ │
|
|
387
|
+
──→ (eth_sendRawTx) ──→ └──────┘
|
|
388
|
+
↓
|
|
389
|
+
✅ Receipt
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### Package Structure
|
|
393
|
+
|
|
394
|
+
```
|
|
395
|
+
uniswap_autopilot/ 13,000 lines total
|
|
396
|
+
│
|
|
397
|
+
├── swap/ 2,500 Full swap pipeline
|
|
398
|
+
│ ├── trading_api/ Uniswap Trading API — quote / swap / permit2
|
|
399
|
+
│ ├── flow_core/ Policy engine, diagnostics, paper trading
|
|
400
|
+
│ ├── extensions/ Bridge, limit orders, dynamic slippage
|
|
401
|
+
│ └── links/ Deep link generation
|
|
402
|
+
│
|
|
403
|
+
├── lp/ 4,500 Liquidity provision (largest module)
|
|
404
|
+
│ ├── v2/ Classic AMM — add / remove / positions
|
|
405
|
+
│ ├── v3/ Concentrated liquidity — auto-rebalance, compound
|
|
406
|
+
│ ├── v4/ PoolManager — v4 LP flows
|
|
407
|
+
│ └── compare_pools Fee tier & TVL comparison
|
|
408
|
+
│
|
|
409
|
+
├── analytics/ 1,500 Quantitative tools
|
|
410
|
+
│ ├── il_calculator Impermanent loss at any price ratio
|
|
411
|
+
│ ├── range_suggest Concentrated liquidity range optimization
|
|
412
|
+
│ ├── position Fee tracking, PnL, health monitoring
|
|
413
|
+
│ └── portfolio Multi-position aggregation
|
|
414
|
+
│
|
|
415
|
+
├── search/ 750 Token intelligence
|
|
416
|
+
│ ├── search DexScreener + GeckoTerminal
|
|
417
|
+
│ └── risk Multi-factor risk scoring
|
|
418
|
+
│
|
|
419
|
+
├── execute/ 1,900 Transaction engine
|
|
420
|
+
│ ├── _internal/rpc Pure JSON-RPC over urllib
|
|
421
|
+
│ ├── _internal/pure_signer eth-account signing (optional dep)
|
|
422
|
+
│ ├── _internal/signer Backend detection & wallet resolution
|
|
423
|
+
│ ├── _internal/submit eth_sendRawTransaction broadcast
|
|
424
|
+
│ ├── _internal/preflight Balance / allowance / gas pre-checks
|
|
425
|
+
│ ├── broadcast Main broadcast orchestrator
|
|
426
|
+
│ ├── detect Backend capability detection
|
|
427
|
+
│ └── telegram_confirm Human-in-the-loop via Telegram
|
|
428
|
+
│
|
|
429
|
+
├── common/ 1,400 Shared utilities
|
|
430
|
+
│ └── ... Chain config, token resolution, gas, balances
|
|
431
|
+
│
|
|
432
|
+
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
## Supported Chains
|
|
436
|
+
|
|
437
|
+
| Chain | Chain ID | Native Token | LP Versions |
|
|
438
|
+
|---|---|---|---|
|
|
439
|
+
| Ethereum | 1 | ETH | v2 · v3 · v4 |
|
|
440
|
+
| Base | 8453 | ETH | v2 · v3 · v4 |
|
|
441
|
+
| Arbitrum | 42161 | ETH | v2 · v3 · v4 |
|
|
442
|
+
| Optimism | 10 | ETH | v2 · v3 · v4 |
|
|
443
|
+
| Polygon | 137 | MATIC | v2 · v3 |
|
|
444
|
+
| Unichain | 130 | ETH | v3 · v4 |
|
|
445
|
+
|
|
446
|
+
Plus 13 additional chains configurable via [`data/chains.json`](data/chains.json).
|
|
447
|
+
|
|
448
|
+
## Security Model
|
|
449
|
+
|
|
450
|
+
| Concern | How we handle it |
|
|
451
|
+
|---|---|
|
|
452
|
+
| Private keys | Environment variables only — never written to disk, never logged |
|
|
453
|
+
| Transaction signing | In-process via eth-account — no external CLI, no IPC, no file I/O |
|
|
454
|
+
| Large trades | Telegram inline buttons for human confirmation before broadcast |
|
|
455
|
+
| Preflight checks | Balance, allowance, and gas verified *before* signing |
|
|
456
|
+
| Supply chain | Zero npm, zero Foundry, zero web3.py — pure Python stdlib |
|
|
457
|
+
| RPC calls | Direct JSON-RPC over urllib — no middleware, no proxy |
|
|
458
|
+
|
|
459
|
+
## 🔐 Private Key Security
|
|
460
|
+
|
|
461
|
+
Your private key is the only thing standing between your funds and an attacker. This library takes a strict approach:
|
|
462
|
+
|
|
463
|
+
**How this library handles your key:**
|
|
464
|
+
- Read from environment variable `EXECUTOR_PRIVATE_KEY` — **never** stored in a file, config, or database
|
|
465
|
+
- Used in-process via `eth-account` for signing — no shell command, no IPC, no temp file
|
|
466
|
+
- **Never logged** — the key appears nowhere in stdout, debug output, or trade journals
|
|
467
|
+
|
|
468
|
+
**Author's setup (production-grade isolation):**
|
|
469
|
+
|
|
470
|
+
```
|
|
471
|
+
┌─────────────────┐ HTTPS ┌──────────────────┐
|
|
472
|
+
│ Agent Process │ ──────────────────→ │ Signing Service │
|
|
473
|
+
│ (no private │ sign request │ (holds key in │
|
|
474
|
+
│ key access) │ ←────────────────── │ HSM / enclave) │
|
|
475
|
+
└─────────────────┘ signed payload └──────────────────┘
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
- Private key lives in a **separate signing microservice** on an isolated machine
|
|
479
|
+
- Agent process **never sees the key** — only sends transaction payloads to be signed
|
|
480
|
+
- Communication over HTTPS with Bearer token auth
|
|
481
|
+
- This is the most secure architecture but requires infrastructure setup
|
|
482
|
+
|
|
483
|
+
**Recommended approaches (pick your level):**
|
|
484
|
+
|
|
485
|
+
| Level | Approach | Security | Complexity |
|
|
486
|
+
|---|---|---|---|
|
|
487
|
+
| ⭐ Basic | Environment variable + `pip install uniswap-autopilot[signer]` | Good for dev/testing | Zero |
|
|
488
|
+
| ⭐⭐ Standard | `.env` file (gitignored) + env var | Good for personal bots | Low |
|
|
489
|
+
| ⭐⭐⭐ Advanced | Dedicated signing service (separate machine / Docker) | Production-grade | Medium |
|
|
490
|
+
| ⭐⭐⭐⭐ Maximum | HSM or AWS KMS backed signing service | Institutional-grade | High |
|
|
491
|
+
|
|
492
|
+
**Rules that apply to every level:**
|
|
493
|
+
|
|
494
|
+
1. **Never commit a private key to git** — not in code, not in config, not in `.env` (unless `.env` is in `.gitignore`)
|
|
495
|
+
2. **Never paste your key in an AI chat** — LLM providers may log and train on your input
|
|
496
|
+
3. **Use a dedicated trading wallet** — fund it with only what you're willing to lose
|
|
497
|
+
4. **Test on testnet first** — every chain has a faucet, use it before mainnet
|
|
498
|
+
5. **Set spending limits** — use `auto_trade_policy.json` to cap per-trade amounts
|
|
499
|
+
|
|
500
|
+
```bash
|
|
501
|
+
# Basic setup (Level ⭐)
|
|
502
|
+
# Step 1: Create a dedicated wallet
|
|
503
|
+
# Step 2: Export the private key
|
|
504
|
+
export EXECUTOR_PRIVATE_KEY=0x...
|
|
505
|
+
export WALLET_ADDRESS=0x...
|
|
506
|
+
export RPC_URL_BASE=https://mainnet.base.org
|
|
507
|
+
|
|
508
|
+
# Step 3: Add to your shell profile (never to git)
|
|
509
|
+
echo 'export EXECUTOR_PRIVATE_KEY=0x...' >> ~/.bashrc # or ~/.zshrc
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
## For AI Agent Developers
|
|
513
|
+
|
|
514
|
+
This library is designed as the execution backend for coding agents:
|
|
515
|
+
|
|
516
|
+
```python
|
|
517
|
+
# 1. Research → search tokens, assess risk
|
|
518
|
+
# 2. Plan → get quote, calculate optimal slippage
|
|
519
|
+
# 3. Verify → preflight balance/allowance/gas check
|
|
520
|
+
# 4. Execute → sign + broadcast (with optional human confirmation)
|
|
521
|
+
# 5. Report → receipt, PnL journal, position health
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
Compatible with:
|
|
525
|
+
- **[uniswap-ai](https://github.com/Uniswap/uniswap-ai)** — use for planning, use this for execution
|
|
526
|
+
- **[Claude Code](https://docs.anthropic.com/en/docs/claude-code)** / **[Cursor](https://cursor.sh)** — import directly in agent scripts
|
|
527
|
+
- **[Codex](https://github.com/openai/codex)** — `pip install` in sandbox, execute trades
|
|
528
|
+
- **Any MCP-compatible agent** — wrap the API in an MCP tool server
|
|
529
|
+
|
|
530
|
+
## Development
|
|
531
|
+
|
|
532
|
+
```bash
|
|
533
|
+
# Install with dev dependencies
|
|
534
|
+
pip install -e ".[dev]"
|
|
535
|
+
|
|
536
|
+
# Run tests
|
|
537
|
+
pytest # 99 tests
|
|
538
|
+
pytest --cov=uniswap_autopilot # with coverage
|
|
539
|
+
pytest -x # stop at first failure
|
|
540
|
+
|
|
541
|
+
# Lint
|
|
542
|
+
ruff check src/ tests/
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
## Roadmap
|
|
546
|
+
|
|
547
|
+
- [ ] MCP server wrapper for plug-and-play agent integration
|
|
548
|
+
- [x] PyPI package publishing
|
|
549
|
+
- [ ] Async support (async/await)
|
|
550
|
+
- [ ] More DEX aggregators (1inch, Paraswap)
|
|
551
|
+
- [ ] Position monitoring & alerting
|
|
552
|
+
- [ ] Backtesting framework
|
|
553
|
+
|
|
554
|
+
## Contributing
|
|
555
|
+
|
|
556
|
+
Contributions welcome! Areas of particular interest:
|
|
557
|
+
|
|
558
|
+
- **More chains** — add config to `data/chains.json`
|
|
559
|
+
- **More analytics** — fee income forecasting, Monte Carlo IL simulation
|
|
560
|
+
- **More extensions** — DCA, TWAP, MEV protection
|
|
561
|
+
- **Tests** — the more the merrier
|
|
562
|
+
- **Docs** — tutorials, API reference, integration guides
|
|
563
|
+
|
|
564
|
+
Please open an issue first to discuss what you'd like to change.
|
|
565
|
+
|
|
566
|
+
## License
|
|
567
|
+
|
|
568
|
+
[MIT](LICENSE) — use it however you want.
|
|
569
|
+
|
|
570
|
+
---
|
|
571
|
+
|
|
572
|
+
If this project helped you, please ⭐ star this repo — it helps others find it!
|
|
573
|
+
|
|
574
|
+
### Related Projects
|
|
575
|
+
|
|
576
|
+
- **[defi-autopilot](https://github.com/counterfactual5/defi-autopilot)** — Multi-protocol DeFi toolkit (Aave, Compound, Morpho, Moonwell, Curve, Lido, 1inch + Uniswap). If you need more than just Uniswap, check it out.
|