win10搭建truffle框架(踩坑、填坑至无坑)

1.版本信息

1.1 node

node -v
v12.15.0

1.2 npm

npm -v
6.13.4
#换源
npm config set registry https://registry.npm.taobao.org


npm config list
; cli configs
metrics-registry = "https://registry.npm.taobao.org/"
scope = ""
user-agent = "npm/6.13.4 node/v12.15.0 win32 x64"

; userconfig C:\Users\12173\.npmrc
registry = "https://registry.npm.taobao.org/"

; builtin config undefined
prefix = "C:\\Users\\12173\\AppData\\Roaming\\npm"

; node bin location = E:\Program Files\nodejs\node.exe
; cwd = C:\Users\12173
; HOME = C:\Users\12173
; "npm config ls -l" to show all defaults.

1.3 git

git --version
git version 2.21.0.windows.1

1.4 安装ganache-cli节点仿真器

1.4.1 简介

用于测试和开发的快速以太坊RPC客户端。

注意:testrpc 是现在的ganache-cli。 像使用testrpc一样去使用它。

为了快速开发和测试以太坊DApp,我们通常使用以太坊节点仿真器来模拟区块链,最流行的节点仿真器就是Ganache,之前被称为TeseRPC。

1.4.2 安装

npm install -g ganache-cli

C:\Users\12173\AppData\Roaming\npm\ganache-cli -> C:\Users\12173\AppData\Roaming\npm\node_modules\ganache-cli\cli.js
+ [email protected]
updated 1 package in 5.506s

ganache-cli --version
Ganache CLI v6.9.1 (ganache-core: 2.10.2)

1.5 安装solidity编译器

1.5.1 简介

solidity是开发以太坊智能合约的编程语言。 官网 : https://solidity.readthedocs.io/en/v0.6.3/

1.5.2 安装

npm install -g solc

C:\Users\12173\AppData\Roaming\npm\solcjs -> C:\Users\12173\AppData\Roaming\npm\node_modules\solc\solcjs
+ [email protected]
added 25 packages from 15 contributors in 39.318s

solcjs -V
0.6.3+commit.8dda9521.Emscripten.clang

1.6 Web3

1.6.1 简介

web3.js是一个库集合,你可以使用HTTP或IPC连接本地或远程以太它节点进行交互。 web3的JavaScript库能够与以太坊区块链交互。 它可以检索用户帐户,发送交易,与智能合约交互等。

1.6.2 安装

npm install -g [email protected]
+ [email protected]
added 6 packages from 9 contributors in 44.408s

node -p 'require("web3")'
require(web3)

1.7 Truffle

1.7.1 简介

Truffle是针对基于以太坊的Solidity语言的一套开发框架。 本身基于Javascript

1.7.2 安装

npm install -g truffle
C:\Users\12173\AppData\Roaming\npm\truffle -> C:\Users\12173\AppData\Roaming\npm\node_modules\truffle\build\cli.bundled.js

> [email protected] postinstall C:\Users\12173\AppData\Roaming\npm\node_modules\truffle
> node ./scripts/postinstall.js

- Fetching solc version list from solc-bin. Attempt #1
- Fetching solc version list from solc-bin. Attempt #2
- Fetching solc version list from solc-bin. Attempt #3
+ [email protected]
added 27 packages from 439 contributors in 121.064s

truffle --version
Truffle v5.1.14 - a development framework for Ethereum

Usage: truffle <command> [options]

Commands:
  build     Execute build pipeline (if configuration present)
  compile   Compile contract source files
  config    Set user-level configuration options
  console   Run a console with contract abstractions and commands available
  create    Helper to create new contracts, migrations and tests
  debug     Interactively debug any transaction on the blockchain (experimental)
  deploy    (alias for migrate)
  develop   Open a console with a local development blockchain
  exec      Execute a JS module within this Truffle environment
  help      List all commands or provide information about a specific command
  init      Initialize new and empty Ethereum project
  install   Install a package from the Ethereum Package Registry
  migrate   Run migrations to deploy contracts
  networks  Show addresses for deployed contracts on each network
  obtain    Fetch and cache a specified compiler
  opcode    Print the compiled opcodes for a given contract
  publish   Publish a package to the Ethereum Package Registry
  run       Run a third-party command
  test      Run JavaScript and Solidity tests
  unbox     Download a Truffle Box, a pre-built Truffle project
  version   Show version number and exit
  watch     Watch filesystem for changes and rebuild the project automatically

See more at http://truffleframework.com/docs

1.8webpack

1.8.1简介

本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle

1.8.2安装

 npm install -g [email protected]
C:\Users\12173\AppData\Roaming\npm\webpack -> C:\Users\12173\AppData\Roaming\npm\node_modules\webpack\bin\webpack.js

> [email protected] postinstall C:\Users\12173\AppData\Roaming\npm\node_modules\webpack\node_modules\uglifyjs-webpack-plugin
> node lib/post_install.js

npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected] (node_modules\webpack\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

+ [email protected]
added 333 packages from 285 contributors in 26.975s

webpack -v
3.11.0

2.相关知识

2.1 Truffle与web3初始

Truffle提供功能如下

  1. 内置智能合约编译、链接、部署和二进制字节码管理

  2. 针对快速迭代开发的自动化合约

  3. 可脚本化、可扩展部署和迁移框架

  4. 网络管理,可部署到任意数量的公共网络和私有网络

  5. 使用EthPM和NPM进行包安装管理

  6. 用于直接与合约通信的交互式控制台

  7. 支持持续集成可配置构建管道

  8. 外部脚本运行程序可以在Truffle环境中执行脚本

  9. 提供合约抽象接口,可以直接通过var instance = Storage.deployed()拿到合约对象,然后在JavaScript中直接操作对应的合约函数。

**web3.js **

  1. web3.js提供了用于和geth通信的javascript API,其内部使用了JSON-RPC与geth通信。

  2. JSON-RPC是一个无状态且轻量级的远程过程调用,允许使用socket,http等协议进行通信。使用JSON作为数据格式。

  3. web3.js可以与所有支持JSON-RPC的节点通信。不仅支持ETH中的API,还支持ETH生态中其他系统的API,比如whispir

  4. whispir是一个集成进ETH的消息系统 , 允许DApp发送小量信息进行非实时通信。

3. Truffle项目构建

3.1初始化项目(truffle unbox webpack)

truffle unbox webpack
This directory is non-empty...
? Proceed anyway? (Y/n)
Starting unbox...
=================

? Proceed anyway? Yes
√ Preparing to download box
√ Downloading
gyp ERR! find Python
gyp ERR! find Python Python is not set from command line or npm configuration
gyp ERR! find Python Python is not set from environment variable PYTHON
gyp ERR! find Python checking if "python" can be used
gyp ERR! find Python - "python" is not in PATH or produced an error
gyp ERR! find Python checking if "python2" can be used
gyp ERR! find Python - "python2" is not in PATH or produced an error
gyp ERR! find Python checking if "python3" can be used
gyp ERR! find Python - "python3" is not in PATH or produced an error
gyp ERR! find Python checking if the py launcher can be used to find Python 2
gyp ERR! find Python - "py.exe" is not in PATH or produced an error
gyp ERR! find Python checking if Python is C:\Python27\python.exe
gyp ERR! find Python - "C:\Python27\python.exe" could not be run
gyp ERR! find Python checking if Python is C:\Python37\python.exe
gyp ERR! find Python - "C:\Python37\python.exe" could not be run
gyp ERR! find Python
gyp ERR! find Python **********************************************************
gyp ERR! find Python You need to install the latest version of Python.
gyp ERR! find Python Node-gyp should be able to find and use Python. If not,
gyp ERR! find Python you can try one of the following options:
gyp ERR! find Python - Use the switch --python="C:\Path\To\python.exe"
gyp ERR! find Python   (accepted by both node-gyp and npm)
gyp ERR! find Python - Set the environment variable PYTHON
gyp ERR! find Python - Set the npm configuration variable python:
gyp ERR! find Python   npm config set python "C:\Path\To\python.exe"
gyp ERR! find Python For more information consult the documentation at:
gyp ERR! find Python https://github.com/nodejs/node-gyp#installation
gyp ERR! find Python **********************************************************
gyp ERR! find Python
gyp ERR! configure error
gyp ERR! stack Error: Could not find any Python installation to use
gyp ERR! stack     at PythonFinder.fail (E:\Program Files\nodejs\node_modules\npm\node_modules\node-gyp\lib\find-python.js:307:47)
gyp ERR! stack     at PythonFinder.runChecks (E:\Program Files\nodejs\node_modules\npm\node_modules\node-gyp\lib\find-python.js:136:21)
gyp ERR! stack     at PythonFinder.<anonymous> (E:\Program Files\nodejs\node_modules\npm\node_modules\node-gyp\lib\find-python.js:225:16)
gyp ERR! stack     at PythonFinder.execFileCallback (E:\Program Files\nodejs\node_modules\npm\node_modules\node-gyp\lib\find-python.js:271:16)
gyp ERR! stack     at exithandler (child_process.js:302:5)
gyp ERR! stack     at ChildProcess.errorhandler (child_process.js:314:5)
gyp ERR! stack     at ChildProcess.emit (events.js:223:5)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:270:12)
gyp ERR! stack     at onErrorNT (internal/child_process.js:456:16)
gyp ERR! stack     at processTicksAndRejections (internal/process/task_queues.js:81:21)
gyp ERR! System Windows_NT 10.0.16299
gyp ERR! command "E:\\Program Files\\nodejs\\node.exe" "E:\\Program Files\\nodejs\\node_modules\\npm\\node_modules\\node-gyp\\bin\\node-gyp.js" "rebuild"
gyp ERR! cwd E:\Dapp\hello\app\node_modules\keccak
gyp ERR! node -v v12.15.0
gyp ERR! node-gyp -v v5.0.5
gyp ERR! not ok
/ Downloading
npm ERR! errno 1
npm ERR! [email protected] rebuild: `node-gyp rebuild`

npm ERR!
npm ERR! Failed at the [email protected] rebuild script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm WARN Local package.json exists, but node_modules missing, did you mean to install?

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\12173\AppData\Roaming\npm-cache\_logs\2020-02-22T17_26_38_700Z-debug.log
gyp ERR! find Python

