新消息:Helius 收购 Light Protocol
如何设置 Solana Telegram 机器人
博客/开发

如何设置 Solana Telegram 机器人

开发者体验工程师X 上的 Owen VenterLinkedIn 上的 Owen Venter
阅读需 8 分钟

Solana 区块链每秒大约发生 400 笔交易,其中包括代币转账、NFT 销售、代币兑换、出价、DAO 投票、投注等。但面对如此庞大的数据量,如何跟踪你关心的变化?这正是 webhook 的用武之地。Webhook 可以帮助你跟踪这些变化,及时掌握你关心的信息。本指南将介绍如何设置 Telegram 机器人,并使用 Cloudflare Worker 将链上更新直接发送给用户或频道。

设置 Telegram 机器人的步骤

  1. 设置 Telegram 频道和 Telegram 机器人。
  2. 创建 Cloudflare Worker,连接发送更新的 webhook 与 Telegram 机器人。
  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 Worker

Cloudflare Worker 可让你部署托管在线并持续运行的代码,以便随时接收 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 控制面板中,前往 Worker 的“Settings”选项卡。

你可以在这里将机器人的令牌、聊天令牌和 Helius API 密钥添加为环境变量。这有助于避免在主代码中暴露敏感数据,确保数据安全。

确保正确命名这些环境变量,使其与代码中的预期名称一致(例如 BOT_TOKEN、CHAT_ID 等)。

6. 部署 Worker

确认代码和环境变量均已正确设置后,点击“Save and Deploy”按钮。你的 Worker 将完成部署,并获得一个唯一的公共 URL。

7. 记下公共 URL

部署完成后,请务必记下分配给 Worker 的公共 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 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 账户地址,可以是用户的钱包,也可以是某个系列的铸币地址列表。

如何跟踪 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 webhook 端点。我在下方附上了一些代码,让此操作更加简单。只需创建一个名为 webhookUpdate.js 的新 JavaScript 文件(与哈希列表放在同一目录),然后添加下方代码。接着编辑代码,填入你的 Helius API 密钥和 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 Worker 并编辑代码,让它返回 NFT 的相关详细信息。所需代码已经包含在内,你只需注释掉发送 TRANSFER 更新的部分,并取消注释发送 NFT 更新的部分。

当你跟踪的事件在链上发生时,webhook 会向 Cloudflare Worker 发送更新。该更新采用 JSON 格式,通常包含大量信息,例如涉及的所有账户、每个账户的变化以及与事件类型相关的信息。在提供的代码中,我们提取了认为重要的部分。

如果你想自定义发送的消息,或更改从 webhook 更新中提取的数据,可以修改 messageToSend 变量。如果你想跟踪转账和 NFT 事件以外的内容,同样可以实现。你可以修改 Cloudflare 代码,使其发送完整的 requestBody[0]。这会将完整的 webhook JSON 响应转发给 Telegram 机器人,让你可以查看响应结构。然后,你可以查看并决定要在消息中包含哪些部分。

完成这些设置后,你的 Telegram 频道将成为获取 Solana 区块链实时更新的中心,这一切都得益于 Helius webhook。希望本指南对你有所帮助。如果有任何问题,请随时通过 Discord 或 X 联系团队。

订阅 Helius

及时了解 Solana 开发的最新动态,并在我们发布新内容时收到更新

放大图片