feat(indexer): complete AMM orderbook sim (curve walk) for CG/CMC #210
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:implement
agent:implement
agent:open_issues
agent:ready
agent:research
agent:security_audit
agent:verify
architecture
backend
blocker:hybrid
blocker:launch
blocker:limit-orders
blocker:v2
block:log_only
block:security
bug
ci
contracts
correctness
deploy
dev
devops
docs
documentation
duplicate
e2e
enhancement
epic
feature
frontend
functional-completion
gas
good first issue
governance
help wanted
high-risk
hooks
hybrid
indexer
infra
infrastructure
integrators
invalid
launch-blocker
limit-orders
localnet
localterra
low priority
missing-implementation
needs-design
ops
performance
priority
high
priority
medium
product
qa
QA
question
ready
ready
research
scripts
security
security-hardening
smartcontracts
tech-debt
testing
ux
UX
v2
verification
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
code/cl8y-dex-terraclassic#210
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Complete the AMM orderbook simulation (
curve walk) in the indexer so CoinGecko/CoinMarketCap/cg/orderbookand/cmc/orderbook/*return production-faithful synthetic depth. Today the module is cataloged in #105 as a stub/stand-in: it works end-to-end but uses simplified float math, omits swap fees, and diverges from the published compliance spec. This is not the on-chain FIFO limit order book (seelimit-book).Parent catalog: #105. Gap row:
gaps/GAP_1780023683.md§2.2 (Orderbook sim).Current codebase
Production module (
indexer/src/api/orderbook_sim.rs)simulate_orderbook{"pool": {}}→ reserves asf64→ constant-product walk fordepthlevelsfraction = 0.001 + 0.099 * i / (depth-1)(0.1%–10% ofreserve_0)dxof asset_0; price =dy/dxafterk/(R0+dx)dxof asset_0 whendx < R0; skips level ifdx >= R0f64division — not pairceil_div_pool: &PgPoolsimulate_orderbook_cached(pair_addr, depth)HTTP consumers
GET /cg/orderbookindexer/src/api/cg.rscg_orderbookGET /cmc/orderbook/:market_pairindexer/src/api/cmc.rscmc_orderbookTests today
indexer/tests/api_orderbook_lcd_mock.rs: HTTP 200, level count matchesdepth, cache avoids second LCD call — no price/amount correctness vs on-chain math.indexer/tests/common/lcd_mock.rs: Wiremock LCD HTTP stub only (fixed pool reserves); explicitly not orderbook logic (#105).#[cfg(test)]unit tests inorderbook_sim.rs.On-chain reference (pair swap)
smartcontracts/contracts/pair/src/contract.rs:k = R_in * R_out,new_out = ceil_div(k, new_in), commission =gross * fee_bps / 10000, net return = gross − commission.docs/CG_CMC_COMPLIANCE.md§ AMM Orderbook Simulation — step formula uses(i/depth)*0.10, not the current linear 0.1%–10% interpolation.Naming confusion (documented in #105)
orderbook_sim.rs,/cg/orderbook,/cmc/orderbook/*orderbookmodule; indexerlimit-book,order-book-headtests/common/lcd_mock.rsRetail UI
OrderBookPaneluses on-chain limit book via indexer LCD proxy — out of scope for curve-walk completion.Why this is needed
gaps/GAP_1780023683.mdmark this row Stub — engineers should not treat current output as canonical.CG_CMC_COMPLIANCE.mdalgorithm ≠ implementation; completing the stub requires one normative definition and tests that enforce it.Constraints and guardrails
poolquery; fee fromfee_config(or indexerpairs.fee_bpsonly as documented fallback when LCD fee query fails).Uint128-style math (or fixed-precision decimal crate already in indexer) — nof64on token amounts. Match pairceil_divfor new output reserve.fee_bpsto gross output per hop (same formula as pair swap). Trader-specific fee discounts are out of scope for public orderbook API.docs/indexer-invariants.md).internal_err()(no raw stack). Zero/empty reserves → emptybids/asks(current behavior).[price, quantity]strings per CG/CMC; document decimal places / trimming rules.ticker_id,timestamp,bids,asks). Level values may change when fees/rounding are fixed — note in changelog for listing teams.Relevant files
indexer/src/api/orderbook_sim.rsindexer/src/api/cg.rs/cg/orderbookindexer/src/api/cmc.rs/cmc/orderbook/:market_pairindexer/src/api/mod.rsOrderbookCacheonAppStateindexer/src/lcd/LcdClient,PoolResponse,FeeConfigResponseindexer/tests/api_orderbook_lcd_mock.rsindexer/tests/common/lcd_mock.rsdocs/CG_CMC_COMPLIANCE.mddocs/indexer-invariants.mddocs/testing.md,skills/AGENTS_TESTING_P2_EPIC.mdsmartcontracts/contracts/pair/src/contract.rsgaps/GAP_1780023683.mdRecommended direction
Normative spec
CG_CMC_COMPLIANCE.md(i/depth)*10%or update the doc to match the chosen 0.1%–10% ladder — do not leave both.Pure function + unit tests
walk_amm_book(reserve_0, reserve_1, depth, fee_bps) -> OrderbookData(no async).depth=1,depth=100, zero reserves, max fraction near 10% cap, ask side never panics whendxapproachesR0.On-chain parity layer
ceil_divand fee deduction from pairexecute_swappool leg.Simulation/ wasm unit test reserves and compare indexer output within 1 wei tolerance.LCD integration
simulate_orderbook: querypool+fee_config; remove unused_poolor usepairs.fee_bpsfallback with log warning.simulate_orderbook_cachedsemantics; includefee_bpsin cache key if fee can change without reserve change.Integration tests
api_orderbook_lcd_mock.rs: assert monotonic bid prices (decreasing) and ask prices (increasing); first level < spot mid; with mock fee, levels worse than fee-free baseline.orderbook_simunit test module (no Postgres).Docs / #105
lcd_mock.rs/orderbook_sim.rspointing to this issue instead of “stub” once complete.Acceptance criteria
ceil_div(nof64on amounts).fee_bpsapplied to each simulated level consistent with pair pool swap.docs/CG_CMC_COMPLIANCE.mdand implementation match (code or doc updated with rationale).orderbook_sim(orindexerlib tests) cover bids, asks, empty pool, depth 1/100, and fee effect.api_orderbook_lcd_mock.rscover depth cap, cache, and price monotonicity / fee regression./cg/orderbookand/cmc/orderbook/*response JSON schema unchanged; OpenAPI descriptions mention AMM-simulated (not limit book).cargo testorderbook-related tests pass (api_orderbook_lcd_mock, new unit tests).Test plan — functional paths
depth=20[price, qty]non-empty stringsdepth=1divisordepth=9999(CG)bids/asks, 200poolquery (existing cache test)ticker_id/ market pairA_B_C)security.rs)fee_bps = 30mockfee_bps = 0baseline at same reservesLUNC_USTCR0Run:
cd indexer && cargo test api_orderbook_lcd_mock orderbook_sim -- --test-threads=1Test plan — attack vectors / abuse
depth=100hammeringpoolquery per TTL keyparsefailure → empty book or 500 without panicticker_idsecurity.rs/ ticker shape tests unchangeddepthorpair_addr→ separate cache entrieslimit-bookfor real FIFOAlso run:
cargo test --test security(rate limits unchanged).Verification criteria
ceil_div+ fee calculation for known reserves.cd indexer && cargo test --tests -j 1 -- --test-threads=1green.CG_CMC_COMPLIANCE.md§ AMM Orderbook Simulation matches code; QA template row 13.5.3 / 13.6.4 still accurate.gaps/GAP_1780023683.mdOrderbook sim row → Done (with note: not FIFO)./cg/orderbook?ticker_id=…&depth=5on localnet; spot-check monotonicity and that prices move withfee_bpsgovernance change.orderbook_sim.rsresolved; stub table row removed or marked complete.Out of scope
OrderBookPanelchangesRelated issues
marked as related to #105
mentioned in commit
5318382351Implementation complete (merged to
main)@brouie — please verify on your side when you have a moment.
Commit:
5318382onmain—feat(indexer): production-faithful AMM orderbook sim for CG/CMC (#210)What changed
indexer/src/api/orderbook_sim.rswith purewalk_amm_book:u128reserves, pair-styleceil_div, poolfee_bpson swap outputdocs/CG_CMC_COMPLIANCE.md:R0 * (i/depth) * 10%fori = 1..depthasset_0= base,asset_1= quote; levels[price, quantity]as decimal stringspoolon cache miss; fee from indexedpairs.fee_bps(hot path) elseget_fee_config(pair, depth, fee_bps)prefix; repeat requests skip LCD (see integration test)Docs / agents
docs/indexer-invariants.md— AMM sim + cache keydocs/CG_CMC_COMPLIANCE.md§ AMM Orderbook Simulation (fees + ceil_div)gaps/GAP_1780023683.md— row Doneskills/AGENTS_INDEXER_AMM_ORDERBOOK_SIM.md(new)skills/AGENTS_TESTING_P2_EPIC.md— stub table updatedTests run (green)
Verification checklist
/cg/orderbook?ticker_id=<known>&depth=20— 20 bids + 20 asks; bid prices decrease, ask prices increasedepth=9999capped at 100 levelspoolquery (fee from DB when pair indexed)fee_bps > 0/cmc/orderbook/LUNC_USTCmatches CG for same pair/depthLeaving issue open until sign-off.
mentioned in issue #221
marked as related to #220
mentioned in issue #222
marked as related to #221
mentioned in issue #223
marked as related to #222
marked as related to #223
mentioned in issue #224
marked as related to #224
Follow-up issues (listing API spot-check)
Opened from post-#210 compliance review:
depthOpenware semantics (total across book → 50+50 at depth=100)CG_CMC_COMPLIANCE.mdexact match to official listing specsRecommended implementation order: #221–#223 (schema fixes) → #220 (hybrid depth) → #224 (doc pass with live
curlexamples).mentioned in issue #220
Doc pass for CG/CMC listing compliance completed in #224 (main
89449a1):docs/CG_CMC_COMPLIANCE.mdspec matrix + live handler alignment; orderbook timestamps (#222) and CMC array wrapper shipped in indexer.Verification summary (GitLab #210)
Verified on worktree
verify/issue-210againstorigin/main+ LocalTerra stack (LCD:1317, indexer:3001).AMM orderbook sim (#210) — already shipped on main
Pool leg in
indexer/src/api/orderbook_sim.rsmatches acceptance criteria:u128curve walk,ceil_div,fee_bpson swap output(i / levels_per_side) * 10%perdocs/CG_CMC_COMPLIANCE.md§ AMM Orderbook Simulationorderbook_sim(manual ceil_div golden, monotonicity, fee regression, depth 1/100)api_orderbook_lcd_mock.rs(depth cap, cache, monotonicity, CG/CMC parity, hybrid limits)gaps/GAP_1780023683.md; #105 catalog points to production sim (not stub)Follow-ups #220–#224 extended listing APIs (hybrid merge, Openware depth split, timestamps, CMC array wrapper, compliance doc pass) — documented in
skills/AGENTS_INDEXER_AMM_ORDERBOOK_SIM.md.Fix merged in this pass
4af22d6—test(indexer): serialize shared Postgres seed for orderbook integrationflockonseed_db/clean_db(/tmp/cl8y-dex-indexer-test.seed.lock, overrideTEST_DB_LOCK_FILE)#[serial]onapi_orderbook_lcd_mocktestsdocs/testing.mdnote under shared PostgresManual (localnet)
curl -s "http://127.0.0.1:3001/cg/orderbook?ticker_id=EMBER_CORAL&depth=5"— 200, ms timestamp, monotonic 2+2 levels; CMC path matches.Automated (when host Postgres was healthy)
cargo test --lib orderbook— 19 passedcargo test --test api_orderbook_lcd_mock— 10 passedcargo test --test security— 19 passedLater, host
sqlxconnections to127.0.0.1:5432timed out (containerdocker execstill OK). Fullcargo test --tests -j 1not re-run locally.Reviewer checklist
cd indexer && cargo test --lib orderbook -- --test-threads=1cd indexer && cargo test --test api_orderbook_lcd_mock -- --test-threads=1cd indexer && cargo test --tests -j 1 -- --test-threads=1GET /cg/orderbook?ticker_id=<pair>&depth=20— 10+10 levels, monotonic pricesGET /cmc/orderbook/<PAIR>?depth=20— same levels, array wrapper, seconds timestampdocs/CG_CMC_COMPLIANCE.md§ AMM + Hybrid matches codegaps/GAP_1780023683.mdorderbook sim = Done@brouie — please confirm CI after
4af22d6. Leaving open until pipelinecargo test --testsis green (local host Postgres blocked full suite at end of run).Verification complete — closing #210
Re-ran full acceptance + verification criteria on
main(36b64ed+) after host Postgres was restored (postgresql-client+ Postgres container recycle).Automated (all green)
cargo test --lib orderbook -- --test-threads=1cargo test api_orderbook_lcd_mock orderbook_sim -- --test-threads=1cargo test --test api_orderbook_lcd_mock -- --test-threads=1cargo test --test security -- --test-threads=1cargo test --tests -j 1 -- --test-threads=1Acceptance criteria (issue body)
ceil_div+fee_bps(walk_amm_book,orderbook_sim.rs)docs/CG_CMC_COMPLIANCE.md§ AMM Orderbook Simulation aligned with code (#221 Openware depth split documented)/cg/orderbook+/cmc/orderbook/*schema unchanged; OpenAPI Hybrid-simulated descriptionsgaps/GAP_1780023683.mdorderbook sim row Done;docs/testing.md/ #105 catalog → production sim (not stub)4af22d6: flock on shareddex_indexer_testseed +#[serial]orderbook wiremock testsManual localnet
:3001health 200;/cg/pairsreturns seededLUNC_USTConly (integration DB state ondex_indexer)./cg/orderbook?ticker_id=LUNC_USTC→ 500 (expected: faketerra1paircontractabcpool LCD query fails per guardrail).deploy-dex-local+ healthy LocalTerra; covered byapi_orderbook_lcd_mockagainst wiremock LCD (same code path as production).Out of scope (unchanged)
Hybrid merge (#220), Openware depth (#221), timestamps (#222), CMC array (#223), doc pass (#224) — documented and cross-linked; pool leg (#210) remains in
walk_amm_book.Closing as verified on
main. Pool-only rollback:ORDERBOOK_HYBRID=0.mentioned in commit
8c69546d8cDoc pass complete (GitLab #224)
CG/CMC listing compliance doc aligned with live handlers and authoritative specs:
docs/CG_CMC_COMPLIANCE.md— spec matrix, Pro API v3 warning, hybrid-sim disclosure, compliance checklistorderbook_sim.rscurve walk — not a stub)skills/AGENTS_INDEXER_AMM_ORDERBOOK_SIM.md,docs/indexer-invariants.md,gaps/GAP_1780023683.mdRe-verified 2026-05-30 on
main@8c69546(codebase @3e7a175): live indexer + 29/29 integration tests.Tracking: #224
mentioned in issue #335