4.7 KiB
White-Label API Gateway (api-gateway-gateway)
The Lux ecosystem's Gateway at lux-mainnet/api-gateway-gateway:80
is a shared multi-tenant backend. Any white-label app — Zoo, Hanzo,
Pars, or third-party — points its api.<their-domain> at the
gateway and gets:
- All Lux-ecosystem chain RPCs (
/v1/chain/{C,X,P,zoo,hanzo,spc,pars,Q,Z,T,A,D}/rpc) - Indexer endpoints (
/api/indexer/indexer-{c,zoo,hanzo,spc,pars}) - Health, info, and admin endpoints (
/v1/health,/v1/info) - DAG chain stats (
/api/v2/dag/{q,z,t,a}chain/{health,stats}) - DEX precompile / gateway routes
- TLS via cert-manager letsencrypt
- CORS already wide-open (
Access-Control-Allow-Origin: *)
Zero per-tenant config needed in the gateway itself.
Onboarding a new white-label app
-
Pick a hostname:
api.<your-app>.<tld>(e.g.api.zoo.exchange,api.hanzo.network,api.pars.market). -
Create an Ingress in
lux-mainnetns:apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: api-<your-app> namespace: lux-mainnet annotations: cert-manager.io/cluster-issuer: letsencrypt spec: ingressClassName: ingress tls: - hosts: [api.<your-app>.<tld>] secretName: api-<your-app>-tls rules: - host: api.<your-app>.<tld> http: paths: - path: / pathType: Prefix backend: service: name: api-gateway-gateway port: { number: 80 } -
Add DNS:
Arecord forapi.<your-app>.<tld>→134.199.138.27(hanzo-ingressLB ondo-sfo3-lux-k8s). Cloudflare-proxied is fine. -
Verify:
curl -X POST -H 'Content-Type: application/json' \ --data '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' \ https://api.<your-app>.<tld>/v1/chain/zoo/rpc # → {"jsonrpc":"2.0","id":1,"result":"0x30e08"} -
Point your SPA at the new hostname. With
hanzoai/sparuntime, set the env vars:- { name: SPA_RPC_HOST, value: https://api.<your-app>.<tld>/v1/chain/<chain>/rpc } - { name: SPA_API_HOST, value: https://api.<your-app>.<tld> } - { name: SPA_GATEWAY_HOST, value: https://api.<your-app>.<tld> }These get templated into
/config.jsonat pod start; the SPA reads them on boot and uses them for every backend call.
Live deployments
| host | namespace | ingress |
|---|---|---|
api.lux.network |
lux-mainnet |
(legacy direct DNS) |
api.zoo.exchange |
lux-mainnet |
api-zoo-exchange |
api.hanzo.network |
(reserve) | (create when needed) |
api.pars.market |
(reserve) | (create when needed) |
api.liquid.exchange |
(reserve) | (create when needed) |
All point to the same api-gateway-gateway service; each just gets its
own TLS cert and DNS record.
Endpoints exposed
# Chain RPCs (40+ endpoints across 12 chains × 3 envs each)
POST /v1/chain/C/rpc # Lux C-Chain (96369)
POST /v1/chain/zoo/rpc # Zoo (200200)
POST /v1/chain/hanzo/rpc # Hanzo (36963)
POST /v1/chain/pars/rpc # Pars (494949)
POST /v1/chain/spc/rpc # SPC (36911)
POST /v1/chain/{Q,Z,T,A,D}/rpc # primary network chains
POST /v1/chain/{X,P} # X-Chain, P-Chain
GET /v1/info
GET /v1/health{,/liveness}
# Indexer (block/tx data per chain)
GET /api/indexer/indexer-{c,zoo,hanzo,spc,pars}/...
# DAG / consensus stats
GET /api/v2/dag/{q,z,t,a}chain/{health,stats}
GET /api/chains
Add a new endpoint by editing lux-mainnet/api-gateway-gateway-config
ConfigMap (gateway.json endpoints[]) and rolling the deployment.
CORS
Wide-open by default — any browser Origin is allowed:
"security/cors": {
"allow_origins": ["*"],
"allow_methods": ["GET","POST","OPTIONS"],
"allow_headers": ["Content-Type","Authorization"],
"expose_headers": ["Content-Length"],
"max_age": "12h"
}
To tighten to a specific allow-list, replace ["*"] with the explicit
origin list and roll api-gateway-gateway deployment in lux-mainnet.
Backend topology
Browser (zoo.exchange / hanzo.exchange / pars.market / ...)
│
│ https://api.<app>.<tld>/v1/chain/zoo/rpc
▼
Cloudflare (TLS termination + caching)
│
▼
hanzo-ingress LB (lux-system, 134.199.138.27)
│ routes by Host header → matching K8s Ingress
▼
api-gateway-gateway (lux-mainnet, Gateway :80)
│ matches /v1/chain/<alias>/rpc → looks up backend host
▼
luxd-headless.lux-mainnet.svc.cluster.local:9630
│ StatefulSet: 5 luxd validators on Lux Mainnet
▼
EVM plugin (per chain) → on-disk badgerdb state
The SPA never needs to know any of this — it just calls
https://api.<their-domain>/v1/chain/<chain>/rpc and Gateway does the rest.