Skip to content

Conversation

@Y3drk
Copy link
Contributor

@Y3drk Y3drk commented May 21, 2025

Closes #506 , which includes:

  • New panel title
  • SVG icons for each chain
  • Make block number a link to block explorer for the chains that allow it
  • Change time display from date to relative timestamp

@changeset-bot
Copy link

changeset-bot bot commented May 21, 2025

🦋 Changeset detected

Latest commit: 29a2e99

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 10 packages
Name Type
@ensnode/datasources Minor
ensadmin Minor
ensindexer Minor
ensrainbow Minor
@ensnode/ensrainbow-sdk Minor
@ensnode/ponder-metadata Minor
@ensnode/ensnode-schema Minor
@ensnode/ponder-subgraph Minor
@ensnode/ensnode-sdk Minor
@ensnode/shared-configs Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link

vercel bot commented May 21, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
admin.ensnode.io ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 10, 2025 11:09am
ensnode.io ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 10, 2025 11:09am
ensrainbow.io ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 10, 2025 11:09am

@Y3drk
Copy link
Contributor Author

Y3drk commented May 26, 2025

For whoever may review

I am a little confused about the display of block's timestamp.

In the Latest indexed registrations panel we leverage react hooks for display, but this approach wasn't employed in the Indexed chains panel (have a look at BlockStats component)

I was unsure what the right approach here was, and continued with the "static" display for the relative timestamp.
Changing it to leverage hooks should be super easy, I am just not sure we need them.

@Y3drk Y3drk marked this pull request as ready for review May 26, 2025 11:11
@Y3drk Y3drk requested a review from a team as a code owner May 26, 2025 11:11
Copy link
Member

@lightwalker-eth lightwalker-eth left a comment

Choose a reason for hiding this comment

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

@Y3drk Hey great job! 🚀 Reviewed and shared some suggestions with feedback 👍


