86 Commits
Author SHA1 Message Date
zeekay 5d1038aa06 the fee panel appears when there is something in it
While the split is off every figure in this panel is a zero, and it spent the
top of the explorer's landing page explaining why: a status tag reading "Not
active", two zero counters, a third card for the coinbase, and a line promising
a chart later. A reader arriving to look up a block met a paragraph about a
feature that is not running.

It renders when the split is active and not otherwise, which also deletes the
inactive/scheduled/unknown copy, the fallback styling and the empty-chart note —
the states existed only to describe an absence.
2026-08-10 21:18:00 -07:00
zeekayandHanzo Dev 6f80c0ce4e fix(explore): the explorer's own token sheet is the umbrella's
styles/tokens.css was a 494-line FORK of @luxfi/ui/tokens.css, which is how it
drifted its own browns: --color-status-warn #B45309 / #FBBF7A and the whole
Chakra orange + yellow badge ramp (#FEEBCB #FFFAF0 #DD6B20 #FFFFF0 #D69E2E
#FEFCBF #B7791F #C05621 #7B341E #744210 #FAF089). It imports the umbrella now
and adds nothing of its own.

next.config.js hand-listed SEVEN of the engine's 55 packages in
transpilePackages and deduped none of them, which is how this app's store holds
seven physical copies of @hanzogui/popper (3.0.0, 3.0.1, 3.0.2 x3, 7.3.0 x2). A
context published at module scope is per-copy, so PopperAnchor read the empty
default and called refs.setReference on undefined once per tooltip trigger. It
uses withLuxUi now — the one place that wiring lives.

47 files reached for Tailwind's chromatic ramps directly (108 occurrences).
They resolve through tokens now, under short semantic names registered in the
@theme block: text-good / text-bad / text-warn, where warn is ACHROMATIC —
attention in Lux is the loudest neutral, not a hue. The Quasar certificate
tooltip stops naming colours it no longer paints ("BLS (green)", "Corona
(blue)", "ML-DSA (purple)") — copy that describes a palette has to change with
it.

Measured on the rendered pages: warm 0%, tinted-neutral 0.0003%, mean chroma
0.004 (/) and 0.003 (/txs) at 1440x900, 0.000 at 390x844, both modes; zero
uncaught setReference errors.

Two pre-existing defects surfaced because lint-staged now lints these files and
are fixed here rather than skipped: `Box` was used but never imported in
AddressEntity.pw.tsx, and eight lines already exceeded the 160-column limit.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 19:14:51 -07:00
zeekayandHanzo Dev 86cfb45d2c fix: declare CSS side-effect imports for TypeScript 7 (TS2882)
TypeScript 7 reports TS2882 for a stylesheet side-effect import with no type
declaration; TS 5.x accepted them silently. Bundlers resolve stylesheets through
their own loaders, so the import never reaches the TypeScript module resolver —
this declares them legitimate rather than giving them a shape.

MEASURED, not assumed: this repo reports TS2882 under tsc 7 without the file and
zero with it. Repos where a framework already ships ambient CSS declarations
(Next's next-env.d.ts) were left alone — the declaration is inert there and was
not added.

Co-Authored-By: Hanzo Dev <[email protected]>
2026-07-27 18:24:48 -07:00
zeekayandHanzo Dev 521e47ab47 fix(explore): a failed validator read printed 0, not "unknown"
/validators reported "0 validators / 0 LUX staked" about a network running
five with 2,500,000,000 LUX bonded. Measured now against the live P-Chain:

  POST https://api.lux.network/ext/bc/P platform.getCurrentValidators
    -> 5 validators, sum(weight) 2500000000000000000 nLUX = 2,500,000,000 LUX

(P-chain figures are nLUX, 1e9 — and the rows carry `weight`, not
`stakeAmount`, which is why the reader already falls back.)

useCurrentValidators returns a ZEROED ValidatorStats when the query fails,
and a zeroed stat is indistinguishable from a chain with no validators.
NetworkOverview and NetworkStats each guarded against that with their own
copy of `!isError && validatorCount > 0`; ValidatorsPage and
ValidatorsDashboard had no guard at all, so they rendered the zeros —
"Validators (0)", "Delegators (0)", "0 LUX Total Stake" — as if measured.

The question "did the read answer?" now has exactly one answer, computed
where the read happens: the hook exports `isKnown`. The two ad-hoc copies
are gone and the two unguarded surfaces use it, showing an em dash and
naming the method that did not answer.

Also restores module resolution. 258bd1a48 dropped `baseUrl: "."` from
tsconfig on the grounds that `paths` already covered it — but `paths` was
`{}`, so baseUrl alone was resolving every absolute import in the repo
("configs/app", "lib/api/pchain", "ui/..."). Without it tsc could not
resolve a single one. `"*": ["./*"]` is the same rule in the form TS7
accepts: tsc goes from thousands of TS2307 to 1.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 14:32:37 -07:00
zeekay 2abb742d55 feat(explore): fee burn + staking rewards panel, from one balance
creditTxFee credits floor(fee/2) to the fee reward vault 0x0100..0002 and leaves
the rest credited to no account at all. The vault has no code and no key, so its
balance only grows, and it is BOTH counters at once: rewards accrued exactly, and
supply burned to within one wei per transaction. One eth_getBalance is the whole
data set — no indexer, no event log, no receipts. That is the panel.

Reads are one batched JSON-RPC round trip (vault balance, coinbase balance, head
block, eth_getChainConfig), polled every 30s.

Decimals: the divisor is 10^18, NOT 10^9. nLUX is the P-Chain staking unit; this
is a C-Chain EVM balance from eth_getBalance, i.e. wei, and it goes through the
one canonical path (NativeCoinValue -> config.chain.currency.decimals). Pinned by
a test against live mainnet: the coinbase holds 3867543864740765677447 wei =
3,867.54 LUX. At 10^9 it would print 3.87 trillion LUX, about double the supply.
Same class of bug as 1b6e86a16, one billion times larger.

Honest about the zero. Mainnet's config has no feeSplitTimestamp, so the split has
never fired and nothing is deflationary. The panel says exactly that, tags itself
"Not active", and shows where the fees really go: the coinbase 0x0100..0000, which
has no code and no key either, so its 3,867 LUX is stranded, not burned.

Two traps the tests pin:
  - The gate reads the HEAD BLOCK's timestamp, mirroring IsFeeSplit(blockTime).
    Devnet's feeSplitTimestamp has passed in wall-clock terms while its C-Chain
    sits at height 0 — wall clock would report a burn that never happened.
  - Burn is zero before activation, never the raw vault balance. The vault is a
    plain account; anyone can transfer into it, and calling that "burned" invents
    the deflation this panel exists to report honestly. Unverifiable state prints
    a dash, never a zero.

It lives on the home overview, not /stats: guards.stats 404s the whole /stats
route when the stats microservice is not configured, and burn is a chain fact that
owes nothing to an indexer. Not gated on the primary network either — it reads
whichever chain it is pointed at and reports that chain's own state.

Chart: the vault balance sampled once per new block, deduplicated on block number
and capped at 240 points. There is no cheaper honest source — the nodes prune, so
eth_getBalance one block back already answers "missing trie node", and
api-explore.lux.network serves 404 for every path including /.

next.config.js: `next dev` runs Turbopack, which never read the webpack() block, so
every `import Icon from 'icons/*.svg'` resolved to a static-image object and React
threw "Element type is invalid ... but got: object" — Hint, ChartWidget,
toolkit/next/link and BackToButton all import SVGs directly, so the dev server had
been rendering an error page instead of the app. Same loader, declared for both
bundlers.

Verified against live mainnet 96369 in a real browser, not by HTTP status:
  panel renders "Not active", "LUX burned 0", "Staking rewards accrued 0",
  "Held by the fee coinbase 3,867.5496 LUX", "read at block #1,098,193";
  exactly one batched RPC call carrying all four methods; 0px mobile overflow.
The active and scheduled branches, which mainnet cannot exercise, were driven with
a stubbed RPC: "Active" copy, both counters at the vault balance, coinbase card
correctly hidden, and the chart drawing after three samples.

17 unit tests, 288 in the suite, all green. Typecheck unchanged at 223
pre-existing errors, none in these files.
2026-07-27 12:25:48 -07:00
zeekay 3849ae2407 fix(lux): nLUX is 10^9, not 10^6 — every LUX figure was 1000x too large
LUX_DECIMALS was 6 in four separate files, each dividing a value the code
itself names nanoLux. Nano is 10^-9. Every staking and balance figure the Lux
explorer rendered was inflated by 1000.

The validators page reported 2,500,000,000,000 LUX staked — against a total
supply of ~2T. An impossible number, and it is reached from lux.cloud's own
"View on explorer" link: an investor reads 2.5B on the dashboard, clicks
through, and sees 2.5T. lux.cloud was right; this was wrong.

Verified against live chain state (platform.getCurrentValidators):
  500000000000000000  nLUX -> 500,000,000 LUX   per validator
  2500000000000000000 nLUX -> 2,500,000,000 LUX total across 5

Four copies of one constant, so the bug shipped four times:
  ui/validators/lux/utils.ts · ui/chains/ChainDetailPage.tsx
  ui/pages/NetworkOverview.tsx · ui/stats/lux/NetworkStats.tsx
Each still owns its own copy; they should share one, which is the follow-up.

Typecheck shows no new errors in these files (the existing _app.tsx and *.pw.tsx
failures predate this change).
2026-07-26 20:11:27 -07:00
zeekay 608243e03a refactor(pchain): Subnet -> Net; add the mainnet explorer ingress
Drops "subnet" from the P-chain surface, which is not our vocabulary:

    useSubnets          -> useNets      (useSubnets.ts deleted)
    PChainSubnet        -> PChainNet
    GetSubnetsResponse  -> GetNetsResponse

One "subnet" deliberately survives — `subnetID` in lib/api/pchain/wire.spec.ts.
That is the UPSTREAM P-chain wire field, read through a raw
Record<string,string> cast, so renaming it would break response parsing. The
rule is about our own language, not about lying to the wire.

Also adds deploy/k8s/explore-fe/ingress-mainnet.yaml. explore.lux.network is
served by the Next.js deployment explore-fe-lux (ghcr.io/luxfi/explore), not
the Go `explorer` binary, which only backs api-explore.lux.network. This
replaces drift where the plain Ingress pointed explore.lux.network at
explorer:80 — the Go binary's embedded, stale build.

Two pre-commit gates had to be satisfied, both legitimate:
- eslint max-len: three className lines (BridgePage 230 chars, ChainRow 188 x2)
  exceeded the 160 limit; wrapped.
- cspell: `platformvm` flagged unknown. It is the P-chain VM's actual name, so
  it is added to cspell.jsonc `words` rather than renamed in code. (Note for
  the next person: .cspell-words.txt is listed under ignorePaths — it is a file
  excluded from checking, NOT the dictionary. Adding a word there does nothing.)

Verified: tsc --noEmit reports ZERO errors in every file this commit touches and
zero stale-symbol errors, so the rename resolves completely. The project's 223
pre-existing errors are all in untouched files and unchanged by this commit.
2026-07-26 09:11:38 -07:00
zeekayandHanzo Dev 8901706f59 fix(explore/ui): readable detail labels, real validator metrics, stat contrast (v1.1.9)
Three UI-correctness fixes surfaced by visual inspection of explore.lux.network:

- DetailedInfo (block/tx/address detail pages): every field label + value
  rendered white-on-white because the grid inherited the @luxfi/ui Tamagui
  `t_dark` theme color while the page is in light mode. The two most-used
  drill-downs were unreadable. Anchor the container to
  --color-text-primary and labels to --color-text-secondary so text follows
  the app color mode instead of the stray Tamagui theme.

- StatsWidget (home metric cards): the value had no explicit color and
  inherited the same Tamagui white -> near-invisible "Total blocks /
  transactions / addresses". Anchor to --color-text-primary.

- Validators dashboard + Network Overview: dropped the "Connected" (0/5) and
  "Avg Uptime" (0.0%) widgets/columns. platform.getCurrentValidators reports
  connected=null and uptime=0 for every validator on the public RPC (the API
  node does not track peer uptime), so those numbers were fabricated-looking
  zeros. Only chain-verifiable metrics (count, stake, delegation fee,
  delegators) remain -- real data, no fake numbers.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-17 01:53:24 -07:00
zooqueen 67bbfef7b0 fix(explore/stats): gate stats:lines query on stats feature flag
When no stats microservice is configured (config.features.stats.isEnabled
false), don't fire the stats:lines request that can only fail — the Stats page
already renders the live Network Overview + an honest 'being indexed' note.
Avoids a wasted erroring query on every Stats page load.
2026-06-23 21:10:33 -07:00
zeekay 3813d03918 feat: explorer FE — stateless SSR, chain selector, localnet, registry cleanup 2026-03-01 18:00:00 -08:00
zeekay da79f9e711 feat: rename @blockscout to @luxfi, monochrome theme, horizontal blocks
- Rename all @blockscout/* npm packages to @luxfi/* aliases (150+ files)
- Override blue accent colors to gray for monochrome theme
- Fix dropdown/menu/popover fonts to use Geist Sans
- Change Latest Blocks to horizontal scrolling layout
- Show dashes instead of zeros for validator stats on error
- Fix GHA deploy step to use correct deployment name
2026-03-02 12:28:15 -08:00
zeekay 8c1f6b438b feat: update all chain definitions to 14 primary network chains
Add D-Chain (DexVM), G-Chain (GraphVM), I-Chain (IdentityVM),
O-Chain (OracleVM), R-Chain (RelayVM) to match ~/work/lux/node
vms_allvms.go. Fix VM names: ThresholdVM, BridgeVM, KeyVM.
Update chain count from 9 to 14 across all pages.
2026-02-26 11:10:12 -08:00
zeekay f6eb142582 feat: add Bridge page and Network Stats to Stats page
- Add /bridge page with cross-chain transfer route tracker
- Show bridge routes between Primary Network chains and L1 subnets
- Add Network Stats section (validators, chains, stake, uptime) to Stats page
- Add Bridge to navigation menu
- Register /bridge route in nextjs-routes, metadata, and mixpanel
2026-02-26 00:47:24 -08:00
tom goriunovandGitHub 4335faeb35 UI/UX: Implement unified EmptyState component for stats page (#3195)
* add EmptyState component to toolkit and use it in the stats page

* remove EmptySearchResult component

* tweaks

* refactor ComingSoon component

* fix toolkit build

* rollback changes in main preset
2025-12-23 11:34:33 +01:00
tom goriunovandGitHub 932add9d96 Change zero to <0.001 value within different pages (#3150)
* basic components and address page refactoring

* second part of refactoring

* third part of refactoring

* NativeCoinValue component

* more refactoring

* rename TruncatedValue into TruncatedText

* minor fixes

* refactor block details

* fix layout of value and fee in tx table

* update screenshots

* different units for tooltip and stats widget small value fix

* update screenshots

* update tx table screenshot

* fix copy button vertical alignment
2025-12-05 16:04:27 +01:00
edc54514f1 OP Superchain explorer: aggregated views (#3040)
* refactor widgets on home page

* coming soon placeholder component

* top accounts page

* contract data

* address ERC-20 tokens list

* chain filter for address ERC-20 tokens

* token select for address detailed view

* address details fields

* tokens table

* stats widgets on home page

* chain indicators graph on the home page

* quick search

* search results all tab

* tabs and chain select on search results page

* search results mobile view

* add contract info to search and address details

* add text filter for tokens and search improvements

* load all results inside tab on search results page

* token balance info

* add support for domains in the full search

* Multichain explorer

Resolves #2989

* add envs validator for multichain

* add some tests

* fix search bar on search results page on mobile

* home stats fixes

* fix ts

* optimize amount of queries on address page

* add more contract info on address page

* add enter key hint to search input

* fix tests

* fix test

* update bg.primary css-variable on color theme change

* sitemap for multichain

* txs page: render first tab if blob tab is not available on the chain

* filter out in active chains from chain select on address page and user ops page

* add chain icon to advanced filter table

* fix tooltip on entity with shield

* fix ts

* show contract implementations

* fixes

* add chain icon to all lists

* refactor zetachain chains config type

* use chain id as primary option instead of chain slug

* refactor chain config type for multichain and essential dapps

* refactor chain icon and chain select

* rename chain-slug in chain_slug

* change default radius of chain icon and update screenshots for multichain tests

* change conditions for "isContract" and "isVerified"

* test fixes

* make shield optional for external chain entities

* add chain icon to approvals lists

* add stats page for multichain

* add chain postfix to chart .png and .csv assets name

* fix tests

* sync verified contracts language filter and fix loading state in the search results page

* fix sol2uml diagram and csv export

* regcred from helmfile for review

* link fixes

* fix state for unknown address

* fix incorrect chain in the context during spa transition to the same route on different chain

* add links to stats widgets

* add mixpanel to L2 demo values

* show message of on-demand contract verification

* fix screenshots

---------

Co-authored-by: Nick Zenchik <[email protected]>
2025-11-18 09:44:22 +01:00
tom goriunovandGitHub 5c0c18149d Move charts to toolkit and improve color mode hook (#3075)
* move charts to toolkit

* refactor imports

* fix tests

* change the behavior of the color mode hook and add the noWatermark prop

* fix gas tracker test and fix toolkit build
2025-10-21 17:33:04 +02:00
tom goriunovandGitHub f0e713b877 Add support for customizing the UI color theme (#2923)
* UI customizations: new features

Fixes #2905

* colors for graphs

* introduce env variable

* colors for topbar, stats, selected state and tabs

* fix build

* fix validator

* refactor link.primary.hover color token

* refactor selected colors

* update styles for switch and fix some color tokens

* change color for selectable controls

* icon color tokens refactoring

* UI customizations: new features

Fixes #2905

* test for common components

* tweaks

* migrate from color-mode-hex cookie to color-theme cookie

* clean up

* update screenshots

* more screenshot updates

* update default color of chart line

* update envs for mega eth
2025-08-19 11:58:05 +02:00
tom goriunovandGitHub ecae7062b2 Merge pull request #2700 from blockscout/release/v2-0-1
Release v2.0.1
2025-05-05 09:56:18 +02:00
tom 24411cee0e update screenshots 2025-05-02 14:13:44 +02:00
tom 866bdfbac9 update margins on stats page and in the tx heading 2025-05-02 13:45:34 +02:00
tom goriunovandGitHub fae4990e1f API resource refactoring (#2699)
* add prefix to API resources

* fix pw tests

* refactor config

* remove unnecessary prefixes in resource names

* fixes

* update screenshots
2025-05-01 15:22:38 +02:00
tom goriunovandGitHub f6725649da UI toolkit package (#2691)
* first version of the pack

* single entry point

* add custom components to the package

* move form components to toolkit

* add more utils and hooks to the package

* minor fixes

* add CI workflow

* update readme and package.json

* fix ts

* fix build of env-validator

* fix docker build

* fix icons size

* test fixes

* more test fixes
2025-04-21 19:44:22 +02:00
tom c55dfdcf5b remove old semantic tokens 2025-03-13 15:22:59 +01:00
tom 46a00cedbb fix more ts errors 2025-03-11 16:18:03 +01:00
tom 57bb722cb0 refactor Select usage 2025-03-11 12:35:49 +01:00
tom f55aecd4cb stats pages 2025-02-21 19:57:22 +01:00
Igor StuevandGitHub 6c2356d607 remove skeleton animations (#2505)
* remove skeleton animations test

* eslint add Skeleton

* eslint-fix
2025-01-06 16:57:22 +01:00
tom goriunovandGitHub c802f0b5ed Replace system selectors with Blockscout selectors style (#2451)
* migrate from native select to the custom one

* migrate popover radio filter to select component

* migrate stats menu to select

* migrate Sort component

* screenshot updates
2024-12-13 14:42:21 +01:00
tom 125c4880de migrate to eslint 9 and its flat config 2024-11-13 12:54:12 +01:00
isstuev 2923e7f027 design fixes 2024-09-25 10:16:02 +02:00
isstuev 61271e560a stats updates 2024-09-25 10:16:02 +02:00
tom goriunovandGitHub e9aa8a3c2f Stats: give emphasis to incomplete data days (#2085)
* draw dotted line for incomplete data

* add title to tooltip

* refactor parts into separate components

* move utils

* refactor render logic of tooltip

* more refactoring

* fix issue in safari

* tweaks

* test

* make an approximation as a straight line.

* update screenshots

* fix the tooltip hiding behavior.

* add prop for disabling animation
2024-07-22 14:41:18 +02:00
tom goriunovandGitHub c735b217a7 Update info icon color (#2088)
* Icon info color

Fixes #2045

* fix test

* more test fixes
2024-07-09 18:21:04 +02:00
tom d1e04a0dde Merge branch 'main' of github.com:blockscout/frontend into tom2drum/issue-1977 2024-07-05 19:18:51 +02:00
tom goriunovandGitHub 5d2ae73172 Migrate to @blockscout/stats-types and @blockscout/visualizer-types (#2063)
* migrate to stats-types package

* migrate to visualizer-types package

* update package.json
2024-07-02 16:27:13 +02:00
tom d932e16b07 update gutter for Menu dropdown 2024-06-28 18:55:22 +02:00
tom goriunovandGitHub d4c92518b1 Update styles of outlined buttons and more (#1978)
* selected state for Button

* tests

* fix menu filter button hover issue

* update screenshots

* try to fix SearchBar recent keywords test
2024-06-05 12:44:09 +02:00
tom goriunovandGitHub c0e660d2e1 Stats Update (#1796)
* [WIP] chart for secondary coin price

* latest L1 state batch snippet

* txs stats snipper

* Merge main branch

* optimism preset

* rename governance token into secondary coin

* add secondary coin price to top bar

* calculate usd value for avg tx fee

* tests

* tweaks

* change envs for demo

* fix tests

* fixes

* fix flaky test

* change scroll to filter for stats link behaviour
2024-04-17 10:04:33 +02:00
tom goriunovandGitHub ae5489b1f7 Gas tracker page (#1524)
* add custom headers to API resource

* refactoring

* page title

* chart

* gas prices snippet

* GasPrice component

* add ENV for gas units

* dark theme and other tweaks

* tests

* add base and priority fee

* [skip ci] small fiat values

* change behavior of the variable

* update tooltip layout

* refactor gas info tooltip

* refactor GasPrice component

* fix logic and deploy demo for eth mainnet

* tests

* remove link from anchor

* [skip ci] rollback ENVs for demo

* review fixes

* fix tests
2024-02-20 08:36:57 +04:00
tom goriunovandGitHub 797b8f57bb Validators list (#1621)
* new ENV and page placeholder

* display list data

* comment out SearchInput

* add counters

* add tag to address page

* tests

* refactoring

* fix ts

* change ENVs for demo

* fix ENVs validator

* [skip ci] remove hash

* review fixes
2024-02-19 11:04:28 +04:00
tom 58f80b5055 use dataUpdatedAt as a reference 2024-01-11 19:50:04 +04:00
tom 4b90c45a5a tooltip on stats page 2024-01-08 07:57:10 +04:00
tom 87bbfdd449 migration: next part 2023-12-20 14:09:33 +04:00
isstuev e983387c4e stats second fix 2023-12-14 12:53:10 +01:00
tom goriunovandGitHub c559061506 migrate to ReactQuery v5 (#1321)
* change signature of hooks

* isLoading -> isPending

* default error type

* dev tools props
2023-11-02 10:27:41 -03:00
tom goriunovandGitHub 3cfc6170cd Charts&Stats: add tooltips to number charts (#1192)
Fixes #1151
2023-09-19 11:21:26 -03:00
tom 2bdeccedaf skeletons for stats counters 2023-06-02 11:59:47 -03:00
tom dc5fb9142c skeletons for stats 2023-05-25 17:54:20 -03:00
tom 2b813d102e renaming 2023-05-08 15:47:14 -03:00