Skip to content

feat(scan): /supply, /forks, /epochs pages + finality + rail badges#7

Merged
satyakwok merged 2 commits intomainfrom
feat/scan-supply-forks-epochs
Apr 30, 2026
Merged

feat(scan): /supply, /forks, /epochs pages + finality + rail badges#7
satyakwok merged 2 commits intomainfrom
feat/scan-supply-forks-epochs

Conversation

@satyakwok
Copy link
Copy Markdown
Contributor

Why

Per Satya's directive: explorer yang lengkap fitur, orang paham, ready for SRX launch. Three new top-level pages + two new badge components — same data sources the rest of the explorer already uses (no new backend endpoints required for Phase 1).

What

`/supply`

Canonical SRX supply breakdown URL. Listing platforms (CG / CMC / DefiLlama) + due-diligence reviewers deep-link here. Includes:

  • Headline stat row (max / minted / burnt / bonded)
  • Distribution donut chart (circulating / premine / bonded / remaining / burnt)
  • Per-wallet premine breakdown with addresses pulled from the existing canonical-addresses registry
  • Protocol-sentinel addresses called out
  • Numerical reference (sentri-scale, mintable headroom, bonded ratio)

Reads live values via `useStats` + `useValidators` so it reflects real chain state.

`/forks`

Fork-activation timeline. Source of truth in `lib/forks/registry.ts`, hand-synced against `founder-private/U64_MAX_FORK_GATES.md`. Per fork: state (active / scheduled / dormant), activation height, "what changed when" description. Cross-network comparison table at the bottom. Includes the 2026-04-30 `JAIL_CONSENSUS` activation (mainnet h=950400, testnet h=1030500) and the deliberately-dormant `NFT_TOKENOP_HEIGHT` (DO NOT activate marker).

`/epochs`

Current-epoch detail with progress bar (blocks-into-epoch %), total bonded, rewards accrued. Past 12 epochs derived locally from the current `epoch_number` + `EPOCH_LENGTH=28800`; entries deep-link to first / last block of each epoch.

`RailBadge`

Distinguishes Sentrix's four rails (EVM / Native / SRC-20 / Staking). `classifyRail(tx)` centralises the heuristic so every tx page agrees.

`FinalityBadge`

Sentrix BFT finality ladder (Pending → Included → Justified → Finalized). The "Justified" / "Finalized" distinction is what exchanges and bridges should pin. `classifyFinality()` computes the state from `txBlockHeight` + `latestHeight` + `hasJustification`.

Nav wiring

  • `/supply` → top header ("Supply")
  • `/epochs` + `/forks` → footer Explorer column
  • `nav.supply` i18n string added in en + id

Verification

`pnpm --filter @sentriscloud/scan typecheck` clean. Lint reports only pre-existing warnings unrelated to this PR.

Next sessions

  • Wire `RailBadge` + `FinalityBadge` into existing `tx/[hash]` page
  • Get the new `sentriscloud/indexer` running on the build host so /supply + /epochs + everything else can fall through to the indexer DB for deeper history queries instead of RPC pagination
  • Verified-contracts UI deepening (Sourcify source viewer)

Add lib/sourcify.ts hook + components/common/SourcifyBadge.tsx that
queries https://verify.sentrixchain.com/files/any/<chainId>/<addr>
to detect contract source verification status:
- "perfect" → green "verified" badge linking to Sourcify
- "partial" → amber "partial match" badge
- "none" → hidden by default (no noise on EOAs/unverified contracts)

Wired into [locale]/address/[addr]/page.tsx PageHeader actions next
to the existing label kind chip.

Self-hosted Sourcify deployed on vps4 supports both mainnet (7119)
and testnet (7120). All 8 canonical contract deployments (WSRX,
Multicall3, TokenFactory, SentrixSafe across both chains) verified
with perfect bytecode match.

