DeFiPy 2.0.0__tar.gz → 2.1.0a2__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 (117) hide show
  1. {defipy-2.0.0 → defipy-2.1.0a2}/DeFiPy.egg-info/PKG-INFO +83 -24
  2. {defipy-2.0.0 → defipy-2.1.0a2}/DeFiPy.egg-info/SOURCES.txt +1 -0
  3. {defipy-2.0.0 → defipy-2.1.0a2}/DeFiPy.egg-info/requires.txt +4 -0
  4. {defipy-2.0.0 → defipy-2.1.0a2}/PKG-INFO +83 -24
  5. {defipy-2.0.0 → defipy-2.1.0a2}/README.md +79 -23
  6. defipy-2.1.0a2/python/prod/twin/_rpc.py +315 -0
  7. defipy-2.1.0a2/python/prod/twin/live_provider.py +440 -0
  8. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/twin/mock_provider.py +5 -1
  9. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/twin/provider.py +16 -5
  10. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/twin/snapshot.py +34 -0
  11. {defipy-2.0.0 → defipy-2.1.0a2}/setup.py +18 -6
  12. defipy-2.0.0/python/prod/twin/live_provider.py +0 -45
  13. {defipy-2.0.0 → defipy-2.1.0a2}/DeFiPy.egg-info/dependency_links.txt +0 -0
  14. {defipy-2.0.0 → defipy-2.1.0a2}/DeFiPy.egg-info/not-zip-safe +0 -0
  15. {defipy-2.0.0 → defipy-2.1.0a2}/DeFiPy.egg-info/top_level.txt +0 -0
  16. {defipy-2.0.0 → defipy-2.1.0a2}/LICENSE +0 -0
  17. {defipy-2.0.0 → defipy-2.1.0a2}/NOTICE +0 -0
  18. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/__init__.py +0 -0
  19. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/agents/ImpermanentLossAgent.py +0 -0
  20. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/agents/PriceThresholdSwapAgent.py +0 -0
  21. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/agents/TVLBasedLiquidityExitAgent.py +0 -0
  22. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/agents/VolumeSpikeNotifierAgent.py +0 -0
  23. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/agents/__init__.py +0 -0
  24. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/agents/config/ImpermanentLossConfig.py +0 -0
  25. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/agents/config/PriceThresholdConfig.py +0 -0
  26. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/agents/config/TVLExitConfig.py +0 -0
  27. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/agents/config/VolumeSpikeConfig.py +0 -0
  28. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/agents/config/__init__.py +0 -0
  29. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/agents/data/UniswapPoolData.py +0 -0
  30. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/agents/data/__init__.py +0 -0
  31. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/analytics/risk/__init__.py +0 -0
  32. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/analytics/simulate/__init__.py +0 -0
  33. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/erc/__init__.py +0 -0
  34. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/math/basic/__init__.py +0 -0
  35. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/math/interest/__init__.py +0 -0
  36. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/math/interest/ips/__init__.py +0 -0
  37. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/math/interest/ips/aggregate/__init__.py +0 -0
  38. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/math/model/__init__.py +0 -0
  39. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/math/risk/__init__.py +0 -0
  40. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/__init__.py +0 -0
  41. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/comparison/CompareFeeTiers.py +0 -0
  42. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/comparison/CompareProtocols.py +0 -0
  43. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/comparison/__init__.py +0 -0
  44. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/execution/CalculateSlippage.py +0 -0
  45. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/execution/DetectMEV.py +0 -0
  46. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/execution/__init__.py +0 -0
  47. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/optimization/EvaluateRebalance.py +0 -0
  48. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/optimization/EvaluateTickRanges.py +0 -0
  49. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/optimization/OptimalDepositSplit.py +0 -0
  50. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/optimization/__init__.py +0 -0
  51. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/pool_health/CheckPoolHealth.py +0 -0
  52. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/pool_health/DetectFeeAnomaly.py +0 -0
  53. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/pool_health/DetectRugSignals.py +0 -0
  54. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/pool_health/__init__.py +0 -0
  55. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/portfolio/AggregatePortfolio.py +0 -0
  56. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/portfolio/__init__.py +0 -0
  57. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/position/AnalyzeBalancerPosition.py +0 -0
  58. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/position/AnalyzePosition.py +0 -0
  59. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/position/AnalyzeStableswapPosition.py +0 -0
  60. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/position/FindBreakEvenPrice.py +0 -0
  61. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/position/FindBreakEvenTime.py +0 -0
  62. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/position/SimulateBalancerPriceMove.py +0 -0
  63. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/position/SimulatePriceMove.py +0 -0
  64. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/position/SimulateStableswapPriceMove.py +0 -0
  65. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/position/__init__.py +0 -0
  66. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/risk/AssessDepegRisk.py +0 -0
  67. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/risk/CheckTickRangeStatus.py +0 -0
  68. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/primitives/risk/__init__.py +0 -0
  69. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/process/__init__.py +0 -0
  70. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/process/burn/__init__.py +0 -0
  71. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/process/deposit/__init__.py +0 -0
  72. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/process/join/Join.py +0 -0
  73. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/process/join/__init__.py +0 -0
  74. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/process/liquidity/AddLiquidity.py +0 -0
  75. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/process/liquidity/RemoveLiquidity.py +0 -0
  76. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/process/liquidity/__init__.py +0 -0
  77. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/process/mint/__init__.py +0 -0
  78. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/process/swap/Swap.py +0 -0
  79. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/process/swap/__init__.py +0 -0
  80. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/tools/__init__.py +0 -0
  81. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/tools/registry.py +0 -0
  82. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/tools/schemas.py +0 -0
  83. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/twin/__init__.py +0 -0
  84. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/twin/builder.py +0 -0
  85. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/client/__init__.py +0 -0
  86. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/client/contract/ExecuteScript.py +0 -0
  87. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/client/contract/__init__.py +0 -0
  88. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/BalancerPositionAnalysis.py +0 -0
  89. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/BalancerPriceMoveScenario.py +0 -0
  90. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/BreakEvenAlphas.py +0 -0
  91. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/BreakEvenTime.py +0 -0
  92. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/DepegRiskAssessment.py +0 -0
  93. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/DepositSplitResult.py +0 -0
  94. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/FeeAnomalyResult.py +0 -0
  95. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/FeeTierCandidate.py +0 -0
  96. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/FeeTierComparison.py +0 -0
  97. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/MEVDetectionResult.py +0 -0
  98. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/PoolHealth.py +0 -0
  99. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/PortfolioAnalysis.py +0 -0
  100. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/PortfolioPosition.py +0 -0
  101. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/PositionAnalysis.py +0 -0
  102. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/PriceMoveScenario.py +0 -0
  103. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/ProtocolComparison.py +0 -0
  104. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/RebalanceCostReport.py +0 -0
  105. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/RugSignalReport.py +0 -0
  106. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/SlippageAnalysis.py +0 -0
  107. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/StableswapPositionAnalysis.py +0 -0
  108. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/StableswapPriceMoveScenario.py +0 -0
  109. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/TickRangeCandidate.py +0 -0
  110. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/TickRangeEvaluation.py +0 -0
  111. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/TickRangeStatus.py +0 -0
  112. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/data/__init__.py +0 -0
  113. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/interfaces/__init__.py +0 -0
  114. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/tools/UniswapScriptHelper.py +0 -0
  115. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/tools/__init__.py +0 -0
  116. {defipy-2.0.0 → defipy-2.1.0a2}/python/prod/utils/tools/v3/__init__.py +0 -0
  117. {defipy-2.0.0 → defipy-2.1.0a2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: DeFiPy
3
- Version: 2.0.0
3
+ Version: 2.1.0a2
4
4
  Summary: Python SDK for Agentic DeFi
5
5
  Home-page: http://github.com/defipy-devs/defipy
6
6
  Author: icmoore
@@ -20,6 +20,9 @@ Requires-Dist: bokeh>=3.3
20
20
  Requires-Dist: uniswappy>=1.7.9
21
21
  Requires-Dist: balancerpy>=1.1.0
22
22
  Requires-Dist: stableswappy>=1.1.0
23
+ Provides-Extra: chain
24
+ Requires-Dist: web3scout>=0.2.0; extra == "chain"
25
+ Requires-Dist: web3<7.0,>=6.0; extra == "chain"
23
26
  Provides-Extra: book
24
27
  Requires-Dist: web3scout>=0.2.0; extra == "book"
25
28
  Requires-Dist: web3<7.0,>=6.0; extra == "book"
@@ -52,21 +55,34 @@ For onchain event access and scripting, pair it with [Web3Scout](https://github.
52
55
 
53
56
  🔗 SPDX-Anchor: [anchorregistry.ai/AR-2026-YdPXB5g](https://anchorregistry.ai/AR-2026-YdPXB5g)
54
57
 
55
- ## 🆕 What's new in v2.0
58
+ ## 🆕 What's new in v2.1
56
59
 
57
- v2.0 makes DeFiPy's primitives **agent-ready** without coupling the library to any specific LLM framework. Three new modules land alongside the existing 22 primitives:
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.
61
+
62
+ * **`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
+ * **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
+ * **`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."
65
+ * **`[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.
66
+
67
+ 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
+
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.
70
+
71
+ ## v2.0 foundations
72
+
73
+ The State Twin abstraction, agentic primitives, and MCP server pattern shipped in v2.0. v2.1 builds on that surface without changing it:
58
74
 
59
75
  * **`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.
60
- * **`defipy.twin`** — the **State Twin** abstraction. `MockProvider` ships four canonical synthetic pools (V2, V3, Balancer, Stableswap) for notebooks and tests; `LiveProvider` (chain reads) lands in v2.1.
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.
61
77
  * **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.
62
78
 
63
79
  ### What is MCP?
64
80
 
65
81
  The [Model Context Protocol](https://modelcontextprotocol.io) is an open standard for giving LLMs access to tools and data. With DeFiPy's MCP server running, Claude can answer natural-language LP questions backed by exact math:
66
82
 
67
- > *"Is the ETH/DAI V2 pool healthy? Any rug signals?"*
83
+ > *"Is this V2 pool healthy? Any rug signals?"*
68
84
 
69
- Claude reads the tool descriptions, picks `CheckPoolHealth`, calls it against a MockProvider twin, receives the typed dataclass result, and synthesizes a response — one that correctly interprets TVL, LP concentration, and activity signals, because the primitives encode the domain, not the LLM.
85
+ Claude reads the tool descriptions, picks `CheckPoolHealth`, calls it against a twin (synthetic via MockProvider, or live via LiveProvider), receives the typed dataclass result, and synthesizes a response — one that correctly interprets TVL, LP concentration, and activity signals, because the primitives encode the domain, not the LLM.
70
86
 
71
87
  **Substrate, not agent.** DeFiPy itself has zero LLM dependencies and zero network calls at core. The library is a substrate that agent runtimes (including forthcoming DeFiMind and any third-party project) build on top of.
72
88
 
@@ -84,10 +100,10 @@ Claude reads the tool descriptions, picks `CheckPoolHealth`, calls it against a
84
100
 
85
101
  Full primitive catalog with LP-question mappings lives in the [v2 docs](https://defipy.org).
86
102
 
87
- *Legacy event-driven agents (`python/prod/agents/`) are preserved for chapter 9 of* Hands-On AMMs with Python *but are not the go-forward architecture — new agentic behavior composes from primitives.*
103
+ *Legacy event-driven agents (`python/prod/agents/`) are preserved for chapter 9 of* Hands-On AMMs with Python *but are not the go-forward architecture — new agentic behavior composes from primitives running against State Twin twins.*
88
104
 
89
105
  ## 📝 Docs
90
- Visit [**DeFiPy docs**](https://defipy.org) for full documentation
106
+ Visit [**DeFiPy docs**](https://defipy.org) for full documentation. The [LiveProvider page](https://defipy.org/live-provider/) covers the v2.1 chain-reading surface in detail.
91
107
 
92
108
  ## 🔍 Install
93
109
 
@@ -97,6 +113,28 @@ DeFiPy requires **Python 3.10 or later**. Install via pip:
97
113
  > pip install defipy
98
114
  ```
99
115
 
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.
117
+
118
+ ### Chain install (LiveProvider — v2.1+)
119
+
120
+ To use `LiveProvider` for on-chain pool snapshots, install the `[chain]` extra:
121
+
122
+ ```
123
+ > pip install defipy[chain]
124
+ ```
125
+
126
+ 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:
127
+
128
+ ```python
129
+ from defipy.twin import LiveProvider, StateTwinBuilder
130
+
131
+ provider = LiveProvider("https://eth-mainnet.g.alchemy.com/v2/<key>")
132
+ snapshot = provider.snapshot("uniswap_v2:0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc")
133
+ lp = StateTwinBuilder().build(snapshot)
134
+ ```
135
+
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.
137
+
100
138
  ### MCP install (Claude Desktop / Claude Code demo)
101
139
 
102
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:
@@ -115,7 +153,7 @@ Chapter 9 of *Hands-On AMMs with Python* — *Building Autonomous DeFi Agents*
115
153
  > pip install defipy[book]
116
154
  ```
117
155
 
118
- This pulls in `web3scout` on top of the core install, enabling the chain event monitoring, ABI loading, and token-fetching utilities that chapter 9's agents require. Other chapters work with the core install alone.
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.
119
157
 
120
158
  ### Anvil install (local Foundry workflows)
121
159
 
@@ -125,7 +163,7 @@ If you're using `ExecuteScript` or `UniswapScriptHelper` against a local [Anvil]
125
163
  > pip install defipy[anvil]
126
164
  ```
127
165
 
128
- `[book]` already includes everything in `[anvil]`, so book readers only need `[book]`.
166
+ `[book]` and `[chain]` already include everything in `[anvil]`, so users on either of those don't need it separately.
129
167
 
130
168
  ### Source install
131
169
 
@@ -159,11 +197,11 @@ DeFiPy is accompanied by educational resources for developers and researchers
159
197
  interested in on-chain analytics and DeFi modeling.
160
198
 
161
199
  ### 📘 Textbook
162
- **_DeFiPy: Python SDK for On-Chain Analytics_**
200
+ **_DeFiPy: Python SDK for On-Chain Analytics_**
163
201
 
164
202
  A comprehensive guide to DeFi analytics, AMM modeling, and simulation.
165
203
 
166
- 🔗 **Buy on Amazon:** https://www.amazon.com/dp/B0G3RV5QRB
204
+ 🔗 **Buy on Amazon:** https://www.amazon.com/dp/B0G3RV5QRB
167
205
 
168
206
  ### 🎓 Course
169
207
  **On-Chain Analytics Foundations**
@@ -180,25 +218,32 @@ Topics include:
180
218
 
181
219
  🔗 **Course Page:** https://defipy.thinkific.com/products/courses/foundations
182
220
 
183
- ## 🚀 Quick Example (high-level: primitives + State Twin)
221
+ ## 🚀 Quick Example (LiveProvider: real chain state + primitives)
184
222
  --------------------------
185
223
 
186
- The fastest way to see DeFiPy at work. `MockProvider` ships canonical synthetic pools; `StateTwinBuilder` turns a snapshot into a usable exchange object; any primitive runs against it.
224
+ 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.
187
225
 
188
226
  from defipy import AnalyzePosition
189
- from defipy.twin import MockProvider, StateTwinBuilder
227
+ from defipy.twin import LiveProvider, StateTwinBuilder
190
228
 
191
- # Build a synthetic ETH/DAI Uniswap V2 pool
192
- provider = MockProvider()
193
- builder = StateTwinBuilder()
194
- lp = builder.build(provider.snapshot("eth_dai_v2"))
229
+ # Pull live state from a real Uniswap V2 pool — WETH/USDC mainnet
230
+ provider = LiveProvider("https://eth-mainnet.g.alchemy.com/v2/<key>")
231
+ snapshot = provider.snapshot(
232
+ "uniswap_v2:0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc"
233
+ )
234
+ lp = StateTwinBuilder().build(snapshot)
235
+
236
+ # 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}")
195
240
 
196
- # Ask the primitive: why is this LP position gaining or losing money?
241
+ # Run any primitive against the live twin same call shape as MockProvider
197
242
  result = AnalyzePosition().apply(
198
243
  lp,
199
244
  lp_init_amt=1.0,
200
245
  entry_x_amt=1000,
201
- entry_y_amt=100000,
246
+ entry_y_amt=3_000_000,
202
247
  )
203
248
 
204
249
  print(f"Diagnosis: {result.diagnosis}")
@@ -206,14 +251,24 @@ The fastest way to see DeFiPy at work. `MockProvider` ships canonical synthetic
206
251
  print(f"IL %: {result.il_percentage:.4f}")
207
252
  print(f"Current val: {result.current_value:.4f}")
208
253
 
209
- At-entry state with 100% pool ownership yields `diagnosis=il_dominant` with zero IL and fees. Other recipes (`eth_dai_v3`, `eth_dai_balancer_50_50`, `usdc_dai_stableswap_A10`) exercise the other three AMM families; every curated primitive works against them.
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.
255
+
256
+ **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
+
258
+ from defipy.twin import MockProvider, StateTwinBuilder
259
+
260
+ provider = MockProvider()
261
+ lp = StateTwinBuilder().build(provider.snapshot("eth_dai_v2"))
262
+ # ... AnalyzePosition().apply(lp, ...) works identically
263
+
264
+ The State Twin abstraction is what makes this work: providers know about *sources*, primitives know about *math*, the twin is the canonical handoff between them. Same `lp` shape from a synthetic recipe, a live chain read, or a custom CSV-backed provider — every primitive consumes them identically.
210
265
 
211
266
  For LLM-driven interaction with these primitives, see the [MCP server README](./python/mcp/README.md).
212
267
 
213
268
  ## 🧱 Quick Example (low-level: Uniswap V3 pool construction)
214
269
  --------------------------
215
270
 
216
- To construct a Uniswap V3 pool directly (outside MockProvider's canonical recipes), you must first create the tokens in the pair using the `ERC20` object. Next, create a liquidity pool (LP) factory using `IFactory` object. Once this is setup, an unlimited amount of LPs can be created; the procedures for such are as follows:
271
+ To construct a Uniswap V3 pool directly (outside MockProvider's canonical recipes and outside LiveProvider's chain reads), you must first create the tokens in the pair using the `ERC20` object. Next, create a liquidity pool (LP) factory using `IFactory` object. Once this is setup, an unlimited amount of LPs can be created; the procedures for such are as follows:
217
272
 
218
273
  from defipy import *
219
274
 
@@ -252,7 +307,7 @@ To construct a Uniswap V3 pool directly (outside MockProvider's canonical recipe
252
307
 
253
308
  ## 🧪 Tests
254
309
 
255
- DeFiPy ships 629 tests across primitives, tools, twin, packaging, and the MCP server dispatch layer. Run the full suite:
310
+ DeFiPy ships ~677 tests across primitives, tools, twin, packaging, and the MCP server dispatch layer. Run the full suite:
256
311
 
257
312
  pytest python/test/ -v
258
313
 
@@ -260,6 +315,10 @@ Run just the primitive suite (504 tests, no MCP or twin dependencies):
260
315
 
261
316
  pytest python/test/primitives/ -v
262
317
 
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:
319
+
320
+ DEFIPY_LIVE_RPC=https://eth-mainnet.g.alchemy.com/v2/<key> pytest -m live_rpc -v
321
+
263
322
  ## License
264
323
  Licensed under the Apache License, Version 2.0.
265
324
  See [LICENSE](./LICENSE) and [NOTICE](./NOTICE) for details.
@@ -75,6 +75,7 @@ python/prod/tools/__init__.py
75
75
  python/prod/tools/registry.py
76
76
  python/prod/tools/schemas.py
77
77
  python/prod/twin/__init__.py
78
+ python/prod/twin/_rpc.py
78
79
  python/prod/twin/builder.py
79
80
  python/prod/twin/live_provider.py
80
81
  python/prod/twin/mock_provider.py
@@ -17,5 +17,9 @@ web3<7.0,>=6.0
17
17
  web3scout>=0.2.0
18
18
  web3<7.0,>=6.0
19
19
 
20
+ [chain]
21
+ web3scout>=0.2.0
22
+ web3<7.0,>=6.0
23
+
20
24
  [mcp]
21
25
  mcp>=1.27.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: DeFiPy
3
- Version: 2.0.0
3
+ Version: 2.1.0a2
4
4
  Summary: Python SDK for Agentic DeFi
5
5
  Home-page: http://github.com/defipy-devs/defipy
6
6
  Author: icmoore
@@ -20,6 +20,9 @@ Requires-Dist: bokeh>=3.3
20
20
  Requires-Dist: uniswappy>=1.7.9
21
21
  Requires-Dist: balancerpy>=1.1.0
22
22
  Requires-Dist: stableswappy>=1.1.0
23
+ Provides-Extra: chain
24
+ Requires-Dist: web3scout>=0.2.0; extra == "chain"
25
+ Requires-Dist: web3<7.0,>=6.0; extra == "chain"
23
26
  Provides-Extra: book
24
27
  Requires-Dist: web3scout>=0.2.0; extra == "book"
25
28
  Requires-Dist: web3<7.0,>=6.0; extra == "book"
@@ -52,21 +55,34 @@ For onchain event access and scripting, pair it with [Web3Scout](https://github.
52
55
 
53
56
  🔗 SPDX-Anchor: [anchorregistry.ai/AR-2026-YdPXB5g](https://anchorregistry.ai/AR-2026-YdPXB5g)
54
57
 
55
- ## 🆕 What's new in v2.0
58
+ ## 🆕 What's new in v2.1
56
59
 
57
- v2.0 makes DeFiPy's primitives **agent-ready** without coupling the library to any specific LLM framework. Three new modules land alongside the existing 22 primitives:
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.
61
+
62
+ * **`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
+ * **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
+ * **`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."
65
+ * **`[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.
66
+
67
+ 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
+
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.
70
+
71
+ ## v2.0 foundations
72
+
73
+ The State Twin abstraction, agentic primitives, and MCP server pattern shipped in v2.0. v2.1 builds on that surface without changing it:
58
74
 
59
75
  * **`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.
60
- * **`defipy.twin`** — the **State Twin** abstraction. `MockProvider` ships four canonical synthetic pools (V2, V3, Balancer, Stableswap) for notebooks and tests; `LiveProvider` (chain reads) lands in v2.1.
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.
61
77
  * **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.
62
78
 
63
79
  ### What is MCP?
64
80
 
65
81
  The [Model Context Protocol](https://modelcontextprotocol.io) is an open standard for giving LLMs access to tools and data. With DeFiPy's MCP server running, Claude can answer natural-language LP questions backed by exact math:
66
82
 
67
- > *"Is the ETH/DAI V2 pool healthy? Any rug signals?"*
83
+ > *"Is this V2 pool healthy? Any rug signals?"*
68
84
 
69
- Claude reads the tool descriptions, picks `CheckPoolHealth`, calls it against a MockProvider twin, receives the typed dataclass result, and synthesizes a response — one that correctly interprets TVL, LP concentration, and activity signals, because the primitives encode the domain, not the LLM.
85
+ Claude reads the tool descriptions, picks `CheckPoolHealth`, calls it against a twin (synthetic via MockProvider, or live via LiveProvider), receives the typed dataclass result, and synthesizes a response — one that correctly interprets TVL, LP concentration, and activity signals, because the primitives encode the domain, not the LLM.
70
86
 
71
87
  **Substrate, not agent.** DeFiPy itself has zero LLM dependencies and zero network calls at core. The library is a substrate that agent runtimes (including forthcoming DeFiMind and any third-party project) build on top of.
72
88
 
@@ -84,10 +100,10 @@ Claude reads the tool descriptions, picks `CheckPoolHealth`, calls it against a
84
100
 
85
101
  Full primitive catalog with LP-question mappings lives in the [v2 docs](https://defipy.org).
86
102
 
87
- *Legacy event-driven agents (`python/prod/agents/`) are preserved for chapter 9 of* Hands-On AMMs with Python *but are not the go-forward architecture — new agentic behavior composes from primitives.*
103
+ *Legacy event-driven agents (`python/prod/agents/`) are preserved for chapter 9 of* Hands-On AMMs with Python *but are not the go-forward architecture — new agentic behavior composes from primitives running against State Twin twins.*
88
104
 
89
105
  ## 📝 Docs
90
- Visit [**DeFiPy docs**](https://defipy.org) for full documentation
106
+ Visit [**DeFiPy docs**](https://defipy.org) for full documentation. The [LiveProvider page](https://defipy.org/live-provider/) covers the v2.1 chain-reading surface in detail.
91
107
 
92
108
  ## 🔍 Install
93
109
 
@@ -97,6 +113,28 @@ DeFiPy requires **Python 3.10 or later**. Install via pip:
97
113
  > pip install defipy
98
114
  ```
99
115
 
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.
117
+
118
+ ### Chain install (LiveProvider — v2.1+)
119
+
120
+ To use `LiveProvider` for on-chain pool snapshots, install the `[chain]` extra:
121
+
122
+ ```
123
+ > pip install defipy[chain]
124
+ ```
125
+
126
+ 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:
127
+
128
+ ```python
129
+ from defipy.twin import LiveProvider, StateTwinBuilder
130
+
131
+ provider = LiveProvider("https://eth-mainnet.g.alchemy.com/v2/<key>")
132
+ snapshot = provider.snapshot("uniswap_v2:0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc")
133
+ lp = StateTwinBuilder().build(snapshot)
134
+ ```
135
+
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.
137
+
100
138
  ### MCP install (Claude Desktop / Claude Code demo)
101
139
 
102
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:
@@ -115,7 +153,7 @@ Chapter 9 of *Hands-On AMMs with Python* — *Building Autonomous DeFi Agents*
115
153
  > pip install defipy[book]
116
154
  ```
117
155
 
118
- This pulls in `web3scout` on top of the core install, enabling the chain event monitoring, ABI loading, and token-fetching utilities that chapter 9's agents require. Other chapters work with the core install alone.
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.
119
157
 
120
158
  ### Anvil install (local Foundry workflows)
121
159
 
@@ -125,7 +163,7 @@ If you're using `ExecuteScript` or `UniswapScriptHelper` against a local [Anvil]
125
163
  > pip install defipy[anvil]
126
164
  ```
127
165
 
128
- `[book]` already includes everything in `[anvil]`, so book readers only need `[book]`.
166
+ `[book]` and `[chain]` already include everything in `[anvil]`, so users on either of those don't need it separately.
129
167
 
130
168
  ### Source install
131
169
 
@@ -159,11 +197,11 @@ DeFiPy is accompanied by educational resources for developers and researchers
159
197
  interested in on-chain analytics and DeFi modeling.
160
198
 
161
199
  ### 📘 Textbook
162
- **_DeFiPy: Python SDK for On-Chain Analytics_**
200
+ **_DeFiPy: Python SDK for On-Chain Analytics_**
163
201
 
164
202
  A comprehensive guide to DeFi analytics, AMM modeling, and simulation.
165
203
 
166
- 🔗 **Buy on Amazon:** https://www.amazon.com/dp/B0G3RV5QRB
204
+ 🔗 **Buy on Amazon:** https://www.amazon.com/dp/B0G3RV5QRB
167
205
 
168
206
  ### 🎓 Course
169
207
  **On-Chain Analytics Foundations**
@@ -180,25 +218,32 @@ Topics include:
180
218
 
181
219
  🔗 **Course Page:** https://defipy.thinkific.com/products/courses/foundations
182
220
 
183
- ## 🚀 Quick Example (high-level: primitives + State Twin)
221
+ ## 🚀 Quick Example (LiveProvider: real chain state + primitives)
184
222
  --------------------------
185
223
 
186
- The fastest way to see DeFiPy at work. `MockProvider` ships canonical synthetic pools; `StateTwinBuilder` turns a snapshot into a usable exchange object; any primitive runs against it.
224
+ 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.
187
225
 
188
226
  from defipy import AnalyzePosition
189
- from defipy.twin import MockProvider, StateTwinBuilder
227
+ from defipy.twin import LiveProvider, StateTwinBuilder
190
228
 
191
- # Build a synthetic ETH/DAI Uniswap V2 pool
192
- provider = MockProvider()
193
- builder = StateTwinBuilder()
194
- lp = builder.build(provider.snapshot("eth_dai_v2"))
229
+ # Pull live state from a real Uniswap V2 pool — WETH/USDC mainnet
230
+ provider = LiveProvider("https://eth-mainnet.g.alchemy.com/v2/<key>")
231
+ snapshot = provider.snapshot(
232
+ "uniswap_v2:0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc"
233
+ )
234
+ lp = StateTwinBuilder().build(snapshot)
235
+
236
+ # 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}")
195
240
 
196
- # Ask the primitive: why is this LP position gaining or losing money?
241
+ # Run any primitive against the live twin same call shape as MockProvider
197
242
  result = AnalyzePosition().apply(
198
243
  lp,
199
244
  lp_init_amt=1.0,
200
245
  entry_x_amt=1000,
201
- entry_y_amt=100000,
246
+ entry_y_amt=3_000_000,
202
247
  )
203
248
 
204
249
  print(f"Diagnosis: {result.diagnosis}")
@@ -206,14 +251,24 @@ The fastest way to see DeFiPy at work. `MockProvider` ships canonical synthetic
206
251
  print(f"IL %: {result.il_percentage:.4f}")
207
252
  print(f"Current val: {result.current_value:.4f}")
208
253
 
209
- At-entry state with 100% pool ownership yields `diagnosis=il_dominant` with zero IL and fees. Other recipes (`eth_dai_v3`, `eth_dai_balancer_50_50`, `usdc_dai_stableswap_A10`) exercise the other three AMM families; every curated primitive works against them.
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.
255
+
256
+ **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
+
258
+ from defipy.twin import MockProvider, StateTwinBuilder
259
+
260
+ provider = MockProvider()
261
+ lp = StateTwinBuilder().build(provider.snapshot("eth_dai_v2"))
262
+ # ... AnalyzePosition().apply(lp, ...) works identically
263
+
264
+ The State Twin abstraction is what makes this work: providers know about *sources*, primitives know about *math*, the twin is the canonical handoff between them. Same `lp` shape from a synthetic recipe, a live chain read, or a custom CSV-backed provider — every primitive consumes them identically.
210
265
 
211
266
  For LLM-driven interaction with these primitives, see the [MCP server README](./python/mcp/README.md).
212
267
 
213
268
  ## 🧱 Quick Example (low-level: Uniswap V3 pool construction)
214
269
  --------------------------
215
270
 
216
- To construct a Uniswap V3 pool directly (outside MockProvider's canonical recipes), you must first create the tokens in the pair using the `ERC20` object. Next, create a liquidity pool (LP) factory using `IFactory` object. Once this is setup, an unlimited amount of LPs can be created; the procedures for such are as follows:
271
+ To construct a Uniswap V3 pool directly (outside MockProvider's canonical recipes and outside LiveProvider's chain reads), you must first create the tokens in the pair using the `ERC20` object. Next, create a liquidity pool (LP) factory using `IFactory` object. Once this is setup, an unlimited amount of LPs can be created; the procedures for such are as follows:
217
272
 
218
273
  from defipy import *
219
274
 
@@ -252,7 +307,7 @@ To construct a Uniswap V3 pool directly (outside MockProvider's canonical recipe
252
307
 
253
308
  ## 🧪 Tests
254
309
 
255
- DeFiPy ships 629 tests across primitives, tools, twin, packaging, and the MCP server dispatch layer. Run the full suite:
310
+ DeFiPy ships ~677 tests across primitives, tools, twin, packaging, and the MCP server dispatch layer. Run the full suite:
256
311
 
257
312
  pytest python/test/ -v
258
313
 
@@ -260,6 +315,10 @@ Run just the primitive suite (504 tests, no MCP or twin dependencies):
260
315
 
261
316
  pytest python/test/primitives/ -v
262
317
 
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:
319
+
320
+ DEFIPY_LIVE_RPC=https://eth-mainnet.g.alchemy.com/v2/<key> pytest -m live_rpc -v
321
+
263
322
  ## License
264
323
  Licensed under the Apache License, Version 2.0.
265
324
  See [LICENSE](./LICENSE) and [NOTICE](./NOTICE) for details.