开发工具:
truffle
vue
metamask
目录结构:
demo ├── contracts │ ├── Demo.sol │ ├── Lib.sol │ └── Migrations.sol ├── migrations │ ├── 1_initial_migration.js │ └── 2_demo.js ├── package.json ├── public │ ├── favicon.ico │ └── index.html ├── src │ ├── App.vue │ ├── components │ │ └── Demo.vue │ └── main.js ├── test │ └── Demo.js └── truffle-config.js
环境搭建:
- 安装
vue-cli
:npm install -g @vue/cli
- 创建项目:
vue create demo
- 进入项目根目录:
cd demo
- 安装
truffle-contract
、web3
:npm install truffle-contract web3
- 安装
truffle
智能合约配置:- 初始化项目:
truffle init
- 修改配置文件:
vim truffle-config.js
// const HDWalletProvider = require('truffle-hdwallet-provider'); // const mnemonic = 'relief submit stairs blossom blossom brush sheriff aisle dice swing number lyrics'; module.exports = { networks: { // rinkeby: { // provider: new HDWalletProvider(mnemonic, 'https://rinkeby.infura.io/v3/ca8b6a8c5394446db1ee24ba523cbffe'), // network_id: '4' // }, develop: { host: "127.0.0.1", port: 8545, network_id: 20, accounts: 5, defaultEtherBalance: 500, // blockTime: 3, gas: 4712388, gasPrice: 100000000000, // from: "0xef6a214542A5371F321a3e457EeC76DA2b4b3C34" } }, compilers: { solc: { version: "0.8.0" } } };
- 开启测试网络:
truffle develop --log
- 设置
metamask
到truffle develop
网络(略) - 安装
@openzeppelin/contracts
:npm install @openzeppelin/contracts
- 安装
truffle-hdwallet-provider
(可选):npm install truffle-hdwallet-provider
- 创建
solidity
文件:- 创建合约文件:
vim contracts/Demo.sol
// SPDX-License-Identifier: GPL-3.0 import "./Lib.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; pragma solidity ^0.8.0; contract Demo is ERC20 { event PrintNum(uint _num,uint _add); event DoTransfer(address _to,uint _amount); uint num; constructor() public ERC20('WETH', 'WETH') { num = 1; } // eth-to-weth receive() external payable { require(msg.value > 0); _mint(msg.sender, msg.value); } // weth-to-eth function transfer(address recipient, uint256 amount) public virtual override returns (bool) { if (recipient == address(this)) { _burn(msg.sender, amount); payable(msg.sender).transfer(amount); } else { _transfer(_msgSender(), recipient, amount); } return true; } function get() public view returns (uint) { return num; } function add(uint _add) public { emit PrintNum(num,_add); num = Lib.add(num,_add); } function getBalance(address addr) public view returns (uint) { return addr.balance; } function doTransfer(address payable _to) public payable{ _to.transfer(msg.value); emit DoTransfer(_to,msg.value); } }
- 创建库文件:
vim contracts/Lib.sol
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.0; library Lib{ function add(uint a,uint b) public pure returns(uint){ return a + b; } }
- 创建合约文件:
- 创建测试脚本:
vim test/Demo.js
const Demo = artifacts.require('./Demo.sol'); contract('Demo', (accounts) => { it('get', async () => { const demo = await Demo.deployed() const num = await demo.get() console.log('num is:') console.log(num.toNumber()) assert.equal(num, 1) }) it('add', async () => { const demo = await Demo.deployed() await demo.add(2); const num = await demo.get() assert.equal(num, 3) }) it('do transfer', async () => { const demo = await Demo.deployed() await demo.doTransfer('0xef6a214542A5371F321a3e457EeC76DA2b4b3C34', {value: 10 ** 18}) }) it('get balance', async () => { const demo = await Demo.deployed() const balance = await demo.getBalance('0xef6a214542A5371F321a3e457EeC76DA2b4b3C34') console.log('balance is:') console.log(balance.toString()) }) it('get weth balance', async () => { const demo = await Demo.deployed() const balance = await demo.balanceOf('0xef6a214542A5371F321a3e457EeC76DA2b4b3C34') console.log('weth balance is:') console.log(balance.toString()) }) });
- 测试合约:
truffle test --show-events --network develop test/Demo.js
- 编译:
truffle compile --network develop
- 创建部署脚本:
vim migrations/2_demo.js
var Demo = artifacts.require("./Demo.sol"); var Lib = artifacts.require("./Lib.sol"); module.exports = function(deployer) { deployer.deploy(Lib,{overwrite: false}); deployer.link(Lib,Demo); deployer.deploy(Demo); };
- 部署合约:
truffle migrate --reset --network develop
- 查看部署成功的合约地址:
truffle networks
- 控制台
console
用法:- 进入控制台:
truffle console --network develop
- 实例化合约:
let instance = await Demo.deployed()
- 调用合约方法:
let num = await instance.get() console.log(num.toNumber()) await instance.add(2) num = await instance.get() console.log(num.toNumber()) await instance.doTransfer('0xef6a214542A5371F321a3e457EeC76DA2b4b3C34',{value: 10**18}) let balance = await instance.getBalance('0xef6a214542A5371F321a3e457EeC76DA2b4b3C34') console.log(balance.toString())
- 退出控制台:
.exit
- 进入控制台:
- 使用区块链浏览器浏览本地区块数据(略):
ethscan-私有链浏览器
- 初始化项目:
vue
前端页面编写:App.vue
:vim src/App.vue
<template> <div id="app"> <Demo/> </div> </template> <script> import Demo from './components/Demo.vue'; export default { name: 'app', components: { Demo } } </script>
Demo.vue
(重点):vim src/components/Demo.vue
<template> <ul> <li>---</li> <li>current num: <input :value="currentNum" disabled></li> <li>---</li> <li><input v-model="newNum"></li> <li> <button @click="addNum">add num</button> </li> <li>---</li> <li>current balance: <input :value="balance" disabled></li> <li>address: <input v-model="toAddress"> amount: <input v-model="amount"></li> <li> <button @click="transferTo">do transfer</button> </li> <li>---</li> <li>address: <input v-model="toAddressByWeb3"> amount: <input v-model="amountByWeb3"></li> <li> <button @click="sendTransactionByWeb3">send transaction</button> </li> <li>---</li> <li> <button @click="getBalanceByWeb3">get balance</button> </li> <li>{{ balanceByWeb3 }}</li> <li>---</li> <li> <button @click="getBalanceOfWeth">get weth balance</button> </li> <li>{{ balanceOfWeth }}</li> <li>---</li> <li><input v-model="eth"></li> <li> <button @click="ethToWeth">eth to weth</button> </li> <li>---</li> <li><input v-model="weth"></li> <li> <button @click="wethToEth">weth to eth</button> </li> </ul> </template> <script> import Web3 from "web3"; import contract from "truffle-contract"; import demo from '../../build/contracts/Demo.json'; export default { name: 'Demo', data() { return { web3: null, provider: null, account: null, contractInstance: null, currentNum: 0, newNum: 0, toAddress: "", amount: 0, balance: 0, toAddressByWeb3: "", amountByWeb3: 0, balanceByWeb3: 0, balanceOfWeth: 0, eth: 0, weth: 0, } }, async created() { await this.initWeb3Account(); await this.initContract(); await this.getNum(); }, methods: { async initWeb3Account() { if (window.ethereum) { this.provider = window.ethereum; try { await window.ethereum.enable(); } catch (error) { alert("User denied account access"); } } else if (window.web3) { this.provider = window.web3.currentProvider; } else { this.provider = new Web3.providers.HttpProvider("http://127.0.0.1:8545"); } this.web3 = new Web3(this.provider); this.web3.eth.getAccounts().then(accs => { this.account = accs[0]; }) }, async initContract() { let demoContract = contract(demo); demoContract.setProvider(this.provider); this.contractInstance = await demoContract.deployed(); }, async getNum() { this.contractInstance.get().then( res => { this.currentNum = res; } ) }, addNum() { this.contractInstance.add(this.newNum, { from: this.account }).then(() => { this.getNum(); }) }, async getBalance() { let _this = this; this.contractInstance.getBalance(this.toAddress).then( res => { this.balance = _this.web3.utils.fromWei(res, 'ether'); } ) }, transferTo() { this.contractInstance.doTransfer(this.toAddress, { from: this.account, value: this.amount * 10 ** 18 }).then(() => { this.getBalance(); }) }, sendTransactionByWeb3() { this.web3.eth.sendTransaction({ from: this.account, to: this.toAddressByWeb3, value: this.amountByWeb3 * 10 ** 18 }, function (err, hash) { console.log(err, hash); }) }, getBalanceByWeb3() { let _this = this; this.web3.eth.getBalance(this.account).then( function (wei) { _this.balanceByWeb3 = _this.web3.utils.fromWei(wei, 'ether'); } ) }, async getBalanceOfWeth() { this.contractInstance.balanceOf(this.account).then( res => { this.balanceOfWeth = this.web3.utils.fromWei(res.toString(), 'ether'); } ) }, ethToWeth() { this.web3.eth.sendTransaction({ from: this.account, to: this.contractInstance.address, value: this.web3.utils.toWei(this.eth.toString(), 'ether') }, function (err, hash) { console.log(err, hash); }); }, wethToEth() { this.contractInstance.transfer(this.contractInstance.address, this.web3.utils.toWei(this.weth.toString(), 'ether'), { from: this.account }).then(() => { this.getBalanceOfWeth(); }) }, } } </script>
- 运行:
npm run serve
文档更新时间: 2024-04-20 10:57 作者:lee