ensdomains / ensjs-v2

Javascript bindings for the Ethereum Name Service
206 stars 121 forks source link

Poor "getting started" documentation here and on the npm page #69

Open cyrusadkisson opened 3 years ago

cyrusadkisson commented 3 years ago

I'm by no means a node/javascript expert, but I don't think I'm a dumb-dumb either. But I literally could not figure out how to use this module in my application after about 2 (err, now 3) hours of trying. This is essentially the extent of your getting started documentation:

import ENS, { getEnsAddress } from '@ensdomains/ensjs'

const ens = new ENS({ provider, ensAddress: getEnsAddress('1') })

ens.name('resolver.eth').getAddress() // 0x123

Which may seem obvious to experts but was difficult to decipher for me and probably for other folks.

  1. The "import something, {somethingElse}" syntax was not familiar to me. IMO, you should either explain it with a comment or break it into multiple declarations. Minimizing code may be helpful in some circumstances, but when teaching with an example, readability is paramount.
  2. Many dapps are still on the "require" system as that's how web3js documentation still says to do it. It took me a few attempts to figure out the right "var ENS = require" declaration to move forward.
  3. At the point of giving up, I'm getting errors about "provider" being undefined.
  4. Why use "resolver.eth" as your example lookup? That's just confusing.
  5. "ens.name('resolver.eth').getAddress()" is a promise (unless I'm mistaken) that needs to handled with a .then or in some other way. Why not include that syntax? Why show an incomplete example?
  6. Size - including ensdomains in my AWS deployable nodejs bundle jumped the package size from 12.5 MB to 44 MB. By comparison, ethereum-ens adds less than 1 MB.
  7. I can't find where you explain why you forked this off of "ethereum-ens". What was the problem?
  8. Is there a browser-deployable min.js package?

Anyway I've given up and will try ethers.js or something.

If you're trying to maximize integrations and this repo is not ready for prime time (and this appears the case by the issues load and my own troubles), I would suggest marking it as such to prevent others from falling down this hole.

jefflau commented 3 years ago

Thank you for the feedback, it’s helpful to know the trouble you went through and we’ll do better to make this package easier to use and improve documentation.

Thank you again for taking the time to write this up. I’m happy to take this to DMs on Twitter (_jefflau) if you still want to help us the improve this package, we’ve definitely not prioritised it and I will endeavor to improve this as soon as possible.

jefflau commented 3 years ago

I have had a quick go at setting it up myself from scratch and I've updated the docs (as a start). Can you have a look to see if this works for you out the box? I think as you said it's important to have the setup work by copying and pasting.

I will work on some of your other requests as soon as I can.

This is the readme: https://github.com/ensdomains/ensjs/blob/0d6f4e99a57539c79cf3f9dcdebc1b3793cb7a49/README.md

and this is the PR: https://github.com/ensdomains/ensjs/pull/70

cyrusadkisson commented 3 years ago

Thank you but I'm still stuck on reverse resolution and I'm following the ENS docs as closely as I can with as many brain cells as I can muster. Apparently it's not enough.

const ENSModule = require('@ensdomains/ensjs');
const ENS = ENSModule.default;
const getEnsAddress = ENSModule.getEnsAddress;

const ens = new ENS({ provider, ensAddress:getEnsAddress('1') })
ens.name('ens.eth').getAddress().then(addr => console.log("addr=" + addr)) 
> 0xb6E040C9ECAaE172a89bD561c5F73e1C48d28cd9

var address = '0xb6E040C9ECAaE172a89bD561c5F73e1C48d28cd9';
ens.getName(address).then( result => console.log("name=" + JSON.stringify(result)));
>  name={"name":null}

Why am I getting back "null"? I literally just resolved that name to the given address.

And the docs (https://docs.ens.domains/dapp-developer-guide/resolving-names) try to describe using a special domain x.addr.reverse but don't provide any examples and I can't figure out the right formula for using this method either. What methods? Is the address wrapped in a string? Is the whole thing a string? What should the response look like?

Is there a complete technical reference like there is for web3js (or any other mature project, for that matter)?

jefflau commented 3 years ago

Reverse records need to be set manually. So you need to do:

address => setName(‘ens.eth’)

addresses are set using a special namespace, which is [address].addr.reverse

To set this you need to use the reverse registrar to claim this “reverse node”. Then you setup a resolver as normal and then setName on that reverse node.

After that you can then do ens.getName and get the name associated with that address.

cyrusadkisson commented 3 years ago

Ok I don't understand this at all. I just need to reverse various addresses and see if there are ENS addresses. That's all. Can you show me a full code snippet for my requirement?

edit: To be clear I don't ever need to set any ENS names. Read-only reverse lookups.

edit2: Figured it out, I think. Some reverse lookups don't work? The reverse lookup has to be manually set by the owner? Still not totally grokking this. Anyway here is the solution that works for some names.

const ENSModule = require('@ensdomains/ensjs');
//const ethers = require('ethers');

const ENS = ENSModule.default;
const getEnsAddress = ENSModule.getEnsAddress;
console.log("using ENS address=" + getEnsAddress('1'));

//Provider can be a web3 or ethers provider
//const provider = new ethers.providers.JsonRpcProvider('https://main-light.eth.linkpool.io/');

const ens = new ENS({ provider, ensAddress: getEnsAddress('1') })
ens.name('somename.eth').getAddress().then(function(addr) {
    console.log("addr=" + addr)
    ens.getName(addr).then(result => console.log("name=" + JSON.stringify(result)));
});
jefflau commented 3 years ago

Yes exactly, you can have many names that resolve to one address. e.g. cyrus1.eth, cyrus2.eth could all resolver to 0x123, but you can only have 1 reverse records, e.g if you own 0x123, you can set that to resolver to cyrus1.eth.

cyrusadkisson commented 3 years ago

Is there a master reverse resolver that most people use? Do services like Etherscan somehow keep track of all the reverse lookups on their own by watching a stream of events that set these values?

elboletaire commented 2 years ago

Hey and what about all the write options? How am I supposed to update or create a subdomain if I cannot set a custom signer?

Sorry I'm kinda newbie in web3, but clearly this documentation needs an update (and I'm thankful I did found this issue, otherwise I'd be still stuck trying to just read a record).

danielcolinjames commented 2 years ago

hey @jefflau, just want to add my 2 cents here and say that I agree with the original post here. I'm new to Ethereum development stuff but just starting to poke around.

I'm a huge fan of ENS and I think it's one of the most exciting projects in the crypto space. we even support sending HNT to ENS names in the Helium app if they have a Helium wallet address specified

but right now I'm doing a little learning project to try and get a handle on ENS / basic Ethereum development, so I want to just do a simple lookup to see if an address has a reverse record/primary name set on ENS, and like Cyrus, I am really struggling to use the current documentation to help me figure it out with either ensjs or any of the other options...

I am also seeing the same error cyrus described:

errors about "provider" being undefined

I guess that provider is just a placeholder example, and I would need to define it before that snippet? (but doing so has just resulted in different errors so far). and ensAddress: getEnsAddress("1") is also confusing to me. is ("1") a placeholder example, or is "1" a valid option there? what would normally go there if it's a placeholder—an address?

I assume that object as the argument for the new ENS() instantiation is like the config for the ENS object, but it's really not quite clear to me what that bit of code is doing or how it works and I can't find any good info about it on the docs site

I kind of expect it to just be like:

const ens = new ENS()

and then be able to call a bunch of useful functions from ens, but changing it to that ^ just gives me: TypeError: Cannot read properties of undefined (reading 'networkId')

I made the (I guess faulty) assumption that the Getting Started code snippet would "just work"

I know you're all probably busy with lots of different things but I really think it's important that the Getting Started code snippet(s) should:

  1. just work
  2. show in one or two lines how to check if a primary name has been set for 0x123
  3. show in one or two lines how to get the address of banana.eth

anyway just some thoughts as I jump between dozens of browser tabs to try to make sense of this...

thanks for all the work you do on this important protocol! I hope to understand it well enough to contribute on the docs site and the frontend(s) soon (I think Brantly said in a Twitter Spaces room that the Figma file for the new manager might be shared to the community soon? 👀 I'd love to help build it)

peduarte commented 2 years ago

Im banging my head too :/

could someone ELI5 what is provider?