//JSON-RPC방식
{"jsonrpc":"2.0","method":"eth_sendTransaction","params":[{"from":"0xb60e8dd61c5d32be8058bb8eb970870f07233155","to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","gas":"0x76c0","gasPrice":"0x9184e72a000","value":"0x9184e72a","data":"0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"}],"id":1}
//web3 라이브러리 사용방식
CryptoZombies.methods.createRandomZombie("Vitalik Nakamoto 🤔")
.send({ from: "0xb60e8dd61c5d32be8058bb8eb970870f07233155", gas: "3000000" })
이더리움 노드
들은JSON-RPC
방식을 통해 서로 소통한다.
JSON-RPC
방식은 사람이 읽기 어렵다.
이러한 문제를web3.js
가 해결하며web3.js
를 통해자바스크립트 interface
로 우리는 이더리움 노드들과 상호작용할 수 있다.
const Web3 = require('web3');
//provider설정 : http..안에 infura등의 url이 들어간다
function getWeb3() {
const web3 = new Web3(new Web3.providers.HttpProvider('http://...'))
return web3;
}
Web3.js
에서Web3 provider
를 설정하는 것은 내가 작성한 스마트 컨트랙트 코드의 읽기와 쓰기를 어떤 노드가 처리해줄 것인지 선택하는 것과 같다.이는 전통적인 웹 앱에서 API 호출을 위해 원격 웹 서버의 URL을 설정하는 것과 같다.
나의 PC에 이더리움 노드를 설치하고 provider로 지정할 수 있지만, 이더리움 전체 노드의 용량이 크기 때문에 비효율적인 방법이다.
때문에 DApp의 개발자들의 편의성을 위해 각 PC에서 이더리움 노드를 운영할 필요가 없도록 하기 위해Infura서비스
가 만들어졌다.그리고
메타마스크
는 내부적으로 Infura의 서버를 Web3 provider로 사용한다
(provider변경도 가능함).
// myContract 인스턴스화
var myContract = new web3js.eth.Contract(myABI, myContractAddress);
내가 작성한 스마트 컨트랙트와 통신하기 위해(이미 배포됨) 2가지를 필요로 한다
var myContract = new web3js.eth.Contract(myABI, myContractAddress);
ABI
ABI는 Application Binary Interface의 줄임말이다. 기본적으로 JSON 형태로 나의 컨트랙트 메소드를 표현하는 것이다.
ABI는 remix등의 solidity 컴파일러로부터 얻을 수 있다.
컨트랙트의 주소
내가 작성한 코드를 remix나 truffle등을 통해 이더리움 블록체인 네트워크에 배포하면
contract 주소를 얻을 수 있다.
내가 배포한 contract를 가지고 web3.js를 통해 무엇인가를 하고 싶다면(javascript, html, css등으로 무엇인가 앱을 만들고 싶다면) 내가 이더리움 네트워크에 배포한 contract주소를 알아야 한다
배포된 Contract의 함수를 사용하기 위해서 두 개의 메소드를 써야한다
call
//123을 매개 변수로 myMethod라는 이름의 함수를 call했다 myContract.methods.myMethod(123).call()
call은 view와 pure 함수를 위해 사용한다.
로컬 노드에서만 실행하고, 블록체인에 트랜잭션을 만들지 않는다.
view와 pure 함수는 읽기 전용이고 블록체인에서 상태를 변경하지 않는다.
가스를 전혀 소모하지 않고, 메타마스크에서 트랜잭션에 서명하라고 사용자에게 창을 띄우지도 않는다.
send
//123을 매개 변수로 myMethod라는 이름의 함수를 호출하는 트랜잭션을 send했다 myContract.methods.myMethod(123).send()
send는 트랜잭션을 만들고 블록체인 상의 데이터를 변경한다.
view와 pure가 아닌 모든 함수에 대해 send를 사용해야 하는 것이다.
트랜잭션을 send하는 것은 사용자에게 가스를 지불하도록 하고, 메타마스크에서 트랜잭션에 서명하라고 창을 띄울 것이다. Web3 프로바이더로 메타마스크를 사용할 때, send()를 호출하면 자동으로 이 모든 것이 이루어지고, 내가 작성하는 코드에 어떤 특별한 것도 추가할 필요가 없다.
web3.js는 아래와 같은 라이브러리가 존재한다
web3.eth, web3.eth.subscribe
: 노드 관련 라이브러리
web3.eth.Contract, web3.eth.abi
: 컨트랙트 관련 라이브러리
web3.eth.accounts
: 계정, 지갑관련 라이브러리
web3.eth.personal
: 트랜잭션 관련 라이브러리
web3.*.net
: 이더리움이 아닌 다른 블록체인 네트워크를 추가하여 사용하는 경우
web3.utils
: 암호화 등 유틸 라이브러리
web3.eth.ens
web3.eth.Iban
//가스비를 resturn한다.
web3.eth.getGasPrice().then((result) => {
console.log(result);
})
이더리움에 컨트랙트를 배포할 때는 네트워크 사용량에 따라 Gas fee가 발생함. 가스비를 잘못 책정하는 경우, 트랜잭션을 실행하다가 가스비가 고갈되면 트랜잭션이 revert되는 문제가 발생함. 따라서 적절한 가스비를 계산해야 트랜잭션을 배포할 수 있음.
//인자로 블록의 해시값이나 블록 숫자, "earliest" "latest" "pending"의 string 값이 들어가기도 함
web3.eth.getBlock(blockHashOrBlockNumber).then((result) => {
console.log(result);
})
아래와 같은 정보가 return됨
web3.eth.getBalance(계정주소).then((result) => {
console.log(result);
})
특정 주소의 잔액을 보여준다(wei단위로 보여줌).
그래서 아래와 같이 utils의 fromWei 라이브러리를 사용해서 변환가능
web3.eth.getBalance(계정주소).then((result)=>{
return web3.utils.fromWei(price."ether");
})
.then((eth)=>{
console.log(eth);
})
web3.eth.getTransaction(트랜잭션 해시 값).then((result) => {
console.log(result);
})
트랜잭션을 조회할수 있는 method
web3.eth.getTransactionReceipt(txHash).then((result) => {
console.log(result);
})
완료된 트랜잭션의 영수증을 들고옴
web3.eth.getPendingTransactions().then((result) => {
console.log(result);
})
provider가 요청한 contract 중 pending상태인 transaction을 들고옴