Commit Graph
170 Commits
Author SHA1 Message Date
Kevin Codex e6e5e2cadc brand: drop the assets README; each SVG carries its own source comment
The note was served publicly from /brand and referenced by nothing. The
provenance it recorded already lives in a Source comment inside every SVG,
which the UI tests assert.
2026-09-16 20:11:49 +08:00
Vasanth T f5c9400473 fix(rpc): keep malformed batch errors retryable
Viem accepts JSON-RPC error envelopes even on HTTP failures, so a single upstream error object can still crash a batched gas preflight. Return non-RPC HTTP errors for retryable failures and reject mismatched response IDs or malformed envelopes. Preserve Kevin's Arc proxy, method denials, recovery flow, and actionable error copy.

Cover real viem batching and retry behavior, keep bridge alerts within the panel, and leave unrelated local changes out. Verified 627 unit tests, 10 read-only live routes, Base/Arc approval preflights, lint, typecheck, and production build.
2026-09-16 17:33:01 +05:30
Kevin Codex 2eaa192c13 bridge: drop an unused export; record the wallet test and its findings
otherBridgeChain had no callers. docs/bridge.md now records the
maintainer's Base USDC to Arc transfer on 2026-09-16 and what the wallet
test surfaced: Phantom cannot add Arc or Robinhood, the proxy's whole-batch
403 on eth_fillTransaction, public-node rate limits, and why publicnode is
unsuitable as a proxy upstream.
2026-09-16 19:56:59 +08:00
Kevin Codex ed258b71cf rpc proxy: answer disallowed methods in place instead of failing the batch
viem probes eth_fillTransaction when estimating Base fees. The proxy replied
HTTP 403 for the whole batch, so every read in it failed with "unknown RPC
error" and viem never took its fallback path. Disallowed methods now get a
JSON-RPC -32601 error in their own slot while the rest of the batch is
forwarded; the allowlist itself is unchanged.
2026-09-16 19:45:05 +08:00
Kevin Codex 945d57134c bridge: proxy Arc reads and make the RPC proxy retry-friendly
Public Base and Arc nodes rate-limit a single quote's burst of reads. They
answer inside a 200 body, sometimes with one object where a batch array was
due, which viem cannot use ("unknown RPC error" or a TypeError in its
batch scheduler). The proxy now maps rate-limit and malformed replies to
HTTP 429/502 so viem retries with backoff, and Arc reads go through the
proxy (ARC_RPC_URL upstream, else the official node) instead of straight
from every browser. The Arc origin leaves the CSP; a dev override
NEXT_PUBLIC_RPC_URL_ARC is allowed like the other chains.
2026-09-16 19:37:35 +08:00
Kevin Codex cc5428e847 bridge: show the provider's own reason behind generic RPC errors
viem wraps unrecognised wallet/RPC error codes as "An unknown RPC error
occurred." and keeps the provider text in details. bridgeErrorMessage now
appends that text, maps the wallet's "unrecognized chain" reply to an
actionable hint, and treats any insufficient-funds cause uniformly.
2026-09-16 19:21:29 +08:00
Kevin Codex a0f59f4d93 bridge: discard re-verifies Relay status and the receipt under the lock
The observation that shows the discard control only decides visibility.
Removal now fetches a fresh provider status and, when a hash exists, the
source-chain receipt under the per-wallet lock, and keeps the record if
either shows activity. The button is disabled while that check runs.
2026-09-16 19:03:09 +08:00
Kevin Codex 1cb3c26eeb bridge: drop the design-tool artifacts (DESIGN.md, bridge-surface.md)
Neither file is read by code or tests. They are output templates from the
contributor's design tooling and duplicate theme tokens that already live in
the stylesheet. docs/bridge.md remains the bridge documentation.
2026-09-16 18:49:58 +08:00
Kevin Codex 7ec59657a5 bridge: unstick stranded records, anchor quote expiry, drop AbortSignal.any
Review fixes on the Relay bridge:

