Metadata-Version: 2.4
Name: sally-defi-py-sdk
Version: 0.3.0
Summary: Modern Python SDK for the Sally DeFi CrossHybrid protocol (Base + BSC) — swaps, pricing, liquidity, treasury.
Keywords: defi,ethereum,base,bsc,web3,uniswap,swap,liquidity,sally
Author: Sally.tools
Author-email: Sally.tools <support@sally.tools>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Office/Business :: Financial
Classifier: Typing :: Typed
Requires-Dist: web3>=7.6,<8
Requires-Dist: eth-account>=0.13,<0.14
Requires-Dist: eth-abi>=5,<6
Requires-Dist: eth-utils>=5,<6
Requires-Dist: pydantic>=2.9,<3
Requires-Python: >=3.12
Project-URL: Homepage, https://sally.tools
Project-URL: Repository, https://github.com/SallyTools/sally-defi-py-sdk
Project-URL: Documentation, https://github.com/SallyTools/sally-defi-py-sdk/tree/main/docs
Project-URL: Issues, https://github.com/SallyTools/sally-defi-py-sdk/issues
Project-URL: Changelog, https://github.com/SallyTools/sally-defi-py-sdk/blob/main/CHANGELOG.md
Description-Content-Type: text/markdown

<div align="center">

<img src="assets/header.svg" alt="sally-defi-py-sdk · Python SDK" width="100%">

# sally-defi-py-sdk · Python SDK

**One client for CrossHybrid swaps & liquidity on Base + BSC.**

