truffle init 從零開始建立簡單DApp項目

下面的部分軟件須要FQ。這裏默認你已經會***,不懂的能夠本身搜索解決。

軟件安裝

chrome瀏覽器

下載地址css

metamask插件

谷歌應用商店中搜索metamaskhtml

ganche(圖形版)

下載地址node

nodejs和npm

下載地址
安裝完成須要將node.exe所在路徑加入環境變量PATH中
而且須要保證在cmd中能夠使用nodenpm命令,簡單測試:jquery

$ node -v
$ npm -v

開發環境配置

  1. 啓動ganache
  2. remix切換運行環境。點擊remix在線編輯器右側的run->Environment,選擇Injected Web3
  3. metamask鏈接ganache。打開chrome瀏覽器中的metamask插件,首先經過12個單詞短語恢復帳號。而後經過"Custom RPC", 輸入http://localhost:7545,保存並將換網絡切換至http://localhost:7545,鏈接成功後顯示主帳戶信息''

配置截圖

Demo項目

$ mkdir demo
$ cd demo
$ npm init

後面所有enter默認選擇(直接敲回車)就行了,效果以下:git

$ ls
package.json
$ cat package.json
{
  "name": "demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

$ npm install ethereum/web3.js --save

安裝比較耗時, 須要耐心等待安裝完成
完成後效果:github

$ ls
node_modules/  package.json  package-lock.json

$ ls node_modules/
bignumber.js/  crypto-js/  web3/          xmlhttprequest/
cookiejar/     utf8/       xhr2-cookies/

$ ls node_modules/web3/
bower.json  example/      lib/        package.json     styleguide.md
circle.yml  gulpfile.js*  LICENSE.md  package-init.js
dist/       index.js      package.js  README.md

# 發現配置已經發生了改變
$ cat package.json
{
  "name": "demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "web3": "github:ethereum/web3.js"
  }
}

完整項目結構

在項目根目錄下建立index.htmlmain.css
以下:web

$ ls demo
index.html  main.css  node_modules/  package.json  package-lock.json

index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>DApp Demo</title>
    <link rel="stylesheet" type="text/css" href="main.css">
    <script src="./node_modules/web3/dist/web3.min.js"></script>
    <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.js"></script>
</head>
<body>
<div class="container">
    <h1>Simple DApp Demo</h1>
    <h2 id="info"></h2>

    <label for="name" class="col-lg-2 control-label">Name</label>
    <input id="name" type="text">
    <label for="age" class="col-lg-2 control-label">Age</label>
    <input id="age" type="text">

    <button id="button">更新我的信息</button>
</div>
<script>
    window.addEventListener('load', function () {
        if (typeof web3 !== 'undefined') {
            web3 = new Web3(web3.currentProvider);
        } else {
            web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:7545"));
        }
        //web3.eth.defaultAccount = web3.eth.accounts[0];

        // replace with your abi code
        const abi = [
            {
                "constant": false,
                "inputs": [
                    {
                        "name": "_name",
                        "type": "string"
                    },
                    {
                        "name": "_age",
                        "type": "uint256"
                    }
                ],
                "name": "setPersonalInfo",
                "outputs": [],
                "payable": false,
                "stateMutability": "nonpayable",
                "type": "function"
            },
            {
                "constant": true,
                "inputs": [],
                "name": "getPersonalInfo",
                "outputs": [
                    {
                        "name": "",
                        "type": "string"
                    },
                    {
                        "name": "",
                        "type": "uint256"
                    }
                ],
                "payable": false,
                "stateMutability": "view",
                "type": "function"
            }
        ];


        // replace with your contract address
        const address = "0x0d4aed2bf6178c870355ce1100a11e8fafdbd15d";

        // create contract instance
        const PersonalInfo = web3.eth.contract(abi).at(address);
        console.log("PersonalInfoContract:", PersonalInfo);

        PersonalInfo.getPersonalInfo(function (error, result) {
            if (!error) {
                $("#info").html(result[0] + ' (' + result[1] + ' years old)');
                console.log("get PersonalInfo success: ", result);
            } else {
                console.error("failed to get PersonalInfo :", error);
            }
        });


        $("#button").click(function () {
            var name = $("#name").val();
            var age = $("#age").val();
            PersonalInfo.setPersonalInfo(name, age, function (error, result) {
                if (!error) {
                    // update label
                    $("#info").html(name + ' (' + age + ' years old)');
                    console.log("setPersonalInfo success: " + result);
                } else {
                    consoe.log("fail to setPersonalInfo: " + error);
                }
            });
        });
    });
</script>
</body>
</html>

main.css

body {
    background-color:#F0F0F0;
    padding: 2em;
    font-family: 'Raleway','Source Sans Pro', 'Arial';
}
.container {
    width: 50%;
    margin: 0 auto;
}
label {
    display:block;
    margin-bottom:10px;
}
input {
    padding:10px;
    width: 50%;
    margin-bottom: 1em;
}
button {
    margin: 2em 0;
    padding: 1em 4em;
    display:block;
}

#info {
    padding:1em;
    background-color:#fff;
    margin: 1em 0;
}

使用web3.js和智能合約進行交互

使用solidity在線編輯器remix
solidity代碼以下:chrome

pragma solidity ^0.4.16;

contract PersonalInfo {
   string name;
   uint age;
   function setPersonalInfo(string _name, uint _age) public {
       name =_name;
       age = _age;
   }
   function getPersonalInfo() public view returns(string, uint){
       return (name, age);
   }
}

使用metamask須知:

Due to browser security restrictions, we can't communicate with dapps running on file://. Please use a local server for development.npm

若是直接使用瀏覽器打開index.html會出現跨域訪問,以下圖:
json

遇到的問題:

The MetaMask Web3 object does not support synchronous methods like eth_sendTransaction without a callback parameter

官方解釋:

All Async - Think of MetaMask as a light client
The user does not have the full blockchain on their machine, so data lookups can be a little slow. For this reason, we are unable to support most synchronous methods. The exceptions to this are:

  • eth_accounts (web3.eth.accounts)
  • eth_coinbase (web3.eth.coinbase)
  • eth_uninstallFilter (web3.eth.uninstallFilter)
  • web3.eth.reset (uninstalls all filters).
  • net_version (web3.version.network).

解決方法:

在合約實例調用對應函數的時候,加上回調函數。形如:

PersonalInfoContract.setPersonalInfo(name, age, function (error, result) {
                if (!error) {
                    // update label
                    $("#info").html(name + ' (' + age + ' years old)');
                    console.log("setPersonalInfo success: " + result);
                } else {
                    consoe.log("fail to setPersonalInfo: " + error);
                }
            });

參考:

相關文章
相關標籤/搜索