Metadata-Version: 2.4
Name: tribulnation-sdk
Version: 2.2.0
Summary: An abstract, fully-typed, async Python SDK for automated crypto trading. By Tribulnation.
Author-email: Marcel Claramunt <marcel@tribulnation.com>
License-Expression: MIT
Project-URL: Github, https://github.com/tribulnation/sdk.git
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: lazy-loader
Requires-Dist: typing-extensions
Requires-Dist: typed-core>=0.8.1
Provides-Extra: mexc
Requires-Dist: tribulnation-mexc>=2.0.0; extra == "mexc"
Provides-Extra: dydx
Requires-Dist: tribulnation-dydx>=0.7.0; extra == "dydx"
Provides-Extra: hyperliquid
Requires-Dist: tribulnation-hyperliquid>=0.7.0; extra == "hyperliquid"
Provides-Extra: binance
Requires-Dist: tribulnation-binance>=0.3.0; extra == "binance"
Provides-Extra: bitget
Requires-Dist: tribulnation-bitget>=0.7.0; extra == "bitget"
Provides-Extra: bit2me
Requires-Dist: tribulnation-bit2me>=0.5.0; extra == "bit2me"
Provides-Extra: ethereum
Requires-Dist: tribulnation-ethereum>=0.6.0; extra == "ethereum"
Provides-Extra: bybit
Requires-Dist: tribulnation-bybit>=0.2.0; extra == "bybit"
Provides-Extra: coinbase
Requires-Dist: tribulnation-coinbase>=0.2.0; extra == "coinbase"
Provides-Extra: kraken
Requires-Dist: tribulnation-kraken>=0.2.0; extra == "kraken"
Provides-Extra: kucoin
Requires-Dist: tribulnation-kucoin>=0.3.0; extra == "kucoin"
Provides-Extra: deribit
Requires-Dist: tribulnation-deribit>=0.3.0; extra == "deribit"
Dynamic: license-file

# Tribulnation SDK

