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
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")]),
]File → Add Package Dependencies → paste https://github.com/cryptohopper/cryptohopper-swift-sdk.git → choose your version rule.
- Swift 5.9+
- iOS 13+ / macOS 10.15+ / tvOS 13+ / watchOS 6+ / Linux (via
FoundationNetworking)
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")
}
}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.
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>
)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.
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.
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"] == 42The SDK's own test suite uses exactly this pattern — see Tests/CryptohopperTests/ for examples covering error mapping, retry behaviour, and resource path wiring.
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.
| 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 |
MIT — see LICENSE.