Skip to content

EVM support, global search, and account inspector - #91

Open
akobrin1 wants to merge 45 commits into
mainfrom
evm-support
Open

EVM support, global search, and account inspector#91
akobrin1 wants to merge 45 commits into
mainfrom
evm-support

Conversation

@akobrin1

Copy link
Copy Markdown
Collaborator

Summary

  • Global search in the header: accepts a block height, transaction hash, or account address (bech32 or ETH hex, case-insensitive) and routes to the matching inspector
  • New account inspector at /account/[address]: balances (available/staking/rewards/unstaking), delegations with validator links, both address formats with copy, and sent/received transaction tabs
  • Dashboard versions footer: network chain-id + node app version from node_info, EVM chain ID (EVM networks only), and Hub version baked from git tag/commit at build time
  • EVM wallet support refinements: named EVM network profiles, MetaMask account data fixes, idempotent WalletConnect initialization
  • Refactors: shared TransactionHistory component and portfolio aggregation helpers extracted from WalletScreen; fetchAccountInfo/useTransaction parameterized by address
  • Bug fix: wallet "Unstaking" total always showed zero (read unbonding_responses off the response object instead of .data)
  • Docs: CHANGELOG.md for v1.0.0, README Quick Start for Makefile network targets

Test plan

  • 130 unit tests pass (pnpm --filter web test), including new suites for search parsing, account address parsing, tx query building, portfolio helpers, and node-info parsing
  • tsc --noEmit clean
  • Verified in browser against testnet: search flows (height/hash/hex/bech32/invalid), account inspector with real validator account, versions footer values, wallet page rendering

🤖 Generated with Claude Code

akobrin1 and others added 27 commits July 28, 2026 17:59
Profiles that define both an EVM RPC endpoint and EVM chain ID now use
an injected EIP-1193 wallet (e.g. MetaMask) for connecting, native LUME
balances, and transfers. Staking, governance signing, and transaction
history stay on the legacy Cosmos flow and are hidden or disabled on
EVM profiles.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Global search dialog in the header accepting block height, tx hash,
  or account address (bech32 / ETH hex, case-insensitive), routing to
  the matching inspector
- Account inspector page at /account/[address]: balances, delegations,
  both address formats, sent/received transaction history
- Dashboard versions footer: network chain-id and node version, EVM
  chain ID, and Hub build version from git tag/commit
- Extract shared portfolio aggregation helpers and TransactionHistory
  component from WalletScreen; parameterize account/tx fetchers by
  address
- Fix wallet Unstaking total always reading zero (misread unbonding
  response)
- EVM wallet provider refinements and named EVM network profiles
- Add CHANGELOG.md and document Makefile targets in README

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds first-class EVM/MetaMask wallet support alongside the existing Cosmos/Interchain flow, a global header search that routes to block/tx/account inspectors, a new account inspector at /account/[address], and a dashboard "versions" footer (chain-id, node app version, EVM chain id, and a git-derived Hub version). It also refactors shared logic out of WalletScreen (a reusable TransactionHistory component and portfolio aggregation helpers), parameterizes fetchAccountInfo/useTransaction by address, adds staking-overview caching with a manual/auto refresh UI, surfaces the user's current governance vote, and fixes the wallet "Unstaking" total (reads unbonding_responses off the response object). Extensive Vitest suites and docs (README Quick Start, CHANGELOG v1.0.0) accompany the change.

Changes:

  • EVM wallet support: named EVM network profiles, MetaMask account/data fixes, idempotent WalletConnect init, and EVM-aware balance/transfer/tx-history handling.
  • New navigation/inspection features: global search parsing + dialog, account inspector screen, and a dashboard versions footer.
  • Refactors and fixes: extracted TransactionHistory/portfolio helpers, address-parameterized hooks, staking-overview cache + refresh UI, governance current-vote display, and the "Unstaking total = 0" bug fix.

Reviewed changes