Wraps the live [Sally](https://sally.tools) v2.0.2 protocol — best-route hybrid
swaps, V2·V3·V4·Slipstream liquidity, 1e18 USD pricing, honeypot screening, locks,
referral fees and the multi-owner treasury — behind one typed, beginner-friendly
and AI-agent-ready API.

[Website](https://sally.tools) · [Docs](docs/) · [Examples](examples/) · `support@sally.tools`

</div>

---

## Why sally-defi-py-sdk

Most Python DeFi code is raw `web3.py`: untyped tuples, hand-rolled approvals, a
quote you *hope* matches execution, and zero protection against honeypots or
sandwiches. sally-defi-py-sdk collapses all of that into **one safe call**.

`swap.execute` does the work a careful integrator would do by hand — approve →
enumerate routes → **simulate every route on-chain** → screen the output token for
honeypot/tax → set `minOut` from the *simulated* output → send → **assert you
actually received it**. That whole pipeline is the default, not an opt-in.

* 🛡️ **Safety in the hot path.** Simulate-before-execute + post-trade balance-delta
  assertion — not just in your test suite. (The balance-delta check is something
  even mature SDKs don't ship.)
* 🧱 **Typed end-to-end.** `pos.liquidity`, `plan.is_safe`, `quote.estimated_amount_out`
  — dataclasses, autocomplete, JSON-able. No `tuple[7]`.
* 🤖 **AI-agent-ready by construction.** Every return serializes cleanly, so wiring
  Sally into LLM tools is mechanical.
* ⚡ **Async + MEV-protection + permit** are constructor/keyword arguments, not projects.
* 🪶 **Light deps** (web3, eth-account, eth-abi, eth-utils, pydantic), Python ≥3.12, `py.typed`.

Honest about scope: Sally routes within **its own protocol** on **Base + BSC** — it
is not a 100-source aggregator. Full, cited comparison (vorteile *and* nachteile)
vs raw web3.py / uniswap-python / eth_defi / Ape / aggregator SDKs:
**[docs/comparison.md](docs/comparison.md)**.

## What you get

* **One object, every function.** `SallyClient` exposes the whole protocol through
  feature namespaces (`prices`, `swap`, `wallet`, `liquidity`, `fees`, `treasury`,
  `admin`). Reads need only an RPC; writes need a signer.
* **Safe by default.** `swap.execute` enumerates routes, **integrity-checks** each so
  funds can never enter a wrong pool, **simulates** every candidate on-chain, picks
  the best realized output, runs a **honeypot/tax probe** on the output token, sets
  `minOut` from the simulation, then **asserts the received balance actually grew**.
* **Single source of truth.** All addresses + ABIs come from the bundled
  `deployment.json` (addresses + ABIs only). Nothing hard-coded; drop in a new
  deployment and the SDK follows.
* **Proxy-fallback aware.** v2.0.2 serves Lens views through the swap proxy and
  Sidecar views through the liq proxy — the SDK wires this for you.
* **Typed returns.** Every struct is a dataclass (`SwapPath`, `V3Position`, `Lock`,
  `SwapPlan`, …) — `pos.liquidity`, not `pos[7]`.

## Install

```bash
uv add sally-defi-py-sdk          # or: pip install sally-defi-py-sdk
```

> Install as **`sally-defi-py-sdk`**, import as **`sally_defi`**
> (like `pip install scikit-learn` → `import sklearn`).

Requires Python ≥ 3.12 and `web3 >= 7.6`.

## Quickstart (read-only)

```python
from sally_defi import SallyClient
from sally_defi.constants import Base

sally = SallyClient("base", "https://mainnet.base.org")

sally.prices.usd(Base.USDC).as_float            # 1.0  (display / spot-mid)
sally.prices.usd_impact(Base.WETH).as_float     # 1703.19  (execution-aware)

quote = sally.swap.quote(Base.WETH, Base.USDC, 10**18)
quote.estimated_amount_out / 1e6                # 1703.45 USDC
```

## Swapping — safe by default

```python
sally = SallyClient("base", RPC, private_key="0x…")   # or SALLY_PRIVATE_KEY env

# Inspect first: compares every route, simulates each, screens the output token.
plan = sally.swap.plan(Base.WETH, Base.USDC, 10**18)
plan.summary()             # 'SwapPlan(… out~1702924727 sim=1702924727 min=1694410103 impact=13bps steps=2 SAFE)'
plan.is_safe               # False if honeypot / excessive tax / >15% impact / bad route
plan.candidates            # every route considered, with simulated output

# Execute: same vetting, then send + balance-delta assertion.
receipt = sally.swap.execute(Base.WETH, Base.USDC, 10**18, slippage_bps=50)

# Native ETH in — pass the NATIVE sentinel; value is attached for you.
from sally_defi.token import NATIVE
sally.swap.execute(NATIVE, Base.USDC, 10**17, slippage_bps=50)
```

What `execute` does, in order: approve (exact amount) → enumerate routes →
integrity-check → simulate each on-chain → pick best realized output →
honeypot/tax preflight → `minOut` from the simulation → send →
**assert received ≥ minOut**. See [`docs/safety.md`](docs/safety.md).

Tune the guard rails:

```python
from sally_defi import SafetyConfig
sally = SallyClient("base", RPC, private_key="0x…",
                    safety=SafetyConfig(slippage_bps=30, tax_block_bps=3000,
                                        price_impact_block_bps=1000))
```

## Liquidity

```python
sally.liquidity.add_v2(dex_id=4, token_a=Base.WETH, token_b=Base.USDC,
                       amount_a=10**15, amount_b=2_000_000, lock_days=0)

sally.liquidity.positions_v3(wallet, 0, 10)     # list[V3Position]
sally.liquidity.locks(wallet)                   # list[Lock]
sally.liquidity.claimable_fees(npm, token_id)   # ClaimableFees
# add_v3 / add_v4 / add_slipstream, increase/decrease, remove_v2,
# lock/unlock, claim_fees_v3/v4(+_locked), mass_claim_fees, harvest_op
```

## Referral system 💸

Every swap and liquidity action takes a `referral` address. Pass yours and the
protocol accrues referral fees to it; read and claim them anytime:

```python
sally.swap.execute(Base.WETH, Base.USDC, 10**18, referral="0xYourRef")

sally.fees.total_referral_owed("0xYourRef")     # total owed across tokens
sally.fees.referral_tokens("0xYourRef")         # per-token breakdown (paged)
sally.fees.claim_referral([Base.USDC, Base.WETH])   # claim selected tokens
```

See [`docs/referrals.md`](docs/referrals.md).

## Async · permit · private mempool

```python
# Async (concurrent quoting + simulation)
from sally_defi.aio import AsyncSallyClient
sally = AsyncSallyClient("base", RPC, private_key="0x…")
await sally.swap.execute(Base.WETH, Base.USDC, 10**18, slippage_bps=50)

# EIP-2612 permit instead of approve
sally.swap.execute(Base.USDC, Base.WETH, 10**8, approval="permit")

# Private mempool (MEV protection)
from sally_defi.constants import PrivateRelays
SallyClient("base", RPC, private_key="0x…", private_rpc_url=PrivateRelays.FLASHBOTS_FAST)
```

Full guide: [`docs/advanced.md`](docs/advanced.md).

## Sign with your own wallet 🔑

Give a `private_key`, a `mnemonic`, or **no key at all** — build a vetted, simulated,
ABI-decoded *unsigned* transaction and sign it with your own web3:

```python
# mnemonic seed phrase
sally = SallyClient("base", RPC, mnemonic="word1 … word12", account_index=0)

# external signing — the SDK never holds your key
sally = SallyClient("base", RPC, address="0xYourWallet")   # knows sender, no key
build = sally.swap.execute(Base.WETH, Base.USDC, 10**18, build_only=True)
build.plan.summary()       # what happens to your wallet: out, min, impact, safe?
build.needs_approval       # sign build.approve_tx first if True
build.swap_tx              # unsigned tx → sign with your own account, then broadcast

# preview ANY call: decoded function + args + simulated result + revert reason
sally.preview(some_contract_fn).summary()
```

See [`docs/signing.md`](docs/signing.md).

## Namespaces

| Namespace | What it covers |
|---|---|
| `client.prices` | `usd` (display), `usd_impact` (exec), `spot`, `weth`, `usd_liquidity`, `token_info` |
| `client.swap` | `quote(_v2/v3/v4/deep)`, `candidates`, `plan`, `simulate_route`, `execute` (+ `build_only`), `token_info` |
| `client.wallet` | `balances`, `balances_raw`, `total_usd` |
| `client.liquidity` | add / increase / decrease / remove / lock / claim / harvest, positions, pool state, dex registry |
| `client.fees` | referral + batch fee reads & claims, `swap_fee` |

Raw contracts are always reachable: `client.swap_contract`, `…liquidity_contract`,
`…lens_contract`, `…sidecar_contract`.

## AI agents

Every call returns a JSON-able dataclass with a clear docstring — wrapping Sally as
LLM tools is trivial. See [`docs/ai-agents.md`](docs/ai-agents.md) and
[`examples/10_ai_agent_tools.py`](examples/10_ai_agent_tools.py).

## Docs

| | |
|---|---|
| [Why sally-defi-py-sdk](docs/comparison.md) | comparison vs other DeFi SDKs, advantages & trade-offs |
| [Getting started](docs/getting-started.md) | install, connect, first read & swap |
| [Swap & safety](docs/safety.md) | route comparison, simulation, all guard rails |
| [Liquidity](docs/liquidity.md) | add/remove/lock/harvest across V2·V3·V4 |
| [Pricing](docs/pricing.md) | display vs execution price, spot, impact |
| [Referrals](docs/referrals.md) | earn & claim referral fees |
| [Advanced](docs/advanced.md) | async client, EIP-2612 permit, Permit2, private mempool, BSC |
| [AI agents](docs/ai-agents.md) | typed returns as tool functions |
| [API reference](docs/api-reference.md) | every namespace + method |

## Live deployment (v2.0.2, Base = BSC)

| Contract | Address |
|---|---|
| SwapController (proxy) | `0x7777D0e2e2d772b5D750540B3932261574e87777` |
| LiquidityController (proxy) | `0x7777d7fFF155B043CE0A0785dd8c8c42bEbe7777` |
| Treasury | `0x7777D7dC7ea65F33EC126165e03C6B6030887777` |

## Development & tests

```bash
uv sync
uv run pytest -m "not fork"        # offline unit tests
anvil --fork-url $BASE_RPC --port 8547 --chain-id 8453 &
SALLY_RPC_URL=http://127.0.0.1:8547 uv run pytest   # + fork smoke tests
```

## Support

Questions, integrations, partnerships → [`support@sally.tools`](mailto:support@sally.tools)
· [sally.tools](https://sally.tools)

## License

MIT
