微三云志英带你开发 dApp 的三个步骤

供应商
微三云大数据科技有限公司
认证
电商模式设计
183****0056
经理
李志英
所在地
松山湖园区瑞和路1号2栋304室
更新时间
2023-07-11 07:00

详细介绍

去中心化应用,或者叫 dapp,是一种不依赖于中心化服务器的应用。相反,dapp 使用像是***和预言机这些 web3技术,来实现自己的逻辑和后台功能,具备不可篡改和安全的特性。

在这个技术教程中,你会学习到怎样**一个 end-to-end 的 dapp。在 dapp中,用户可以通过一个智能合约,获取和存储 eth 的当前价格。这个教程 demo代码存储在 github 中。

要求

你需要先安装以下软件:

nodejs

metamask

去中心化应用是什么?

与传统的 app 在中心化服务器运行后端代码不同的是,dapp 的后端代码是运行在***上的。当然,dapp 的前端代码和 ui可以使用任何语言**,可以部署在任何服务器上与后端逻辑相交互。

因为 dapp 可以通过安全性很高且不可篡改的智能合约来承载后端逻辑,所以 dapp 有很多 web2系统中没有的优势:

不会宕机

隐私性更强

抗操纵

在*小信任环境下执行逻辑

然而,这些优势也带来了对应的缺点。因为代码是部署在***上,这些逻辑默认是无法修改的,所以 dapp的维护难度比较高。除此以外,因为代码是运行在分布式网络中,而不是中心化服务器,所以性能会比较低。另外,由于用户需要有 web3钱包并且通过有足够的加密资产来支付手续费,所以用户体验也会下降。

dapp 组件

dapp 的组件会有三个不同的类型:智能合约,前端逻辑(ui)和数据存储。

智能合约

智能合约存储了 dapp 的业务逻辑和当前的状态,这个是 dapp 和传统网络应用的*大区别,也正是因为这一点让 dapp具备了以上提到过的优势。

前端 / ui

尽管后端逻辑需要**者完成智能合约代码,并把它部署在***上,但是在前端,**者还是使用标准的网络技术,比如 html 和javascript,因此**者可以使用自己熟悉的工具,库和框架。客户端的 ui 通常通过 web3.js 和 ether.js 与智能合约交互。像是对信息进行签名并且发送给智能合约这些操作,通常是通过浏览器的web3 钱包 metamask 完成。

数据存储

大多数应用需要存储数据,但是因为***分布式的特点,在链上存储大量的数据效率很低,而且非常贵。这也是为什么许多 dapp需要使用 ipfs 或者 filecoin 这样的链下存储服务来存储数据,只让***存储重要的业务逻辑和状态。
当然你也可以选择传统的云存储服务,然而还是有很多**者选择分布式存储,因为***应用可以提供*小信任的特性。


source以太坊 dapp 架构 来源:the architecture of a web3 application

现在我们知道了 dapp 的组件,让我们**一个简单的 dapp。

第一步:创建智能合约

我们 dapp 中的智能合约是一个简单的例子,它可以查看数据并且反应出***上的变化。在这个例子中,我们会通过chainlink eth/usd 喂价对查看 eth/usd 的价格,然后将结果**存储在智能合约上。

第一步是打开 chainlink 的文档,然后导航到 using data feeds 页面。从这里将源代码复制进你的 ide中的一个新的文件里(比如 visual code),或者你可以点击“open in remix”按钮,然后使用在线 ideremix。


在这个例子中,我们会使用 visual studio code 和 hardhat(一个 evm **框架)。

首先,为我们的 dapp 创建一个新的文件夹,并在这个文件夹中创建一个后端文件夹,用来存储智能合约代码:

mkdir chainlink-dapp-examplecd chainlink-dapp-examplemkdir backendcd backend

接下来,我通过 vs code 打开创建好的文件夹,然后安装 hardhat:

npm init -ynpm install --save-dev hardhatnpx hardhat(choose create javascript project, choose default parameters)

当安装完成之后,在“contracts”文件夹中删掉 touch.sol ,然后在这个文件夹中创建一个叫做priceconsumerv3.sol 的文件。在这个文件将存储我们的合约,所以将 chainlink文档中的代码复制到这个文件中,然后保存。


在样例代码中,你会看到 demo 合约已经有一个叫做 getlatestprice 的功能来通过 rinkeby 上的eth/usd 喂价对查看 ethereum 的当前价格。

function getlatestprice() public view returns (int) { ( /*uint80 roundid*/, int price, /*uint startedat*/, /*uint timestamp*/, /*uint80 answeredinround*/ ) = pricefeed.latestrounddata(); return price;

创建一个新的变量和函数,在智能合约上储存这个值。

int public storedprice;

然后,创建一个新的函数,它会被 dapp 的前端调用。这个函数会通过调用 getlatestprice 函数查看ethereum 的*新价格,然后将这个值存储在 storedprice 这个参数中:

function storelatestprice() external { storedprice = getlatestprice(); }

你的新的合约应该和下面的一样:

// spdx-license-identifier: mitpragma solidity ^0.8.7;import "@chainlink/contracts/src/v0.8/interfaces/aggregatorv3interface.sol";contract priceconsumerv3 { aggregatorv3interface internal pricefeed; int public storedprice; /** * network: rinkeby * aggregator: eth/usd * address: 0x8a753747a1fa494ec906ce90e9f37563a8af630e */ constructor() { pricefeed = aggregatorv3interface(0x8a753747a1fa494ec906ce90e9f37563a8af630e); } /** * returns the latest price */ function getlatestprice() public view returns (int) { ( /*uint80 roundid*/, int price, /*uint startedat*/, /*uint timestamp*/, /*uint80 answeredinround*/ ) = pricefeed.latestrounddata(); return price; } function storelatestprice() external { storedprice = getlatestprice(); }}

第二步:部署智能合约

现在你已经可以在 rinkeby 测试网中编译和部署你的合约了,如果没有测试网的通证的话,可以在 chainlinkfaucet 获得一些。

如果你使用的是 remix 的话,你可以通过 remix 编译和部署你的合约。如果你使用的是像是 visual studiocode 这样的 ide 的话,我们推荐使用 hardhat 来管理你的合约。


在部署合约之前,第一步是安装 hardhat 工具包,chainlink 合约库和 dotenv 库。dotenv可以将存储密码和敏感信息存储在一个单独的 .env 文件中:

npm install --save-dev @nomicfoundation/hardhat-toolboxnpm install @chainlink/contracts --savenpm install dotenv

然后,将 hardhat-config.js 文件中的内容换成下面的内容:

require("@nomicfoundation/hardhat-toolbox");//require("@nomiclabs/hardhat-ethers") require('dotenv').config() const rinkeby_rpc_url = process.env.rinkeby_rpc_url || "https://eth-rinkeby.alchemyapi.io/v2/your-api-key" const private_key = process.env.private_key || "abcdef" module.exports = { defaultnetwork: "rinkeby", networks: { hardhat: { // // if you want to do some forking, uncomment this // forking: { // url: mainnet_rpc_url // } }, localhost: { }, rinkeby: { url: rinkeby_rpc_url, accounts: [private_key], savedeployments: true, }, }, solidity: "0.8.9",};

下一步是在 backend 文件夹中创建一个 .env 文件。然后你需要从 web3 钱包中获取你的私钥,然后粘贴到private_key 这一行。请再确定一下,为了安全你在这个例子中**使用一个在主网上没有任何的资产的新 web3 钱包。


当这些做完以后,你需要一个 rpc endpoint 来接入 rinkeby 网络。你可以将它粘贴到 .env 文件的rinkeby_rpc_url 中的 rpc url 中。我们推荐注册一个免费的 infura 或者 alchemy 账户以获取一个rpc url。


创建 .env 文件

下一步是修改“script” 文件夹中 deploy.js文件中的内容,使得它可以部署你的新合约。打开文件,然后将代码替换为下列代码。

// we require the hardhat runtime environment explicitly here. this is optional// but useful for running the script in a standalone fashion through `node `. if you do that, hardhat// will compile your contracts, add the hardhat runtime environment's members to the// global scope, and execute the script.const hre = require("hardhat");async function main() { const priceconsumer = await hre.ethers.getcontractfactory("priceconsumerv3"); const priceconsumer = await priceconsumer.deploy(); await priceconsumer.deployed(); console.log("contract deployed to:", priceconsumer.address);}// we recommend this pattern to be able to use async/await everywhere// and properly handle errors.main().catch((error) => { console.error(error); process.exitcode = 1;});现在你已经可以通过 hardhat 来编译你的智能合约并且把它部署在 rinkeby 网络中:npx hardhat compilenpx hardhat run --network rinkeby scripts/deploy.js你现在应该看到类似下面这行的信息,会展示你部署在 rinkeby 网络上的智能合约地址。注意这个地址,我们在后面的步骤中需要用到它。部署的智能合约恭喜,你已经完成了 dapp 的合约部分!第三步:创建前端应用dapp 的前端逻辑和 ui 可以通过各种框架完成。react 是*受欢迎的 javascript 代码库之一,它可以用来**功能丰富的网页,因此也被许多 web3 dapp 所使用。除此之外,ether.js 是一个 javascript 库,它是用来和 evm ***连接和交互的。当你把这两者结合起来,就可以开始**你的 dapp 的前端的了。在这部分,我们将使用 create-react-app 创建一个新的 react 应用。然后我会介绍如何通过 ether.js 来将 ui 和已经部署的智能合约连接起来,完成一个 end-to-end 的 dapp。创建 react 应用**前端代码之前,需要先安装和初始化一个 cerate-react-app 项目,然后修改它以满足我们的 dapp。第一步将这个库安装到“frontend”文件夹:cd ..npx create-react-app frontend这一步完成后,你应该可以在 “frontend” 文件夹中看到所有相关的 react 代码。打开“frontend” 文件夹然后做以下操作:删除 /src/setuptests.js删除 /src/reportwebvitals.js删除 /src/logo.svg删除 /src/app.test.js删除 /src/app.css文件夹结构应该如下所示:react front-end 文件夹结构在修改 react 应用代码之前,我们需要先安装 bootstrap 和 ether.js。bootstrap 是一个很流行的前端 css 框架,有很多 react 可以使用的 ui widgets 和 css 样式。ether.js 可以将前端代码与***上已经部署的智能合约相连接。在 “frontend” 文件夹中输入以下命令:cd frontendnpm install bootstrapnpm install ethers现在我们可以开始修改 react 应用的代码,在 /src/ 文件夹中打开 app.js 文件,然后删掉这些内容。我们从 0 开始编写。第一步是告诉 app 我们想要使用 react(包括 useeffect 和 usestate 库)和 ether.js:import react, { useeffect, usestate } from 'react';import { ethers } from "ethers";下一步,创建一个叫 “app” 的函数然后 export 它:function app() { }export default app;现在我们将开始完成 “app” 函数的代码。加入下面的代码,这些代码会做以下的操作:建立 storeprice 和 setstoresprice 的 react hook。连接你的 metamask web3 钱包。设置已经部署的智能合约地址和 abi。ether.js 在与已经部署的合约交互的时候需要这两个信息。把智能合约地址这个值(可以在部署的时候获得)插入到replace_with_deployed_contract_address这里。智能合约的 abi 可以从文件/backend/artifacts/contracts/priceconsumerv3.json中获得,你还可以使用 code minifier 对它进行更好的格式化,存储在你的应用中。 const [storedprice, setstoredprice] = usestate(''); const provider = new ethers.providers.web3provider(window.ethereum) const signer = provider.getsigner() const contractaddress = ’'; const abi = '[{"inputs":[],"statemutability":"nonpayable","type":"constructor"},{"inputs": [],"name":"getlatestprice","outputs":[{"internaltype":"int256","name":"","type":"int256"}],"statemutability":"view","type":"function"},{"inputs":[],"name":"storelatestprice","outputs":[],"statemutability":"nonpayable","type":"function"},{"inputs":[],"name":"storedprice","outputs":[{"internaltype":"int256","name":"","type":"int256"}],"statemutability":"view","type":"function"}]' const contract = new ethers.contract(contractaddress, abi, signer);现在我们在应用中创建两个函数:getstoredprice 会连接部署的合约,并且通过 storedprice() 获取当前价格。setnewprice 会调用已部署合约的 storelatestprice 函数,等到交易完成,然后调用 getstoredprice 函数来获取存储在智能合约中的价格。我们会在应用中加入 getstoredprice 函数,它会在加载页面的时候调用 getter 函数:const getstoredprice = async () => { try { const contractprice = await contract.storedprice(); setstoredprice(parseint(contractprice) / 100000000); } catch (error) { console.log("getstoredprice error: ", error); } } async function updatenewprice() { try { const transaction = await contract.storelatestprice(); await transaction.wait(); await getstoredprice(); } catch (error) { console.log("updatenewprice error: ", error); } } getstoredprice() .catch(console.error)前端代码的*后一步是返回 jsx 代码以让浏览器 render。将下面的代码复制进 app 的函数中,在 getstoreprice() 的下面。这些代码会做下面的操作:返回一个简单的 2 列 grid layout。第一列包含了智能合约中存储的 eth/usd 价格。第二列包含了一个按钮,用户可以使用这个按钮来与智能合约交互,更新存储的价格。点击按钮,然后调用下面的 setnewprice 函数。return ( stored price stored eth/usd price: {storedprice} update price update );你的应用现在已经完成了。如果需要,你可以和这里完整代码比较,保证你的代码中没有错误。你可以运行你的 dapp 了。运行你的 dapp" _ue_custom_node_="true">
DAPP,火币,,上链,Dapp,比原链,智能合约开发搭建Dapp,软件开发,广东山东上海重庆

展开全文

我们其他产品
我们的新闻
优质商家推荐 拨打电话