Skip to content

Repository files navigation

KalqiX Hummingbot Connector

REST-only Hummingbot CEX connector for KalqiX, an order-book DEX.

Distributed as a standalone plugin — drops eight Python modules into your Hummingbot install's connector/exchange/kalqix/ directory. Auto-discovered by Hummingbot at boot via AllConnectorSettings; no edits to Hummingbot's own source are required.


Status

Beta. Used in production against testnet-api.kalqix.com and api.kalqix.com.

This repository is the public drop-in distribution — clone it, install once, and connect kalqix or connect kalqix_testnet from your Hummingbot CLI. A parallel repository tracks the work toward submitting this connector upstream to hummingbot/hummingbot; that flow requires additional unit-test scaffolding and is not the path most users will take. If you just want to run a bot today, this repo is the right place.

What it supports

Feature Status
LIMIT / MARKET orders
Post-only / LIMIT_MAKER ✅ sent as time_in_force: 3; a crossing order is killed by the engine after placement and surfaces as an order failure (see limitations)
Place / cancel / status / fills
Account balances
Public order book + trade tape ✅ via REST polling
client_order_id (idempotency / crash recovery)
WebSocket channels ❌ Planned for future
Perpetuals ❌ Planned for future

Polling cadences (defaults; tweak in kalqix/kalqix_constants.py):

Endpoint Default cadence
Order book snapshot 500 ms
Public trades 1 s
Open orders 1 s
Balances (framework status loop) per Hummingbot config

Prerequisites

kalqix-node-api 1.9.0 or newer: every list the connector polls is cursor-paginated (next_cursor). Against an older API the connector logs an error and reads only the first page of each list.

A KalqiX account with:

  • An API key (api_key + api_secret) minted via PUT /v1/api-keys in the KalqiX UI (production or testnet).
  • An export-pool agent wallet (slot 6..255) and its private key, generated via Settings → Agent Wallets → Generate for export.

Both credentials are shown once and not retrievable later — copy them into your secrets store on generation.

For Path B below (symlink into an existing install) you also need a working Hummingbot 1.x install on your host. Path A (Docker) bundles Hummingbot in the image — nothing else needed on your host beyond Docker Desktop.

BIP-340 Schnorr signing is now done inline in kalqix_auth.py (~50 lines of pure Python, no external curve lib). Earlier releases needed pip install coincurve — that's no longer the case.

Install

Two paths — pick one:

A. Docker (recommended for trying it out)

No host-side Python / Hummingbot install. The container bundles Hummingbot; this repo bind-mounts the connector on top.

git clone https://github.com/kalqix/kalqix-hummingbot-connector.git
cd kalqix-hummingbot-connector
docker compose up --build -d
docker attach kalqix-hummingbot
>>> connect kalqix_testnet      # then enter your testnet creds

Full step-by-step (incl. troubleshooting + a pure_market_making smoke test): see DOCKER.md.

B. Symlink into an existing Hummingbot install

git clone https://github.com/kalqix/kalqix-hummingbot-connector.git
cd kalqix-hummingbot-connector
./install.sh                          # auto-detect via `python -c "import hummingbot"`
# OR
./install.sh /path/to/hummingbot      # explicit install dir

The script symlinks kalqix/ into Hummingbot's connector/exchange/kalqix/. Symlink (not copy) so an update via git pull here is picked up by Hummingbot without re-running the script.

To uninstall: rm /path/to/hummingbot/connector/exchange/kalqix.

Connect

The plugin registers two named connectors with Hummingbot — pick the one matching the network where you minted your credentials. Both prompt for the same four fields; credentials are stored separately so you can have both configured at once.

$ hummingbot
>>> connect kalqix_testnet              # testnet (testnet-api.kalqix.com)
# OR
>>> connect kalqix                      # mainnet (api.kalqix.com)

Enter your KalqiX API key:           <api_key>
Enter your KalqiX API secret:        <api_secret>
Enter the agent-wallet slot index:   <6..255>
Enter the agent-wallet private key:  <64 hex chars, no 0x>

Hummingbot validates by calling GET /v1/positions. A 200 means HMAC auth works. The agent-wallet credentials are exercised on the first order placement.

Testnet vs mainnet — how routing works

The two names map to two BaseConnectorConfigMap subclasses backed by the same KalqixExchange Python class with different domain values:

Hummingbot command domain passed in Base URL
connect kalqix "com" https://api.kalqix.com/v1
connect kalqix_testnet "testnet" https://testnet-api.kalqix.com/v1

kalqix_testnet is wired in via Hummingbot's OTHER_DOMAINS framework hook (see kalqix/kalqix_utils.py:120-124):

