Frontend: fee-discount registry outage warning for traders (#374) #893
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!893
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "issue-374-fee-discount-registry-warning"
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 #374 — non-blocking Swap banner when registered traders may be charged full pair fee because the fee-discount registry LCD is unreachable or the indexer reports registry downtime.
feeDiscountRegistryWarning.ts:resolveFeeDiscountRegistryStatusdistinguishesunregisteredvsregistry_unreachablevsregistered;shouldShowFeeDiscountRegistryWarninggates the banner.SwapPage.tsx: Amberrole="status"banner (swap-fee-discount-registry-warning); polls indexer health every 30s whenFEE_DISCOUNT_CONTRACT_ADDRESSis set; Hold CL8Y… CTA only for confirmed unregistered wallets.GET /api/v1/health/fee-discount: narrow LCDconfigprobe returning{ configured, fee_discount_registry_ok }(no per-trader data, no raw LCD errors).docs/frontend.md,skills/AGENTS_FEE_DISCOUNT_TIERS.md§ Registry outage observability.Swap submit stays enabled when the warning is shown (on-chain fail-closed to full fee unchanged).
Acceptance checklist
get_registration/get_discountLCD → non-blocking outage warning on Swapcd frontend-dapp && ./node_modules/.bin/vitest run src/pages/SwapPage.test.tsx -t "registration LCD fails"fee_discount_registry_ok: false→ same warning even if LCD reads succeedcd frontend-dapp && ./node_modules/.bin/vitest run src/pages/SwapPage.test.tsx -t "indexer reports registry down"cd frontend-dapp && ./node_modules/.bin/vitest run src/pages/SwapPage.test.tsx -t "Hold CL8Y CTA"getByRole('button', { name: /^Swap$/i })enabledmake test-frontend(or vitest onfeeDiscountRegistryWarning.test.ts+SwapPage.test.tsx)make setup-cloud-localterra+ pause registrycurl http://127.0.0.1:3001/api/v1/health/fee-discountafter indexer startThird-party verification
On Swap with a connected wallet: banner
data-testid="swap-fee-discount-registry-warning"appears only forregistry_unreachable; unregistered wallets see Hold CL8Y… instead.Related
changed the description
changed the description
Cursor Bugbot has reviewed your changes using default effort 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
16f31c3d35. Configure here.Health query never polls
Medium Severity
feeDiscountHealthQuerysetsstaleTime: 30_000but norefetchInterval. With app-widerefetchOnWindowFocus: false, indexer registry health is fetched once per mount, so the outage banner may stay after the registry recovers until the user leaves Swap.Reviewed by Cursor Bugbot for commit
16f31c3d35. Configure here.added 1 commit
8160805f- fix(frontend): poll fee-discount health every 30s on SwapCompare with previous version
Security review
Commit reviewed:
16f31c3d35045892550e9a1afce8f3fc98d4f8c2Scope: Frontend fee-discount registry outage banner (
feeDiscountRegistryWarning.ts,SwapPage.tsx, indexer client), new indexerGET /api/v1/health/fee-discount, tests and docs.Outcome:
FINDINGS: 0medium+ — Security review: no medium+ findings on this diff.Summary
Reviewed added/modified paths for injection, authz bypass, secret leakage, SSRF/XSS, unsafe deserialization, and new attack surface. No plausible medium-or-higher exploit path was identified.
fee_discount_addresswith fixed{"config":{}}query — no user-controlled URL/contract/path. Response is two booleans only (no raw LCD errors or per-trader data). Standard API rate limit applies (rate_limit_rps).FEE_DISCOUNT_REGISTRY_WARNING_TEXT) rendered as text — no attacker-controlled HTML/JS sink.getFeeDiscountHealth()parses JSON; status logic uses strict=== true/=== falseon known fields. Failed health fetch is ignored (indexerHealth: null), falling back to LCD error signals only.Inline threads: none (no medium+ findings).
Prior security-review comments on !893: none found.
changed the description
resolved all threads
added 92 commits
main44d73ee4- Merge origin/main into issue-374-fee-discount-registry-warningCompare with previous version
Resolved merge conflicts with
main.Conflicts resolved
feeDiscountRegistryWarning.ts— kept #374 nuanced status resolution (unregistered vsregistry_unreachablewhen indexer is down) on top of main's input types andconsecutive_lcd_failureshealth snapshot (#373).SwapPage.tsx— kept #374 top-level outage banner (swap-fee-discount-registry-warning), 30s health polling, and Hold CL8Y CTA only for confirmedunregistered; removed duplicate in-card warning from main.indexer/src/api/fee_discount_health.rs+ tests — kept main's cachedFeeDiscountRegistryHealthprobe (#373).client.ts— deduplicatedgetFeeDiscountHealthexport; response includesconsecutive_lcd_failures.Sanity checks
vitestfee-discount / SwapPage banner tests: passMerge commit:
44d73eechanged the description
Security review
Commit reviewed:
44d73ee47ceefe87dd8a52fc469d5482d3f37332Scope: MR !893 diff —
feeDiscountRegistryWarning.ts,SwapPage.tsx(outage banner + 30s health poll), indexer client E2E timeout tweak, tests, docs. Consumes existing read-onlyGET /api/v1/health/fee-discount(added in #373, not modified here).Outcome:
FINDINGS: 0medium+ — Security review: no medium+ findings on this diff.Summary
Re-reviewed after merge with
mainand the polling fix (refetchInterval: 30_000). Traced attacker-controlled inputs through the new paths; no plausible medium-or-higher exploit was identified.FEE_DISCOUNT_REGISTRY_WARNING_TEXT; no LCD errors, wallet addresses, or indexer JSON interpolated into DOM. React text escaping applies.getFeeDiscountHealth()fetches a fixed path; response fields are used only as boolean/number predicates in status logic — never rendered. Failed health fetch yieldsindexerHealth: null(fail-open on ops signal only).INDEXER_URLis build-time env (same trust model as other indexer calls)./tierslink; gated on confirmedunregisteredstatus from successful LCD read.Inline threads: none (no medium+ findings).
Prior review on
16f31c3dremains valid; this pass confirms the post-merge polling fix does not introduce new attack surface.mentioned in commit
a17df69fcb