5분 안에 Ethereum 가스 추적기를 구축하는 방법 이해

소개하다
보조 제목
소개하다
2021년 8월 런던 하드포크는 이더리움 네트워크 역사상 가장 큰 업그레이드를 가져왔습니다. 포크는 EIP-1559를 구현하며 블라인드 경매 모델보다 우수하다고 선전되는 가스 가격 메커니즘입니다. 또한 이더리움(ETH) 통화 정책의 근본적인 변화를 도입하여 적어도 단기적으로는 디플레이션 통화로 만듭니다.
이 튜토리얼에서는 EIP-1559의 두 가지 새로운 가스 요금 구성 요소와 마지막 20개 블록에 대한 기타 통계(예: 블록 크기)를 추적하는 가스 추적기를 구축합니다. 이렇게 함으로써 우리는 두 가지 중요한 목표를 달성할 것입니다.
EIP-1559의 작동 방식과 개선 사항에 대해 자세히 알아보십시오.
기본 및 우선 수수료로 분류된 최신 블록 볼륨 및 가스 수수료를 검색하는 모든 기능을 갖춘 가스 추적 애플리케이션입니다.
이를 위해 Alchemy, Alchemy web3.js 라이브러리, Node 및 React를 사용합니다. 이 단어가 낯설게 들리더라도 걱정하지 마세요. 자세하게 다룰 것입니다!
이 튜토리얼은 독자가 이더리움에서 가스 및 가스 가격이 어떻게 작동하는지에 대한 기본적인 이해가 있다고 가정합니다. EIP-1559에 대한 사전 이해도 도움이 되지만 필수는 아닙니다.
EIP-1559 빠른 검토
EIP-1559는 이더리움의 가스 가격 책정 메커니즘에 다음과 같은 변경 사항을 가져옵니다.
블라인드 경매 가스 수수료는 이제 기본 수수료와 우선 수수료(또는 채굴자 팁)의 두 가지 수수료로 대체됩니다.
기본 요금은 네트워크에 의해 자동으로 결정됩니다. 이전 블록이 가득 차 있었다면 12.5%로 증가하고 이전 블록이 비어 있었다면 12.5%로 감소할 수 있습니다.
채굴자의 팁은 사용자가 결정하며 거래의 긴급성에 따라 조정할 수 있습니다.
채굴자들이 블록을 인위적으로 넘치게 하는 것을 방지하기 위해 기본 수수료는 네트워크에 의해 소각됩니다. 그러나 광부는 팁을 주머니에 넣을 수 있습니다.
가스 가격을 개선하는 것 외에도 EIP-1559는 갑작스러운 트래픽 급증을 처리하기 위해 네트워크를 더 잘 갖추기 위한 개선 사항도 제안합니다. 아시다시피 Ethereum의 트랜잭션은 블록으로 그룹화됩니다. 포크 이전에는 블록이 트래픽에 관계없이 1,500만 개의 가스 트랜잭션만 보유할 수 있었습니다.
업그레이드를 통해 블록 크기 상한선이 3천만 가스로 두 배가 되었습니다. 이는 수요 증가 기간에 더 잘 대응하기 위해 수행됩니다. 그러나 기본 요금은 블록 볼륨(또는 블록에서 사용하는 가스)의 평균 50% 또는 약 1,500만 가스로 조정될 것으로 예상됩니다.
우리가 만든 가스 추적기로 이 모든 것이 실시간으로 어떻게 작동하는지 확인할 수 있습니다. 우리는 이 프로젝트를 두 부분으로 만들 것입니다. 첫 번째 부분에서는 거래 수수료 내역을 실시간으로 추적하는 노드 스크립트를 작성합니다. 두 번째 부분에서는 이 스크립트를 활용하여 최종 추적기를 빌드하는 React 애플리케이션을 생성합니다.
파트 1: 거래 수수료 내역 스크립트

이 섹션에서는 이더리움 네트워크의 마지막 20개 블록에 대한 가스 수수료 내역을 얻을 수 있는 스크립트(노드에서)를 작성합니다.
0단계: 노드 및 npm 설치
로컬 시스템에 node 및 npm(최소 v14 이상)이 설치되어 있는지 확인하십시오.
1단계: 연금술 계정 만들기

블록에 대한 최신 가스 수수료 내역을 얻으려면 통신을 위해 이더리움 네트워크에 연결해야 합니다. Alchemy는 자체 노드를 시작하지 않고도 이를 수행할 수 있는 블록체인 개발 플랫폼입니다.

2단계: Alchemy 애플리케이션(및 API 키) 생성
Alchemy 대시보드에서 애플리케이션을 생성합니다. 체인은 이더리움으로 설정되고 네트워크는 메인넷으로 설정됩니다.
그런 다음 애플리케이션 페이지를 방문하여 키 보기를 클릭합니다. 애플리케이션의 HTTP 및 Websocket URL이 있는 팝업이 열립니다. 이 자습서에서는 Websocket URL을 사용합니다.
3단계: 노드 프로젝트 생성 및 종속 항목 설치
> mkdir gas-tracker-script && cd gas-tracker-script > npm init -y > npm install --save @alch/alchemy-web3 > touch main.js
이제 노드 스크립트 작성을 시작할 수 있습니다. 빈 저장소를 만들고 종속성을 설치해 보겠습니다. 이 스크립트에는 Alchemy web3.js 라이브러리가 필요합니다.
터미널(또는 명령 프롬프트)에서 다음 명령을 실행합니다.
이렇게 하면 필요한 모든 파일과 종속성이 포함된 gas tracker-script라는 리포지토리가 생성됩니다. 선호하는 코드 편집기에서 이 리포지토리를 엽니다. main.js 파일에 모든 코드를 작성할 것입니다.
4단계: Alchemy로 web3 클라이언트 인스턴스 생성
const { createAlchemyWeb3 } = require("@alch/alchemy-web3");// Using WebSockets
const web3 = createAlchemyWeb3(
"wss://eth-mainnet.alchemyapi.io/v2/<--API KEY-->",
);
Alchemy web3로 클라이언트 인스턴스를 생성하는 것은 매우 간단합니다.
main.js 파일에서 다음 코드 줄을 추가합니다.
위의 자리 표시자를 애플리케이션의 websocket URL로 바꾸십시오.
5단계: 최근 20개 블록의 기록 가져오기
마지막 10개 블록의 가스 비용 내역을 원합니다. 관심 있는 데이터에는 기본 수수료, 선호 수수료 범위, 블록 크기 및 블록 번호가 포함됩니다.
다행스럽게도 Alchemy에는 앞서 언급한 모든 데이터를 자동으로 반환하는 매우 편리한 eth_feeHistory가 있습니다.
web3.eth.getFeeHistory(20, "latest", [25, 50, 75]).then(console.log)
우리가 지정해야 하는 것은 데이터를 원하는 가장 최근 블록, 확인할 총 블록 수, 선호 수수료의 백분율 범위입니다.

