sally-defi-py-sdk 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. sally_defi_py_sdk-0.2.0/LICENSE +21 -0
  2. sally_defi_py_sdk-0.2.0/PKG-INFO +260 -0
  3. sally_defi_py_sdk-0.2.0/README.md +227 -0
  4. sally_defi_py_sdk-0.2.0/pyproject.toml +73 -0
  5. sally_defi_py_sdk-0.2.0/src/sally_defi/__init__.py +95 -0
  6. sally_defi_py_sdk-0.2.0/src/sally_defi/aio/__init__.py +21 -0
  7. sally_defi_py_sdk-0.2.0/src/sally_defi/aio/client.py +275 -0
  8. sally_defi_py_sdk-0.2.0/src/sally_defi/aio/modules/__init__.py +0 -0
  9. sally_defi_py_sdk-0.2.0/src/sally_defi/aio/modules/fees.py +51 -0
  10. sally_defi_py_sdk-0.2.0/src/sally_defi/aio/modules/liquidity.py +119 -0
  11. sally_defi_py_sdk-0.2.0/src/sally_defi/aio/modules/prices.py +53 -0
  12. sally_defi_py_sdk-0.2.0/src/sally_defi/aio/modules/swap.py +247 -0
  13. sally_defi_py_sdk-0.2.0/src/sally_defi/aio/modules/treasury.py +40 -0
  14. sally_defi_py_sdk-0.2.0/src/sally_defi/aio/modules/wallet.py +36 -0
  15. sally_defi_py_sdk-0.2.0/src/sally_defi/aio/token.py +56 -0
  16. sally_defi_py_sdk-0.2.0/src/sally_defi/client.py +403 -0
  17. sally_defi_py_sdk-0.2.0/src/sally_defi/constants.py +46 -0
  18. sally_defi_py_sdk-0.2.0/src/sally_defi/data/deployment.json +1 -0
  19. sally_defi_py_sdk-0.2.0/src/sally_defi/deployment.py +127 -0
  20. sally_defi_py_sdk-0.2.0/src/sally_defi/errors.py +154 -0
  21. sally_defi_py_sdk-0.2.0/src/sally_defi/modules/__init__.py +0 -0
  22. sally_defi_py_sdk-0.2.0/src/sally_defi/modules/admin.py +149 -0
  23. sally_defi_py_sdk-0.2.0/src/sally_defi/modules/fees.py +66 -0
  24. sally_defi_py_sdk-0.2.0/src/sally_defi/modules/liquidity.py +357 -0
  25. sally_defi_py_sdk-0.2.0/src/sally_defi/modules/prices.py +89 -0
  26. sally_defi_py_sdk-0.2.0/src/sally_defi/modules/swap.py +416 -0
  27. sally_defi_py_sdk-0.2.0/src/sally_defi/modules/treasury.py +73 -0
  28. sally_defi_py_sdk-0.2.0/src/sally_defi/modules/wallet.py +41 -0
  29. sally_defi_py_sdk-0.2.0/src/sally_defi/permit2.py +181 -0
  30. sally_defi_py_sdk-0.2.0/src/sally_defi/py.typed +0 -0
  31. sally_defi_py_sdk-0.2.0/src/sally_defi/safety.py +104 -0
  32. sally_defi_py_sdk-0.2.0/src/sally_defi/token.py +183 -0
  33. sally_defi_py_sdk-0.2.0/src/sally_defi/types.py +423 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sally (sally.tools)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,260 @@