Tested: typecheck clean, build OK, scan service restarted.
Three new top-level pages aimed at "explorer that listing teams + delegators
+ technical reviewers can read top-to-bottom and understand". Same data
sources the rest of the explorer already uses (no new backend endpoints
required for Phase 1):

- /supply — single canonical SRX breakdown URL. Headline stat row, donut
  distribution (circulating / premine / bonded / remaining-to-mint / burnt),
  per-wallet premine breakdown with addresses pulled from the existing
  canonical-addresses registry, protocol-sentinel addresses called out.
  Pulls live values via useStats + useValidators so it reflects real chain
  state without baking magic numbers into the page.

- /forks — fork-activation timeline. Source of truth in
  lib/forks/registry.ts, hand-synced against U64_MAX_FORK_GATES.md. Each
  fork gets a card with state (active / scheduled / dormant) + activation
  height + a non-technical "what changed when" description. Cross-network
  comparison table at the bottom so drift between mainnet + testnet is
  visible at a glance. Includes the 2026-04-30 JAIL_CONSENSUS activation
  (mainnet h=950400, testnet h=1030500) and the deliberately-dormant
  NFT_TOKENOP_HEIGHT (DO NOT activate marker).

- /epochs — current-epoch detail with progress bar (blocks-into-epoch %),
  total bonded, rewards accrued. Past 12 epochs derived locally from the
  current epoch_number + EPOCH_LENGTH=28800; entries deep-link to the
  first / last block of each epoch. Footnote explains what an epoch does
  (validator-set rotation, reward settlement, slashing window, jail
  evidence boundary).

Two new badge components for the deeper tx/block detail pages we'll wire
in next:

- RailBadge — distinguishes Sentrix's four transaction rails (EVM call /
  native SRX transfer / SRC-20 native TokenOp / native StakingOp). Sentrix
  is one of the only chains where SRC-20 lives at the protocol level
  alongside ERC-20, so users need to be told which rail they're looking
  at; classifyRail(tx) helper centralises the heuristic.

- FinalityBadge — Sentrix BFT finality ladder (Pending → Included →
  Justified → Finalized). The "Justified" / "Finalized" distinction
  is what exchanges and bridges should pin, and no other EVM explorer
  surfaces it because no other EVM chain has 2/3+1 stake-weighted
  precommit-supermajority finality at 1s blocks. classifyFinality()
  helper computes the state from txBlockHeight + latestHeight +
  hasJustification.

Nav: /supply added to the top header ("Supply"); /epochs + /forks
linked from the footer Explorer column. i18n nav.supply added in en/id.

`pnpm typecheck` clean across the workspace; lint reports only existing
warnings unrelated to this PR.
@satyakwok satyakwok merged commit 844d8a5 into main Apr 30, 2026
@satyakwok satyakwok deleted the feat/scan-supply-forks-epochs branch April 30, 2026 00:13
satyakwok added a commit that referenced this pull request Apr 30, 2026
* feat(scan): Sourcify verification badge on address page

Add lib/sourcify.ts hook + components/common/SourcifyBadge.tsx that
queries https://verify.sentrixchain.com/files/any/<chainId>/<addr>
to detect contract source verification status:
- "perfect" → green "verified" badge linking to Sourcify
- "partial" → amber "partial match" badge
- "none" → hidden by default (no noise on EOAs/unverified contracts)

Wired into [locale]/address/[addr]/page.tsx PageHeader actions next
to the existing label kind chip.

Self-hosted Sourcify deployed on vps4 supports both mainnet (7119)
and testnet (7120). All 8 canonical contract deployments (WSRX,
Multicall3, TokenFactory, SentrixSafe across both chains) verified
with perfect bytecode match.

Tested: typecheck clean, build OK, scan service restarted.

* feat(scan): supply / forks / epochs pages + finality + rail badges

Three new top-level pages aimed at "explorer that listing teams + delegators
+ technical reviewers can read top-to-bottom and understand". Same data
sources the rest of the explorer already uses (no new backend endpoints
required for Phase 1):

