바오밥 웹소켓 연결 정책질문

안녕하세요, 간단한 프로젝트 진행중에 바오밥 네트워크에 웹소켓으로 연결해서 이벤트 발송되는걸 받아오고 있습니다.
서버에서 이벤트를 받으면 다시 클라이언트로 던져주려고 하는데, 서버 실행하고 한두번은 잘 받아오다 그이후로는 이벤트를 전혀 받아오질 못합니다. 서버는 Express로 구성하였으며 Subscribe부분은 모듈화해서

const app = express();
subscribe();

형식으로 서버실행될때 실행되도록 했습니다.

subscribe()함수 내용은

const caver = new Caver(WS_PROVIDER, { reconnect: { auto: true } });

CONTRACT.events ....

로 되어있습니다
서버실행하고 초기에는 CONTRACT.events 로 구독하는 이벤트를 잘 받아오더니
두세번 받아오면 더이상 이벤트를 받아오질 않습니다
서버는 히로쿠에 미국서버에 배포되어 있습니다.
혹시 이것과 관련이 있을까요?

안녕하세요

제생각에 서버위치와는 무관할것으로 보여지네요…
처음 몇번은 받아오는걸로 봐서는 연결에 문제는 없어보이는데요 다른 원인이 있을거같아요
혹시 테스트해볼수 있는 코드 snippet을 주실 수 있나요?

1 Like
const express = require("express");
const Caver = require("caver-js");

const cors = require("cors");
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");

const app = express();

const debateABI =
  require("../Project-Agora_server/truffle/build/contracts/Debate.json").abi;
const erc1155ABI =
  require("../Project-Agora_server/truffle/build/contracts/AgoraTokens.json").abi;
const { WS_PROVIDER, ERC1155_ADDRESS } = {
  WS_PROVIDER: "wss://public-node-api.klaytnapi.com/v1/baobab/ws",
  ERC1155_ADDRESS: "0x65E117F5e8E803aF2054BF750F636D168711Bf35",
};
let num = 0;
console.log(ERC1155_ADDRESS);
const caver = new Caver(WS_PROVIDER, { reconnect: { auto: true } });

const ERC1155Contract = new caver.contract(erc1155ABI, ERC1155_ADDRESS);

ERC1155Contract.events.UserNFTFail(async (err, event) => {
  if (!err) {
    num++;

    console.log(num, event);
  } else console.log(err);
  return;
});
ERC1155Contract.events.UserNFTBuy(async (err, event) => {
  if (!err) {
    num++;

    console.log(num, event);
  } else console.log(err);
  return;
});

app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(
  cors({
    origin: true,
    credentials: true,
    methods: ["GET", "POST", "PUT", "DELETE"],
  })
);

app.get("/", (req, res) => {
  res.send("HI");
});

app.listen(8888, () => {
  console.log("Server Started");
});

다음과같이 event subscribe 부분은 간단히 익스프레스 앱에 같이 붙여 넣었습니다
로컬에서 node 나 nodemon 으로 실행시킬때는 잘 받아오는데
Pm2로 실행시키니 이벤트를 3개정도 받아오고 그 뒤론 받아오질 못합니다.

const express = require("express");
const Caver = require("caver-js");

const cors = require("cors");
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");

const app = express();

const debateABI =
  require("../Project-Agora_server/truffle/build/contracts/Debate.json").abi;
const erc1155ABI =
  require("../Project-Agora_server/truffle/build/contracts/AgoraTokens.json").abi;
const { WS_PROVIDER, ERC1155_ADDRESS } = {
  WS_PROVIDER: "wss://public-node-api.klaytnapi.com/v1/baobab/ws",
  ERC1155_ADDRESS: "0x65E117F5e8E803aF2054BF750F636D168711Bf35",
};
let num = 0;
console.log(ERC1155_ADDRESS);
const caver = new Caver(WS_PROVIDER, { reconnect: { auto: true } });

const ERC1155Contract = new caver.contract(erc1155ABI, ERC1155_ADDRESS);

ERC1155Contract.events.UserNFTFail(async (err, event) => {
  if (!err) {
    num++;

    console.log(num, event);
  } else console.log(err);
  return;
});
ERC1155Contract.events.UserNFTBuy(async (err, event) => {
  if (!err) {
    num++;

    console.log(num, event);
  } else console.log(err);
  return;
});

app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(
  cors({
    origin: true,
    credentials: true,
    methods: ["GET", "POST", "PUT", "DELETE"],
  })
);

app.get("/", (req, res) => {
  res.send("HI");
});

app.listen(8888, () => {
  console.log("Server Started");
});

다음과같이 간단한 express 앱에 이벤트 서브스크라이브를 통해 받아온 정보로 특정 동작을 하게 만들었습니다.
배포를 하지 않고도 로컬에서 node, nodemon으로 실행시킬때는 잘 받아오는데
pm2로 실행시키면 이벤트 세개쯤을 받아온 뒤 더이상 받아오질 않습니다.
Pm2로는 fork 모드로 실행시켰습니다.

주신 코드를 기반으로 제가 해보았을때는 잘되는거같습니다…
abi를 혹시 전달해주실수 있나요? 여기에 올려주셔도되고, 부담스러우시다면 dm으로 보내주셔도 좋습니다.

