注意: 这里使用的truffle版本为4.1.4,貌似使用高版本在truffle test时候会出问题,提示

truffle/Assert.sol is not found等错误

使用Truffle Box创建Truffle项目

$ mkdir petshop
$ cd petshop
$ truffle unbox pet-shop

项目目录结构

$ ls
box-img-lg.png contracts/ node_modules/ src/
box-img-sm.png LICENSE package.json test/
bs-config.json migrations/ package-lock.json truffle.js

项目

$ touch 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;
} // Retrieving the adopters
function getAdopters() public view returns(address[16]) {
return adopters;
} }

Migrations.sol代码如下:

pragma solidity ^0.4.17;

contract Migrations {
address public owner;
uint public last_completed_migration; modifier restricted() {
if (msg.sender == owner) _;
} function Migrations() public {
owner = msg.sender;
} function setCompleted(uint completed) public restricted {
last_completed_migration = completed;
} function upgrade(address new_address) public restricted {
Migrations upgraded = Migrations(new_address);
upgraded.setCompleted(last_completed_migration);
}
}

编译

solidity代码编译成以太坊虚拟机(Ethereum Virtual Machine,简称EVM)可以执行的字节码。

$ truffle compile
Compiling .\contracts\Adoption.sol...
Compiling .\contracts\Migrations.sol...
Writing artifacts to .\build\contracts

运行ganache

Quickly fire up a personal Ethereum blockchain which you can use to run tests, execute commands, and inspect state while controlling how the chain operates.

Migration(迁移)

A migration is a deployment script meant to alter the state of your application's contracts, moving it from one state to the next.

$ touch migrations/2_deploy_contracts.js

内容如下:

var Adoption = artifacts.require("./Adoption.sol");

module.exports = function (deployer) {
deployer.deploy(Adoption);
}
$ truffle migrate
Using network 'development'. Running migration: 1_initial_migration.js
Deploying Migrations...
... 0x69df0a2b452808f94386709c3c22f6c10607ff7473d92558eb75c743cbae0e1c
Migrations: 0x658dfbe4e9a30de42b8c48373eca4d05d6a0fe52
Saving successful migration to network...
... 0xa7fd9f435d8d942bd3e83ab8fef01ed8f7d1d161803364a9193a526e681cb7c4
Saving artifacts...
Running migration: 2_deploy_contracts.js
Deploying Adoption...
... 0x340f8e750a19a0178f54b328e59802231dd001c11ddb999776f900113e570dba
Adoption: 0xa739c709b5c06110fb15433f9f65832f5188fe43
Saving successful migration to network...
... 0x6c9b3b180ea294d968d7e607bd78c53872e08a688b01aca629e5bb6e73440c8e
Saving artifacts...

编写测试代码

$ touch test/TestAdoption.sol

内容如下:

pragma solidity ^0.4.17;

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 {
// Expected owner is this contract
address expected = this; address adopter = adoption.adopters(8); Assert.equal(adopter, expected, "Owner of pet Id 8 should be recored.");
} // Testing retrieval of all pet owners
function testGetAdopterAddressByPetIdInArray() public {
// Expected owner is this contract
address expected = this; // store adopters in memory rather than contract's storage
address[16] memory adopters = adoption.getAdopters(); Assert.equal(adopters[8], expected, "Owner of pet ID 8 should be recorded.");
}
}

测试

$ truffle test

效果:

 TestAdoption
√ testUserCanAdoptPet (83ms)
√ testGetAdopterAddressByPetId (87ms)
√ testGetAdopterAddressByPetIdInArray (107ms) 3 passing (1s)

虽然vscode依然有错误提示,但是能够测试通过

创建和智能合约交互的用户接口

1) 实例化web3对象

打开项目目录src/js/app.js

修改initWeb3,使用下面内容替换带多行注释:

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

2) 实例化合约

修改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();
});

3) 获取已收养的宠物并更新UI

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

4) 处理adopt()函数

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

5) 安装配置metamask插件,创建并切换网络为localhost:7545

6) 启动服务

$ npm run dev

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

效果:

出现的问题

1 > 执行truffle test的时候出现如下错误: truffle/Assert.sol is not found

$ npm view truffle versions
$ npm uninstall -g truffle
$ npm install -g truffle@4.1.4

删除build目录

然后重新执行命令即可。

$ truffle compile
$ truffle test

参考:

DApp demo之pet-shop的更多相关文章

  1. Microsoft .NET Pet Shop 4

    Microsoft .NET Pet Shop 4:将 ASP.NET 1.1 应用程序迁移到 2.0 299(共 313)对本文的评价是有帮助 - 评价此主题 发布日期 : 2006-5-9 | 更 ...

  2. asp.net的3个经典范例(ASP.NET Starter Kit ,Duwamish,NET Pet Shop)学习资料

    asp.net的3个经典范例(ASP.NET Starter Kit ,Duwamish,NET Pet Shop)学习资料 NET Pet Shop .NET Pet Shop是一个电子商务的实例, ...

  3. Microsoft .NET Pet Shop 简介

    最初研究 .NET Pet Shop 的目的是用 Microsoft .NET 实现 Sun 主要的 J2EE 蓝图应用程序 Sun Java Pet Store 同样的应用程序功能. 根据用 .NE ...

  4. Microsoft .NET Pet Shop 4: Migrating an ASP.NET 1.1 Application to 2.0

    249 out of 297 rated this helpful - Rate this topic Gregory Leake Microsoft Corporation Alan Le, Ale ...

  5. Bytom Dapp 开发笔记(三):Dapp Demo前端源码分析

    本章内容会针对比原官方提供的dapp-demo,分析里面的前端源码,分析清楚整个demo的流程,然后针对里面开发过程遇到的坑,添加一下个人的见解还有解决的方案. 储蓄分红合约简述 为了方便理解,这里简 ...

  6. ethereum Pet Shop

    在部署宠物商店时遇到的一些坑,给大家总结一下,以免大家多走弯路 转载的地址(详细):https://steemit.com/cn/@lucia3/ethereum-pet-shop 启动"n ...

  7. Microsoft-PetSop4.0(宠物商店)-数据库设计-Sql

    ylbtech-DatabaseDesgin:Microsoft-PetSop4.0(宠物商店)-数据库设计-Sql DatabaseName:PetShop(宠物商店) Model:宠物商店网站 T ...

  8. 以太仿DApp开发环境搭建

    在网上找了些以太仿的资料,是node.js写的,之前也了解过node.js,正好也可以用上.本篇主要学习以太仿DApp开发环境搭建. 一.安装 DApp 开发环境 1.1安装 Node.js 首先下载 ...

  9. 调用Bytom Chrome插件钱包开发Dapp

    安装使用插件钱包 1. 打开Google浏览器的应用商店,搜索Bystore 下载链接:http://t.cn/E6cFFwb 2. 然后点击添加到Chrome,就可以添加到我们的: 3. 使用goo ...

随机推荐

  1. WPF popup自动关闭

    var tileMore = new Tile { Height = , Width = , Background = , , )), Title = "更多...", }; ti ...

  2. 使用lua读文件并输出到stdin

    io.input("c:\\AudioCom.log") t= io.read("*all") io.write(t) 三行代码搞定,简洁的不像话 io.rea ...

  3. select 使其默认选中文本不为空

    ```html<select ref="type" v-model="selectedvalue" > <option v-for=" ...

  4. WEB学习笔记13-高可读性的HTML之精简HTML代码/过时的块状元素和行内元素

    <a id="more-intro">点击此处 <img src="down-arrow.png" /></a> (1)删除 ...

  5. cobbler批量化安装系统

  6. 2018 ,请领取您Power BI 年终报告

    Power BI365 3Jan 2019 新年已至,岁寒温暖! 为方便Power BI用户们能快速找到所需要的Power BI各类型文章,小悦将2018年Power BI的所有精彩文章按照各应用场景 ...

  7. 移动端调用ArcGIS Server 10.1服务

    1.最好用mdb数据源,不要用shp文件作为数据源,一是属性字段长度超过5个字符会被截断,二是中文会变成乱码. 2.mxd的layer的坐标系要是WGS1984(4362),不然属性查询不出来.

  8. oracle追加表空间

    ----查询表空间使用情况--- SELECT UPPER(F.TABLESPACE_NAME) "表空间名", D.TOT_GROOTTE_MB "表空间大小(M)&q ...

  9. Java中switch对整型/字符型/字符串型具体实现细节

    转自:http://www.hollischuang.com/archives/61 Java7中switch中支持的数据类型有: byte short int char String类型 其实swi ...

  10. 软件测试第四次作业—— 性能测试(含JMeter实验)

                                           性能测试(含JMeter实验) 一.概览 1.性能测试有几种类型,它们之间什么关系? 2.搭建并简单配置一个JMeter的 ...