스마트컨트랙트에서 이더리움 네트워크와 통신하듯이 프론트엔드에서도 Data를 가져오거나 표시할 때 이더리움 네트워크와 통신해야 한다. 이 때 사용하는 것이 Web3.js
또는 Ethers.js
다. 둘 다 자바스크립트 라이브러리이며, 여러 모듈로 구성되어 있다.
Web3.js
는 이더리움 재단에서 만든 것으로 Ethers.js
보다 일찍 나왔다. 공식문서를 봤을 때 하위 모듈인 Web3.bzz
와 Web3.shh
는 딱히 이렇다 할 내용이 없었고, 전체적으로 많은 양 대비 가독성이 떨어진다는 느낌을 받았다. Ethers.js
도 가독성이 좋다는 느낌은 없었지만 그래도 그나마 나은 느낌이다. 코드를 보면서 직관적인 차이점을 살펴보자.
const Web3 = require('web3')
const rpcURL = '' // Your RCkP URL goes here
const web3 = new Web3(rpcURL)
const address = '0x73BCEb1Cd57C711feaC4224D062b0F6ff338501e'
web3.eth.getBalance(address, (err, wei) => {
balance = web3.utils.fromWei(wei, 'ether')
console.log(balance)
})
const { ethers } = require("ethers");
const INFURA_ID = ''
const provider = new ethers.providers.JsonRpcProvider(`https://mainnet.infura.io/v3/${INFURA_ID}`)
const address = '0x73BCEb1Cd57C711feaC4224D062b0F6ff338501e'
const main = async () => {
const balance = await provider.getBalance(address)
console.log(`\nETH Balance of ${address} --> ${ethers.utils.formatEther(balance)} ETH\n`)
}
main()
const Web3 = require('web3')
const rpcURL = '' // Your RCP URL goes here
const web3 = new Web3(rpcURL)
const abi = [{"constant":true,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_releaseTime","type":"uint256"}],"name":"mintTimelocked","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[],"name":"MintFinished","type":"event"},{"anonymous":false,"inputs":[],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]
const address = '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07'
const contract = new web3.eth.Contract(abi, address)
contract.methods.totalSupply().call((err, result) => { console.log(result) })
contract.methods.name().call((err, result) => { console.log(result) })
contract.methods.symbol().call((err, result) => { console.log(result) })
contract.methods.balanceOf('0xd26114cd6EE289AccF82350c8d8487fedB8A0C07').call((err, result) => { console.log(result) })
const { ethers } = require("ethers");
const INFURA_ID = ''
const provider = new ethers.providers.JsonRpcProvider(`https://mainnet.infura.io/v3/${INFURA_ID}`)
const ERC20_ABI = [
"function name() view returns (string)",
"function symbol() view returns (string)",
"function totalSupply() view returns (uint256)",
"function balanceOf(address) view returns (uint)",
];
const address = '0x6B175474E89094C44Da98b954EedeAC495271d0F' // DAI Contract
const contract = new ethers.Contract(address, ERC20_ABI, provider)
const main = async () => {
const name = await contract.name()
const symbol = await contract.symbol()
const totalSupply = await contract.totalSupply()
console.log(`\nReading from ${address}\n`)
console.log(`Name: ${name}`)
console.log(`Symbol: ${symbol}`)
console.log(`Total Supply: ${totalSupply}\n`)
const balance = await contract.balanceOf('0x6c6Bc977E13Df9b0de53b251522280BB72383700')
console.log(`Balance Returned: ${balance}`)
console.log(`Balance Formatted: ${ethers.utils.formatEther(balance)}\n`)
}
main()
Web3.js에서는 abi를 전부 하드코딩으로 가져오지만 Ethers.js에선 인터페이스로 갈결하게 가져올 수 있다. 그 외에 Web3.js에서는 메소드 다음에 call()
이 자주 반복되는 것을 볼 수 있지만 Ethers.js에서는 딱히 반복되는 부분은 없는 것 같다. 다른 예제도 몇 개 있지만 두드러진 차이점은 없었다. 사용법에서 호불호가 갈리는 게 아닐까 싶다. 다만 몇몇 라이브러리를 사용려면 Ethers.js가 있어야 하는 것들이 있다고 한다.