[![PyPI](https://img.shields.io/pypi/v/tribulnation-sdk.svg)](https://pypi.org/project/tribulnation-sdk/)
[![Python versions](https://img.shields.io/pypi/pyversions/tribulnation-sdk.svg)](https://pypi.org/project/tribulnation-sdk/)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)

> Fully-typed, async Python SDK for crypto trading and data.

`Market`, `Wallet`, `Earn`, and `Report` are abstract interfaces implemented per exchange and chain. Code written against `MarketSDK` runs unchanged on dYdX, Hyperliquid, MEXC, or any other supported venue.

## Installation

```bash
pip install tribulnation-sdk[dydx,hyperliquid,mexc]
```

See the [support matrix](docs/support.md) for details on extras.

## Trading Quick Start

```python
from dotenv import load_dotenv
from tribulnation.sdk import MarketSDK, accounts

load_dotenv()  # load credentials from .env file

sdk = MarketSDK(
  {
    'mexc_account1': accounts.Mexc(
      api_key='$MEXC_API_KEY', api_secret='$MEXC_API_SECRET'
    ),
    # 'dydx', 'hyperliquid', and 'mexc' are available by default, even without listing them here
  }
)
mexc = await sdk.market('mexc_account1:spot:BTCUSDT')
dydx = await sdk.market('dydx:perp:BTC-USD')

async with mexc.trades_stream() as my_trades:
  async for my_trade in my_trades:
    print(f'Hedging {my_trade}')
    await dydx.place_order(
      {
        'type': 'LIMIT',
        'qty': -my_trade.qty,
        'price': my_trade.price,
      }
    )
```

`accounts.<Venue>()` reads credentials from environment variables named after each field (`accounts.Mexc()` reads `$MEXC_API_KEY`/`$MEXC_API_SECRET`) — pass explicit values or other `$VAR` names to override.

## Market IDs & Scoping

`<account_id>:<exchange_id>:<market_id>`, e.g. `mexc_account1:spot:BTCUSDT`. `account_id` is the key you registered in `accounts` — not necessarily the venue's own name — so you can run several accounts on one venue side by side. Equivalent ways to reach a market:

```python
await sdk.depth('mexc_account1:spot:BTCUSDT')

venue = await sdk.venue('mexc_account1')
await venue.depth('spot:BTCUSDT')

exchange = await venue.exchange('spot')
await exchange.depth('BTCUSDT')

market = await exchange.market('BTCUSDT')
await market.depth()
```

Hold a `Market` reference in hot loops; use the scoped one-shot calls otherwise.

## Market Interface

- Public data:
  - `depth() -> Book`
  - `depth_stream() -> AsyncContextManager[AsyncIterable[Book]]`
  - `rules() -> Rules`: tick/step size, fees, min/max, rounding helpers
  - `candles(interval, start, end) -> PaginatedResponse[Candle]`: trade candles opening in `[start, end)`, with timezone-aware bounds and no ordering guarantee; `CANDLE_INTERVALS` says which widths a venue serves
- User data:
  - `query_order(id) -> OrderState | None`
  - `open_orders() -> Sequence[OrderState]`
  - `trades_history(start, end) -> AsyncIterable[Sequence[Trade]]`
  - `trades_stream() -> AsyncContextManager[AsyncIterable[Trade]]`
  - `position() -> Position`
  - `available_notional() -> Decimal`: max. notional you could open now
- Trading:
  - `place_order(order) -> OrderResponse`
  - `place_orders(orders) -> Sequence[OrderResponse]`
  - `cancel_order(id)`
  - `cancel_orders(ids)`
  - `cancel_open_orders()`
- Perpetual markets:
  - `index() -> Decimal`
  - `next_funding() -> FundingRate`
  - `funding_rates(start, end=None) -> AsyncIterable[Sequence[FundingRate]]`: market-wide rate history
  - `funding_payments(start, end) -> AsyncIterable[Sequence[FundingPayment]]`: your own settled cashflows
  - `perp_position() -> PerpPosition`: includes entry price

Full reference: [docs/market/index.md](docs/market/index.md), with per-venue notes for [dYdX](docs/market/impl/dydx.md), [Hyperliquid](docs/market/impl/hyperliquid.md), and [MEXC](docs/market/impl/mexc.md).

Mutating methods also take an optional `settings` dict for venue-specific options, keyed by venue:

```python
await dydx.place_order(
  {
    'type': 'LIMIT',
    'qty': 0.01,
    'price': 60_000,
  },
  settings={'dydx': {'order_flags': 'SHORT_TERM', 'short_term_gtb': 2}},
)
```

## Other SDKs

Same account-mapping shape as `MarketSDK`:

- `WalletSDK`: deposit/withdrawal methods — [docs/wallet.md](docs/wallet.md)
- `EarnSDK`: yield instruments — [docs/earn.md](docs/earn.md)
- `ReportSDK`: balance/position history, with provenance — [docs/report.md](docs/report.md)

Every SDK object is an async context manager: call methods on it directly, or enter it with `async with` to close its connections at a point you choose. Details: [Async Usage](https://github.com/tribulnation/sdk/blob/main/docs/reference/async-usage.md).

## Error Handling

All errors subclass `Error`: `NetworkError`, `ValidationError`, `ApiError` (`BadRequest`, `AuthError`, `RateLimited`), `LogicError`.

## Context, Logging & Retries

SDK calls are plain by default — no logging, no retries. Wrap them in a `Context` to add both:

```python
from tribulnation.sdk import Context, NetworkError, RateLimited

ctx = Context().retried(NetworkError, RateLimited, max_retries=5).logged()
with ctx.use():
  await sdk.place_order(
    'mexc_account1:spot:BTCUSDT', {'type': 'LIMIT', 'qty': 0.01, 'price': 60_000}
  )
```

Retries back off exponentially and only wrap plain async calls, not streams or paginated history. Nested SDK calls each re-apply the active context, so retries can compound across scoping layers. Details: [Context, Logging & Retries](https://github.com/tribulnation/sdk/blob/main/docs/reference/context.md).

## License

[MIT](LICENSE)
