注意: 这里使用的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. Android作业

    一.设置跑马灯功能   使用滚动字幕显示标题“请选择你喜欢哪种花” <?xml version="1.0" encoding="utf-8"?>&l ...

  2. dos3章

    FOR命令中有一些变量,他们的用法许多新手朋友还不太了解,今天给大家讲解他们的用法! 先把FOR的变量全部列出来: ~I          - 删除任何引号("),扩展 %I     %~f ...

  3. A The Empire Age

    1月28日 Description 帝国时代3是一款十分刺激的RTS游戏.你需要控制自己的一块殖民地,发展殖民地的经济和军事,最终打败其他殖民地.小L是这个游戏的狂热爱好者.一次小L打算打AI试试身手 ...

  4. 两种语言实现设计模式(C++和Java)(二:单例模式)

    本篇介绍单例模式,可以说是使用场景最频繁的设计模式了.可以根据实例的生成时间,分为饿汉模式和懒汉模式 懒汉模式:饿了肯定要饥不择食.所以在单例类定义的时候就进行实例化. 饿汉模式:故名思义,不到万不得 ...

  5. wordpress 暴力破解防范

    一.author页面地址 author页面地址为 http://yoursite/?author=1 ID是自增的 请求这个地址会 301 到一个url,这个url里包含了作者的用户名.虽然不算漏洞, ...

  6. Linux 安装aria2

    Ubuntu/Linux Mint/Debian sudo apt-get install aria2 CentOS/Fedora sudo yum install aria2 Manjaro/Arc ...

  7. Codeforces Hello 2018 E题Logical Expression dp+最短路 好题

    j题目链接: http://codeforces.com/contest/913/problem/E 题意: 给你x,y,z三个变量,与&   或|  非!  括号()   四种运算符,规定括 ...

  8. Unity UGUI Layout自动排版组件用法介绍

    Unity UGUI布局组件 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分享 ...

  9. Java基于opencv实现图像数字识别(二)—基本流程

    Java基于opencv实现图像数字识别(二)-基本流程 做一个项目之前呢,我们应该有一个总体把握,或者是进度条:来一步步的督促着我们来完成这个项目,在我们正式开始前呢,我们先讨论下流程. 我做的主要 ...

  10. NABCD(团队项目)

    N (Need 需求) 随着时代的进步和手机迅速发展,各种软件充斥这我们的生活,在学校里,我们总为一些各种各样的群所困扰,我们需要一件工具整合信息,让我们的生活更加便利. A (Approach 做法 ...