gyp ERR! find Python Python is not set from environment variable PYTHON
gyp ERR! find Python checking if "python" can be used
gyp ERR! find Python - "python" is not in PATH or produced an error
gyp ERR! find Python checking if "python2" can be used
gyp ERR! find Python - "python2" is not in PATH or produced an error
gyp ERR! find Python checking if "python3" can be used
gyp ERR! find Python - "python3" is not in PATH or produced an error
gyp ERR! find Python checking if the py launcher can be used to find Python 2
gyp ERR! find Python - "py.exe" is not in PATH or produced an error
gyp ERR! find Python checking if Python is C:\Python27\python.exe
gyp ERR! find Python - "C:\Python27\python.exe" could not be run
gyp ERR! find Python checking if Python is C:\Python37\python.exe
gyp ERR! find Python - "C:\Python37\python.exe" could not be run
gyp ERR! find Python
gyp ERR! find Python **********************************************************
gyp ERR! find Python You need to install the latest version of Python.
gyp ERR! find Python Node-gyp should be able to find and use Python. If not,
gyp ERR! find Python you can try one of the following options:
gyp ERR! find Python - Use the switch --python="C:\Path\To\python.exe"
gyp ERR! find Python   (accepted by both node-gyp and npm)
gyp ERR! find Python - Set the environment variable PYTHON
gyp ERR! find Python - Set the npm configuration variable python:
gyp ERR! find Python   npm config set python "C:\Path\To\python.exe"
gyp ERR! find Python For more information consult the documentation at:
gyp ERR! find Python https://github.com/nodejs/node-gyp#installation
gyp ERR! find Python **********************************************************
gyp ERR! find Python
gyp ERR! configure error
gyp ERR! stack Error: Could not find any Python installation to use
gyp ERR! stack     at PythonFinder.fail (E:\Program Files\nodejs\node_modules\npm\node_modules\node-gyp\lib\find-python.js:307:47)
gyp ERR! stack     at PythonFinder.runChecks (E:\Program Files\nodejs\node_modules\npm\node_modules\node-gyp\lib\find-python.js:136:21)
gyp ERR! stack     at PythonFinder.<anonymous> (E:\Program Files\nodejs\node_modules\npm\node_modules\node-gyp\lib\find-python.js:225:16)
gyp ERR! stack     at PythonFinder.execFileCallback (E:\Program Files\nodejs\node_modules\npm\node_modules\node-gyp\lib\find-python.js:271:16)
gyp ERR! stack     at exithandler (child_process.js:302:5)
gyp ERR! stack     at ChildProcess.errorhandler (child_process.js:314:5)
gyp ERR! stack     at ChildProcess.emit (events.js:223:5)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:270:12)
gyp ERR! stack     at onErrorNT (internal/child_process.js:456:16)
gyp ERR! stack     at processTicksAndRejections (internal/process/task_queues.js:81:21)
gyp ERR! System Windows_NT 10.0.16299
gyp ERR! command "E:\\Program Files\\nodejs\\node.exe" "E:\\Program Files\\nodejs\\node_modules\\npm\\node_modules\\node-gyp\\bin\\node-gyp.js" "rebuild"
gyp ERR! cwd E:\Dapp\hello\app\node_modules\secp256k1
gyp ERR! node -v v12.15.0
gyp ERR! node-gyp -v v5.0.5
gyp ERR! not ok
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] rebuild: `node-gyp rebuild`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] rebuild script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm WARN Local package.json exists, but node_modules missing, did you mean to install?

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\12173\AppData\Roaming\npm-cache\_logs\2020-02-22T17_26_39_779Z-debug.log
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected] (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

√ cleaning up temporary files
√ Setting up box

Unbox successful, sweet!

Commands:

  Compile:              truffle compile
  Migrate:              truffle migrate
  Test contracts:       truffle test
  Run dev server:       cd app && npm run dev
  Build for production: cd app && npm run build

解决没有python环境的问题:

我们选择安装windows-build-tools,他的依赖中包含一些Visual Studio Build Tools以及python2.7

npm install --global --production windows-build-tools 

> [email protected] postinstall C:\Users\12173\AppData\Roaming\npm\node_modules\windows-build-tools
> node ./dist/index.js



Downloading python-2.7.15.amd64.msi
[>                                            ] 0.0% (0 B/s)
Downloaded python-2.7.15.amd64.msi. Saved to C:\Users\12173\.windows-build-tools\python-2.7.15.amd64.msi.
Downloading vs_BuildTools.exe
[>                                            ] 0.0% (0 B/s)
Downloaded vs_BuildTools.exe. Saved to C:\Users\12173\.windows-build-tools\vs_BuildTools.exe.

Starting installation...
Launched installers, now waiting for them to finish.
This will likely take some time - please be patient!

Status from the installers:
---------- Visual Studio Build Tools ----------
Successfully installed Visual Studio Build Tools.
------------------- Python --------------------
Action ended 12:45:23: MsiUnpublishAssemblies. Return value 1.
Action start 12:45:23: UnpublishFeatures.
Action ended 12:45:23: UnpublishFeatures. Return value 1.
Action start 12:45:23: StopServices.
Action ended 12:45:23: StopServices. Return value 1.

Now configuring the Visual Studio Build Tools and Python...

All done!

+ [email protected]
updated 1 package in 15.463s

配置python2.7的环境变量

在系统变量path下添加如下内容:

C:\Users\12173.windows-build-tools\python27

初始化成功结果如下:

$ truffle unbox webpack

Starting unbox...
=================

- Preparing to download box
√ Preparing to download box
- Downloading
√ Downloading
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected] (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

- cleaning up temporary files
√ cleaning up temporary files
- Setting up box
√ Setting up box

Unbox successful, sweet!

Commands:

  Compile:              truffle compile
  Migrate:              truffle migrate
  Test contracts:       truffle test
  Run dev server:       cd app && npm run dev
  Build for production: cd app && npm run build


3.2 修改truffle配置

     development: {
      host: "127.0.0.1",     // Localhost (default: none)
      port: 8545,            // Standard Ethereum port (default: none)
      network_id: "*",       // Any network (default: none)
     },

3.3启动节点( ganache-cli )

$ ganache-cli
Ganache CLI v6.9.1 (ganache-core: 2.10.2)

Available Accounts
==================
(0) 0xc1a8803eAA83aCb7bf942e5cAf4284b0e2AdcDD7 (100 ETH)
(1) 0xd188bc0a7BEE5890dcd0D59d384199520D75665D (100 ETH)
(2) 0xC7be8b832cb3A3285803a006648Fe4dB0E0e4dD9 (100 ETH)
(3) 0xe1F1B3C361fd5361ad131aA9BBfDef9BaC3f009C (100 ETH)
(4) 0x2d8AfB48dA53BDFFd25B52d7f89A1455769571C7 (100 ETH)
(5) 0x8Ce8ceF65b854A49df75D7f9DcCd2a8017E263B8 (100 ETH)
(6) 0x87d5646Fcb48DBB8d0453104EDe3bb8b75fc75b6 (100 ETH)
(7) 0x6B950A801d325a08Fe7d064E2D1A60A700dA0812 (100 ETH)
(8) 0x74C29Af89F6ABD921059B3666168CD78F9144aE7 (100 ETH)
(9) 0x96708eaE55B8D3749493b7069692E31BDc9B4465 (100 ETH)

Private Keys
==================
(0) 0xe71b27443128f13736d4abf56be959231a495e240827fecda3e89671ddaf03c2
(1) 0xc6d43777cce13673ffce12406437e97d85f10809704643a6b348c00cb7bbeea3
(2) 0x9bdcbb3a51e3645c4788091f27fa33043f6a1c7ad078c654482bc04c847bd41b
(3) 0x0978ac0611e532bac1697beca2b7494981bababc9680a0d8176df3ef8a7f9e13
(4) 0xf0e5af8777fee7fc5aa1dff3ffac6f41f9f28a3da4abd300e9b5439b309822d3
(5) 0x9475d9b1047e2d52be6d9ab4c0eaeba2d0ecc54a305d3e75874551d0308d83cf
(6) 0x496a8ceed4f5c273905ade586e654c1504cbeaab61128e0197aa81bcfa0badd9
(7) 0xea4a812229f425bcab97c684b7aade7399e35bbe3f27971ff6c4d394d862a64f
(8) 0xba0a1f75915f771b4e24ceee2a96841e7d2f57849569b3da4d6e567b3206f278
(9) 0x79fa9edf9864b0f90c0b0e88e69cb56eb7a01e33f07c669b82ee053bd1248d3d

HD Wallet
==================
Mnemonic:      deputy explain stock just boat year health desk arrive double almost depend
Base HD Path:  m/44'/60'/0'/0/{account_index}

Gas Price
==================
20000000000

Gas Limit
==================
6721975

Call Gas Limit
==================
9007199254740991

Listening on 127.0.0.1:8545

成功之后,会给自动建立10个账户,必须先启动这个之后才能合约的编译与部署。否则部署不成功。

3.4 安装项目依赖的NPM包

npm install
npm WARN saveError ENOENT: no such file or directory, open 'E:\Dapp\myproject\package.json'
npm WARN enoent ENOENT: no such file or directory, open 'E:\Dapp\myproject\package.json'
npm WARN myproject No description
npm WARN myproject No repository field.
npm WARN myproject No README data
npm WARN myproject No license field.

up to date in 0.418s

出错原因:

缺少package.json文件。

解决办法:

#初始化项目
npm init -f

#安装依赖
npm install formidable --save

-f表示force的意思,不加这个,npm会让你输入一堆信息,比如name、version之类,如果只是做做实验小demo,直接-f,npm帮你初始化package.json,并填充各种默认值,省事。

--save表示将安装的包加入依赖列表的意思,可以看下package.json 里的dependencies字段。后面再运行 npm install,就会把所有依赖安装下来。如果不加--save,什么都不会安装。

npm init -f
npm WARN using --force I sure hope you know what you are doing.
Wrote to E:\Dapp\myproject\package.json:

{
  "name": "myproject",
  "version": "1.0.0",
  "description": "",
  "main": "truffle-config.js",
  "directories": {
    "test": "test"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
  
npm install formidable --save
npm WARN [email protected] No description
npm WARN [email protected] No repository field.

+ [email protected]
added 1 package in 0.438s

错误描述:

缺少描述、缺少仓库。

解决办法:

修改package.内容如下:

{
  "name": "myproject",
  "version": "1.0.0",
  "description": "my first project",
  "main": "truffle-config.js",
  "directories": {
    "test": "test"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "private": true,
  "dependencies": {
    "formidable": "^1.2.1"
  }
}

结果如下:

npm install formidable --save
+ [email protected]
updated 1 package in 0.353s

3.5编译合约(truffle compile)

E:\Dapp\myproject>truffle compile

Compiling your contracts...
===========================
> Compiling .\contracts\ConvertLib.sol
> Compiling .\contracts\MetaCoin.sol
> Compiling .\contracts\Migrations.sol
> Artifacts written to E:\Dapp\myproject\build\contracts
> Compiled successfully using:
   - solc: 0.5.16+commit.9c3226ce.Emscripten.clang

3.6部署合约(truffle migrate)

E:\Dapp\myproject>truffle migrate

Compiling your contracts...
===========================
> Compiling .\contracts\ConvertLib.sol
> Compiling .\contracts\MetaCoin.sol
> Compiling .\contracts\Migrations.sol
> Artifacts written to E:\Dapp\myproject\build\contracts
> Compiled successfully using:
   - solc: 0.5.16+commit.9c3226ce.Emscripten.clang



Starting migrations...
======================
> Network name:    'development'
> Network id:      1582444858253
> Block gas limit: 0x6691b7


1_initial_migration.js
======================

   Deploying 'Migrations'
   ----------------------
   > transaction hash:    0xe0b8512e708ca45c8b2e7237f689f61f658b4075f149f76cb8c842363f848af0
   > Blocks: 0            Seconds: 0
   > contract address:    0x9A73F98453dF48993F7a252C1e7810C05C976891
   > block number:        1
   > block timestamp:     1582446022
   > account:             0xc1a8803eAA83aCb7bf942e5cAf4284b0e2AdcDD7
   > balance:             99.9967165
   > gas used:            164175
   > gas price:           20 gwei
   > value sent:          0 ETH
   > total cost:          0.0032835 ETH


   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:           0.0032835 ETH


2_deploy_contracts.js
=====================

   Deploying 'ConvertLib'
   ----------------------
   > transaction hash:    0xb5e1469996cbd6f1592edce0d68c9661abb9c6d47d1b9af3b9121e7273c4c987
   > Blocks: 0            Seconds: 0
   > contract address:    0xe8b65D954EC3dB61A068184DAFAEcc7a4Ce3784E
   > block number:        3
   > block timestamp:     1582446023
   > account:             0xc1a8803eAA83aCb7bf942e5cAf4284b0e2AdcDD7
   > balance:             99.99396028
   > gas used:            95470
   > gas price:           20 gwei
   > value sent:          0 ETH
   > total cost:          0.0019094 ETH


   Linking
   -------
   * Contract: MetaCoin <--> Library: ConvertLib (at address: 0xe8b65D954EC3dB61A068184DAFAEcc7a4Ce3784E)

   Deploying 'MetaCoin'
   --------------------
   > transaction hash:    0x411669a9e6bb3c8986d411433ce92e4c2a89228069221b2d2f25efe01764bc9b
   > Blocks: 0            Seconds: 0
   > contract address:    0xC0B8C2A1384b4bacE94FA448B7cA1fD01C012f68
   > block number:        4
   > block timestamp:     1582446023
   > account:             0xc1a8803eAA83aCb7bf942e5cAf4284b0e2AdcDD7
   > balance:             99.98822898
   > gas used:            286565
   > gas price:           20 gwei
   > value sent:          0 ETH
   > total cost:          0.0057313 ETH


   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:           0.0076407 ETH


Summary
=======
> Total deployments:   3
> Final cost:          0.0109242 ETH

3.7启动Dapp(npm run dev)

**注意:**需要在app目录下执行,或者在当前目录执行cd app && npm run dev

npm run dev
npm ERR! missing script: dev

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\12173\AppData\Roaming\npm-cache\_logs\2020-02-23T08_21_47_877Z-debug.log

E:\Dapp\webpacktest\app>npm run dev

> [email protected] dev E:\Dapp\webpacktest\app
> webpack-dev-server

i 「wds」: Project is running at http://localhost:8080/
i 「wds」: webpack output is served from /
i 「wds」: Content not from webpack is served from E:\Dapp\webpacktest\app\dist
× 「wdm」: Hash: 438dc1a71410c6fb5b06
Version: webpack 4.41.2
Time: 1794ms
Built at: 2020-02-23 16:52:17
     Asset       Size  Chunks             Chunk Names
index.html  879 bytes          [emitted]
  index.js   2.37 MiB    main  [emitted]  main
Entrypoint main = index.js
[0] multi (webpack)-dev-server/client?http://localhost:8080 ./src/index.js 40 bytes {main} [built]
[./node_modules/ansi-html/index.js] 4.16 KiB {main} [built]
[./node_modules/html-entities/index.js] 231 bytes {main} [built]
[./node_modules/loglevel/lib/loglevel.js] 8.36 KiB {main} [built]
[./node_modules/web3/src/index.js] 2.01 KiB {main} [built]
[./node_modules/webpack-dev-server/client/index.js?http://localhost:8080] (webpack)-dev-server/client?http://localhost:8080 4.29 KiB {main} [built]
[./node_modules/webpack-dev-server/client/overlay.js] (webpack)-dev-server/client/overlay.js 3.51 KiB {main} [built]
[./node_modules/webpack-dev-server/client/socket.js] (webpack)-dev-server/client/socket.js 1.53 KiB {main} [built]
[./node_modules/webpack-dev-server/client/utils/createSocketUrl.js] (webpack)-dev-server/client/utils/createSocketUrl.js 2.89 KiB {main} [built]
[./node_modules/webpack-dev-server/client/utils/log.js] (webpack)-dev-server/client/utils/log.js 964 bytes {main} [built]
[./node_modules/webpack-dev-server/client/utils/reloadApp.js] (webpack)-dev-server/client/utils/reloadApp.js 1.59 KiB {main} [built]
[./node_modules/webpack-dev-server/client/utils/sendMessage.js] (webpack)-dev-server/client/utils/sendMessage.js 402 bytes {main} [built]
[./node_modules/webpack-dev-server/node_modules/strip-ansi/index.js] (webpack)-dev-server/node_modules/strip-ansi/index.js 161 bytes {main} [built]
[./node_modules/webpack/hot sync ^\.\/log$] (webpack)/hot sync nonrecursive ^\.\/log$ 170 bytes {main} [built]
[./src/index.js] 2.08 KiB {main} [built]
    + 349 hidden modules

ERROR in ./src/index.js
Module not found: Error: Can't resolve '../../build/contracts/MetaCoin.json' in 'E:\Dapp\webpacktest\app\src'
 @ ./src/index.js 2:0-67 15:30-46 17:8-24
i 「wdm」: Failed to compile.

运行结果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VJnPC6S0-1583398995100)(https://s2.ax1x.com/2020/02/23/3188K0.png)]

注:从3.3以后的操作都在项目工程的app目录下进行

4. 以太坊宠物商店‘

4.1初始化项目(truffle unbox pet-shop)

在指定目录下执行truffle unbox pet-shop命令初始化项目。生成目录如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WPPwZD46-1583398995101)(https://s2.ax1x.com/2020/02/26/3NA3DS.png)]

4.2编写智能合约

在contracts目录下创建新合约文件Adoption.sol内容如下:

pragma solidity >=0.4.21 <0.7.0;

contract Adoption {
	//定义变量 数组类型的 adopters   保存领养者地址
	address[16] public adopters;
	
	// 定义方法  
	//Adopting a pet 领养宠物
	function adopt(uint petId) public returns (uint) {
		require(petId >= 0 && petId <= 15);

		adopters[petId] = msg.sender;

	return petId;
	}
	// Retrieving the adopters  检索领养者
	function getAdopters() public view returns (address[16] memory) {
		return adopters;
	}
}

4.3编译和迁移智能合约

4.3.1汇编

Solidity是一种编译语言,这意味着我们需要将Solidity编译为字节代码,以供以太坊虚拟机(EVM)执行。将其视为将人类可读的Solidity转换为EVM可以理解的东西。

  1. 在项目根目录下执行truffle compile

    可以看到如下输出:

    $ truffle compile
    
    Compiling your contracts...
    ===========================
    > Compiling .\contracts\Adoption.sol
    > Compiling .\contracts\Migrations.sol
    > Artifacts written to E:\Dapp\guide-pet-shop\build\contracts
    > Compiled successfully using:
       - solc: 0.5.16+commit.9c3226ce.Emscripten.clang
    

4.3.2迁移

在成功编译合约后,需将合约迁移到区块链上。

迁移是一种部署脚本,旨在更改应用程序合同的状态,将其从一种状态转移到另一种状态。对于第一次迁移,您可能只是在部署新代码,但是随着时间的推移,其他迁移可能会移动数据或用新合同替换合同。

您将在migrations/目录中看到一个JavaScript文件:1_initial_migration.js。这将处理部署Migrations.sol合同以观察后续的智能合同迁移,并确保我们将来不会重复迁移未更改的合同。

现在,我们准备创建自己的迁移脚本。

  1. migrations/目录中创建一个新的js文件命名为 2_deploy_contracts.js

  2. 添加如下内容:

    var Adoption = artifacts.require("Adoption");
    
    module.exports = function(deployer) {
      deployer.deploy(Adoption);
    };
    
    
  3. 在将合同迁移到区块链之前,我们需要运行一个区块链。在此我使用的是ganache

    运行ganache

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OegJBEeF-1583398995102)(https://s2.ax1x.com/2020/02/26/3Nu4W4.png)]

  4. 回到我们的终端,将合同迁移到区块链(truffle migrate)。

    在打开的 Ganache 里可以看到区块链状态的变化,现在产生了 4 个区块。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S4hH5bJb-1583398995104)(https://s2.ax1x.com/2020/02/26/3NKuXn.png)]

4.4测试智能合约

Truffle在智能合约测试方面非常灵活,因为测试可以用JavaScript或Solidity编写。在此,我们将使用Solidity编写测试。

  1. test/目录中创建一个新文件 TestAdoption.sol

  2. 写入内容如下:

    pragma solidity ^0.5.16;
    
    import "truffle/Assert.sol";   // 引入的断言
    import "truffle/DeployedAddresses.sol";  // 用来获取被测试合约的地址
    import "../contracts/Adoption.sol";      // 被测试合约
    
    contract TestAdoption {
      Adoption adoption = Adoption(DeployedAddresses.Adoption());
    
      // 领养测试用例
      function testUserCanAdoptPet() public {
        uint returnedId = adoption.adopt(8);
    
        uint expected = 8;
        Assert.equal(returnedId, expected, "Adoption of pet ID 8 should be recorded.");
      }
    
      // 宠物所有者测试用例
      function testGetAdopterAddressByPetId() public {
        // 期望领养者的地址就是本合约地址,因为交易是由测试合约发起交易,
        address expected = this;
        address adopter = adoption.adopters(8);
        Assert.equal(adopter, expected, "Owner of pet ID 8 should be recorded.");
      }
    
        // 测试所有领养者
      function testGetAdopterAddressByPetIdInArray() public {
      // 领养者的地址就是本合约地址
        address expected = this;
        address[16] memory adopters = adoption.getAdopters();
        Assert.equal(adopters[8], expected, "Owner of pet ID 8 should be recorded.");
      }
    }
    
  3. 测试结果如下:

    $ truffle test
    Using network 'development'.
    
    
    Compiling your contracts...
    ===========================
    > Compiling .\contracts\Adoption.sol
    > Compiling .\contracts\Migrations.sol
    > Compiling .\test\TestAdoption.sol
    > Artifacts written to C:\Users\12173\AppData\Local\Temp\test-2020126-25536-1azqqoo.mstk
    > Compiled successfully using:
       - solc: 0.5.16+commit.9c3226ce.Emscripten.clang
    
    
    
      TestAdoption
        1) "before all" hook: prepare suite
    
    
      0 passing (320ms)
      1 failing
    
      1) TestAdoption
           "before all" hook: prepare suite:
         TypeError: Error parsing E:/Dapp/guide-pet-shop/contracts/Adoption.sol: Cannot destructure property `body` of 'undefined' or 'null'.
          at getImports (C:\Users\12173\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\compile-solidity\profiler\getImports.js:5:1)
          at C:\Users\12173\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\compile-solidity\profiler\index.js:145:1
    
    

    Cannot destructure property body of ‘undefined’ or 'null’

    暂无解决方案。无法进行智能合约测试,但不影响正常使用。

4.5创建用户界面以与智能合约进行交互

现在我们已经创建了智能合约,并将其部署到本地测试区块链中,并确认我们可以通过控制台与之交互,是时候创建一个UI,以便Pete可以在他的宠物店中使用它了!

pet-shoptruffle盒中包含该应用程序前端的代码。该代码存在于src/目录中。

4.5.1实例化web3

  1. /src/js/app.js在文本编辑器中打开。
  2. 检查文件。请注意,存在一个全局App对象来管理我们的应用程序,将数据加载到其中init(),然后调用函数initWeb3()。该WEB3 JavaScript库交互与复仇blockchain。它可以检索用户帐户,发送交易,与智能合约进行交互等等。
  3. 从内部删除多行注释,initWeb3并将其替换为以下内容:
if (window.ethereum) {
  App.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) {
  App.web3Provider = window.web3.currentProvider;
}
// If no injected web3 instance is detected, fall back to Ganache
else {
  App.web3Provider = new Web3.providers.HttpProvider('http://localhost:7545');
}
web3 = new Web3(App.web3Provider);

注意事项:

  • 首先,我们检查,如果我们使用现代DAPP浏览器或更近的版本MetaMask其中一个ethereum供应商被注入window对象。如果是这样,我们将使用它来创建我们的web3对象,但是我们还需要通过显式请求访问帐户ethereum.enable()
  • 如果ethereum对象不存在,则检查注入的web3实例。如果存在,则表明我们使用的是较旧的dapp浏览器(如Mist或较旧的MetaMask版本)。如果是这样,我们将获得其提供程序并使用它来创建我们的web3对象。
  • 如果不存在注入的web3实例,我们将基于本地提供程序创建web3对象。(这种后备方式适用于开发环境,但不安全且不适合生产。)

4.5.2实例化合同

现在我们可以通过web3与以太坊进行交互,我们需要实例化我们的智能合约,以便web3知道在哪里可以找到它以及它是如何工作的。truffle有一个名为的库来帮助您解决此问题truffle-contract。它使有关合同的信息与迁移保持同步,因此您无需手动更改合同的部署地址。

  1. 仍在中/src/js/app.js,从内部删除多行注释,initContract并将其替换为以下内容:

    $.getJSON('Adoption.json', function(data) {
      // Get the necessary contract artifact file and instantiate it with truffle-contract
      var AdoptionArtifact = data;
      App.contracts.Adoption = TruffleContract(AdoptionArtifact);
    
      // Set the provider for our contract
      App.contracts.Adoption.setProvider(App.web3Provider);
    
      // Use our contract to retrieve and mark the adopted pets
      return App.markAdopted();
    });
    

注意事项:

  • 我们首先检索智能合约的工件文件。工件是有关我们合同的信息,例如其部署地址和应用程序二进制接口(ABI)ABI是一个JavaScript对象,定义了如何与合同进行交互,包括其变量,函数及其参数。
  • 回调中包含工件后,便将它们传递给TruffleContract()。这将创建一个我们可以与之交互的合同实例。
  • 实例化合同后,我们使用App.web3Provider设置web3时存储的值来设置其web3提供程序。
  • 然后markAdopted(),如果以前访问过任何宠物,我们都会调用该应用程序的功能。我们将其封装在一个单独的函数中,因为每次更改智能合约的数据时都需要更新UI。

4.5.3获取被收养的宠物并更新UI

  1. 仍在中/src/js/app.js,从中删除多行注释,markAdopted并将其替换为以下内容:

    var adoptionInstance;
    
    App.contracts.Adoption.deployed().then(function(instance) {
      adoptionInstance = instance;
    
      return adoptionInstance.getAdopters.call();
    }).then(function(adopters) {
      for (i = 0; i < adopters.length; i++) {
        if (adopters[i] !== '0x0000000000000000000000000000000000000000') {
          $('.panel-pet').eq(i).find('button').text('Success').attr('disabled', true);
        }
      }
    }).catch(function(err) {
      console.log(err.message);
    });
    

注意事项:

  • 我们访问已部署的Adoption合同,然后调用getAdopters()该实例。
  • 我们首先adoptionInstance在智能合约调用之外声明变量,以便在最初检索实例后可以访问该实例。
  • 使用**call()**允许我们从区块链读取数据,而不必发送完整的交易,这意味着我们不必花费任何以太币。
  • 致电后getAdopters(),我们将遍历所有这些对象,检查是否为每个宠物存储了地址。由于数组包含地址类型,因此以太坊使用16个空地址初始化数组。这就是为什么我们检查一个空的地址字符串而不是null或其他虚假值的原因。
  • 一旦petId找到具有相应地址的,我们将禁用其采用按钮,并将按钮文本更改为“成功”,以便用户获得一些反馈。
  • 任何错误都会记录到控制台。

4.5.4处理take()函数

  1. 仍在中/src/js/app.js,从中删除多行注释,handleAdopt并将其替换为以下内容:

    var adoptionInstance;
    
    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }
    
      var account = accounts[0];
    
      App.contracts.Adoption.deployed().then(function(instance) {
        adoptionInstance = instance;
    
        // Execute adopt as a transaction by sending account
        return adoptionInstance.adopt(petId, {from: account});
      }).then(function(result) {
        return App.markAdopted();
      }).catch(function(err) {
        console.log(err.message);
      });
    });
    

