Metadata-Version: 2.5
Name: epsilon-exchange
Version: 0.2.0
Summary: Python SDK for Epsilon — non-custodial limit/stop/DCA orders on Robinhood Chain via the Epsilon /v1 API
Project-URL: Homepage, https://developers.epsilon.exchange
Project-URL: Documentation, https://developers.epsilon.exchange
Project-URL: Repository, https://github.com/alienbase-xyz/EpsilonRobinhood
Author-email: Epsilon <team@epsilon.exchange>
License-Expression: MIT
Keywords: dex,eip712,epsilon,limit-order,robinhood-chain,trading
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Office/Business :: Financial
Requires-Python: >=3.9
Requires-Dist: eth-account<0.14,>=0.11
Requires-Dist: requests>=2.28
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == 'dev'
Description-Content-Type: text/markdown

# epsilon-exchange

Python SDK for [Epsilon](https://www.epsilon.exchange) — non-custodial limit,
stop-loss, and DCA orders on Robinhood Chain, via the Epsilon `/v1` API.

Your private key never leaves your machine: orders are built and EIP-712
signed locally, and the API only ever sees the signed payload. The signing
implementation is pinned byte-for-byte against the TypeScript SDK and the Go
verifier by a shared golden fixture.

## Install

```bash
pip install epsilon-exchange
```

Get an API key at [developers.epsilon.exchange/dashboard](https://developers.epsilon.exchange/dashboard).

## Place a limit order

```python
from epsilon_exchange import (
    EpsilonClient, build_and_sign_order, parse_units, calculate_trigger_price,
)

client = EpsilonClient(api_key="eps_...")
private_key = "0x..."   # the wallet that holds the tokens
wallet = "0x..."        # its address

# 1. Find tokens (symbol → address + decimals)
eth = client.search_tokens("WETH")["tokens"][0]
usd = client.search_tokens("USDG")["tokens"][0]

# 2. Route — request it with the order_type you will submit; its feeLegs carry
#    that fee cell and are exact-matched on submit. Pass them through unmodified.
amount_in = parse_units("0.5", eth["decimals"])
route = client.order_route(eth["address"], usd["address"], amount_in,
                           slippage_ppm=10_000, wallet=wallet, order_type="limit")

# 3. Build + sign locally (sell 0.5 WETH at 3000 USDG/WETH or better)
signed = build_and_sign_order(
    private_key,
    token_in=eth["address"],
    token_out=usd["address"],
    amount_in=amount_in,
    trigger_price=calculate_trigger_price("3000", usd["decimals"]),
    token_in_decimals=eth["decimals"],
    fee_legs=route.get("feeLegs"),
    kind="limit",
)

# 4. Submit
res = client.submit_order(signed, "limit")
print(res["orderHash"])
```

The router must be approved to spend `token_in` first (a plain ERC-20
`approve` to the router — address in `epsilon_exchange.ROUTER_ADDRESS`).

## Modules

- `EpsilonClient` — `/v1` API: `search_tokens`, `quote`, `order_route`,
  `submit_order`, `get_order`, `list_orders`, `cancel_order`
- `build_and_sign_order` / `sign_cancel` — local EIP-712 signing
  (`eth-account`)
- `parse_units` / `format_units` / `calculate_trigger_price` — decimal helpers
- `chain` — chain id, router address, EIP-712 domain and types

## Also available

- TypeScript: [`@epsilon-exchange/sdk`](https://www.npmjs.com/package/@epsilon-exchange/sdk)
- AI agents (Claude/Cursor): [`@epsilon-exchange/mcp`](https://www.npmjs.com/package/@epsilon-exchange/mcp)
- Docs: [developers.epsilon.exchange](https://developers.epsilon.exchange)
