web3 라이브러리
이더리움 네트워크는 노드로 구성되어 있고, 각 노드는 블록체인의 복사본을 가지고 있더. 만약 스마트 컨트랙트의 함수를 실행하고자 한다면, 이 노드들 중 하나에 질의를 보내 아래 내용을 전달해야 한다:
- 스마트 컨트랙트의 주소
- 실행하고자 하는 함수, 그리고
- 그 함수에 전달하고자 하는 변수들
이더리움 노드들은 JSON-RPC라고 불리는 언어로만 소통할 수 있고, 이는 사람이 읽기는 불편하다. 컨트랙트의 함수를 실행하고 싶다고 질의를 보내는 것은 아래와 같다.
터미널에서 curl문법을 사용할 때:
curl -X POST \
-H "Content-type: application/json" \
--data '{ "jsonrpc":"2.0", "method":"eth_accounts","params":[]}' \
http://localhost:8545
(request method 기본적으로 다 post임)
(헤더부분 content-type 다 application/json)
간단하게 postman이나 썬더 클라이언트를 사용하면,
데이터를 실어 보낼 때, 아래처럼 작성만 해주면 된다.
{
"id":1337 (가나슈가 제공해주는 체인 아이디),
"jsonrpc":"2.0", //필수
"method":"eth_accounts", // 필수
"params":[]
}
여기서 method 항목은? core, set, getBalance, 같은 메서드이다.
etherenum jsonrpc 홈페이지에 메서드 나와있으니 읽어보면 어떻게 사용하는 지 다 알 수 있다.
https://ethereum.github.io/execution-apis/api-documentation/
다행히도, Web3.js는 이런 골치 아픈 질의를 몰라도 되게 해준다. 우리는 편리하고 쉽게 읽을 수 있는 자바스크립트 인터페이스로 상호작용을 하면 되는 것!
그럼 설치 해보자.
test를 해보기 위해 jest도 다운로드 해주겠다.
npm init -y
npm install -D jest
npm install web3
npm install ethereumjs-tx # Transaction 객체를 이더리움 클라이언트가 이해할 수 있게 만들어주는 라이브러리
#서명 만들려고~
# 우선 이것도 깔아주자!
Web3가 가진 다양한 모듈
web3-eth : 이더리움 블록체인과 스마트 컨트랙트 모듈이다.
web3-utils : dApp 개발자를 위한 유용한 헬퍼 함수를 모아둔 모듈이다.
web3-bzz : 탈중앙화 파일 스토리지를 위한 스왐 프로토콜 모듈이다.
web3-shh : P2P 커뮤니케이션과 브로드캐스트를 위한 위스터 프로토콜 모듈이다.
자주 쓰이는 메서드 모음
web3.eth.getAccounts() //노드에 의해 관리되는 계정들을 배열로 반환
web3.eth.getBlockNumber() //가장 최근 블록의 번호를 반환
web3.eth.getBalance() //주어진 주소의 잔액을 반환
web3.eth.getBlock(blockHashOrBlockNumber [, returnTransactionObjects])//블록 번호 또는 해쉬와 일치하는 블럭을 반환
web3.eth.getBlockTransactionCount(blockHashOrBlockNumber) //주어진 블럭 안에 있는 transaction의 수 반환
web3.eth.getTransaction(transactionHash [, callback]) //주어진 해시와 일치하는 transaction 반환
web3.eth.getTransactionCount(address) //계정으로부터 보내진 transaction의 수 반환
web3.eth.sendTransaction(transactionObject [, callback]) //network로 transaction 전송
web3.eth.sendSignedTransaction(signedTransactionData) //서명이 완료된 transaction 전송
web3.utils.toHex(mixed) //주어진 값을 Hex로 변환해서 hex 문자열로 반환
web3.utils.toWei(number [, unit])
jest.config.js 루트 디렉토리에 파일을 추가해주자.
const config = {
verbose: true,
testMatch: ["<rootDir>/**/*test.js"],
};
module.exports = config;
그리고 package 다운로드가 모두 끝났다면,
package.json 파일도 수정해주자.
"scripts": {
"test": "jest"
}
//scripts 안의 test 항목을 "jest"로 바꾸자.
이렇게 하면 npm run test를 터미널에 입력하여 테스트 코드를 빠르게 실행할 수 있다.
본격적으로, 테스트 코드를 작성해보자.
const Web3 = require("web3");
const ethTx = require("ethereumjs-tx").Transaction;
describe("Web3 테스트코드", () => {
let web3;
let accounts;
let sender;
let receiver;
it("web 연결 테스트", () => {
web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.01:8545"));
console.log(web3);
});
//최신블럭의 번호 가져오기
it("Latest Block 높이 가져오기", async () => {
const latestBlock = await web3.eth.getBlockNumber();
console.log(latestBlock);
// eth.getBalance
});
it("전체 accounts 가져오기", async () => {
accounts = await web3.eth.getAccounts();
sender = accounts[0];
receiver = accounts[1];
console.log(accounts, sender, receiver);
});
it("첫번째 계정 밸런스 가져오기", async () => {
const balance = await web3.eth.getBalance(accounts[0]);
console.log(balance); // wei 단위로 이더를 표현했다.
console.log(balance / 10 ** 18);
// 1 ETH = 10^18
});
it("ETH 단위 변경해보기", () => {
//eth
//gwei
//wei
console.log(web3.utils.toWei("1", "gwei"));
console.log(web3.utils.toWei("1", "ether"));
});
it("트랜잭션 횟수 구해오기", async () => {
const txCount = await web3.eth.getTransactionCount(sender);
console.log(txCount);
console.log(web3.utils.toHex(txCount));
});
it("트랜잭션 실행하기", async () => {
const txCount = await web3.eth.getTransactionCount(sender);
// e2df70dfa0b038f4c2d1d7ec5262c411d3380bde3f1f5471b016a65a2cc44878
const privateKey = Buffer.from(
"e2df70dfa0b038f4c2d1d7ec5262c411d3380bde3f1f5471b016a65a2cc44878",
"hex"
);
const txObject = {
nonce: web3.utils.toHex(txCount),
from: sender,
to: receiver,
value: web3.utils.toHex(web3.utils.toWei("1", "ether")), //단위 Wei로 보내야함 10 ** 18 -> toHex
gasLimit: web3.utils.toHex(6721975), // 아반떼 연료통이 55 L
gasPrice: web3.utils.toHex(web3.utils.toWei("1", "gwei")), // 1L 당 = 2,000
data: web3.utils.toHex(""),
};
const tx = new ethTx(txObject);
tx.sign(privateKey);
console.log(tx);
const serializedTx = tx.serialize();
// console.log(serializedTx.toString("hex"));
const TransactionObject = await web3.eth.sendSignedTransaction(
"0x" + serializedTx.toString("hex")
);
console.log(TransactionObject);
});
it("balance확인", async () => {
const SenderBalance = await web3.eth.getBalance(sender);
const ReceivedBalance = await web3.eth.getBalance(receiver);
console.log("sender balance : ", SenderBalance / 10 ** 18);
console.log("Received balance : ", ReceivedBalance / 10 ** 18);
});
it("가스 사용량 확인하기", async () => {
// 가스 사용량 21004
// 21000 + 4
// 가스 사용량 21004 // 기름 10L 넣을거야. -> 한번에 넣을 kg
// 가스최대치 6721975
// 가스비 = 가스가격 * 가스한도
const gas_price = 4; //4gwei를 사용하면 2분 내로 전송가능
console.log((gas_price * 21004) / 10 ** 8 + "ETH");
});
});
이 코드를 실행하기 전에는, 늘 터미널에서 ganache-cli를 먼저 실행시킨 상태여야한다.
1 wei = 10^18 Eth
1 Gwei = 10^9 wei
(10의 9 승 표기 = G (Giga, 기가))
(10의 18승은 E로 표기하고 Exa(엑사)라고 읽는데, 이더리움의 E를 따와서,
아마 이더의 최소단위인 1wei가 10^18 이더가 되지 않았나 하는 추측.....(뇌피셜임))
Reference:
https://velog.io/@citron03/web3.js%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C
https://yellow-w.tistory.com/340
'블록체인' 카테고리의 다른 글
[이더리움] geth puppeth 이용하여 private network 구성하기(리눅스 환경) (0) | 2022.07.01 |
---|---|
[이더리움] Geth로 다른 블록노드와 연결하기(리눅스 환경) (0) | 2022.06.30 |
[이더리움] test account 만들어 메타마스크 사용해보기 (0) | 2022.06.27 |
[이더리움] 리눅스 환경에 Go lang(Go 언어), Geth 설치하기 (0) | 2022.06.27 |
[Typesript] 암호화폐 지갑 웹으로 구현해보기(트랜잭션&정보입력) (0) | 2022.06.17 |