DApp demo之pet-shop
注意: 这里使用的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的更多相关文章
- Microsoft .NET Pet Shop 4
Microsoft .NET Pet Shop 4:将 ASP.NET 1.1 应用程序迁移到 2.0 299(共 313)对本文的评价是有帮助 - 评价此主题 发布日期 : 2006-5-9 | 更 ...
- 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是一个电子商务的实例, ...
- Microsoft .NET Pet Shop 简介
最初研究 .NET Pet Shop 的目的是用 Microsoft .NET 实现 Sun 主要的 J2EE 蓝图应用程序 Sun Java Pet Store 同样的应用程序功能. 根据用 .NE ...
- 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 ...
- Bytom Dapp 开发笔记(三):Dapp Demo前端源码分析
本章内容会针对比原官方提供的dapp-demo,分析里面的前端源码,分析清楚整个demo的流程,然后针对里面开发过程遇到的坑,添加一下个人的见解还有解决的方案. 储蓄分红合约简述 为了方便理解,这里简 ...
- ethereum Pet Shop
在部署宠物商店时遇到的一些坑,给大家总结一下,以免大家多走弯路 转载的地址(详细):https://steemit.com/cn/@lucia3/ethereum-pet-shop 启动"n ...
- Microsoft-PetSop4.0(宠物商店)-数据库设计-Sql
ylbtech-DatabaseDesgin:Microsoft-PetSop4.0(宠物商店)-数据库设计-Sql DatabaseName:PetShop(宠物商店) Model:宠物商店网站 T ...
- 以太仿DApp开发环境搭建
在网上找了些以太仿的资料,是node.js写的,之前也了解过node.js,正好也可以用上.本篇主要学习以太仿DApp开发环境搭建. 一.安装 DApp 开发环境 1.1安装 Node.js 首先下载 ...
- 调用Bytom Chrome插件钱包开发Dapp
安装使用插件钱包 1. 打开Google浏览器的应用商店,搜索Bystore 下载链接:http://t.cn/E6cFFwb 2. 然后点击添加到Chrome,就可以添加到我们的: 3. 使用goo ...
随机推荐
- ABP框架(asp.net core 2.X+Vue)模板项目学习之路(一)
前言: 第一次接触ABP的项目是在2018年6月份,但是当时没有深入具体的研究,而今天因为工作的需要,需要学习.了解这个框架,在时隔半年之后,今天重新下载了这个项目,虽然在园子里有很多前辈们写的这类的 ...
- git怎么fork一个仓库并pull request
一.使用git push <-----------就是这个玩意 1.设置用户信息 当安装完 Git 应该做的第一件事就是设置你的用户名称与邮件地址. 这样做很重要,因为每一个 Git 的提交都会 ...
- Csrf_token ||| CSRF跨站请求伪造
# 注: 部分内容参考网上,侵删 CSRF(Cross-site request forgery) 跨站请求伪造,是一种对网站的恶意利用 它会通过伪装成受信任用户的请求来利用受信任的网站来获取一 ...
- sql业务分割
create Function StrToTable(@str varchar(1000)) Returns @tableName Table ( str2table varchar(50) ) As ...
- python基础1-转自金角大王
Python之路,Day1 - Python基础1---转自金角大王 本节内容 Python介绍 发展史 Python 2 or 3? 安装 Hello World程序 变量 用户输入 模块初识 ...
- Pick the Right Shoes
shoe-->shoes pointed shoes ballet shoes high heel wedged boots strappy sandals绑带凉鞋 t-straps丁字鞋 co ...
- AS 400 常用命令
转自:http://blog.chinaunix.net/uid-22375044-id-3049793.html 一.命令技巧 命令构成: CRT* (Creat) 创建 WRK* (Work Wi ...
- 影响Arcmap运行效率的因素
在使用ArcMap的过程中,总觉得ArcMap运行起来非常慢,目前发现了两点原因: 一.渲染太多图斑 比较常见的,我们在打开矢量图层时,Arcmap会自动渲染加载进去的图斑,进行符号化.在渲染的过程中 ...
- conts、var 、let的区别
1.const定义的变量不可以直接修改,通过 this.a = 'kkk' 进行修改, 而且必须初始化. 2.var定义的变量可以修改,如果不初始化会输出undefined 3.let是块级作用域,函 ...
- sql执行内部操作期间检测到不一致性解决方案
解决方法:重启下SQL服务,把下面脚本运行即可.运行后,坏掉的数据库可能会丢失. --mydb 为坏了的数据库名--mytable 为坏了的据库表--master 这里不需要更改 use mydb ...