diff --git a/CHANGELOG.md b/CHANGELOG.md index fc407e4..f76fa9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,16 @@ All notable changes to `@cryptohopper/sdk` are documented in this file. The format is loosely based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). -## 0.4.0-alpha.1 — Unreleased +## 0.4.0-alpha.2 — Unreleased + +### Fixed +- **Critical: every authenticated request was rejected by the API gateway.** The transport sent `Authorization: Bearer `, which the AWS API Gateway in front of `api.cryptohopper.com/v1/*` rejects (it routes `Authorization` to a SigV4 parser and returns `405 Missing Authentication Token`). Cryptohopper's Public API v1 uses a different header — `access-token: ` — confirmed by the official [API documentation](https://www.cryptohopper.com/api-documentation/how-the-api-works) and the legacy `cryptohopper-ios-sdk` / `cryptohopper-android-sdk` (which also send `access-token` for v1 calls). Switching the SDK to send `access-token` instead. The `Authorization` header is no longer set. +- The `appKey` → `x-api-app-key` header is unchanged; that one was always correct. + +### Compatibility +No public-API change. The fix is purely in the request-builder and is invisible to callers — `client.user.get()`, `client.hoppers.list()`, etc. all keep their existing signatures and behaviour. Only the wire-level header sent on each request changes. + +## 0.4.0-alpha.1 — 2026-04-25 Adds four more API domains: `social`, `tournaments`, `webhooks`, `app`. This is the final A-wave — all 14 remaining public domains are now covered. diff --git a/README.md b/README.md index a47de12..c01c4f1 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ await ch.hoppers.configGet(42); await ch.hoppers.configUpdate(42, { /* config fields */ }); await ch.hoppers.panic(42); -// Exchange (public — no auth required) +// Exchange — market data (still requires a real token; the gateway has no anonymous routes) await ch.exchange.ticker({ exchange: "binance", market: "BTC/USDT" }); await ch.exchange.candles({ exchange: "binance", market: "BTC/USDT", timeframe: "1h" }); await ch.exchange.orderbook({ exchange: "binance", market: "BTC/USDT" }); @@ -74,7 +74,7 @@ await ch.backtest.list(); await ch.backtest.cancel(1); await ch.backtest.limits(); -// Marketplace (public — no auth required) +// Marketplace — same auth requirement as everything else await ch.market.signals({ type: "buy" }); await ch.market.signal(99); await ch.market.items({ type: "strategy" }); diff --git a/package.json b/package.json index 12714ee..e3c8719 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cryptohopper/sdk", - "version": "0.4.0-alpha.1", + "version": "0.4.0-alpha.2", "description": "Official Node.js SDK for the Cryptohopper API", "type": "module", "main": "./dist/index.js", diff --git a/src/client.ts b/src/client.ts index 1521883..7c2ba8b 100644 --- a/src/client.ts +++ b/src/client.ts @@ -157,7 +157,10 @@ export class CryptohopperClient { const url = this.buildUrl(path, options.query); const ua = `cryptohopper-sdk/${CURRENT_VERSION}${this.userAgentSuffix ? ` ${this.userAgentSuffix}` : ""}`; const headers: Record = { - Authorization: `Bearer ${this.apiKey}`, + // Cryptohopper Public API v1 uses `access-token: `, not the + // OAuth2-conventional `Authorization: Bearer `. The gateway in + // front of the API rejects Bearer with a SigV4 parse error. + "access-token": this.apiKey, "User-Agent": ua, Accept: "application/json", }; diff --git a/src/version.ts b/src/version.ts index 26dd551..651cb33 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const CURRENT_VERSION = "0.4.0-alpha.1"; +export const CURRENT_VERSION = "0.4.0-alpha.2"; diff --git a/test/client.test.ts b/test/client.test.ts index 46d9211..50f59cd 100644 --- a/test/client.test.ts +++ b/test/client.test.ts @@ -17,7 +17,8 @@ describe("CryptohopperClient transport", () => { const req = mock.requests[0]!; expect(req.url).toBe("https://api.cryptohopper.com/v1/user/get"); expect(req.method).toBe("GET"); - expect(req.headers["authorization"]).toBe("Bearer ch_abc"); + expect(req.headers["access-token"]).toBe("ch_abc"); + expect(req.headers["authorization"]).toBeUndefined(); expect(req.headers["user-agent"]).toBe(`cryptohopper-sdk/${CURRENT_VERSION}`); expect(req.headers["x-api-app-key"]).toBeUndefined(); });