Git Product home page Git Product logo

ens-app-v3's Introduction

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://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

Stateless vs Stateful

Our e2e tests are split into two categories, stateless and stateful. Stateless test use the development environment, are faster, and is the general recommended way to write integration tests. Occasionally, you may need to test a feature that requires an external api or service. In this case, you can use the stateful tests. These tests are slower,

Running the tests

Running the entire stateless test suite:

pnpm denv
pnpm dev:glocal
pnpm e2e

Running a single test within a browser:

pnpm denv
pnpm dev:glocal
pnpm e2e < filename >:< linenumber > --headed

Running the entire stateful test suite:

pnpm dev
pnpm e2e:stateful

Running a single stateful test within a browser:

pnpm dev
pnpm e2e:stateful < filename >:< linenumber > --headed

makeName

The most important function in the e2e stateless tests is makeName. This function is used to create a unique name for each test. This is important because we want to avoid any conflicts between tests.

Syntax
  const name = await makeName({
    label: 'name',
    type: 'legacy',
    owner: '0x1234567890123456789012345678901234567890',
    manager: '0x1234567890123456789012345678901234567890',
    resolver: '0x1234567890123456789012345678901234567890',
    records: {
      texts: [{
        key: 'text',
        value: 'value'
      }],
      coins: [{
        coin: 'eth',
        value: '0x1234567890123456789012345678901234567890'
      }],
      contentHash: 'bafybeico3uuyj3vphxpvbowchdwjlrlrh62awxscrnii7w7flu5z6fk77y',
      abi: await encodeAbi({ encodeAs: 'cbor', data: { test2: 'test2' } }),
    }
    subnames: [{
      label: 'subname',
      type: 'wrapped',
      owner: '0x1234567890123456789012345678901234567890',
      duration: 365,
      resolver: '0x1234567890123456789012345678901234567890',
      records: [{
        key: 'text',
        value: 'value'
      }]
    }]
  })
Parameters
nameOrNames

A single or an array of names to create. Each name can have the following properties:

label: string

The label of the name.

type: legacy | legacy-register | wrapped*

The type of the name. legacy names adopt the original data structure of ENS and are not ERC1155 complaint. wrapped names are names that have been wrapped with the NameWrapper contract and are ERC1155 compliant. legacy-register names simulate how mass registration services register names, usually without a resolver of other options that may increase gas.

owner: user | user2 | user3

defaults to owner

The address of the owner of the name.

manager: user | user2 | user3

defaults to value of owner

The address of the manager of the name. Only applicable to legacy and legacy-registr names.

duration: number

defaults to 365 days in seconds

The number of seconds the name will be registered for. Negative values are allowed to simulate names that have expired or are in the grace period.

secret: hex

defaults to a zero hex

The secret used during the register process. You will most likely not need to set this value.

resolver: address

defaults to the legacy resolver for legacy names and the latest resolver for wrapped names

The address of the resolver for the name. Used to test cases where the resolver is misconfgured or not set.

addr: address

defaults to the address of the owner

The address record for the name. Is used to test cases where the eth address is not set.

records: RecordOptions

The records for the name. Below is a type definition for the records object.

type RecordOptions = {
  texts: {
    key: string,
    value: string
  }[]
  coins: {
    coin: string | number,
    value: string
  }[]
  contentHash: string
  abi: AbiObject
}

fuses: FusesType

applicable to wrapped names only

The fuses to burn for a wrapped name. Below is a type definition for the fuses object. Note that PARENT_CANNOT_CONTROL is not fuse option as it is burned by default when a 2LD name is wrapped.

type FusesType = {
  named: Array<"CANNOT_UNWRAP" | "CANNOT_BURN_FUSES" | "CANNOT_TRANSFER" | "CANNOT_SET_RESOLVER" | "CANNOT_SET_TTL" | "CANNOT_CREATE_SUBDOMAIN" | "CANNOT_APPROVE">
}

subnames: SubnameType[]

The subnames for the name. Below is a type definition for the subname object.

type SubnameType = {
  label: string
  type: 'legacy' | 'wrapped'
  resolver: string
  records: RecordOptions
  duration: number
  subnames: SubnameType[]
  fuses: FusesType // Only applicable to wrapped names
}
options

timeOffset: number

defaults to 0

The duration in seconds to move the blockchain forward after the name has been registered. In rare use cases, usually when you are testing a name with a negative duration, the blockchain may need to be moved forward after all the transactions before it will resolve correctly.

syncSubgraph: boolean

defaults to true

Whether to wait for the subgraph to sync before returning the name. It is useful to set this value to false when you are testing a feature that does not rely on the subgraph to speed up the tests.

Returns

Returns a string for the 2LD name that is made up of the label with a timestamp appended to it and .eth TLD. The appended timestamp ensures that each time that a name is generated that it is unique.

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.

Knip Configuration Guide

1. Install Knip:

Install Knip as a development dependency in your project:

pnpm add -D knip

2. Add a knip script to your package.json:

Add a script to your package.json for easy access to Knip:

{
  "scripts": {
    ...,
    "knip": "knip",
    "knip:fix": "knip --fix --allow-remove-files"
  }
}

3. Create Knip Configuration File:

Create a knip.config.ts file at the root of your project. For more detail of configuration options, refer to the knip.config.ts file in the ENSDomains repository.

4. Run Knip:

To analyze your project, run Knip using the following command:

pnpm knip

Knip will exit with code 1 if any issues are found, such as unused files, dependencies, or exports that need to be removed.

5. Review and Remove Unused Files

After Knip completes its analysis, review the results. Manually remove any unused files that are safe to delete, or let Knip handle it automatically with the following command:

pnpm knip:fix

Ensure you carefully examine any files marked for removal to avoid accidentally deleting necessary code.

6. Run Unit Tests and E2E Tests:

After removing files, it's important to run your unit and end-to-end tests to ensure that everything is still functioning correctly:

pnpm test:coverage
pnpm e2e

ens-app-v3's People

Contributors

arachnid avatar cthulu-dot-eth avatar doplur avatar gskril avatar hibbb avatar jefflau avatar leonmanrolls avatar lucemans avatar makoto avatar mdtanrikulu avatar nhohb avatar o-az avatar rex4539 avatar stoooops avatar storywithoutend avatar sugh01 avatar talentlessguy avatar tateb avatar trees0x avatar wangereth avatar yeewiz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ens-app-v3's Issues

BNB and BSC are easily confused

This is the current situation:

Screenshot 2023-02-19 at 09 21 44

Since most people and platforms take BNB for the current Binance Smart Chain, indicating the nowdays Binance Smart Chain is better for BNB.

Here is the search result of BSC on Coingecko, seems BSC can't indicate any prevalent Chains:

Screenshot 2023-02-25 at 08 10 03

No address page nor cannot search by Ethereum Address.

On v2, clicking "My name" jumps to /address/0x134... and also you can search by address not owned by you.

Screenshot 2022-06-22 at 10 25 34

This feature is no longer available as search by address is invalid and also the slug is now /my/names .

Screenshot 2022-06-22 at 10 25 03

I think the previous URL scheme of /address/0x123 is better.

Z-Index on User Profile Dropdown

Peek.2022-07-05.10-16.mp4

The User Profile Dropdown appears to go underneath the table filtering on the name page, during the animation and resolves properly after. This is probably some kind of z-indexing issue.

Timer is unstable.

When I tried to buy an ENS name, I went to the timer page and ran a commit tx.

This tx seems to be going well, but ENS' pop-up was a bit laggy and I couldn't go to the registration page, instead, I see pages below.


Screenshots

Screen Shot 2023-11-03 at 22 09 08

Screen Shot 2023-11-03 at 22 09 14

Screen Shot 2023-11-03 at 22 09 22


I guess I can reach to the normal timer again once I wait for 86400 secs (maxCommitmentAge).

I tried making tx from etherscan but register function needs secret in the argment and I gave up checking it.

Discontiguous Upgrade Procedure

'Upgrade' feature consisting of two steps in not contiguous and cookie-dependent. If cookies are cleared/lost between step 1 (migrate profile) & step 2 (wrap name), user has to restart from scratch and pay for step 1 again (~ 41000 gas units). This can be reproduced with any name.

Example steps to recreate this on any name:

  1. Transaction 1 (Migrate): 0x8cf5a6c070c7cf0a157dcd5150162ffe15ada49a5f5cf70226b774a36772ba9d

  2. Clear cookies or restart browser

  3. Transaction 2 (Migrate again):
    0xfea15b8d1b04e12b59e1d72c7561c99e1e945aa42894341b669da6cebdb3972e

  4. Clear cookies or restart browser again

  5. Transaction 3 (Migrate again x2):
    0x5aada297e79d093978c0a9b7d0c01d3d530ae7f7cb26373907d984590dd0b1f6

  • Do not clear cookies after this step
  1. Transaction 4 (Wrap):
    0x089886bdc95c95a27a8a0db46c2c8cf61f7f02fcb00fb1a9fb1e59e640c9a038

UI shouldn't need cookies and should be able to check on-chain if step 1 has already been completed by a name before allowing step 2. UI even sends a prompt that user can leave the page and return to complete the process. This is highly misleading and doesn't mention that the user shouldn't close the browser.

pnpm dev getting error: client is undefined

I am trying to run ens app on my mac. But I am getting below error when I run pnpm dev:

TypeError: client is undefined
    useSubgraphClient useSubgraphClient.ts:9
    SyncProvider SyncProvider.tsx:98

dev error

I tried running ens-app-v3

Run this command:
pnpm install
pnpm dev

error occurred:

[email protected] dev C:\src\nodejs\ens-app-v3
next dev

ready - started server on 0.0.0.0:3000, url: http://localhost:3000
info - Loaded env from C:\src\nodejs\ens-app-v3.env
warn - You have enabled experimental feature(s).
warn - Experimental features are not covered by semver, and may cause unexpected or broken application behavior. Use them at your own risk.

wait - compiling...
error - ./node_modules/.pnpm/@[email protected]_6o7qlqixt7rvy6p5to6xkpdm2u/node_modules/@wagmi/core/connectors/coinbaseWallet/dist/wagmi-core-connectors-coinbaseWallet.esm.js
Error: Could not find module for providers
at String.replace ()

Revision: b534b7b
node: v16.19.0
system: windows 11

Connect Wallet (Metamask) not working in Firefox

When trying to connect a wallet with Firefox, the app doesn't detect the Metamask extension installed in the browser. Therefore, it redirects the user to scan the QR code. Works as expected with Chrome.

image

On a similar note, the button to "Add to Firefox" in the Get Metamask modal redirects the user to the Chrome store instead of the Firefox addons page.

d00de62688bb92a392eb5834d0a08811

Domain Name Transfer is Counterintuitive

When transferring a domain name to someone, they will not see it in their "Names" tap but rather have to search for the domain name.

Here are the current steps:

  1. Address A buys domain name
  2. Sends domain name to Address B
  3. Address B has to use the ENS search function to find the name, as it does not show up in the "Name" tab
  4. Address B has to change the address associated with the domain and set to "Primary Name"
  5. Address B does not see the name in the "Name" tab
  6. Address A still sees the domain in their "Name" tab, but is not the controller or Owner.

Better flow:

  1. Address A buys domain name
  2. Sends domain name to Address B
  3. Address B sees the new domain name in their "Name" tabs and can set / modify
  4. Address A does not see the transfered domain name in their "Name" tab anymore.

add hindi Language to website

I would like to add one more Language to the website which will help the users of India and increase userbase from India

Configure TLD

We would like to have TLD other than eth. Will it be enough to set baseNode in BaseRegistrarImplementation and related contracts and change eth in every place in application?

The ENS domain does not appear on Tab

  1. I've minted a domain to alpha.ens.domains
  2. When I try to view the created name on the page: alpha.ens.domains/my/names the site displays nothing
  3. but if I go to the tab: alpha.ens.domains/my/settings it is displayed correctly and set as 'Primary Name'

DNS Record Invalid (DNSSEC)

Specs:

TLD Name Provider: Namecheap
TLD: .com domain

After enabling DNSSEC, it takes 20-30 min to be recognized by the app.
The next step is to create a TXT record. However, it seems that the app is not recognizing it, even after waiting 24h.

Screenshot

Screenshot

subdomain shows an empty avatar image

Screenshot 2022-06-22 at 10 17 35

shouldn't it also just show steward.matoken.eth in the avatar image or is it only for NFT names liket matoken.eth?

FYI, other non NFT name like DNS name also does not show the avatar image but it doesn't have the frame either

Screenshot 2022-06-22 at 10 22 53

It looks inconsistent

Incorrect renewal fees for 3 and 4-character names

When extending 3 and 4-character names the manager app displays a cost of $5/year to the user, while the contract charges $640 & $160/year respectively. This is true for both the testnet and production deployments.

abc.eth abx8.eth
abc abx8

Release

When will the official release be available?

Using A tags instead of Buttons

It appears that in most places,
image
image
We are using button tags to do these. I would propose the usage of a tags, (using whatever implementation our router has) so that we are doing SPA-style routing when the link is clicked.

Benifits of switching include:

  • SEO / Linking
  • Better A11y, support for screenreaders etc
  • Middle clicking to open in new tab

CCIP-read and wildcard is not supported

Subname expiry does not display in manager app

Problem
When I set an expiry on a subname, the expiry does not display in manager.

Is the expiry correctly set?
Am I missing something?

Details:
nachos.lovedaos.eth has been set to expire on 1683102616 (the current time is 1683023981).

Etherscan result for 0x2ed723f2e69d9b783e0b4912f8a2e258e72ab62f342fe6be77f4822cc1446a34 (nachos.lovedaos.eth)

id (uint256): 0x2ed723f2e69d9b783e0b4912f8a2e258e72ab62f342fe6be77f4822cc1446a34

[ getData(uint256) method Response ]
  owner   address :  [0xDC3c886D5b0528E9C99F66820f9F2409a2e8C2cA](https://etherscan.io/address/0xDC3c886D5b0528E9C99F66820f9F2409a2e8C2cA)
  fuses   uint32 :  262144
  expiry   uint64 :  1683102616

image

https://app.ens.domains/nachos.lovedaos.eth does not display the expiry date:
image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.