- /supply — single canonical SRX breakdown URL. Headline stat row, donut
  distribution (circulating / premine / bonded / remaining-to-mint / burnt),
  per-wallet premine breakdown with addresses pulled from the existing
  canonical-addresses registry, protocol-sentinel addresses called out.
  Pulls live values via useStats + useValidators so it reflects real chain
  state without baking magic numbers into the page.

- /forks — fork-activation timeline. Source of truth in
  lib/forks/registry.ts, hand-synced against U64_MAX_FORK_GATES.md. Each
  fork gets a card with state (active / scheduled / dormant) + activation
  height + a non-technical "what changed when" description. Cross-network
  comparison table at the bottom so drift between mainnet + testnet is
  visible at a glance. Includes the 2026-04-30 JAIL_CONSENSUS activation
  (mainnet h=950400, testnet h=1030500) and the deliberately-dormant
  NFT_TOKENOP_HEIGHT (DO NOT activate marker).

- /epochs — current-epoch detail with progress bar (blocks-into-epoch %),
  total bonded, rewards accrued. Past 12 epochs derived locally from the
  current epoch_number + EPOCH_LENGTH=28800; entries deep-link to the
  first / last block of each epoch. Footnote explains what an epoch does
  (validator-set rotation, reward settlement, slashing window, jail
  evidence boundary).

Two new badge components for the deeper tx/block detail pages we'll wire
in next:

- RailBadge — distinguishes Sentrix's four transaction rails (EVM call /
  native SRX transfer / SRC-20 native TokenOp / native StakingOp). Sentrix
  is one of the only chains where SRC-20 lives at the protocol level
  alongside ERC-20, so users need to be told which rail they're looking
  at; classifyRail(tx) helper centralises the heuristic.

- FinalityBadge — Sentrix BFT finality ladder (Pending → Included →
  Justified → Finalized). The "Justified" / "Finalized" distinction
  is what exchanges and bridges should pin, and no other EVM explorer
  surfaces it because no other EVM chain has 2/3+1 stake-weighted
  precommit-supermajority finality at 1s blocks. classifyFinality()
  helper computes the state from txBlockHeight + latestHeight +
  hasJustification.

Nav: /supply added to the top header ("Supply"); /epochs + /forks
linked from the footer Explorer column. i18n nav.supply added in en/id.

`pnpm typecheck` clean across the workspace; lint reports only existing
warnings unrelated to this PR.

* feat(scan): wire RailBadge + FinalityBadge into the tx detail page

Both badges shipped in PR #7 but weren't wired anywhere yet. This puts
them at the top of every tx page so the user instantly sees "what kind
of tx is this" + "how settled is it":

- Page header actions now render RailBadge + FinalityBadge alongside
  the existing success/failed status — three compact badges grouped
  together like Etherscan's "Status: Success | Block: 12345 (Finalized)"
  cluster, but Sentrix-aware.
- The Status row in the Summary card now stacks the success/failed
  badge with the finality badge (Pending / Included / Justified /
  Finalized), with a hint explaining what the four states mean.
- A new "Rail" row sits below Status: shows the rail badge + a
  contextual one-liner explaining what that rail means (EVM call vs
  native SRX transfer vs SRC-20 op vs native staking op). This is the
  teaching aid we keep getting support tickets about — users don't
  know which rail their tx travelled on.

Finality classification: pending if no block_height, finalized if
descendant has landed (chain head > tx block), else justified for
any block past the Voyager activation height (`h >= 579_047` —
every Voyager block ships a justification by construction).

Rail classification piggybacks on the centralised `classifyRail()`
heuristic the badge component shipped with — to_address sentinels
0x0000…0000 / 0x0000…0100 → SRC-20 / Staking; data prefix "EVM:"
→ EVM; everything else → Native.

`pnpm --filter @sentriscloud/scan typecheck` clean.

