作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
拉狄克·奥斯特洛夫斯基的头像

Radek Ostrowski

Radek是一名区块链工程师,对以太坊智能合约感兴趣. 他在机器学习方面也有丰富的经验.

Previously At

Sony
Share

In 区块链系列的上一篇文章, 我向您介绍了智能合约开发,但略读了如何开发分布式应用程序(dapp), stylized ĐApp). 这一次,我想把重点放在这一点上. However, 让我们的工作更有意义, 让我们构建一个服务,允许人们通过单个区块链交易创建免费的以太坊子域.

让我们先从解释以太坊名称服务(ENS)开始这个ĐApp教程.

以太坊名称服务

ENS is a blockchain 相当于常用的域名系统(DNS). 两者都可以用电话簿的比喻来形容. 它们作为查找服务, 将人类可读的名称转换为其底层表示形式——在DNS和ENS的情况下, 电脑地址而不是电话号码.

DNS将网站地址的域名转换为IP (Internet Protocol)地址. 它们很容易被计算机理解,但对我们人类来说就不那么方便了. 例如,在写这篇文章的时候, ngskmc-eis.net represents 35.186.228.167-你宁愿记住并输入哪个?

$ ping ngskmc-eis.net
PING ngskmc-eis.net (35.186.228.167): 56个数据字节

ENS也起到同样的作用, 而不是IP地址, 域名被映射到以太坊地址, 哪些是42个字符长. 顶级ENS域为 .eth.

有趣的是,相当于DNS的中央注册表被表示为一组 smart contracts. 这些都在以太坊区块链上运行, 以分布的方式, 这意味着它不会受到DNS系统不安全的影响. 你可以确信你输入的名字是他们的主人想要的,“as” the ENS website describes.

下面是ENS架构的高级概述. 该服务的骨干是ENS注册智能合约, 哪些域名表示映射到ENS解析器的智能合约. 这些依次映射到目标以太坊地址. 看看这个图,如果一个应用程序想要解析ENS地址 radek.freedomain.eth, 它将首先向ENS注册表查询相应的ENS解析器,然后向解析器询问映射的以太坊地址,该地址将响应 0x0987.... 要了解更多信息,请参阅ENS文档 here.

ENS架构,显示ENS注册表智能合约映射到ENS解析器智能合约

.eth ENS Domains

ENS于5月4日启动, 2017, 现在(第一阶段), 它的域名必须包含七个或更多字符. 它不可能使用 toptal.eth 它有六个字符,所以我们将使用我购买的ENS域名: freedomain.eth.

任何人都可以注册 .eth 通过在部署的智能合约调解的Vickrey拍卖过程中锁定一些以太币来获得域名. 拍卖分为两个阶段, bid and reveal,分别持续三天和两天.

首先,拍卖的域名必须开始与放置第一个出价. 一旦启动,任何人都可以出价. 一旦第一阶段完成, 新的出价不再被接受,然后参与者必须透露他们的出价. 出价最高的赢家只需要匹配第二高的出价, 剩下的乙醚被退还. 所有剩下的参与者也会得到退款. 但重要的是要注意,如果你没有及时透露你的出价,你出价的以太就会丢失.

一旦你被确认为赢家,你只需要 finalize 拍卖和设置 resolver and the target address. Simple? 如果您是以太坊的新手,可能不会那么多. 有几个工具可以帮助你 MyCrypto, MyEtherWallet, and ENS Manager但这是一个多阶段的过程.

子域名呢?? 它们更简单吗?? Let’s have a look.

ENS Subdomains

首先,子域名有什么用呢? 我最好的猜测是,它与DNS中的子域相同. 它们还可以给用户带来更多的组织感, 其中域代表组织,子域类似于电子邮件地址的结构:

radek@freedomain.com => radek.freedomain.eth

当前正在实现的新用例 Tenzorum Project 是使用你的子域名作为用户名/登录到以太坊ĐApps. 假设有一个ĐApp游戏,你已经玩了一段时间了. 当你在旅途中使用笔记本电脑和手机登录时,即使这两种设备使用不同的密钥对,也可以继续玩游戏. 这是如何实现的:

  • 使用子域e登录到ĐApp.g., radek.tenz-id.eth
  • ĐApp要求您签署消息,以验证您是相应私钥的持有者
  • ĐApp通过询问您的个人钱包智能合约来检查您是否有权登录. (You guessed it, ENS子域代表的登录地址指向您的个人钱包地址.)

这样做的额外好处是,即使您丢失了设备(以及设备上的私钥),也可以继续玩游戏。, 因为你不会失去使用个人钱包的权限.

