Metadata-Version: 2.4
Name: cryptohopper
Version: 0.4.0a1
Summary: Official Python SDK for the Cryptohopper API
Project-URL: Homepage, https://www.cryptohopper.com
Project-URL: Documentation, https://api.cryptohopper.com/v1/docs
Project-URL: Repository, https://github.com/cryptohopper/cryptohopper-python-sdk
Project-URL: Issues, https://github.com/cryptohopper/cryptohopper-python-sdk/issues
Project-URL: Changelog, https://github.com/cryptohopper/cryptohopper-python-sdk/blob/main/CHANGELOG.md
Author-email: Cryptohopper <info@cryptohopper.com>
License: MIT License
        
        Copyright (c) 2026 Cryptohopper
        
        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.
License-File: LICENSE
Keywords: api-client,bot,crypto,cryptohopper,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.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business :: Financial :: Investment
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: httpx<0.29,>=0.27
Provides-Extra: dev
Requires-Dist: mypy>=1.11; extra == 'dev'
Requires-Dist: pytest-httpx>=0.30; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Description-Content-Type: text/markdown

# cryptohopper

Official Python SDK for the [Cryptohopper](https://www.cryptohopper.com) API.

> **Status: 0.1.0a1** — early access. Covers 6 core domains: `user`, `hoppers`, `exchange`, `strategy`, `backtest`, `market`.

## Install

```bash
pip install cryptohopper
```

Requires Python 3.10+.

## Quickstart

```python
import os
from cryptohopper import CryptohopperClient

with CryptohopperClient(api_key=os.environ["CRYPTOHOPPER_TOKEN"]) as ch:
    me = ch.user.get()
    print(me["email"])

    ticker = ch.exchange.ticker(exchange="binance", market="BTC/USDT")
    print(ticker["last"])
```

## Authentication

Cryptohopper uses OAuth2 bearer tokens. To get one:

1. Sign in at [cryptohopper.com](https://www.cryptohopper.com) and open the developer dashboard.
2. Create an OAuth application — you'll receive a `client_id` and `client_secret`.
3. Drive the OAuth consent flow (`/oauth-consent?app_id=<client_id>&redirect_uri=<your_uri>&state=<csrf>`) to receive a 40-character bearer token scoped to the permissions you requested.

Pass the token as `api_key`. Optionally pass your OAuth `client_id` as `app_key` — it's sent as the `x-api-app-key` header.

```python
ch = CryptohopperClient(
    api_key=os.environ["CRYPTOHOPPER_TOKEN"],
    app_key=os.environ.get("CRYPTOHOPPER_CLIENT_ID"),  # optional
)
```

## Resources

```python
# User
ch.user.get()

# Hoppers
ch.hoppers.list(exchange="binance")
ch.hoppers.get(42)
ch.hoppers.create({"name": "My Bot", "exchange": "binance"})
ch.hoppers.update(42, {"name": "Renamed"})
ch.hoppers.delete(42)
ch.hoppers.positions(42)
ch.hoppers.orders(42)
ch.hoppers.buy({"hopper_id": 42, "market": "BTC/USDT", "amount": 0.001})
ch.hoppers.sell({"hopper_id": 42, "market": "BTC/USDT", "amount": 0.001})
ch.hoppers.config_get(42)
ch.hoppers.config_update(42, {"strategy_id": 99})
ch.hoppers.panic(42)

# Exchange (public — no auth required)
ch.exchange.ticker(exchange="binance", market="BTC/USDT")
ch.exchange.candles(exchange="binance", market="BTC/USDT", timeframe="1h")
ch.exchange.orderbook(exchange="binance", market="BTC/USDT")
ch.exchange.markets("binance")
ch.exchange.exchanges()

# Strategy
ch.strategy.list()
ch.strategy.get(5)
ch.strategy.create({"name": "My Strategy"})
ch.strategy.update(5, {"name": "Renamed"})
ch.strategy.delete(5)

# Backtest
ch.backtest.create({"hopper_id": 42, "from_date": "2026-01-01", "to_date": "2026-03-01"})
ch.backtest.get(1)
ch.backtest.list()
ch.backtest.cancel(1)
ch.backtest.limits()

# Marketplace (public — no auth required)
ch.market.signals(type="buy")
ch.market.signal(99)
ch.market.items(type="strategy")
ch.market.homepage()
```

## Client options

| Option | Default | Description |
|---|---|---|
| `api_key` | — (required) | OAuth2 bearer token |
| `app_key` | — | Optional OAuth `client_id`, sent as `x-api-app-key` |
| `base_url` | `https://api.cryptohopper.com/v1` | Override for staging/dev |
| `timeout` | `30.0` | Per-request timeout in seconds |
| `max_retries` | `3` | Retries on HTTP 429 (respects `Retry-After`). Set to `0` to disable. |
| `user_agent` | — | Appended after `cryptohopper-sdk-python/<version>` |
| `http_client` | — | Inject a custom `httpx.Client` |

## Errors

Every non-2xx response becomes a `CryptohopperError`:

```python
from cryptohopper import CryptohopperClient, CryptohopperError

try:
    ch.user.get()
except CryptohopperError as err:
    print(err.code)            # "UNAUTHORIZED" | "FORBIDDEN" | "RATE_LIMITED" | ...
    print(err.status)          # HTTP status
    print(err.server_code)     # Numeric unique error code from the server, if any
    print(err.ip_address)      # Client IP the server saw (IP-whitelist debug help)
    print(err.retry_after_ms)  # Milliseconds to wait on 429 (if server sent Retry-After)
```

Unknown server-side codes pass through as-is on `.code`.

## Rate limiting

The server enforces three buckets (`normal` 30/min, `order` 8/8s, `backtest` 1/2s). On HTTP 429 the SDK retries with exponential backoff up to `max_retries` (default 3), respecting `Retry-After`. Pass `max_retries=0` to disable auto-retry.

## Development

```bash
pip install -e ".[dev]"
ruff check .
mypy src
pytest -q
```

## Release

Push a `py-v<version>` git tag. The release workflow runs ruff + mypy + pytest, verifies tag-version parity, builds sdist + wheel, and publishes via **PyPI Trusted Publishing (OIDC)** — no long-lived API token needed. Configure the publisher at [pypi.org/manage/account/publishing](https://pypi.org/manage/account/publishing/) before the first release.

## License

MIT — see [LICENSE](./LICENSE).
