注意: 这里使用的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. OGNL表达式的一个坑!

    我在写Spring整合JDBC框架的时候用了properties文件去设置JDBC的参数.但是发现了一个问题先付上代码 properties文件的代码 db.driverClass=com.mysql ...

  2. python学习第一次笔记

    python第一次学习记录 python是什么编程语言 变成语言主要从以下几个角度进行分类,编译型和解释型.静态语言和动态语言.强类型定义语言和弱类型定义语言. 1.1编译型与解释性 编译型:一次性将 ...

  3. CornerStone使用跳坑总结(陆续更新)

    Cornerstone是专门为Mac用户设计的Subversion(SVN)的控制,使版本控制更加透明.cornerstone根Xcode相比,能够更好的忽略文件,所以除了项目经理第一次初始化项目的时 ...

  4. linux ps 按进程消耗内存资源大小排序

    linux ps 关于sort的解释 --sort spec specify sorting order. Sorting syntax is [+|-]key[,[+|-]key[,...]] Ch ...

  5. MVCC(Multi-version Cocurrent Control)多版本并发控制协议

    MVCC相比2PC是一种更简单有效的分布式事务解决方案. 假设一种场景,一个分布式事务在A,B两个节点更新数据,要么同时成功,要么同时失败. MVCC 中,为每个事务分配一个递增的事务编号,有一个中心 ...

  6. [LeetCode&Python] Problem 704. Binary Search

    Given a sorted (in ascending order) integer array nums of n elements and a target value, write a fun ...

  7. Restful下的token认证方案

    Restful讲究一个无状态的特性(stateless),这就不能把一些例如登陆后的认证信息写进cookie的传统方式, 目前探索的是采用token的方式来进行权限的识别. 刚开始研究token的时候 ...

  8. MATLAB实现Brovey图像融合

    自定义函数: function BF=Brovey_fuse(Hyperspectral_image,High_resolution_image) x0=imread(Hyperspectral_im ...

  9. 支持pc和移动端的手写签批功能

    由于之前的业务需要,要求在pc端(用鼠标写字).移动端(手写)实现会签功能,然后百度下载了个签字插件,经过一些修改和功能添加,实现了现有的功能插件,效果如图: 代码下载地址:https://githu ...

  10. JS如何充分“压榨”浏览器

    不同浏览器厂商实现的 JS 标准有所不同,这意味着 window 对象和可用的 api 也有所不同,希望不久的将来,所有浏览器都能实现统一的 JS 标准. 自己写 api 是很耗费时间跟精力的,而且变 ...