Notice
Recent Posts
Recent Comments
올해는 머신러닝이다.
[DAPP] truffle을 활용한 Pet-Shop 튜터리얼 분석해보자. 본문
Truffle를 활용한 Pet-Shop 튜터리얼 분석
광고 클릭시 많은 힘이 됩니다.
Truffle 튜터리얼 중 펫샵을 활용해서 프론트 까지 적용해서 어떤식으로 웹에서 연동되는지 살펴보자.
아래 주소에 있는 내용은 깔끔하게 정리되어 있다. 따라해보는 걸 추천한다.
여기 글은 펫샵에 사용되는 소스를 분석해보자 한다.
이더리움 플랫폼 위 DAPP
개발 프레임워크 중 하나인 truffle
사용시 개발시 순서는 다음과 같다.
- 개발환경을 설정한다.
- truffle box( 보일러 플레이트처럼 만들어준다.)를 이용해서 pet-shop 을 해제
- 스마트 계약 소스를 (.sol) 작성한다.
- 컴파일 및 배포를 한다.
- Ganeche 를 통해 테스팅을 한다.
- 웹 브라우저에서 스마트 계약이 정상적으로 인터랙션이 제대로 이루어지는지 확인해본다.
아래 이미지는 결과 화면이다. Adopt 버튼을 통해서 success 이 제대로 이루어 지는 지 보면 된다.
MetaMask 를 통해서 창이 열리면서 Submit를 클릭해준다.
최종적으로 채택이 된 것을 웹에서 확인해볼 수 있다. ( 새로고침을 해야한다. )
결과물은 따라하다보면 쉽게 볼 수 있을것이다. 여기서 특이한 점은
MetaMask
를 통한Custom RPC
로ganache private network
로 접속해서 진행
스마트 계약을 테스팅시 솔리디티 언어로 테스팅 하는 방법
우선 Adoption.sol 파일을 훝어보자.
pragma solidity ^0.4.17;
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]) {
return adopters;
}
}
주로 스마트 계약을 테스팅시 자바스크립트(mocha)로 계약 함수를 신뢰성을 테스트한다. 하지만 여기에선 바로 솔리디티 언어로 테스팅하는 걸 보여준다.
pragma solidity ^0.4.17;
//다양한 테스팅 도구 제공
import "truffle/Assert.sol";
//이미 서버에 배포된 계약 주소를 가져온다.
import "truffle/DeployedAddresses.sol";
//계약 소스를 가져온다.
import "../contracts/Adoption.sol";
contract TestAdoption {
//Adoption 초기화
Adoption adoption = Adoption(DeployedAddresses.Adoption());
//Pet에 Adopt를 할수 있는지 테스트
function testUserCanAdoptPet() public {
//8번 아이디를 adopt 함수 실행
uint returnedId = adoption.adopt(8);
uint expected = 8;
//값이 제대로 가져오는 지 체크
Assert.equal(returnedId, expected, "Adoption of pet ID 8 should be recoreded");
}
//아이디를 통해 Adopter 주소를 가져오는 걸 테스팅
function testGetAdopterAddressByPetId() public {
//트랙잭션을 할 예정이므로 예상 값을 this로 설정 가능하다. (펫 구매한 사람 주소)
address expected = this;
//adopters 변수 설정되면 public getter 가 되므로 거기 위치에 8의 값을 가져와서 테스팅해본다.
address adopter = adoption.adopters(8);
//값 맞게 들어오는지 체크
Assert.equal(adopter, expected, "Owner of pet Id 8 should be recored");
}
function testGetAdopterAddressByPetIdInArray() public {
//트랙잭션을 할 예정이므로 예상 값을 this로 설정 가능하다. (펫 구매한 사람 주소)
address expected = this;
//storeage, memory 를 설정해서 실제 물리적으로 저장 할 것인지 내부에서 저장할 건지 정한다.
//adoption 클래스에서 adopter 배열목록을 가져온다.
address[16] memory adopters = adoption.getAdopters();
//가져온 adopter의 8번째가 맞는지 체크
Assert.equal(adopters[8], expected, "Owner of pet ID 8 should be recorded.");
}
}
그리고 다음과 같이 테스팅을 해본다.
> truffle test
or
devlope 모드일 경우 단지 test 만 입력
Using network 'development'.
Compiling ./contracts/Adoption.sol...
Compiling ./test/TestAdoption.sol...
Compiling truffle/Assert.sol...
Compiling truffle/DeployedAddresses.sol...
TestAdoption
✓ testUserCanAdoptPet (91ms)
✓ testGetAdopterAddressByPetId (70ms)
✓ testGetAdopterAddressByPetIdInArray (89ms)
3 passing (670
그리고 웹쪽 프론트에서 이 계약 함수들을 사용하는 내용이다. App.js
에서 볼 수 있다.
주석을 달아봄으로써 해당 기능을 알아볼 예정이다.
App = {
web3Provider: null,
contracts: {},
//초기화
init: function() {
//펫 배열을 가져와서 리스트를 만든다.
$.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") {
//Metamask 가 실행시 현 지갑을 리턴한다.
App.web3Provider = web3.currentProvider;
} else {
//만약 지정된 지갑이 없는 경우 미리 설정된 Ganeche 지갑을 리턴한다.
App.web3Provider = new Web3.providers.HttpProvider(
"http://localhost:7545"
);
}
web3 = new Web3(App.web3Provider);
return App.initContract();
},
//계약 초기화
initContract: function() {
/*
Adoption.JSON 형태
{
"contractName": "Adoption",
"abi": [
{
"constant": true,
"inputs": [
{
"name": "",
"type": "uint256"
}
],
"name": "adopters",
...............
*/
//Adoption 은 컴파일 시 나온 ABI JSON이다 여기에 기본 함수들이 표시가 된다.
//웹에서는 이 ABI JSON을 보고 실행을 할 수 있다.
$.getJSON("Adoption.json", function(data) {
// Get the necessary contract artifact file and instantiate it with truffle-contract
var AdoptionArtifact = data;
//미리 제공된 truffleContract 를 통해 Adoption 인스턴스 생성
App.contracts.Adoption = TruffleContract(AdoptionArtifact);
//지갑 설정
App.contracts.Adoption.setProvider(App.web3Provider);
//
// 이미 채택된 애완 동물이 있는 경우 함수를 호출해서 데이터 확인 후 업데이트 할수 있도록 한다.
return App.markAdopted();
});
return App.bindEvents();
},
//이벤트 바인딩
bindEvents: function() {
$(document).on("click", ".btn-adopt", App.handleAdopt);
},
//채택된 아이템이 있는 경우 버튼을 success 로 변경
markAdopted: function(adopters, account) {
var adoptionInstance;
App.contracts.Adoption.deployed()
.then(function(instance) {
adoptionInstance = instance;
//전체 adopte 배열 주소를 리턴한다.
return adoptionInstance.getAdopters.call();
})
.then(function(adopters) {
//for 문 돌면서 adopte 만큼 버튼을 success 로 바꾸고 비활성화를 시킨다.
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);
});
},
//Adopt 버튼 클릭시 adopt 함수 실행하는 함수이다. (트랙잭션이 발생된다.)
handleAdopt: function(event) {
//기본 이벤트 블럭함
event.preventDefault();
//펫 아이디를 id 를 통해 쿼리해옴
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;
//petId, account를 넣어서 adopt 함수를 실행한다.
return adoptionInstance.adopt(petId, { from: account });
})
.then(function(result) {
//완료 된 후 success 버튼으로 변경...잘 안됨..
return App.markAdopted();
})
.catch(function(err) {
console.log(err.message);
});
});
}
};
$(function() {
$(window).load(function() {
//초기화
App.init();
});
});
Truffle을 이용해서 손쉽게 테스팅 가능하며 배포도 쉽게 가능한 걸 볼수 있다. 잘 배워놓으면 도움이 많이 된다고 본다.
'스터디 > DAPP' 카테고리의 다른 글
Geth를 이용한 dapp 개발 #1 (1) | 2018.04.17 |
---|---|
[DAPP] Truffle로 스마트 계약을 테스팅하고 디버깅해보자. (0) | 2018.03.31 |
[DAPP] 크립토좀비 요약 내용[1 ~ 6장] (2) | 2018.03.25 |
[DAPP] ERC20 토큰을 만들어서 배포까지 (7) | 2018.03.21 |
[DAPP]예제로 배우는 DAPP 개발편 - 복권편 (3) | 2018.03.19 |