DeFiPy 2.1.0a2__tar.gz → 2.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.
- {defipy-2.1.0a2 → defipy-2.2.0}/DeFiPy.egg-info/PKG-INFO +84 -53
- {defipy-2.1.0a2 → defipy-2.2.0}/DeFiPy.egg-info/requires.txt +7 -2
- {defipy-2.1.0a2 → defipy-2.2.0}/PKG-INFO +84 -53
- {defipy-2.1.0a2 → defipy-2.2.0}/README.md +77 -50
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/pool_health/CheckPoolHealth.py +12 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/twin/_rpc.py +96 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/twin/live_provider.py +257 -37
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/twin/snapshot.py +2 -3
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/PoolHealth.py +19 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/setup.py +16 -8
- {defipy-2.1.0a2 → defipy-2.2.0}/DeFiPy.egg-info/SOURCES.txt +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/DeFiPy.egg-info/dependency_links.txt +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/DeFiPy.egg-info/not-zip-safe +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/DeFiPy.egg-info/top_level.txt +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/LICENSE +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/NOTICE +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/ImpermanentLossAgent.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/PriceThresholdSwapAgent.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/TVLBasedLiquidityExitAgent.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/VolumeSpikeNotifierAgent.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/config/ImpermanentLossConfig.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/config/PriceThresholdConfig.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/config/TVLExitConfig.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/config/VolumeSpikeConfig.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/config/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/data/UniswapPoolData.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/data/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/analytics/risk/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/analytics/simulate/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/erc/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/math/basic/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/math/interest/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/math/interest/ips/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/math/interest/ips/aggregate/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/math/model/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/math/risk/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/comparison/CompareFeeTiers.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/comparison/CompareProtocols.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/comparison/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/execution/CalculateSlippage.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/execution/DetectMEV.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/execution/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/optimization/EvaluateRebalance.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/optimization/EvaluateTickRanges.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/optimization/OptimalDepositSplit.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/optimization/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/pool_health/DetectFeeAnomaly.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/pool_health/DetectRugSignals.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/pool_health/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/portfolio/AggregatePortfolio.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/portfolio/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/position/AnalyzeBalancerPosition.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/position/AnalyzePosition.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/position/AnalyzeStableswapPosition.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/position/FindBreakEvenPrice.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/position/FindBreakEvenTime.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/position/SimulateBalancerPriceMove.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/position/SimulatePriceMove.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/position/SimulateStableswapPriceMove.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/position/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/risk/AssessDepegRisk.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/risk/CheckTickRangeStatus.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/risk/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/process/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/process/burn/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/process/deposit/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/process/join/Join.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/process/join/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/process/liquidity/AddLiquidity.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/process/liquidity/RemoveLiquidity.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/process/liquidity/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/process/mint/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/process/swap/Swap.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/process/swap/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/tools/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/tools/registry.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/tools/schemas.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/twin/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/twin/builder.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/twin/mock_provider.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/twin/provider.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/client/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/client/contract/ExecuteScript.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/client/contract/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/BalancerPositionAnalysis.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/BalancerPriceMoveScenario.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/BreakEvenAlphas.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/BreakEvenTime.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/DepegRiskAssessment.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/DepositSplitResult.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/FeeAnomalyResult.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/FeeTierCandidate.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/FeeTierComparison.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/MEVDetectionResult.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/PortfolioAnalysis.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/PortfolioPosition.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/PositionAnalysis.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/PriceMoveScenario.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/ProtocolComparison.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/RebalanceCostReport.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/RugSignalReport.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/SlippageAnalysis.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/StableswapPositionAnalysis.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/StableswapPriceMoveScenario.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/TickRangeCandidate.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/TickRangeEvaluation.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/TickRangeStatus.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/interfaces/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/tools/UniswapScriptHelper.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/tools/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/tools/v3/__init__.py +0 -0
- {defipy-2.1.0a2 → defipy-2.2.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: DeFiPy
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Python SDK for Agentic DeFi
|
|
5
5
|
Home-page: http://github.com/defipy-devs/defipy
|
|
6
6
|
Author: icmoore
|
|
@@ -21,15 +21,19 @@ Requires-Dist: uniswappy>=1.7.9
|
|
|
21
21
|
Requires-Dist: balancerpy>=1.1.0
|
|
22
22
|
Requires-Dist: stableswappy>=1.1.0
|
|
23
23
|
Provides-Extra: chain
|
|
24
|
-
Requires-Dist: web3scout>=0.
|
|
24
|
+
Requires-Dist: web3scout>=1.0.0; extra == "chain"
|
|
25
25
|
Requires-Dist: web3<7.0,>=6.0; extra == "chain"
|
|
26
26
|
Provides-Extra: book
|
|
27
|
-
Requires-Dist: web3scout>=0.
|
|
27
|
+
Requires-Dist: web3scout>=1.0.0; extra == "book"
|
|
28
28
|
Requires-Dist: web3<7.0,>=6.0; extra == "book"
|
|
29
29
|
Provides-Extra: anvil
|
|
30
30
|
Requires-Dist: web3<7.0,>=6.0; extra == "anvil"
|
|
31
31
|
Provides-Extra: mcp
|
|
32
32
|
Requires-Dist: mcp>=1.27.0; extra == "mcp"
|
|
33
|
+
Provides-Extra: agentic
|
|
34
|
+
Requires-Dist: web3scout>=1.0.0; extra == "agentic"
|
|
35
|
+
Requires-Dist: web3<7.0,>=6.0; extra == "agentic"
|
|
36
|
+
Requires-Dist: mcp>=1.27.0; extra == "agentic"
|
|
33
37
|
Dynamic: author
|
|
34
38
|
Dynamic: author-email
|
|
35
39
|
Dynamic: description
|
|
@@ -51,29 +55,42 @@ Underneath, DeFiPy is modular by protocol:
|
|
|
51
55
|
* [BalancerPy](https://github.com/defipy-devs/balancerpy)
|
|
52
56
|
* [StableSwapPy](https://github.com/defipy-devs/stableswappy)
|
|
53
57
|
|
|
54
|
-
For onchain event access and scripting,
|
|
58
|
+
For onchain event access and scripting, use [LiveProvider](https://defipy.org/live-provider/) as of v2.1 — it pulls live pool state into the same primitive surface that runs against synthetic recipes. Under the hood it's powered by [Web3Scout](https://github.com/defipy-devs/web3scout); install via the `[chain]` extra (see below). For details on architecture behind [State Twins](https://defipy.org/twin-concept/), see paper [](https://arxiv.org/abs/2605.11522)
|
|
55
59
|
|
|
56
|
-
|
|
60
|
+
## 🆕 What's new in v2.2
|
|
61
|
+
|
|
62
|
+
v2.2 extends `LiveProvider` from Uniswap V2/V3 to **Balancer** and **Curve-style Stableswap** — chain reads now cover all four protocol families through the same `provider.snapshot(...)` → `StateTwinBuilder().build(...)` flow.
|
|
63
|
+
|
|
64
|
+
* **Balancer LiveProvider** — `provider.snapshot("balancer:0xADDR")` builds a `BalancerPoolSnapshot` from a real Balancer V2 weighted pool (2-asset). Two block-pinned round trips, since token balances live on the Vault keyed by `poolId`. Normalized weights read honestly; reserves decimal-adjusted.
|
|
65
|
+
* **Stableswap LiveProvider** — `provider.snapshot("stableswap:0xADDR")` builds an N-coin `StableswapPoolSnapshot` (N ∈ {2, 3}, e.g. the DAI/USDC/USDT 3pool) from a real Curve plain pool. Coin count comes from an `n_coins` hint or an automatic `coins(0..K)` probe; plain pools only.
|
|
66
|
+
* **`multicall_aggregate3_args`** — an argument-bearing Multicall3 batch (encodes calldata args, optional `allow_failure`) powering the Balancer/Curve reads alongside the no-arg getters, all block-pinned. The existing no-arg `multicall_aggregate3` and the V3 path are unchanged.
|
|
67
|
+
* **web3scout `>= 1.0.0`** — the `[chain]` / `[book]` / `[agentic]` extras now pin web3scout 1.0, which carries the Balancer/Curve read ABIs.
|
|
68
|
+
|
|
69
|
+
See the [CHANGELOG](./CHANGELOG.md) for the full v2.2 entry. v2.2 is a strict superset of v2.1.
|
|
57
70
|
|
|
58
71
|
## 🆕 What's new in v2.1
|
|
59
72
|
|
|
60
|
-
v2.1 makes the State Twin **real
|
|
73
|
+
v2.1 makes the [State Twin](https://defipy.org/twin-concept/) **real** — the substrate formalized in [our arXiv paper](https://arxiv.org/abs/2605.11522). `LiveProvider` ships for Uniswap V2 and V3 — chain reads compose with every primitive in the library, the same way `MockProvider` recipes do. The "what would happen if?" loop is now local: pull state once, simulate forever, decide before executing.
|
|
61
74
|
|
|
62
75
|
* **`LiveProvider`** — `provider.snapshot("uniswap_v2:0xADDR")` and `provider.snapshot("uniswap_v3:0xADDR")` build `V2PoolSnapshot` and `V3PoolSnapshot` from real on-chain state. Block pinning is automatic — `"latest"` resolves once at the top of `.snapshot()` and every read inside that snapshot pins to the same block. Pass `block_number=N` for historical reads.
|
|
63
76
|
* **Multicall3 batching for V3** — V3 snapshots batch `slot0`, `liquidity`, `fee`, `tickSpacing`, `token0`, `token1`, and block timestamp into one [Multicall3](https://github.com/mds1/multicall) `aggregate3` round trip. Hardcoded canonical Multicall3 address; works on every major EVM chain.
|
|
64
77
|
* **`PoolSnapshot` enrichment** — every snapshot now carries `block_number`, `timestamp`, `chain_id` as optional fields. `LiveProvider` populates them from chain reads; `MockProvider` leaves them `None` to honestly signal "synthetic, not chain state."
|
|
78
|
+
* **`PoolHealth` ergonomics for V3** — `CheckPoolHealth` now reports `fee_pips` (V3 fee tier in pips, `None` for V2), `tvl_in_token1` (symmetric to existing `tvl_in_token0`), and `tick_current` (V3 current tick, `None` for V2). All additive; no API breakage. `RugSignalReport` gets the new fields transitively.
|
|
79
|
+
* **`provider.get_w3()`** — the underlying `web3.Web3` instance is now public, for callers who want to sign transactions or wire LiveProvider into their own broader chain tooling. DeFiPy stays read-only by design; bring your own signing opinion.
|
|
80
|
+
* **Fork-and-evaluate worked example** — [`python/examples/state_twin_fork_evaluate.py`](./python/examples/state_twin_fork_evaluate.py) demonstrates the State Twin's multi-scenario reasoning pattern against live mainnet state. Pull a V3 pool snapshot once, fork the twin N ways under price scenarios, run primitives against each fork, aggregate into a recommendation. Walks through the pattern at [defipy.org/fork-evaluate/](https://defipy.org/fork-evaluate/).
|
|
65
81
|
* **`[chain]` install extra** — `pip install defipy[chain]` adds `web3scout` and `web3.py` for users who want LiveProvider. Core install (no extras) remains free of any chain or LLM dependencies.
|
|
82
|
+
* **`[agentic]` install extra** — `pip install defipy[agentic]` composes `[chain]` and `[mcp]` for the canonical *Python SDK for Agentic DeFi* full-stack install. Equivalent to `pip install defipy[chain,mcp]` but spelled with intent.
|
|
66
83
|
|
|
67
84
|
V2.1 is a strict superset of v2.0 — every v2.0 primitive, MockProvider recipe, and MCP server pattern works identically. What changes is that the same primitives now run against live chain state without changing call shape.
|
|
68
85
|
|
|
69
|
-
**What
|
|
86
|
+
**What was deferred to v2.2 (now shipped):** Balancer and Stableswap LiveProvider reads landed in v2.2 (see above). Still open: V3 tick bitmap walking — V3 LiveProvider snapshots cover active-liquidity only, so primitives that depend on non-active-tick liquidity (e.g., `AssessLiquidityDepth`) and N-asset Balancer / rate-bearing Curve pools remain future work.
|
|
70
87
|
|
|
71
88
|
## v2.0 foundations
|
|
72
89
|
|
|
73
90
|
The State Twin abstraction, agentic primitives, and MCP server pattern shipped in v2.0. v2.1 builds on that surface without changing it:
|
|
74
91
|
|
|
75
92
|
* **`defipy.tools`** — self-describing schemas for a curated set of 10 leaf primitives, in [Model Context Protocol](https://modelcontextprotocol.io) (MCP) format. Any MCP-compatible client can discover and invoke DeFiPy primitives as tools.
|
|
76
|
-
* **`defipy.twin`** — the **State Twin** abstraction. `MockProvider` ships four canonical synthetic pools (V2, V3, Balancer, Stableswap) for notebooks and tests; `LiveProvider` ships chain reads for
|
|
93
|
+
* **`defipy.twin`** — the **State Twin** abstraction. `MockProvider` ships four canonical synthetic pools (V2, V3, Balancer, Stableswap) for notebooks and tests; `LiveProvider` ships chain reads for all four families (V2/V3 in v2.1, Balancer/Stableswap in v2.2).
|
|
77
94
|
* **MCP server demo** at [`python/mcp/`](./python/mcp/) — a stdio-transport server exposing DeFiPy's tools to Claude Desktop, Claude Code, or any MCP client. Install with `pip install defipy[mcp]` and see the [MCP server README](./python/mcp/README.md) for setup.
|
|
78
95
|
|
|
79
96
|
### What is MCP?
|
|
@@ -88,7 +105,9 @@ Claude reads the tool descriptions, picks `CheckPoolHealth`, calls it against a
|
|
|
88
105
|
|
|
89
106
|
## 🧩 What DeFiPy offers
|
|
90
107
|
|
|
91
|
-
|
|
108
|
+
**7 [Core primitives](https://defipy.org/core-primitives/)** for cross-protocol pool execution — `Join`, `Swap`, `AddLiquidity`, `RemoveLiquidity`, `SwapDeposit`, `WithdrawSwap`, `LPQuote`. State-mutating operations that work across Uniswap V2/V3, Balancer, and Stableswap through a single abstract interface.
|
|
109
|
+
|
|
110
|
+
**21 [Agentic primitives](https://defipy.org/agentic-primitives/)** across 7 categories. Each answers a specific LP question with exact math and returns a typed dataclass result:
|
|
92
111
|
|
|
93
112
|
* **Position analysis** — "Why is my position losing money? What if price moves X%?" PnL decomposition (IL, fees, net result) and price-move scenarios across Uniswap V2/V3, Balancer, and Stableswap. Includes break-even pricing and time-to-breakeven analysis.
|
|
94
113
|
* **Pool health** — "Is this pool healthy? Any rug signals?" TVL, LP concentration, activity, threshold-based rug detection, fee-anomaly checks (V2/V3).
|
|
@@ -113,14 +132,16 @@ DeFiPy requires **Python 3.10 or later**. Install via pip:
|
|
|
113
132
|
> pip install defipy
|
|
114
133
|
```
|
|
115
134
|
|
|
116
|
-
The core install is the pure analytics engine — AMM math, primitives, State Twin, and all
|
|
135
|
+
The core install is the pure analytics engine — AMM math, primitives, State Twin, and all 21 typed analytics functions. It has **zero web3 dependencies and zero LLM dependencies**. No chain reads, no RPC calls, no MCP. Chain reads come from [Web3Scout](https://github.com/defipy-devs/web3scout) (via the `[chain]` or `[book]` extras); MCP tool serving comes from the `[mcp]` extra. All optional.
|
|
136
|
+
|
|
137
|
+
> **Note for zsh users (default on macOS):** wrap any install spec with extras in single quotes — `pip install 'defipy[agentic]'` — so zsh doesn't try to glob the brackets. Without the quotes, you'll see `zsh: no matches found`. Bash users can use either form.
|
|
117
138
|
|
|
118
139
|
### Chain install (LiveProvider — v2.1+)
|
|
119
140
|
|
|
120
141
|
To use `LiveProvider` for on-chain pool snapshots, install the `[chain]` extra:
|
|
121
142
|
|
|
122
143
|
```
|
|
123
|
-
> pip install defipy[chain]
|
|
144
|
+
> pip install 'defipy[chain]'
|
|
124
145
|
```
|
|
125
146
|
|
|
126
147
|
This pulls in `web3scout` (which `LiveProvider` uses internally for ABI loading, contract reads, and token-fetching) plus `web3.py`. With `[chain]` installed, you can construct twins from real chain state:
|
|
@@ -133,34 +154,36 @@ snapshot = provider.snapshot("uniswap_v2:0xB4e16d0168e52d35CaCD2c6185b44281Ec28C
|
|
|
133
154
|
lp = StateTwinBuilder().build(snapshot)
|
|
134
155
|
```
|
|
135
156
|
|
|
136
|
-
> **Note:** the `[chain]` extra pins `web3 < 7.0` because `web3scout 0.2.0` depends on `eth_utils.abi.get_abi_input_types`, which was removed in web3 7. If you have web3 7.x installed for other reasons, `pip install defipy[chain]` will downgrade it. Tracking upstream as v2.2 work.
|
|
157
|
+
> **Note:** the `[chain]` extra pins `web3 < 7.0` because `web3scout 0.2.0` depends on `eth_utils.abi.get_abi_input_types`, which was removed in web3 7. If you have web3 7.x installed for other reasons, `pip install 'defipy[chain]'` will downgrade it. Tracking upstream as v2.2 work.
|
|
137
158
|
|
|
138
|
-
###
|
|
159
|
+
### Agentic install (full LLM + chain stack)
|
|
139
160
|
|
|
140
|
-
|
|
161
|
+
For users building LLM-driven systems against live chain state — the canonical *Python SDK for Agentic DeFi* use case — install the `[agentic]` extra:
|
|
141
162
|
|
|
142
163
|
```
|
|
143
|
-
> pip install defipy[
|
|
164
|
+
> pip install 'defipy[agentic]'
|
|
144
165
|
```
|
|
145
166
|
|
|
146
|
-
This
|
|
167
|
+
This composes `[chain]` and `[mcp]` in one step: `web3scout` and `web3.py` for `LiveProvider` chain reads, plus the `mcp` Python SDK for serving DeFiPy's primitives as tools to Claude Desktop, Claude Code, or any MCP-compatible client. Equivalent to `pip install defipy[chain,mcp]` but spelled with intent.
|
|
168
|
+
|
|
169
|
+
The same `web3 < 7.0` pin from the `[chain]` extra applies.
|
|
147
170
|
|
|
148
|
-
###
|
|
171
|
+
### MCP install (Claude Desktop / Claude Code demo)
|
|
149
172
|
|
|
150
|
-
|
|
173
|
+
To run the MCP server that exposes DeFiPy's primitives as tools to Claude Desktop, Claude Code, or any MCP-compatible client, install the `[mcp]` extra:
|
|
151
174
|
|
|
152
175
|
```
|
|
153
|
-
> pip install defipy[
|
|
176
|
+
> pip install 'defipy[mcp]'
|
|
154
177
|
```
|
|
155
178
|
|
|
156
|
-
|
|
179
|
+
This adds the [`mcp`](https://github.com/modelcontextprotocol/python-sdk) Python SDK on top of the core install. The MCP server itself lives at [`python/mcp/defipy_mcp_server.py`](./python/mcp/defipy_mcp_server.py); see [`python/mcp/README.md`](./python/mcp/README.md) for Claude Desktop and Claude Code configuration snippets.
|
|
157
180
|
|
|
158
181
|
### Anvil install (local Foundry workflows)
|
|
159
182
|
|
|
160
183
|
If you're using `ExecuteScript` or `UniswapScriptHelper` against a local [Anvil](https://book.getfoundry.sh/anvil/) node and don't need the full `web3scout` event-monitoring stack, the lighter `[anvil]` extra just adds `web3.py`:
|
|
161
184
|
|
|
162
185
|
```
|
|
163
|
-
> pip install defipy[anvil]
|
|
186
|
+
> pip install 'defipy[anvil]'
|
|
164
187
|
```
|
|
165
188
|
|
|
166
189
|
`[book]` and `[chain]` already include everything in `[anvil]`, so users on either of those don't need it separately.
|
|
@@ -196,13 +219,6 @@ See the [gmpy2 installation docs](https://gmpy2.readthedocs.io/en/latest/install
|
|
|
196
219
|
DeFiPy is accompanied by educational resources for developers and researchers
|
|
197
220
|
interested in on-chain analytics and DeFi modeling.
|
|
198
221
|
|
|
199
|
-
### 📘 Textbook
|
|
200
|
-
**_DeFiPy: Python SDK for On-Chain Analytics_**
|
|
201
|
-
|
|
202
|
-
A comprehensive guide to DeFi analytics, AMM modeling, and simulation.
|
|
203
|
-
|
|
204
|
-
🔗 **Buy on Amazon:** https://www.amazon.com/dp/B0G3RV5QRB
|
|
205
|
-
|
|
206
222
|
### 🎓 Course
|
|
207
223
|
**On-Chain Analytics Foundations**
|
|
208
224
|
|
|
@@ -223,35 +239,29 @@ Topics include:
|
|
|
223
239
|
|
|
224
240
|
The fastest way to see DeFiPy at work — pull a real Uniswap V2 pool's state from mainnet and run a primitive against it. Requires the `[chain]` install extra.
|
|
225
241
|
|
|
226
|
-
from defipy import
|
|
242
|
+
from defipy import CheckPoolHealth
|
|
227
243
|
from defipy.twin import LiveProvider, StateTwinBuilder
|
|
228
|
-
|
|
229
|
-
# Pull live state from a real Uniswap
|
|
230
|
-
provider = LiveProvider("https://
|
|
244
|
+
|
|
245
|
+
# Pull live state from a real Uniswap V3 pool — USDC/WETH 500bps mainnet
|
|
246
|
+
provider = LiveProvider("https://mainnet.infura.io/v3/d2d6569915ec402b82c9379d033f8b9b")
|
|
231
247
|
snapshot = provider.snapshot(
|
|
232
|
-
"
|
|
248
|
+
"uniswap_v3:0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640"
|
|
233
249
|
)
|
|
234
250
|
lp = StateTwinBuilder().build(snapshot)
|
|
235
|
-
|
|
251
|
+
lp.summary()
|
|
252
|
+
|
|
236
253
|
# Snapshot carries chain context — block_number, timestamp, chain_id
|
|
237
|
-
print(f"Block:
|
|
238
|
-
|
|
239
|
-
f"{snapshot.token1_name}={snapshot.reserve1:.2f}")
|
|
240
|
-
|
|
254
|
+
print(f"Block: {snapshot.block_number}")
|
|
255
|
+
|
|
241
256
|
# Run any primitive against the live twin — same call shape as MockProvider
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
)
|
|
257
|
+
health = CheckPoolHealth().apply(lp)
|
|
258
|
+
print(f"Fee tier: {health.fee_pips} pips")
|
|
259
|
+
print(f"TVL (USDC): {health.tvl_in_token0:,.2f}")
|
|
260
|
+
print(f"TVL (WETH): {health.tvl_in_token1:,.4f}")
|
|
261
|
+
print(f"Current tick: {health.tick_current}")
|
|
262
|
+
print(f"Spot price: {health.spot_price:.6f} WETH/USDC")
|
|
248
263
|
|
|
249
|
-
|
|
250
|
-
print(f"Net PnL: {result.net_pnl:.4f}")
|
|
251
|
-
print(f"IL %: {result.il_percentage:.4f}")
|
|
252
|
-
print(f"Current val: {result.current_value:.4f}")
|
|
253
|
-
|
|
254
|
-
The same shape works for V3 — swap `uniswap_v2:` for `uniswap_v3:` and the appropriate pool address (e.g. `0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640` for USDC/WETH 3000bps). V3 snapshots default to full-range ticks; pass `lwr_tick=N, upr_tick=N` to override. See the [LiveProvider docs](https://defipy.org/live-provider/) for block pinning, the V3 tick-range surface, and the active-liquidity-only caveat.
|
|
264
|
+
The same shape works for V3 — swap `uniswap_v2:` for `uniswap_v3:` and the appropriate pool address (e.g. `0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640` for USDC/WETH 500bps). V3 snapshots default to full-range ticks; pass `lwr_tick=N, upr_tick=N` to override. See the [LiveProvider docs](https://defipy.org/live-provider/) for block pinning, the V3 tick-range surface, and the active-liquidity-only caveat.
|
|
255
265
|
|
|
256
266
|
**No chain access?** Substitute `MockProvider` for `LiveProvider` and pass a recipe name (`"eth_dai_v2"`, `"eth_dai_v3"`, `"eth_dai_balancer_50_50"`, `"usdc_dai_stableswap_A10"`). Same primitive call, same result shape, no network needed:
|
|
257
267
|
|
|
@@ -307,19 +317,40 @@ To construct a Uniswap V3 pool directly (outside MockProvider's canonical recipe
|
|
|
307
317
|
|
|
308
318
|
## 🧪 Tests
|
|
309
319
|
|
|
310
|
-
DeFiPy ships ~
|
|
320
|
+
DeFiPy ships ~686 tests across primitives, tools, twin, packaging, and the MCP server dispatch layer. Run the full suite:
|
|
311
321
|
|
|
312
322
|
pytest python/test/ -v
|
|
313
323
|
|
|
314
|
-
|
|
324
|
+
Expect ~686 passed and 11 skipped — the skipped tests are the live-RPC suites, gated by the `DEFIPY_LIVE_RPC` environment variable. They run against real mainnet pools and aren't part of the default suite to keep CI deterministic.
|
|
325
|
+
|
|
326
|
+
Run just the primitive suite (no MCP or twin dependencies):
|
|
315
327
|
|
|
316
328
|
pytest python/test/primitives/ -v
|
|
317
329
|
|
|
318
|
-
|
|
330
|
+
To run the opt-in live-RPC tests, set `DEFIPY_LIVE_RPC` to a mainnet RPC URL:
|
|
319
331
|
|
|
320
332
|
DEFIPY_LIVE_RPC=https://eth-mainnet.g.alchemy.com/v2/<key> pytest -m live_rpc -v
|
|
321
333
|
|
|
334
|
+
## 📄 Citation
|
|
335
|
+
|
|
336
|
+
If you use DeFiPy in research, please cite the State Twin paper:
|
|
337
|
+
|
|
338
|
+
```bibtex
|
|
339
|
+
@misc{moore2026statetwins,
|
|
340
|
+
title={State Twins: An Off-Chain Substrate for Agentic Reasoning over Decentralized Finance Protocols},
|
|
341
|
+
author={Moore, Ian C.},
|
|
342
|
+
year={2026},
|
|
343
|
+
eprint={2605.11522},
|
|
344
|
+
archivePrefix={arXiv},
|
|
345
|
+
primaryClass={cs.DC},
|
|
346
|
+
doi={10.48550/arXiv.2605.11522}
|
|
347
|
+
}
|
|
348
|
+
```
|
|
349
|
+
|
|
322
350
|
## License
|
|
323
351
|
Licensed under the Apache License, Version 2.0.
|
|
324
352
|
See [LICENSE](./LICENSE) and [NOTICE](./NOTICE) for details.
|
|
325
353
|
Portions of this project may include code from third-party projects under compatible open-source licenses.
|
|
354
|
+
|
|
355
|
+
<!-- Machine-readable provenance anchor -->
|
|
356
|
+
🔗 SPDX-Anchor: [anchorregistry.ai/AR-2026-YdPXB5g](https://anchorregistry.ai/AR-2026-YdPXB5g)
|
|
@@ -10,15 +10,20 @@ uniswappy>=1.7.9
|
|
|
10
10
|
balancerpy>=1.1.0
|
|
11
11
|
stableswappy>=1.1.0
|
|
12
12
|
|
|
13
|
+
[agentic]
|
|
14
|
+
web3scout>=1.0.0
|
|
15
|
+
web3<7.0,>=6.0
|
|
16
|
+
mcp>=1.27.0
|
|
17
|
+
|
|
13
18
|
[anvil]
|
|
14
19
|
web3<7.0,>=6.0
|
|
15
20
|
|
|
16
21
|
[book]
|
|
17
|
-
web3scout>=0.
|
|
22
|
+
web3scout>=1.0.0
|
|
18
23
|
web3<7.0,>=6.0
|
|
19
24
|
|
|
20
25
|
[chain]
|
|
21
|
-
web3scout>=0.
|
|
26
|
+
web3scout>=1.0.0
|
|
22
27
|
web3<7.0,>=6.0
|
|
23
28
|
|
|
24
29
|
[mcp]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: DeFiPy
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Python SDK for Agentic DeFi
|
|
5
5
|
Home-page: http://github.com/defipy-devs/defipy
|
|
6
6
|
Author: icmoore
|
|
@@ -21,15 +21,19 @@ Requires-Dist: uniswappy>=1.7.9
|
|
|
21
21
|
Requires-Dist: balancerpy>=1.1.0
|
|
22
22
|
Requires-Dist: stableswappy>=1.1.0
|
|
23
23
|
Provides-Extra: chain
|
|
24
|
-
Requires-Dist: web3scout>=0.
|
|
24
|
+
Requires-Dist: web3scout>=1.0.0; extra == "chain"
|
|
25
25
|
Requires-Dist: web3<7.0,>=6.0; extra == "chain"
|
|
26
26
|
Provides-Extra: book
|
|
27
|
-
Requires-Dist: web3scout>=0.
|
|
27
|
+
Requires-Dist: web3scout>=1.0.0; extra == "book"
|
|
28
28
|
Requires-Dist: web3<7.0,>=6.0; extra == "book"
|
|
29
29
|
Provides-Extra: anvil
|
|
30
30
|
Requires-Dist: web3<7.0,>=6.0; extra == "anvil"
|
|
31
31
|
Provides-Extra: mcp
|
|
32
32
|
Requires-Dist: mcp>=1.27.0; extra == "mcp"
|
|
33
|
+
Provides-Extra: agentic
|
|
34
|
+
Requires-Dist: web3scout>=1.0.0; extra == "agentic"
|
|
35
|
+
Requires-Dist: web3<7.0,>=6.0; extra == "agentic"
|
|
36
|
+
Requires-Dist: mcp>=1.27.0; extra == "agentic"
|
|
33
37
|
Dynamic: author
|
|
34
38
|
Dynamic: author-email
|
|
35
39
|
Dynamic: description
|
|
@@ -51,29 +55,42 @@ Underneath, DeFiPy is modular by protocol:
|
|
|
51
55
|
* [BalancerPy](https://github.com/defipy-devs/balancerpy)
|
|
52
56
|
* [StableSwapPy](https://github.com/defipy-devs/stableswappy)
|
|
53
57
|
|
|
54
|
-
For onchain event access and scripting,
|
|
58
|
+
For onchain event access and scripting, use [LiveProvider](https://defipy.org/live-provider/) as of v2.1 — it pulls live pool state into the same primitive surface that runs against synthetic recipes. Under the hood it's powered by [Web3Scout](https://github.com/defipy-devs/web3scout); install via the `[chain]` extra (see below). For details on architecture behind [State Twins](https://defipy.org/twin-concept/), see paper [](https://arxiv.org/abs/2605.11522)
|
|
55
59
|
|
|
56
|
-
|
|
60
|
+
## 🆕 What's new in v2.2
|
|
61
|
+
|
|
62
|
+
v2.2 extends `LiveProvider` from Uniswap V2/V3 to **Balancer** and **Curve-style Stableswap** — chain reads now cover all four protocol families through the same `provider.snapshot(...)` → `StateTwinBuilder().build(...)` flow.
|
|
63
|
+
|
|
64
|
+
* **Balancer LiveProvider** — `provider.snapshot("balancer:0xADDR")` builds a `BalancerPoolSnapshot` from a real Balancer V2 weighted pool (2-asset). Two block-pinned round trips, since token balances live on the Vault keyed by `poolId`. Normalized weights read honestly; reserves decimal-adjusted.
|
|
65
|
+
* **Stableswap LiveProvider** — `provider.snapshot("stableswap:0xADDR")` builds an N-coin `StableswapPoolSnapshot` (N ∈ {2, 3}, e.g. the DAI/USDC/USDT 3pool) from a real Curve plain pool. Coin count comes from an `n_coins` hint or an automatic `coins(0..K)` probe; plain pools only.
|
|
66
|
+
* **`multicall_aggregate3_args`** — an argument-bearing Multicall3 batch (encodes calldata args, optional `allow_failure`) powering the Balancer/Curve reads alongside the no-arg getters, all block-pinned. The existing no-arg `multicall_aggregate3` and the V3 path are unchanged.
|
|
67
|
+
* **web3scout `>= 1.0.0`** — the `[chain]` / `[book]` / `[agentic]` extras now pin web3scout 1.0, which carries the Balancer/Curve read ABIs.
|
|
68
|
+
|
|
69
|
+
See the [CHANGELOG](./CHANGELOG.md) for the full v2.2 entry. v2.2 is a strict superset of v2.1.
|
|
57
70
|
|
|
58
71
|
## 🆕 What's new in v2.1
|
|
59
72
|
|
|
60
|
-
v2.1 makes the State Twin **real
|
|
73
|
+
v2.1 makes the [State Twin](https://defipy.org/twin-concept/) **real** — the substrate formalized in [our arXiv paper](https://arxiv.org/abs/2605.11522). `LiveProvider` ships for Uniswap V2 and V3 — chain reads compose with every primitive in the library, the same way `MockProvider` recipes do. The "what would happen if?" loop is now local: pull state once, simulate forever, decide before executing.
|
|
61
74
|
|
|
62
75
|
* **`LiveProvider`** — `provider.snapshot("uniswap_v2:0xADDR")` and `provider.snapshot("uniswap_v3:0xADDR")` build `V2PoolSnapshot` and `V3PoolSnapshot` from real on-chain state. Block pinning is automatic — `"latest"` resolves once at the top of `.snapshot()` and every read inside that snapshot pins to the same block. Pass `block_number=N` for historical reads.
|
|
63
76
|
* **Multicall3 batching for V3** — V3 snapshots batch `slot0`, `liquidity`, `fee`, `tickSpacing`, `token0`, `token1`, and block timestamp into one [Multicall3](https://github.com/mds1/multicall) `aggregate3` round trip. Hardcoded canonical Multicall3 address; works on every major EVM chain.
|
|
64
77
|
* **`PoolSnapshot` enrichment** — every snapshot now carries `block_number`, `timestamp`, `chain_id` as optional fields. `LiveProvider` populates them from chain reads; `MockProvider` leaves them `None` to honestly signal "synthetic, not chain state."
|
|
78
|
+
* **`PoolHealth` ergonomics for V3** — `CheckPoolHealth` now reports `fee_pips` (V3 fee tier in pips, `None` for V2), `tvl_in_token1` (symmetric to existing `tvl_in_token0`), and `tick_current` (V3 current tick, `None` for V2). All additive; no API breakage. `RugSignalReport` gets the new fields transitively.
|
|
79
|
+
* **`provider.get_w3()`** — the underlying `web3.Web3` instance is now public, for callers who want to sign transactions or wire LiveProvider into their own broader chain tooling. DeFiPy stays read-only by design; bring your own signing opinion.
|
|
80
|
+
* **Fork-and-evaluate worked example** — [`python/examples/state_twin_fork_evaluate.py`](./python/examples/state_twin_fork_evaluate.py) demonstrates the State Twin's multi-scenario reasoning pattern against live mainnet state. Pull a V3 pool snapshot once, fork the twin N ways under price scenarios, run primitives against each fork, aggregate into a recommendation. Walks through the pattern at [defipy.org/fork-evaluate/](https://defipy.org/fork-evaluate/).
|
|
65
81
|
* **`[chain]` install extra** — `pip install defipy[chain]` adds `web3scout` and `web3.py` for users who want LiveProvider. Core install (no extras) remains free of any chain or LLM dependencies.
|
|
82
|
+
* **`[agentic]` install extra** — `pip install defipy[agentic]` composes `[chain]` and `[mcp]` for the canonical *Python SDK for Agentic DeFi* full-stack install. Equivalent to `pip install defipy[chain,mcp]` but spelled with intent.
|
|
66
83
|
|
|
67
84
|
V2.1 is a strict superset of v2.0 — every v2.0 primitive, MockProvider recipe, and MCP server pattern works identically. What changes is that the same primitives now run against live chain state without changing call shape.
|
|
68
85
|
|
|
69
|
-
**What
|
|
86
|
+
**What was deferred to v2.2 (now shipped):** Balancer and Stableswap LiveProvider reads landed in v2.2 (see above). Still open: V3 tick bitmap walking — V3 LiveProvider snapshots cover active-liquidity only, so primitives that depend on non-active-tick liquidity (e.g., `AssessLiquidityDepth`) and N-asset Balancer / rate-bearing Curve pools remain future work.
|
|
70
87
|
|
|
71
88
|
## v2.0 foundations
|
|
72
89
|
|
|
73
90
|
The State Twin abstraction, agentic primitives, and MCP server pattern shipped in v2.0. v2.1 builds on that surface without changing it:
|
|
74
91
|
|
|
75
92
|
* **`defipy.tools`** — self-describing schemas for a curated set of 10 leaf primitives, in [Model Context Protocol](https://modelcontextprotocol.io) (MCP) format. Any MCP-compatible client can discover and invoke DeFiPy primitives as tools.
|
|
76
|
-
* **`defipy.twin`** — the **State Twin** abstraction. `MockProvider` ships four canonical synthetic pools (V2, V3, Balancer, Stableswap) for notebooks and tests; `LiveProvider` ships chain reads for
|
|
93
|
+
* **`defipy.twin`** — the **State Twin** abstraction. `MockProvider` ships four canonical synthetic pools (V2, V3, Balancer, Stableswap) for notebooks and tests; `LiveProvider` ships chain reads for all four families (V2/V3 in v2.1, Balancer/Stableswap in v2.2).
|
|
77
94
|
* **MCP server demo** at [`python/mcp/`](./python/mcp/) — a stdio-transport server exposing DeFiPy's tools to Claude Desktop, Claude Code, or any MCP client. Install with `pip install defipy[mcp]` and see the [MCP server README](./python/mcp/README.md) for setup.
|
|
78
95
|
|
|
79
96
|
### What is MCP?
|
|
@@ -88,7 +105,9 @@ Claude reads the tool descriptions, picks `CheckPoolHealth`, calls it against a
|
|
|
88
105
|
|
|
89
106
|
## 🧩 What DeFiPy offers
|
|
90
107
|
|
|
91
|
-
|
|
108
|
+
**7 [Core primitives](https://defipy.org/core-primitives/)** for cross-protocol pool execution — `Join`, `Swap`, `AddLiquidity`, `RemoveLiquidity`, `SwapDeposit`, `WithdrawSwap`, `LPQuote`. State-mutating operations that work across Uniswap V2/V3, Balancer, and Stableswap through a single abstract interface.
|
|
109
|
+
|
|
110
|
+
**21 [Agentic primitives](https://defipy.org/agentic-primitives/)** across 7 categories. Each answers a specific LP question with exact math and returns a typed dataclass result:
|
|
92
111
|
|
|
93
112
|
* **Position analysis** — "Why is my position losing money? What if price moves X%?" PnL decomposition (IL, fees, net result) and price-move scenarios across Uniswap V2/V3, Balancer, and Stableswap. Includes break-even pricing and time-to-breakeven analysis.
|
|
94
113
|
* **Pool health** — "Is this pool healthy? Any rug signals?" TVL, LP concentration, activity, threshold-based rug detection, fee-anomaly checks (V2/V3).
|
|
@@ -113,14 +132,16 @@ DeFiPy requires **Python 3.10 or later**. Install via pip:
|
|
|
113
132
|
> pip install defipy
|
|
114
133
|
```
|
|
115
134
|
|
|
116
|
-
The core install is the pure analytics engine — AMM math, primitives, State Twin, and all
|
|
135
|
+
The core install is the pure analytics engine — AMM math, primitives, State Twin, and all 21 typed analytics functions. It has **zero web3 dependencies and zero LLM dependencies**. No chain reads, no RPC calls, no MCP. Chain reads come from [Web3Scout](https://github.com/defipy-devs/web3scout) (via the `[chain]` or `[book]` extras); MCP tool serving comes from the `[mcp]` extra. All optional.
|
|
136
|
+
|
|
137
|
+
> **Note for zsh users (default on macOS):** wrap any install spec with extras in single quotes — `pip install 'defipy[agentic]'` — so zsh doesn't try to glob the brackets. Without the quotes, you'll see `zsh: no matches found`. Bash users can use either form.
|
|
117
138
|
|
|
118
139
|
### Chain install (LiveProvider — v2.1+)
|
|
119
140
|
|
|
120
141
|
To use `LiveProvider` for on-chain pool snapshots, install the `[chain]` extra:
|
|
121
142
|
|
|
122
143
|
```
|
|
123
|
-
> pip install defipy[chain]
|
|
144
|
+
> pip install 'defipy[chain]'
|
|
124
145
|
```
|
|
125
146
|
|
|
126
147
|
This pulls in `web3scout` (which `LiveProvider` uses internally for ABI loading, contract reads, and token-fetching) plus `web3.py`. With `[chain]` installed, you can construct twins from real chain state:
|
|
@@ -133,34 +154,36 @@ snapshot = provider.snapshot("uniswap_v2:0xB4e16d0168e52d35CaCD2c6185b44281Ec28C
|
|
|
133
154
|
lp = StateTwinBuilder().build(snapshot)
|
|
134
155
|
```
|
|
135
156
|
|
|
136
|
-
> **Note:** the `[chain]` extra pins `web3 < 7.0` because `web3scout 0.2.0` depends on `eth_utils.abi.get_abi_input_types`, which was removed in web3 7. If you have web3 7.x installed for other reasons, `pip install defipy[chain]` will downgrade it. Tracking upstream as v2.2 work.
|
|
157
|
+
> **Note:** the `[chain]` extra pins `web3 < 7.0` because `web3scout 0.2.0` depends on `eth_utils.abi.get_abi_input_types`, which was removed in web3 7. If you have web3 7.x installed for other reasons, `pip install 'defipy[chain]'` will downgrade it. Tracking upstream as v2.2 work.
|
|
137
158
|
|
|
138
|
-
###
|
|
159
|
+
### Agentic install (full LLM + chain stack)
|
|
139
160
|
|
|
140
|
-
|
|
161
|
+
For users building LLM-driven systems against live chain state — the canonical *Python SDK for Agentic DeFi* use case — install the `[agentic]` extra:
|
|
141
162
|
|
|
142
163
|
```
|
|
143
|
-
> pip install defipy[
|
|
164
|
+
> pip install 'defipy[agentic]'
|
|
144
165
|
```
|
|
145
166
|
|
|
146
|
-
This
|
|
167
|
+
This composes `[chain]` and `[mcp]` in one step: `web3scout` and `web3.py` for `LiveProvider` chain reads, plus the `mcp` Python SDK for serving DeFiPy's primitives as tools to Claude Desktop, Claude Code, or any MCP-compatible client. Equivalent to `pip install defipy[chain,mcp]` but spelled with intent.
|
|
168
|
+
|
|
169
|
+
The same `web3 < 7.0` pin from the `[chain]` extra applies.
|
|
147
170
|
|
|
148
|
-
###
|
|
171
|
+
### MCP install (Claude Desktop / Claude Code demo)
|
|
149
172
|
|
|
150
|
-
|
|
173
|
+
To run the MCP server that exposes DeFiPy's primitives as tools to Claude Desktop, Claude Code, or any MCP-compatible client, install the `[mcp]` extra:
|
|
151
174
|
|
|
152
175
|
```
|
|
153
|
-
> pip install defipy[
|
|
176
|
+
> pip install 'defipy[mcp]'
|
|
154
177
|
```
|
|
155
178
|
|
|
156
|
-
|
|
179
|
+
This adds the [`mcp`](https://github.com/modelcontextprotocol/python-sdk) Python SDK on top of the core install. The MCP server itself lives at [`python/mcp/defipy_mcp_server.py`](./python/mcp/defipy_mcp_server.py); see [`python/mcp/README.md`](./python/mcp/README.md) for Claude Desktop and Claude Code configuration snippets.
|
|
157
180
|
|
|
158
181
|
### Anvil install (local Foundry workflows)
|
|
159
182
|
|
|
160
183
|
If you're using `ExecuteScript` or `UniswapScriptHelper` against a local [Anvil](https://book.getfoundry.sh/anvil/) node and don't need the full `web3scout` event-monitoring stack, the lighter `[anvil]` extra just adds `web3.py`:
|
|
161
184
|
|
|
162
185
|
```
|
|
163
|
-
> pip install defipy[anvil]
|
|
186
|
+
> pip install 'defipy[anvil]'
|
|
164
187
|
```
|
|
165
188
|
|
|
166
189
|
`[book]` and `[chain]` already include everything in `[anvil]`, so users on either of those don't need it separately.
|
|
@@ -196,13 +219,6 @@ See the [gmpy2 installation docs](https://gmpy2.readthedocs.io/en/latest/install
|
|
|
196
219
|
DeFiPy is accompanied by educational resources for developers and researchers
|
|
197
220
|
interested in on-chain analytics and DeFi modeling.
|
|
198
221
|
|
|
199
|
-
### 📘 Textbook
|
|
200
|
-
**_DeFiPy: Python SDK for On-Chain Analytics_**
|
|
201
|
-
|
|
202
|
-
A comprehensive guide to DeFi analytics, AMM modeling, and simulation.
|
|
203
|
-
|
|
204
|
-
🔗 **Buy on Amazon:** https://www.amazon.com/dp/B0G3RV5QRB
|
|
205
|
-
|
|
206
222
|
### 🎓 Course
|
|
207
223
|
**On-Chain Analytics Foundations**
|
|
208
224
|
|
|
@@ -223,35 +239,29 @@ Topics include:
|
|
|
223
239
|
|
|
224
240
|
The fastest way to see DeFiPy at work — pull a real Uniswap V2 pool's state from mainnet and run a primitive against it. Requires the `[chain]` install extra.
|
|
225
241
|
|
|
226
|
-
from defipy import
|
|
242
|
+
from defipy import CheckPoolHealth
|
|
227
243
|
from defipy.twin import LiveProvider, StateTwinBuilder
|
|
228
|
-
|
|
229
|
-
# Pull live state from a real Uniswap
|
|
230
|
-
provider = LiveProvider("https://
|
|
244
|
+
|
|
245
|
+
# Pull live state from a real Uniswap V3 pool — USDC/WETH 500bps mainnet
|
|
246
|
+
provider = LiveProvider("https://mainnet.infura.io/v3/d2d6569915ec402b82c9379d033f8b9b")
|
|
231
247
|
snapshot = provider.snapshot(
|
|
232
|
-
"
|
|
248
|
+
"uniswap_v3:0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640"
|
|
233
249
|
)
|
|
234
250
|
lp = StateTwinBuilder().build(snapshot)
|
|
235
|
-
|
|
251
|
+
lp.summary()
|
|
252
|
+
|
|
236
253
|
# Snapshot carries chain context — block_number, timestamp, chain_id
|
|
237
|
-
print(f"Block:
|
|
238
|
-
|
|
239
|
-
f"{snapshot.token1_name}={snapshot.reserve1:.2f}")
|
|
240
|
-
|
|
254
|
+
print(f"Block: {snapshot.block_number}")
|
|
255
|
+
|
|
241
256
|
# Run any primitive against the live twin — same call shape as MockProvider
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
)
|
|
257
|
+
health = CheckPoolHealth().apply(lp)
|
|
258
|
+
print(f"Fee tier: {health.fee_pips} pips")
|
|
259
|
+
print(f"TVL (USDC): {health.tvl_in_token0:,.2f}")
|
|
260
|
+
print(f"TVL (WETH): {health.tvl_in_token1:,.4f}")
|
|
261
|
+
print(f"Current tick: {health.tick_current}")
|
|
262
|
+
print(f"Spot price: {health.spot_price:.6f} WETH/USDC")
|
|
248
263
|
|
|
249
|
-
|
|
250
|
-
print(f"Net PnL: {result.net_pnl:.4f}")
|
|
251
|
-
print(f"IL %: {result.il_percentage:.4f}")
|
|
252
|
-
print(f"Current val: {result.current_value:.4f}")
|
|
253
|
-
|
|
254
|
-
The same shape works for V3 — swap `uniswap_v2:` for `uniswap_v3:` and the appropriate pool address (e.g. `0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640` for USDC/WETH 3000bps). V3 snapshots default to full-range ticks; pass `lwr_tick=N, upr_tick=N` to override. See the [LiveProvider docs](https://defipy.org/live-provider/) for block pinning, the V3 tick-range surface, and the active-liquidity-only caveat.
|
|
264
|
+
The same shape works for V3 — swap `uniswap_v2:` for `uniswap_v3:` and the appropriate pool address (e.g. `0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640` for USDC/WETH 500bps). V3 snapshots default to full-range ticks; pass `lwr_tick=N, upr_tick=N` to override. See the [LiveProvider docs](https://defipy.org/live-provider/) for block pinning, the V3 tick-range surface, and the active-liquidity-only caveat.
|
|
255
265
|
|
|
256
266
|
**No chain access?** Substitute `MockProvider` for `LiveProvider` and pass a recipe name (`"eth_dai_v2"`, `"eth_dai_v3"`, `"eth_dai_balancer_50_50"`, `"usdc_dai_stableswap_A10"`). Same primitive call, same result shape, no network needed:
|
|
257
267
|
|
|
@@ -307,19 +317,40 @@ To construct a Uniswap V3 pool directly (outside MockProvider's canonical recipe
|
|
|
307
317
|
|
|
308
318
|
## 🧪 Tests
|
|
309
319
|
|
|
310
|
-
DeFiPy ships ~
|
|
320
|
+
DeFiPy ships ~686 tests across primitives, tools, twin, packaging, and the MCP server dispatch layer. Run the full suite:
|
|
311
321
|
|
|
312
322
|
pytest python/test/ -v
|
|
313
323
|
|
|
314
|
-
|
|
324
|
+
Expect ~686 passed and 11 skipped — the skipped tests are the live-RPC suites, gated by the `DEFIPY_LIVE_RPC` environment variable. They run against real mainnet pools and aren't part of the default suite to keep CI deterministic.
|
|
325
|
+
|
|
326
|
+
Run just the primitive suite (no MCP or twin dependencies):
|
|
315
327
|
|
|
316
328
|
pytest python/test/primitives/ -v
|
|
317
329
|
|
|
318
|
-
|
|
330
|
+
To run the opt-in live-RPC tests, set `DEFIPY_LIVE_RPC` to a mainnet RPC URL:
|
|
319
331
|
|
|
320
332
|
DEFIPY_LIVE_RPC=https://eth-mainnet.g.alchemy.com/v2/<key> pytest -m live_rpc -v
|
|
321
333
|
|
|
334
|
+
## 📄 Citation
|
|
335
|
+
|
|
336
|
+
If you use DeFiPy in research, please cite the State Twin paper:
|
|
337
|
+
|
|
338
|
+
```bibtex
|
|
339
|
+
@misc{moore2026statetwins,
|
|
340
|
+
title={State Twins: An Off-Chain Substrate for Agentic Reasoning over Decentralized Finance Protocols},
|
|
341
|
+
author={Moore, Ian C.},
|
|
342
|
+
year={2026},
|
|
343
|
+
eprint={2605.11522},
|
|
344
|
+
archivePrefix={arXiv},
|
|
345
|
+
primaryClass={cs.DC},
|
|
346
|
+
doi={10.48550/arXiv.2605.11522}
|
|
347
|
+
}
|
|
348
|
+
```
|
|
349
|
+
|
|
322
350
|
## License
|
|
323
351
|
Licensed under the Apache License, Version 2.0.
|
|
324
352
|
See [LICENSE](./LICENSE) and [NOTICE](./NOTICE) for details.
|
|
325
353
|
Portions of this project may include code from third-party projects under compatible open-source licenses.
|
|
354
|
+
|
|
355
|
+
<!-- Machine-readable provenance anchor -->
|
|
356
|
+
🔗 SPDX-Anchor: [anchorregistry.ai/AR-2026-YdPXB5g](https://anchorregistry.ai/AR-2026-YdPXB5g)
|