注意事项:

  • 我们使用web3获取用户的帐户。在错误检查后的回调中,我们选择第一个帐户。
  • 从那里,我们像上面一样获得已部署的合同,并将实例存储在中adoptionInstance。不过这次,我们将发送交易而不是致电。交易需要一个“发件人”地址,并具有相关的成本。这种以醚支付的费用称为煤气。气体成本是在智能合约中执行计算和/或存储数据的费用。我们通过adopt()同时使用宠物ID和包含帐户地址的对象执行该函数来发送交易,该地址先前存储在中account
  • 发送交易的结果是交易对象。如果没有错误,我们将继续调用markAdopted()函数以将UI与新存储的数据同步。

4.5.5dapp与浏览器中的交互

  • 安装和配置MetaMask

  • 安装和配置Lite服务器

    现在,我们可以启动本地Web服务器并使用dapp。我们正在使用该lite-server库来提供我们的静态文件。这是pet-shop松露盒随附的,但让我们看一下它是如何工作的。

    1. bs-config.json在文本编辑器(在项目的根目录中)中打开并检查内容:

      {
        "server": {
          "baseDir": ["./src", "./build/contracts"]
        }
      }
      

      这告诉lite-server哪些文件要包含在我们的基本目录中。我们./src为网站文件添加目录,./build/contracts为合同工件添加目录。

      我们还向项目根目录中文件中的对象添加了dev命令。该对象允许我们将控制台命令别名为单个npm命令。在这种情况下,我们仅执行单个命令,但是可能具有更复杂的配置。这是您的样子:scripts``package.json``scripts

      "scripts": {
        "dev": "lite-server",
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      

      这告诉npm 从控制台lite-server执行时运行本地安装npm run dev

4.6使用dapp

  1. 启动本地Web服务器:

    npm run dev
    

    开发服务器将启动并自动打开一个包含您的dapp的新浏览器选项卡。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ubvvmUOt-1583398995106)(https://www.trufflesuite.com/img/tutorials/pet-shop/dapp.png)]

    皮特的宠物店

  2. 应该会出现一个MetaMask弹出窗口,要求您批准,以允许Pete的Pet Shop连接到您的MetaMask钱包。未经明确批准,您将无法与dapp进行交互。单击连接

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hGmJ9Asr-1583398995107)(https://www.trufflesuite.com/img/tutorials/pet-shop/metamask-transactionconfirm.png)]

    MetaMask批准请求

  3. 要使用dapp,请在您选择的宠物上单击“ **采用”**按钮。

  4. MetaMask将自动提示您批准交易。单击提交以批准交易。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mzfUvJf2-1583398995109)(https://www.trufflesuite.com/img/tutorials/pet-shop/metamask-transactionconfirm.png)]

    收养交易审查

  5. 正如我们指定的那样,您将看到已收养宠物旁边的按钮更改为“成功”并被禁用,因为该宠物现已被收养。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pXylsdmP-1583398995110)(https://www.trufflesuite.com/img/tutorials/pet-shop/dapp-success.png)]

    收养成功

你可能感兴趣的:(以太坊环境搭建)