The CLOB read base is `<node>/v1/bc/D/dex/...`, not /ext/. luxd serves one prefix (node server/http/server.go baseURL = "/v1"). Measured 2026-07-27 on both fleets, each with a bogus-path control: mainnet luxd-1:9630 /v1/bc/C/rpc 200 0x17871 | /ext/ 404 | control 404 devnet luxd-2:9650 /v1/bc/C/rpc 200 0x1786f | /ext/ 404 | control 404 Ports come from each net's LuxNetwork CR spec.ports.http — never assume. go vet ./... clean; go test ./indexer/ -run CLOB -> 3/3 PASS. Co-authored-by: Hanzo Dev <[email protected]>
4.8 KiB
graph
Org: luxfi · Ecosystem: lux · Path: /Users/a/work/lux/luxfi/graph
Origin: https://github.com/luxfi/graph.git
Discovery
This file (CLAUDE.md) is the canonical agent-facing readme; LLM.md is a symlink to it. Update either name and both stay in sync.
Where to look first
README.md— human-facing overview (if present)package.json/Cargo.toml/pyproject.toml/go.mod— language & deps.github/workflows/— CI surfacedocs/— extended docs (if present)
DEX indexing has TWO orthogonal sources (EVM 0x9999 logs + native D-Chain CLOB)
The dex subgraph (markets/fills/orders/orderbook) can be fed from either or both of:
- EVM 0x9999 settlement logs — the cross-chain SETTLEMENT view.
handleDEXFill/handleInitializeV4derive Market/Fill fromDEXFill/Initializelogs emitted by the 0x9999 PoolManager on an EVM chain (C-Chain). Source =indexer.goeth_getLogs. - Native D-Chain CLOB read RPC — the TRADING view. On a native-DEX deployment the
trade engine IS the D-Chain (dexvm): a trade is a consensus state transition at
Block.Verify, NOT an EVM event, so it NEVER appears on the EVM RPC.CLOBSource(indexer/clob.go) polls the committed-state read RPC…/v1/bc/<D>/dex/clob_get_{markets,trades,orders}(GET/JSON, READ-ONLY, zero consensus impact — seeluxfi/dex pkg/dchain/read.go) and writes the SAME Market/Fill/Order entities the resolvers serve. Enabled byConfig.DexRPC(graph) /dex_rpc:per-chain (explorerchains.yaml); empty = source 1 only.
The two sources are ORTHOGONAL — distinct loop, distinct protocol, distinct endpoint;
they share only the store (the sink) and the entity shapes (the contract). Running the
CLOB source NEVER regresses AMM/EVM indexing (the amm subgraph never gets dex_rpc).
Both Markets key by poolID, so when both run they converge on one Market per pool:
writeMarket refreshes the live CLOB book summary and MERGES through any EVM-accrued
volume24h/tradeCount/lastPrice it does not own.
Markets serve on the same host under distinct slugs (.../cchain/amm/graphql,
.../cchain/dex/graphql).
Native CLOB source notes (clob.go)
- Fills are a GLOBAL feed. The 80-byte on-chain trade row carries no poolID (frozen
GPU ABI), so
clob_get_tradesis a global height-ordered log.writeTraderecords every fill as aFill(the trade-history view) keyedheight:seq(deterministic → idempotent re-read). Per-market figures (open orders, depth, best bid/ask, remaining) come fromclob_get_markets' authoritative per-market book summary — we do NOT fabricate a per-market volume by mis-attributing the global log. - Incremental.
drainTradespages bysince=lastHeight+1; a steady chain costs one small query per tick. Symbol decode: a bound market's hex symbol (4c55…= ASCIILUX/LUSD) → human pair; an unbound poolID stays hex.
Native DEX indexing (0x9999) — the EVM-settlement source detail
- Single Fill source. A settled fill is recorded ONLY from the authoritative
DEXFillevent inhandleDEXFill.handleSwapV4is the AMM-side view and does NOT write a Fill. Do not add a second fill source. - Emitter-scoped.
handleDEXFilldrops anyDEXFillnot emitted by the configuredPoolManager(0x9999) —!isPoolManager(l.Address)returns early. This is the anti-spoof control; keep it. - Topic0 hashes (
indexer/events.go) are keccak256 of the EXACT signatures theluxfi/precompileemits (see~/work/lux/precompile/dex/events.go). The LuxSwapcarries a trailinguint24 fee— NOT the upstream Uniswap-v4 signature.DEXFill=keccak256("DEXFill(bytes32,address,uint256,uint256)"). If you change a signature in the precompile, recompute the hash here or it matches nothing. - Re-genesis self-heal rewinds the cursor only on a confirmed re-genesis (changed genesis-block hash) after a hysteresis streak — never on a transient low-head blip.
Deployment topology — TWO exchange-api images (do not conflate)
ghcr.io/luxfi/graph(this repo,Dockerfile→graphd) backs the explorer. Built by.github/workflows/docker.ymlonv*tags, self-hosted ARC pool.ghcr.io/luxfi/exchange-apihas TWO independent source/version lines:v2.2.x← repoluxfi/exchange-api(TypeScript,/v1/graphqlwith amm/dex routing +DEX_SUBGRAPH_URL). Deployed in lux-explorer. This is the markets API.v5.x← repoluxfi/exchangeDockerfile.api(server.js, REST/v1/tokens|pools|trades|price+/subgraph/*). Deployed in lux-ns. These are NOT the same codebase. A change to one does not reach the other's image.
Sibling repos
See the org-level LLM.md at /Users/a/work/lux/luxfi/LLM.md for the full inventory of sibling repos and inter-repo dependencies.