From fe7ae91ee4c31edb26fc2f9f2472231639d1a545 Mon Sep 17 00:00:00 2001 From: emmett Date: Thu, 31 Oct 2019 22:19:35 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9tabs=20=E5=8F=8A=20hint=20?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=20=EF=BC=8C=E4=BB=A5=E4=BE=BF=E7=BC=96?= =?UTF-8?q?=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../.eth-permanent-registrar/controller.md | 9 +-- contract-api-reference/publicresolver.md | 4 +- .../front-end-design-guidelines.md | 18 +++-- dapp-developer-guide/managing-names.md | 69 ++++++------------- dapp-developer-guide/resolving-names.md | 64 +++++++---------- dapp-developer-guide/working-with-ens.md | 28 +++----- 6 files changed, 67 insertions(+), 125 deletions(-) diff --git a/contract-api-reference/.eth-permanent-registrar/controller.md b/contract-api-reference/.eth-permanent-registrar/controller.md index 7e295b41..d9853f4b 100644 --- a/contract-api-reference/.eth-permanent-registrar/controller.md +++ b/contract-api-reference/.eth-permanent-registrar/controller.md @@ -21,8 +21,7 @@ 下面的示例演示了注册域名所需的步骤。 -{% tabs %} -{% tab title="web3.js" %} +**web3.js** ```javascript const controller = web3.eth.contract(controller_abi).at(controller_address); async function register(name, owner, duration) { @@ -42,11 +41,7 @@ async function register(name, owner, duration) { } ``` -{% hint style="info" %} -For clarity, this example is written using async rather than callbacks. As a result, this example works in web3 1.0.x; note that it will not work in the web3 injected by MetaMask, as this presently is an older version lacking async support. -{% endhint %} -{% endtab %} -{% endtabs %} +> For clarity, this example is written using async rather than callbacks. As a result, this example works in web3 1.0.x; note that it will not work in the web3 injected by MetaMask, as this presently is an older version lacking async support. ## 读取操作 diff --git a/contract-api-reference/publicresolver.md b/contract-api-reference/publicresolver.md index 07108ae8..a1c1fab0 100644 --- a/contract-api-reference/publicresolver.md +++ b/contract-api-reference/publicresolver.md @@ -18,9 +18,7 @@ description: 默认的公共解析器。 * [EIP634](https://eips.ethereum.org/EIPS/eip-634) - Text records \(`text()`\). * [EIP1577](https://eips.ethereum.org/EIPS/eip-1577) - Content hash support \(`contenthash()`\). -{% hint style="warning" %} -虽然`公共解析器`提供了一个方便的默认解析器,但仍然存在许多其他的解析器实例和版本。调用者**不能**假设域名使用的是公共解析器的最新版本,或是解析器包含了这里描述的所有方法。要检查一个解析器是否支持某个特性,请参见[接口检查支持](publicresolver.md#jie-kou-jian-cha-zhi-chi)。 -{% endhint %} +> 虽然`公共解析器`提供了一个方便的默认解析器,但仍然存在许多其他的解析器实例和版本。调用者**不能**假设域名使用的是公共解析器的最新版本,或是解析器包含了这里描述的所有方法。要检查一个解析器是否支持某个特性,请参见[接口检查支持](publicresolver.md#jie-kou-jian-cha-zhi-chi)。 ## 接口检查支持 diff --git a/dapp-developer-guide/front-end-design-guidelines.md b/dapp-developer-guide/front-end-design-guidelines.md index 8e91f737..66178bfe 100644 --- a/dapp-developer-guide/front-end-design-guidelines.md +++ b/dapp-developer-guide/front-end-design-guidelines.md @@ -18,11 +18,11 @@ description: >- ## 1. 用ENS域名替换以太坊地址 -{% hint style="warning" %} -只有当用户为其地址设置了一个[反向记录](dapp-developer-guide/resolving-names#reverse-resolution),并且反向记录(地址 > 域名)能够与[正向解析](dapp-developer-guide/resolving-names#looking-up-ethereum-addresses)(域名 > 地址)完全匹配时,这个ENS域名(作为对应以太坊地址的替代)**才可以被显示出来**。 - + +> 警告:只有当用户为其地址设置了一个[反向记录](dapp-developer-guide/resolving-names#reverse-resolution),并且反向记录(地址 > 域名)能够与[正向解析](dapp-developer-guide/resolving-names#looking-up-ethereum-addresses)(域名 > 地址)完全匹配时,这个ENS域名(作为对应以太坊地址的替代)**才可以被显示出来**。 + 因此,作为DApp开发者,首先应该确认用户是否已经为其地址设置了反向记录。而且,由于用户可以自由设置反向记录,即使不属于他的域名或是其他随机字符也可以设置成功,所以,你还应该确认这个反向解析出的域名也能通过正向解析得到原来的地址。请从[这里](dapp-developer-guide/resolving-names#reverse-resolution)和后面的 _'other guidelines'_ 部分了解更多内容。 -{% endhint %} + ### 1.1 - 将以太坊地址换成ENS域名显示 @@ -32,9 +32,7 @@ description: >- **添加一个可视校验和:**使用ENS域名时重要的一点就是得向用户指出,这里的域名是指可以关联以太坊地址或其他散列的ENS域名,而不是指http链接。为此,建议将ENS域名与某种形式的可视校验和(比如地址的[标识、Blockies](http://discuss.conflux.network/t/comparing-the-efficacy-of-visual-checksums-identicons-vs-blockies-vs-custom/59)或其他自定义算法表示)相关联。 -{% hint style="danger" %} -**可视校验和**像身份识别一样[可以被欺骗](https://medium.com/@austin_48503/vanity-blockie-miner-for-ethereum-902fccf0a427)或模仿,所以它们**不能算是一种安全机制**。它们只是一个标识符,让用户知道这个域名**只是以太坊地址的另一种表示**。 -{% endhint %} +> 警告:**可视校验和**像身份识别一样[可以被欺骗](https://medium.com/@austin_48503/vanity-blockie-miner-for-ethereum-902fccf0a427)或模仿,所以它们**不能算是一种安全机制**。它们只是一个标识符,让用户知道这个域名**只是以太坊地址的另一种表示**。 * **设计一个缩略版的ENS域名:**ENS域名可以很长,除了不受字符限制之外,用户还可以创建无限数量的子域名以及子域名的子域名,所以可以考虑设计一个缩略版的ENS域名。如果显示了缩略版的域名,则应该提供查看完整域名的方法,例如在悬停时展开整个域名。 * **不是所有的ENS域名都以.eth结尾:**ENS域名通常以.eth结尾。但是,ENS系统目前已经实现了对.xyz和.luxe这两个顶级域名(TLD)的支持,未来还将支持更多的顶级域名。如果你考虑在缩略版的ENS域名中显示TLD部分,请注意这一点。 @@ -88,11 +86,11 @@ description: >- ### **缓存和更新ENS域名** -如果你的DApp需要在UI界面中显示许多以太坊地址或ENS域名,你还可以考虑在解析(和验证)该域名后,或是用户在输入字段中添加该域名之后,将这个ENS域名**缓存**起来。 - +如果你的DApp需要在UI界面中显示许多以太坊地址或ENS域名,你还可以考虑在解析(和验证)该域名后,或是用户在输入字段中添加该域名之后,将这个ENS域名**缓存**起来。 + 你的**开放式UI**可以在**毫无风险的情况下**安全地显示缓存中的域名,例如,用户只是在浏览,并且不需要根据显示的信息采取行动或做出决策,尤其是有风险的决策。 但是,在所有**存在危险的情况下**(如转移ETH、代币或其他值),或者当用户与另一个ENS域名或以太坊地址交互时,你就应该**直接执行实时解析**,并从ENS注册表中获取最新的信息。 - + 此外,考虑到用户可以随时更改ENS注册表中的信息,你还应该**定期验证当前缓存的信息**。为此,你可以订阅相关合约中发生的一些特定**事件**,尤其是[AddrChanged](../contract-api-reference/publicresolver#set-ethereum-address)和[NameChanged](../contract-api-reference/publicresolver#set-canonical-name)。 ### 关于显示以太坊地址的说明(无论有没有ENS域名) diff --git a/dapp-developer-guide/managing-names.md b/dapp-developer-guide/managing-names.md index 51697407..107378e5 100644 --- a/dapp-developer-guide/managing-names.md +++ b/dapp-developer-guide/managing-names.md @@ -4,46 +4,38 @@ ENS中的每个域名都有一个所有者,这个所有者可以是帐户或智能合约,而且是唯一一个可以在ENS注册表中对这个域名进行更改的帐户或合约。域名的所有者可以将所有权转移到任何其他帐户或合约。 -{% tabs %} -{% tab title="ethereum-ens" %} +**ethereum-ens**: ```javascript await ens.setOwner('alice.eth', '0x1234...', {from: ...}); ``` -{% endtab %} - -{% tab title="go-ens" %} +**go-ens** ```go // opts are go-ethereum's bind.TransactOpts err := registry.SetOwner(opts, "alice.eth", common.HexToAddress("0x1234...")) ``` -{% endtab %} -{% tab title="web3.py" %} +**web3.py** ```python ns.setup_owner('alice.eth', '0x1234...') ``` -{% endtab %} -{% endtabs %} + ## 创建子域名 每个域名的所有者都可以根据需要配置子域名,配置子域名是指创建子域名并将其所有者设置为所需地址的过程,这个地址可以与父域名的所有者相同,也可以不同。 -{% tabs %} -{% tab title="ethereum-ens" %} +**ethereum-ens** ```text await ens.setSubnodeOwner('iam.alice.eth', '0x1234...', {from: ...}); ``` -{% endtab %} -{% tab title="go-ens" %} +**go-ens** ```go // opts are go-ethereum's bind.TransactOpts err := registry.SetSubdomainOwner(opts, "alice.eth", "iam", common.HexToAddress("0x1234...")) ``` -{% endtab %} -{% tab title="web3.py" %} +**web3.py** ```text ns.setup_owner('iam.alice.eth', '0x1234...') ``` @@ -55,8 +47,7 @@ ns.setup_address('iam.alice.eth', '0x1234...') ``` 一般情况下,域名应该指向所有者的地址,因此上面函数的第二个参数是可选的(默认值是域名所有者的地址)。 -{% endtab %} -{% endtabs %} + ## 设置解析器 @@ -64,8 +55,7 @@ ns.setup_address('iam.alice.eth', '0x1234...') 域名的解析器通常设置为公共解析器,公共解析器是一个"符合标准"的解析器,它能提供常用的功能,但是每个人都可以编写和部署自己的专用解析器,有关详细信息,请参见解析器接口定义。 -{% tabs %} -{% tab title="ethereum-ens" %} +**ethereum-ens** ```text await ens.setResolver('iam.alice.eth', '0x1234...', {from: ...}); ``` @@ -76,19 +66,15 @@ await ens.setResolver('iam.alice.eth', '0x1234...', {from: ...}); const resolver = await ens.resolver('resolver.eth').addr(); await ens.setResolver('iam.alice.eth', resolver, {from: ...}); ``` -{% endtab %} -{% tab title="go-ens" %} +**go-ens** ```go // opts are go-ethereum's bind.TransactOpts err := registry.SetResolver(opts, "iam.alice.eth", common.HexToAddress("0x1234...")) ``` -{% endtab %} -{% tab title="web3.py" %} +**web3.py** 不支持自定义解析器。web3.py会在用户调用`setup_address`时,自动使用公共解析器,它不支持设置自定义解析器。 -{% endtab %} -{% endtabs %} 注意,更改域名的解析器后,该域名在原解析器上的记录不会自动迁移到新解析器上。要更新解析器记录,需要按照下面的程序来实现。 @@ -100,60 +86,49 @@ err := registry.SetResolver(opts, "iam.alice.eth", common.HexToAddress("0x1234.. ### 更新解析到地址的记录 -{% tabs %} -{% tab title="ethereum-ens" %} +**ethereum-ens** ```javascript await ens.resolver('iam.alice.eth').setAddr('0x1234...', {from: ...}); ``` -{% endtab %} -{% tab title="go-ens" %} +**go-ens** ```go resolver, err := ens.NewResolver(client, "iam.alice.eth") // opts are go-ethereum's bind.TransactOpts err := resolver.SetAddress(opts, common.HexToAddress("0x1234...")) ``` -{% endtab %} -{% tab title="web3.js" %} +**web3.js** ```javascript ens.setAddress('iam.alice.eth, '0x1234...', {from: ...}); ``` -{% endtab %} -{% tab title="web3.py" %} +**web3.py** ```python ns.setup_address('iam.alice.eth', '0x1234...') ``` -{% endtab %} -{% endtabs %} ### 更新解析到其他资源的记录 有些ENS库(目前只有ethereum-ens、go-ens和web3.js)支持使用相同的模式更新其他记录类型(内容的散列和文本记录等)。例如,要设置或更新文本记录: -{% tabs %} -{% tab title="ethereum-ens" %} +**ethereum-ens** ```javascript ens.resolver('iam.alice.eth').setText('test', 'Test record', {from: ...}); ``` -{% endtab %} -{% tab title="go-ens" %} +**go-ens** ```go // opts are go-ethereum's bind.TransactOpts err := resolver.SetContenthash(opts, []byte{0x12, 0x34...}) err := resolver.SetAbi(opts, "Sample", `[{"constant":true,"inputs":...}]`, big.NewInt(1)) err := resolver.SetText(opts, "Sample", `Hello, world`) ``` -{% endtab %} -{% tab title="web3.js" %} +**web3.js** ```javascript ens.setText('iam.alice.eth', 'Test', 'Test record', {from: ...}); ``` -{% endtab %} -{% endtabs %} ## 配置反向解析 @@ -163,19 +138,15 @@ ens.setText('iam.alice.eth', 'Test', 'Test record', {from: ...}); 配置反向解析通常是通过诸如[ENS管理器](https://manager.ens.domains/)这样的用户界面来实现的。go-ens和web3.py也可以提供这项功能: -{% tabs %} -{% tab title="go-ens" %} +**go-ens** ```go reverseRegistrar, err := ens.NewReverseRegistrar(client) // opts are go-ethereum's bind.TransactOpts err := reverseRegistrar.SetName(opts, "iam.alice.eth") ``` -{% endtab %} -{% tab title="web3.py" %} +**web3.py** ```python ns.setup_name('iam.alice.eth', '0x1234...') ``` -{% endtab %} -{% endtabs %} diff --git a/dapp-developer-guide/resolving-names.md b/dapp-developer-guide/resolving-names.md index 0db524d8..4d1d069d 100644 --- a/dapp-developer-guide/resolving-names.md +++ b/dapp-developer-guide/resolving-names.md @@ -4,26 +4,23 @@ ENS中最简单和最常用的函数是域名解析函数。域名可以关联多种类型的资源,其中最常见的是以太坊地址。借助ENS库,将域名解析为以太坊地址很简单: -{% tabs %} -{% tab title="ethereum-ens" %} +**ethereum-ens** ```javascript var address = await ens.resolver('alice.eth').addr(); ``` -{% endtab %} -{% tab title="web3.js" %} +**web3.js** ```javascript var address = ens.getAddress('alice.eth'); ``` -{% endtab %} -{% tab title="ethjs-ens" %} +**ethjs-ens** + ```javascript var address = await ens.lookup('alice.eth'); ``` -{% endtab %} -{% tab title="ethers.js" %} +**ethers.js** ```javascript var address = await provider.resolveName('alice.eth'); ``` @@ -43,21 +40,19 @@ const abi = [ ]; const contract = new ethers.Contract('contract.alice.eth', abi, provider); ``` -{% endtab %} -{% tab title="go-ens" %} +**go-ens** ```go address, err := ens.Resolve(client, "alice.eth") ``` -{% endtab %} -{% tab title="web3.py" %} +**web3.py** + ```text address = ns.address('alice.eth') ``` -{% endtab %} -{% tab title="web3j" %} +**web3j** ```java String address = ens.resolve("alice.eth"); ``` @@ -68,8 +63,6 @@ web3j同样支持在任何需要使用地址的地方也可以使用ENS域名, YourSmartContract contract = YourSmartContract.load( "contract.alice.eth", web3j, credentials, GAS_PRICE, GAS_LIMIT); ``` -{% endtab %} -{% endtabs %} 如果不借助ENS库,解析的过程可以分为三步: @@ -79,9 +72,8 @@ YourSmartContract contract = YourSmartContract.load( 对多币地址解析的支持是通过重载`addr()`来实现的。要解析多币地址,必须要有相应加密货币的Namehash和符合[SLIP44](https://github.com/satoshilabs/slips/blob/master/slip-0044.md)规范的链ID。例如,要解析一个比特币地址,可以调用`addr(hash, 0)`。注意,返回的地址是用二进制表示的,因此要通过解码来得到文本格式的地址,详细内容请参阅[EIP2304](https://eips.ethereum.org/EIPS/eip-2304)。 -{% hint style="warning" %} -使用`addr()`进行解析时,必须将来自解析器0x00…00的返回值视为未设置的记录。否则,在用户配置了解析器却没有为域名设置解析地址的情况下,可能导致用户的资金被发送到空地址! -{% endhint %} +> 警告: 使用`addr()`进行解析时,必须将来自解析器0x00…00的返回值视为未设置的记录。否则,在用户配置了解析器却没有为域名设置解析地址的情况下,可能导致用户的资金被发送到空地址! + ## 解析至其他资源 @@ -95,14 +87,13 @@ YourSmartContract contract = YourSmartContract.load( 反向解析是通过专用域名 _addr.reverse_ 和解析器的`name()`函数实现的。_addr.reverse_ 的所有权属于一个专用的注册中心合约,该合约将子域名分配给相应地址的所有者。例如,地址 _0x314159265dd8dbb310642f98f50c066173c1259b_ 可以要求使用 _314159265dd8dbb310642f98f50c066173c1259b.addr.reverse_,并设置解析器和解析记录。通过这个解析器的`name()`函数可以取得与该地址关联的域名。 -{% hint style="danger" %} -ENS并不强制要求反向记录的准确性。例如,每个人都可以声明其地址的域名为"alice.eth"。所以,为了确保声明是准确的,你必须始终对返回的域名执行正向解析,并检查正向解析得到的地址是否与原始地址匹配。 -{% endhint %} + +> 警告: ENS并不强制要求反向记录的准确性。例如,每个人都可以声明其地址的域名为"alice.eth"。所以,为了确保声明是准确的,你必须始终对返回的域名执行正向解析,并检查正向解析得到的地址是否与原始地址匹配。 + 大多数ENS库提供了执行反向解析的功能: -{% tabs %} -{% tab title="ethereum-ens" %} +**ethereum-ens**: ```javascript const address = '0x1234...'; var name = await ens.reverse(address).name() @@ -111,13 +102,11 @@ if(address != await ens.resolver(name).addr()) { name = null; } ``` -{% endtab %} -{% tab title="web3.js" %} -Not supported. -{% endtab %} +**web3.js** 不支持 -{% tab title="ethjs-ens" %} + +**ethjs-ens**: ```javascript var address = '0x1234...'; var name = await ens.reverse(address); @@ -126,23 +115,22 @@ if(address != await ens.lookup(name)) { name = null; } ``` -{% endtab %} -{% tab title="ethers.js" %} +**ethers.js**: ```text var address = '0x1234...'; var name = await provider.lookupAddress(address); // ethers.js automatically checks that the forward resolution matches. ``` -{% endtab %} -{% tab title="go-ens" %} +**go-ens**: + ```go name, err := ens.ReverseResolve(client, common.HexToAddress("0x1234...") ``` -{% endtab %} -{% tab title="web3.py" %} +**web3.py**: + ```python address = '0x1234...' name = ns.reverse(address) @@ -150,9 +138,8 @@ name = ns.reverse(address) if address != ns.address(name): name = None ``` -{% endtab %} -{% tab title="web3j" %} +**web3j:**: ```java String address = "0x1234..."; String name = ens.reverseResolve(address); @@ -161,8 +148,7 @@ if(address != ens.resolve(name)) { name = null; } ``` -{% endtab %} -{% endtabs %} + 如果不使用库,实现反向解析的过程也是一样的:查询`1234....addr.reverse`(其中的 _1234..._ 是需要进行反向解析的地址)的解析器并在该解析器上调用`name()`函数。然后,执行正向解析以验证记录是否准确。 diff --git a/dapp-developer-guide/working-with-ens.md b/dapp-developer-guide/working-with-ens.md index c37c12b1..b470af06 100644 --- a/dapp-developer-guide/working-with-ens.md +++ b/dapp-developer-guide/working-with-ens.md @@ -4,17 +4,18 @@ 下面的代码是基于Javascript的API(ethereum-ens、web3.js、ethjs-ens和ethers.js)的使用示例,这些代码适合运行在一个引入了`ethereum`对象的DApp浏览器中,比如安装了[metamask](https://metamask.github.io/metamask-docs/Main_Concepts/Getting_Started)的Chrome。 -{% tabs %} -{% tab title="ethereum-ens" %} + +**ethereum-ens** + ```javascript var ENS = require('ethereum-ens'); var accounts = ethereum.enable(); var ens = new ENS(ethereum); ``` -{% endtab %} -{% tab title="web3.js" %} +**web3.js** + ```javascript var Web3 = require("web3") @@ -22,9 +23,8 @@ var accounts = ethereum.enable(); var web3 = new Web3(ethereum); var ens = web3.eth.ens; ``` -{% endtab %} -{% tab title="ethjs-ens" %} +**ethjs-ens** ```javascript const ENS = require('ethjs-ens'); // Currently requires both provider and @@ -32,17 +32,16 @@ const ENS = require('ethjs-ens'); var accounts = ethereum.enable(); const ens = new ENS({ ethereum, network: '1' }); ``` -{% endtab %} -{% tab title="ethers.js" %} +**ethers.js** ```javascript var ethers = require('ethers'); var provider = new ethers.providers.Web3Provider(ethereum); // ENS functionality is provided directly on the core provider object. ``` -{% endtab %} -{% tab title="go-ens" %} +**go-ens** + ```go import ( ens "github.com/wealdtech/go-ens/v2" @@ -53,20 +52,15 @@ import ( client, err := ethereum.Dial("/home/ethereum/.ethereum/geth.ipc") registry, err := ens.Registry(client) ``` -{% endtab %} - -{% tab title="web3.py" %} +**web3.py** ```python from ens.auto import ns ``` -{% endtab %} -{% tab title="web3j" %} +**web3j** ```java EnsResolver ens = new EnsResolver(web3j, 300 /* sync threshold, seconds */); ``` -{% endtab %} -{% endtabs %} 一些web3库(ethers.js、web3j和web3.py )已经内置了对域名解析的支持。在这些库中,只要可以使用地址的地方,都可以直接使用ENS域名,也就是说,除非你想手动解析域名或是进行其他特殊的ENS操作,否则你根本不需要直接与它们的ENS API交互。