제가 다르게 한 점은, wss://public-node-api.klaytnapi.com/v1/baobab/ws => ws://public-node-api.klaytnapi.com/v1/baobab/ 이 부분이네요.

1 Like

안녕하세요.
제가 생각할때에는 메시지가 몇번 주고 받는건 잘되신다고 하셨으니 혹시 주기적으로 블록넘버를 받아오는걸 따로 돌아가게 해두면 되지 않을가 싶습니다…?

웹소켓에서 연결하고 지속적인 연결유지가 되려면 1분인가… 몇초동안 메시지가 오고가지 않는다면 자동으로 끊어지게 되어있어요.

인터벌로 연결된 웹소켓으로 40초? 정도 간격으로 블록넘버라도 호출하게 해주시면 못받아오는 현상이 없어지지 않을가 싶습니다.

3 Likes
  "abi": [
    {
      "inputs": [],
      "stateMutability": "nonpayable",
      "type": "constructor"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "operator",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "bool",
          "name": "approved",
          "type": "bool"
        }
      ],
      "name": "ApprovalForAll",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address[]",
          "name": "fromArr",
          "type": "address[]"
        },
        {
          "indexed": false,
          "internalType": "uint256[]",
          "name": "amount",
          "type": "uint256[]"
        }
      ],
      "name": "BurnedToken",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "tokenId",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "price",
          "type": "uint256"
        }
      ],
      "name": "MintedNFT",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address[]",
          "name": "toArr",
          "type": "address[]"
        },
        {
          "indexed": false,
          "internalType": "uint256[]",
          "name": "amount",
          "type": "uint256[]"
        }
      ],
      "name": "MintedToken",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "previousOwner",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "newOwner",
          "type": "address"
        }
      ],
      "name": "OwnershipTransferred",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "operator",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "from",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "to",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256[]",
          "name": "ids",
          "type": "uint256[]"
        },
        {
          "indexed": false,
          "internalType": "uint256[]",
          "name": "values",
          "type": "uint256[]"
        }
      ],
      "name": "TransferBatch",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "operator",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "from",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "to",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "id",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "value",
          "type": "uint256"
        }
      ],
      "name": "TransferSingle",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "string",
          "name": "value",
          "type": "string"
        },
        {
          "indexed": true,
          "internalType": "uint256",
          "name": "id",
          "type": "uint256"
        }
      ],
      "name": "URI",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "buyer",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "tokenId",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "price",
          "type": "uint256"
        }
      ],
      "name": "UserNFTBuy",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "buyer",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "tokenId",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "price",
          "type": "uint256"
        }
      ],
      "name": "UserNFTFail",
      "type": "event"
    },
    {
      "inputs": [],
      "name": "AgoraToken",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "id",
          "type": "uint256"
        }
      ],
      "name": "balanceOf",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address[]",
          "name": "accounts",
          "type": "address[]"
        },
        {
          "internalType": "uint256[]",
          "name": "ids",
          "type": "uint256[]"
        }
      ],
      "name": "balanceOfBatch",
      "outputs": [
        {
          "internalType": "uint256[]",
          "name": "",
          "type": "uint256[]"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "operator",
          "type": "address"
        }
      ],
      "name": "isApprovedForAll",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "owner",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "renounceOwnership",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "from",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "to",
          "type": "address"
        },
        {
          "internalType": "uint256[]",
          "name": "ids",
          "type": "uint256[]"
        },
        {
          "internalType": "uint256[]",
          "name": "amounts",
          "type": "uint256[]"
        },
        {
          "internalType": "bytes",
          "name": "data",
          "type": "bytes"
        }
      ],
      "name": "safeBatchTransferFrom",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "from",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "to",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "id",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        },
        {
          "internalType": "bytes",
          "name": "data",
          "type": "bytes"
        }
      ],
      "name": "safeTransferFrom",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "operator",
          "type": "address"
        },
        {
          "internalType": "bool",
          "name": "approved",
          "type": "bool"
        }
      ],
      "name": "setApprovalForAll",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes4",
          "name": "interfaceId",
          "type": "bytes4"
        }
      ],
      "name": "supportsInterface",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "testNFT",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "newOwner",
          "type": "address"
        }
      ],
      "name": "transferOwnership",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "name": "uri",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address[]",
          "name": "toArr",
          "type": "address[]"
        },
        {
          "internalType": "uint256[]",
          "name": "amountArr",
          "type": "uint256[]"
        }
      ],
      "name": "tokenMint",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address[]",
          "name": "fromArr",
          "type": "address[]"
        },
        {
          "internalType": "uint256[]",
          "name": "amountArr",
          "type": "uint256[]"
        }
      ],
      "name": "tokenBurn",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "price",
          "type": "uint256"
        }
      ],
      "name": "mintNFT",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "buyer",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "tokenId",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "price",
          "type": "uint256"
        }
      ],
      "name": "buyNFT",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "tokenId",
          "type": "uint256"
        }
      ],
      "name": "ownerOfNFT",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    }
  ],

엄청 긴데 잘 올라갔나요? 저는 ws://public-node-api.klaytnapi.com/v1/baobab/ 이 주소로 provider를 설정하니 웹소켓 연결이 되질 않습니다.

오 말씀하신 코드를 삽입하니 끊김없이이제 이벤트를 잘 받아옵니다! 감사합니다

2 Likes

잘 해결 되셨다니 다행입니다^^
즐거운 코딩 되세요!

2 Likes