子域将名称映射到地址的方式与域完全相同, 但你不需要通过拍卖过程来创建一个. 幸运的是,在ENS子域上也没有最小长度限制.

要注册子域,您必须是该域的所有者,这是先决条件. 要创建或更新子域,必须调用 setSubnodeOwner 在ENS注册表智能合约上. 一旦成功,应用与域相同的逻辑:所有者必须设置 resolver and the target address.

如果我们可以自动化这个过程并为用户简化这个过程会怎么样呢? 我已经创建了一个智能合约,正是这样做的 EnsSubdomainFactory.sol-允许任何人通过单个区块链调用创建子域. However, 因为本文的重点是构建ĐApps, 我把它留给你们作为练习来检验.

分布式应用程序(ĐApps)

ĐApp只是一个与区块链后端交互的前端网站. 该网站必须在支持以太坊的浏览器上查看 Mist, Parity,或移动应用程序 Cipher; or by installing the MetaMask plugin.

而不是传统的带有服务器和数据库的后端, 读取和写入调用直接对以太坊区块链进行. 调用可以使用JSON RPC协议完成, 但幸运的是,有一个库以开发人员友好的方式包装了这些调用.

Meet Web3. 在不同的编程语言中有几个版本, 但我们将使用JavaScript, web3.js. Also, the web3 实例被浏览器注入,或者在我们这里的例子中,是MetaMask插件.

HTML Website

现在,我们开始学习如何构建ĐApp. 在我们的例子中,我们所需要的只是一个包含五个元素的简单表单:

  • 子域名的输入字段
  • 下拉列表显示可用的域
  • 子域的新所有者的输入字段
  • 目标地址的输入字段
  • Submit button

我把它装饰了一下 Bootstrap. (Remember, 在UI功能方面, ĐApp和其他web应用程序一样, 所以我们不需要ĐApp框架 per se-像Bootstrap这样的常规网络技术在这方面做得很好.)它看起来是这样的:

“免费ENS子域”ĐApp界面

只是个普通的 HTML website 所以我们就不详细说明了. 所有神奇的事情都发生在JavaScript文件中 dapp.js.

JavaScript和Web3

