This document explains how market makers can authenticate and integrate with the Ekiden Gateway HTTP API and WebSocket feeds exposed by the Axum service. It mirrors what is generated by utoipa and available in Swagger UI.
Swagger UI
OpenAPI JSON

1. Service Overview

  • Protocol: HTTP/1.1 + WebSocket
  • Default Port: 3010
  • Base REST Path: /api/v1
  • CORS: Open (all origins/headers/methods allowed)
  • Auth: JWT Bearer (obtained via an Ed25519 signature challenge)
  • Modules exposed: orders, fills, user, deposits, withdraws (all are nested under /api/v1)
  • WebSocket: GET /ws (top‑level; not under /api/v1)
The service depends on external gRPC backends:
  • SEQUENCER_GRPC_URL → Sequencer
  • REFEREE_GRPC_URL → Referee

2. Authentication Flow

Authentication is performed via a one-shot signature challenge. Clients sign the literal message AUTHORIZE using their Ed25519 private key and send the resulting signature and associated public key to /api/v1/authorize. On success, the API returns a JWT bearer token to include in subsequent requests.

Endpoint

POST /api/v1/authorize
Summary: Verify AUTHORIZE signature and issue a JWT. Tags: Auth Sec: no auth required for this call.

Request Body –

AuthorizeParams

{
  "public_key": "<ed25519-public-key>",
  "signature": "<signature-over-\\"AUTHORIZE\\">"
}
  • public_key: Client’s Ed25519 public key (encoding per your SDK; commonly base64 or hex).
  • signature: Signature of the exact byte string AUTHORIZE using the corresponding Ed25519 private key (same encoding style as public_key).
The server verifies with signature::verify_msg(b”AUTHORIZE”, signature, public_key) and computes a user address from the public key. If the user does not exist, it is created.

Responses

  • 200 OK – AuthorizeResponse
{ "token": "<jwt-bearer-token>" }
  • 400 Bad Request – invalid signature or public key
  • 500 Internal Server Error

Example – cURL

curl -X POST "http://<host>:3010/api/v1/authorize" \\
  -H "Content-Type: application/json" \\
  -d '{
    "public_key": "<YOUR_ED25519_PUBKEY>",
    "signature": "<SIG_OVER_AUTHORIZE>"
  }'
On success, save the returned token and include it in the Authorization header:
Authorization: Bearer <token>

3. Using the JWT

All authenticated REST endpoints require the standard HTTP Bearer token.
Authorization: Bearer <token>
The OpenAPI spec declares a bearer_auth security scheme, and all protected routes are annotated to use it.

4. REST API Surface

All resource routers are mounted under /api/v1:
  • GET/POST/… /api/v1/orders – Order management (exact routes in Swagger)
  • GET/… /api/v1/fills – Fill information
  • GET/… /api/v1/user – User/account endpoints
  • GET/POST/… /api/v1/deposits – Deposit endpoints
  • GET/POST/… /api/v1/withdraws – Withdraw endpoints
Authoritative contract:

Example – Authenticated request

curl -X GET "http://<host>:3010/api/v1/fills?limit=100" \\
  -H "Authorization: Bearer $TOKEN"
Tip: If you see 401 Unauthorized, refresh your token via /api/v1/authorize.

5. WebSocket Streaming

  • Endpoint: GET ws://<host>:3010/ws
  • Purpose: Real-time event feed (emitted via an internal broadcast channel)
  • Auth: Implementation-specific. If private streams are offered, you may be required to present the JWT (e.g., as the first message or via subprotocol). Consult the deployed config/team for the expected pattern.

Example – JavaScript

const ws = new WebSocket("ws://<host>:3010/ws");
ws.onopen = () => {
  // If auth is required, send your token here (example only):
  // ws.send(JSON.stringify({ op: "auth", token: YOUR_JWT }));
};
ws.onmessage = (e) => console.log("event", e.data);
ws.onclose = () => console.log("closed");
Event payloads are defined by the server’s ws::EventWithChannel. Use your environment’s Swagger or internal docs for the exact schema of each channel.

6. Local Testing

  1. Export backend endpoints:
export SEQUENCER_GRPC_URL=grpc://<sequencer-host>:<port>
export REFEREE_GRPC_URL=grpc://<referee-host>:<port>
  1. Run the API (binds 0.0.0.0:3010):
cargo run -p <your-api-crate>
  1. Open Swagger UI:
<http://localhost:3010/swagger-ui>

7. Error Handling

  • 400 – Invalid signature or public key on /authorize.
  • 401 – Missing/expired/invalid Authorization: Bearer token on protected routes.
  • 5xx – Internal server errors or dependency failures (database, gRPC backends).
Errors are logged with tracing and the service emits structured JSON logs in non‑debug builds.

8. Security Notes

  • Use HTTPS in production (behind a reverse proxy / LB) and store tokens securely.
  • JWT validity/claims are generated by AuthClaims::generate_with_token.
  • Rate limits are not enforced by this service; deploy behind an API gateway if needed.

9. FAQ

Q: What exact encodings are expected for public_key and signature? A: The server treats them as strings and passes to the Ed25519 verifier. Use the same encoding your SDK produces (commonly base64 or hex). Confirm with your Ekiden contact if unsure. Q: Is /ws namespaced under /api/v1? A: No. It is mounted at the root /ws. Q: Where can I find the exact schemas for Orders/Fills/etc.? A: Open Swagger UI at /swagger-ui or fetch /api-docs/openapi.json. Those are generated from the code and are the source of truth.

10. Changelog

  • v1.0 – Initial draft based on Axum service wiring and utoipa annotations provided in source.