Frontend: canonical address display (blockie + label + mega.etherscan.io link) site-wide #98
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:open_issues
agents
agent:security_audit
agent:verify
area
timecurve
arena
arena-v2
audit
block:feature_review
block:security
bug
contracts
design
devops
docs
documentation
enhancement
epic
feature
frontend
indexer
low priority
megaeth
operations
ops
performance
QA
qa checklist
referrals
removal
security
smart-contracts
tech-debt
testing
time-arena
timecurve
visual-qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
code/yieldomega#98
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
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
Establish a single canonical UI component for displaying 20-byte Ethereum addresses (
0x+ 40 hex, EOAs and contracts) across the dapp: identicon (blockie) + human-readable label + link to the address on the block explorer, defaulting to MegaETH Etherscan (same base URL convention as transaction links).Today we already ship
AddressInline(frontend/src/components/AddressInline.tsx) usingethereum-blockiesviaWalletBlockie, plus optionalWalletFormatShortlabels. It does not yet open explorer address pages.explorer.tsonly exposesexplorerTxUrl(/tx/{hash}); we need a siblingexplorerAddressUrl(/address/{address}) with the sameVITE_EXPLORER_BASE_URLdefault (https://mega.etherscan.io).Goals (acceptance criteria)
<span className="mono">, raw<code>, or truncated hex alone.0x000…000—show a clear fallback like—).{normalized_explorer_base}/address/{address}using the same env contract as
explorerTxUrl(frontend/src/lib/explorer.ts). Default base:https://mega.etherscan.io. Respect trailing-slash trimming; validate withviemisAddressbefore emitting a URL.target="_blank"+rel="noreferrer noopener"on explorer links; decorative blockie remainsaria-hidden; screen readers get a non-misleading name (e.g. visually hidden “View address on Etherscan” or include full address in accessible name where the visible label is truncated).frontend/.env.example(if needed),docs/frontend/wallet-connection.mdor explorer notes, and any QA checklist that mentions address display.Scope note: “EOA” vs contract
Block explorers use the same
/address/0x…page for EOAs and contracts. Unless product explicitly hides blockies for contracts, treat all 20-byte addresses the same in the shared component (FeeRouter sink destinations, token contracts, etc.). Do not use this pattern for 32-byte tx hashes (keepTxHash/explorerTxUrl).Current baseline — where
AddressInlineis already usedVerify after adding explorer links (grep from repo root):
frontend/src/components/AddressInline.tsxfrontend/src/pages/TimeCurveSimplePage.tsxfrontend/src/pages/timeCurveArena/TimeCurveArenaView.tsxfrontend/src/pages/timeCurveArena/useTimeCurveArenaModel.tsxfrontend/src/pages/timeCurveArena/TimeCurveArenaWalletMono.tsxfrontend/src/pages/timecurve/TimeCurveSections.tsxfrontend/src/pages/TimeCurveProtocolPage.tsxrenderAddress+ fee sink destinations.frontend/src/components/FeeTransparency.tsxfrontend/src/pages/referrals/ReferralConnectedWalletSection.tsxfrontend/src/pages/referrals/ReferralLeaderboardSection.tsxLikely gaps — systematic search (run from repo root)
1) Standalone blockie (bypasses shared chrome / explorer)
Primary hit:
frontend/src/pages/timecurve/LiveBuyRow.tsx— custom layout with its ownWalletBlockie+ mono name. Refactor to the shared component or composeWalletBlockie+explorerAddressUrlonly insideAddressInlineso there is one implementation.2)
formatWallet/shortAddress/ truncation outside the componentPay special attention to string-only uses (no React node):
Examples:
buyProjectedEffectstemplate strings,label: formatWallet(...)for chart/history payloads,buildBuyFeedNarrative/buildWarbowFeedNarrativeinfrontend/src/lib/timeCurveUx.ts(pure strings). Decide per surface:{ address, label }[]or React fragments where the UI should show blockies (larger refactor).Document the decision in the MR.
3)
mono+ address-like contentManually filter rows that are amounts / bps / ISO times (out of scope) vs hex identities.
4)
title={with wallet-ish props5) Other app surfaces
Audit Home, Collection, Rabbit Treasury, Kumbaya, Sir, Presale vesting, UnderConstruction, LaunchCountdown, WalletConnectButton / RainbowKit custom children—any truncated connected account display.
6) Indexer / API field names (discovery aid)
Cross-check each field surfaced in UI.
Implementation sketch
frontend/src/lib/explorer.tsexplorerAddressUrl(address: string): string | undefined(same base asexplorerTxUrl; path/address/; validateisAddress).frontend/src/lib/explorer.test.tshttps://mega.etherscan.io/address/0x…VITE_EXPLORER_BASE_URL; reject invalid / non-0x40hex.AddressInline(or renamedLinkedAddress/AccountAddress)explorer?: boolean(default true for “identity” rows; allow false for dense tables if design requires—justify in MR).<a href={explorerAddressUrl(raw)}>around label (or icon+label cluster) with external-link cursor class per existing patterns (TxHash.tsx).LiveBuyRowwith shared behavior.Verification checklist (before merge)
cd frontend && npm run typecheckcd frontend && npm test(includesexplorerunit tests)VITE_EXPLORER_BASE_URLin.env.local)monotext-only nodesReferences
frontend/src/lib/explorer.ts(explorerTxUrl, defaulthttps://mega.etherscan.io)frontend/src/components/WalletBlockie.tsx, packageethereum-blockiesfrontend/src/lib/addressFormat.ts,frontend/src/pages/referrals/referralAddressDisplay.tsOut of scope (explicit)
TxHashcomponent (different explorer path).AmountDisplay, bps, WAD decimals) inmono.mentioned in commit
c18fd7ba62mentioned in commit
72c5716461Implemented on
main(c18fd7b)Merged GitLab #98: canonical 20-byte address UX — blockie + label + explorer link sharing
VITE_EXPLORER_BASE_URLwith tx URLs (explorerAddressUrl/explorerTxUrl),AddressInlineupdates,LiveBuyRowrefactor (role="group"hit target + buyer link),MegaScannerAddressLinkaligned, docs +skills/verify-yo-canonical-address-explorer/SKILL.md.@brouie — please verify when you have a moment.
Checklist for verification
cd frontend && npm run typecheck && npm test -- --runnpm run test:e2e:timecurve-ui(Arena live-buys + modals; dev server clearsVITE_LAUNCH_TIMESTAMP)AddressInline/ fee-sink / live-buy buyer links → correct/address/0x…on MegaETH Etherscan (or customVITE_EXPLORER_BASE_URL)VITE_TIMECURVE_ADDRESS+ indexer URL: live buys strip + More + detail modal still work (indexer-mocked E2E path)Issue left open per request.
mentioned in commit
ca2aaffdd6mentioned in issue #100
Verified
c18fd7bondd1c59aHEAD today. All 5 checklist items PASS. Closing.Stack state
dd1c59aHEAD on main, Vite restarted/v1/statusschema_version=1.8.0, max_indexed_block=12, database_connected=trueItem 1 — typecheck + vitest: PASS
npm run typecheckclean,npm test -- --run40 files / 238 tests / all green / 4.94s.Item 2 — e2e:timecurve-ui: PASS
npm run test:e2e:timecurve-ui2 chromium specs pass in 6.7s ("live buys strip + More + detail modal stack" and "side strip opens buy detail without list").Item 3 — Manual address links: PASS
Tested across Simple, Arena, Protocol:
explorerAddressUrl and explorerTxUrl helpers consistently respect VITE_EXPLORER_BASE_URL.
Item 4 — Interactive live-buy row: PASS
On /timecurve/arena Live buys panel:
role="group" + buyer-link refactor preserves both interaction modes correctly.
Item 5 — Arena with no VITE_TIMECURVE_ADDRESS (indexer-mocked path): PASS
Covered by Item 2 e2e — playwright.timecurve-ui.config.ts dev server clears VITE_LAUNCH_TIMESTAMP and exercises live buys strip, More list modal, detail modal from list, and detail modal direct from side strip. All 2 specs green.
Closure
Canonical 20-byte address UX wired across AddressInline, MegaScannerAddressLink, LiveBuyRow refactor (role="group" separates Tab stops). /address/0x... and /tx/0x... correctly differentiated. Indexer-mocked fallback works end-to-end.
Closing #98.
cc @PlasticDigits
mentioned in issue #226
marked as related to #226
mentioned in issue #230
mentioned in issue #231
mentioned in issue #234