Adapter Contract
Every provider in Artery implements the same IPredictionMarketProvider
interface (@artery/types). Capabilities (data / trade / stream /
delegation) are declared per-provider and surfaced via GET /providers.
Wire format
All Endpoints return the native passthrough shape:
json{
"native": {
/* raw upstream JSON, unmodified */
},
"meta": {
"provider": "polymarket",
"fetchedAt": "2026-05-05T07:30:00.000Z",
"source": "live"
}
}An upcoming release will add an optional normalized field on responses where semantics align across providers
(e.g. binary YES/NO markets). The native shape is preserved indefinitely.
Capability matrix
| Provider | data | trade | stream | delegation |
|---|---|---|---|---|
| Polymarket (CLOB + Gamma) | ✅ | ✅ (planned) | ✅ | EIP-712 + Safe Module |
| Kalshi | ✅ | ✅ | ✅ | RSA private-key upload (KMS-encrypted) |
| Hyperliquid Perp + HIP-3 | ✅ | ✅ | ✅ | EIP-712 approveAgent |
| Hyperliquid HIP-4 | ✅ | ✅ | ✅ | EIP-712 approveAgent (USDH) |
| Hyperliquid DEX (HyperEVM) | ✅ | ✅ | ❌ (RPC limitation) | Permit2 typed data |
Self-hosted source: Hyperliquid
The Hyperliquid adapter is the first one running in "indexed" mode in
production. Artery operates its own Hyperliquid non-validator node
(hl-visor) on dedicated hardware, paired with hl-adapter — a small
Go service that:
- Tails
node_fills_by_block/hourly/<day>/<hour>+misc_events_by_block/...files and indexes them into Postgres (hl_fills,hl_misc_events) - Serves the
/infoAPI on the same JSON contract asapi.hyperliquid.xyz— locally for the supported types, transparently passing through for anything else - Caches HL official passthrough responses in an in-memory LRU per-type so repeat calls inside the cache TTL never re-hit the public API
Net effect for clients: zero rate-limit + sub-millisecond latency for
the locally-served /info types (allMids, candleSnapshot, meta,
spotMeta, clearinghouseState, userFills, userFillsByTime,
userFunding, userNonFundingLedgerUpdates, openOrders, subAccounts,
delegations), with full HL outage immunity for those endpoints. See
providers/hyperliquid for the customer-facing
catalog + caveats.
The other providers (Polymarket, Kalshi) still route through public API + RPC. Same indexing pattern can be applied later if scale or cost justifies it.
Two-implementation pattern
Each adapter has two implementations sharing one interface:
- Live — calls upstream API directly via
@artery/transport - IndexedDB — A future release will read from our own RPC node + indexer
tsconst polymarketAdapter = createPolymarketAdapter({
source:
ART_SOURCE === 'indexed'
? new IndexedPolymarketSource(redis, postgres) // indexed source (roadmap)
: new LivePolymarketSource(transport), // live source
});A single contract test suite (apps/api/test/contract/) runs against
both implementations, guaranteeing equivalence at switchover.