Metadata-Version: 2.4
Name: tribulnation-sdk
Version: 1.3.0
Summary: An abstract, fully-typed, async Python SDK for automated crypto trading. By Tribulnation.
Author-email: Marcel Claramunt <marcel@tribulnation.com>
License: MIT License
        
        Copyright (c) 2025 Tribulnation
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Github, https://github.com/tribulnation/sdk.git
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: lazy-loader
Requires-Dist: typing-extensions
Provides-Extra: mexc
Requires-Dist: tribulnation-mexc; extra == "mexc"
Provides-Extra: dydx
Requires-Dist: tribulnation-dydx; extra == "dydx"
Provides-Extra: hyperliquid
Requires-Dist: tribulnation-hyperliquid; extra == "hyperliquid"
Provides-Extra: binance
Requires-Dist: tribulnation-binance; extra == "binance"
Provides-Extra: bitget
Requires-Dist: tribulnation-bitget; extra == "bitget"
Provides-Extra: bit2me
Requires-Dist: tribulnation-bit2me; extra == "bit2me"
Provides-Extra: ethereum
Requires-Dist: tribulnation-ethereum; extra == "ethereum"
Provides-Extra: kraken
Requires-Dist: tribulnation-kraken; extra == "kraken"
Provides-Extra: bybit
Requires-Dist: tribulnation-bybit; extra == "bybit"
Provides-Extra: bingx
Requires-Dist: tribulnation-bingx; extra == "bingx"
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 for my_trade in mexc.trades_stream():
  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() -> Stream[Book]`
  - `rules() -> Rules`: tick/step size, fees, min/max, rounding helpers
- User data:
  - `query_order(id) -> OrderState | None`
  - `open_orders() -> Sequence[OrderState]`
  - `trades_history(start, end) -> AsyncIterable[Sequence[Trade]]`
  - `trades_stream() -> Stream[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_history(start, end) -> AsyncIterable[Sequence[FundingRate]]`
  - `funding_payments(start, end) -> AsyncIterable[Sequence[FundingPayment]]`
  - `perp_position() -> PerpPosition`: includes entry price

Full reference: [docs/market.md](docs/market.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)

## 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: [docs/context.md](docs/context.md).

## License

[MIT](LICENSE)
