• 以太坊开发教程(二) 利用truffle发布宠物商店 DAPP 到 以太坊测试环境Ropsten


     1.环境安装  

     1) node安装

    设置镜像地址:  curl --silent --location https://rpm.nodesource.com/setup_8.x | bash -
    下载安装
    yum -y install nodejs
    node -v 查看版本:

    2)安装truffle  

    $npm install -g truffle

    3)安装python

    npm install python

    2.创建truffle项目

    我的项目安装在 /usr/local下、

    所以分别执行下面三个命令:  1)cd /usr/local

         2)mkdir pet_test  //创建项目文件地址

               3) truffle 帮我们打包了一些常用的经典示例,放在box中, 这个是我们用到的pet_shop的地址:https://truffleframework.com/boxes/pet-shop

        执行: truffle unbox pet-shop

    这个命令会自动帮我们初始化 truffle init,然后创建前端的文件夹。

    介绍一下truffle的文件架构:

    • contracts/ : 智能合约文件存在这里,后缀.sol (solidity)

    • migrations/ : 部署脚本

    • test/ : 测试脚本

    • truffle.js :truffle的配置文件

    编写智能合约:

    在 contracts/ 目录下创建 Adoption.sol 文件,内容如下:

    pragma solidity ^0.4.17;

    contract Adoption {
       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;
       }

       //retrieve the adopters
       function getAdopters() public view returns (address[16]) {
         return adopters;
       }
    }

    编写前端:

    用户界面(UI)是前端工作,这里用的javascript。主要文件是app.js,存在目录 /src/js/app.js 中。文件内容如下:

    App = {
     web3Provider: null,
     contracts: {},

     init: function() {
       // Load pets.
       $.getJSON('../pets.json', function(data) {
         var petsRow = $('#petsRow');
         var petTemplate = $('#petTemplate');

         for (i = 0; i < data.length; i ++) {
           petTemplate.find('.panel-title').text(data[i].name);
           petTemplate.find('img').attr('src', data[i].picture);
           petTemplate.find('.pet-breed').text(data[i].breed);
           petTemplate.find('.pet-age').text(data[i].age);
           petTemplate.find('.pet-location').text(data[i].location);
           petTemplate.find('.btn-adopt').attr('data-id', data[i].id);

           petsRow.append(petTemplate.html());
         }
       });

       return App.initWeb3();
     },

     initWeb3: function() {
       // Is there an injected web3 instance?
    if (typeof web3 !== 'undefined') {
     App.web3Provider = web3.currentProvider;
    } else {
     // If no injected web3 instance is detected, fall back to Ganache
     App.web3Provider = new Web3.providers.HttpProvider('http://localhost:7545');
    }
    web3 = new Web3(App.web3Provider);

       return App.initContract();
     },

     initContract: function() {
       $.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();
    });

       return App.bindEvents();
     },

     bindEvents: function() {
       $(document).on('click', '.btn-adopt', App.handleAdopt);
     },

     markAdopted: function(adopters, account) {
       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);
    });
     },

     handleAdopt: function(event) {
       event.preventDefault();

       var petId = parseInt($(event.target).data('id'));

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

    };

    $(function() {
     $(window).load(function() {
       App.init();
     });
    });

    到这里 整个项目的前端和合约部分都完成了。下面讲述如何编译部署合约和如何启动前端应用。

    因为部署是要把合约部署到ropsten的测试网络上,所以要提前配置好。部署就需要消耗gas,那么就需要指定账号。打开truffle的配置文件 truffle.js。修改内容为:

    var HDWalletProvider = require("truffle-hdwallet-provider");
    var mnemonic = "bomb when antenna suggest submit kitten thumb lazy silent uncover ten seek";
    module.exports = {
    networks: {
    ropsten: {
    provider: function() {
    return new HDWalletProvider(mnemonic, "https://ropsten.infura.io/b59397a69a0f4639b4c70e9786a9db1f")
    },
    network_id: 3
    }
    }
    };

    详细解释一下 HDWalletProvider,mnemonic , https://ropsten.infura.io/b59397a69a0f4639b4c70e9786a9db1f。

    HDWalletProvider 需要提前安装: 

    npm install truffle-hdwallet-provider 

    我在执行过程中报错:

     因为我是centOs系统,执行安装gcc:

    yum -y update gcc
    yum -y install gcc+ gcc-c++

     mnemonic 是你账号的助记词,是通过metaMask获取的:

     

    显示的Your private seed phrase就是你的助记词。替换到这个变量中。

     https://ropsten.infura.io/b59397a69a0f4639b4c70e9786a9db1f中,b59397a69a0f4639b4c70e9786a9db1f是你在infura的秘钥。

    Infura是一个托管的以太坊节点集群,可以将你开发的以太坊智能合约部署到infura提供的节点上,而无需搭建自己的以太坊节点。到这个地址注册:https://infura.io/ 在dashborad里找到自己的秘钥拷贝过来。


    编译部署合约

    1.首先执行 truffle compile 

    这里是编译合约 把合约编译成对应的ABI  二进制文件。

    2. 下面要部署合约,教程的目的是把合约部署到 ropsten的测试网络上。结合truffle.js中的配置,读者可以更好的理解部署命令:

     truffle migrate --network ropsten

    到这里你的合约就成功部署完成了。

    因为pet_shop是一个打包好的文件,所以只需要执行 npm run dev 就可以启动。默认的端口是3000,这个是lite sever 默认的端口。

    启动好以后就可以通过地址访问了。注意我上面External 后面的IP是阿里云的内网ip,需要替换成外面的ip访问:http://120.55.51.210:3000/

    然后可以通过钱包提交对合约的方法调用请求。

     至此,一个部署在Ropsten测试完的DAPP就部署完成了。

  • 相关阅读:
    第一次博客园作业
    弹性布局/流动式布局
    元素在网页或视口上位置的相关问题求解
    element
    给body设置高度
    盒模型宽高的获取和设置
    选择器
    变量、作用域和内存问题
    js之捕捉冒泡和事件委托
    transition transform animate的使用
  • 原文地址:https://www.cnblogs.com/gzhlt/p/9969794.html
Copyright © 2020-2023  润新知