일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- 스마트컨트렉트테스트
- multicall
- 오블완
- Vue
- ethers type
- 스마트컨트렉트 예약어 함수이름 중복
- nest.js설명
- 스마트컨트렉트 함수이름 중복 호출
- 러스트기초
- vue기초
- 러스트 기초 학습
- Vue.js
- 스마트컨트렉트프록시
- ethers
- ethers v6
- ethers typescript
- rust 기초
- 체인의정석
- 스마트 컨트렉트 함수이름 중복
- 컨트렉트 동일한 함수이름 호출
- chainlink 설명
- git rebase
- 러스트 기초
- 컨트렉트 배포 자동화
- 프록시배포구조
- 티스토리챌린지
- SBT표준
- ethers websocket
- 머신러닝기초
- ambiguous function description
Archives
- Today
- Total
체인의정석
ethers & websocket 참고 예제 본문
728x90
반응형
https://github.com/ethers-io/ethers.js/issues/1053
해당 링크에서는 지속적으로 코드가 업데이트 되고 있기 때문에 버전이 바뀜에 따라서 위의 링크를 계속해서 참고해서 만들면 될 것 같다.
const EXPECTED_PONG_BACK = 15000
const KEEP_ALIVE_CHECK_INTERVAL = 7500
export const startConnection = () => {
provider = new ethers.providers.WebSocketProvider(config.ETH_NODE_WSS)
let pingTimeout = null
let keepAliveInterval = null
provider._websocket.on('open', () => {
keepAliveInterval = setInterval(() => {
logger.debug('Checking if the connection is alive, sending a ping')
provider._websocket.ping()
// Use `WebSocket#terminate()`, which immediately destroys the connection,
// instead of `WebSocket#close()`, which waits for the close timer.
// Delay should be equal to the interval at which your server
// sends out pings plus a conservative assumption of the latency.
pingTimeout = setTimeout(() => {
provider._websocket.terminate()
}, EXPECTED_PONG_BACK)
}, KEEP_ALIVE_CHECK_INTERVAL)
// TODO: handle contract listeners setup + indexing
})
provider._websocket.on('close', () => {
logger.error('The websocket connection was closed')
clearInterval(keepAliveInterval)
clearTimeout(pingTimeout)
startConnection()
})
provider._websocket.on('pong', () => {
logger.debug('Received pong, so connection is alive, clearing the timeout')
clearInterval(pingTimeout)
})
}
websocket 웹소켓이 ping을 날리고 응답이 없을 시에는 웹소켓을 죽이고. 웹소켓이 죽을 경우 interval과 timeout을 초기화 한 후에 다시 connection을 만든다. ping을 날리고 응답이 있다면 pong에 걸리기 때문에 clearInterval을 해준 후에 다음 호출을 또 기다리게 된다. 이런 식으로 지속적으로 ping과 pong을 만들어 주어야 웹소켓을 사용할 수 있다.
해당 정보는
ethers.providers.WebSocketProvider;
해당 provider로 부터 얻을 수 있다.
최신 버전의 경우 다음과 같은 예제가 있었다.
import { Networkish, WebSocketProvider } from "ethers";
import WebSocket from "ws";
const EXPECTED_PONG_BACK = 15000;
const KEEP_ALIVE_CHECK_INTERVAL = 60 * 1000; //7500;
const debug = (message: string) => {
console.debug(new Date().toISOString(), message);
};
export const ResilientWebsocket = (
url: string,
network: Networkish,
task: (provider: WebSocketProvider) => void
) => {
let terminate = false;
let pingTimeout: NodeJS.Timeout | null = null;
let keepAliveInterval: NodeJS.Timeout | null = null;
let ws: WebSocket | null;
const sleep = (ms: number) =>
new Promise((resolve) => setTimeout(resolve, ms));
const startConnection = () => {
ws = new WebSocket(url);
ws.on("open", async () => {
keepAliveInterval = setInterval(() => {
if (!ws) {
debug("No websocket, exiting keep alive interval");
return;
}
debug("Checking if the connection is alive, sending a ping");
ws.ping();
// Use `WebSocket#terminate()`, which immediately destroys the connection,
// instead of `WebSocket#close()`, which waits for the close timer.
// Delay should be equal to the interval at which your server
// sends out pings plus a conservative assumption of the latency.
pingTimeout = setTimeout(() => {
if (ws) ws.terminate();
}, EXPECTED_PONG_BACK);
}, KEEP_ALIVE_CHECK_INTERVAL);
const wsp = new WebSocketProvider(() => ws!, network);
while (ws?.readyState !== WebSocket.OPEN) {
debug("Waiting for websocket to be open");
await sleep(1000);
}
wsp._start();
while (!wsp.ready) {
debug("Waiting for websocket provider to be ready");
await sleep(1000);
}
task(wsp);
});
ws.on("close", () => {
console.error("The websocket connection was closed");
if (keepAliveInterval) clearInterval(keepAliveInterval);
if (pingTimeout) clearTimeout(pingTimeout);
if (!terminate) startConnection();
});
ws.on("pong", () => {
debug("Received pong, so connection is alive, clearing the timeout");
if (pingTimeout) clearInterval(pingTimeout);
});
return ws;
};
startConnection();
return () => {
terminate = true;
if (keepAliveInterval) clearInterval(keepAliveInterval);
if (pingTimeout) clearTimeout(pingTimeout);
if (ws) {
ws.removeAllListeners();
ws.terminate();
}
};
};
참고로 아래 예제 또한 매우 잘 되어 있엇다.
const { ethers } = require('ethers')
const url = 'wss://bsc.nownodes.io/wss/YOUR_API_KEY'
const EXPECTED_PONG_BACK = 15000
const KEEP_ALIVE_CHECK_INTERVAL = 7500
const startConnection = async () => {
const provider = new ethers.providers.WebSocketProvider(url, {
name: 'binance',
chainId: 56,
})
let pingTimeout = null
let keepAliveInterval = null
provider._websocket.on('open', () => {
console.log('Connect')
keepAliveInterval = setInterval(() => {
console.log('Checking if the connection is alive, sending a ping')
provider._websocket.ping()
// Use WebSocket#terminate(), which immediately destroys the connection,
// instead of WebSocket#close(), which waits for the close timer.
// Delay should be equal to the interval at which your server
// sends out pings plus a conservative assumption of the latency.
pingTimeout = setTimeout(() => {
provider._websocket.terminate()
}, EXPECTED_PONG_BACK)
}, KEEP_ALIVE_CHECK_INTERVAL)
})
provider._websocket.on('close', () => {
console.error('The websocket connection was closed')
clearInterval(keepAliveInterval)
clearTimeout(pingTimeout)
startConnection()
})
provider._websocket.on('pong', () => {
console.log('Received pong, so connection is alive, clearing the timeout')
clearInterval(pingTimeout)
})
provider.on('block',(block)=>{
console.log('New block!', block)
})
}
startConnection()
728x90
반응형
'개발 > backend' 카테고리의 다른 글
mac에서 Jmeter 설치 및 사용해서 api 테스트해보기 (0) | 2024.02.13 |
---|---|
nestjs-telegraf 사용해보기 (Nest.js 텔레그램봇) (0) | 2023.11.27 |
Nest.js 기본 구조 공부(기본 구조, Controller, Provider, Moudule) (1) | 2023.11.24 |
Bignumber.js 사용하여 데이터 처리하기 (0) | 2023.08.25 |
UniswapV3 백엔드 구축하며, 틱 단위 계산에 사용한 다시 볼 것 같은 함수들 정리 (tickSpace 맞추기, 데이터 쌓는 지점 체크 & 동일 블록에서의 값 합산, Promise.all의 중첩 사용) (0) | 2023.08.24 |
Comments