- A sped-up or cancelled-and-replaced deposit no longer blocks tracking
  forever. When the wallet's hash is unmined and Relay reports a different
  source hash, that hash is verified as this wallet's exact deposit for the
  same order and adopted.
- A record with no deposit anywhere can be discarded after 15 minutes, only
  while Relay still reports "waiting" with no hashes and the source chain
  has no receipt, observed within the last minute. Unmined approvals get the
  same bounded discard; a late-mined approval only grants the exact
  allowance every deposit re-reads.
- A wallet chain change during a quote no longer leaves the form locked on
  "Finding your route…".
- Quote validity travels as ttlMs and is anchored on the browser clock at
  request time, so device clock skew cannot expire or extend a quote.
- Fetch timeouts use a hand-linked signal instead of AbortSignal.any, which
  older in-app wallet browsers lack.
- Relay's chain catalogue is cached per fetcher for a minute instead of
  re-downloaded on every quote; an unverifiable copy is dropped.
- The USDC approval is no longer gated on the 45 s quote TTL, since a fresh
  quote is required after it anyway.
- Wallet and RPC errors go through friendlyError; the dialog states that
  Openlaunch does not operate Relay or hold funds in transit.

Unit tests cover the hash adoption rule, the quoting-lock reset, expiry
anchoring, the linked timeout signal, both discard gates and the catalogue
cache. 621 tests, lint, typecheck, build and the read-only live route suite
pass.
2026-09-16 18:35:55 +08:00
Vasanth T 81278787f3 fix(wallet): use official network logos
Replace letter placeholders with the existing official Base and Robinhood assets. Switch the Robinhood mark through theme CSS to preserve contrast without adding hydration state or changing wallet actions.
2026-09-16 14:07:56 +05:30
Vasanth T 718c8f3556 test(csp): assert exact connect-source membership
CodeQL mistook the split-array includes assertion for substring URL validation. Use Set membership for every expected origin so the test's token boundary is explicit without changing production CSP behavior.
2026-09-16 13:54:49 +05:30
Vasanth T 4ae0a6ceff feat(bridge): add Relay funding across three chains
Let users fund the same wallet across Base, Robinhood and Arc without leaving Openlaunch or deploying new contracts. Validate Relay orders and deposits, require exact USDC approvals, and preserve uncertain transfers for recovery instead of resending.

Include route, approval, recovery and UI regression tests, official asset provenance, and rollout documentation. Keep Robinhood USDC disabled because current routes fail the deposit and impact safeguards.
2026-09-16 13:39:13 +05:30
Kevin Codex c51e0ce080 Merge pull request #40 from Gitlawb/codex/input-notification-fixes
fix(app): improve launch input, fees and notifications
2026-09-15 15:32:03 +08:00
Kevin Codex bdda69282b toasts: an empty snapshot after a gap does not complete the baseline
An empty feed records nothing, so treating it as the post-gap baseline let the
next populated poll surface the missed activity. The gap stays open until a
populated snapshot is seen. (CodeRabbit)
2026-09-15 15:28:31 +08:00
Kevin Codex d8744a4489 launch form: unconfigured chains read "Coming soon" in production
The missing-contracts explanation helps a developer, but a visitor seeing a
chain that is not live yet (Arc, next) should read it as upcoming. Production
builds keep "Coming soon."; development still says the contract settings are
missing.
2026-09-15 15:21:24 +08:00
Kevin Codex 37da150854 toasts: queue at most 10 activity cards so a busy stream stays under a minute old
Cards show one at a time for 6s, so 20 queued let "just launched" and buy
cards run up to two minutes behind. Ten keeps what is on screen within about a
minute; the newest activity is kept and own confirmations are not capped.
2026-09-15 15:18:30 +08:00
Kevin Codex 55c4c7cb27 notification settings: only promise persistence when storage works
When the browser refuses storage the choice lasts for the current page only,
so the footer says so instead of "Saved in this browser". (CodeRabbit)
2026-09-15 15:04:03 +08:00
Kevin Codex 5adcaf2abc toasts: re-arm a timer that fires early instead of freezing the queue
A timeout can fire a moment before Date.now() reaches the deadline. expireToast
then returned the same state, the effect never re-ran, and the card plus
everything queued behind it (own confirmations included) stayed on screen
until dismissed. The callback now waits out the remainder. (CodeRabbit)
2026-09-15 15:04:03 +08:00
Kevin Codex 738228c8e6 toasts: a poll after a hidden-tab or offline gap is a baseline, not a replay
Polling pauses while the tab is hidden, so the first snapshot back marked
everything missed as new and queued up to 20 old activity cards, shown one at
a time for minutes. Snapshots more than 30s apart by server time now refresh
what has been seen without queueing it; live activity resumes on the next
poll. Server times are compared with each other, so client clock skew does
not matter.
2026-09-15 14:55:17 +08:00
Kevin Codex 69a53656bc notifications: live activity on by default
Live launches, buys and sells are the social proof of engagement, so a
visitor sees them unless they turn them off in notification settings. Only
an explicit saved off mutes them; a missing, unknown or cleared value falls
back to on, and the server snapshot matches that default.
2026-09-15 14:55:17 +08:00
Kevin Codex bb8b4db460 launch form: show the symbol in capitals as it is typed
Typed and pasted text is uppercased in the field itself before React sees the
change, so the caret stays put when editing mid-word and fast keystrokes land
in order. An in-progress IME composition is left as typed and uppercased once
it is committed, so candidate windows keep working.
2026-09-15 14:55:17 +08:00
Kevin Codex a6576b5ebf Merge pull request #36 from Ayush7614/fix/memo-lru-cap
fix(memo): bound the cache with per-entry TTL expiry and oldest-first eviction
2026-09-15 14:30:44 +08:00
Kevin Codex 9a6fb61829 Merge pull request #35 from Ayush7614/fix/search-correctness
fix(search): order cross-chain results by block time and escape LIKE wildcards
2026-09-15 14:23:31 +08:00
Kevin Codex e6f852249e Merge pull request #29 from Ayush7614/fix/feed-future-round-guard
fix(app): reject future-dated Chainlink rounds in feedUsd
2026-09-15 14:04:46 +08:00
Vasanth T ee45cd0101 Merge main and preserve fee splits in launch settings 2026-09-14 14:14:56 +05:30
Kevin Codex c250bec5ab Merge pull request #45 from Gitlawb/fix/beneficiary-token-side-fees
fees: show and claim the launched-token side for beneficiaries
2026-09-14 11:47:30 +08:00
Kevin Codex 1cd14c1bfd fee panel: keep pending feedback on the button that sent the transaction
The sent phase dropped which action and currency were submitted, so a claim
showed "Confirming…" on Collect instead of on its own Claim button.
2026-09-14 11:44:21 +08:00
Kevin Codex a9ca5efdc3 fees: show and claim the launched-token side for beneficiaries
Every collect pays beneficiaries both pool currencies (quote from buys, the
launched token from sells), but the fee panel and dashboard only read the
quote side. The token page now shows collected, burned and paid amounts for
both, with a Claim button per credited currency. The dashboard counts
token-side uncollected fees (a sells-only pool was not collectable) and
prices the token share into earned at the pool price, marked with ≈.
2026-09-14 11:33:41 +08:00
Kevin Codex f93cc0d845 Merge pull request #44 from Gitlawb/feat/fee-split-form
launch form: split trading fees between up to 7 beneficiaries
2026-09-13 23:52:46 +08:00
Kevin Codex 2947f5c8a5 Merge pull request #30 from Ayush7614/feat/trade-slippage-control
feat(trade): user slippage control with per-chain persistence
2026-09-13 23:50:18 +08:00
Kevin Codex 4ff3aba31f launch form: split trading fees between up to 7 beneficiaries
The locker has always accepted up to 7 recipients with bps shares, but the form
could only name one beneficiary or burn. "Someone else" is now a split editor:
address + percent rows, quick adds for the connected wallet and a burn share
(0x…dEaD), and a running total.

