Webhook Quickstart

What is Nodit Webhook?

Nodit Webhook은 추적하고자 하는 온체인 이벤트를 정의하여 사전에 등록해두면, Nodit 서버에서 해당 이벤트의 발생 여부를 추적하여 이벤트가 발생한 시점에 지정된 Webhook Endpoint를 호출하여 이벤트 정보를 전달하는 기능입니다. 프로젝트에서 구현한 Backend Endpoint를 통해 온체인 이벤트의 발생 여부와 내용을 비동기, 실시간으로 전달받을 수 있어 사용자 액션 추척, 토큰 액티비티 추적, 트랜잭션 처리여부 등을 효과적으로 모니터링할 수 있습니다. Nodit Webhook은 다음과 같은 순서를 통해 생성 및 사용할 수 있습니다.

  1. Webhook 수신을 위한 Endpoint 구현하기
  2. Nodit 콘솔 또는 API를 통해 원하는 Webhook 생성하기
    2-1. 모니터링 하고자 하는 대상 네트워크를 선택한 뒤 Event Type으로 추적하고자 하는 이벤트 정의
    2-2. 1에서 생성한 Webhook Endpoint 입력
  3. (Optional)Webhook 설정 정보를 수정 또는 삭제하기

실제 이벤트 발생 시점과 Webhook을 수신하는 시점사이에 시간 지연이 있습니다.

Nodit Webhook은 모니터링 대상 이벤트가 포함된 블록이 Confirmed된 이후 Webhook Endpoint를 호출하므로, Scan과 같은 Explorer에서 보여지는 이벤트의 발생 시점과 Webhook을 수신하는 시점 사이에 적절한 Block Confirmation 시간 만큼의 지연이 발생할 수 있습니다. 이러한 시간 지연은 Testnet과 같이 블록 타임이 긴 네트워크에서 Webhook을 사용하는 경우 더욱 크게 발생할 수 있으니 사용에 참고해주세요.

Nodit팀은 향후 Webhook을 더 다양한 용도로 사용하실 수 있도록, Confirmed되지 않은 블록에 포함된 이벤트를 빠르게 감지하여 Webhook을 받을 수 있는 새로운 옵션 제공을 검토하고 있습니다. 곧 Release될 더 빠른 Webhook을 기대해주세요!


Webhook 사용 예제

1. 환경 세팅

1-1. Nodit 콘솔 가입

Nodit에서는 다양한 블록체인 네트워크에 연결할 수 있는 Node 서비스를 제공합니다. 아래 링크를 클릭하여 Nodit Console에 접속하여 회원가입을 진행하세요.

1-2. Webhook Listener Endpiont 얻기

webhook 생성을 위해서는 알림을 받을 별도의 Webhook Listener 서버가 필요합니다. 이 서버는 외부의 이벤트 통지를 받아 처리하는 역할을 합니다. 서비스 운영을 위해서는 Webhook Listener 서버를 직접 구축해야 하지만, 이번 예제에서는 webhook 응답만 확인하기 때문에 써드파티 서비스를 활용합니다.

[써드파티 서비스 사용 예시]

  • Postman Mockserver: Postman Mockserver를 사용하면 API를 모의할 수 있으며, Webhook 요청을 받을 수 있는 임시 URL을 제공받습니다. 설정은 간단하며, Postman의 Mock 서버 생성 기능을 통해 쉽게 구성할 수 있습니다. 자세한 설정 방법은 아래 링크에서 확인할 수 있습니다.
    ▶︎ Set up Postman Mock server

  • Webhook.site: Webhook.site는 실시간으로 Webhook 데이터를 캡처하고 확인할 수 있는 서비스를 제공합니다. 이 서비스를 사용하면 별도의 서버 구축 없이 즉시 Webhook 테스트를 시작할 수 있습니다. 아래 링크를 클릭하면 무료 사용할 수 있는 Webhook Listener Endpoint를 얻을 수 있습니다.
    ▶︎ Webhook.site

이번 예제에서는 Webhook.site를 활용하여 Webhook 응답을 확인합니다. Webhook.site에 접속하여 제공되는 unique URL을 복사합니다.

webhook.site 화면

webhook.site 화면

2. Webhook 생성하기

콘솔 혹은 Webhook API를 사용하여 원하는 이벤트를 구독할 수 있습니다. 이 예제에서는 Webhook API를 활용하여 BLOCK_PERIOD 이벤트를 구독하는 Webhook을 생성합니다.

  • X-API-KEY: Nodit 콘솔에서 제공된 실제 API 키를 입력합니. API 키는 서비스에 안전하게 접근하고, 사용자의 인증을 확인하는 데 필수적인 요소입니다.
  • webhookUrl: 구독하고자 하는 이벤트의 알림을 받을 Webhook Listener Endpoint를 입력합니다. 위에서 복사한 Webhook Listener Endpoint를 webhookUrl에 붙여넣습니다.
curl --request POST \
     --url https://web3.nodit.io/v1/ethereum/mainnet/webhooks \
     --header 'X-API-KEY: {Your API key}' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "eventType": "BLOCK_PERIOD",
  "description": "Webhook Test",
  "notification": {
    "webhookUrl": "{Your webhook listener endpoint}"
  },
  "condition": {
    "period": 1
  }
}
'

위의 스크립트를 실행하고 webhook이 성공적으로 생성되면, 성공 메세지와 함께 subscription ID을 포함한 응답을 반환합니다. 아래는 생성 예시입니다.

{
  "subscriptionId": "2361",
  "description": "Webhook test",
  "protocol": "ETHEREUM",
  "network": "MAINNET",
  "eventType": "BLOCK_PERIOD",
  "notification": {
    "webhookUrl": "https://example.com/webhook"
  },
  "signingKey": "cd5...d12",
  "condition": {
    "period": 1
  },
  "createdAt": "2024-04-29T08:04:11.098Z"
}

3. Webhook Listener 서버에서 응답 확인하기

Webhook이 정상적으로 생성되면, 구독하는 이벤트가 발생할 때마다 Webhook Listener 서버에 알림을 전송합니다. 아래는 Webhook.site에서 알림을 받은 예시입니다.

{
  "subscriptionId": "2347",
  "description": "Webhook test",
  "protocol": "ETHEREUM",
  "network": "MAINNET",
  "subscriptionType": "WEBHOOK",
  "notification": {
    "webhookUrl": "https://webhook.site/c3aa6f3b-e19d-416c-ab24-2659ffc0f304"
  },
  "signingKey": "0dc...286",
  "eventType": "BLOCK_PERIOD",
  "event": {
    "period": 5,
    "message": {
      "parent_hash": "0x4cff8863b4dadd17424574f71898d46dc4170567e68fece6514c3c0fd3c6aa37",
      "sha3_uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
      "miner": "0x95222290dd7278aa3ddd389cc1e1d165cc4bafe5",
      "state_root": "0x0ac76dcf2b9b460db6aa1b87aba041a16fdc626d454c6c8722753a54a4180684",
      "transactions_root": "0x6504d7b34c36760e9de9c8ab5468c71f9442aab965a29234822651557b076a83",
      "receipts_root": "0x9b7bebea2e5bdc0055e1b937e6993cc6b52a533ce68373b6e91b61bd4d2b570d",
      "logs_bloom": "0xbffffdfdfff7ffff7fdfffefdffffffffdbbffffcfffffffaffffff7feffffffffffffedf7cfffdf7fefff7ffffbfddfbfffef6ffbfdfffdfffbfc3df3bffffbffefbffbff6fffefffaf67fffef7fffefffff7f7ffffffff9fffffefeffffffffbffefff7afff5f7f7fffffffbbdfbff9fbffefb9ffdffeffffdfffbffffdafffefefbdffdffff7ef8fdfffbffffffffffbfdfbf7ff6f7fffffbebefffdfffffbeffdfff9fdfef7fafffffffffffffefbeffffffffffffffffdffffdbfe7fbfff7fdffffbfffcfdb7fffffffbffffbffffbffffefffddffff7fefffadffffffbfffffffffffffdeffbedfdf7bf1fbdffafffffefffdffffff7fdfffeffbffffd",
      "difficulty": "0",
      "gas_limit": 30000000,
      "gas_used": 29997074,
      "extra_data": "0x6265617665726275696c642e6f7267",
      "mix_hash": "0xd7af35f660850b15564a7667678d51a9db1bbe045702efbb2b8034d98b01c2f4",
      "nonce": "0x0000000000000000",
      "hash": "0xd69b6a597874ad7382569e85b93bed4e8d0d6c7152b9ac59677611fa00a568a6",
      "size": 155824,
      "total_difficulty": "58750003716598352816469",
      "transactions": [
        "0xef99067235b9d30831f5161cdfb9cd1a1b24f04fc9a694b120ef8e568bd70234",
				// ... snip
        "0x586442f7566519e7e3f026bfd318a65f559783cafe0f5a9b3162dc7f50c0d6cb"
      ],
      "transaction_count": 318,
      "log_count": 1548,
      "base_fee_per_gas": 5838584039,
      "withdrawals_root": "0xc0419b57a2665a2682834b323193cdbc56f13698aed0467a028b586ae9720488",
      "withdrawal_count": 16,
      "blob_gas_used": "0x0",
      "excess_blob_gas": "0x60000",
      "parent_beacon_block_root": "0x40735f721e4de4c63825f5885795ade7ac314a8502953ef14c074b64b70b2b4e",
      "type": "block",
      "number": 19758850,
      "timestamp": 1714368119
    }
  },
  "createdAt": "2024-04-29T05:23:46.838Z"
}

