Integrators: accurate hybrid trade volume reporting and reconciliation docs #216
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#216
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
CoinGecko / CoinMarketCap integrators and Vyntrex-style aggregators need trustworthy, documented hybrid swap volume semantics. On-chain wasm attrs and indexer DB columns exist (#82, consolidated CG/CMC in #189), but end-to-end accuracy and integrator-facing guidance remain partial — see gap analysis
gaps/GAP_1780023683.md§6.3.Current codebase
On-chain (pair contract)
Hybrid swaps (Pattern C: pool + limit book in one tx) emit Terraport-compatible baseline wasm attrs plus CL8Y leg breakdown:
offer_amount/return_amountspread_amount/commission_amountbook_commission_amountpool_return_amount/book_return_amountreturn_amount= sumlimit_book_offer_consumedeffective_fee_bpsPer-maker fills also emit separate
limit_order_fillwasm events (not duplicated in baselinecommission_amount).Indexer
swap_eventscolumnspool_return_amount,book_return_amount,limit_book_offer_consumed,effective_fee_bps(migrationindexer/migrations/20260326000001_limit_order_fills.sql); parser inindexer/src/indexer/parser.rs.GET /api/v1/pairs/{addr}/tradesreturns hybrid columns onTradeResponse(indexer/src/api/pairs.rs).offer_amount/return_amount; optionalcl8y_extensionson tickers/summary (hybrid_trade_count_24h,book_leg_volume_quote_24h, etc.) viaindexer/src/api/consolidated_stats.rsandget_24h_hybrid_breakdowninindexer/src/db/queries/swap_events.rs; per-tradepool_leg_volume/book_leg_volumeon historical trade feeds (indexer/src/api/cg.rs,cmc.rs).total_volumeaggregate fromswap_eventsoffer/return totals, not from summinglimit_order_fills(by design — avoids double-count).indexer/tests/swap_events_hybrid_columns.rs,indexer/tests/api_consolidated_reporting.rs; invariant row indocs/indexer-invariants.md.Documentation (partial)
docs/integrators.md§ Vyntrex / Terraport (GitLab #189).docs/CG_CMC_COMPLIANCE.md§ Consolidated hybrid + pool-only reporting.Why this is needed
limit_order_fillsandswap_events, or that use pool-onlycommission_amountas “volume,” will misstate hybrid activity.volume_usd, candles, leaderboards, andtoken_volume_statsinherit consolidated swap rows; integrators need explicit rules for when USD/leg attribution is valid vs unknown.Constraints and guardrails
swap_eventsconsolidatedoffer_amount/return_amount, not again by summinglimit_order_fillsfor the same tx.commission_amount/spread_amounton swaps to include book leg (breaks Vyntrex baseline parsers); use extension attrs and indexer columns.book_return_amount,pool_return_amount, CGpool_leg_volume/book_leg_volume) vs offer-side (limit_book_offer_consumed,offer_amount).commission_amountis total (pool+book); swap attrcommission_amountis pool-only — integrator docs must not conflate them (docs/integrators.md).Relevant files
smartcontracts/contracts/pair/src/contract.rs(swap execution + attrs)smartcontracts/packages/dex-common/indexer/src/indexer/parser.rsindexer/src/db/queries/swap_events.rs,volume.rs,indexer/src/indexer/candle_builder.rs,trader_tracker.rsindexer/src/api/consolidated_stats.rs,cg.rs,cmc.rsindexer/src/api/pairs.rs,text_csv.rsindexer/src/db/queries/limit_order_fills.rs,indexer/src/api/pairs.rs(limit-fills)docs/integrators.md,docs/CG_CMC_COMPLIANCE.md,docs/limit-orders.md,docs/terraport.md,docs/indexer-invariants.mdindexer/tests/api_consolidated_reporting.rs,swap_events_hybrid_columns.rsfrontend-dapp/src/types/index.ts,TradesTable.tsxgaps/GAP_1780023683.md,docs/reviews/20260409T030009Z/ISSUE_BACKLOG.mdRecommended direction
docs/integrators.mdordocs/integrators-hybrid-volume.mdlinked from README/docs index):swap_events; leg attribution → optional columns; maker-level detail →limit_order_fillsonly when not already counted in parent swap.return_amount)./api/v1mapping in one table.get_24h_hybrid_breakdownleg sums use the same asset side as CGbook_leg_volume/pool_leg_volume; align pair stats / overview if any endpoint exposes misleading partial volumes.pool_leg_volume/book_leg_volumeon/api/v1/pairs/{addr}/tradesfor parity with CG/CMC; documentbook_commission_amountin OpenAPI if parsed/stored.docs/CG_CMC_COMPLIANCE.mdand Terraport comparison (docs/terraport.md) to the reconciliation guide.Acceptance criteria
docs/CG_CMC_COMPLIANCE.mdanddocs/indexer-invariants.mdlink to the guide; Terraport mapping table references volume reconciliation.pool_return_amount + book_return_amount = return_amount(within rounding) is asserted in tests; documented behavior when attrs missing.cl8y_extensions24h leg volumes are documented as ask-side (quote/target) raw units (or corrected in code if audit finds mismatch).limit_order_fillsinto pair volume, using pool-onlycommission_amountas volume, counting parked/expired placements as trade volume./api/v1/pairs/{addr}/tradesexposes leg volume aliases consistent with CG/CMC if audit recommends parity.Test plan — functional paths
swap_eventsrow; null leg columns; consolidated volume =offer_amount; CG ticker counts aspool_only_trade_countreturn_amount= pool + book legs; CG trade haspool_leg_volume+book_leg_volume; extensions counts hybrid +1limit_order_filleventsswap_eventsrow; multiplelimit_order_fillslinked viaswap_event_id; headline volume still single rowswap_events_hybrid_columns.rsapi_consolidated_reporting.rscl8y_extensionsmatches seeded hybrid row; standard volumes unchanged/api/v1/pairs/{addr}/tradestext_csv.rs/ download pathvolume_quote/volume_baseuse consolidated amounts, not leg double-countvolume_aggregatorjobtoken_volume_statssumsoffer_amountonce per swaptotal_volumeincrements by consolidated offer (or documented rule), not per-fill sumasset_1_idbase_volume/target_volumeorientation matches compliance docTest plan — attack vectors / abuse scenarios
tx_hashtrade_exists/ ON CONFLICT prevents duplicateswap_eventsreturn_amountmust equal sum of legs; contract rejects inconsistent settlementcl8y_extensionsafter reorgindexer/tests/security.rspatternsoffer_amount/return_amount; legs omitted, not"0"fake attributioncompute_volume_usdbook_leg_volume_quote_24h+pool_leg_volume_quote_24h+ standard volumetarget_volumeVerification criteria
cd indexer && cargo test swap_events_hybrid_columns api_consolidated_reporting --testspasses.make check-fee-discount-tier-docs(if fee bps examples touched) — N/A otherwise.make test-e2e-tx/hybrid-swap.spec.tspath), query/cg/tickers,/cg/historical_trades,/api/v1/pairs/{addr}/trades; confirm leg sum equalsreturn_amountand extensions match.docs/CG_CMC_COMPLIANCE.mdupdated with link to reconciliation guide.Related issues
Priority
P1 — integrator/listings trust; unblocks honest CG/CMC and Vyntrex volume reporting without waiting for full hybrid routing product work.
Labels
indexer,docs,hybrid,integratormentioned in commit
2097452008Implemented (#216) — merged to
main@2097452Delivered integrator-facing hybrid volume reconciliation (reporting + docs + API parity), without changing consolidated volume totals or Terraport baseline wasm attrs.
What changed
pool_return_amount + book_return_amount = return_amountwhen legs indexed.GET /api/v1/pairs/{addr}/tradesnow exposespool_leg_volume/book_leg_volume(CG/CMC aliases); CSV export includes the same columns.CG_CMC_COMPLIANCE.md(listing sign-off checklist),integrators.md,terraport.md,docs/README.md, gap analysis §6.3.Tests run (pass)
Verification checklist (please confirm)
/cg/tickerscl8y_extensionsleg sums are ask-side attribution, not added totarget_volume./cg/historical_tradesand/api/v1/pairs/{addr}/tradesshowpool_leg_volume+book_leg_volumesumming toreturn_amount."0"); headline volume still fromoffer_amount/return_amount.limit_order_fillsinto pair headline volume.@brouie — could you verify the checklist above (docs + indexer API) when you have a moment? Leaving this issue open until sign-off.
/cc @PlasticDigits
Verification complete (agent, 2026-05-29)
Verified GitLab #216 on
main@13fef65(implementation landed in2097452). Worktreeverify/issue-216had no additional code changes — reconciliation guide, L10 invariant, internal trades leg aliases, and tests were already merged.What was verified
cargo test --test swap_events_hybrid_columns --test api_consolidated_reporting --test api_integrator_hybrid_volume— 7/7 passedGET /api/v1/pairs/{addr}/tradesexposespool_leg_volume/book_leg_volume(CG/CMC aliases)543D8DFF…: on-chainpool_return_amount=0,book_return_amount=5202750,return_amount=5202750; indexer trade id 3506 matches;pool_leg_volume+book_leg_volume=return_amount;/cg/tickershybrid_trade_count_24hincremented/trade/{pair}loads order book + recent trades against live indexer (leg breakdown in retail UI remains optional/out of scope per issue)Checklist for operators / integrators
swap_eventsoffer_amount/return_amount(or CGbase_volume/target_volume) once per taker tx.limit_order_fillsnotionals on top of parent swaps.cl8y_extensions.*_leg_volume_quote_24has ask-side attribution, not additive totarget_volume.pool_return_amount + book_return_amount = return_amount(ask-side).cd indexer && cargo test --test swap_events_hybrid_columns --test api_consolidated_reporting --test api_integrator_hybrid_volumescripts/e2e-seed-hybrid-book.sh) + hybrid swap; query/cg/tickers,/cg/historical_trades,/api/v1/pairs/{addr}/trades.Closing as all acceptance criteria and verification items from the issue body pass on current
main.mentioned in issue #337
mentioned in issue #544
marked as related to #631
mentioned in issue #631
mentioned in issue #707