feat: pair search combobox with relevance + liquidity ranking (#314) #792
No reviewers
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!792
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "cursor/gitlab-issue-workflow-da3d"
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
Implements GitLab #314 — searchable pair combobox on Trade and Limit Orders with indexer-backed relevance ranking and 24h volume tie-break.
https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/work_items/314
Indexer
sort=relevance, default whenqpresent): exact pair address / pair-symbol match (5) → token contract/denom (4) → symbol (3) → name (2) → substring (1)ORDER BY relevance DESC, volume_quote DESC, idLUNC USTC,LUNC/USTC)list_pairs_relevance_orderingFrontend
PairSearchSelectcombobox (role=combobox, debounced ≥300ms, min 2 chars unlessterra1…address)MenuSelectdropdownvolume_24h desc)Docs
docs/frontend.md§ Pair search combobox invariantsAcceptance checklist
list_pairs_relevance_ordering(LUNC query)PairSearchSelectusessort=volume_24hwhenqemptycargo test --test api_pairs list_pairs_relevance_orderingmake test-frontendgreenmake test-frontend(832 tests)Verification for third parties
Manual: deploy LocalTerra stack, open
/tradeand/limits, search by pair address, token address, symbol, name, andSYMBOL_A SYMBOL_B; confirm volume-ordered results within tier.Blockers
Manual LocalTerra matrix and Lighthouse/a11y spot check were not executed in the cloud agent environment. Issue stays open until manual QA on a deploy with ≥6 pairs.
changed the description
changed the description
mentioned in issue #314
changed the description
Stale Security Review comment
Stale Security Review comment
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issues.
Reviewed by Cursor Bugbot for commit
5a873ad3d2. Configure here.E2E pair index order mismatch
Medium Severity
selectLimitPairByFactoryIndexclicksgetByRole('option').nth(factoryIndex), butfactoryIndexis the factory LCDpairsarray index while the combobox lists options by indexer 24h volume. With multiple factory pairs, E2E can select the wrong market.Reviewed by Cursor Bugbot for commit
5a873ad3d2. Configure here.Premature no-match empty state
Low Severity
The list shows “No pairs match your search” whenever
debouncedSearchis non-empty andoptionsis empty, even whenisPairSearchQueryReadyis false so the indexer query is disabled. A single-character query never runs but still gets the no-results message.Reviewed by Cursor Bugbot for commit
5a873ad3d2. Configure here.Security review
Commit reviewed:
5a873ad3d2c35639e731b389cc06a91459154675Scope: Pair search combobox (
PairSearchSelect) on Trade/Limits; indexersort=relevance+ expandedqfiltering; docs and tests.Outcome:
FINDINGS: 0medium+Areas reviewed
indexer/src/db/queries/pairs.rs,indexer/src/api/pairs.rs)q/asset/ sort values are passed only viasqlx::QueryBuilder::push_bind; SQL identifiers (a0,a1,p) are hardcoded. No injection path found.PairSearchSelect.tsx){opt.label},formatNum(...)); nodangerouslySetInnerHTMLor HTML interpolation.onChangefires only from listboxselectIndexon factory-gated options (factorySet.has(p.pair_address)). Non-factory indexer rows are dropped before display.qtruncated to 128 chars;limitclamped (frontend uses 20); global indexer rate limiting applies to/api/v1/pairs; combobox debounces ≥300ms. RelevanceORDER BYis heavier than prior sorts but remains bounded public read traffic.Inline threads
None — no medium+ issues to anchor on specific diff lines.
Automated security review (MR open webhook).
changed this line in version 2 of the diff
added 1 commit
eea6b346- Fix pair search E2E selection and premature empty stateCompare with previous version
changed the description
resolved all threads
resolved all threads
Stale Security Review comment
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.
Reviewed by Cursor Bugbot for commit
eea6b34662. Configure here.Label treated as search query
Medium Severity
When a pair is selected, closing the combobox copies the full menu label into
searchText/debouncedSearch, anduseIndexerSearchstays enabled becausedebouncedSearch.length > 0even while closed. Reopening callsgetPairswith that label asq(relevance sort) instead of an empty high-liquidity list, which can show wrong results or “No pairs match your search.”Reviewed by Cursor Bugbot for commit
eea6b34662. Configure here.added 1 commit
e30c3eeb- fix: stop pair combobox label from triggering indexer search when closedCompare with previous version
changed the description
resolved all threads
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issues.
Reviewed by Cursor Bugbot for commit
e30c3eebe7. Configure here.Empty query shows factory order
Medium Severity
With an empty search query, the list shows the first factory pairs while the indexer request is in flight, instead of waiting for volume-sorted results. Users can pick from that interim list before high-liquidity ordering arrives, contradicting the empty-query volume default.
Reviewed by Cursor Bugbot for commit
e30c3eebe7. Configure here.Enter picks wrong pair
High Severity
When the active pair is not among the combobox options (e.g. deep-linked low-volume pair outside the top 20 indexer results),
selectedIndexis -1 and keyboard focus defaults to index 0. Pressing Enter always callsonChangefor that row, so Trade can navigate away from the intended pair without an explicit user choice.Reviewed by Cursor Bugbot for commit
e30c3eebe7. Configure here.added 1 commit
0aab8a7a- fix(PairSearchSelect): keep current pair on Enter and wait for volume-sorted resultsCompare with previous version
changed the description
resolved all threads
resolved all threads
Security review
Commit reviewed:
0aab8a7abd6af4795e4de19fd79b176dd1c7244eScope: Pair search combobox (
PairSearchSelect) on Trade/Limits; indexerGET /api/v1/pairsrelevance sort and expandedqfiltering; follow-up fix for Enter-key / empty-query loading behavior.Outcome:
FINDINGS: 0medium+Areas reviewed
indexer/src/db/queries/pairs.rs,indexer/src/api/pairs.rs)sqlx::QueryBuilder::push_bindonly; sort is allowlisted;qtruncated to 128 chars. No injection path.PairSearchSelect.tsx)dangerouslySetInnerHTML.onChangeonly viaselectIndexon options built from factory-gated indexer rows (factorySet.has) or factory fallback; current pair prepend requiresfactorySet.has(value).0aab8a7)limitclamped server-side; combobox useslimit=20, 300ms debounce; global indexer rate limits apply. RelevanceORDER BYis heavier but bounded public read traffic.Prior review
Re-checked against the earlier review on
5a873ad3(alsoFINDINGS: 0). Bugbot threads on Enter-key and empty-query ordering are UX/safety fixes, not medium+ security issues on re-test at0aab8a7.Inline threads
None — no medium+ issues to anchor on specific diff lines.
Automated security review (MR update webhook).
Security review
Commit reviewed:
0aab8a7abd6af4795e4de19fd79b176dd1c7244eScope: Pair search combobox (
PairSearchSelect) on Trade/Limits; indexerGET /api/v1/pairsrelevance sort and expandedqfiltering; follow-up fixes for Enter-key selection, closed-label query gating, and empty-query loading.Outcome:
FINDINGS: 0medium+Areas reviewed
indexer/src/db/queries/pairs.rs,indexer/src/api/pairs.rs)q/asset/ sort values usesqlx::QueryBuilder::push_bindonly; SQL identifiers (a0,a1,p) are hardcoded;sortis allowlisted;qtruncated to 128 chars. No injection path.PairSearchSelect.tsx,pairMenuOptions.ts)dangerouslySetInnerHTML. Indexer-returned symbols/names are escaped by React.onChangeonly viaselectIndexon options built from factory-gated indexer rows (factorySet.has) or factory fallback; active pair prepend requiresfactorySet.has(value). Trade deep links validated viaisKnownFactoryTradePair; limit placement requiresselectedPairfrom factory list.0aab8a7)limitclamped server-side (frontend uses 20);qcapped at 128 chars; combobox debounces ≥300ms; global indexer rate limits apply. RelevanceORDER BYis heavier but bounded public read traffic.Prior review
Re-checked against earlier reviews on
5a873ad3and0aab8a7(bothFINDINGS: 0). No new medium+ issues on this MR update.Inline threads
None — no medium+ issues to anchor on specific diff lines.
Automated security review (MR update webhook).
Security review
Commit reviewed:
0aab8a7abd6af4795e4de19fd79b176dd1c7244e(MR head; webhook referencede30c3eeb)Scope: Pair search combobox (
PairSearchSelect) on Trade/Limits; indexerGET /api/v1/pairsrelevance sort and expandedqfiltering; follow-up fixes (e30c3eeb,0aab8a7) for closed-label query gating, Enter-key selection, and empty-query loading.Outcome:
FINDINGS: 0medium+Areas reviewed
indexer/src/db/queries/pairs.rs,indexer/src/api/pairs.rs)q/asset/ sort usesqlx::QueryBuilder::push_bindonly; table aliases (a0,a1,p) are hardcoded;sortis allowlisted;qtruncated to 128 chars. No injection path.PairSearchSelect.tsx,pairMenuOptions.ts)dangerouslySetInnerHTML.onChangeonly from listboxselectIndexon factory-gated options (factorySet.has); active pair prepend requiresfactorySet.has(value). Trade routes still gated byisKnownFactoryTradePair.0aab8a7)limitclamped (max 100; UI uses 20);qcapped; combobox debounces ≥300ms; global indexer rate limits apply. RelevanceORDER BYis heavier but remains bounded public read traffic.Prior reviews
Re-checked prior security reviews on
5a873ad3and0aab8a7(bothFINDINGS: 0). Bugbot threads on E2E ordering, label-as-query, Enter-key, and empty-query loading are UX/correctness fixes, not exploitable authz or injection issues at current head.Inline threads
None — no medium+ issues to anchor on specific diff lines.
Automated security review (MR update webhook).
mentioned in commit
43c56c4ea5mentioned in issue #328
mentioned in merge request !811