-
Notifications
You must be signed in to change notification settings - Fork 0
Comparison
Same operations, all 9 official Cryptohopper SDKs side-by-side. Use this page as a quick mapping when porting between languages, or when picking which SDK to start with — every SDK exposes the same 18 API domains with the same error taxonomy and retry contract, just in idiomatic shape per language.
The CLI is included at the bottom for reference.
| Language | Snippet |
|---|---|
| Node | const ch = new CryptohopperClient({ apiKey: token, timeoutMs: 30_000, maxRetries: 3 }); |
| Python | with CryptohopperClient(api_key=token, timeout=30, max_retries=3) as ch: |
| Go | ch, _ := cryptohopper.NewClient(token, cryptohopper.WithTimeout(30*time.Second), cryptohopper.WithMaxRetries(3)) |
| Ruby | ch = Cryptohopper::Client.new(api_key: token, timeout: 30, max_retries: 3) |
| Rust | let ch = Client::builder().api_key(token).timeout(Duration::from_secs(30)).max_retries(3).build()?; |
| PHP | $ch = new Client(apiKey: $token, timeout: 30, maxRetries: 3); |
| Dart | final ch = CryptohopperClient(apiKey: token, timeout: const Duration(seconds: 30), maxRetries: 3); |
| Swift | let ch = try Client(apiKey: token, timeout: 30, maxRetries: 3) |
| CLI |
cryptohopper login (token persists in ~/.cryptohopper/config.json) |
All nine accept identical option semantics: timeout is per-request, maxRetries covers HTTP 429 (Retry-After honoured automatically; set 0 to disable).
| Language | Snippet |
|---|---|
| Node | const me = await ch.user.get(); |
| Python | me = ch.user.get() |
| Go | me, err := ch.User.Get(ctx) |
| Ruby | me = ch.user.get |
| Rust | let me = ch.user.get().await?; |
| PHP | $me = $ch->user->get(); |
| Dart | final me = await ch.user.get(); |
| Swift | let me = try await client.user.get() |
| CLI | cryptohopper whoami |
| Language | Snippet |
|---|---|
| Node | const hoppers = await ch.hoppers.list({ exchange: "binance" }); |
| Python | hoppers = ch.hoppers.list(exchange="binance") |
| Go | hoppers, _ := ch.Hoppers.List(ctx, &cryptohopper.HoppersListOptions{Exchange: "binance"}) |
| Ruby | hoppers = ch.hoppers.list(exchange: "binance") |
| Rust | let hoppers = ch.hoppers.list(Some("binance")).await?; |
| PHP | $hoppers = $ch->hoppers->list(exchange: "binance"); |
| Dart | final hoppers = await ch.hoppers.list(exchange: 'binance'); |
| Swift | let hoppers = try await client.hoppers.list(exchange: "binance") |
| CLI | cryptohopper hoppers list --exchange binance |
| Language | Snippet |
|---|---|
| Node | const t = await ch.exchange.ticker({ exchange: "binance", market: "BTC/USDT" }); |
| Python | t = ch.exchange.ticker(exchange="binance", market="BTC/USDT") |
| Go | t, _ := ch.Exchange.Ticker(ctx, "binance", "BTC/USDT") |
| Ruby | t = ch.exchange.ticker(exchange: "binance", market: "BTC/USDT") |
| Rust | let t = ch.exchange.ticker(&json!({"exchange":"binance","market":"BTC/USDT"})).await?; |
| PHP | $t = $ch->exchange->ticker(exchange: "binance", market: "BTC/USDT"); |
| Dart | final t = await ch.exchange.ticker(exchange: 'binance', market: 'BTC/USDT'); |
| Swift | let t = try await client.exchange.ticker(exchange: "binance", market: "BTC/USDT") |
| CLI | cryptohopper ticker binance BTC/USDT |
Although /exchange/ticker is conceptually "public market data," the AWS API Gateway in front of the production API rejects every call without a valid OAuth bearer today (it returns 405 Missing Authentication Token). Practical result: pass a real token to every SDK call. See Authentication.
| Language | Snippet |
|---|---|
| Node | const bt = await ch.backtest.create({ hopper_id: 42, start_date: "2026-01-01", end_date: "2026-04-01" }); |
| Python | bt = ch.backtest.create({"hopper_id": 42, "start_date": "2026-01-01", "end_date": "2026-04-01"}) |
| Go | bt, _ := ch.Backtest.Create(ctx, map[string]any{"hopper_id":42, "start_date":"2026-01-01", "end_date":"2026-04-01"}) |
| Ruby | bt = ch.backtest.create(hopper_id: 42, start_date: "2026-01-01", end_date: "2026-04-01") |
| Rust | let bt = ch.backtest.create(&json!({"hopper_id":42,"start_date":"2026-01-01","end_date":"2026-04-01"})).await?; |
| PHP | $bt = $ch->backtest->create(["hopper_id" => 42, "start_date" => "2026-01-01", "end_date" => "2026-04-01"]); |
| Dart | final bt = await ch.backtest.create({"hopper_id": 42, "start_date": "2026-01-01", "end_date": "2026-04-01"}); |
| Swift | let bt = try await client.backtest.create(["hopper_id": 42, "start_date": "2026-01-01", "end_date": "2026-04-01"]) |
| CLI | cryptohopper backtest new 42 --from 2026-01-01 --to 2026-04-01 |
Same code in every SDK, just with the language's idiomatic catch syntax.
| Language | Snippet |
|---|---|
| Node | try { ... } catch (e) { if (e instanceof CryptohopperError && e.code === "RATE_LIMITED") { ... e.retryAfterMs ... } } |
| Python | try: ... except CryptohopperError as e: if e.code == "RATE_LIMITED": ... e.retry_after_ms ... |
| Go | var ce *cryptohopper.Error; if errors.As(err, &ce) && ce.Code == "RATE_LIMITED" { ... ce.RetryAfter ... } |
| Ruby | rescue Cryptohopper::Error => e; case e.code in "RATE_LIMITED" then ... e.retry_after_ms ... |
| Rust | Err(e) if e.code == ErrorCode::RateLimited => { ... e.retry_after_ms ... } |
| PHP | catch (CryptohopperException $e) { if ($e->getErrorCode() === "RATE_LIMITED") { ... $e->getRetryAfterMs() ... } } |
| Dart | on CryptohopperException catch (e) { if (e.code == "RATE_LIMITED") { ... e.retryAfterMs ... } } |
| Swift | catch let e as CryptohopperError where e.code == .rateLimited { ... e.retryAfterMs ... } |
| CLI | exit code 3 (rate limited); --json exposes error.code + error.retry_after_ms
|
The error code strings (RATE_LIMITED, UNAUTHORIZED, FORBIDDEN, NOT_FOUND, VALIDATION_ERROR, SERVER_ERROR, SERVICE_UNAVAILABLE, DEVICE_UNAUTHORIZED, NETWORK_ERROR, TIMEOUT, UNKNOWN) are stable across every SDK. The Rust enum and the Swift enum carry the same values via as_str() / rawValue.
For proxies, mTLS, request logging, etc.
| Language | Snippet |
|---|---|
| Node |
new CryptohopperClient({ apiKey, fetch: customFetch }) (any function matching globalThis.fetch) |
| Python | CryptohopperClient(api_key=token, http_client=httpx.Client(proxy=..., verify=...)) |
| Go | cryptohopper.NewClient(token, cryptohopper.WithHTTPClient(&http.Client{Transport: customRT})) |
| Ruby | not exposed today — the SDK uses Ruby's stdlib Net::HTTP directly |
| Rust | Client::builder().http_client(reqwest::Client::builder().proxy(...).build()?).build()? |
| PHP | new Client(apiKey: $token, httpClient: new GuzzleClient(['proxy' => ...])) |
| Dart |
CryptohopperClient(apiKey: token, httpClient: customClient) (any http.Client) |
| Swift |
Client(apiKey: token, httpClient: customClient) (any HTTPClient) |
| CLI | not exposed; honours HTTPS_PROXY / NO_PROXY env vars via Node's native fetch |
| Language | Snippet |
|---|---|
| Node | new CryptohopperClient({ apiKey, maxRetries: 0 }) |
| Python | CryptohopperClient(api_key=token, max_retries=0) |
| Go | cryptohopper.NewClient(token, cryptohopper.WithMaxRetries(0)) |
| Ruby | Cryptohopper::Client.new(api_key: token, max_retries: 0) |
| Rust | Client::builder().api_key(token).max_retries(0).build()? |
| PHP | new Client(apiKey: $token, maxRetries: 0) |
| Dart | CryptohopperClient(apiKey: token, maxRetries: 0) |
| Swift | try Client(apiKey: token, maxRetries: 0) |
| CLI | not exposed — the underlying Node SDK retries 429 transparently |
The AWS API Gateway in front of the production API rejects every call without a valid OAuth bearer token (returns 405 Missing Authentication Token). This holds even on routes the API conceptually treats as "public market data" like /exchange/ticker and /market/homepage. Practical result: every SDK call (and every CLI subcommand, including cryptohopper ticker) requires a real token. See Authentication for how to issue one.
- Already in a Node.js codebase? → Node.
- Server-side Python (FastAPI, Django, Airflow)? → Python.
- High-performance backend, want tight binary size, deploying to cloud functions? → Go or Rust.
- Web-app side (Rails, Sinatra)? → Ruby.
- WordPress / Laravel / Symfony / Magento integration? → PHP.
- Mobile (Flutter cross-platform)? → Dart. (The legacy
cryptohopper-android-sdktargets Android-only via Kotlin and predates this suite.) - Native iOS / macOS / Linux server-side Swift? → Swift. (The legacy
cryptohopper-ios-sdktargets iOS-only via CocoaPods and predates this suite.) - One-off scripts, CI automation, terminal use? → CLI.
All nine are MIT-licensed, share the same error taxonomy and retry semantics, and cover all 18 public API domains.
- Recipes — interactive day-to-day CLI patterns
- Scripting — CI/automation reference, jq pipelines, exit codes
- Cross-SDK overview (pending in PR #3)
Pages
SDK wikis
Resources