Skip to content

feat(trade): per-chain slippage control + per-IP write rate limits - #42

Open
Ayush7614 wants to merge 5 commits into
Gitlawb:mainfrom
Ayush7614:feat/slippage-and-write-limits-v2
Open

feat(trade): per-chain slippage control + per-IP write rate limits#42
Ayush7614 wants to merge 5 commits into
Gitlawb:mainfrom
Ayush7614:feat/slippage-and-write-limits-v2

Conversation

@Ayush7614

Copy link
Copy Markdown
Contributor

TradePanel hardcoded 1% slippage (too tight on fresh launches, too loose for large size) and three unauthenticated write routes had no per-IP limits.

This PR:

  • Slippage control (trade-slippage.ts, TradePanel.tsx): presets 0.5%/1%/3% plus custom 0.1–20% input, per-chain persistence via localStorage, clamping, decimal-comma normalization, validation of raw input (PR feat(trade): user slippage control with per-chain persistence #30: minus/letters not stripped to valid, comma → dot), external store with server snapshot so hydration matches. Quote and Minimum received use the selected bps; errors surface the actual slippage via friendlyError({slippagePct}). 8 unit tests in trade-slippage.test.ts (presets, clamp, parseSlippageInput/Field, format, storage key, bounds, external store).
  • Write rate limits (api/launch/sync|meta|presence): per-IP token-bucket via shared rateLimited in editServer.ts — sync 10/min (most expensive, fans out over chains), meta 20/min (unsigned, only spam defense), presence 30/min (UA-controlled hash would mint rows per rotated UA). Limits run before any DB/RPC work and return 429 slow down like sibling routes; presence keeps bot short-circuit before the bucket, sync keeps 400 shape validation. 5 structural tests in write-limits.test.ts pin the wiring and order.

Verified on upstream/main base:

  • npx tsc --noEmit -p .: pass
  • npm run lint: pass
  • npx tsx --conditions=react-server --tsconfig ./tsconfig.test.json --test src/lib/launchpad/trade-slippage.test.ts src/app/api/write-limits.test.ts: 13/13 pass
  • npm run build: pass

TradePanel hardcoded 1% slippage: too tight on fresh launches (avoidable
reverts) with no override. Add 0.5/1/3% presets plus custom 0.1-20% input,
persisted per chain, wired into minOut and Minimum received. Default stays
1% so existing behavior is unchanged unless the user picks otherwise.

New pure module trade-slippage.ts (presets, parse/clamp/format, external-
store with server snapshot so hydration never mismatches) with 7 unit
tests.
…deRabbit, PR Gitlawb#30)

parseSlippageInput("0.01") passed validation then clamped to 10bps,
silently changing the selection to 0.1%. Reject anything below
SLIPPAGE_MIN_BPS so the field keeps the previous value and shows the
0.1-20% hint.
…n errors (PR Gitlawb#30)

- parseSlippageField rejects minus/letters, normalizes decimal comma to dot
- input handler no longer strips chars before parsing (0,5 no longer becomes 5%)
- trade captures slippageBps per transaction and passes it to friendlyError
… fallback on preflight fail (PR Gitlawb#30 CI)

- declare tradeSlippageBps outside try, assign after preflight awaits
- catch uses it when set, else default (preflight errors are never slippage reverts)
- sync had no limit despite being the most expensive route (tx-less calls fan
  out over every chain); 10/min per IP
- meta is unsigned by design, so the IP bucket is the only spam defense;
  20/min per IP before validation
- presence hashes caller-controlled UA into a DB row per variant; 30/min per
  IP after the bot short-circuit
- write-limits.test.ts pins the wiring (429 shape, limit-before-work order)
@coderabbitai

coderabbitai Bot commented Sep 13, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 59 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

This review ran on the open-source allowance, not this organization's plan, because the pull request author doesn't have an assigned seat. Waiting won't change this — ask an organization admin to assign them a seat, or add seats in Billing if every seat is already assigned, then retry.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 7573ef0b-0c82-499c-8f16-9315d6646261

📥 Commits

Reviewing files that changed from the base of the PR and between ea635bc and a2d75ec.

📒 Files selected for processing (7)
  • app/src/app/api/launch/meta/route.ts
  • app/src/app/api/launch/sync/route.ts
  • app/src/app/api/presence/route.ts
  • app/src/app/api/write-limits.test.ts
  • app/src/components/launchpad/TradePanel.tsx
  • app/src/lib/launchpad/trade-slippage.test.ts
  • app/src/lib/launchpad/trade-slippage.ts

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant