ERC721 DApp 开发实例
Last updated
Last updated
本教程是技术大牛 luofei614 的DApp开发学习笔记,编成教程分享给开发者。
DAPP例子:领取宠物
拉群官方pet-shop的项目模板:
truffle unbox pet-shop
truffle unbox 可以下载一些项目模板代码。 更多查看: https://www.trufflesuite.com/boxes
目录结构:
contracts/: 存放合约文件夹
migrations/: 部署迁移改变文件夹
test/: 测试文件
truffle-config.js: 配置文件
安装node模块依赖
yarn install
运行项目
yarn dev
浏览器看见界面如下:
此项目只显示了前端, 还没实现合约和交互。 我们继续添加代码让他可以实现区块链领宠物。
原始教程地址:https://www.trufflesuite.com/tutorial
下面来创建智能合约:
在contracts目录下添加文件Adoption.sol文件:
pragma solidity ^0.5.0;
contract Adoption {
address[16] public adopters;
function adopt(uint petId) public returns(uint){
require(petId>=0&&petId<=15);
adopters[petId]=msg.sender;
return petId;
}
function getAdopters() public view returns(address[16] memory){
return adopters;
}
}
编译合约,在项目根目录运行命令
truffle compile
编译的结果是会在build/contracts 生成合约的json文件。 json文件中包含了合约的abi信息和bytecode编码。 这个json中还有一个networks字段,是合约部署完成后会显示出区块链网络内容。
创建迁移文件
在migrations目录下创建2_deploy_contracts.js文件:
var Adoption = artifacts.require("Adoption");
module.exports = function(deployer) {
deployer.deploy(Adoption);
};
部署合约
本地打卡Ganache, 默认监听的端口是7545
truffle-config.js 中以及设置了开发环境的测试区块链RPC地址,默认就是为本地测试网络7545的
Ganache,默认有创建十个以太坊账号,并都充了100ETH
部署合约运行命令:
truffle migrate
部署成功后,可以在Ganache界面中看见区块增多,并且第一个账户的以太坊减少, 默认会以第一个账户作为部署账户, 减少的以太坊是部署合约是gas花费。
当 truffle migrate 运行多少时,已经部署过的合约不会再部署,需要重新部署需要在运行时加上参数 --reset
编写js代码:
在/src/js/app.js文件中的initWeb3函数中添加如下代码:
初始化Web3,链接钱包:
// Modern dapp browsers...
if (window.ethereum) {
App.web3Provider = window.ethereum;
try {
// Request account access
await window.ethereum.enable();
} catch (error) {
// User denied account access...
console.error("User denied account access")
}
}
// Legacy dapp browsers...
else if (window.web3) {
App.web3Provider = window.web3.currentProvider;
}
// If no injected web3 instance is detected, fall back to Ganache
else {
App.web3Provider = new Web3.providers.HttpProvider('http://localhost:7545');
}
web3 = new Web3(App.web3Provider);
window.ethereum 是MetaMask插件的对象, window.ethereum.enable() 可以弹出MetaMask选择钱包。
初始化合约实例,设置Provider:
在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();
});
这个为什么Adoption.json可以直接获得数据, 是因为根目录下bs-config.json中配置了baseDir中有 build/contracts
在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);
});
此代码获取合约中已经被领取的代码,标记为已领取,其他人不能再领取。
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);
});
});
将上面代码替换注释 replace me
现在这个例子可以完整跑了。 注意在使用时,将自己MetaMask钱包地址切换为测试网络。 并添加一个有余额的账号。 可以Ganache界面上选一个有余额的账号,复制私钥, 在MetaMask钱包创建账号时选择导入私钥。