---------

Co-authored-by: satyakwok <satyakwok@users.noreply.github.com>
satyakwok added a commit that referenced this pull request Apr 30, 2026
* feat(scan): Sourcify verification badge on address page

Add lib/sourcify.ts hook + components/common/SourcifyBadge.tsx that
queries https://verify.sentrixchain.com/files/any/<chainId>/<addr>
to detect contract source verification status:
- "perfect" → green "verified" badge linking to Sourcify
- "partial" → amber "partial match" badge
- "none" → hidden by default (no noise on EOAs/unverified contracts)

Wired into [locale]/address/[addr]/page.tsx PageHeader actions next
to the existing label kind chip.

Self-hosted Sourcify deployed on vps4 supports both mainnet (7119)
and testnet (7120). All 8 canonical contract deployments (WSRX,
Multicall3, TokenFactory, SentrixSafe across both chains) verified
with perfect bytecode match.

Tested: typecheck clean, build OK, scan service restarted.

* feat(scan): supply / forks / epochs pages + finality + rail badges

Three new top-level pages aimed at "explorer that listing teams + delegators
+ technical reviewers can read top-to-bottom and understand". Same data
sources the rest of the explorer already uses (no new backend endpoints
required for Phase 1):

- /supply — single canonical SRX breakdown URL. Headline stat row, donut
  distribution (circulating / premine / bonded / remaining-to-mint / burnt),
  per-wallet premine breakdown with addresses pulled from the existing
  canonical-addresses registry, protocol-sentinel addresses called out.
  Pulls live values via useStats + useValidators so it reflects real chain
  state without baking magic numbers into the page.

- /forks — fork-activation timeline. Source of truth in
  lib/forks/registry.ts, hand-synced against U64_MAX_FORK_GATES.md. Each
  fork gets a card with state (active / scheduled / dormant) + activation
  height + a non-technical "what changed when" description. Cross-network
  comparison table at the bottom so drift between mainnet + testnet is
  visible at a glance. Includes the 2026-04-30 JAIL_CONSENSUS activation
  (mainnet h=950400, testnet h=1030500) and the deliberately-dormant
  NFT_TOKENOP_HEIGHT (DO NOT activate marker).

- /epochs — current-epoch detail with progress bar (blocks-into-epoch %),
  total bonded, rewards accrued. Past 12 epochs derived locally from the
  current epoch_number + EPOCH_LENGTH=28800; entries deep-link to the
  first / last block of each epoch. Footnote explains what an epoch does
  (validator-set rotation, reward settlement, slashing window, jail
  evidence boundary).

Two new badge components for the deeper tx/block detail pages we'll wire
in next:

- RailBadge — distinguishes Sentrix's four transaction rails (EVM call /
  native SRX transfer / SRC-20 native TokenOp / native StakingOp). Sentrix
  is one of the only chains where SRC-20 lives at the protocol level
  alongside ERC-20, so users need to be told which rail they're looking
  at; classifyRail(tx) helper centralises the heuristic.

- FinalityBadge — Sentrix BFT finality ladder (Pending → Included →
  Justified → Finalized). The "Justified" / "Finalized" distinction
  is what exchanges and bridges should pin, and no other EVM explorer
  surfaces it because no other EVM chain has 2/3+1 stake-weighted
  precommit-supermajority finality at 1s blocks. classifyFinality()
  helper computes the state from txBlockHeight + latestHeight +
  hasJustification.

Nav: /supply added to the top header ("Supply"); /epochs + /forks
linked from the footer Explorer column. i18n nav.supply added in en/id.

`pnpm typecheck` clean across the workspace; lint reports only existing
warnings unrelated to this PR.

* feat(scan): wire RailBadge + FinalityBadge into the tx detail page

Both badges shipped in PR #7 but weren't wired anywhere yet. This puts
them at the top of every tx page so the user instantly sees "what kind
of tx is this" + "how settled is it":

