使用 Truffle 框架创建 dApp
dApps (去中心化应用程序)是不依赖于传统服务器的应用程序。相反,dApps 利用区块链来托管传统上存储在服务器上的数据。数据存储在连接到区块链的节点网络中。各种工具和框架用于编写全栈、去中心化的应用程序。使用 Solidity 编程语言编写 dApp 的流行框架之一是Truffle 。 Truffle 提供了设计 dApp 项目的基本脚手架。使用 Truffle,我们可以创建创建区块链功能所需的智能合约,为功能编写单元测试,并设计 dApp 的前端设计。
设计全栈 dApp 的基本步骤如下:
第一步:搭建开发环境:开始一个 Truffle 项目之前的要求如下:
- 节点.js
- Ganache——用于在本地模拟区块链。
- Metamask——用于通过浏览器处理区块链交易。
要设置 Truffle 框架,请运行以下命令:
npm install -g truffle
出于开发目的,我们不是使用真正的以太坊区块链,而是依赖于使用测试网络或本地私有区块链。要在您的计算机上本地模拟以太坊区块链,您可以使用Ganache 。 Ganache 安装后,可以通过命令行或使用提供的 GUI 使用。使用 Ganache,您将获得一组测试帐户,默认情况下每个帐户最多 100 个以太币,用于开发过程。
第 2 步:使用 Truffle Box 生成样板代码:为了简化在 Truffle 中创建 dApp 的过程,而不是手动创建文件并包含依赖项,您可以使用Truffle Box 。 Truffle Box 提供了有用的样板代码,您可以使用它直接开始设计您的 dApp。这些“盒子”还包含其他有用的组件,例如常用的 Solidity Contracts、库、前端视图等。根据您项目的要求,您可以从他们的官方网站上选择一个 Truffle 盒子
truffle unbox pet-shop
truffle unbox react
第 3 步:编写 Solidity 智能合约:下载 truffle box 并解压后,它会创建一个 Truffle 特定的目录结构。一个 Truffle 项目的一般结构如下图所示:
- 合约目录,所有 Solidity 智能合约都被编写并存储为 .sol 文件。
- 迁移目录包含用于迁移和部署设计合约的代码。
- node_modules 目录存储了运行项目所需的所有节点依赖项。
- src 目录用于存放项目的前端组件,例如 HTML 和 CSS 文件。
- test 目录存放开发者编写的单元测试。
一般来说,第一步是设计合同并将其保存为合同目录中的.sol文件。 Solidity 智能合约的一个简单示例如下所示:
javascript
pragma solidity ^0.4.4;
contract TestContract {
uint my_id;
function setId(uint x) public {
my_id = x;
}
function getId() public view returns (uint) {
return my_id;
}
}
javascript
// Instantiating the compiled contract to be deployed
var TestContract = artifacts.require("TestContract ");
module.exports = function(deployer) {
// Deploying the contract to the blockchain
deployer.deploy(TestContract);
};
javascript
App = {
web3Provider: null,
contracts: {},
init: async function() {
return await App.initWeb3();
},
initWeb3: async function() {
if (window.ethereum) {
App.web3Provider = window.ethereum;
try {
await window.ethereum.enable();
} catch (error) {
console.error("User denied account access")
}
}
else if (window.web3) {
App.web3Provider = window.web3.currentProvider;
}
else {
App.web3Provider = new Web3.providers
.HttpProvider('http://localhost:7545');
}
web3 = new Web3(App.web3Provider);
return App.initContract();
},
initContract: function() {
$.getJSON("TestContract.json", function(data) {
var TestContractArtifact = data;
App.contracts.TestContract =
TruffleContract(TestContractArtifact);
App.contracts.TestContract
.setProvider(App.web3Provider);
});
return App.callFunctionFromContract();
},
callFunctionFromContract: function() {
App.contracts.TestContract.deployed()
.then(function(instance) {
console.log(instance.getId());
}
}
};
第 4 步:编译和迁移合约:一旦编写了合约,我们就可以编译然后迁移以将它们存储在我们的区块链上。要在 Truffle 中编译 Solidity 合约,请运行命令
truffle compile
成功编译后,合约将转换为由以太坊虚拟机 (EVM) 执行的字节码。编译成功后,需要将合约保存在区块链上,以便用户访问合约提供的功能。一旦迁移到区块链,每个部署的合约都会被分配一个唯一的地址来引用它在区块链上的位置。当用户希望调用某个已部署合约的函数时,需要调用区块链上已部署合约地址对应的函数。
要指定必须迁移哪些合约,我们需要在新文件的迁移目录中指定它们的引用。该文件名为“2_deploy_contracts.js”,结构如下
javascript
// Instantiating the compiled contract to be deployed
var TestContract = artifacts.require("TestContract ");
module.exports = function(deployer) {
// Deploying the contract to the blockchain
deployer.deploy(TestContract);
};
接下来是执行命令:
truffle migrate
注意:由于我们是在 Ganache 上本地模拟区块链,因此 Ganache 服务应该在执行迁移之前运行。
第 5 步:编写单元测试:尽管测试驱动开发是所有软件开发范围内强烈推荐的方法。对于 dApp 而言,这一点至关重要。通过区块链的设计,一旦对区块链进行的更改将永久且不可变地存储在链上。因此,如果开发人员在区块链上部署了有缺陷的合约,则该合约一旦迁移就无法修复。修复错误的唯一方法是创建一个新合约,在新地址上部署和迁移它,并要求所有用户使用新地址而不是旧的、有问题的合约地址。因此,在 dApp 开发中必须进行一致的测试。
所有测试文件都写入并存储在测试目录中。 Truffle 中的单元测试可以在 Chai 和 Mocha 库的帮助下完成,它们提供了一系列断言和其他工具来执行测试。编写完成后,通过执行运行测试
truffle test
第 6、7 步:创建 UI 并与合约集成: dApp 的 UI 设计像往常一样使用 HTML、CSS、Bootstrap、JavaScript 等工具和语言完成。为了将前端与部署的合约接口,我们依赖在 web3 JavaScript 库上。使用 web3js,我们可以在前端 JS 文件中实例化部署的以太坊合约,然后调用函数并与区块链交换数据。初始化web3js和实例化部署的合约的代码如下:
javascript
App = {
web3Provider: null,
contracts: {},
init: async function() {
return await App.initWeb3();
},
initWeb3: async function() {
if (window.ethereum) {
App.web3Provider = window.ethereum;
try {
await window.ethereum.enable();
} catch (error) {
console.error("User denied account access")
}
}
else if (window.web3) {
App.web3Provider = window.web3.currentProvider;
}
else {
App.web3Provider = new Web3.providers
.HttpProvider('http://localhost:7545');
}
web3 = new Web3(App.web3Provider);
return App.initContract();
},
initContract: function() {
$.getJSON("TestContract.json", function(data) {
var TestContractArtifact = data;
App.contracts.TestContract =
TruffleContract(TestContractArtifact);
App.contracts.TestContract
.setProvider(App.web3Provider);
});
return App.callFunctionFromContract();
},
callFunctionFromContract: function() {
App.contracts.TestContract.deployed()
.then(function(instance) {
console.log(instance.getId());
}
}
};
为了与区块链交互并通过网络浏览器进行交易,我们需要一个能够处理此类交易的浏览器扩展。为此,一个流行的选择是MetaMask 。设置 MetaMask 帐户后,每次在区块链上执行交易时,MetaMask 都会显示提示,详细说明请求的交易,以及 Gas 价格以及可能必须发送的任何其他 Ether 金额
有了这个,我们可以设置一个在本地 Ganache 区块链上运行的 dApp。