신규: Helius가 Light Protocol을 인수했습니다
Solana Telegram 봇 설정 방법
블로그/개발

Solana Telegram 봇 설정 방법

개발자 경험 엔지니어X의 Owen VenterLinkedIn의 Owen Venter
읽는 데 8분

Solana 블록체인에서는 초당 약 400건의 트랜잭션이 발생합니다. 여기에는 토큰 전송, NFT 판매, 토큰 스왑, 입찰, DAO 투표, 베팅 등이 포함됩니다. 이렇게 데이터가 많을 때 중요한 변경 사항을 어떻게 추적할 수 있을까요? 이때 webhook이 필요합니다. Webhook을 사용하면 변경 사항을 추적하고 중요한 정보를 최신 상태로 확인할 수 있습니다. 이 가이드에서는 Cloudflare 워커를 사용해 온체인 업데이트를 사용자나 채널에 직접 전송하는 Telegram 봇을 설정하는 방법을 설명합니다.

Telegram 봇 설정 단계

  1. Telegram 채널과 Telegram 봇을 설정합니다.
  2. 업데이트를 전송하는 webhook과 Telegram 봇을 연결할 Cloudflare 워커를 생성합니다.
  3. Helius webhook을 생성합니다.
  4. Helius Webhook API를 통해 webhook이 추적하는 주소를 수정합니다. 전체 NFT 컬렉션을 추적할 때만 필요한 단계입니다.

Telegram 봇 설정

Telegram 봇은 업데이트를 비롯한 특정 작업을 자동화하는 데 유용합니다. 다음 단계에 따라 설정하세요.

1. BotFather와 대화 시작

Telegram 검색창에서 'BotFather'를 검색한 후 클릭해 대화를 시작합니다.

2. 새 봇 생성

'/newbot'을 입력해 전송합니다. 그러면 BotFather가 봇 이름과 사용자 이름을 설정하는 과정을 안내합니다.

3. 액세스 토큰 받기

설정을 마치면 BotFather가 액세스 토큰을 제공합니다.

이 토큰은 튜토리얼 뒷부분에서 사용하므로 안전하게 기록해 두세요.

4. 채널 생성

메뉴(☰)로 이동해 '새 채널'을 선택합니다.

채널을 설정한 후 채널 이름을 클릭하고 '관리자'를 선택한 다음 봇을 관리자로 추가합니다.

5. 채팅 ID 찾기

다음 단계에 따라 채널의 채팅 ID를 확인하세요.

메시지 전송:

먼저 생성한 채널에 메시지를 전송합니다.

Telegram API 사용

브라우저에서 https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates 로 이동하고 <YOUR_BOT_TOKEN>을 BotFather에서 받은 토큰으로 바꿉니다.

채팅 ID 찾기

반환된 데이터에서 chat 필드를 찾으세요. 그 안에 있는 id이 채널의 채팅 ID입니다.

추가 구성에 필요하므로 이 채팅 ID를 안전하게 기록해 두세요.

Cloudflare 워커 생성

Cloudflare 워커를 사용하면 온라인에서 호스팅되고 계속 실행되는 코드를 배포해 webhook의 업데이트를 상시 감지할 수 있습니다.

1. Cloudflare 로그인

먼저 Cloudflare 계정에 로그인합니다. 아직 계정이 없다면 무료로 가입할 수 있습니다.

2. Workers 섹션 열기

Cloudflare 대시보드에서 "Workers" 탭으로 이동합니다.

3. 새 Worker 생성

“Create a Worker” 버튼을 클릭합니다. Worker Editor로 이동합니다.

4. Worker 코드 수정

에디터에 스크립트 템플릿이 표시됩니다. 기본 코드를 Telegram 봇용으로 제공된 Cloudflare 코드로 교체합니다.

코드에서 BOT_TOKEN 및 CHAT_ID 변수를 찾으세요. 이 변수는 자리 표시자이며, 봇을 통해 올바른 채팅으로 메시지를 전송하는 데 사용됩니다.

5. 환경 변수 구성

Cloudflare Workers 대시보드에서 워커의 "Settings" 탭으로 이동합니다.

여기에서 봇 토큰, 채팅 토큰, Helius API 키를 환경 변수로 추가할 수 있습니다. 민감한 데이터를 기본 코드와 분리해 안전하게 보호할 수 있습니다.

환경 변수 이름이 코드에서 요구하는 이름과 정확히 일치하는지 확인하세요(예: BOT_TOKEN, CHAT_ID 등).

6. Worker 배포

코드와 환경 변수가 올바르게 설정되었는지 확인한 후 “Save and Deploy” 버튼을 클릭합니다. 워커가 배포되고 고유한 공개 URL이 할당됩니다.

7. 공개 URL 기록

배포 후 워커에 할당된 공개 URL을 반드시 기록해 두세요. 이 URL을 Telegram 봇의 webhook 엔드포인트로 사용합니다.

Cloudflare Worker 코드:

코드
const TELEGRAM_BOT_TOKEN = BOT_TOKEN;
const TELEGRAM_CHAT_ID = CHAT_ID;
const HELIUS_API_KEY=API_KEY;
const HELIUS_RPC_URL = `https://mainnet.helius-rpc.com/?api-key=${HELIUS_API_KEY}`;

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
  if (request.method === 'POST') {
    const requestBody = await request.json();
    console.log('Received POST request with body:', requestBody);

    //THIS IS FOR NFT UPDATES (comment this section out if you are doing something else)
    // Extract transaction description, timestamp, signature, and mint address
      // const NFTdescription = requestBody[0].description;
      // const NFTtimestamp = new Date(requestBody[0].timestamp * 1000).toLocaleString(); // Convert Unix timestamp to readable date-time
      // const NFTsignature = `https://solscan.io/tx/${requestBody[0].signature}`
      // const NFTmintAddress = requestBody[0].events.nft.nfts[0].mint;
      // const NFTimageUrl = await getAssetImageUrl(NFTmintAddress);// Get NFT image URL
      // // Construct the message
      // const messageToSendNFT =
      // `----NEW UPDATE---\n`+
      // `Description:\n${NFTdescription}\n` +
      // `Mint Address:\n${NFTmintAddress}\n` +
      // `Signature:\n${NFTsignature}\n` +
      // `Timestamp:\n${NFTtimestamp}`;
      // await sendToTelegramNFT(messageToSendNFT, NFTimageUrl); // Send to Telegram

    //THIS IS FOR TRANSFER UPDATES (comment this section out if you are doing something else)
    // Extract transaction description, timestamp, signature
      const Transferdescription = requestBody[0].description;
      const Transfertimestamp = new Date(requestBody[0].timestamp * 1000).toLocaleString(); // Convert Unix timestamp to readable date-time
      const Transfersignature = `https://xray.helius.xyz/tx/${requestBody[0].signature}`
      // Construct the message
      const messageToSendTransfer =
      `----NEW UPDATE---\n`+
      `Description:\n${Transferdescription}\n` +
      `Signature:\n${Transfersignature}\n` +
      `Timestamp:\n${Transfertimestamp}`;
      await sendToTelegramTransfer(messageToSendTransfer); // Send to Telegram

    return new Response('Logged POST request body.', {status: 200});
  } else {
    return new Response('Method not allowed.', {status: 405});
  }
}

// This function is used to send NFT Updates to the bot
async function sendToTelegramNFT(message, imageUrl) {
  const telegramUrl = `https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendPhoto`;
  const response = await fetch(telegramUrl, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      chat_id: TELEGRAM_CHAT_ID,
      photo: imageUrl,
      caption: message,
      parse_mode: "HTML"
    }),
  });
  const responseData = await response.json();

  if (!response.ok) {
    console.error('Failed to send photo to Telegram:', responseData);
  }
}