要构建任何泛型ĐApp,您需要做的是:

  • Web3实例(例如.g.(使用MetaMask提供程序)
  • 从区块链中读取的一种方法(例如.g.,以太坊余额)
  • 一种写入区块链的方法(e.g., send ether)
  • 一种从智能合约中读取的方法(例如.g., ENS域所有者,或ERC20令牌余额)
  • 一种写入智能合约的方法(例如.g.、创建子域或传输ERC20令牌)

此外,要使您的去中心化应用程序与智能合约交互,您需要:

  • 应用程序二进制接口(ABI)
  • 智能合约的部署地址

我将依次介绍上述内容,并向您展示如何将它们应用于ĐApp.

Web3.js and MetaMask

开发ĐApps最方便的方法是使用Firefox或Chrome的MetaMask插件. 有关如何安装它的说明,请重新访问 previous article.

在撰写本文时,有两个相关的web3版本.在开发去中心化应用程序时需要考虑的几个问题 0.20 还有尚未发布但已经广泛使用的 1.0.0. 在本文中,我们将使用后一个版本.

The check for the web3 实例发生在 initWeb3() function. 这也将适用于即将推出的MetaMask Web3注入变化:

window.addEventListener('load', () => {
    //如果没有注入web3
    If (typeof web3 === 'undefined') {
        //监听提供商注入
        window.addEventListener('message', ({ data }) => {
            if (data && data.type && data.type === 'ETHEREUM_PROVIDER_SUCCESS') {
                //使用注入的提供商
                web3 = new web3(以太坊);
                // ...
            } else {
                //没有可用的web3实例. Show a popup
                // ... 
            }
        });
        //请求提供程序
        window.postMessage({type: 'ETHEREUM_PROVIDER_REQUEST'}, '*');
    }
    //如果web3被注入,使用它的提供商
    else {
        web3 =新web3 (web3.currentProvider);
        // ...
    } 
});

If no web3 ,我们可以向用户显示一个通知:

当没有找到web3实例时弹出,建议用户安装MetaMask

与区块链交互

首先,让我们获取当前加载的以太坊帐户,如 loadAccount() function:

web3.eth.getAccounts(函数(错误,帐户){
    if (error) {
        // handle error
    } else {
        DApp.currentAccount = accounts[0];
        // ...
    }
});

然后,我们可以用当前帐户的地址自动填充新所有者和目标的输入字段.

默认使用当前帐户的地址作为子域所有者

在我们的应用中, 我们不需要与以太币余额交互, 但是为了完整, 以下是查看账户余额的方法:

web3.eth.getBalance(DApp.当前帐户,函数(错误,ethBalance) {
    if (error) {
        // handle error
    } else {
        console.log("Eth balance", ethBalance);
    }
});

下面是发送以太的方法:

web3.eth.sendTransaction(
    {
        from: DApp.currentAccount,
        : receiverAddress,
        value: ethValue
    },
    函数(错误,txHash) {
        if (error) {
            // handle error
        } else {
            console.log("Transaction hash", txHash);
        }
    }
);

注意,您必须指定 from and to 字段作为以太坊地址,以及 value 你想要发送的. 这是用wei-e表示的.g., 1000000000000000000 is one ether.

与智能合约交互

为了与智能合约进行交互,我们首先必须创建一个代理对象. 要做到这一点,我们需要它 应用程序二进制接口 (ABI),它指定可用的操作.

我们还需要在区块链上部署智能合约的以太坊地址.

在应用程序中,我们与一个智能合约进行交互,这是我们的 EnsSubdomainFactory:

factoryAbi: [...],

// Local
factoryAddress:“0 x9fbda871d559710256a2502a2517b794b482db40”,
...

合同在 initContracts() function:

DApp.factoryContract =新web3.eth.Contract(DApp.factoryAbi, DApp.factoryAddress);

在此设置之后,我们终于准备好拨打一些电话了. For our use case, 我们需要知道特定域和子域的当前所有者是谁, 这就是我们如何 checkSubdomainOwner () function looks:

DApp.factoryContract.methods.subdomainOwner(子域、域).call()

注意,这是一个只读操作:我们使用 call() 函数,它可以自由地执行.e.,它不消耗任何气体.

这就是我们的ĐApp显示给定域可用的方式, taken, 或由当前用户拥有:

“子域是可用的”消息在我们的ĐApp

“子域占用”消息在我们的ĐApp

“子域名是你的”消息在我们的ĐApp

我们需要进行的最后一个区块链调用是创建或更新子域. 我们在里面做 newSubdomain() function:

DApp.factoryContract.methods.newSubdomain(
    子域、域、所有者、目标).send(
    {
        gas: 150000,
        from: DApp.currentAccount
    },
    函数(错误,txHash) {
        if (error) {
            // handle error
        } else {
            console.log("Transaction hash", txHash);
        }   
    }
);

这一次,我们向函数传递了四个形参: subdomain, domain, owner, and target. 它们不言自明.

注意,我们使用 send() instead of call(). 这是因为这是一个写操作,将改变区块链的状态, 还会花费一些乙醚作为汽油. 我们包含的另一个参数是 gas 哪个代表交易的gas限制. 如果事务成本超过执行限制,我们希望它恢复.

监听事件

我们想知道我们的事务何时成功完成,并通知用户他们的子域已准备好使用.

工厂智能合约定义了当子域被创建或更新时触发的事件:

事件SubdomainCreated(地址索引创建者), 地址索引所有者, string domain, 字符串的子域);

Following the web3.js documentation,我们应该能够做到这一点:

DApp.factoryContract.一次(“SubdomainCreated”,
    {
        filter: {creator: DApp.currentAccount}
    },
    函数(错误,事件){
        if (error) {
            // handle error
        } else {
            //显示事件发生的通知
        }
    }
);

在哪里指定要监听的事件 SubdomainCreated and pass the filter 参数使其仅监听 creator 指定为我们的 DApp.currentAccount. 不幸的是,当前版本的MetaMask 还不支持web套接字,这是web3所要求的.js 1.0 events. 这适用于旧版本的web3.Js,但是语法不同.

As a workaround, 我们可以轮询交易收据来检查它是否被挖矿, 但是为了简单起见, 我们将显示一个链接到Etherscan的ENS查找服务,其中包含我们的新子域的详细信息, e.g., http://etherscan.io/enslookup?q=radek.freedomain.eth 交易状态也可以在MetaMask窗口中找到.

跟随Etherscan ENS查找链接

Etherscan ENS详细信息

这就是我们完成简单的ĐApp所需要的. 要获得完整的源代码,请随意深入研究 here.

Running Locally

如果您想在本地使用代码, 只需检查它,并确保安装了以下NPM包:

npm i -g truffle
NPM I web3 lite-server eth-ens-namehash-ms

您可以使用 Truffle:

$ truffle develop
…
truffle(develop)> migrate
…
truffle(develop)> test
利用网络“发展”.

  合同:EnsSubdomainFactory
    ✓创建新的子域作品(143ms)
    当工厂不是域的所有者时,创建新的子域失败(47ms)
    更新子域作品,如果由当前所有者完成(215ms)
    如果子域名已经被别人拥有,创建新子域名失败(197ms)
    ✓传送域作品(76ms)
    锁定时无法传输域(97毫秒)
    非合同所有人无法转让域名(55ms)
    检查域名和子域名所有者工作(138ms)

  8 passing (2s)

最后,通过取消注释中的一行,将工厂智能合约重新指向本地节点 dapp.js:

// Local
factoryAddress:“0 x9fbda871d559710256a2502a2517b794b482db40”,

// Ropsten
// factoryAddress: "0xf9fa2ff44a474b6d20500969bda61c2827fbc6b6",

// Mainnet
// factoryAddress: "0 xbd185de5172ca64eec3d8cc763883a68f9154cd6",

要启动web服务器,只需执行即可 npm run dev,这应该会启动浏览器 localhost:3000.

注意,为了便于本地开发,我已经包含了ENS注册表和解析器模拟契约.

以太坊网络的结果

契约被部署到 0 xbd185de5172ca64eec3d8cc763883a68f9154cd6.

我们的生产ĐApp网站可在 http://ens.startonchain.com.

源代码与MIT许可 在GitHub上可用.

免责声明:这是运行在主网,而不是测试网,所以你是用真钱操作. 使用风险自负.

重要的是要注意,域所有者总是可以更改子域所有者—即使它们已经被分配. 我们在智能合约中禁用了这个选项, 但是当你使用别人的域时,你应该小心.

欢迎来到ĐApps的世界

在这个ĐApp教程中,我介绍了以太坊名称服务(ENS), web3.js, ABI, smart contracts, MetaMask, 事务事件监听器, 以及如何生成一个松露项目. 这个ĐApp做了一些有趣和有用的事情, 让人们通过单个区块链交易创建免费的以太坊子域. Combined with 我的智能合约教程, 我已经给了你足够的细节(希望是灵感),让你创建自己的基于以太坊的区块链应用程序. Best of luck!

了解基本知识

  • 区块链中的智能合约是什么?

    智能合约是在区块链节点上执行的计算机程序. 智能合约可以执行任何计算, persist data, 定义业务规则, 也可以发送和接受像以太币这样的本地货币. 契约本质上是不可变的,除非程序另有规定.

  • 你所说的域名系统是什么意思?

    互联网的域名系统(DNS)是分层的, 去中心化服务,翻译人类友好的域名,如 ngskmc-eis.net 转换成数字IP地址,比如 35.186.228.167它们是互联网上的计算机定位数据和提供网站等内容所必需的.

  • 什么是ENS域?

    以太坊名称服务(ENS)域相当于DNS域,并提供了一种分散和安全的方式将人类记忆的文本转换为以太坊地址. ENS域名目前以。结尾 .并且有七个或更多的字符. 它们可以在拍卖中购买,并且可以具有分层子域.

  • 什么是去中心化应用程序(i.e., dapp or ĐApp)?

    ĐApp只是一个与区块链后端交互的前端网站(通常通过web3),而不是一个带有服务器和数据库的传统后端. 该网站必须在像Mist这样的支持以太坊的浏览器上查看, Parity,或移动应用程序 Cipher; or by installing the MetaMask plugin.

  • 区块链是去中心化的还是分布式的?

    所有区块链本质上都是分布式的,因为它们有单独的节点以分布式的方式一起工作. 不过,并不是所有的区块链都是去中心化的. 如果有一家公司可以进行审查,有些是集中的, change, 或者停止区块链的运行.

  • 什么是子域名,它的用途是什么?

    子域是二级域的一部分,但被搜索引擎视为独立的实体. 它们可以用来为不同的地区创建不同的网站, languages, departments, user types, or device types. E.g.,一个专用移动版的例子.Com可能会用m.example.com subdomain.

聘请Toptal这方面的专家.
Hire Now
拉狄克·奥斯特洛夫斯基的头像
Radek Ostrowski

Located in Phuket, Thailand

Member since 2014年9月24日

About the author

Radek是一名区块链工程师,对以太坊智能合约感兴趣. 他在机器学习方面也有丰富的经验.

Toptal作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.

Previously At

Sony

世界级的文章,每周发一次.

订阅意味着同意我们的 privacy policy

世界级的文章,每周发一次.

订阅意味着同意我们的 privacy policy

Toptal Developers

Join the Toptal® community.