Copilot reviewed 88 out of 94 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
turbo.json Declares NEXT_PUBLIC_* build inputs for cache correctness (missing NEXT_PUBLIC_EVM_PROFILE_NAME).
README.md Adds Make network targets and network-profile / EVM selection docs.
packages/ui/src/screens/StakingScreen/index.tsx Memoized validator-uptime map, canDelegate/refresh wiring into child components.
packages/ui/src/screens/StakingScreen/components/RewardsCalculator.tsx Gates the stake CTA on canDelegate with a Keplr prompt.
packages/ui/src/screens/StakingScreen/components/AllValidators.tsx Adds refresh UI (progress/last-updated) and MetaMask "not supported" banner; safer sort.
packages/ui/src/screens/HomeScreen.tsx Uses shared getPortfolioData, adds countdown + current-vote display in proposals/vote modal.
apps/web/src/contants/network.ts Adds named EVM profiles and EVM_PROFILE_NAME/IS_EVM_NETWORK derivation.
apps/web/src/app/providers/evm-wallet-provider.tsx New EIP-1193/MetaMask wallet context.
apps/web/src/utils/* (portfolio, search, account, evm, governance-votes, node-info, countdown, staking-overview-cache, transaction-history, …) New helper modules with accompanying tests.
apps/web/src/hooks/* (useStaking, useAccountInfo, useTransaction, useProposals, useWalletConnect, …) Address-parameterized fetching, staking cache/refresh, EVM-aware vote/tx queries.
packages/ui/src/screens/AccountScreen.tsx Full account inspector (balances, delegations, tx tabs).
Makefile / CHANGELOG.md Network run/build targets and v1.0.0 changelog.
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread turbo.json
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

@etapsc etapsc left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review

Verdict: merge with fixes. The EVM signing/address core is solid and well-tested; one user-facing vote-integrity bug and one silent-failure bug should be fixed first. Proposed fixes are attached as inline suggestions (validated locally: 130/130 pnpm --filter web test, tsc --noEmit clean with all suggestions applied).

Bugs

  1. HIGH — governance vote can sign a different option than the UI shows (useProposals state vs uncontrolled radio; 3 inline suggestions).
  2. MED — staking auto-refresh dies permanently after one failed refresh (useStaking timer only re-arms on lastUpdated change; 5 inline suggestions, with a 30s retry floor so failures don't tight-loop against the LCD).
  3. LOW — portfolio pie tooltip shows raw micro-LUME (HomeScreen.tsx:850-856 feeds getPortfolioData micro-units straight into the chart tooltip).
  4. LOW — search.ts:11-13 routes degenerate heights ("0", "007") to /block/0, /block/007.
  5. LOW — evm-wallet-provider.tsx:131-146: overlapping accountsChanged/chainChanged handlers race (last-async-write-wins), a transient RPC failure in assertEvmProviderMatchesRpc clears the connected address, and the error state is rendered nowhere.

Security — clean

No key material handled (signing stays in MetaMask/Keplr). EVM send path re-verifies sender/recipient at send time, uses exact BigInt decimal math, and defeats chain-ID spoofing by comparing a 12-blocks-back block hash between wallet provider and configured RPC (evm.ts:229-265) — nice. No XSS surface (search returns fixed path shapes only; no dangerouslySetInnerHTML). Wallet-mode isolation (forced Keplr disconnect under MetaMask) prevents address/mode confusion. New deps benign; cosmjs 0.36→0.39 pinned by the ethsecp256k1 behavior test.

Deploy/ops notes

  • NEXT_PUBLIC_NETWORK_PROFILE defaults to mainnet when unset; unknown values throw. Deployments must set it explicitly.
  • EVM UX auto-enables on testnet/devnet profiles and empty-string env overrides cannot disable it (all overrides use || fallback) — the only off-switch is the mainnet profile.
  • Version baking runs git describe --tags at build: Docker builds need .git with tags + a git binary or the footer shows a bare hash/unknown.
  • turbo.json env hash omits NEXT_PUBLIC_EVM_PROFILE_NAME and the baked git version — a tag-only rebuild can serve a stale cached bundle; skip turbo cache for release builds.
  • Dead config: NEXT_PUBLIC_EVM_WS_ENDPOINT is read by no runtime code; NEXT_PUBLIC_COSMOS_EIP712_ENABLED can never take effect while useWalletConnect.ts:32 hard-codes hasEvmCosmosSigner=false (intentional Phase-1 fail-closed, but the .env.example comment implies otherwise).
  • .env.example override comment says NEXT_PUBLIC_CHAIN_NAME=lumeratestnet; profile + Makefile use lumera-testnet.

Test gaps

No test pins the vote display/submit sync (bug 1) or the refresh scheduling loop (bug 2); transaction hooks' EVM wiring untested (only extracted helpers). The tests that exist are genuinely good — DI'd fetchers, upstream cosmjs behavior pins, negative address cases.

🤖 Generated with Claude Code

Comment thread packages/ui/src/screens/HomeScreen.tsx Outdated
Comment thread packages/ui/src/screens/GovernanceScreen.tsx Outdated
Comment thread packages/ui/src/screens/GovernanceDetailsScreen.tsx Outdated
Comment thread apps/web/src/utils/staking-overview-cache.ts
Comment thread apps/web/src/hooks/useStaking.ts
Comment thread apps/web/src/hooks/useStaking.ts
Comment thread apps/web/src/hooks/useStaking.ts
Comment thread apps/web/src/hooks/useStaking.ts Outdated
a-ok123 and others added 5 commits August 17, 2026 00:14
Co-authored-by: Kullat Nunu <ak@etapiscium.com>
Co-authored-by: Kullat Nunu <ak@etapiscium.com>
Co-authored-by: Kullat Nunu <ak@etapiscium.com>
Co-authored-by: Kullat Nunu <ak@etapiscium.com>
Co-authored-by: Kullat Nunu <ak@etapiscium.com>
Comment thread apps/web/src/hooks/useStaking.ts Fixed
a-ok123 and others added 4 commits August 17, 2026 00:27
Co-authored-by: Kullat Nunu <ak@etapiscium.com>
Co-authored-by: Kullat Nunu <ak@etapiscium.com>
Co-authored-by: Kullat Nunu <ak@etapiscium.com>
…tion or class'

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 88 out of 94 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file
Suppressed comments (1)

packages/ui/src/screens/HomeScreen.tsx:852

  • This change passes the raw micro-denom sums (stacked, liquid) into the donut chart, whereas the previous code converted them to display LUME via formatTokenDisplay before charting. The pie tooltip (trigger: 'item') renders the raw value, so on hover it will now show large micro amounts (e.g. 1234500000) instead of the formatted LUME figure. The wedge proportions are unchanged, but the tooltip value is a regression. Consider converting to display units before passing them to the chart.

Applying the review suggestions for the staking auto-refresh retry left the
branch unable to compile: the dependency-array suggestion was added without
replacing the original line, and the follow-up autofix then dropped the
STAKING_REFRESH_RETRY_DELAY_MS import that the new delay calculation needs.

Remove the duplicated dependency array and restore the import, then add
regression tests for the behaviour the fix was meant to deliver: a failed
refresh re-arms the timer instead of dying, retries persist across repeated
failures, and a success resets the attempt counter so the long cadence
resumes. Verified by reverting each half of the fix in turn - dropping the
refreshAttempt dependency fails all three tests, and dropping the retry
floor fails the tight-loop assertion.

These are the first React-rendering tests in the app, so jsdom is opted into
per file via a docblock and the other suites keep the node environment.
window.localStorage is stubbed because Node defines a localStorage global
that stays undefined without --localstorage-file, which vitest's jsdom
environment will not shadow.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@a-ok123
a-ok123 self-requested a review August 17, 2026 16:21
a-ok123
a-ok123 previously approved these changes Aug 17, 2026
akobrin1 and others added 6 commits August 17, 2026 12:46
Addresses the three low-severity review findings on this branch.

The portfolio pie carries micro-denom totals, so the default tooltip printed
raw micro-LUME beside figures that were already formatted. Format the tooltip
value through the same helper the surrounding labels use, so the two cannot
drift apart.

Global search treated any digit string as a block height, routing "0" and
"007" to /block/0 and /block/007. Strip leading zeros and reject an all-zero
height instead.

The EVM wallet sync had two defects. Overlapping accountsChanged and
chainChanged events each started a multi-round-trip sync, so the slowest
response won and could restore state a newer event had already superseded;
a sequence counter now discards stale results, and a cancelled flag stops a
sync that resolves after unmount. Separately, any verification failure
cleared the connected address, so a transient RPC error made the wallet look
disconnected. Distinguish the stages: a missing account or a genuine
EvmNetworkMismatchError still clears, while an unverifiable network keeps the
address and surfaces the reason. This does not weaken signing safety, because
the send path re-runs the same check via ensureNetwork before broadcasting.

The provider error state was also rendered nowhere, leaving the header simply
looking disconnected with no explanation. Show it as an alert chip that stays
visible whether or not an address survived, collapsing to icon-only on narrow
screens.

Verified by reverting the provider fix: the race test then reports the stale
address winning, and the transient-failure test reports a cleared address.
The mismatch and missing-account tests pass either way by design, pinning the
behaviour the fix had to preserve.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The hub's deployed revision (39aedbc) sits on develop, which is not an
ancestor of main. main has not moved since 2025-12-09 while develop
accumulated 264 commits and serves both production hubs. evm-support was
branched from the stale main, so it lacks that feature surface.

Records the decision to move the smaller tested change onto the live line
rather than the reverse, the file-by-file reconciliation plan for the 40
overlapping files, the wallet consolidation to Keplr + MetaMask, and a
route-parity gate to stop a wrong HUB_VERSION re-pin from silently
dropping routes from the public hub.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.

4 participants