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.
Files changed (116) hide show
  1. {defipy-2.1.0a2 → defipy-2.2.0}/DeFiPy.egg-info/PKG-INFO +84 -53
  2. {defipy-2.1.0a2 → defipy-2.2.0}/DeFiPy.egg-info/requires.txt +7 -2
  3. {defipy-2.1.0a2 → defipy-2.2.0}/PKG-INFO +84 -53
  4. {defipy-2.1.0a2 → defipy-2.2.0}/README.md +77 -50
  5. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/pool_health/CheckPoolHealth.py +12 -0
  6. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/twin/_rpc.py +96 -0
  7. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/twin/live_provider.py +257 -37
  8. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/twin/snapshot.py +2 -3
  9. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/PoolHealth.py +19 -0
  10. {defipy-2.1.0a2 → defipy-2.2.0}/setup.py +16 -8
  11. {defipy-2.1.0a2 → defipy-2.2.0}/DeFiPy.egg-info/SOURCES.txt +0 -0
  12. {defipy-2.1.0a2 → defipy-2.2.0}/DeFiPy.egg-info/dependency_links.txt +0 -0
  13. {defipy-2.1.0a2 → defipy-2.2.0}/DeFiPy.egg-info/not-zip-safe +0 -0
  14. {defipy-2.1.0a2 → defipy-2.2.0}/DeFiPy.egg-info/top_level.txt +0 -0
  15. {defipy-2.1.0a2 → defipy-2.2.0}/LICENSE +0 -0
  16. {defipy-2.1.0a2 → defipy-2.2.0}/NOTICE +0 -0
  17. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/__init__.py +0 -0
  18. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/ImpermanentLossAgent.py +0 -0
  19. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/PriceThresholdSwapAgent.py +0 -0
  20. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/TVLBasedLiquidityExitAgent.py +0 -0
  21. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/VolumeSpikeNotifierAgent.py +0 -0
  22. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/__init__.py +0 -0
  23. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/config/ImpermanentLossConfig.py +0 -0
  24. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/config/PriceThresholdConfig.py +0 -0
  25. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/config/TVLExitConfig.py +0 -0
  26. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/config/VolumeSpikeConfig.py +0 -0
  27. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/config/__init__.py +0 -0
  28. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/data/UniswapPoolData.py +0 -0
  29. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/agents/data/__init__.py +0 -0
  30. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/analytics/risk/__init__.py +0 -0
  31. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/analytics/simulate/__init__.py +0 -0
  32. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/erc/__init__.py +0 -0
  33. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/math/basic/__init__.py +0 -0
  34. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/math/interest/__init__.py +0 -0
  35. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/math/interest/ips/__init__.py +0 -0
  36. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/math/interest/ips/aggregate/__init__.py +0 -0
  37. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/math/model/__init__.py +0 -0
  38. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/math/risk/__init__.py +0 -0
  39. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/__init__.py +0 -0
  40. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/comparison/CompareFeeTiers.py +0 -0
  41. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/comparison/CompareProtocols.py +0 -0
  42. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/comparison/__init__.py +0 -0
  43. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/execution/CalculateSlippage.py +0 -0
  44. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/execution/DetectMEV.py +0 -0
  45. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/execution/__init__.py +0 -0
  46. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/optimization/EvaluateRebalance.py +0 -0
  47. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/optimization/EvaluateTickRanges.py +0 -0
  48. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/optimization/OptimalDepositSplit.py +0 -0
  49. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/optimization/__init__.py +0 -0
  50. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/pool_health/DetectFeeAnomaly.py +0 -0
  51. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/pool_health/DetectRugSignals.py +0 -0
  52. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/pool_health/__init__.py +0 -0
  53. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/portfolio/AggregatePortfolio.py +0 -0
  54. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/portfolio/__init__.py +0 -0
  55. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/position/AnalyzeBalancerPosition.py +0 -0
  56. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/position/AnalyzePosition.py +0 -0
  57. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/position/AnalyzeStableswapPosition.py +0 -0
  58. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/position/FindBreakEvenPrice.py +0 -0
  59. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/position/FindBreakEvenTime.py +0 -0
  60. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/position/SimulateBalancerPriceMove.py +0 -0
  61. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/position/SimulatePriceMove.py +0 -0
  62. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/position/SimulateStableswapPriceMove.py +0 -0
  63. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/position/__init__.py +0 -0
  64. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/risk/AssessDepegRisk.py +0 -0
  65. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/risk/CheckTickRangeStatus.py +0 -0
  66. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/primitives/risk/__init__.py +0 -0
  67. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/process/__init__.py +0 -0
  68. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/process/burn/__init__.py +0 -0
  69. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/process/deposit/__init__.py +0 -0
  70. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/process/join/Join.py +0 -0
  71. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/process/join/__init__.py +0 -0
  72. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/process/liquidity/AddLiquidity.py +0 -0
  73. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/process/liquidity/RemoveLiquidity.py +0 -0
  74. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/process/liquidity/__init__.py +0 -0
  75. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/process/mint/__init__.py +0 -0
  76. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/process/swap/Swap.py +0 -0
  77. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/process/swap/__init__.py +0 -0
  78. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/tools/__init__.py +0 -0
  79. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/tools/registry.py +0 -0
  80. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/tools/schemas.py +0 -0
  81. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/twin/__init__.py +0 -0
  82. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/twin/builder.py +0 -0
  83. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/twin/mock_provider.py +0 -0
  84. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/twin/provider.py +0 -0
  85. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/client/__init__.py +0 -0
  86. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/client/contract/ExecuteScript.py +0 -0
  87. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/client/contract/__init__.py +0 -0
  88. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/BalancerPositionAnalysis.py +0 -0
  89. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/BalancerPriceMoveScenario.py +0 -0
  90. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/BreakEvenAlphas.py +0 -0
  91. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/BreakEvenTime.py +0 -0
  92. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/DepegRiskAssessment.py +0 -0
  93. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/DepositSplitResult.py +0 -0
  94. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/FeeAnomalyResult.py +0 -0
  95. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/FeeTierCandidate.py +0 -0
  96. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/FeeTierComparison.py +0 -0
  97. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/MEVDetectionResult.py +0 -0
  98. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/PortfolioAnalysis.py +0 -0
  99. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/PortfolioPosition.py +0 -0
  100. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/PositionAnalysis.py +0 -0
  101. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/PriceMoveScenario.py +0 -0
  102. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/ProtocolComparison.py +0 -0
  103. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/RebalanceCostReport.py +0 -0
  104. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/RugSignalReport.py +0 -0
  105. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/SlippageAnalysis.py +0 -0
  106. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/StableswapPositionAnalysis.py +0 -0
  107. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/StableswapPriceMoveScenario.py +0 -0
  108. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/TickRangeCandidate.py +0 -0
  109. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/TickRangeEvaluation.py +0 -0
  110. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/TickRangeStatus.py +0 -0
  111. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/data/__init__.py +0 -0
  112. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/interfaces/__init__.py +0 -0
  113. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/tools/UniswapScriptHelper.py +0 -0
  114. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/tools/__init__.py +0 -0
  115. {defipy-2.1.0a2 → defipy-2.2.0}/python/prod/utils/tools/v3/__init__.py +0 -0
  116. {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.1.0a2
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.2.0; extra == "chain"
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.2.0; extra == "book"
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, pair it with [Web3Scout](https://github.com/defipy-devs/web3scout) a companion tool for [decoding pool events](https://defipy.readthedocs.io/en/latest/onchain/pool_events.html) and [interfacing with Solidity contracts](https://defipy.readthedocs.io/en/latest/onchain/testnet_sim_univ2.html).
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 [![arXiv](https://img.shields.io/badge/arXiv-2605.11522-b31b1b.svg)](https://arxiv.org/abs/2605.11522)
55
59
 
56
- 🔗 SPDX-Anchor: [anchorregistry.ai/AR-2026-YdPXB5g](https://anchorregistry.ai/AR-2026-YdPXB5g)
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**. `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.
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's deferred to v2.2:** Balancer and Stableswap LiveProvider implementations. V3 tick bitmap walking (active-liquidity-only is the v2.1 stance). Calls for those raise `NotImplementedError` pointing at the planned version.
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 V2 and V3 in v2.1.
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
- 22 primitives across 7 categories. Each answers a specific LP question with exact math and returns a typed dataclass result:
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 22 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.
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
- ### MCP install (Claude Desktop / Claude Code demo)
159
+ ### Agentic install (full LLM + chain stack)
139
160
 
140
- 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:
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[mcp]
164
+ > pip install 'defipy[agentic]'
144
165
  ```
145
166
 
146
- 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.
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
- ### Book install (chapter 9 agents)
171
+ ### MCP install (Claude Desktop / Claude Code demo)
149
172
 
150
- Chapter 9 of *Hands-On AMMs with Python* *Building Autonomous DeFi Agents* uses live chain integration via `web3scout`. To run those examples, install the `[book]` extra:
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[book]
176
+ > pip install 'defipy[mcp]'
154
177
  ```
155
178
 
156
- The `[book]` extra carries the same package set as `[chain]` (`web3scout` + `web3`). The split is intent-based `[chain]` signals production live-state reads via LiveProvider; `[book]` signals textbook chapter 9 use. Either works for either purpose.
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 AnalyzePosition
242
+ from defipy import CheckPoolHealth
227
243
  from defipy.twin import LiveProvider, StateTwinBuilder
228
-
229
- # Pull live state from a real Uniswap V2 pool — WETH/USDC mainnet
230
- provider = LiveProvider("https://eth-mainnet.g.alchemy.com/v2/<key>")
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
- "uniswap_v2:0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc"
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: {snapshot.block_number}")
238
- print(f"Reserves: {snapshot.token0_name}={snapshot.reserve0:.2f}, "
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
- result = AnalyzePosition().apply(
243
- lp,
244
- lp_init_amt=1.0,
245
- entry_x_amt=1000,
246
- entry_y_amt=3_000_000,
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
- print(f"Diagnosis: {result.diagnosis}")
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 ~677 tests across primitives, tools, twin, packaging, and the MCP server dispatch layer. Run the full suite:
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
- Run just the primitive suite (504 tests, no MCP or twin dependencies):
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
- The twin suite includes opt-in live-RPC tests gated by the `DEFIPY_LIVE_RPC` environment variable — set it to a mainnet RPC URL to verify LiveProvider against real chain state:
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.2.0
22
+ web3scout>=1.0.0
18
23
  web3<7.0,>=6.0
19
24
 
20
25
  [chain]
21
- web3scout>=0.2.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.1.0a2
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.2.0; extra == "chain"
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.2.0; extra == "book"
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, pair it with [Web3Scout](https://github.com/defipy-devs/web3scout) a companion tool for [decoding pool events](https://defipy.readthedocs.io/en/latest/onchain/pool_events.html) and [interfacing with Solidity contracts](https://defipy.readthedocs.io/en/latest/onchain/testnet_sim_univ2.html).
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 [![arXiv](https://img.shields.io/badge/arXiv-2605.11522-b31b1b.svg)](https://arxiv.org/abs/2605.11522)
55
59
 
56
- 🔗 SPDX-Anchor: [anchorregistry.ai/AR-2026-YdPXB5g](https://anchorregistry.ai/AR-2026-YdPXB5g)
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**. `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.
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's deferred to v2.2:** Balancer and Stableswap LiveProvider implementations. V3 tick bitmap walking (active-liquidity-only is the v2.1 stance). Calls for those raise `NotImplementedError` pointing at the planned version.
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 V2 and V3 in v2.1.
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
- 22 primitives across 7 categories. Each answers a specific LP question with exact math and returns a typed dataclass result:
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 22 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.
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
- ### MCP install (Claude Desktop / Claude Code demo)
159
+ ### Agentic install (full LLM + chain stack)
139
160
 
140
- 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:
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[mcp]
164
+ > pip install 'defipy[agentic]'
144
165
  ```
145
166
 
146
- 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.
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
- ### Book install (chapter 9 agents)
171
+ ### MCP install (Claude Desktop / Claude Code demo)
149
172
 
150
- Chapter 9 of *Hands-On AMMs with Python* *Building Autonomous DeFi Agents* uses live chain integration via `web3scout`. To run those examples, install the `[book]` extra:
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[book]
176
+ > pip install 'defipy[mcp]'
154
177
  ```
155
178
 
156
- The `[book]` extra carries the same package set as `[chain]` (`web3scout` + `web3`). The split is intent-based `[chain]` signals production live-state reads via LiveProvider; `[book]` signals textbook chapter 9 use. Either works for either purpose.
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 AnalyzePosition
242
+ from defipy import CheckPoolHealth
227
243
  from defipy.twin import LiveProvider, StateTwinBuilder
228
-
229
- # Pull live state from a real Uniswap V2 pool — WETH/USDC mainnet
230
- provider = LiveProvider("https://eth-mainnet.g.alchemy.com/v2/<key>")
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
- "uniswap_v2:0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc"
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: {snapshot.block_number}")
238
- print(f"Reserves: {snapshot.token0_name}={snapshot.reserve0:.2f}, "
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
- result = AnalyzePosition().apply(
243
- lp,
244
- lp_init_amt=1.0,
245
- entry_x_amt=1000,
246
- entry_y_amt=3_000_000,
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
- print(f"Diagnosis: {result.diagnosis}")
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 ~677 tests across primitives, tools, twin, packaging, and the MCP server dispatch layer. Run the full suite:
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
- Run just the primitive suite (504 tests, no MCP or twin dependencies):
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
- The twin suite includes opt-in live-RPC tests gated by the `DEFIPY_LIVE_RPC` environment variable — set it to a mainnet RPC URL to verify LiveProvider against real chain state:
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)