- Page header actions now render RailBadge + FinalityBadge alongside
  the existing success/failed status — three compact badges grouped
  together like Etherscan's "Status: Success | Block: 12345 (Finalized)"
  cluster, but Sentrix-aware.
- The Status row in the Summary card now stacks the success/failed
  badge with the finality badge (Pending / Included / Justified /
  Finalized), with a hint explaining what the four states mean.
- A new "Rail" row sits below Status: shows the rail badge + a
  contextual one-liner explaining what that rail means (EVM call vs
  native SRX transfer vs SRC-20 op vs native staking op). This is the
  teaching aid we keep getting support tickets about — users don't
  know which rail their tx travelled on.

Finality classification: pending if no block_height, finalized if
descendant has landed (chain head > tx block), else justified for
any block past the Voyager activation height (`h >= 579_047` —
every Voyager block ships a justification by construction).

Rail classification piggybacks on the centralised `classifyRail()`
heuristic the badge component shipped with — to_address sentinels
0x0000…0000 / 0x0000…0100 → SRC-20 / Staking; data prefix "EVM:"
→ EVM; everything else → Native.

`pnpm --filter @sentriscloud/scan typecheck` clean.

* feat(chain-landing): publish canonical chain.json + tokenlist.json

Three new static endpoints served by the chain-landing app at
sentrixchain.com:

- /chain.json          — Sentrix Mainnet (7119) descriptor
- /chain-testnet.json  — Sentrix Testnet (7120) descriptor
- /tokenlist.json      — Uniswap-format token list (WSRX 7119 + WtSRX 7120)

Mirrors the ethereum-lists/chains#8283 metadata one level deeper —
includes consensus + finality model + canonical contract addresses +
Sourcify verifier URL inline so a tooling integrator can read a
single JSON and have everything they need (RPC, WS, explorer,
verifier, WSRX address, decimals, finality semantics).

Token list follows the standard Uniswap schema so dApp UIs that
already speak it (Uniswap interface, OpenSea-style allowlists,
portfolio trackers) can drop the URL in without bespoke parsing.

URLs go live the next time chain-landing redeploys via the existing
sentrix-landing systemd flow on the build host.

---------

Co-authored-by: satyakwok <satyakwok@users.noreply.github.com>
satyakwok added a commit that referenced this pull request May 5, 2026
Five small fixes from the pre-launch audit:

#3 /tokens title was 'SRC-20 Tokens' / 'Token SRC-20' but the page
   covers BOTH SRC-20 and ERC-20 (filter pills cover All / EVM / Native).
   Title was misleading when the EVM pill was active. Now generic
   'Tokens' / 'Token'.

#5 home stat sublines were hardcoded English ('active in BFT set',
   'SRC-20 contracts', '50% of every fee', 'claimable via StakingOp',
   'vs <range> window', 'BFT-finalized · live', 'BFT-finalized · -<lag>',
   'Epoch #<n>', 'target 1s'). On the /id locale only the labels
   translated — sublines still read English. Added 9 keys under
   home.stats.subline_*, both locales, indonesian-first phrasing
   keeping technical terms (BFT, StakingOp, SRC-20, Epoch) in English
   per the SentrixCloud design system.

#6 stat-card and sticky-bar labels were getting truncated mid-word on
   <375 px viewports ('LIVE _' / 'BLOCK_' / 'TOTAL_') because the wide
   letter-spacing (.22em) pushed the second word past the truncate
   boundary. Drop spacing to .12em on small screens, restore .22em
   at sm+ (640 px+).

#7 /forks NFT_TOKENOP_HEIGHT description had Rust panic syntax
   ('unreachable!()', 'u64::MAX') that's noise for a public visitor.
   Rewritten editorially — same warning, no Rust idioms.

Skeleton-forever observation on /tokens left as-is — looks like a
transient first-render snapshot rather than a stuck state.
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