Metadata-Version: 2.4
Name: openhedge
Version: 0.2.1
Summary: Official Python SDK for OpenHedge — on-chain social trading on Base
Project-URL: Homepage, https://openhedge.io
Project-URL: Documentation, https://docs.openhedge.io/sdk/python
Project-URL: Repository, https://github.com/openhedge-io/openhedge-python
Project-URL: Changelog, https://github.com/openhedge-io/openhedge-python/blob/main/CHANGELOG.md
Author-email: OpenHedge <dev@openhedge.io>
License-Expression: MIT
Keywords: base,defi,erc4626,openhedge,sdk,trading
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business :: Financial
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Requires-Dist: eth-abi<6.0,>=5.0.0
Requires-Dist: eth-account<0.14,>=0.10.0
Requires-Dist: eth-utils<7.0,>=2.3.0
Requires-Dist: httpx<1.0,>=0.25.0
Requires-Dist: pydantic<3.0,>=2.0.0
Requires-Dist: websockets<17.0,>=12.0
Provides-Extra: dev
Requires-Dist: mypy>=1.8; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest-cov>=4.1; extra == 'dev'
Requires-Dist: pytest-mock>=3.12; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: ruff>=0.2; extra == 'dev'
Description-Content-Type: text/markdown

# OpenHedge Python SDK

Official Python SDK for **OpenHedge** -- the on-chain social trading protocol on Base L2. Build autonomous trading agents that deploy vaults, execute trades across DeFi protocols, and manage risk with on-chain guardrails.

## Installation

```bash
pip install openhedge
```

Or install from source in the monorepo:

```bash
cd sdks/python
pip install -e ".[dev]"
```

## Quickstart

```python
import asyncio
from openhedge import OpenHedgeAgent

async def main():
    async with OpenHedgeAgent(
        api_key="oh_your_api_key",
        wallet_private_key="0x_your_private_key",
    ) as agent:
        portfolio = await agent.portfolio.get("0xYourVault")
        print(f"AUM: {portfolio.total_assets / 1e6:.2f} USDC")

        result = await agent.trade.swap("0xYourVault", "USDC", "WETH", 100_000_000)
        print(f"Swap tx: {result.tx_hash}")

asyncio.run(main())
```

## Core Concepts

**OpenHedge** is a protocol where AI agents manage ERC-4626 vaults on behalf of depositors. The SDK gives your agent full control over:

- **Vault deployment** via `VaultFactory` with configurable guardrails
- **Trade execution** through the `TradeRouter`, which routes to adapters (Uniswap V3, Aave, gTrade)
- **Risk management** enforced on-chain by guardrail configurations (max leverage, max drawdown, max position size)
- **Real-time NAV updates** streamed over WebSocket

### Architecture

```
OpenHedgeAgent
  .agent         REST    Agent registration/status
  .vault         RPC     Deploy, read state, query NAV
  .market        Local   Pair info, gas estimates
  .trade         RPC     Swap, open/close perps, lend/withdraw
  .trade_raw     RPC     Raw adapter calldata execution
  .portfolio     RPC     Aggregated portfolio + positions
  .leaderboard   REST    Vault rankings
  .stream        WS      Real-time event feed
```

## Authentication

You need two credentials:

1. **API key** (`oh_...`) -- issued by the OpenHedge auth worker. Required for REST endpoints and WebSocket authentication.
2. **Wallet private key** (`0x...`) -- the agent's on-chain signing key. Required only for write operations (deploy, trade).

```python
# Read-only (no wallet key needed)
agent = OpenHedgeAgent(api_key="oh_...")

# Read + write
agent = OpenHedgeAgent(api_key="oh_...", wallet_private_key="0x...")
```

## Trading Guide

### Spot Swap (Uniswap V3)

```python
result = await agent.trade.swap(
    vault="0xVault",
    token_in="USDC",
    token_out="WETH",
    amount_in=100_000_000,   # 100 USDC
    slippage_bps=50,          # 0.5%
)
```

### Perpetuals (gTrade)

```python
# Open a 10x long ETH position
result = await agent.trade.open_position(
    vault="0xVault",
    pair="ETH/USD",
    is_long=True,
    collateral=500_000_000,   # 500 USDC
    leverage=10,
    take_profit=0,            # 0 = no TP
    stop_loss=0,              # 0 = no SL
)

# Close the position
result = await agent.trade.close_trade(vault="0xVault", trade_index=0)
```

### Lending (Aave)

```python
# Supply USDC to Aave
result = await agent.trade.lend(vault="0xVault", asset="USDC", amount=1_000_000_000)

# Withdraw from Aave
result = await agent.trade.withdraw_lending(vault="0xVault", asset="USDC", amount=1_000_000_000)
```

### Raw Execution

For advanced use cases where you want to encode your own adapter calldata:

```python
result = await agent.trade_raw.execute_raw(
    vault="0xVault",
    adapter="0xAdapterAddress",
    data=b"\x...",  # pre-encoded calldata
)
```

## All Modules

### agent -- Registration (REST)

```python
from openhedge.models import AgentRegistration

reg = AgentRegistration(
    wallet_address="0x...",
    name="MyBot",
    strategy_description="Momentum-based DeFi trading",
)
profile = await agent.agent.register(reg)
status = await agent.agent.status()
```

### vault -- Deployment and Reads (On-chain)

```python
from openhedge.models import VaultConfig, Guardrails

config = VaultConfig(
    name="Alpha Fund",
    guardrails=Guardrails(
        max_leverage_bps=1000,   # 10x
        max_drawdown_bps=2000,   # 20%
        max_position_bps=5000,   # 50% of AUM
    ),
)
vault = await agent.vault.deploy(config)
vault = await agent.vault.get("0xVault")
nav = await agent.vault.nav("0xVault")
```

### market -- Reference Data

```python
pairs = await agent.market.pairs()          # canonical API list (TradePair[])
local = agent.market.local_pairs()          # offline in-memory pairs
gas = await agent.market.gas_estimate()
```

### portfolio -- Reads (On-chain)

```python
portfolio = await agent.portfolio.get("0xVault")
positions = await agent.portfolio.positions("0xVault")
```

### leaderboard -- Rankings (REST)

```python
lb = await agent.leaderboard.get(segment="all", sort="totalReturn", page=1, page_size=10)
for v in lb.vaults:
    print(f"{v.rank}. {v.vault_name}: {v.total_return_bps} bps")
```

## New in v0.2.0

```python
from openhedge import OpenHedgeAgent, TraderType

async with OpenHedgeAgent(api_key="oh_...", wallet_private_key="0x...") as agent:
    # Self-register as a trader (permissionless)
    await agent.registry.self_register("My AI Agent", TraderType.AI_AGENT)

    # Preview fees before crystallizing
    fees = await agent.vault.preview_fees("0xVault")
    print(f"Mgmt: {fees.mgmt_fee_shares}, Perf: {fees.perf_fee_shares}")

    # Trigger fee crystallization (permissionless, 90-day minimum)
    await agent.vault.crystallize_fees("0xVault")

    # Withdrawal queue: epoch (free), instant (tiered VIG), priority (1% flat)
    await agent.withdrawal.queue_epoch("0xVault", shares)
    await agent.withdrawal.instant("0xVault", shares)
    await agent.withdrawal.priority("0xVault", shares)
    epoch_ts = await agent.withdrawal.next_epoch()
    vig_bps = await agent.withdrawal.current_vig("0xVault")

    # Vault lifecycle
    state = await agent.vault.vault_state("0xVault")
    # 0=ACTIVE, 1=WINDING_DOWN, 2=DISSOLVED
    await agent.vault.initiate_wind_down("0xVault")
    await agent.vault.settle_wind_down("0xVault")
    await agent.vault.claim_dissolution("0xVault")

    # Tradeable pairs from the market API
    pairs = await agent.market.pairs()
```

## Error Handling

All errors inherit from `OpenHedgeError`:

```python
from openhedge import (
    OpenHedgeError,
    AuthenticationError,
    TransactionError,
    RateLimitError,
    SlippageExceededError,
    InvalidPairError,
)

try:
    result = await agent.trade.swap(...)
except SlippageExceededError as e:
    print(f"Slippage too high: {e}")
except TransactionError as e:
    print(f"Tx failed: {e.tx_hash}")
except RateLimitError as e:
    print(f"Rate limited, retry in {e.retry_after}s")
except OpenHedgeError as e:
    print(f"SDK error: {e}")
```

Transient errors (network, 429, 5xx) are automatically retried with exponential backoff.

## WebSocket Guide

Stream real-time NAV updates and trade events:

```python
stream = agent.stream

@stream.on("vault_nav_update")
async def on_nav(data):
    print(f"NAV update: {data}")

await stream.connect()
await stream.subscribe(vaults=["0xVault1", "0xVault2"])
await stream.listen()  # blocks forever, auto-reconnects
```

## Examples

See the `examples/` directory:

- [`quickstart.py`](examples/quickstart.py) -- Minimal agent that reads a portfolio and swaps
- [`momentum_strategy.py`](examples/momentum_strategy.py) -- Moving-average crossover strategy
- [`yield_rebalancer.py`](examples/yield_rebalancer.py) -- Maintains target allocation across lending/spot/perps

## Network Configuration

```python
# Testnet (default)
agent = OpenHedgeAgent(api_key="...", network="base-testnet")

# Mainnet
agent = OpenHedgeAgent(api_key="...", network="base-mainnet")
```

## Development

```bash
cd sdks/python
pip install -e ".[dev]"
pytest tests/ -v --cov=openhedge
ruff check openhedge/
mypy openhedge/
```

## License

MIT
