컨트랙트와 상호작용하기
이 튜토리얼은, 이전에 우리가 로컬 개발 네트워크에 생성하고 만든(업그레이드까지 한!) 간단한 ‘Counter’ 컨트랙트를 기반으로 합니다. 이제 web3.js를 사용하여 자바 스크립트 코드에서이 계약과 상호 작용하는 방법을 살펴 보겠습니다. 작은 스크립트를 작성하여, 카운터값을 증가 시킨 후 업데이트된 결과값을 보고받아 보겠습니다.
이 튜토리얼의 전체 코드는 OpenZeppelin SDK github 저장소의 첫 번째 프로젝트
예제에서 찾을 수 있습니다.
Setup
OpenZeppelin SDK가 사용하는 라이브러리와 동일한 라이브러리 인 web3.js를 사용하여 코드에서 블록 체인과 상호 작용할 것입니다. 이미 만든 my-project
에서 다음을 실행하여 설치 해 주세요.
npm install web3
다양하고 많은 자바스크립트가 있으며, 가장 좋아하는 것을 사용할 수 있습니다. 컨트랙트가 배포되면 어떤 라이브러리를 통해서도 계약과 상호 작용할 수 있습니다!
네트워크에 연결
첫 번째 단계는 네트워크 연결을 여는 것입니다. 이전 튜토리얼에서 시작한 로컬 개발 네트워크에 연결합니다.
주의: 기본적으로, ganache-cli
는 중지되면 모든 데이터를 제거합니다. 이전 튜토리얼에서 가나슈를 종료 했다면, ganache-cli --deterministic
를 실행하여 새로 시작후, openzeppelin create Counter
를 다시 실행 해 주세요.
자바스크립트는 새 파일 src/index.js
에서 코딩을 시작해 보겠습니다. 비동기코드를 작성하기위한 보일러플레이트를 이용하고, web3
객체를 설정 해 보겠습니다.
const Web3 = require('web3');
async function main() {
// Set up web3 object, connected to the local development network
const web3 = new Web3('http://localhost:8545');
}
main();
이제 로컬 호스트 포트 8545인 개발 네트워크에 연결하는, 새 web3
인스턴스를 초기화하고 있습니다. 활성화 된 계정 목록과 같은 로컬 노드에 무언가를 요청하여 연결이 작동하는지 테스트 할 수 있습니다.
// Set up web3 object, connected to the local development network
const web3 = new Web3('http://localhost:8545');
// Retrieve accounts from the local node
const accounts = await web3.eth.getAccounts();
console.log(accounts);
Note 모든 스니펫에서 상용구 코드를 반복하지는 않지만 항상 위에서 정의한 main
함수 내에서 코딩해야합니다.
node
를 사용하여 위의 코드를 실행하고 사용 가능한 계정 목록이 있는지 확인하십시오.
$ node src/index.js [
'0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1',
'0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0',
'0x22d491Bde2303f2f43325b2108D26f1eAbA1e32b',
'0xE11BA2b4D45Eaed5996Cd0823791E0C93114882d',
'0xd03ea8624C8C5987235048901fB614fDcA89b117',
'0x95cED938F7991cd0dFcb48F0a06a40FA1aF46EBC',
'0x3E5e9111Ae8eB78Fe1CC3bb8915d5D461F3Ef9A9',
'0x28a8746e75304c0780E011BEd21C72cD78cd535E',
'0xACa94ef8bD5ffEE41947b4585a84BdA5a3d3DA6E',
'0x1dF62f291b2E969fB0849d99D9Ce41e2F137006e'
]
계정은 openzeppelin 계정
을 실행할 때 얻은 계정과 일치해야합니다.
$ openzeppelin accounts
? Pick a network development
Accounts for dev-1567476967339:
Default: 0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1
All:
- 0: 0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1
- 1: 0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0
- 2: 0x22d491Bde2303f2f43325b2108D26f1eAbA1e32b
- 3: 0xE11BA2b4D45Eaed5996Cd0823791E0C93114882d
- 4: 0xd03ea8624C8C5987235048901fB614fDcA89b117
- 5: 0x95cED938F7991cd0dFcb48F0a06a40FA1aF46EBC
- 6: 0x3E5e9111Ae8eB78Fe1CC3bb8915d5D461F3Ef9A9
- 7: 0x28a8746e75304c0780E011BEd21C72cD78cd535E
- 8: 0xACa94ef8bD5ffEE41947b4585a84BdA5a3d3DA6E
- 9: 0x1dF62f291b2E969fB0849d99D9Ce41e2F137006e
훌륭합니다! 첫 번째 코드 스니펫이 블록 체인에서 데이터를 가져옵니다. 이제 우리가 만든 컨트랙트를 이용해 보겠습니다.
컨트랙트 인스턴스 얻기
우리가 배포한 Counter
컨트랙트와 상호작용하기 위해, web3 컨트랙트 인스턴스를 새로 만들어 보겠습니다. 이것은 블록체인에 있는 우리의 컨트랙트를 나타내는 자바스크립트 객체 입니다.
이 web3 컨트랙트를 만들기 위해서 두가지가 필요합니다.
- 컨트랙트가 배포된 주소(address)
- 컨트랙트의 함수를 정의한 ABI
address 는 OpenZeppelin CLI가 컨트랙트를 배포할때 표시됩니다. ABI는 아래와 같이 build/contracts
폴더의 컴파일 된 아티팩트에서 검색 할 수 있습니다.
// Set up web3 object, connected to the local development network
const web3 = new Web3('http://localhost:8545');
// Set up a web3 contract, representing our deployed Counter instance
const address = '0xCfEB869F69431e42cdB54A4F4f105C19C080A601';
const abi = require('../build/contracts/Counter.json').abi;
const counter = new web3.eth.Contract(abi, address);
Note address
는 본인이 컨트랙트를 배포할때 받은 것으로 대체 하세요, 아마 여기 나와있는것과 다를 것 입니다.
이제 이 자바 스크립트 객체를 사용하여 컨트랙트와 상호 작용할 수 있습니다. 어떻게 하는지 보겠습니다!
컨트랙트 호출하기
Counter
컨트랙트의 현재 value 를 표시하는것 부터 해 보겠습니다. 컨트랙트 안에 있는 퍼블릭 함수value()
를 호출(call)한뒤, 응답을 기다려야(await) 합니다.
// Call the value() function of the deployed Counter contract
const value = await counter.methods.value().call();
console.log(value);
스크립트를 다시 실행하고 출력 된 값을 확인하여 모든 것이 원활하게 실행되고 있는지 확인하십시오.
$ node src/index.js
11
Note 이전 튜토리얼과 이 튜토리얼을 진행하는 사이에, 가나슈를 다시 시작한 경우 모든 상태가 지워 지므로, 리턴 된 값은 0이 됩니다.
멋져요! 이제 트랜잭션을 보내서 실제로 컨트랙트와 상호 작용할 수 있습니다.
트랜잭션 보내기
이제 트랜잭션을 보내서 카운터의 값을 증가
시켜 보겠습니다. 트랜잭션을 보내는 것은, 누가보내는지 지정하고, 가스 한계치와 사용할 가스비용을 지정해야 하기때문에, call
만큼 간단하진 않습니다. 이 예제를 단순하게 유지하기위해, 가스 및 가스 가격 모두에 대해 하드 코딩 된 값을 사용하고 노드에서 사용 가능한 첫 번째 계정에서 거래를 보내겠습니다.
Note 실제 응용 프로그램에서는 거래 가스를 추정 하고 가스 가격 오라클을 확인하여 모든 거래에 사용할 최적의 값을 알고 싶을 수 있습니다.
스니펫이 실행될 때마다 Counter
값을 20 씩 늘린 다음, 이전에 작성한 코드를 사용하여 업데이트 된 값을 표시해 보겠습니다.
// Retrieve accounts from the local node, we will use the first one to send the transaction
const accounts = await web3.eth.getAccounts();
// Send a transaction to increase() the Counter contract
await counter.methods.increase(20)
.send({ from: accounts[0], gas: 50000, gasPrice: 1e6 });
// Call the value() function of the deployed Counter contract
const value = await counter.methods.value().call();
console.log(value);
이제 스니펫을 실행할 수 있으며 호출 할 때마다 카운터 값이 증가하는것을 확인할 수 있습니다!
$ node src/index.js
31
$ node src/index.js
51
$ node src/index.js
71
이전 튜토리얼에서와 같이 openzeppelin send-tx
및 openzeppelin call
을 사용하여 컨트렉트와 상호 작용을 시도 할 수 있으며, 서로 다른 두 인터페이스에서 작업중인 인스턴스와 동일한 인스턴스인지 확인할 수 있습니다.
이 학습서의 스니펫은 단순하지만 Javascript 애플리케이션에서 스마트 계약과 상호 작용하기위한 기본입니다. web3.js
외에 다른 라이브러리를 이용 할 수도 있고, 자바스크립트가 아닌 다른 언어를 이용 할 수도 있습니다. OpenZeppelin SDK가 블록체인의 컨트랙트를 잘 관리 합니다.
다음 튜토리얼에서는, 스마트컨트랙트의 더 흥미로운 부분에 접근해 보겠습니다. 더 복잡한 로직을 실행해 보고, 토큰을 생성하기 위해 @openzeppelin/contracts-ethereum-package
과 연동하고, 컨트랙트 간에 연결을 해 보겠습니다.