//This function is used to send Transfer Updates to the Bot
async function sendToTelegramTransfer(message) {
  const telegramUrl = `https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage`;
  const response = await fetch(telegramUrl, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      chat_id: TELEGRAM_CHAT_ID,
      text: message,
      parse_mode: "HTML"
    }),
  });
  const responseData = await response.json();

  if (!response.ok) {
    console.error('Failed to send message to Telegram:', responseData);
  }
}

//This function gets images associated to NFTs that are features in updates.
async function getAssetImageUrl(mintAddress) {
  const response = await fetch(HELIUS_RPC_URL, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      jsonrpc: '2.0',
      id: 'my-id',
      method: 'getAsset',
      params: {
        id: mintAddress,
      },
    }),
  });
  const { result } = await response.json();
  return result.content.links.image;
}

Helius Webhook 설정

Helius webhooks는 Solana 블록체인의 변경 사항과 Telegram 채널을 연결합니다. 이 예시에서는 특정 지갑에서 발생하는 모든 트랜잭션을 추적하도록 webhook을 설정합니다.

1. 가입

dashboard.helius.dev에 접속해 무료 계정을 만드세요.

2. Webhook 생성

대시보드에서 새 webhook을 생성합니다. 유형은 Raw, Enhanced, Discord, Account 중에서 선택할 수 있습니다. 특정 유형별 업데이트가 필요하다면 'Enhanced'를 권장합니다. 이 유형을 선택할 때 NFT_SALES 또는 NFT_LISTING 등 관심 있는 업데이트를 지정하세요.

전체 목록은 여기에서 확인할 수 있습니다.

3. Worker 링크 및 Solana 주소 입력

배포한 Cloudflare 워커의 링크를 입력하세요. 또한 모니터링할 특정 Solana 계정 주소도 입력합니다. 사용자 지갑이나 컬렉션의 민트 목록 등이 될 수 있습니다.

NFT 컬렉션 추적 방법(판매 봇 설정)

특정 컬렉션을 추적하고 해당 컬렉션의 NFT에 이벤트가 발생할 때 업데이트를 받으려면 모든 NFT 민트 주소를 webhook의 계정으로 추가해야 합니다. 이를 위해 Helius webhook 엔드포인트를 사용해 처음 만든 webhook을 수정합니다. 설정이 완료되면 판매, 리스팅, 입찰, 소각 및 NFT가 관련된 기타 모든 트랜잭션을 추적할 수 있습니다.

먼저 추적할 컬렉션의 해시/민트 목록이 필요합니다. 다음 코드를 사용하면 DAS로 민트 목록을 가져올 수 있습니다. Helius API 키를 추가하고 creatorAddress를 NFT에서 첫 번째로 검증된 크리에이터의 주소로 교체하면 됩니다. 첫 번째로 검증된 크리에이터는 선호하는 Solana 블록 탐색기에서 메타데이터를 확인한 후 크리에이터 섹션 아래의 주소를 찾아 확인할 수 있습니다.

스냅샷 코드:

코드
const fs = require('fs');
const url = `https://mainnet.helius-rpc.com/?api-key=`;

const getAssetsByCreator = async () => {
  let page = 1;
  let allMintAddresses = [];

  while (true) {
    const response = await fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        jsonrpc: '2.0',
        id: `my-id-page-${page}`,
        method: 'getAssetsByCreator',
        params: {
          creatorAddress: 'GFQBHxuNcAwYwHtEpggMwbH5kwV6Ne4JowHbLVfsMC6C',
          onlyVerified: true,
          page: page,
          limit: 1000
        },
      }),
    });

    const { result } = await response.json();

    // If there are no more items, break the loop
    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }else{
      if (!result.items || result.items.length === 0) {
        break;
      }
    }

    // Extract mint addresses and add them to the list
    const mintAddresses = result.items.map(item => item.id);
    allMintAddresses.push(...mintAddresses);

    // Check if there are less than 1000 results to stop further requests
    if (result.items.length < 1000) {
      break;
    }

    page++;
  }

  // Join the addresses by comma
  const addressesString = allMintAddresses.join(',');
  console.log("All Mint Addresses: ", addressesString);
  fs.writeFileSync('addresses.json', JSON.stringify(allMintAddresses, null, 2));
};

getAssetsByCreator();

준비가 끝나면 터미널을 열고 스크립트가 있는 디렉터리로 이동한 후 node snapshot.js를 실행합니다. 그러면 해당 디렉터리에 addresses.json이라는 JSON 파일이 생성됩니다. 또는 Magic Eden 스냅샷 도구와 같은 도구를 사용해 해시 목록을 가져올 수 있습니다.

해시 목록을 준비했다면 webhook이 추적하는 계정 목록을 업데이트할 수 있습니다. 이를 위해 Helius webhooks 엔드포인트를 사용해야 합니다. 아래에 이 작업을 간편하게 처리하는 코드를 첨부했습니다. webhookUpdate.js라는 새 JavaScript 파일을 해시 목록과 같은 디렉터리에 만들고 아래 코드를 추가하세요. 그런 다음 코드에 Helius API 키와 webhook ID를 입력합니다. webhook ID는 개발자 포털에서 확인할 수 있습니다. 이후 webhook을 생성할 때 사용한 데이터와 일치하도록 요청 본문을 수정해야 합니다. NFT 리스팅과 판매를 추적하도록 선택했다면 해당 항목을 반드시 포함하세요. accountAddresses 필드는 앞서 만든 해시 목록을 사용하도록 설정되어 있으므로 수정하지 마세요.

변경을 완료한 후 터미널에서 node webhookUpdate.js를 실행합니다. 코드를 실행하면 터미널에 확인 메시지가 표시됩니다.

webhookUpdate.js:

코드
const fs = require('fs');

const editWebhook = async () => {
    try {
      // Read the JSON file
      const addresses = JSON.parse(fs.readFileSync('addresses.json', 'utf8'));
  
      const response = await fetch(
        "https://api.helius.xyz/v0/webhooks/?api-key=",
        {
          method: 'PUT',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            webhookURL: "",
            transactionTypes: ["NFT_LISTING","NFT_SALE"],
            accountAddresses: addresses,  // Use the addresses from the file
            webhookType: "enhanced"
          }),
        }
      );
      const data = await response.json();
      console.log({ data });
    } catch (e) {
      console.error("error", e);
    }
  };
  
  editWebhook();

webhook이 업데이트되면 Cloudflare 워커로 돌아가 NFT 관련 세부 정보를 반환하도록 코드를 수정할 수 있습니다. 필요한 코드는 이미 포함되어 있습니다. TRANSFER 업데이트 전송 섹션을 주석 처리하고 NFT 업데이트 전송 섹션의 주석을 해제하면 됩니다.

추적 중인 이벤트가 온체인에서 발생하면 webhook이 Cloudflare 워커로 업데이트를 전송합니다. 이 업데이트는 JSON 형식이며 일반적으로 관련된 모든 계정, 각 계정의 변경 사항, 이벤트 유형 관련 정보 등 많은 정보를 포함합니다. 제공된 코드에서는 중요하다고 판단한 부분만 추출합니다.

전송되는 메시지를 맞춤 설정하거나 webhook 업데이트에서 추출하는 데이터를 변경하려면 messageToSend 변수를 수정하세요. 전송 및 NFT 이벤트 외의 항목도 추적할 수 있습니다. Cloudflare 코드를 수정해 전체 **requestBody[0]**을 전송하면 됩니다. 그러면 전체 webhook JSON 응답이 Telegram 봇으로 전달되어 응답 구조를 확인할 수 있습니다. 이후 메시지에 포함할 섹션을 확인하고 선택할 수 있습니다.

이 설정을 완료하면 Telegram 채널이 Helius webhooks를 통해 Solana 블록체인의 실시간 업데이트를 제공하는 허브가 됩니다. 이 가이드가 도움이 되었기를 바랍니다. 질문이나 문제가 있다면 언제든 Discord 또는 X에서 팀에 문의하세요.

Helius 구독하기

최신 Solana 개발 소식을 확인하고 새 게시물 알림을 받아보세요

확대 이미지