메인 콘텐츠로 건너뛰기

Documentation Index

Fetch the complete documentation index at: https://docs.stablenet.network/llms.txt

Use this file to discover all available pages before exploring further.

WebSocket 구독과 로그 쿼리를 사용해 StableNet에서 새 블록과 컨트랙트 이벤트를 실시간으로 수신합니다.

배우는 내용

이 튜토리얼을 완료하면 다음을 할 수 있습니다:
  • WebSocket으로 새 블록 헤더 구독
  • 토픽 필터에 맞는 컨트랙트 이벤트 구독
  • eth_getLogs로 컨트랙트 과거 로그 조회

사전 준비

  • Node.js ≥ 18
  • npm install ethers (v6)
  • 이벤트를 발생시키는 배포된 컨트랙트 (예: Foundry로 배포하기WKRCPayment 컨트랙트)

WebSocket으로 연결

eth_subscribe는 지속적인 WebSocket 연결이 필요합니다. HTTP 엔드포인트는 구독을 지원하지 않습니다.
import { ethers } from "ethers";

const wsProvider = new ethers.WebSocketProvider(
  "wss://api.test.stablenet.network/ws"
);

새 블록 헤더 구독

새 블록이 생성될 때마다 헤더 이벤트가 발생합니다. 체인 진행 상황 추적이나 폴링 로직 트리거에 활용합니다.
wsProvider.on("block", async (blockNumber) => {
  const block = await wsProvider.getBlock(blockNumber);
  console.log(`Block ${block.number} — hash: ${block.hash}`);
});
Block 1234567 — hash: 0xabc...
Block 1234568 — hash: 0xdef...

컨트랙트 이벤트 구독

특정 컨트랙트의 이벤트를 수신하려면 컨트랙트의 ABI와 주소로 ethers.Contract 인스턴스를 생성합니다. 아래 예시는 WKRCPayment 컨트랙트의 Payment 이벤트를 구독합니다.
const CONTRACT_ADDRESS = "0xYourDeployedContract";
const ABI = [
  "event Payment(address indexed from, address indexed to, uint256 amount)"
];

const contract = new ethers.Contract(CONTRACT_ADDRESS, ABI, wsProvider);

contract.on("Payment", (from, to, amount, event) => {
  console.log(`Payment from ${from} to ${to}: ${ethers.formatEther(amount)} WKRC`);
  console.log(`  tx: ${event.log.transactionHash}`);
});
Payment from 0xSender to 0xRecipient: 1.0 WKRC
  tx: 0xabc...

토픽으로 이벤트 필터링

특정 발신자의 이벤트만 수신하려면 토픽 필터를 추가합니다. EVM 토픽 필터에서 null은 와일드카드입니다.
// 특정 주소가 보낸 결제만 수신
const filter = contract.filters.Payment("0xSpecificSender");
contract.on(filter, (from, to, amount) => {
  console.log(`Filtered payment: ${ethers.formatEther(amount)} WKRC`);
});

eth_getLogs로 과거 로그 조회

지속적인 연결 없이 과거 이벤트를 조회하려면 eth_getLogs를 사용합니다. 블록 범위와 토픽 필터를 지정합니다.
const httpProvider = new ethers.JsonRpcProvider(
  "https://api.test.stablenet.network"
);

const logs = await httpProvider.getLogs({
  address: CONTRACT_ADDRESS,
  fromBlock: 1200000,
  toBlock: "latest",
  topics: [
    ethers.id("Payment(address,address,uint256)")  // 이벤트 시그니처의 keccak256
  ],
});

for (const log of logs) {
  const parsed = contract.interface.parseLog(log);
  console.log(
    `Block ${log.blockNumber}: ${ethers.formatEther(parsed.args.amount)} WKRC`
  );
}
Block 1234500: 1.0 WKRC
Block 1234512: 0.5 WKRC

구독 정리

더 이상 필요하지 않을 때 이벤트 리스너를 제거해 메모리 누수를 방지합니다.
// 특정 리스너 제거
contract.off("Payment", listenerFunction);

// 이벤트의 모든 리스너 제거
contract.removeAllListeners("Payment");

// WebSocket 연결 종료
await wsProvider.destroy();

토픽 매칭 규칙

토픽은 indexed 이벤트 파라미터에 매핑됩니다. 한 위치에 여러 값을 지정하면 OR 조건, 값이 없는 위치는 와일드카드입니다.
위치의미
topics[0]이벤트 시그니처 해시 (항상 필수)
topics[1]첫 번째 indexed 파라미터 (from)
topics[2]두 번째 indexed 파라미터 (to)
어떤 위치든 null모든 값에 매칭
최대 4개의 토픽 위치를 지원합니다.

다음 단계

Foundry로 배포하기

이벤트를 발생시키는 컨트랙트를 배포합니다.

RPC API 레퍼런스

eth_subscribe, eth_getLogs, 필터 메서드 전체 레퍼런스.

온체인 데이터 읽기

잔액, 스토리지 슬롯, 컨트랙트 상태를 조회합니다.

수수료 위임

별도 계정이 사용자 대신 가스를 납부하게 합니다.