zoukankan      html  css  js  c++  java
  • truffle init 从零开始创建简单DApp项目

    下面的部分软件需要翻墙。这里默认你已经会科学上网,不懂的可以自己搜索解决。

    软件安装

    chrome浏览器

    下载地址

    metamask插件

    谷歌应用商店中搜索metamask

    ganche(图形版)

    下载地址

    nodejs和npm

    下载地址
    安装完成需要将node.exe所在路径加入环境变量PATH中
    并且需要保证在cmd中可以使用nodenpm命令,简单测试:

    $ 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默认选择(直接敲回车)就好了,效果如下:

    $ 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 
    

    安装比较耗时, 需要耐心等待安装完成
    完成后效果:

    $ 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
    如下:

    $ 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 {
         50%;
        margin: 0 auto;
    }
    label {
        display:block;
        margin-bottom:10px;
    }
    input {
        padding:10px;
         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代码如下:

    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.

    如果直接使用浏览器打开index.html会出现跨域访问,如下图:

    遇到的问题:

    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);
                    }
                });
    

    参考:

  • 相关阅读:
    移动web开发视口viewport
    五层网络模型
    移动web开发理解设备像素、CSS像素、DPR
    git rebase简单使用
    position:fixed; IE6下解决办法。。
    (经典收藏)三十款最常用css选择器解析
    js控制搜索内容为空则搜索按钮不能用
    SAPBOE Universe 设计方法
    【转帖】开源BI系统分类
    【转贴】SQL2005 四个排名函数(row_number、rank、dense_rank和ntile)的比较
  • 原文地址:https://www.cnblogs.com/hupeng1234/p/9856696.html
Copyright © 2011-2022 走看看