OTHER_DOMAINS = ["kalqix_testnet"]
OTHER_DOMAINS_PARAMETER = {"kalqix_testnet": "testnet"}
OTHER_DOMAINS_KEYS = {"kalqix_testnet": KalqixTestnetConfigMap.model_construct()}

URL resolution is centralised in kalqix/kalqix_constants.py:rest_url(domain) — that's the one place to look if you ever need to verify which endpoint a request is hitting.

Architecture

File Lines Purpose
kalqix_constants.py 165 REST URLs, rate limits, order-state map, polling cadences
kalqix_utils.py 109 KalqixConfigMap, ticker conversions, exchange-info filter
kalqix_auth.py 160 HMAC-SHA256 transport + BIP-340 Schnorr signing helper
kalqix_web_utils.py 69 URL builder, throttler, /v1/time reader
kalqix_order_book.py 114 Snapshot + trade message adapters
kalqix_api_order_book_data_source.py 220 REST-poll order book + trade tape (overrides Hummingbot's WS hooks)
kalqix_api_user_stream_data_source.py 167 REST-poll open orders + user trades, emits synthetic events
kalqix_exchange.py 561 KalqixExchange(ExchangePyBase) — main connector class

Two-layer auth

Every authenticated request carries:

  1. HMAC-SHA256 over METHOD|PATH|QUERY|BODY|TIMESTAMP as x-api-key / x-api-signature / x-api-timestamp headers. Handled transparently by KalqixAuth.rest_authenticate.
  2. For state-changing requests (place / cancel), an additional BIP-340 Schnorr signature over the action's canonical payload, signed by the export-pool agent wallet's private key, inlined into the request body or query as signature + agent_index.

client_order_id is not part of the signed payload — it's a bot tag, not a security boundary. The server validates its format and uniqueness independently.

REST-poll override pattern

Hummingbot's OrderBookTrackerDataSource and UserStreamTrackerDataSource are normally WS-driven. The connector overrides listen_for_subscriptions and listen_for_order_book_diffs to no-op infinite sleeps, and rewrites listen_for_order_book_snapshots / listen_for_trades / listen_for_user_stream as REST poll loops on fixed cadences. The framework's task scheduling still drives execution; the WS layer is just bypassed.

Known limitations + what's likely to break first

These are flagged for early testers — none are blockers for the common case but are worth knowing:

  • Decimal scaling race. Order placement looks up market decimals from _market_decimals, populated during the first trading-rules load. Placing an order before the framework's first _update_trading_rules tick raises ValueError. Hummingbot's normal startup sequence loads rules first; this would only show as a startup-race bug.
  • Cancel before place ack. The cancel path needs tracked_order.exchange_order_id, which arrives via the open-orders poll. A cancel-immediately-after-place can return False and get retried on the next status loop. Not a correctness bug — just a latency spike.
  • Post-only rejection is asynchronous, and it changes maker strategies' default. KalqiX accepts a LIMIT_MAKER order at the API and the matching engine kills it if any part would trade on arrival (status: EXPIRED, close_reason: POST_ONLY_CROSS, zero fills). Because the connector advertises LIMIT_MAKER, Hummingbot's stock maker strategies (pure market making, Avellaneda, XEMM's maker leg, liquidity mining) place post-only orders by default; a quote that crosses is rejected instead of filling as a taker. Pure market making can opt out with take_if_crossed. The rejection never appears in /orders?open=true, so the user-stream poller looks for tracked orders that have dropped out of the open list and fetches their terminal state: a crossing order surfaces as an order failure about one to two poll intervals (1 s each) after placement, and the framework's own status loop (LONG_POLL_INTERVAL, 120 s) remains as the fallback.
  • Polling cost. With today's ≤10 trading pairs on KalqiX, a steady-state market-making bot runs around 2–3k req/min — well under the 18k req/min wallet rate limit. The polling cadences in kalqix_constants.py only need tuning if KalqiX's pair count grows materially or you run multiple bots on one wallet (the limit is per-wallet, not per-bot).

License

Apache 2.0 — see LICENSE. Matches the upstream Hummingbot project.

Security

To report a security issue (e.g. anything that touches signature verification, agent-wallet key handling, or HMAC transport), please do not open a public issue. See SECURITY.md for the responsible-disclosure channel.

Contributing

Issues and PRs welcome. The roadmap (in rough order):

  1. WebSocket support once kalqix-node-api ships the channels.
  2. Perpetuals once KalqiX adds a perp venue.

Upstream PR work (Hummingbot-style unit tests with aioresponses / NetworkMockingAssistant, then the hummingbot/hummingbot:development submission) is tracked in a parallel repository; it's not on this repo's roadmap because the two distributions are intentionally decoupled — changes here ship to users immediately on git pull, while upstream changes go through a multi-week review cycle.

About

REST-only Hummingbot connector for KalqiX DEX

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages