基础开发环境

本教程是技术大牛 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{

function withdraw(uint withdraw_amont) public {

require(withdraw_amont<0.1 ether);

msg.sender.transfer(withdraw_amont);

}

function() public payable{}

}

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

2处点击即可开始编译

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

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{

constructor() public payable {}

function withdraw(uint withdraw_amont) public {

require(withdraw_amont<0.1 ether);

msg.sender.transfer(withdraw_amont);

}

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) {

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) {

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

};

或者代码写为:

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

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

deployer.deploy(Faucet).then(function(instance){

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

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

});

};

重新部署:

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 {

data(){

return {

web3:false,

contract_instance:false,

accounts:[]

}

},

async created(){

//初始化web3

// Modern dapp browsers...

let web3Provider ;

if (window.ethereum) {

web3Provider = window.ethereum;

try {

// Request account access

await window.ethereum.enable();

} catch (error) {

// User denied account access...

console.error("User denied account access")

}

}

// Legacy dapp browsers...

else if (window.web3) {

web3Provider = window.web3.currentProvider;

}

// If no injected web3 instance is detected, fall back to Ganache

else {

web3Provider = new Web3.providers.HttpProvider('http://localhost:7545');

}

this.web3 = new Web3(web3Provider);

//初始化合约

const FaucetContract=contract(FaucetJson);

FaucetContract.setProvider(web3Provider);

this.contract_instance=await FaucetContract.deployed();

this.accounts=await this.web3.eth.getAccounts();

},

methods:{

click(){

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

}

},

name: 'HelloWorld',

props: {

msg: String

}

}

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

到水龙头下去领币:

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: {

provider: () => new HDWalletProvider(mnemonic, `https://http-testnet.hecochain.com`),

network_id: 256

},

hecomain: {

provider: () => new HDWalletProvider(mnemonic, "https://http-mainnet.hecochain.com"),

network_id: 128

}

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

truffle migrate --network=hecotest

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

Last updated