가장 최근의 20개 블록과 우선 순위 수수료의 25번째, 50번째 및 75번째 백분위수에 관심이 있습니다.
이 스크립트를 실행하면(node main.js 사용) 찾고 있는 데이터를 가져와야 합니다. 다음은 5개의 데이터 블록을 요청한 후 받은 결과입니다.
6단계: 출력 포맷
const formatOutput = (data, numBlocks) => { let blocks = []
for (let i = 0; i < numBlocks; i++) {
blocks.push({
blockNumber: Number(data.oldestBlock) + i,
reward: data.reward[i].map(r => Math.round(Number(r) / 10 ** 9)),
baseFeePerGas: Math.round(Number(data.baseFeePerGas[i]) / 10 ** 9),
gasUsedRatio: data.gasUsedRatio[i],
})
}
return blocks;
5단계에서 받은 출력은 정확했지만 가독성이 좋지 않았습니다. 수수료는 16진수로 표현되며 데이터 구조상 어떤 데이터가 어떤 블록에 해당하는지 파악하기 어렵습니다.
const numBlocks = 5;web3.eth.getFeeHistory(numBlocks, "latest", [25, 50, 75]).then((data) => {
const blocks = formatOutput(data, numBlocks);
console.log(blocks);
});
원시 데이터를 사전 목록으로 변환하는 작은 함수를 작성해 보겠습니다. 각 사전에는 특정 블록의 데이터가 포함됩니다. 이 함수는 또한 wei로 표현되는 모든 16진수 가스 값을 Gwei로 표현되는 십진수로 변환합니다.

마지막으로 이 함수를 feeHistory로 사용합시다.
이 버전의 스크립트를 실행하면 다음 형식의 출력이 생성됩니다.
7단계: 최신 블록 헤더 구독
let subscription = web3.eth.subscribe('newBlockHeaders');subscription.on("data", () => {
web3.eth.getFeeHistory(numBlocks, "latest", [25, 50, 75]).then((data) => {
const blocks = formatOutput(data, numBlocks);
console.log(blocks);
});
});
약 15초마다 새 블록이 이더리움 블록체인에 추가됩니다. 따라서 이상적으로는 추가되는 블록에 대한 이벤트를 구독하고 트랜잭션 기록을 업데이트하여 항상 마지막 20개 블록의 데이터를 표시하려고 합니다.
구독 이벤트 콜백 내에 getFeeHistory 함수를 중첩시키겠습니다.

이제 main.js 스크립트를 실행하면 약 15초마다 최신 데이터 배치가 출력됩니다. 여기까지 오셨다면 축하합니다! 이제 완전한 기능을 갖춘 가스 추적기를 갖게 된 것입니다.
2부: 리액트 애플리케이션
이전 섹션에서는 Ethereum 메인넷에 새 블록이 추가될 때마다 마지막 20개 블록에 대한 수수료 내역을 검색하는 스크립트를 작성했습니다.
이 섹션에서는 이 데이터를 터미널에서 브라우저로 스트리밍하는 작은 React 애플리케이션을 빌드합니다. 수수료 거래 내역 외에도 지난 20개 블록의 평균 가스 수수료와 블록 크기도 표시됩니다.
> npx create-react-app gas-tracker-frontend > cd gas-tracker-frontend
1단계: React 프로젝트 초기화 및 종속성 설치
> npm install --save @alch/alchemy-web3
다음 명령을 실행합니다.
이렇게 하면 샘플 React 프로젝트가 생성됩니다. 반응 종속성 외에도 이전 섹션에서 Alchemy web3 라이브러리를 설치해야 합니다.
import './App.css';
import { useEffect, useState } from 'react';
import { createAlchemyWeb3 } from '@alch/alchemy-web3';const NUM_BLOCKS = 20;function App() { const [blockHistory, setBlockHistory] = useState(null);
const [avgGas, setAvgGas] = useState(null);
const [avgBlockVolume, setAvgBlockVolume] = useState(null); const formatOutput = (data) => { let avgGasFee = 0;
let avgFill = 0;
let blocks = []; for (let i = 0; i < NUM_BLOCKS; i++) { avgGasFee = avgGasFee + Number(data.reward[i][1]) + Number(data.baseFeePerGas[i])
avgFill = avgFill + Math.round(data.gasUsedRatio[i] * 100); blocks.push({
blockNumber: Number(data.oldestBlock) + i,
reward: data.reward[i].map(r => Math.round(Number(r) / 10 ** 9)),
baseFeePerGas: Math.round(Number(data.baseFeePerGas[i]) / 10 ** 9),
gasUsedRatio: Math.round(data.gasUsedRatio[i] * 100),
})
} avgGasFee = avgGasFee / NUM_BLOCKS;
avgGasFee = Math.round(avgGasFee / 10 ** 9) avgFill = avgFill / NUM_BLOCKS;
return [blocks, avgGasFee, avgFill];
} useEffect(() => { const web3 = createAlchemyWeb3(
"wss://eth-mainnet.alchemyapi.io/v2/<--API KEY-->",
); let subscription = web3.eth.subscribe('newBlockHeaders'); subscription.on('data', () => {
web3.eth.getFeeHistory(NUM_BLOCKS, "latest", [25, 50, 75]).then((feeHistory) => {
const [blocks, avgGasFee, avgFill] = formatOutput(feeHistory, NUM_BLOCKS);
setBlockHistory(blocks);
setAvgGas(avgGasFee);
setAvgBlockVolume(avgFill);
});
}); return () => {
web3.eth.clearSubscriptions();
}
}, [])
return (
EIP-1559 Gas Tracker
{!blockHistory &&
Data is loading...
}{avgGas && avgBlockVolume &&
{avgGas} Gwei | {avgBlockVolume}% Volume
}{blockHistory &&
| Block Number | Base Fee | Reward (25%) | Reward (50%) | Reward (75%) | Gas Used |
|---|---|---|---|---|---|
| {block.blockNumber} | {block.baseFeePerGas} | {block.reward[0]} | {block.reward[1]} | {block.reward[2]} | {block.gasUsedRatio}% |
);
}export default App;
2단계: App.js 파일 채우기
모든 로직은 App.js 파일에 있습니다. 위 파일에 다음 내용을 복사합니다.
이것은 React 과정이 아니기 때문에 React 관련 부분을 자세히 다루지 않을 것입니다. 그러나 스크립트에서 수행한 대로 비용 내역을 검색하고 HTML 테이블로 출력하는 것이 우리가 하는 일이라고는 관찰할 수 있어야 합니다.
우리가 사용하는 유일한 추가 논리는 평균 가스 가격과 20개 블록에 대한 평균 블록 크기를 계산하는 것인데 이는 사소한 작업입니다.
.main-container {
text-align: center;
}table {
border-collapse: collapse;
margin: 20px auto;
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2);
}thead {
background: linear-gradient(267.45deg,#05d5ff -34.23%,#53f 99.39%);
color: white;
padding: 10px;
}th {
font-size: 18px;
padding: 15px;}tbody > tr {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
margin: 0px;
padding: 15px;
}td {
padding: 6px;
}.gas {
color: #4299E1;
}.vol {
color: #4C51BF;
(선택 사항) 3단계: 일부 스타일 추가
다음과 같이 App.css 파일에 몇 가지 기본 스타일을 추가할 수 있습니다.
npm start
4단계: localhost에 애플리케이션 배포

앱은 다음과 같이 표시됩니다.
분석하다
축하합니다! 완전한 기능을 갖춘 가스 추적 애플리케이션을 갖게 되었습니다.
분석하다
돌아가서 위의 데이터를 분석해 보겠습니다. 다음은 우리가 관찰할 수 있는 EIP-1559 구현의 직접적인 결과입니다.
기본 요금은 블록마다 크게 변동하지 않습니다. 실제로 가장 큰 증가 또는 감소는 12.5%였습니다.
블록 크기는 변동하는 경향이 있지만 평균 블록 크기는 약 50%입니다.
결론적으로
데이터는 가스 비용이 이 모델에서 훨씬 더 예측 가능하다는 것을 나타내는 것 같습니다. 모든 사람이 동일한 기본 수수료와 우선 수수료를 지불하고 대부분의 경우 우선 수수료는 총 수수료의 작은 부분에 불과하기 때문에 대부분의 거래는 가스에 대해 터무니없이 많은 비용을 지불하지 않습니다. 따라서 이 샘플 데이터는 EIP-1559가 보다 예측 가능한 가스 가격, 가스 초과 지불 감소라는 목표를 성공적으로 달성했음을 보여줍니다.
이 문서에서 많은 내용을 다루었습니다. 처음부터 EIP-1559에 대한 가스 추적기를 구축함으로써 이더리움 거래에 가져오는 개선 사항을 이해하고 감사할 수 있기를 바랍니다.


