新着:HeliusがLight Protocolを買収
Solana Telegram botのセットアップ方法
ブログ/開発

Solana Telegram botのセットアップ方法

Developer ExperienceエンジニアXのOwen VenterLinkedInのOwen Venter
読了時間:8分

Solanaブロックチェーンでは、1秒あたり約400件のトランザクションが発生しています。これには、トークン転送、NFT販売、トークンスワップ、入札、DAO投票、賭けなどが含まれます。しかし、これほど多くのデータがある中で、関心のある変更をどのように追跡すればよいのでしょうか。そこで役立つのがwebhookです。webhookを使うと、こうした変更を追跡し、関心のある情報を常に最新の状態に保てます。このガイドでは、Cloudflare workerを使用して、オンチェーンの更新をユーザーまたはチャンネルへ直接送信するTelegram botのセットアップ方法を説明します。

Telegram Botをセットアップする手順

  1. TelegramチャンネルとTelegram botをセットアップします。
  2. 更新を送信するwebhookとTelegram botを接続するCloudflare workerを作成します。
  3. Helius webhookを作成します。
  4. Helius Webhook APIを使用して、webhookが追跡するアドレスを編集します。この手順が必要なのは、NFTコレクション全体を追跡する場合だけです。

Telegram Botをセットアップする

Telegram botは、特定のタスク、特に更新通知を自動化するのに最適です。以下の手順でセットアップします。

1. BotFatherとの会話を開始する

Telegramの検索バーで「BotFather」を検索し、クリックして会話を開始します。

2. 新しいBotを作成する

「/newbot」と入力して送信します。BotFatherの案内に従って、botの名前とユーザー名を設定します。

3. アクセストークンを取得する

完了すると、BotFatherからアクセストークンが提供されます。

このチュートリアルの後半で使用するため、安全な場所に記録してください。

4. チャンネルを作成する

メニュー(☰)を開き、「新しいチャンネル」を選択します。

チャンネルをセットアップしたら、チャンネル名をクリックし、「管理者」を選択してbotを管理者として追加します。

5. チャットIDを確認する

チャンネルのチャットIDを確認するには、次の手順に従います。

メッセージを送信する:

まず、作成したチャンネルにメッセージを送信します。

Telegram APIを使用する

ブラウザでhttps://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdatesを開き、<YOUR_BOT_TOKEN>をBotFatherから受け取ったトークンに置き換えます。

チャットIDを確認する

返されたデータには、chatというフィールドがあります。その中にあるidが、チャンネルのチャットIDです。

以降の設定で必要になるため、このチャットIDを安全な場所に記録してください。

Cloudflare workerを作成する

Cloudflare workerを使用すると、オンラインでホストされ、常時稼働するコードをデプロイできます。これにより、webhookからの更新を継続的に監視できます。

1. Cloudflareにログインする

まず、Cloudflareアカウントにログインします。アカウントをまだお持ちでない場合は、無料で登録できます。

2. Workersセクションを開く

Cloudflareダッシュボードから「Workers」タブに移動します。

3. 新しいWorkerを作成する

「Create a Worker」ボタンをクリックします。Worker Editorが開きます。

4. Workerコードを編集する

エディターにはスクリプトのテンプレートが表示されます。デフォルトのコードを、Telegram bot用に提供されているCloudflareコードに置き換えます。

コード内のBOT_TOKENとCHAT_IDの変数を見つけます。これらはプレースホルダーであり、botから正しいチャットへメッセージを送信するために使用されます。

5. 環境変数を設定する

Cloudflare Workersダッシュボードで、workerの「Settings」タブに移動します。

ここで、botのトークン、チャットトークン、Helius APIキーを環境変数として追加できます。これにより、機密データをメインコードから分離し、安全に保護できます。

これらの環境変数には、コードで想定されている名前(BOT_TOKEN、CHAT_IDなど)を正確に設定してください。

6. Workerをデプロイする

コードと環境変数が正しく設定されていることを確認したら、「Save and Deploy」ボタンをクリックします。workerがデプロイされ、一意の公開URLが割り当てられます。

