个性化阅读
专注于IT技术分析

终极ENS和ĐApp教程

本文概述

在区块链系列的上一篇文章中, 我向你介绍了智能合约开发, 但略过如何开发分布式应用程序(dapp, 程式化的ĐApp)的知识。这次, 我想重点关注一下。但是, 为了使我们的工作更有意义, 让我们构建一项服务, 使人们可以通过一次区块链交易创建免费的以太坊子域。

让我们首先介绍以太坊名称服务(ENS), 以开始本ĐApp教程。

以太坊名称服务

ENS是等同于常用域名系统(DNS)的区块链。两者都可以用电话簿的隐喻来描述。它们充当查找服务, 将人类可读的名称转换为它们的基本表示形式-在DNS和ENS的情况下, 是计算机地址而不是电话号码。

DNS将网站地址的域名转换为Internet协议(IP)地址。它们很容易被计算机理解, 但对我们人类却不那么方便。例如, 在撰写本文时, srcmini02.com代表35.186.228.167, 你想记住并输入哪个?

$ ping srcmini02.com
PING srcmini02.com (35.186.228.167): 56 data bytes

ENS具有相同的目的, 但域不是IP地址, 而是映射到以太坊地址(以42个字符长)。顶级ENS域是.eth。

有趣的是, 相当于DNS中央注册表的是一组智能合约。这些以分布式方式在以太坊区块链上运行, “……意味着它不会遭受DNS系统不安全的困扰。你可以确信自己输入的名称可以按照所有者的意愿进行输入。”如ENS网站所述。

下面是ENS体系结构的高级概述。该服务的核心是ENS注册中心智能合约, 该合约将域名表示映射到ENS解析器的智能合约。这些依次映射到目标以太坊地址。查看该图, 如果应用程序想要解析ENS地址radek.freedomain.eth, 它将首先在ENS注册表中查询对应的ENS解析器, 然后向解析器询问映射的以太坊地址, 该地址将以0x0987响应…有关更多信息, 请在此处浏览ENS文档。

ENS体系结构,显示了ENS注册表智能合约到ENS解析器智能合约的映射

.eth ENS域名

ENS于2017年5月4日发布, 目前(第一阶段), 其域必须包含七个或更多字符。无法使用具有六个字符的srcmini.eth, 因此我们将改用我购买的ENS域:freedomain.eth。

任何人都可以通过在已部署的智能合约作为中介的Vickrey拍卖过程中锁定一些以太币来注册.eth域名。拍卖分为竞标和揭露两个阶段, 分别持续三天和两天。

首先, 必须在开始竞标的同时开始域名拍卖。一旦运行, 任何人都可以出价。一旦第一阶段完成, 新的投标将不再被接受, 参与者必须公开他们的投标。最高出价的获胜者只需匹配第二高的出价, 其余的以太币将退还。其余所有参与者也将获得退款。但请务必注意, 如果你不及时透露出价, 你的出价就会丢失。

确定获奖者后, 你只需完成拍卖并设置解析器和目标地址。简单?如果你不熟悉以太坊, 可能就不那么多了。有多种工具可以为你提供帮助, 例如MyCrypto, MyEtherWallet和ENS Manager, 但这仍然是一个多阶段的过程。 (我还发现了ENSListing, 它看起来更加用户友好。)

子域名呢?他们更简单吗?我们来看一下。

美国子域

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

[email protected] => radek.freedomain.eth

Tenzorum Project目前正在实施的一种新颖用例是将你的子域用作以太坊ĐApps的用户名/登录名。想象一下, 有一个你已经玩了一段时间的caseApp游戏。即使两个设备使用不同的密钥对, 继续使用笔记本电脑和移动电话上的登录信息继续玩游戏, 也非常好。这是这样实现的:

  • 使用你的子域(例如radek.tenz-id.eth)登录ĐApp
  • ĐApp要求你签名消息以确认你是相应私钥的持有人
  • ĐApp通过询问你的个人钱包智能合约来检查你是否有权登录。 (你猜对了, 由ENS子域表示的登录名指向你的个人钱包地址)。

这样做还有一个好处, 即使你丢失了设备(及其上的私钥)也可以继续播放, 因为你不会丢失对个人钱包的访问权限。

子域名将域名映射到地址的方式与域名完全相同, 但是你无需经过拍卖过程即可创建域名。幸运的是, ENS子域也没有最小长度限制。

要注册子域, 你必须是该域的所有者。要创建或更新子域, 必须在ENS注册表智能合约上调用setSubnodeOwner。成功后, 将应用与域相同的逻辑:所有者必须设置解析器和目标地址。

如果我们可以实现自动化并简化用户流程, 该怎么办?我已经创建了[可以做到这一点的智能合约-上面提到的EnsSubdomainFactory.sol-允许任何人使用单个区块链调用来创建子域。但是, 由于本文的重点是构建ĐApps, 因此我将其留给你练习。

分布式应用程序(ĐApps)

ĐApp只是与区块链后端交互的前端网站。必须在启用了以太坊的浏览器(例如Mist, Parity或移动应用程序Cipher)上浏览该网站;或通过安装MetaMask插件。

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

认识Web3。有几种使用不同编程语言的版本, 但是我们将使用JavaScript, 即web3.js。另外, web3实例是由浏览器注入的, 对于我们这里的方法, 是由MetaMask插件注入的。

HTML网站

所以现在, 我们可以开始构建howApp了。在我们的例子中, 我们需要的是一个简单的表单, 其中包含五个元素:

  • 子域名的输入字段
  • 包含可用域的下拉列表
  • 子域的新所有者的输入字段
  • 目标地址的输入字段
  • 提交按钮

我使用Bootstrap进行了调整。 (请记住, 就UI功能而言, ĐApp就像任何其他网络应用程序一样, 因此我们本身就不需要ĐApp框架-像Bootstrap这样的常规网络技术在这里可以很好地发挥作用。)其外观如下:

"免费ENS子域"ĐAppUI

这只是一个常规的HTML网站, 因此我们不再赘述。所有的魔术都发生在JavaScript文件dapp.js中。

JavaScript和Web3

要构建任何通用的ĐApp, 你需要:

  • 一个Web3实例(例如, 使用MetaMask提供程序)
  • 一种从区块链读取的方式(例如, 以太坊余额)
  • 一种写入区块链的方法(例如发送以太币)
  • 从智能合约读取的方式(例如, ENS域所有者或ERC20令牌余额)
  • 一种写入智能合约的方法(例如, 创建子域或转移ERC20令牌)

此外, 要使分散式应用程序与智能合约进行交互, 你需要:

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

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

Web3.js和MetaMask

开发ĐApps的最便捷方法是使用带有MetaMask插件的Firefox或Chrome。有关如何安装的说明, 请重新阅读上一篇文章。

在撰写本文时, 在开发去中心化应用程序时要考虑两个相关版本的web3.js:0.20和尚未广泛发布但已经广泛使用的1.0.0。在本文中, 我们使用后一个版本。

对web3实例的检查在initWeb3()函数中进行。这也将与即将到来的MetaMask Web3注入更改一起使用:

window.addEventListener('load', () => {
    // If web3 is not injected
    if (typeof web3 === 'undefined') {
        // Listen for provider injection
        window.addEventListener('message', ({ data }) => {
            if (data && data.type && data.type === 'ETHEREUM_PROVIDER_SUCCESS') {
                // Use injected provider
                web3 = new Web3(ethereum);
                // ...
            } else {
                // No web3 instance available. Show a popup
                // ... 
            }
        });
        // Request provider
        window.postMessage({ type: 'ETHEREUM_PROVIDER_REQUEST' }, '*');
    }
    // If web3 is injected, use its provider
    else {
        web3 = new Web3(web3.currentProvider);
        // ...
    } 
});

如果找不到web3实例, 我们可以向用户显示通知:

当找不到web3实例时弹出提示用户安装MetaMask

与区块链互动

首先, 让我们获取当前加载的以太坊账户, 就像在loadAccount()函数中所做的那样:

web3.eth.getAccounts(function(error, accounts) {
    if (error) {
        // handle error
    } else {
        DApp.currentAccount = accounts[0];
        // ...
    }
});

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

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

在我们的应用程序中, 我们不需要与以太币余额进行交互, 但是为了完整起见, 以下是检查帐户余额的方法:

web3.eth.getBalance(DApp.currentAccount, function(error, ethBalance) {
    if (error) {
        // handle error
    } else {
        console.log("Eth balance", ethBalance);
    }
});

…这是发送一些以太币的方法:

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

请注意, 你必须将from和to字段指定为以太坊地址, 以及要发送的以太币的值。用wei表示, 例如1000000000000000000是一个以太。

与智能合约互动

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

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

在应用程序中, 我们正在与一个智能合约(即EnsSubdomainFactory)进行交互:

factoryAbi: [...], // Local
factoryAddress: "0x9fbda871d559710256a2502a2517b794b482db40", ...

合同是在initContracts()函数中启动的:

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

设置完成后, 我们终于可以拨打电话了。对于我们的用例, 我们需要知道特定域和子域的当前所有者是谁, 因此这是我们的checkSubdomainOwner()函数的外观:

DApp.factoryContract.methods.subdomainOwner(subdomain, domain).call()

请注意, 这是只读操作:我们正在使用call()函数, 该函数可以自由执行-即, 它不消耗任何气体。

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

ĐApp中的"可用子域"消息
ĐApp中的"已占用子域"消息
在我们的ĐApp中显示"子域名是你的"消息

我们需要做的最后一个区块链调用是创建或更新子域。我们在newSubdomain()函数内部执行此操作:

DApp.factoryContract.methods.newSubdomain(
    subdomain, domain, owner, target).send(
    {
        gas: 150000, from: DApp.currentAccount
    }, function(error, txHash) {
        if (error) {
            // handle error
        } else {
            console.log("Transaction hash", txHash);
        }   
    }
);

这次, 我们将四个参数传递给函数:子域, 域, 所有者和目标。它们是不言自明的。

请注意, 我们使用的是send()而不是call()。那是因为这是写操作, 将改变区块链的状态, 并且还会使你花费一些以太坊。我们包括的另一个参数是gas, 代表交易的天然气限额。如果交易费用超过执行限制, 我们希望将其还原。

听事件

我们想知道我们的交易何时成功完成, 并通知用户其子域已可以使用。

工厂智能合约定义了一个事件, 该事件在创建或更新子域时发出:

event SubdomainCreated(address indexed creator, address indexed owner, string domain, string subdomain);

遵循web3.js文档, 我们应该可以执行以下操作:

DApp.factoryContract.once('SubdomainCreated', {
        filter: {creator: DApp.currentAccount}
    }, function(error, event){
        if (error) {
            // handle error
        } else {
            // display a notification that the event happened
        }
    }
);

在指定事件的位置, 我们要侦听SubdomainCreated并传递filter参数以仅侦听将创建者指定为DApp.currentAccount的事件。不幸的是, 当前版本的MetaMask尚不支持Web套接字, 这是web3.js 1.0事件所必需的。这适用于旧版本的web3.js, 但语法不同。

解决方法是, 我们可以轮询交易收据以检查是否已被开采, 但为简单起见, 我们将仅显示指向Etherscan的ENS查找服务的链接, 其中包含我们新子域的详细信息, 例如https://etherscan.io /enslookup?q=radek.freedomain.eth和交易状态也可以在MetaMask窗口中找到。

跟随Etherscan ENS查找链接
Etherscan ENS的详细信息

这就是我们完成简单的ĐApp所需的全部。有关完整的源代码, 请随时在此处进行深入研究。

本地运行

如果要在本地使用该代码, 只需将其签出并确保已安装以下npm软件包:

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

你可以使用Truffle启动本地测试网:

$ truffle develop
…
truffle(develop)> migrate
…
truffle(develop)> test
Using network 'develop'.

  Contract: EnsSubdomainFactory
    ✓ creating new subdomain works (143ms)
    ✓ creating new subdomain fails when factory is not the owner of domain (47ms)
    ✓ updating subdomain works if done by current owner (215ms)
    ✓ creating new subdomain fails if it is already owned by someone else (197ms)
    ✓ transferring domain works (76ms)
    ✓ cannot transfer domains when locked (97ms)
    ✓ cannot transfer domains when not contract owner (55ms)
    ✓ checking for domain and subdomain owner works (138ms)

  8 passing (2s)

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

// Local
factoryAddress: "0x9fbda871d559710256a2502a2517b794b482db40", // Ropsten
// factoryAddress: "0xf9fa2ff44a474b6d20500969bda61c2827fbc6b6", // Mainnet
// factoryAddress: "0xbd185de5172ca64eec3d8cc763883a68f9154cd6", 

要启动Web服务器, 只需执行npm run dev, 它将在localhost:3000上启动浏览器。

请注意, 为了方便本地开发, 我包括了ENS注册管理机构和解析器模拟合同。

以太坊网络上的结果

合同已部署到0xbd185de5172ca64eec3d8cc763883a68f9154cd6。

我们的生产ĐApp网站可通过https://ens.startonchain.com获得。

带有MIT许可证的源代码可在GitHub上获得。

免责声明:这是在主网络上运行的, 而不是在testnet上运行的, 因此你的资金是真实的。使用风险自负。

重要的是要注意, 域所有者可以随时更改子域所有者, 即使他们已被分配。我们在智能合约中停用了此选项, 但是在使用其他人的域时请务必小心。

欢迎来到ĐApps的世界

在此ĐApp教程中, 我介绍了以太坊名称服务(ENS), web3.js, ABI, 智能合约, MetaMask, 交易事件侦听器以及如何生成Truffle项目。这款ĐApp可以做一些有趣且有用的事情, 使人们可以通过一次区块链交易创建免费的以太坊子域。结合我的智能合约教程, 我为你提供了足够的详细信息(并希望从中得到启发), 以创建你自己的基于以太坊的区块链应用程序。祝你好运!

赞(0)
未经允许不得转载:srcmini » 终极ENS和ĐApp教程

评论 抢沙发

评论前必须登录!