ERC721 DApp 开发实例

本教程是技术大牛 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钱包创建账号时选择导入私钥。

Last updated