7. 公開URLを記録する

デプロイ後、workerに割り当てられた公開URLを必ず記録してください。このURLをTelegram botの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 webhookは、Solanaブロックチェーン上の変更とTelegramチャンネルをつなぎます。この例では、特定のウォレットが行うすべてのトランザクションを追跡するwebhookをセットアップします。

1. 登録する

dashboard.helius.devにアクセスし、無料アカウントを作成します。

2. Webhookを作成する

ダッシュボードで、新しいwebhookの作成を選択します。タイプはRaw、Enhanced、Discord、Accountから選べます。特定のカテゴリに分類された更新を受け取る場合は、「Enhanced」をおすすめします。これを選択する際は、NFT_SALESやNFT_LISTINGなど、関心のある更新を指定します。

完全なリストはこちらで確認できます。

3. WorkerのリンクとSolanaアドレスを指定する

デプロイ済みのCloudflare workerへのリンクを指定してください。また、監視する特定のSolanaアカウントアドレス(ユーザーのウォレットや、コレクション内のmintのリストなど)も指定します。

NFTコレクションを追跡する方法(Sales Botのセットアップ)

特定のコレクションを追跡し、そのコレクション内のNFTに何かが起きたときに更新を受け取るには、すべてのNFT mintアドレスをwebhookのアカウントとして追加する必要があります。そのためには、Helius webhookエンドポイントを使用して、最初に作成したwebhookを編集します。セットアップが完了すると、販売、出品、入札、バーン、およびNFTが関係するその他のトランザクションを追跡できます。

まず、追跡するコレクションのハッシュリストまたはmintリストが必要です。次のコードを使うと、DASでmintリストを取得できます。Helius APIキーを追加し、creatorAddressをNFTの最初の認証済みクリエイターのアドレスに置き換えるだけです。最初の認証済みクリエイターは、お好みのSolanaブロックエクスプローラーでメタデータを確認し、creatorsセクションにあるアドレスを探すことで確認できます。

スナップショットコード:

コード
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 snapshot toolのようなツールを使用してハッシュリストを取得することもできます。

ハッシュリストを取得したら、webhookが追跡するアカウントのリストを更新できます。そのためには、Helius webhooksエンドポイントを使用します。簡単に実行できるコードを以下に掲載しています。webhookUpdate.jsという新しいJavaScriptファイルをハッシュリストと同じディレクトリに作成し、以下のコードを追加してください。その後、コードを編集してHelius APIキーとwebhook IDを指定します。webhook IDは開発者ポータルで確認できます。次に、webhook作成時に使用したデータと一致するように、リクエストのbodyを編集します。たとえば、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 workerに戻り、NFT固有の詳細を返すようにコードを編集できます。必要なコードはすでに含まれています。TRANSFER更新を送信するセクションをコメントアウトし、NFT更新を送信するセクションのコメントを解除するだけです。

追跡対象のイベントがオンチェーンで発生すると、webhookがCloudflare workerに更新を送信します。この更新はJSON形式で、通常は関係するすべてのアカウント、各アカウントの変更、イベントタイプに関する情報など、多くの情報が含まれます。提供されているコードでは、重要と考えられる部分を抽出しています。

送信するメッセージをカスタマイズしたり、webhookの更新から抽出するデータを変更したりする場合は、messageToSend変数を変更できます。転送やNFTイベント以外を追跡することも可能です。Cloudflareコードを変更して、**requestBody[0]**全体を送信できます。これにより、webhookの完全なJSONレスポンスがTelegram botに転送され、レスポンス構造を確認できます。その後、内容を確認し、メッセージに含めるセクションを選択できます。

このセットアップにより、Helius webhookを通じて、TelegramチャンネルがSolanaブロックチェーンからのリアルタイム更新を受け取るハブになります。このガイドがお役に立てば幸いです。ご質問や問題がある場合は、DiscordまたはXでお気軽にチームへお問い合わせください。

Heliusを購読

Solana開発の最新情報や新しい記事の公開通知を受け取れます

拡大画像