Skip to content

cryptohopper/cryptohopper-swift-sdk

Repository files navigation

cryptohopper-swift-sdk

SwiftPM Swift 5.9+ Platforms CI License: MIT

Official Swift SDK for the Cryptohopper API.

Status: 0.1.0-alpha.1 — full coverage of all 18 public API domains: user, hoppers, exchange, strategy, backtest, market, signals, arbitrage, marketmaker, template, ai, platform, chart, subscription, social, tournaments, webhooks, app.

Deeper docs: Getting Started · Authentication · Error Handling · Rate Limits

Install

Swift Package Manager

In Package.swift:

dependencies: [
    .package(url: "https://github.com/cryptohopper/cryptohopper-swift-sdk.git", from: "0.1.0-alpha.1"),
],
targets: [
    .target(name: "MyApp", dependencies: [.product(name: "Cryptohopper", package: "cryptohopper-swift-sdk")]),
]

Xcode

File → Add Package Dependencies → paste https://github.com/cryptohopper/cryptohopper-swift-sdk.git → choose your version rule.

Requirements

  • Swift 5.9+
  • iOS 13+ / macOS 10.15+ / tvOS 13+ / watchOS 6+ / Linux (via FoundationNetworking)

Quickstart

import Cryptohopper
import Foundation

let token = ProcessInfo.processInfo.environment["CRYPTOHOPPER_TOKEN"]!
let client = try Client(apiKey: token)

do {
    let me = try await client.user.get() as? [String: Any]
    print("Logged in as: \(me?["email"] ?? "unknown")")

    let ticker = try await client.exchange.ticker(
        exchange: "binance",
        market: "BTC/USDT"
    ) as? [String: Any]
    print("BTC/USDT: \(ticker?["last"] ?? "?")")
} catch let error as CryptohopperError {
    print("\(error.code.rawValue) (\(error.status)): \(error.message)")
    if error.code == .rateLimited, let ms = error.retryAfterMs {
        print("Retry after \(ms)ms")
    }
}

Authentication

Every request (except a handful of public endpoints) needs a 40-character OAuth2 bearer token. Issue one through the developer dashboard on cryptohopper.com, then:

let client = try Client(
    apiKey: "your-40-char-oauth-token",
    appKey: "your-oauth-client-id"  // optional, sent as x-api-app-key
)

The optional appKey carries your OAuth client_id for per-app rate-limit attribution.

Configuration

let client = try Client(
    apiKey: ProcessInfo.processInfo.environment["CRYPTOHOPPER_TOKEN"]!,
    appKey: ProcessInfo.processInfo.environment["CRYPTOHOPPER_APP_KEY"],
    baseURL: "https://api.cryptohopper.com/v1",  // override for staging
    timeout: 30,                                  // per-request, seconds
    maxRetries: 3,                                // 429 backoff; 0 disables
    userAgent: "my-app/1.0"                       // appended after cryptohopper-sdk-swift/<v>
)

Errors

Every non-2xx response and every transport failure throws CryptohopperError:

do {
    _ = try await client.hoppers.get("not-a-real-id")
} catch let err as CryptohopperError {
    err.code            // .notFound, .unauthorized, .rateLimited, etc.
    err.status          // HTTP status (0 on transport failure)
    err.serverCode      // numeric Cryptohopper code when present
    err.ipAddress       // server-reported caller IP, when included
    err.retryAfterMs    // parsed Retry-After (only on 429)
}

The CryptohopperError.Code enum has a .other(String) variant that catches server-side codes the SDK predates — your switch doesn't need an SDK update to handle new codes:

switch err.code {
case .rateLimited:    // SDK already retried; back off harder
case .unauthorized:   // re-auth
case .forbidden:      // check err.ipAddress
case .other(let raw): print("new code from server: \(raw)")
default: break
}

Codes are stable across every official Cryptohopper SDK (Node, Python, Go, Ruby, Rust, PHP, Dart, Swift). The .rawValue string is the canonical form.

Rate limits

On HTTP 429 the client sleeps for Retry-After seconds (or an exponential-backoff fallback) and retries up to maxRetries times. The final failure surfaces as CryptohopperError with code == .rateLimited and retryAfterMs populated.

Testing your code

Inject a MockHTTPClient (or your own HTTPClient conforming type):

import Cryptohopper

final class MyMockClient: HTTPClient {
    func send(_ request: URLRequest) async throws -> (Data, HTTPURLResponse) {
        let url = request.url!
        let response = HTTPURLResponse(
            url: url, statusCode: 200,
            httpVersion: "HTTP/1.1", headerFields: [:]
        )!
        return (Data(#"{"data":{"id":42}}"#.utf8), response)
    }
}

let mock = MyMockClient()
let client = try Client(apiKey: "test", httpClient: mock)
let result = try await client.user.get() as? [String: Any]
// result?["id"] == 42

The SDK's own test suite uses exactly this pattern — see Tests/CryptohopperTests/ for examples covering error mapping, retry behaviour, and resource path wiring.

Versioning

Semantic versioning. While on 0.x, minor releases can ship breaking changes — they're called out in CHANGELOG.md. See the shared versioning policy for the full SDK-wide rules.

Other Cryptohopper SDKs

Language Install
Node.js / TypeScript npm i @cryptohopper/sdk
Python pip install cryptohopper
Go go get github.com/cryptohopper/cryptohopper-go-sdk
Ruby gem install cryptohopper --pre
Rust cargo add cryptohopper
PHP composer require cryptohopper/sdk
Dart / Flutter dart pub add cryptohopper
CLI npm i -g @cryptohopper/cli or download a binary

License

MIT — see LICENSE.

About

Official Swift SDK for the Cryptohopper API. Async, typed errors, auto-retry on 429, full coverage of all 18 public API domains. iOS / macOS / tvOS / watchOS / Linux.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages