Coder Social home page Coder Social logo

ens-app's Introduction

ENS Application

ENS Application

⚠️ IMPORTANT NOTE TO CONTRIBUTORS ⚠️

As work has begun on the next version of the ENS app, please do not submit PRs for issues marked 'redesign' or 'post-redesign'. We will soon have info on how to contribute to the new app. Thanks for all your hard work!

Installation

Manual

Expects Node.js version >=14.17.0

$> git clone https://github.com/ensdomains/ens-app.git
$> cd ens-app
$> yarn install
$> yarn start

Open your browser at localhost:3000 and open metamask.

To start the ipfs-enabled build:

yarn start:ipfs

The main difference of the ipfs-build is that it uses HashRouter instead of BrowserRouter and makes sure all links are relative.

The ENS app can be used with the Gnosis Safe web interface. The required steps are outline here.

Unit Testing

All tests are run with Jest for both the front-end application and testing blockchain functionality. For blockchain based tests it uses ganache-cli by default. If you want to see the transactions in the Ganache GUI, you can change the environment in the test file from GANACHE_CLI to GANACHE. Then you can open Ganache on your computer and test manually after the test runner deploys the contracts.

To run the tests:

npm test

To speed up the tests, the contracts are compiled before the tests. If you need to update the solidity code, you can run npm run compile to recompile the code. Alternatively you can uncomment the code that compiles the contracts in the tests, which will slow down the tests considerably.

Troubleshooting tests

If you get this error:

$ npm test

> [email protected] test /Users/youruser/drive/projects/ens-app
> react-scripts test --env=jsdom

2018-05-23 09:17 node[85833] (FSEvents.framework) FSEventStreamStart: register_with_server: ERROR: f2d_register_rpc() => (null) (-22)
2018-05-23 09:17 node[85833] (FSEvents.framework) FSEventStreamStart: register_with_server: ERROR: f2d_register_rpc() => (null) (-22)
events.js:136
      throw er; // Unhandled 'error' event
      ^

Error: Error watching file for changes: EMFILE
    at _errnoException (util.js:999:13)
    at FSEvent.FSWatcher._handle.onchange (fs.js:1374:9)
npm ERR! Test failed.  See above for more details.

Try installing watchman on OSX by doing:

brew uninstall watchman
brew install watchman

Coding Style and Contribution Guide

Importing and Exporting

Global modules will be imported first regardless, e.g. React, ReactDOM and any other libraries that are installed via NPM. Imports thereafter will be separated by type with line separating each type. Generally React components will only have one export, unless there are multiple versions of that component, or it's a collection of related styled components. Since there are generally only one export, we will use export default to allow more flexibility.

import React from 'react'
import ReactDOM from 'react'
import styled from '@emotion/styled/macro'

import util from '../utils'

import ComponentA from '../components/ComponentA'
import ComponentB from '../components/ComponentB'

export

React Style

We use a functional components, using hooks instead of class based components. For basic state we use useState and for more complicated state useReducer. If they reusable, then you can abstract them to the hooks file, which can additionally by split up into a folder once we have enough hooks.

import React, { useState } from 'react'

export default function Component({ someProp }) {
  const [state, setState] = useState(null)
  return <div>...</div>
}

CSS/Styling

Styling in this app is done with Emotion, with styled components style CSS. We do not use css or classNames, unless we are passing through the styles to a component. We use the babel plugin macros import as this enables labels and source mapping for our components. We also use parentheses for all styled components to keep consistency when we create components that compose with each other.

import styled from '@emotion/styled/macro'

const Component = styled('div')`
  display: flex;
`

Media Queries

The main way to use media queries is with the helper function mq located in the root at mediaQuery. We have absolute URL support, so you can just import it directly as mediaQuery. It has properties for all the breakpoints supported by our app. We also have a useMediaMin hook, which we plan to roll out to replace the render prop version when we can convert all our components to functional components.

Currently supported breakpoints:

const breakpoints = {
  small: 576,
  medium: 768,
  large: 992,
  xLarge: 1200
}

You can use it as follows:

import styled from '@emotion/styled/macro'
import mq from 'mediaQuery'

const SomeComponent = styled('div')`
  font-size: 14px;
  ${mq.small`
    font-size: 22px;
  `}
`

The second way is using hooks, which uses useEffect and useState underneath. This must be used with functional components.

import { useMediaMin } from './mediaQuery'

function Component(){
  const mediumBP = useMediaMin('medium')
  return <>
    {mediumBP ? <LargeComponent /> : <SmallComponent />}
  <>
}

Cypress testing best practice.

Cypress end 2 end testing tends to be very flakey when ran on CI environment.

  • Assert the existence before assert the non existence = Cypress waits until the default timeout (set to 12 sec) to make sure that the element does not exist whereas asserting the existence of an element completes as soon as the element becomes visible. Try to assert existing element with default timeout, then try to assert non-existing element with timeout:0 to speed up.
  • Fix warnings = Sometimes React elements render in the strange way very subtly which may not be visible by human but can be detected by automated test. If some assertion is failing, check if there are warning and try to fix them first.
  • Make use of testid rather than asserting with css attributes (such as color) = Asserting to change if button becomes clickable tends to be flakey as you have to manually loop and check the css attribute rather than allowing cypress to wait with built-in timeout feature. Try to set testid such as button-${ canClick ? 'enabled' : 'disabled' } so that you can set assertion against enabled/disabled condition.
  • Consolidate tests where applicable = Even though it's discouraged in unit testing, doing so will save time for setup/teardown. If test is slow because it's doing lots of setup/teardown for each test cast, try to consolidate them.

Internationalisation

We use the i18next and react-i18next package for internationlisation.

Currently we use /public/locales/[language].json for translation. Each property should be a page or reusable component. The only exception to this is c which is a namespace we are using for common language throughout the app that will have to be reused over and over.

Adding a new language

To add a new language, copy the public/locals/en.json file, and name it [language].js and then you can begin to translate each label one by one.

The other thing that needs to be changed is LanguageSwitcher.js, which has a list of currently supported languages, and the i18n.js init file. This will add the language to our dropdown menu.

Once this has been done, please create a pull request for us to review and check it has been done correctly.

End to end Testing

Getting started with E2E testing

In case you haven't already:

  • git clone https://github.com/ensdomains/ens-app.git
  • git clone https://github.com/ensdomains/ens-subgraph

You need to make sure these are all cloned into the same parent folder.

Next in the ens-app folder run the following (will need multiple terminals open):

npx ganache-cli -b 1

Install Docker: https://www.docker.com/get-started

in the ens-app folder:

rm -rf data
docker-compose up

in the ens-app folder:

yarn preTest
yarn subgraph

in the ens-subgraph folder:

yarn setup

in the ens-app folder:

yarn start:test
yarn run cypress:open

This should open up cypress. To run the tests click on 'Run n integration tests'


The main package for the E2E tests is ensdomains/mock, which exposes a script that will prepopulate ganache with ENS so you have everything setup to run Cypress on.

The ENS app has end to end tests with Cypress. To run them you need to start ganache, run the seed script, run the app and then run cypress. This should start chrome and the Cypress GUI. Each time the test run, the script needs to be re-run and the app restarted for it to work.

ganache-cli
yarn run preTest

This runs the app in local ganache mode:

yarn start:test
yarn run cypress:open

To test the ipfs-build use the respective ":ipfs"-variants of the scripts:

yarn start:test:ipfs
yarn run cypress:open:ipfs

Setting up subgraph

Subgraph is used to list subdomains and all the names you have registered.

Prerequisite

Get ens subgraph

git clone https://github.com/ensdomains/ens-subgraph
cd ens-subgraph
yarn

Get graph-node

git clone https://github.com/graphprotocol/graph-node

From now on, we assume that graph-node, ens-app, and ens-subgraph all exist under the same directory

Start ganache

ganache-cli

Download and start docker

Download and start docker first

Start thegraph node

This starts up docker with ipfs, postgresdb, and the-graph node.

cd graph-node/docker
docker-compose up

Deploy ENS contracts and update subgraph.yml

cd ens-app
yarn preTest
yarn subgraph

subgraph job updates ENS contract addresses and updates environment from mainnet to dev

Deploy ENS subgraph

Generate deployment code

cd ../ens-subgraph
yarn
yarn codegen

Deploy

yarn create-local
yarn deploy-local

NOTE: If it raises error, try to delete graph-node/docker/data and startup the docker again.

Confirm that you can query from browser

Screenshot 2019-07-17 at 11 34 59

Bundle size

If you add a new package or make a change to the way files are being imported (e.g. adding an import statement to a file), you should run yarn build before and after the changes and you will see how your changes have impacted the bundle sizes on the second run.

if the bundle size has changed significantly (100kb+) you probably want to consider taking steps to mitigate this:

ens-app's People

Contributors

0xwizardof0x avatar 0xzoomeye avatar alexandergu avatar arachnid avatar arnaud-eb avatar brantlymillegan avatar chasec99 avatar claudiocantara avatar dallasc avatar danchousz avatar dependabot[bot] avatar eltociear avatar hacktar avatar jackson-jackson avatar jefflau avatar katakoto avatar leonmanrolls avatar makoto avatar marvinkruse avatar mdtanrikulu avatar mjpowersjr avatar mmv08 avatar rmeissner avatar sapjax avatar sean-b765 avatar srt32 avatar storywithoutend avatar tateb avatar yutasugimura avatar zorro909 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's Issues

Support looking up TLDs and the root

As a general purpose tool, I should be able to look up 'eth' and get the page describing it. From there it should be possible to look at 'parent domain' and examine the root, too.

Do not whitelist domains

Currently domains are whitelisted. Need to remove all whitelisting to allow all kinds of domains as whitelisting is unsustainable

Mobile App Display Sizing Optimization

Tested on Status iOS browser v0.9.30 (11274); node 0.16.3

Mobile app screens are slightly too wide to fit screen when first loaded. Upon returning to the same page in the same browser session, screen width fits screen well.

See screen capture here.

Refactor queries into mutations so queries are just getting from cache

Currently using queries to also get data, but I should split the mutations up into blockchain state changes and blockchain reads. Front-end will use mutations for both and queries only to read from cache (without reading from the blockchain). Mutations should be used to 'mutate' the cache, not the blockchain

Add visual validation for add record

Currently only changing an address field will show the tick validation. We need it for the AddRecord component that allows the adding of records prior to a record existing.

Check what records the resolver supports

App needs to check which records the resolver supports and allow the new contenthash to be set for the new resolver. Old resolvers will not support this, so if a name is on the old resolver, it should be able to set the old 'content' field

Search Results Page Won't Resolve in Chrome

Chrome - Version 70.0.3538.102 (Official Build) (64-bit)

Summary -

Search results page appears blank after searching on a name.

Steps -

1 - Navigate http://ensappdev.surge.sh/

2 - Allow Metamask to connect

3 - Type "chrisremus" or "chrisremus.eth" into search box

4 - Hit "Return"

Console output -

chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/inpage.js:1 ATTENTION: In an effort to improve user privacy, MetaMask stopped exposing user accounts to dapps if "privacy mode" is enabled on November 2nd, 2018. Dapps should now call provider.enable() in order to view and use accounts. Please see https://bit.ly/2QQHXvF for complete information and up-to-date example code.
(anonymous) @ chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/inpage.js:1
main.a8d7ac45.chunk.js:1 Dapp browser active with injected ethereum object
main.a8d7ac45.chunk.js:1 supported
1.7580c053.chunk.js:1 TypeError: Cannot read property 'name' of undefined
at Object.children (main.a8d7ac45.chunk.js:1)
at main.a8d7ac45.chunk.js:1
at e.render (1.7580c053.chunk.js:1)
at ai (1.7580c053.chunk.js:1)
at oi (1.7580c053.chunk.js:1)
at di (1.7580c053.chunk.js:1)
at Gi (1.7580c053.chunk.js:1)
at Ki (1.7580c053.chunk.js:1)
at Iu (1.7580c053.chunk.js:1)
at Pu (1.7580c053.chunk.js:1)
at ku (1.7580c053.chunk.js:1)
at Ji (1.7580c053.chunk.js:1)
at Object.enqueueForceUpdate (1.7580c053.chunk.js:1)
at e.w.forceUpdate (1.7580c053.chunk.js:1)
at e.r.updateCurrentData (1.7580c053.chunk.js:1)
at Object.next (1.7580c053.chunk.js:1)
gi @ 1.7580c053.chunk.js:1
1.7580c053.chunk.js:1 Uncaught TypeError: Cannot read property 'name' of undefined
at Object.children (main.a8d7ac45.chunk.js:1)
at main.a8d7ac45.chunk.js:1
at e.render (1.7580c053.chunk.js:1)
at ai (1.7580c053.chunk.js:1)
at oi (1.7580c053.chunk.js:1)
at di (1.7580c053.chunk.js:1)
at Gi (1.7580c053.chunk.js:1)
at Ki (1.7580c053.chunk.js:1)
at Iu (1.7580c053.chunk.js:1)
at Pu (1.7580c053.chunk.js:1)
at ku (1.7580c053.chunk.js:1)
at Ji (1.7580c053.chunk.js:1)
at Object.enqueueForceUpdate (1.7580c053.chunk.js:1)
at e.w.forceUpdate (1.7580c053.chunk.js:1)
at e.r.updateCurrentData (1.7580c053.chunk.js:1)
at Object.next (1.7580c053.chunk.js:1)

Search Results Page Won't Resolve in Firefox

Firefox v63.0

Summary -

Search results page appears blank after searching on a name.

Steps -

1 - Navigate http://ensappdev.surge.sh/

2 - Allow Metamask to connect

3 - Type "chrisremus" or "chrisremus.eth" into search box

4 - Hit "Return)

Console output -

ATTENTION: In an effort to improve user privacy, MetaMask stopped exposing user accounts to dapps if "privacy mode" is enabled on November 2nd, 2018. Dapps should now call provider.enable() in order to view and use accounts. Please see https://bit.ly/2QQHXvF for complete information and up-to-date example code. inpage.js:1:1206
Dapp browser active with injected ethereum object web3.js:36:12

TypeError: "i is undefined" value http://ensappdev.surge.sh/static/js/main.a8d7ac45.chunk.js:1:139401 value http://ensappdev.surge.sh/static/js/main.a8d7ac45.chunk.js:1:91804 render http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:16001 ai http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:892926 oi http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:892721 di http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:896878 Gi http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:911869 Ki http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:912246 Iu http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:918738 Pu http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:918118 ku http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:917139 Ji http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:916042 enqueueForceUpdate http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:880762 forceUpdate http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:828784 updateCurrentData http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:13573 next http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:13269 y http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:938949 m http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:939455 value http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:940072 next http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:343202 next http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:343155 queryListenerForObserver http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:681556 broadcastQueries http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:686874 broadcastQueries http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:686854 broadcastQueries http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:686748 next http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:687932 y http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:938949 m http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:939455 value http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:940072 next http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:668132 next http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:668098 y http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:938949 m http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:939455 value http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:940072 next http://ensappdev.surge.sh/static/js/1.7580c053.chunk.js:1:745516react-dom.production.min.js:3841

TypeError: i is undefined[Learn More] ReverseRecord.js:12:19

Investigate creating a settings page

Had discussions with @Arachnid about adding enjinx as a block explorer option so the user can choose between etherscan or enjinx. This raises the question - how do we store this data? The most direct and obvious is to have it in localStorage. Currently we do not store anything apart from favourites in local storage. For the permanent registrar we will likely need to store reveal details that we send on behalf of the user. Therefore we should spend some time investigating and researching how we should best architect this solution. The solution I expect will be client-side only at first, then we will be able to sync to a centralised back-end or storage solution of some sort in the future (IPFS/Swarm)

Unable to Create Subdomains

Chrome Version 70.0.3538.110 (Official Build) (64-bit)
Firefox 63.0.1 (64-bit)

Summary -

Unable to create subdomains of owned domain.

Steps -

1 - Navigate to https://manager-beta.ens.domains

2 - Allow Metamask to connect

3 - Search for name

4 - Click on Details button for owned name on search results page

5 - Click Subdomains

6 - Click Add Subdomain

7 - Enter subdomain, see green check mark, Save button does not activate

screen shot 2018-11-29 at 1 40 31 pm

Adding Records and Resolvers Exhibits Inconsistent Behavior

Regarding records and resolver setting -

screen shot 2019-01-04 at 12 16 12 pm

Adding records and resolver transactions are initiated in the Dapp and confirmed in Metamask. The Dapp exhibits these behaviors, across Chrome and Firefox to varying degrees -

1 - After Tx confirmation, resolver doesn't appear set unless page is refreshed, sometimes it doesn't appear at all.

2 - After Tx confirmation, records don't appear set, even after page refresh.

Support search API

The app should support the 'tab to search' facilities used for the Chrome address bar.

Clarify In-Process Auction State Display

Chrome Version 70.0.3538.110 (Official Build) (64-bit) (suspected same behavior in Firefox too)

Summary -

In-process auction state counts down bid period, then begins counting up when reveal period is entered. Shows state as Bidding Period, even when in reveal period.

Steps -

1 - Navigate to https://manager-beta.ens.domains

2 - Allow Metamask to connect

3 - Find an auction close to entering reveal period, by scrolling back a few days on the twitter.com/ensbot account.

4 - Hit "Return"

screen shot 2018-11-28 at 1 02 33 pm

You'll see the Bidding period count down from "a few minutes" to "a few seconds", then start counting back up from "a few seconds" to "a few minutes", while still displaying "Bidding Period".

Add transaction tracking for each mutation

Currently we are showing the tx pending when the mutation starts, but we want to show it when the transactions has been confirmed in the dapp browser. This is because we have no way of knowing when this is accepted in web3 1.0 as the resolvers wait for the resolver to confirm before returning onCompleted. Previously in web3 0.20 it returns the txHash immediately. So we need to add that transaction to a history of transaction to track the status of a pending transaction.

In the future we can also use this to create a transaction history UI that lists all past transactions. Alternatively if we have a back-end store this, we can keep it persistent across accounts.

'No Accounts' bttn missing when not connected to metamask

Chrome Version Version 71.0.3578.80 (Official Build) (64-bit)

Summary:

If you don't connect to metamask, the 'no accounts' bttn doesn't appear on the landing page or search results page.

Steps:

1 - Navigate to https://manager-beta.ens.domains

2 - Don't connect to metamask

3 - Notice there is no 'no accounts' on landing page

4 - Search for a name

5 - Area in side nav where 'no accounts' would be has a perpetual loader / bttn never appears

screen shot 2018-12-10 at 10 35 16 am

Investigate migrating back to single web3 provider

Due to a metamask/web3 1.0 issue, reads from contracts sometimes fail/

The issue has been documented here by the Origin Protocol team:

OriginProtocol/origin#799

And they have filed an issue with Metamask, which I have also followed up with our own comment:

MetaMask/metamask-extension#5588

A possible solution is to add a separate read provider via Infura or Etherscan. We will lose the benefit on metamask caching which speeds up refreshes, unless we create a caching solution ourselves, and/or have a backend that indexes events. Another overhead would be having multiple providers, although I expect this won't be a huge problem.

Origin have also documented their desire to split read and write providers:

OriginProtocol/origin#682

If this gets fixed in the future, we should investigate migrating back to a single provider

Migrate all render props to hooks

React hooks is soon to be released and I would like to migrate all current render props into hooks so we can create a consistent coding standard for the entire app. Currently we have the Editable render prop, which I have converted to a hook, but needs to be added to AddRecord and AddSubdomain components. Moving forward any new component APIs should also use useState, useReducer, useEffect instead of the class based APIs

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.