1
+ Metadata-Version: 2.4
2
+ Name: sally-defi-py-sdk
3
+ Version: 0.2.0
4
+ Summary: Modern Python SDK for the Sally DeFi CrossHybrid protocol (Base + BSC) — swaps, pricing, liquidity, treasury.
5
+ Keywords: defi,ethereum,base,bsc,web3,uniswap,swap,liquidity,sally
6
+ Author: Sally.tools
7
+ Author-email: Sally.tools <support@sally.tools>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Intended Audience :: Financial and Insurance Industry
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
+ Classifier: Topic :: Office/Business :: Financial
20
+ Classifier: Typing :: Typed
21
+ Requires-Dist: web3>=7.6,<8
22
+ Requires-Dist: eth-account>=0.13,<0.14
23
+ Requires-Dist: eth-abi>=5,<6
24
+ Requires-Dist: eth-utils>=5,<6
25
+ Requires-Dist: pydantic>=2.9,<3
26
+ Requires-Python: >=3.12
27
+ Project-URL: Homepage, https://sally.tools
28
+ Project-URL: Repository, https://github.com/SallyTools/sally-defi-py-sdk
29
+ Project-URL: Documentation, https://github.com/SallyTools/sally-defi-py-sdk/tree/main/docs
30
+ Project-URL: Issues, https://github.com/SallyTools/sally-defi-py-sdk/issues
31
+ Project-URL: Changelog, https://github.com/SallyTools/sally-defi-py-sdk/blob/main/CHANGELOG.md
32
+ Description-Content-Type: text/markdown
33
+
34
+ <div align="center">
35
+
36
+ <img src="assets/header.svg" alt="sally-defi-py-sdk · Python SDK" width="100%">
37
+
38
+ # sally-defi-py-sdk · Python SDK
39
+
40
+ **One client for CrossHybrid swaps & liquidity on Base + BSC.**
41
+
42
+ Wraps the live [Sally](https://sally.tools) v2.0.2 protocol — best-route hybrid
43
+ swaps, V2·V3·V4·Slipstream liquidity, 1e18 USD pricing, honeypot screening, locks,
44
+ referral fees and the multi-owner treasury — behind one typed, beginner-friendly
45
+ and AI-agent-ready API.
46
+
47
+ [Website](https://sally.tools) · [Docs](docs/) · [Examples](examples/) · `support@sally.tools`
48
+
49
+ </div>
50
+
51
+ ---
52
+
53
+ ## Why sally-defi-py-sdk
54
+
55
+ Most Python DeFi code is raw `web3.py`: untyped tuples, hand-rolled approvals, a
56
+ quote you *hope* matches execution, and zero protection against honeypots or
57
+ sandwiches. sally-defi-py-sdk collapses all of that into **one safe call**.
58
+
59
+ `swap.execute` does the work a careful integrator would do by hand — approve →
60
+ enumerate routes → **simulate every route on-chain** → screen the output token for
61
+ honeypot/tax → set `minOut` from the *simulated* output → send → **assert you
62
+ actually received it**. That whole pipeline is the default, not an opt-in.
63
+
64
+ * 🛡️ **Safety in the hot path.** Simulate-before-execute + post-trade balance-delta
65
+ assertion — not just in your test suite. (The balance-delta check is something
66
+ even mature SDKs don't ship.)
67
+ * 🧱 **Typed end-to-end.** `pos.liquidity`, `plan.is_safe`, `quote.estimated_amount_out`
68
+ — dataclasses, autocomplete, JSON-able. No `tuple[7]`.
69
+ * 🤖 **AI-agent-ready by construction.** Every return serializes cleanly, so wiring
70
+ Sally into LLM tools is mechanical.
71
+ * ⚡ **Async + MEV-protection + permit** are constructor/keyword arguments, not projects.
72
+ * 🪶 **Light deps** (web3, eth-account, eth-abi, eth-utils, pydantic), Python ≥3.12, `py.typed`.
73
+
74
+ Honest about scope: Sally routes within **its own protocol** on **Base + BSC** — it
75
+ is not a 100-source aggregator. Full, cited comparison (vorteile *and* nachteile)
76
+ vs raw web3.py / uniswap-python / eth_defi / Ape / aggregator SDKs:
77
+ **[docs/comparison.md](docs/comparison.md)**.
78
+
79
+ ## What you get
80
+
81
+ * **One object, every function.** `SallyClient` exposes the whole protocol through
82
+ feature namespaces (`prices`, `swap`, `wallet`, `liquidity`, `fees`, `treasury`,
83
+ `admin`). Reads need only an RPC; writes need a signer.
84
+ * **Safe by default.** `swap.execute` enumerates routes, **integrity-checks** each so
85
+ funds can never enter a wrong pool, **simulates** every candidate on-chain, picks
86
+ the best realized output, runs a **honeypot/tax probe** on the output token, sets
87
+ `minOut` from the simulation, then **asserts the received balance actually grew**.
88
+ * **Single source of truth.** All addresses + ABIs come from the bundled
89
+ `deployment.json` (addresses + ABIs only). Nothing hard-coded; drop in a new
90
+ deployment and the SDK follows.
91
+ * **Proxy-fallback aware.** v2.0.2 serves Lens views through the swap proxy and
92
+ Sidecar views through the liq proxy — the SDK wires this for you.
93
+ * **Typed returns.** Every struct is a dataclass (`SwapPath`, `V3Position`, `Lock`,
94
+ `SwapPlan`, …) — `pos.liquidity`, not `pos[7]`.
95
+
96
+ ## Install
97
+
98
+ ```bash
99
+ uv add sally-defi-py-sdk # or: pip install sally-defi-py-sdk
100
+ ```
101
+
102
+ > Install as **`sally-defi-py-sdk`**, import as **`sally_defi`**
103
+ > (like `pip install scikit-learn` → `import sklearn`).
104
+
105
+ Requires Python ≥ 3.12 and `web3 >= 7.6`.
106
+
107
+ ## Quickstart (read-only)
108
+
109
+ ```python
110
+ from sally_defi import SallyClient
111
+ from sally_defi.constants import Base
112
+
113
+ sally = SallyClient("base", "https://mainnet.base.org")
114
+
115
+ sally.prices.usd(Base.USDC).as_float # 1.0 (display / spot-mid)
116
+ sally.prices.usd_impact(Base.WETH).as_float # 1703.19 (execution-aware)
117
+
118
+ quote = sally.swap.quote(Base.WETH, Base.USDC, 10**18)
119
+ quote.estimated_amount_out / 1e6 # 1703.45 USDC
120
+ ```
121
+
122
+ ## Swapping — safe by default
123
+
124
+ ```python
125
+ sally = SallyClient("base", RPC, private_key="0x…") # or SALLY_PRIVATE_KEY env
126
+
127
+ # Inspect first: compares every route, simulates each, screens the output token.
128
+ plan = sally.swap.plan(Base.WETH, Base.USDC, 10**18)
129
+ plan.summary() # 'SwapPlan(… out~1702924727 sim=1702924727 min=1694410103 impact=13bps steps=2 SAFE)'
130
+ plan.is_safe # False if honeypot / excessive tax / >15% impact / bad route
131
+ plan.candidates # every route considered, with simulated output
132
+
133
+ # Execute: same vetting, then send + balance-delta assertion.
134
+ receipt = sally.swap.execute(Base.WETH, Base.USDC, 10**18, slippage_bps=50)
135
+
136
+ # Native ETH in — pass the NATIVE sentinel; value is attached for you.
137
+ from sally_defi.token import NATIVE
138
+ sally.swap.execute(NATIVE, Base.USDC, 10**17, slippage_bps=50)
139
+ ```
140
+
141
+ What `execute` does, in order: approve (exact amount) → enumerate routes →
142
+ integrity-check → simulate each on-chain → pick best realized output →
143
+ honeypot/tax preflight → `minOut` from the simulation → send →
144
+ **assert received ≥ minOut**. See [`docs/safety.md`](docs/safety.md).
145
+
146
+ Tune the guard rails:
147
+
148
+ ```python
149
+ from sally_defi import SafetyConfig
150
+ sally = SallyClient("base", RPC, private_key="0x…",
151
+ safety=SafetyConfig(slippage_bps=30, tax_block_bps=3000,
152
+ price_impact_block_bps=1000))
153
+ ```
154
+
155
+ ## Liquidity
156
+
157
+ ```python
158
+ sally.liquidity.add_v2(dex_id=4, token_a=Base.WETH, token_b=Base.USDC,
159
+ amount_a=10**15, amount_b=2_000_000, lock_days=0)
160
+
161
+ sally.liquidity.positions_v3(wallet, 0, 10) # list[V3Position]
162
+ sally.liquidity.locks(wallet) # list[Lock]
163
+ sally.liquidity.claimable_fees(npm, token_id) # ClaimableFees
164
+ # add_v3 / add_v4 / add_slipstream, increase/decrease, remove_v2,
165
+ # lock/unlock, claim_fees_v3/v4(+_locked), mass_claim_fees, harvest_op
166
+ ```
167
+
168
+ ## Referral system 💸
169
+
170
+ Every swap and liquidity action takes a `referral` address. Pass yours and the
171
+ protocol accrues referral fees to it; read and claim them anytime:
172
+
173
+ ```python
174
+ sally.swap.execute(Base.WETH, Base.USDC, 10**18, referral="0xYourRef")
175
+
176
+ sally.fees.total_referral_owed("0xYourRef") # total owed across tokens
177
+ sally.fees.referral_tokens("0xYourRef") # per-token breakdown (paged)
178
+ sally.fees.claim_referral([Base.USDC, Base.WETH]) # claim selected tokens
179
+ ```
180
+
181
+ See [`docs/referrals.md`](docs/referrals.md).
182
+
183
+ ## Async · permit · private mempool
184
+
185
+ ```python
186
+ # Async (concurrent quoting + simulation)
187
+ from sally_defi.aio import AsyncSallyClient
188
+ sally = AsyncSallyClient("base", RPC, private_key="0x…")
189
+ await sally.swap.execute(Base.WETH, Base.USDC, 10**18, slippage_bps=50)
190
+
191
+ # EIP-2612 permit instead of approve
192
+ sally.swap.execute(Base.USDC, Base.WETH, 10**8, approval="permit")
193
+
194
+ # Private mempool (MEV protection)
195
+ from sally_defi.constants import PrivateRelays
196
+ SallyClient("base", RPC, private_key="0x…", private_rpc_url=PrivateRelays.FLASHBOTS_FAST)
197
+ ```
198
+
199
+ Full guide: [`docs/advanced.md`](docs/advanced.md).
200
+
201
+ ## Namespaces
202
+
203
+ | Namespace | What it covers |
204
+ |---|---|
205
+ | `client.prices` | `usd` (display), `usd_impact` (exec), `spot`, `weth`, `usd_liquidity`, `token_info` |
206
+ | `client.swap` | `quote(_v2/v3/v4/deep)`, `candidates`, `plan`, `simulate_route`, `execute`, `token_info` |
207
+ | `client.wallet` | `balances`, `balances_raw`, `total_usd` |
208
+ | `client.liquidity` | add / increase / decrease / remove / lock / claim / harvest, positions, pool state, dex registry |
209
+ | `client.fees` | referral + batch fee reads & claims, `swap_fee` |
210
+ | `client.treasury` | owners, withdraw, `execute`, `swap_auto` |
211
+ | `client.admin` | owner-only setters, DEX registry, pause, rescue, UUPS upgrade |
212
+
213
+ Raw contracts are always reachable: `client.swap_contract`, `…liquidity_contract`,
214
+ `…lens_contract`, `…sidecar_contract`, `…treasury_contract`.
215
+
216
+ ## AI agents
217
+
218
+ Every call returns a JSON-able dataclass with a clear docstring — wrapping Sally as
219
+ LLM tools is trivial. See [`docs/ai-agents.md`](docs/ai-agents.md) and
220
+ [`examples/10_ai_agent_tools.py`](examples/10_ai_agent_tools.py).
221
+
222
+ ## Docs
223
+
224
+ | | |
225
+ |---|---|
226
+ | [Why sally-defi-py-sdk](docs/comparison.md) | comparison vs other DeFi SDKs, advantages & trade-offs |
227
+ | [Getting started](docs/getting-started.md) | install, connect, first read & swap |
228
+ | [Swap & safety](docs/safety.md) | route comparison, simulation, all guard rails |
229
+ | [Liquidity](docs/liquidity.md) | add/remove/lock/harvest across V2·V3·V4 |
230
+ | [Pricing](docs/pricing.md) | display vs execution price, spot, impact |
231
+ | [Referrals](docs/referrals.md) | earn & claim referral fees |
232
+ | [Advanced](docs/advanced.md) | async client, EIP-2612 permit, Permit2, private mempool, BSC |
233
+ | [AI agents](docs/ai-agents.md) | typed returns as tool functions |
234
+ | [API reference](docs/api-reference.md) | every namespace + method |
235
+
236
+ ## Live deployment (v2.0.2, Base = BSC)
237
+
238
+ | Contract | Address |
239
+ |---|---|
240
+ | SwapController (proxy) | `0x7777D0e2e2d772b5D750540B3932261574e87777` |
241
+ | LiquidityController (proxy) | `0x7777d7fFF155B043CE0A0785dd8c8c42bEbe7777` |
242
+ | Treasury | `0x7777D7dC7ea65F33EC126165e03C6B6030887777` |
243
+
244
+ ## Development & tests
245
+
246
+ ```bash
247
+ uv sync
248
+ uv run pytest -m "not fork" # offline unit tests
249
+ anvil --fork-url $BASE_RPC --port 8547 --chain-id 8453 &
250
+ SALLY_RPC_URL=http://127.0.0.1:8547 uv run pytest # + fork smoke tests
251
+ ```
252
+
253
+ ## Support
254
+
255
+ Questions, integrations, partnerships → [`support@sally.tools`](mailto:support@sally.tools)
256
+ · [sally.tools](https://sally.tools)
257
+
258
+ ## License
259
+
260
+ MIT
@@ -0,0 +1,227 @@
1
+ <div align="center">
2
+
3
+ <img src="assets/header.svg" alt="sally-defi-py-sdk · Python SDK" width="100%">
4
+
5
+ # sally-defi-py-sdk · Python SDK
6
+
7
+ **One client for CrossHybrid swaps & liquidity on Base + BSC.**
8
+
9
+ Wraps the live [Sally](https://sally.tools) v2.0.2 protocol — best-route hybrid
10
+ swaps, V2·V3·V4·Slipstream liquidity, 1e18 USD pricing, honeypot screening, locks,
11
+ referral fees and the multi-owner treasury — behind one typed, beginner-friendly
12
+ and AI-agent-ready API.
13
+
14
+ [Website](https://sally.tools) · [Docs](docs/) · [Examples](examples/) · `support@sally.tools`
15
+
16
+ </div>
17
+
18
+ ---
19
+
20
+ ## Why sally-defi-py-sdk
21
+
22
+ Most Python DeFi code is raw `web3.py`: untyped tuples, hand-rolled approvals, a
23
+ quote you *hope* matches execution, and zero protection against honeypots or
24
+ sandwiches. sally-defi-py-sdk collapses all of that into **one safe call**.
25
+
26
+ `swap.execute` does the work a careful integrator would do by hand — approve →
27
+ enumerate routes → **simulate every route on-chain** → screen the output token for
28
+ honeypot/tax → set `minOut` from the *simulated* output → send → **assert you
29
+ actually received it**. That whole pipeline is the default, not an opt-in.
30
+
31
+ * 🛡️ **Safety in the hot path.** Simulate-before-execute + post-trade balance-delta
32
+ assertion — not just in your test suite. (The balance-delta check is something
33
+ even mature SDKs don't ship.)
34
+ * 🧱 **Typed end-to-end.** `pos.liquidity`, `plan.is_safe`, `quote.estimated_amount_out`
35
+ — dataclasses, autocomplete, JSON-able. No `tuple[7]`.
36
+ * 🤖 **AI-agent-ready by construction.** Every return serializes cleanly, so wiring
37
+ Sally into LLM tools is mechanical.
38
+ * ⚡ **Async + MEV-protection + permit** are constructor/keyword arguments, not projects.
39
+ * 🪶 **Light deps** (web3, eth-account, eth-abi, eth-utils, pydantic), Python ≥3.12, `py.typed`.
40
+
41
+ Honest about scope: Sally routes within **its own protocol** on **Base + BSC** — it
42
+ is not a 100-source aggregator. Full, cited comparison (vorteile *and* nachteile)
43
+ vs raw web3.py / uniswap-python / eth_defi / Ape / aggregator SDKs:
44
+ **[docs/comparison.md](docs/comparison.md)**.
45
+
46
+ ## What you get
47
+
48
+ * **One object, every function.** `SallyClient` exposes the whole protocol through
49
+ feature namespaces (`prices`, `swap`, `wallet`, `liquidity`, `fees`, `treasury`,
50
+ `admin`). Reads need only an RPC; writes need a signer.
51
+ * **Safe by default.** `swap.execute` enumerates routes, **integrity-checks** each so
52
+ funds can never enter a wrong pool, **simulates** every candidate on-chain, picks
53
+ the best realized output, runs a **honeypot/tax probe** on the output token, sets
54
+ `minOut` from the simulation, then **asserts the received balance actually grew**.
55
+ * **Single source of truth.** All addresses + ABIs come from the bundled
56
+ `deployment.json` (addresses + ABIs only). Nothing hard-coded; drop in a new
57
+ deployment and the SDK follows.
58
+ * **Proxy-fallback aware.** v2.0.2 serves Lens views through the swap proxy and
59
+ Sidecar views through the liq proxy — the SDK wires this for you.
60
+ * **Typed returns.** Every struct is a dataclass (`SwapPath`, `V3Position`, `Lock`,
61
+ `SwapPlan`, …) — `pos.liquidity`, not `pos[7]`.
62
+
63
+ ## Install
64
+
65
+ ```bash
66
+ uv add sally-defi-py-sdk # or: pip install sally-defi-py-sdk
67
+ ```
68
+
69
+ > Install as **`sally-defi-py-sdk`**, import as **`sally_defi`**
70
+ > (like `pip install scikit-learn` → `import sklearn`).
71
+
72
+ Requires Python ≥ 3.12 and `web3 >= 7.6`.
73
+
74
+ ## Quickstart (read-only)
75
+
76
+ ```python
77
+ from sally_defi import SallyClient
78
+ from sally_defi.constants import Base
79
+
80
+ sally = SallyClient("base", "https://mainnet.base.org")
81
+
82
+ sally.prices.usd(Base.USDC).as_float # 1.0 (display / spot-mid)
83
+ sally.prices.usd_impact(Base.WETH).as_float # 1703.19 (execution-aware)
84
+
85
+ quote = sally.swap.quote(Base.WETH, Base.USDC, 10**18)
86
+ quote.estimated_amount_out / 1e6 # 1703.45 USDC
87
+ ```
88
+
89
+ ## Swapping — safe by default
90
+
91
+ ```python
92
+ sally = SallyClient("base", RPC, private_key="0x…") # or SALLY_PRIVATE_KEY env
93
+
94
+ # Inspect first: compares every route, simulates each, screens the output token.
95
+ plan = sally.swap.plan(Base.WETH, Base.USDC, 10**18)
96
+ plan.summary() # 'SwapPlan(… out~1702924727 sim=1702924727 min=1694410103 impact=13bps steps=2 SAFE)'
97
+ plan.is_safe # False if honeypot / excessive tax / >15% impact / bad route
98
+ plan.candidates # every route considered, with simulated output
99
+
100
+ # Execute: same vetting, then send + balance-delta assertion.
101
+ receipt = sally.swap.execute(Base.WETH, Base.USDC, 10**18, slippage_bps=50)
102
+
103
+ # Native ETH in — pass the NATIVE sentinel; value is attached for you.
104
+ from sally_defi.token import NATIVE
105
+ sally.swap.execute(NATIVE, Base.USDC, 10**17, slippage_bps=50)
106
+ ```
107
+
108
+ What `execute` does, in order: approve (exact amount) → enumerate routes →
109
+ integrity-check → simulate each on-chain → pick best realized output →
110
+ honeypot/tax preflight → `minOut` from the simulation → send →
111
+ **assert received ≥ minOut**. See [`docs/safety.md`](docs/safety.md).
112
+
113
+ Tune the guard rails:
114
+
115
+ ```python
116
+ from sally_defi import SafetyConfig
117
+ sally = SallyClient("base", RPC, private_key="0x…",
118
+ safety=SafetyConfig(slippage_bps=30, tax_block_bps=3000,
119
+ price_impact_block_bps=1000))
120
+ ```
121
+
122
+ ## Liquidity
123
+
124
+ ```python
125
+ sally.liquidity.add_v2(dex_id=4, token_a=Base.WETH, token_b=Base.USDC,
126
+ amount_a=10**15, amount_b=2_000_000, lock_days=0)
127
+
128
+ sally.liquidity.positions_v3(wallet, 0, 10) # list[V3Position]
129
+ sally.liquidity.locks(wallet) # list[Lock]
130
+ sally.liquidity.claimable_fees(npm, token_id) # ClaimableFees
131
+ # add_v3 / add_v4 / add_slipstream, increase/decrease, remove_v2,
132
+ # lock/unlock, claim_fees_v3/v4(+_locked), mass_claim_fees, harvest_op
133
+ ```
134
+
135
+ ## Referral system 💸
136
+
137
+ Every swap and liquidity action takes a `referral` address. Pass yours and the
138
+ protocol accrues referral fees to it; read and claim them anytime:
139
+
140
+ ```python
141
+ sally.swap.execute(Base.WETH, Base.USDC, 10**18, referral="0xYourRef")
142
+
143
+ sally.fees.total_referral_owed("0xYourRef") # total owed across tokens
144
+ sally.fees.referral_tokens("0xYourRef") # per-token breakdown (paged)
145
+ sally.fees.claim_referral([Base.USDC, Base.WETH]) # claim selected tokens
146
+ ```
147
+
148
+ See [`docs/referrals.md`](docs/referrals.md).
149
+
150
+ ## Async · permit · private mempool
151
+
152
+ ```python
153
+ # Async (concurrent quoting + simulation)
154
+ from sally_defi.aio import AsyncSallyClient
155
+ sally = AsyncSallyClient("base", RPC, private_key="0x…")
156
+ await sally.swap.execute(Base.WETH, Base.USDC, 10**18, slippage_bps=50)
157
+
158
+ # EIP-2612 permit instead of approve
159
+ sally.swap.execute(Base.USDC, Base.WETH, 10**8, approval="permit")
160
+
161
+ # Private mempool (MEV protection)
162
+ from sally_defi.constants import PrivateRelays
163
+ SallyClient("base", RPC, private_key="0x…", private_rpc_url=PrivateRelays.FLASHBOTS_FAST)
164
+ ```
165
+
166
+ Full guide: [`docs/advanced.md`](docs/advanced.md).
167
+
168
+ ## Namespaces
169
+
170
+ | Namespace | What it covers |
171
+ |---|---|
172
+ | `client.prices` | `usd` (display), `usd_impact` (exec), `spot`, `weth`, `usd_liquidity`, `token_info` |
173
+ | `client.swap` | `quote(_v2/v3/v4/deep)`, `candidates`, `plan`, `simulate_route`, `execute`, `token_info` |
174
+ | `client.wallet` | `balances`, `balances_raw`, `total_usd` |
175
+ | `client.liquidity` | add / increase / decrease / remove / lock / claim / harvest, positions, pool state, dex registry |
176
+ | `client.fees` | referral + batch fee reads & claims, `swap_fee` |
177
+ | `client.treasury` | owners, withdraw, `execute`, `swap_auto` |
178
+ | `client.admin` | owner-only setters, DEX registry, pause, rescue, UUPS upgrade |
179
+
180
+ Raw contracts are always reachable: `client.swap_contract`, `…liquidity_contract`,
181
+ `…lens_contract`, `…sidecar_contract`, `…treasury_contract`.
182
+
183
+ ## AI agents
184
+
185
+ Every call returns a JSON-able dataclass with a clear docstring — wrapping Sally as
186
+ LLM tools is trivial. See [`docs/ai-agents.md`](docs/ai-agents.md) and
187
+ [`examples/10_ai_agent_tools.py`](examples/10_ai_agent_tools.py).
188
+
189
+ ## Docs
190
+
191
+ | | |
192
+ |---|---|
193
+ | [Why sally-defi-py-sdk](docs/comparison.md) | comparison vs other DeFi SDKs, advantages & trade-offs |
194
+ | [Getting started](docs/getting-started.md) | install, connect, first read & swap |
195
+ | [Swap & safety](docs/safety.md) | route comparison, simulation, all guard rails |
196
+ | [Liquidity](docs/liquidity.md) | add/remove/lock/harvest across V2·V3·V4 |
197
+ | [Pricing](docs/pricing.md) | display vs execution price, spot, impact |
198
+ | [Referrals](docs/referrals.md) | earn & claim referral fees |
199
+ | [Advanced](docs/advanced.md) | async client, EIP-2612 permit, Permit2, private mempool, BSC |
200
+ | [AI agents](docs/ai-agents.md) | typed returns as tool functions |
201
+ | [API reference](docs/api-reference.md) | every namespace + method |
202
+
203
+ ## Live deployment (v2.0.2, Base = BSC)
204
+
205
+ | Contract | Address |
206
+ |---|---|
207
+ | SwapController (proxy) | `0x7777D0e2e2d772b5D750540B3932261574e87777` |
208
+ | LiquidityController (proxy) | `0x7777d7fFF155B043CE0A0785dd8c8c42bEbe7777` |
209
+ | Treasury | `0x7777D7dC7ea65F33EC126165e03C6B6030887777` |
210
+
211
+ ## Development & tests
212
+
213
+ ```bash
214
+ uv sync
215
+ uv run pytest -m "not fork" # offline unit tests
216
+ anvil --fork-url $BASE_RPC --port 8547 --chain-id 8453 &
217
+ SALLY_RPC_URL=http://127.0.0.1:8547 uv run pytest # + fork smoke tests
218
+ ```
219
+
220
+ ## Support
221
+
222
+ Questions, integrations, partnerships → [`support@sally.tools`](mailto:support@sally.tools)
223
+ · [sally.tools](https://sally.tools)
224
+
225
+ ## License
226
+
227
+ MIT
@@ -0,0 +1,73 @@
1
+ [project]
2
+ name = "sally-defi-py-sdk"
3
+ version = "0.2.0"
4
+ description = "Modern Python SDK for the Sally DeFi CrossHybrid protocol (Base + BSC) — swaps, pricing, liquidity, treasury."
5
+ readme = "README.md"
6
+ requires-python = ">=3.12"
7
+ license = "MIT"
8
+ license-files = ["LICENSE"]
9
+ keywords = ["defi", "ethereum", "base", "bsc", "web3", "uniswap", "swap", "liquidity", "sally"]
10
+ authors = [{ name = "Sally.tools", email = "support@sally.tools" }]
11
+ classifiers = [
12
+ "Development Status :: 4 - Beta",
13
+ "Intended Audience :: Developers",
14
+ "Intended Audience :: Financial and Insurance Industry",
15
+ "License :: OSI Approved :: MIT License",
16
+ "Operating System :: OS Independent",
17
+ "Programming Language :: Python :: 3",
18
+ "Programming Language :: Python :: 3.12",
19
+ "Programming Language :: Python :: 3.13",
20
+ "Topic :: Software Development :: Libraries :: Python Modules",
21
+ "Topic :: Office/Business :: Financial",
22
+ "Typing :: Typed",
23
+ ]
24
+ dependencies = [
25
+ "web3>=7.6,<8",
26
+ "eth-account>=0.13,<0.14",
27
+ "eth-abi>=5,<6",
28
+ "eth-utils>=5,<6",
29
+ "pydantic>=2.9,<3",
30
+ ]
31
+
32
+ [project.urls]
33
+ Homepage = "https://sally.tools"
34
+ Repository = "https://github.com/SallyTools/sally-defi-py-sdk"
35
+ Documentation = "https://github.com/SallyTools/sally-defi-py-sdk/tree/main/docs"
36
+ Issues = "https://github.com/SallyTools/sally-defi-py-sdk/issues"
37
+ Changelog = "https://github.com/SallyTools/sally-defi-py-sdk/blob/main/CHANGELOG.md"
38
+
39
+ [build-system]
40
+ requires = ["uv_build>=0.11.8,<0.12.0"]
41
+ build-backend = "uv_build"
42
+
43
+ [tool.uv.build-backend]
44
+ # Distribution is "sally-defi-py-sdk"; the import module stays "sally_defi".
45
+ module-name = "sally_defi"
46
+ # Ship the deployment JSON (single source of truth) inside the wheel.
47
+ source-include = ["src/sally_defi/data/*.json"]
48
+
49
+ [tool.pytest.ini_options]
50
+ markers = [
51
+ "fork: integration tests that need an anvil mainnet fork (set SALLY_RPC_URL)",
52
+ ]
53
+
54
+ [tool.mypy]
55
+ python_version = "3.12"
56
+ files = ["src/sally_defi"]
57
+ ignore_missing_imports = true
58
+ warn_unused_ignores = true
59
+
60
+ [tool.ruff]
61
+ line-length = 100
62
+ target-version = "py312"
63
+
64
+ [tool.ruff.lint]
65
+ select = ["E", "F", "I", "UP", "B"]
66
+ ignore = ["E501"]
67
+
68
+ [dependency-groups]
69
+ dev = [
70
+ "mypy>=1.11",
71
+ "pytest>=8",
72
+ "ruff>=0.6",
73
+ ]
@@ -0,0 +1,95 @@
1
+ """Sally DeFi SDK — one client for CrossHybrid swaps & liquidity on Base + BSC.
2
+
3
+ Quickstart
4
+ ----------
5
+ >>> from sally_defi import SallyClient
6
+ >>> from sally_defi.constants import Base
7
+ >>> sally = SallyClient("base", "https://mainnet.base.org")
8
+ >>> sally.prices.usd(Base.USDC).as_float # display price
9
+ >>> quote = sally.swap.quote(Base.WETH, Base.USDC, 10**18)
10
+ >>> quote.estimated_amount_out
11
+
12
+ To send transactions, give the client a signer:
13
+ >>> sally = SallyClient("base", RPC, private_key="0x…")
14
+ >>> sally.swap.execute(Base.WETH, Base.USDC, 10**17, slippage_bps=50)
15
+
16
+ Everything reads from the bundled ``deployment.json`` (addresses + ABIs only,
17
+ derived from the contracts' deployment artifact). Addresses/ABIs are never
18
+ hard-coded.
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ from . import constants, deployment
24
+ from .client import SallyClient
25
+ from .errors import (
26
+ SallyConfigError,
27
+ SallyError,
28
+ SallyRevert,
29
+ SallyRouteError,
30
+ SallySafetyError,
31
+ )
32
+ from .permit2 import PERMIT2_ADDRESS, Permit2
33
+ from .safety import RouteCandidate, SafetyConfig, SwapPlan
34
+ from .token import NATIVE, ZERO, Token, TokenAmount
35
+ from .types import (
36
+ ClaimableFees,
37
+ Lock,
38
+ LockKind,
39
+ PoolVersion,
40
+ PriceResult,
41
+ ReferralFeeTokens,
42
+ SwapPath,
43
+ SwapStep,
44
+ TokenInfo,
45
+ V2PoolState,
46
+ V2Position,
47
+ V3PoolState,
48
+ V3Position,
49
+ V4PoolState,
50
+ V4Position,
51
+ WalletBalance,
52
+ )
53
+
54
+ try:
55
+ from importlib.metadata import PackageNotFoundError, version
56
+
57
+ __version__ = version("sally-defi-py-sdk")
58
+ except PackageNotFoundError: # not installed (e.g. running from a source checkout)
59
+ __version__ = "0.0.0+local"
60
+
61
+ __all__ = [
62
+ "SallyClient",
63
+ "SallyError",
64
+ "SallyConfigError",
65
+ "SallyRevert",
66
+ "SallyRouteError",
67
+ "SallySafetyError",
68
+ "SafetyConfig",
69
+ "SwapPlan",
70
+ "RouteCandidate",
71
+ "Permit2",
72
+ "PERMIT2_ADDRESS",
73
+ "Token",
74
+ "TokenAmount",
75
+ "NATIVE",
76
+ "ZERO",
77
+ "constants",
78
+ "deployment",
79
+ "PoolVersion",
80
+ "LockKind",
81
+ "SwapStep",
82
+ "SwapPath",
83
+ "TokenInfo",
84
+ "PriceResult",
85
+ "WalletBalance",
86
+ "V2Position",
87
+ "V3Position",
88
+ "V4Position",
89
+ "V2PoolState",
90
+ "V3PoolState",
91
+ "V4PoolState",
92
+ "Lock",
93
+ "ClaimableFees",
94
+ "ReferralFeeTokens",
95
+ ]