🚧

Kaia Webhook 데이터에 대하여

Kaia 체인에서 Webhook을 사용하는 경우 Webhook의 payload 구조 및 일부 필드의 형식이 다른 이더리움 계열 체인의 데이터와 상이할 수 있습니다. 이는 체인별로 정의된 고유한 데이터 명세를 유지하기 위한 것으로, Kaia Webhook 데이터는 노드의 kaia namespace에 속한 API 응답 데이터를 기준으로 생성됩니다. 예를 들어, 트랜잭션 관련 Webhook payload의 transaction_type 필드는 Kaia와 이더리움에서 아래와 같이 상이한 형식의 값으로 반환됩니다.

  • 이더리움의 transaction_type: 2 (Number 타입)
  • Kaia의 transaction_type: "TxTypeEthereumDynamicFee" (String 타입)

4. Webhook 수정 및 조회하기

이제 등록한 Webhook을 수정해본 뒤, 영구적으로 삭제하는 방법을 알아보겠습니다.

Nodit Webhook 서비스에는 알림을 일시 정지할 수 있는 기능을 제공하고 있습니다. 일시정지를 한 경우, 등록한 Webhook은 삭제되지 않고 알림만 해제된 상태가 됩니다. 아래의 예제 스크립트를 실행하여 isActive 필드를 false로 설정해보세요. (이때, 유효한 SUBSCRIPTION_ID와 YOUR_API_KEY를 입력해야 합니다.)

curl --request PATCH \
     --url https://web3.nodit.io/v1/ethereum/mainnet/webhooks/{SUBSCRIPTION_ID} \
     --header 'X-API-KEY: {YOUR_API_KEY}' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
     "isActive":false
}'

result가 true라는 응답을 반환하면 수정이 성공적으로 진행되었음을 의미합니다.

{
  "result": true
}

이번엔 수정된 내용을 확인하기 위해 Webhook 정보를 조회합니다. (이때, 유효한 SUBSCRIPTION_ID와 YOUR_API_KEY를 입력해야 합니다.)

curl --request GET \
     --url 'https://web3.nodit.io/v1/ethereum/mainnet/webhooks?subscriptionId={SUBSCRIPTION_ID}' \
     --header 'X-API-KEY: {YOUR_API_KEY}' \
     --header 'accept: application/json'

{
  "total": 1,
  "rpp": 10,
  "page": 1,
  "items": [
    {
      "subscriptionId": "2361",
      "description": "webhook Test",
      "environmentId": "9999999999999999999",
      "protocol": "ETHEREUM",
      "network": "MAINNET",
      "subscriptionType": "WEBHOOK",
      "eventType": "BLOCK_PERIOD",
      "notification": {
        "webhookUrl": "https://example.com/webhook"
      },
      "signingKey": "0a2...2fd",
      "isActive": false,
      "updatedAt": "2024-04-29T08:20:20.000Z",
      "createdAt": "2024-04-29T08:17:21.826Z",
      "condition": {
        "period": 1
      }
    }
  ]
}

5. Webhook 삭제하기

마지막으로 구독 중인 Webhook을 삭제해보겠습니다. 단, 한 번 삭제를 진행하면 되돌릴 수 없기 때문에 신중하게 삭제 작업을 결정해야 합니다. 삭제 과정은 해당 Webhook에 대한 모든 설정과 데이터 전송을 중지시키므로, 이 이상 이벤트 알람을 받지 못하게 됩니다. 아래 예제 스크립트를 이용하여 이번 예제에서 생성한 Webhook을 삭제해보세요.

curl --request DELETE \
     --url https://web3.nodit.io/v1/ethereum/mainnet/webhooks/{SUBSCRIPTION_ID} \
     --header 'X-API-KEY: {YOUR_API_KEY}' \
     --header 'accept: application/json'

result가 true라는 응답을 반환하면 삭제가 성공적으로 진행되었음을 의미합니다.

{
  "result": true
}

Webhook Retry 정책

Nodit Webhook은 현재 최대 1번의 Retry를 지원합니다. webhookUrl 호출 후 200 OK 응답을 받지 못한 경우, 최초 요청 시점으로부터 15초 후 Webhook 데이터 전달을 위한 재호출이 실행됩니다.