Modern Python SDK for the Sally DeFi CrossHybrid protocol (Base + BSC) — swaps, pricing, liquidity, treasury.
Project description
sally-defi-py-sdk · Python SDK
One client for CrossHybrid swaps & liquidity on Base + BSC.
Wraps the live Sally 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.
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. Notuple[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.
What you get
- One object, every function.
SallyClientexposes 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.executeenumerates 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, setsminOutfrom 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, notpos[7].
Install
uv add sally-defi-py-sdk # or: pip install sally-defi-py-sdk
Install as
sally-defi-py-sdk, import assally_defi(likepip install scikit-learn→import sklearn).
Requires Python ≥ 3.12 and web3 >= 7.6.
Quickstart (read-only)
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
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.
Tune the guard rails:
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
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:
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.
Async · permit · private mempool
# 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.
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:
# 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.
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 and
examples/10_ai_agent_tools.py.
Docs
| Why sally-defi-py-sdk | comparison vs other DeFi SDKs, advantages & trade-offs |
| Getting started | install, connect, first read & swap |
| Swap & safety | route comparison, simulation, all guard rails |
| Liquidity | add/remove/lock/harvest across V2·V3·V4 |
| Pricing | display vs execution price, spot, impact |
| Referrals | earn & claim referral fees |
| Advanced | async client, EIP-2612 permit, Permit2, private mempool, BSC |
| AI agents | typed returns as tool functions |
| API reference | every namespace + method |
Live deployment (v2.0.2, Base = BSC)
| Contract | Address |
|---|---|
| SwapController (proxy) | 0x7777D0e2e2d772b5D750540B3932261574e87777 |
| LiquidityController (proxy) | 0x7777d7fFF155B043CE0A0785dd8c8c42bEbe7777 |
| Treasury | 0x7777D7dC7ea65F33EC126165e03C6B6030887777 |
Development & tests
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
· sally.tools
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sally_defi_py_sdk-0.3.0.tar.gz.
File metadata
- Download URL: sally_defi_py_sdk-0.3.0.tar.gz
- Upload date:
- Size: 56.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
28aee1848c039b715a5a39cd50883571dc0d2e77ebd14a7233fe54c8c2969dc3
|
|
| MD5 |
c4f88d10e5bb4a75ef1624f06074bc87
|
|
| BLAKE2b-256 |
4d85fae085935a09aad12b5c874ff83e94ef26d3745f82465d7afe2ed2c4b4cc
|
File details
Details for the file sally_defi_py_sdk-0.3.0-py3-none-any.whl.
File metadata
- Download URL: sally_defi_py_sdk-0.3.0-py3-none-any.whl
- Upload date:
- Size: 67.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
abb437379b478fc5eb265c33c1eac25fcd7697ff5ea1476850d4f581bc7db344
|
|
| MD5 |
f628265d518e3e18e98f64a755bb3e44
|
|
| BLAKE2b-256 |
a8c93b899a199ddb62c62ae0dd89177368c7cf0560848cca39437cb1f7ad00f1
|