- lib/launchpad/recipients.ts: pure parsing and validation. Percent is parsed as
  integer bps (two decimals = one bp, finer is rejected, never rounded); shares
  must total exactly 100%; no zero address, no duplicates, 1 to MAX_RECIPIENTS rows.
- MAX_RECIPIENTS in config, pinned to LaunchLocker.sol by a test.
- Summary chip, fee tile and routing line derive from the recipients actually
  sent; an unfinished split previews as a split, never as a burn.
- Share card label says "beneficiaries" for more than one.
2026-09-13 23:40:43 +08:00
Vasanth T 309ba6775f fix(app): refine launch setup and notifications
Keep IME input stable and make community activity opt-in so market events do not crowd out personal confirmations. Clarify permanent fee routing without changing launch economics or transaction payloads.
2026-09-13 11:27:24 +05:30
Ayush7614 e043cf52ec fix(search): double backslash in ESCAPE clause so SQL receives ESCAPE '\'
JS template cooked text consumes a single backslash, so ESCAPE '\' in source was cooking to ESCAPE '' (empty escape) and the helper's backslashes were ignored. Using ESCAPE '\\' in source cooks to ESCAPE '\' in SQL, matching escapeLike('\%','\_','\\').

Verified: search.test.ts 9/9; query-construction check shows ESCAPE '\' in cooked SQL.
2026-09-13 10:45:35 +05:30
Ayush7614 97cd800945 fix(memo): guard rejection cleanup against evicted-and-replaced entry; fix TTL boundary
- Make fn().catch cleanup conditional: only delete when cached value is still the failing promise, so an evicted in-flight request that later rejects does not delete a successful replacement under the same key (reproduces at constant clock: pending -> 200 inserts evict -> reload -> old reject).
- Fix expiry check to >= so entries at exactly TTL are considered expired, matching the hit test (<) and avoiding evicting fresh entries while leaving expired ones.
2026-09-13 10:44:57 +05:30
Kevin Codex ea635bc797 Merge pull request #32 from Ayush7614/feat/posts-cursor-pagination
feat(posts): cursor pagination for token comments API
2026-09-13 09:51:09 +08:00
Kevin Codex ebe48bff3c Merge pull request #39 from Gitlawb/feat/gitlawb-burned-total
home: show the GITLAWB burned across Base and Robinhood; dollar totals say ≈ while a price is missing
2026-09-13 09:50:12 +08:00
Kevin Codex 3fa0e42ea2 home (CodeRabbit, PR #39): the GITLAWB burned tooltip carries every digit of the raw amount
fmtUnitsExact formats the raw 18-dec string with BigInt arithmetic (thousands separators, fraction trimmed
of trailing zeros), so the title never rounds through a float. The compact figure in the row is unchanged.
2026-09-13 09:41:45 +08:00
Kevin Codex 5e331ce601 Merge pull request #37 from Ayush7614/feat/write-endpoint-rate-limits
feat(security): per-IP rate limits on sync/meta/presence POST endpoints
2026-09-13 09:36:04 +08:00
Kevin Codex a203587600 Merge pull request #38 from Gitlawb/codex/codeql-cleanup
fix: harden CI permissions and triage CodeQL alerts
2026-09-13 09:33:46 +08:00
Kevin Codex 0398e999fa home: show the GITLAWB burned across Base and Robinhood; dollar totals say ≈ while a price is missing
The network breakdown gains one line: GITLAWB sent to 0x…dEaD by GITLAWB-quoted launches, one combined
figure for both chains (one supply bridged over LayerZero), shown as an amount, never in USD. It sums
fees_quote_burned over GITLAWB-quoted launches; GITLAWB is only ever the quote side, so that is the whole burn.

Along the way:
- The live poller merges totals field by field, so a poll that lands on an old machine during a rolling
  deploy keeps the last value of a newly added total instead of dropping it.
- The receipt sync path no longer writes a Burned/Paid event for a position whose launch is not indexed
  yet: such a row was pinned with token NULL and never rolled into any total (the poller's later pass hit
  ON CONFLICT and the rebuild script joins on token). It now leaves the event for the poller, which
  indexes the launch first. The rebuild script attaches any historical orphaned rows by position id.
- The dollar totals (volume, fees to recipients, fees burned) fold every quote through its USD price and
  silently counted a quote at $0 while its price was unknown (cold start, a feed down >15 min). The totals
  now carry usd_partial and the hero shows ≈ with a tooltip while that is the case.
2026-09-13 09:31:21 +08:00
Vasanth T 6b18a730af fix: address CodeQL hardening findings
Limit build-only CI tokens to read-only contents permissions.
Clarify intentional control filtering without changing signed post text,
and replace the sitemap test hostname-prefix check with exact origins.

Cover the image-preview React attribute boundary without changing its
runtime behavior or dismissing the existing scanner warning.
2026-09-12 23:13:54 +05:30
Kevin Codex 532b5eb84a Merge branch 'fix/holders-null-trader' 2026-09-12 21:55:05 +08:00
Kevin Codex 7aec314840 holders: a swap with an unknown sender no longer crashes the token page; the sync loop heals it
The indexer stores a swap with a null trader when the sender lookup fails
(a rate-limited node during a busy launch block). The holder panel then
called toLowerCase on it, the token page's error boundary replaced the
whole page, and /api/launch/holders returned 500 for that token.

- sniperSummary / creatorActivity skip swaps without a trader
- the sender lookup retries once before giving up
- healSwapTraders re-reads a bounded batch of null-trader swaps every poll
2026-09-12 21:53:25 +08:00
Ayush7614 d5cabbe35a feat(security): per-IP rate limits on sync/meta/presence POST endpoints
- 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)
2026-09-12 18:34:50 +05:30
Ayush7614 ec30ade410 fix(memo): bound the cache with per-entry TTL expiry and oldest-first eviction
- the old sweep only deleted expired entries, so a burst of fresh
  request-controlled keys (candle buckets, per-limit list keys) grew the map
  without limit inside one TTL window
