# 基础开发环境

***本教程是技术大牛 luofei614 的DApp开发学习笔记，编成教程分享给开发者。***

### 1、用remix部署第一个合约

remix是一个以太坊官方的在线合约编辑器。 地址： <https://remix.ethereum.org/>

以太坊编写智能合约的语言一般是用solidity。

我们动手自己实现一个水龙头的合约，调用合约的withdraw方法可以向自己账号充币

在contracts文件夹下新建Faucet.sol文件

代码如下：

/`/ SPDX-License-Identifier: MIT`

`pragma solidity ^0.4.5;`

`contract Faucet{`

&#x20; `function withdraw(uint withdraw_amont) public {`

&#x20;     `require(withdraw_amont<0.1 ether);`

&#x20;     `msg.sender.transfer(withdraw_amont);`

&#x20; `}`

&#x20; `function() public payable{}`

`}`

![图片](https://3485192048-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fhypergraph-decentralized-data-engine%2F-M_C5fuoOO2UeWfhwT6Q%2F-M_C60UfMX7L68m68PYZ%2F0.png?generation=1620496361746190\&alt=media)

点击![图片](https://3485192048-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fhypergraph-decentralized-data-engine%2F-M_C5fuoOO2UeWfhwT6Q%2F-M_C60UgGfPVifYDbXI-%2F1.png?generation=1620496361734156\&alt=media) 按钮进入编译界面。

![图片](https://3485192048-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fhypergraph-decentralized-data-engine%2F-M_C5fuoOO2UeWfhwT6Q%2F-M_C60UhhNPnsgF8-FnQ%2F2.png?generation=1620496361760033\&alt=media)

1处是选择编译器版本， solidity语言有很多版本，而且更新很快，新版本会出现很多不向下兼容版本的情况（以太坊官方说自己的开发文化是敢于创新也体现在此），所以这里选择编译器版本很关键， 如果你是在网上找到代码来调试，一定看看代码中声明适合什么版本的，这里编译器选择到对应的版本。

2处点击即可开始编译

3处可以复制编译好的bytecode和ABI， bytecode就是在创建合约时需要像以太坊传递的参数data中的内容， ABI是向机器指令层面编码和解密传送数据的主要方式， ABI有点类似类的反射，通过ABI知道合约有哪些方法和传参。

点击![图片](https://3485192048-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fhypergraph-decentralized-data-engine%2F-M_C5fuoOO2UeWfhwT6Q%2F-M_C60UikFCNYo6f-fWY%2F3.png?generation=1620496361772574\&alt=media) 按钮进入部署合约界面

![图片](https://3485192048-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fhypergraph-decentralized-data-engine%2F-M_C5fuoOO2UeWfhwT6Q%2F-M_C60Uja1zTLQwFJDGv%2F4.png?generation=1620496361764887\&alt=media)

1处选择编译环境， JavascriptVM 是Remix自带的虚拟机环境，用这个环境可以不用连接钱包就可以调试。 injected Web3 可以连接MetaMask钱包进行调试。 Web3 Provider是连接本地的Ganache测试环境。

点击Deploy按钮进行部署

2处是部署完成后返回的合约地址 ，点开合约地址可以调试合约的函数调用。 (PS：我们也可以在At Address处输入已知的合约地址，调试合约)

我们可以看见因为合约定义了withdraw函数， 所以点开合约地址后下面会有withdraw的调用的地方。

在withdraw旁边输入框输入数字，点击 withdraw按钮可以调试 withdraw函数。 此时调用withdraw会失败，因为这个合约上没有余额

增加余额的方式：

1，给合约地址充币

可以在remix编辑器控制台命令行输入：

web3.eth.sendTransaction({from:"账号地址",to:"合约地址",value:'1000000000000000000'});

上面命令为打1ETH到合约地址。

2，可以在部署合约时输入Value的值（PS：这需要合约的构造函数声明payable才可以接受支付，上面示例代码还没有支持， 后面的演示示例中演示怎么支持payable）

### 2、Ganache本地区块链测试网络安装

<https://www.trufflesuite.com/ganache> 在这里下载安装。

Ganache可视化界面用的非常方便。他是本地的以太坊区块链测试环境， 会自动建立十个账号，并每个账号有100ETH，供我们调试程序。 可以在本地测试链上部署合约。 注意每次Ganache重启后会恢复初始状态，合约需要重新部署， 反复的部署合约需要管理起来， 所以下面我们介绍truffle工具管理合约。

### 3、安装truffle

安装：

npm install -g truffle

初始化truffle项目：

truffle init

目录结构：

├── contracts //存放合约

│   └── Migrations.sol

├── migrations //存放迁移文件

│   └── 1\_initial\_migration.js

├── test //存放测试脚本

└── truffle-config.js //配置文件

编译合约：

truffle compile

部署合约：

truflle migrate

进入命令行：

truffle console

在有truffle配置文件的项目中运行这个命令

### 4、用truffle部署合约

contracts目录下建立合约， 我们还是拿水龙头合约来测试。 建立文件名为：Faucet.sol

代码：

// SPDX-License-Identifier: MIT

pragma solidity ^0.4.5;

contract Faucet{

&#x20;constructor() public payable {}

&#x20;  function withdraw(uint withdraw\_amont) public {

&#x20;     require(withdraw\_amont<0.1 ether);

&#x20;     msg.sender.transfer(withdraw\_amont);

&#x20; }

&#x20; function() public payable{}

truffle 支持的编译器的版本是 0.5.16 , 上面合约是0.4.5版本的， 需要编译器版本可以在 truffle-config.js 配置文件中配置项compilers->solc->version 进行配置，修改为0.4.26。

上面代码增加了contructor为payable属性，主要是让等会创建合约时就可以打以太坊。

在migration文件中建立迁移文件： 2\_Faucet.js

const Faucet = artifacts.require("Faucet");

module.exports = function (deployer) {

&#x20; deployer.deploy(Faucet);

};

1\_initial\_migration.js 是第一个初始化合约， 这个合约的作用是记录了迁移到哪步了，避免重复迁移。migration合约巧妙的把区块链环境当作了数据库。

编译：

truffle compile

编译生成的文件叫作artifacts是json格式文件， 会生成在build/contracts 文件夹下, 生成的json文件会包含编译的betycode，abi，以及在部署后网络合约地址也在生成的json中包含

部署：

truflle migrate

默认会部署到Ganache测试网络, Ganache默认会创建10个有私钥的账号， truflle能读取到Ganacache的私钥，默认会用第一个账户进行部署。

更改部署时的账户并向合约充值： 在2\_Faucet.js文件代码修改如下：

const Faucet = artifacts.require("Faucet");

module.exports = function (deployer,network,accounts) {

&#x20; deployer.deploy(Faucet,{from:accounts\[1],value:web3.utils.toWei('1', 'ether')});

};

或者代码写为：

const Faucet = artifacts.require("Faucet");

module.exports = function (deployer,network,accounts) {

&#x20; deployer.deploy(Faucet).then(function(instance){

//先部署，部署成功后充值

&#x20;web3.eth.sendTransaction({from:accounts\[1],to:instance.address,value:web3.utils.toWei('1', 'ether')});

&#x20; });

};

重新部署：

truffle migrate --reset

用truflle console命令行控制台也给合约账户充值：

truffle console

\>let accounts=await web3.eth.getAccounts()

\>let instance=await Faucet.deployed()

\>web3.eth.sendTransaction({from:accounts\[1],to:instance.address,value:web3.utils.toWei('1', 'ether')})

### 5、用VUE开发水龙头合约界面

安装vue命令行

npm install -g @vue/cli

用vue命令行创建一个应用

vue create myapp

安装依赖

cd myapp

yarn add web3

yarn add @truffle/contract

复制上面合约编译生成的artifacts文件Faucet.json 到 Vue项目src/components/文件夹下。

编辑HelloWorld.vue文件，在默认的界面上增加一个点击按钮

\<button @click="click">水龙头\</button>

在VUM的javascript代码部分使用如下代码

\<script>

import Web3 from "web3";

import contract from "@truffle/contract";

import FaucetJson from "./Faucet.json";

import { BigNumber } from '@ethersproject/bignumber';

export default {

&#x20; data(){

&#x20;   return {

&#x20;     web3:false,

&#x20;     contract\_instance:false,

&#x20;     accounts:\[]

&#x20;   }

&#x20; },

&#x20; async created(){

&#x20;    //初始化web3

&#x20;    // Modern dapp browsers...

&#x20;   let web3Provider ;

&#x20;   if (window\.ethereum) {

&#x20;     web3Provider = window\.ethereum;

&#x20;     try {

&#x20;       // Request account access

&#x20;       await window\.ethereum.enable();

&#x20;     } catch (error) {

&#x20;       // User denied account access...

&#x20;       console.error("User denied account access")

&#x20;     }

&#x20;   }

&#x20;   // Legacy dapp browsers...

&#x20;   else if (window\.web3) {

&#x20;     web3Provider = window\.web3.currentProvider;

&#x20;   }

&#x20;   // If no injected web3 instance is detected, fall back to Ganache

&#x20;   else {

&#x20;     web3Provider = new Web3.providers.HttpProvider('<http://localhost:7545>');

&#x20;   }

&#x20;   this.web3 = new Web3(web3Provider);

&#x20;//初始化合约

&#x20;   const FaucetContract=contract(FaucetJson);

&#x20;   FaucetContract.setProvider(web3Provider);

&#x20;   this.contract\_instance=await FaucetContract.deployed();

&#x20;   this.accounts=await this.web3.eth.getAccounts();

&#x20; },

&#x20; methods:{

&#x20;    click(){

&#x20;//调用合约的withdraw函数     this.contract\_instance.withdraw(this.web3.utils.toWei('1','ether'),{from:this.accounts\[0]});

&#x20;    }

&#x20; },

&#x20; name: 'HelloWorld',

&#x20; props: {

&#x20;   msg: String

&#x20; }

}

\</script>

JS代码中一般调用的步骤是：初始化web3实例-> 初始化合约实例->调用合约

在调用withdraw，不用将值做BigNumber的转换， 因为truflle-contract 底层会做BigNumber转换

运行环境：

yarn serve

这时候在浏览器点击按钮可以试用水龙头功能。

注意，如果出现报错： Error: the tx doesn't have the correct nonce. account has nonce of: 14 tx has nonce of: 0 ， 是钱包的问题，不是代码的问题。 关闭浏览器重启一下MetaMask钱包。

### 6、结合火币链开发

MetaMask添加自定义RPC，添加火币生态链测试地址：

chainid 256

RPC  [https://http-testnet.hecochain.com](https://weibo.cn/sinaurl?u=https%253A%252F%252Fhttp-testnet.hecochain.com%252F)

区块浏览：<https://scan-testnet.hecochain.com/home/index> (PS: 火币生态的浏览器地址可以清晰看到合约的源码，这里是学习合约的一个好地方)

![图片](https://3485192048-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fhypergraph-decentralized-data-engine%2F-M_C5fuoOO2UeWfhwT6Q%2F-M_C60Uk9FJ89CghLr0T%2F5.png?generation=1620496361826573\&alt=media)

到水龙头下去领币：

<https://scan-testnet.hecochain.com/faucet>

火币链是基于EOS的，出块速度更快，也兼用以太坊的EVM，部署合约的操作步骤和以太坊没有区别。

* truffle配置火币链生态链

在truffle项目中安装依赖

yarn add @truffle/hdwallet-provider\@1.0.18

然后编辑配置文件truffle-config.js

去掉下面几行注释

const HDWalletProvider = require('@truffle/hdwallet-provider');

const fs = require('fs');

const mnemonic = fs.readFileSync(".secret").toString().trim();

在.secret 文件中添加账号的私钥， 私钥可以从metamask的账号详情导出。

在  networks下添加:

hecotest: {

&#x20;   provider: () => new HDWalletProvider(mnemonic, \`<https://http-testnet.hecochain.com\\`>),

&#x20;       network\_id: 256

&#x20;    },

&#x20;    hecomain: {

&#x20;       provider: () => new HDWalletProvider(mnemonic, "<https://http-mainnet.hecochain.com>"),

&#x20;       network\_id: 128

&#x20;    }

部署合约时指定网络名称：

truffle migrate --network=hecotest

hdwallet-provider一定要安装1.0.18版本的，不然会有报错：invalid sender , 可能是新版本用法不一样， truffle配置文件中的实例代码是老版本用户。
