일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- nest.js설명
- git rebase
- chainlink 설명
- ethers
- 프록시배포구조
- 러스트 기초
- 스마트 컨트렉트 함수이름 중복
- ethers websocket
- 러스트 기초 학습
- 오블완
- 머신러닝기초
- 스마트컨트렉트 함수이름 중복 호출
- 러스트기초
- 스마트컨트렉트 예약어 함수이름 중복
- 체인의정석
- 컨트렉트 배포 자동화
- 스마트컨트렉트프록시
- vue기초
- ethers type
- ethers typescript
- Vue.js
- SBT표준
- 컨트렉트 동일한 함수이름 호출
- ethers v6
- 티스토리챌린지
- rust 기초
- 스마트컨트렉트테스트
- ambiguous function description
- Vue
- multicall
- Today
- Total
체인의정석
ethers v6 이벤트 구독하고 유지시키는 방법 정리 본문
이벤트 구독 로직의 경우 실제 테스트 환경까지 통과하더라도 이벤트 구독 로직을 오래 켜두면 RPC 엔드포인트 관련 문제가 발생할 수 있다. 이에 따른 대안은 2가지이다.
1. 웹소켓을 쓰고 ping, pong로직 구현 (웹소켓을 쓰는것이 좋다고는 하지만 웹소켓을 써봤자 지속적으로 살려주는 ping, pong 로직을 구현해주고 체크 또한 지속적으로 해주어야 한다.)
2. http 통신을 쓰고 문제가 생길때마다 재시작
1. 가장 좋은 케이스는 문제 없는 URC URL이 제공되며 풀 아카이브 노드 형태로 제공되는 형태 이 경우 일반적인 구독을 사용하더라도 문제가 없다. 이러한 경우 아래와 같이 사용하면 끝난다.
Contract.on("ReceiveMessage", async (...args) => {
await handleReceiveMessageA(...args);
});
// ..args 을 받아오는 함수의 경우
const handleReceiveMessageA = async (caller, uri, params, deadline, event) => {}
그러나 여태까지 경험상 대다수의 회사에서는 이런게 제공되거나 테스트 기간내에 결제를 마치고 사용가능한 경우가 없으며, 자체적인 체인을 운영하는 측에서 엔드포인트 1개가 먹통이라면 시스템이 다운되는 경우도 존재한다. 특히 몇 달전 evm 체인에서 인스크립션의 비문등을 사용하면서 서비스가 다운되는것도 경험했었다. 이러한 경우를 대비해 실서비스에서는 rpc endpoint를 여러개 두고 문제가 생길 경우 바꿔가며 사용하는 식의 이벤트 구독 장치가 필요하다. 그러나 rpc endpoint 오류가 발생할 경우 에러발생을 잡는것 부터 오류가 다양하여 쉽지가 않다.
rpc 관련 오류의 경우 정말 다양한 오류가 발생하며 예측이 어렵운데 과거 부터 내가 많이 사용했던 방식으로는 provider를 새로 세팅해주는 방식이였다. 주기적으로 provider를 새로 새팅해주는것이 내가 생각한 가장 효과적인 해결 방식이다. 이를 위해서 A처럼 주기적으로 endpoint를 바꿔주거나 B처럼 오류가 발생했을 때 endpoint를 바꿔주는 방식을 선택할 수 있다.
사실 해당 부분은 endpoint를 제공하는 노드 업체에 따라서 어떤 방식을 사용하는게 좋을지가 정해지기 때문에 네트워크 및 업체의 응답값을 보고 정해야 한다.
이에 따라 서브로 엔드포인트를 여러개 받아두고 주기적/에러가 났을 때으로 다른 엔드포인트를 사용하는 식으로 오류에 대응을 해두어야 한다. 그러나 이렇게 인터벌을 두고 사용하거나 오류가 생겼을 때 다른 엔드포인트를 바꿀 경우에는 미리 생성된 이벤트 구독 개체를 제대로 지우지 않는다면, 이전에 구독하던 이벤트 봇이 작동해서 같은 블록상에 여러개의 트랜잭션을 쏘는 문제가 발생한다. 따라서 성공한 트랜잭션과 revert 트랜잭션이 같이 찍히는 문제점이 발생한다.
이에 따라 엔드포인트를 바꾸어 주면서, 초기화 까지 시켜야한다.
이때 몇가지 ethers 함수를 사용하였다.
먼저 removeAllListners 이다. 따라서 주기적으로 endpoint를 바꿀 때마다 eventlistner를 명시적으로 제거하는 방법이 존재한다.
await contract.removeAllListeners("ReceiveMessage");
https://docs.ethers.org/v6/api/contract/#BaseContract-removeAllListeners
두번째 사용가능한 방식은 once 이다.
일반적인 이벤트 구독은 Contract.on 으로 진행하지만 ethers v6기준 .once를 사용하면 이벤트가 한번 발생하고 구독을 끝낸다.
따라서 아래와 같이 구독하게 된다면 이벤트가 발생할 때마다 재설정을 다시해주게 된다.
Contract.once("SendMessage", async (...args) => {
await handleSendMessageB(...args);
await metaLane721A.removeAllListeners("ReceiveMessage");
Contract.once("SendMessage", handleSendMessageB);
});
https://docs.ethers.org/v6/api/contract/#BaseContract-once
또한 초기화 하고 다시 돌릴경우에는 delete를 써서 provider, contract, wallet과 같이 관련된 객체들을 삭제해주고 돌려야한다.
이에 따라 2가지 방식으로 이벤트 구독 봇을 재시작 할 수 있다.
1번안. 이벤트가 중복해서 잡히지 않도록 오류가 잡힐 경우 delete를 써서 객체를 제거해주고 난 후 에러를 발생시켜서 pm2 가 재시작 하도록 한다.
2번안. 오류가 잡힌다면 오류가 발생할 경우 rpc_url을 바꾸어 다시 실행하는 형태를 취할 수 있다.
'블록체인 > Ethers & web3' 카테고리의 다른 글
hardhat gas reporter 외부 설치 없이 사용하기 (0) | 2024.08.02 |
---|---|
ethers & websocket & http로 이벤트 구독 및 크로스체인 트랜잭션 실행, 트랜잭션 정보값 뽑아내기 (0) | 2024.07.18 |
ethers v5 -> v6 문법 (0) | 2024.04.15 |
ethers 6버전 이상에서 ethers.utils가 인식이 안되는 에러 (0) | 2023.12.24 |
hardhat, ethers 의 ProviderError: HttpProviderError (0) | 2023.07.21 |