- expiry now uses each entry's own TTL; overflow evicts expired first, then
  oldest; fresh hits refresh recency so hot keys survive cold bursts
- new memo.test.ts: hits, rejection retry, in-flight sharing, cap, LRU, TTL
2026-09-12 18:34:13 +05:30
Ayush7614 b6f5230969 fix(search): order cross-chain results by block time and escape LIKE wildcards
- searchLaunches pre-limit and JS tiebreak used raw block numbers across
  chains, hiding exact matches on low-height chains; both now use block
  time (chain id, block number tiebreaks), matching the newestFirst invariant
- findLaunchChain picks the newest row by block time, not height
- escape %/_ in ILIKE patterns (ESCAPE '\') so they match literally
- compareSearchHit + escapeLike are pure and unit-tested
2026-09-12 18:32:44 +05:30
Ayush7614 bc58393031 fix(trade): keep safety-harness sync prefix dependency-free; slippage fallback on preflight fail (PR #30 CI)
- declare tradeSlippageBps outside try, assign after preflight awaits
- catch uses it when set, else default (preflight errors are never slippage reverts)
2026-09-12 18:19:16 +05:30
Ayush7614 5e0e3ae5ef fix(posts): keep 100-post default so cursor pages do not hide discussions (PR #32)
- default 50 truncated 75-comment threads and orphaned 1 parent + 50 replies
- default 100 matches previous response; callers without params lose nothing
- correct prior capped-at-100 history (not unbounded) in docs
2026-09-12 18:00:15 +05:30
Ayush7614 94d8a51787 fix(trade): validate slippage raw input and report actual tolerance on errors (PR #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
2026-09-12 17:57:36 +05:30
Ayush7614 fc7b3861b8 fix(eth-price): sample clock after Chainlink read so fallback rounds are not rejected as future (PR #29)
- fromChainlink takes injected now() and samples after await feedFn()
- refresh stamps cache from completion time
- regression test: slow Coinbase failure + round published mid-request returns 2441.34
2026-09-12 17:56:23 +05:30