以太坊智能合约开发(truffle box pet-shop为例)

开发环境

    我在ubuntu环境下开发的,建议装好vscode,nodejs 。选用别的编译器也可以。

    装好nodejs后装一下truffle。

    

npm install -g truffle
truffle version

    可以看到版本号,说明安装成功。

开发语言

    本文选用solidity,现在以太坊智能合约开发主流语言,不过比较新东西,和c++ java python这些成熟语言相比用起来没那么方便。想学的话推荐一个网站,加密僵尸,通过做一个游戏来引导solidity入门。如果英语好的话可以看看官方文档:solidity官方文档。这个文档也有中文版,但是更新慢一点solidity文档中文版。

  另外还用了nodejs,不过我不太熟悉js……有点尴尬。

编译测试

    新建一个空文件夹,比如叫pet-shop。然后进入文件夹   

truffle unbox pet-shop

  解释一下,trufflebox 给大家提供一些模板,这里可以看到。当然也可以自己新建一个空的工程,我会在另一篇博客做讲解。这个unbox时间比较长,结束后大概这个样子:

    看一下工程目录:

以太坊智能合约开发(truffle box pet-shop为例)_第1张图片

contracts:智能合约文件夹

migrations:用于部署的脚本

node_modules:nodejs

src:前端资源

test:单元测试

bs-config.json:lite-server的配置文件

package.json:nodejs依赖

truffle.js:不用解释

代码编写与发布

contract下新建Adoption.sol:

pragma solidity ^0.4.16;
import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/Adoption.sol";
contract TestAdoption {
	Adoption adoption = Adoption(DeployedAddresses.Adoption());   
	function testUserCanAdoptPet() {      
		uint returnedId = adoption.adopt(8);       
		uint expected = 8;
		Assert.equal(returnedId, expected, "Adoption of pet ID 8 should be recorded.");
    }   
	function testGetAdopterAddressByPetIdInArray() {       
		address expected = this;
		address[16] memory adopters = adoption.getAdopters();
		Assert.equal(adopters[8], expected, "Owner of pet ID 8 should be recorded.");
    }
}

如果你用的是vscode,那么有时候会出现一些奇怪的错误提示,比如什么换行空格,solidity版本之类的,可以忽略不计,没有python那么严格。比如下图这样的:

migrations下新建2_deploy_contracts.js

var Adoption = artifacts.require("Adoption");
	module.exports = function(deployer) {
	deployer.deploy(Adoption);
};

终端输入truffle develop 进入truffle 控制台.

以太坊智能合约开发(truffle box pet-shop为例)_第2张图片

在truffle控制台输入compile进行编译:

以太坊智能合约开发(truffle box pet-shop为例)_第3张图片

输入migration进行发布。

以太坊智能合约开发(truffle box pet-shop为例)_第4张图片

测试

单元测试还是必要的,当然你要有把握没bug不测也没事。

test下新建TestAdoption.sol.

pragma solidity ^0.4.16;
import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/Adoption.sol";
contract TestAdoption {
	Adoption adoption = Adoption(DeployedAddresses.Adoption());   
	function testUserCanAdoptPet() {      
		uint returnedId = adoption.adopt(8);       
		uint expected = 8;
		Assert.equal(returnedId, expected, "Adoption of pet ID 8 should be recorded.");
    }   
	function testGetAdopterAddressByPetIdInArray() {       
		address expected = this;
		address[16] memory adopters = adoption.getAdopters();
		Assert.equal(adopters[8], expected, "Owner of pet ID 8 should be recorded.");
    }
}

回到truffle控制台,输入test指令进行测试。

以太坊智能合约开发(truffle box pet-shop为例)_第5张图片

前端交互

工程已经帮我们写好了html并定义好了一些js函数,完成剩下部分即可.

打开js/app.js文件。看到有如下函数:

init:读取json并初始化页面,这也是唯一一个已经写好的函数

接下来的函数要自己添加daima

initweb3:初始化web3(web3.js是用来与以太坊智能合约交互的)

 
 initWeb3: function() {
    // Is there is an injected web3 instance?
    if (typeof web3 !== 'undefined') {
      App.web3Provider = web3.currentProvider;
    } else {
      // If no injected web3 instance is detected, fallback to the TestRPC
      App.web3Provider = new Web3.providers.HttpProvider('http://localhost:8545');
    }
    web3 = new Web3(App.web3Provider);
    return App.initContract();
  },

 

 

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:绑定点击事件

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

markAdoption:根据领养情况更新UI

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

handleAdoption:处理领养事件

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

这些代码比较简单没啥可说的吧……

关于html页面,引用的jquery是在线的,可能也需要梯子,因此我替换成了:

metamask与实际运行

为了在浏览器运行dapp需要一个叫metamask的插件。地址:https://metamask.io/.我用的chrome浏览器。可能需要梯子,不过我已经放到github 上了,见文章末尾。

可以看到右上角有个小狐狸头像,点开,假装阅读并接受协议。

以太坊智能合约开发(truffle box pet-shop为例)_第6张图片

不要create,先import existing den.第一个框框输入助记词:candy maple cake sugar pudding cream honey rich smooth crumble sweet treat.然后再输入密码和确认密码.确认,看到界面如下:

以太坊智能合约开发(truffle box pet-shop为例)_第7张图片

显然最好不要用公网测试,除非你是V神。所以自己搞一个,点击custom RPC

以太坊智能合约开发(truffle box pet-shop为例)_第8张图片

在main ethereum network 输入http://localhost:9545. 保存.

以太坊智能合约开发(truffle box pet-shop为例)_第9张图片

点击setting左侧箭头,回到主页。

回到linux终端,不是truffle终端,进入工程目录下输入npm run dev启动项目.

以太坊智能合约开发(truffle box pet-shop为例)_第10张图片

以太坊智能合约开发(truffle box pet-shop为例)_第11张图片

以太坊智能合约开发(truffle box pet-shop为例)_第12张图片

上github

 

 

你可能感兴趣的:(区块链)