Skip to content

ensdomains/ens-app-v3

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

The ENS Manager App (V3)

Quick start

Install pnpm, then:

pnpm install
pnpm dev

Navigate to localhost:3000

Why does this app exist?

The purpose of the manager app is to expose the functionality of the ENS protocol in a user friendly manor.

Brief intro to ENS

ENS is a decentralized naming system that runs on the ethereum blockchain. The main purpose of ENS is to convert unfriendly blockchain addresses into human readable names (e.g. 0xb8c2c29ee19d8307cb7255e1cd9cbde883a267d5 -> nick.eth), but ENS has grown into so much more than that. For more info please visit our docs site.

Coming from web2

Web3 is the term used to describe the blockchain enabled web, web2 is the 'legacy' more centralized web. Much of this app is built in tech that will be familiar to many web2 devs.

Web2 tech

Web3 tech

Explaining the web3 parts

TBC

Setting up the development environment

You must have Docker installed to run the test environment. For more information on the environment, see ens-test-env.

Once installed, you can run:

pnpm denv
pnpm dev:glocal

You can now navigate to http:https://localhost:3000 to see the app running off of a local blockchain.

You will need a browser wallet to develop and test blockchain interactions. Download the Metamask browser extension here.

During the setup flow choose "Import existing wallet".

When it asks for your "Secret recovery phrase", use test test test test test test test test test test test junk

You can then follow the instructions here to connect metamask to our local dev blockchain.

You should now have 10,000 ETH (local network eth) in your wallet. You're a legend on your local machine.

Architecture

High level overview

High level architecture diagram

CI/CD

Github action scripts can be found in .github/workflows

Hosting

The App is hosted on cloudflare and IPFS

Major dependencies

Much of the logic around interacting with the ENS contracts has been extraced into this library. This is mostly so that we can help to make the experience of interacting with ENS as simple as possible for other developers.

As we have many different applications, and also would like to support the community, we have developed a design system in order to ensure consistent styling across the board.

Application Architecture: Key files and concepts

Pages and components

Pages folder has basic route layout and basic react needed for rendering pages. These files should be kept relatively simple

Components that pages consume are kept in the components folder. This folder has a strucutre that mimicks the strucutre of the pages folder. If a component is only used on a specific page then it goes into the corresponding folder in the components folder.

If a component is used across multiple pages and other components, then it goes into the atoms and molecules folder (link to atoms and molecules thingy).

useQuery

TBC

Transactions

TransactionStore.ts

Transaction store is responsible for keeping track of the state of transactions.

TransactionFlowProvider.ts

We noticed transactions always follow a similar pattern and so created an internal API to streamline this. A transaction flow is a series of steps that occur in a modal, culminating in a successful or failed transaction. Transactions can have either an intro or an input step before the transaction step.

Example of transaction with an input and multiple steps

  • Switch to test account 1 (the second account).
  • Go to 'My Names'
  • Select migrated-resolver-to-be-updated.eth
  • Click send
  • The Modal that pops up is rendered by the TransactionDialogManager, which is rendered by TransactionFlowProvider. The logic for rendering the different steps is contained here.
  • This button is in RolesSection.tsx, which gets its actions from useRoleActions.tsx. The onClick property here calls showSendNameInput from usePreparedDataInput. This is a helper function provided by the useTransactionFlow hook. We have various input components prepared already, they are defined in src/transaction-flow/input. This one is using input/SendName. Once the form data has been submitted we dispatch two actions to the TransactionFlowProvider reducer. One to set the transactions required, and the next one to advance to the next step of the transaction flow.
  • Enter any address or ENS name that exists in the dev environment
  • You should see a summary of changes, indicating the steps/transactions required
  • Follow the steps through and complete the multiple transactions
  • The code for managing the sending of transactions is in TransactionStageModal.

Sync Provider

This is for when the graph is behind and we are waiting for it to catchup.

Notification system

TBC

Metadata service

ENS names are NFTs. NFTs can have metadata associated with them, that is data associated with them that is not stored directly on-chain. One of the main use cases of this is to display a nice image that represents the ENS name. You can see an example of this here.

https://metadata.ens.domains/

Cloudflare workers

avatar-upload: url, src

gas-estimate-worker: url, src

app-v3-maintenance: url

moonpay-worker: url, src

etherscan-api worker: url

Data indexing

The graph hosted service: url, src

Unit Test

pnpm test
pnpm test:watch
pnpm test:coverage

If you need to deploy a new subgraph

You shouldn't deploy the subgraph on top of the existing dataset, instead you should create a clean dataset (explained below).

  1. Start the test environment
pnpm denv --save
  1. Deploy the subgraph

After the deploy scripts have run, you can deploy the subgraph. Assuming you are in the ens-subgraph repo, you can use:

yarn setup
  1. Wait for the subgraph to sync

Similar to the update process, a good indicator of sync status is if you see this message:

no chain head update for 30 seconds, polling for update, component: BlockStream

Dissimilar to the update process however is that you will never need to mine blocks manually.

  1. Exit the test environment

You can exit out of the test environment using Ctrl+C.

Once exited, you can commit the data to your branch. You do not need to run a separate save command.

E2E Testing

Note: You don't need to run the test environment command. It is all handled in the e2e script.

pnpm e2e

Building and Starting

pnpm build
pnpm start

# Or with the test environment running
pnpm build:glocal
pnpm buildandstart:glocal

Debugging

To debug a single test:

pnpm denv
pnpm dev:glocal
pnpm playwright test --project=stateless --ui stateless/extendNames

PR builds

Cloudflare will automatically build and deploy a test site when pushed to a new PR branch.

External Package Local Development

  1. Install yalc globally:
npm i -g yalc
  1. Run relevant update script within external repo, for example:
# Example publish script for ENSjs, be aware this may have changed.
pnpm publish:local:ensjs
  1. Run pnpm install within this repo:
pnpm install

If updating an existing yalc installation, you can add the --force flag.

Coding guidelines

  • any is strictly prohibited, tempting as it may be.
  • Prefer small functions that do one thing.
  • Most business logic should be outside of hooks, e.g. useEffect, useQuery etc is just there to manage react rendering and should be small, most of the logic should be in pure functions
  • ts-pattern for conditionally rendering components when something more than a ternary expression is needed
  • Critical pieces of logic should be unit tested

Testing philosophy

Our testing philosophy is user-centric, meaning we want to write out tests so that they resemble the way a user would use our app as much as possible. We've borrowed this from the excellent testing-library.

A user generally clicks, types and swipes, and so most tests should include one of these actions. A user may also load a page in a specific state (by clicking, typing or swiping outside of the app) so sometimes we just want to check a page renders correctly. The vast majority of our tests will be of these kinds.

For deeper parts of the codebase that aren't directly related to a user interaction, such as utility functions, the user is the developer. So simply test the code in the way a developer would use it.