if (
block.timestamp <= Math.floor(Date.now() / 1000) ||
calculatedRelativeTime === "less than a minute ago"
Copy link
Member

Choose a reason for hiding this comment

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

CleanShot 2025-05-26 at 18 31 10

Could you please investigate why both of these blocks are appearing like they have the same relative timestamp?

They have different absolute timestamps as can be confirmed by searching for these block numbers on Basescan: https://basescan.org/

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@lightwalker-eth
I investigated on such Base blocks:

  1. 30742968 - index time: May-26-2025 04:01:23 PM +UTC
  2. 30742961 - index time: May-26-2025 04:01:09 PM +UTC

The time difference between them is 14s, so the fact that both of them had just now relative timestamp was in line with the code at the time.

Why? Because of how we set up the formatRelativeTime function and the formatDistanceToNow helper function inside it. In the version I used till now, it would unify all timestamps that mark time under a minute ago to less than a minute ago, which would then be caught in the component and simplified to just now.

But your conclusion that the timestamps differ and it should be visible in the panel is very much valid, hence I made some changes, and now formatRelativeTime will accept an optional argument that will be responsible for injecting an includeSeconds option into the helper function, which will in turn return a more fine-grained relative timestamp.

Summing up:

  • The timestamps will now be more fine-grained and will include texts such as less than X seconds ago which should make the panel more detailed and less boring (multitude of descriptions rather than just now everywhere)
  • The just now text will now be solely reserved for the future edge case you described in the issue.
  • The optional argument allows backwards compatibility so there is no need to change any code from recent-registrations component that also uses the formatRelativeTime function

Below I'll paste how the panel looks with the aforementioned changes:
image

if (blockExplorerAvailableChains.includes(networkName)) {
return (
<a
href={`https://www.blockexplorer.com/${networkName.toLowerCase().replace(" ", "")}/block/${block.number}/#overview`}
Copy link
Member

Choose a reason for hiding this comment

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

We should use the "de-facto official" chain explorer for each blockchain.

I think @tk-o may have previously written some utility function for this somewhere? Can you please coordinate with him for some advice on this? Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

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

Spoke with @Y3drk about using the Datasource.chain getter to access selected chain configuration object defined by viem: Chain type.

Please note, the Chain value is not fully validated, i.e. it's type allows undefined block explorer.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@lightwalker-eth
Indeed, there was something similar. I got some good advice from Tomasz and applied it in the new solution that I'll describe in the comment about new chain-icon mapping strategy.

network: NetworkStatusViewModel;
}

type chainName =
Copy link
Member

Choose a reason for hiding this comment

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

Suggest we take a different strategy for this:

  1. We should pass chainId numbers around, rather than chain name strings. The issue with chain name strings is it creates interop problems: Is it "OP Mainnet" "Optimism" "Optimism Mainnet", etc..? But with a chain id number all can easily agree with interop.
  2. We should have a function that takes in a chain Id number and then returns the appropriate chain name for use in our UI.
  3. We should have a function that takes in a chain id number and then returns the appropriate icon for use in our UI.
  4. Both of the functions described in 2 and 3 above should throw an error if they see a chain id number they don't have predefined answers for.

Copy link
Contributor Author

@Y3drk Y3drk May 27, 2025

Choose a reason for hiding this comment

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

@lightwalker-eth

The 2nd point of your suggestion is already implemented via globalIndexingStatusViewModel function and getChainById helper function it uses, hence preventing incidents you described in 1st bullet from happening.

I've implemented the 3rd point of the suggestion with chainIcons map and getIconByChainId function.

To avoid boilerplate and limit prop drilling I've added two new fields to NetworkStatusViewModel interface, that is id:number which is chain's numerical identifier and blockExplorer an optional field that takes its structure directly from viem's Chain type.
Since these changes only add new fields (one of them even optional), I expect them to be backwards compatible.
I also updated unit tests for view-models.ts to accommodate for these changes, and the updated versions passed. I tested as thoroughly as I could to confirm that none of these changes break the app, and I am 99.99% sure of it.

These changes also simplified the display of the block's number as a link to chain's block explorer, addressing another comment on this PR.

Since these structures were designed by you, @tk-o, I'd appreciate it if you could confirm the described above changes as legit or share some suggestions on how to improve them.

| "Ethereum"
| "Linea Mainnet"
| "Sepolia"
| "Anvil"
Copy link
Member

Choose a reason for hiding this comment

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

Please check with Tomasz and Matt what name is appropriate to give to a local ethereum. I'm not sure it is fair to always call it "Anvil" and maybe we need a more generic term.

Copy link
Contributor

Choose a reason for hiding this comment

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

We can leverage viem's native configuration object for various chains. For example:

https://github.com/namehash/ensnode/blob/95119d2/apps/ensadmin/src/components/indexing-status/view-models.ts#L58

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@lightwalker-eth

Since https://github.com/wevm/viem/tree/main/src/chains/definitions contain definition for Anvil and lack some obvious generic replacement for it, I stuck with the current naming convention, all while applying new chain-icon approach that you proposed in the other comment.

@tk-o
If I missed some blatantly obvious replacement let me know :)

Copy link
Member

@lightwalker-eth lightwalker-eth left a comment

Choose a reason for hiding this comment

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

@Y3drk Thanks for the updates 👍 Reviewed and shared suggestions

Y3drk added 5 commits July 8, 2025 13:31
…trings, move getChainName to datasources package + beginning of refactors of block exploer & relative time helper functions
…helper functions + refactor of getBlockExplorerUrl function
…/feat-ensadmin-indexed-chains-panel-ui-improvements
Copy link
Member

@lightwalker-eth lightwalker-eth left a comment

Choose a reason for hiding this comment

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

@Y3drk Thank you. Approved. 👍 Shared a few small suggestions. Please take the lead to merge this when ready.

* Chain id standards are organized by the Ethereum Community @ https://github.com/ethereum-lists/chains
*/
const chainIcons = new Map<number, React.ReactNode>([
[mainnet.id, <EthereumIcon width={18} height={18} />],
Copy link
Member

Choose a reason for hiding this comment

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

This is a nice way to define the keys for one of these maps. Why aren't we doing the same in the other maps?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@lightwalker-eth

Perhaps I misunderstood your previous suggestions regarding these maps. Cause I assumed we didn't want the direct imports from viem used in there... Seems I was mistaken. My bad.

Will rollback chainNames and chainBlockExplorers maps to use these. That should also satisfy your request for simplification

…/datasources, minor styling adjustments, fix of formatRelativeTime function + minor docstrings changes
@Y3drk Y3drk merged commit 3c6378b into main Jul 10, 2025
7 checks passed
@Y3drk Y3drk deleted the y3drk/feat-ensadmin-indexed-chains-panel-ui-improvements branch July 10, 2025 11:12
@github-actions github-actions bot mentioned this pull request Jul 10, 2025
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.

Create the ENSNode Alpha-Sepolia instance in Railway ENSAdmin "Indexed Chains" panel UI improvements

5 participants