728x90
저번 게시글(https://stickode.tistory.com/1016)에 이어서 오늘은 이더리움 블록익스플로러에 트랜잭션과 계정의 잔액, 그리고 현재 가스 가격을 조회하는 기능을 추가했습니다.
프로젝트 구조
코드
app.js
// app.js
const express = require('express'); // Express 모듈 불러오기
const app = express(); // Express 애플리케이션 생성
const { Web3 } = require('web3'); // Web3 모듈 불러오기
const web3 = new Web3('https://mainnet.infura.io/v3/발급받은 키'); // Infura를 통해 이더리움 메인넷에 연결
// BigInt 값을 문자열로 변환하여 JSON으로 직렬화하는 함수
function serializeBigInt(key, value) {
return typeof value === 'bigint' ? value.toString() : value; // 만약 값이 BigInt 타입이면 문자열로 변환
}
app.use(express.static('public')); // 'public' 디렉토리의 정적 파일을 제공
// 블록 번호를 이용해 블록 정보를 조회하는 라우트
app.get('/block/:blockNumber', async (req, res) => {
try {
console.log(" blockNumber : " + req.params.blockNumber); // 로그에 블록 번호 출력
const block = await web3.eth.getBlock(req.params.blockNumber); // 비동기적으로 블록 정보 조회
console.log(" block : "); // 로그에 블록 정보 시작을 알림
console.log(block); // 조회한 블록 정보를 로그에 출력
const blockString = JSON.stringify(block, serializeBigInt); // BigInt 처리를 위한 직렬화 함수와 함께 JSON으로 변환
res.setHeader('Content-Type', 'application/json'); // 응답 헤더에 컨텐츠 타입 설정
res.send(blockString); // 직렬화된 블록 정보를 응답으로 전송
} catch (error) {
console.error(error); // 에러 발생시 콘솔에 에러 출력
res.status(500).send(error.toString()); // 클라이언트에 500 상태 코드와 에러 메시지 전송
}
});
// 트랜잭션 해시를 이용해 트랜잭션 정보를 조회하는 라우트
app.get('/transaction/:transactionHash', async (req, res) => {
const transactionHash = req.params.transactionHash; // 요청에서 트랜잭션 해시 추출
console.log(`[Transaction Request] Hash: ${transactionHash}`); // 로그에 트랜잭션 요청 해시 출력
try {
const transaction = await web3.eth.getTransaction(req.params.transactionHash); // 트랜잭션 정보 조회
// BigInt 처리를 위한 직렬화 함수와 함께 JSON으로 변환
const transactionString = JSON.stringify(transaction, serializeBigInt);
res.setHeader('Content-Type', 'application/json'); // 응답 헤더에 컨텐츠 타입 설정
res.send(transactionString); // 직렬화된 트랜잭션 정보를 응답으로 전송
} catch (error) {
console.error(error); // 에러 발생시 콘솔에 에러 출력
res.status(500).send(error.toString()); // 클라이언트에 500 상태 코드와 에러 메시지 전송
}
});
// 계정 주소를 이용해 계정 잔액을 조회하는 라우트
app.get('/balance/:accountAddress', async (req, res) => {
const accountAddress = req.params.accountAddress; // 요청에서 계정 주소 추출
console.log(`[Balance Request] Account address: ${accountAddress}`); // 로그에 계정 잔액 요청 주소 출력
try {
const balance = await web3.eth.getBalance(req.params.accountAddress); // 계정 잔액 조회
// BigInt 처리를 위한 직렬화 함수와 함께 JSON으로 변환
const balanceString = JSON.stringify({ balance }, serializeBigInt);
res.setHeader('Content-Type', 'application/json'); // 응답 헤더에 컨텐츠 타입 설정
res.send(balanceString); // 직렬화된 계정 잔액을 응답으로 전송
} catch (error) {
console.error(error); // 에러 발생시 콘솔에 에러 출력
res.status(500).send(error.toString()); // 클라이언트에 500 상태 코드와 에러 메시지 전송
}
});
// 현재 가스 가격을 조회하는 라우트
app.get('/gasPrice', async (req, res) => {
console.log(`[Gas Price Request] Request for current gas price`); // 로그에 현재 가스 가격 요청 출력
try {
const gasPrice = await web3.eth.getGasPrice(); // 현재 가스 가격 조회
// BigInt 처리를 위한 직렬화 함수와 함께 JSON으로 변환
const gasPriceString = JSON.stringify({ gasPrice }, serializeBigInt);
res.setHeader('Content-Type', 'application/json'); // 응답 헤더에 컨텐츠 타입 설정
res.send(gasPriceString); // 직렬화된 가스 가격을 응답으로 전송
} catch (error) {
console.error(error); // 에러 발생시 콘솔에 에러 출력
res.status(500).send(error.toString()); // 클라이언트에 500 상태 코드와 에러 메시지 전송
}
});
const PORT = 3000; // 서버가 리스닝할 포트 번호
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`); // 서버 시작시 로그에 실행 주소 출력
});
index.html
<!--index.html-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ethereum Block Explorer</title>
</head>
<body>
<h1>Ethereum Block Explorer</h1>
<input type="number" id="blockNumber" placeholder="Block Number" />
<button onclick="getBlock()">Get Block</button>
<br>
<input type="text" id="transactionHash" placeholder="Transaction Hash" />
<button onclick="getTransaction()">Get Transaction</button>
<br>
<input type="text" id="accountAddress" placeholder="Account Address" />
<button onclick="getBalance()">Get Balance</button>
<br>
<button onclick="getGasPrice()">Get Current Gas Price</button>
<br>
<pre id="result"></pre>
<script>
async function getBlock() {
// 입력 필드에서 블록 번호를 가져옴
const blockNumber = document.getElementById('blockNumber').value;
// 블록 번호가 입력되지 않았다면 경고 메시지 출력 후 함수 종료
if (!blockNumber) {
alert('Please enter a block number');
return;
}
try {
// 서버로부터 블록 정보를 조회하는 HTTP 요청
const response = await fetch(`/block/${blockNumber}`);
// HTTP 응답 본문을 텍스트로 읽음
const blockString = await response.text();
// 응답 텍스트를 JSON 객체로 파싱
const block = JSON.parse(blockString, (key, value) => {
// 문자열이 'n'으로 끝나면 BigInt로 변환
if (typeof value === 'string' && value.endsWith('n')) {
return BigInt(value.slice(0, -1));
}
return value;
});
// 블록 정보를 콘솔에 출력
console.log(" block : ");
console.log(block);
// 결과 영역에 블록 정보를 표시
document.getElementById('result').textContent = JSON.stringify(block, null, 2);
} catch (error) {
// 오류 발생 시 콘솔에 오류 메시지 출력 및 사용자에게 알림
console.error('Error fetching block:', error);
alert('Error fetching block. Check the console for more details.');
}
}
async function getTransaction() {
const transactionHash = document.getElementById('transactionHash').value;
if (!transactionHash) {
alert('Please enter a transaction hash');
return;
}
try {
const response = await fetch(`/transaction/${transactionHash}`);
const transaction = await response.json();
document.getElementById('result').textContent = JSON.stringify(transaction, null, 2);
} catch (error) {
console.error('Error fetching transaction:', error);
alert('Error fetching transaction. Check the console for more details.');
}
}
async function getBalance() {
const accountAddress = document.getElementById('accountAddress').value;
if (!accountAddress) {
alert('Please enter an account address');
return;
}
try {
const response = await fetch(`/balance/${accountAddress}`);
const balance = await response.json();
document.getElementById('result').textContent = `Balance: ${balance.balance}`;
} catch (error) {
console.error('Error fetching balance:', error);
alert('Error fetching balance. Check the console for more details.');
}
}
async function getGasPrice() {
try {
const response = await fetch('/gasPrice');
const gasPrice = await response.json();
document.getElementById('result').textContent = `Current Gas Price: ${gasPrice.gasPrice}`;
} catch (error) {
console.error('Error fetching gas price:', error);
alert('Error fetching gas price. Check the console for more details.');
}
}
</script>
</body>
</html>
package.json
{
"name": "js-search-block-info-ethereum",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"express": "^4.18.2",
"web3": "^4.2.1"
}
}
실행영상
트랜잭션 및 계정 조회 시 참고한 사이트
'JavaScript' 카테고리의 다른 글
[JavaScript] 블록 익스플로러에 비트코인 조회 기능 추가하기 (0) | 2024.01.09 |
---|---|
[JavaScript] DeepLink 사용해서 유튜브 앱 열기 (0) | 2024.01.06 |
[JavaScript] 이더리움 블록 조회하는 간단한 사이트 만들기 (0) | 2023.12.26 |
[JavaScript] Phaser 에서 마우스 클릭으로 캐릭터 이동하기 (0) | 2023.11.27 |
[JavaScript] ChatGPT API로 간단한 챗봇 만들기 (0) | 2023.11.17 |