开发自己的TG钱包机器人

这是一篇关于实际工作的 TG 钱包机器人的博客,详解介绍了如何使用node.js开发一个完整的TG钱包机器人。

开发自己的TG钱包机器人
一键发币: SOL | BNB | ETH | BASE | Blast | ARB | OP | POLYGON | AVAX | FTM | OK

大家好👋,我是 Himanshu。在过去的 1.7 年里,我一直在 Cosmos 生态系统的加密钱包扩展中担任前端工程师。工作之余,我通过一个共同的朋友完成了许多自由职业项目。在自由职业中,我主要从事 web3 项目,涉及制作 TG 购买机器人追踪器、DEX网络应用游戏和以太坊生态系统中的 TG 钱包机器人。

在从事这些项目时,我总是发现很难找到一些好的资源,大多数时候我都会参考 Chat GPT、一些随机博客和 YouTube 视频。这就是为什么我认为我应该写一篇关于实际工作的 TG 钱包机器人的博客,这就是这个博客的原因。

让我们开始吧。

1、初始化项目

我将使用 NodeJS 环境来创建此项目。因此,首先,创建一个新文件夹 tg-wallet-bot,并在其中运行 npm init -y。

运行此命令后,你的 tg-wallet-bot 文件夹中必须有一个 package.json 文件。现在,让我们添加一些依赖项,它们将帮助我们快速测试我们的机器人。创建依赖项,在 package.json 文件对象中创建一个新字段,并使用上述版本添加以下依赖项。

"express": "4.18.2",
"telegraf": "4.12.2",
"dotenv": "16.3.1"

为什么要固定依赖项而不是 semver 范围?原因与安全性有关。只是为了确保当攻击者试图在更高版本中做一些可疑的事情时,我们的项目不会受到损害。

为什么只有这些版本?我已经有一个使用此配置运行的项目,所以我仅出于本博客的学习目的而提及它。这就是原因。

到目前为止,您的 package.json 文件必须看起来像这样

{
  "name": "tg-wallet-bot",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "dotenv": "16.3.1",
    "express": "4.18.2",
    "telegraf": "4.12.2"
  }
}

现在,我们在根目录创建一个 index.js 文件,并添加以下代码

require("dotenv").config();
const { Telegraf } = require("telegraf");

const bot = new Telegraf(process.env.TG_WALLET_BOT_TOKEN);

bot.command("start", (ctx) => {
  const message = `Welcome to the TG Wallet Bot!`;
  ctx.reply(message);
});

bot.launch();

在上面的代码片段中,我们创建了一个 Telegram 机器人实例并处理该机器人的 /start 命令。您一定在机器人中见过这个命令,当您第一次开始与机器人交互时单击“开始”按钮时,这个命令也会运行。然后,我们启动机器人。

此外,现在是时候在 TG 上创建一个机器人并将其链接到我们的代码了。要在 TG 上创建机器人,您必须在 Telegram 上搜索 BotFather。搜索后,单击“开始”按钮,之后您必须获得支持的命令列表。要创建新的机器人,您必须单击 /newbot 并回答一些问题,例如 TG 机器人名称和用户名,完成后您将获得一个需要保护的令牌,因为此令牌允许任何人访问您的机器人。

现在在项目目录的根级别创建一个新的 .env 文件,并将以下代码添加到该文件中

TG_WALLET_BOT_TOKEN=<Bot Token that you got in BotFather>

我们几乎准备好测试我们的机器人了。

但在测试之前,请在你的终端中运行 npm install 命令。

进入你刚刚在 BotFather 中创建的 TG 机器人(您必须在 BotFather 上看到带有令牌的 TG 机器人链接)。

现在,在你的终端中运行 node index.js 命令。

单击你在 TG 机器人中看到的“开始”按钮。

哇哦!它正在运行

你可以在消息框中输入 /start 命令,这样也可以正常工作。

到目前为止,我们还没有添加任何与加密相关的代码。这只是一个简单的 TG 机器人。

我想向你展示如何在您的机器人中导入钱包,将其存储在 Telegram 会话中,并向用户显示导入的钱包信息(公共地址)。

我不会在本博客中显示任何交易或其他任何内容,否则,博客会变得很长,并且仅通过导入钱包,您就会了解如何从用户那里获取输入,如何处理单击任何按钮的用户操作,以及如何显示按钮。

2、导入钱包

现在,为了让用户导入钱包,我们需要显示一个按钮,让用户可以选择执行此操作。所以,让我们在启动命令上快速添加一个按钮。要创建一个按钮,我将创建一个实用函数,它将返回一个我们可以使用的按钮。

在项目目录的根级别创建一个 utils 文件夹,并在其中创建 misc.js 和 index.js 文件。

在 utils/misc.js 文件中,添加以下代码

const { Markup } = require("telegraf");

function createCallBackBtn(btnLabel, cbActionCommand) {
  return Markup.button.callback(btnLabel, cbActionCommand);
}

module.exports = {
  createCallBackBtn,
};

上面的代码片段创建了一个回调按钮,我们可以使用它向用户显示一个按钮。

在 utils/index.js 文件中,添加以下代码

const misc = require("./misc");

module.exports = {
  ...misc,
};

在上面的代码片段中,我们只是重新导出函数。这将有助于我们保持代码井然有序。

现在,在 index.js 文件中,使用以下内容更改启动命令处理程序代码

const { Telegraf } = require("telegraf");
const { createCallBackBtn } = require("./utils");

...

bot.command("start", (ctx) => {
  const message = `Welcome to the TG Wallet Bot!`;
  const importWalletButton = createCallBackBtn(
    "Import Wallet",
    "import-wallet"
  );
  ctx.reply(message, {
    reply_markup: {
      inline_keyboard: [[importWalletButton]],
    },
  });
});

因此,我们创建一个带有标签“导入钱包”的按钮,该按钮附带一个回调操作(很快你就会看到它的用途)。

现在,当你在终端中运行 node index.js 命令时(如果任何命令仍在运行,请停止前面的命令),将看到“导入钱包”出现在启动命令消息中。

尝试点击按钮,什么都不会发生。

让我们为导入钱包按钮添加一个处理程序。

在你的 index.js 文件中添加以下代码

...

bot.action("import-wallet", (ctx) => {
  ctx.reply("Import wallet clicked");
});

bot.launch();

现在,当你在终端中运行 node index.js 命令并单击导入钱包按钮时,将看到“单击导入钱包”消息。

因此,我们可以显示一个按钮并监听该按钮上的单击事件,现在我们要获取用户输入,在我们的例子中,该输入将是钱包的种子短语或私钥。

要在 Telegram 中获取用户输入,我们需要创建一个名为“场景”的东西,所以基本上当我们想要来回获取用户的输入时(如果用户输入了错误的值),我们会维护一个场景,而当我们想要停止这样做时,我们会离开该场景。

让我们为导入钱包创建一个场景。

让我们遵循与实用程序函数相同的文件夹结构,首先,在项目的根级别创建一个文件夹 scenes,并在其中创建文件 importWalletScene.js index.js。

在 scenes/importWalletScene.js 文件中,添加以下代码

const { Scenes } = require("telegraf");

const importWalletScene = "importWalletScene";
const importWalletStep = new Scenes.BaseScene(importWalletScene);

importWalletStep.enter((ctx) =>
  ctx.reply(
    "Please provide either the private key of the wallet you wish to import or a 12-word mnemonic phrase."
  )
);

importWalletStep.on("text", (ctx) => {
  const phrase = ctx.message.text;
  ctx.reply("You entered" + phrase);
  ctx.scene.leave();
});

module.exports = {
  importWalletScene,
  importWalletStep,
};

在上面的代码中,我们只是监听文本事件,然后使用用户输入的文本进行回复。

在 scenes/index.js 文件中,添加以下代码

const importWalletScene = require("./importWalletScene");

module.exports = {
  ...importWalletScene,
};

再次,我们只是重新导出场景变量。

现在,在 index.js 文件中,你需要添加以下代码

const { Telegraf, Scenes, session } = require("telegraf");
const { createCallBackBtn } = require("./utils");
const { importWalletScene, importWalletStep } = require("./scenes");

const bot = new Telegraf(process.env.TG_WALLET_BOT_TOKEN);

const stage = new Scenes.Stage([importWalletStep]);
bot.use(session());
bot.use(stage.middleware());

...

bot.action("import-wallet", (ctx) => {
  ctx.scene.enter(importWalletScene);
});

在上面的代码片段中,我们只是导入了必要的变量,并为机器人放置了一些中间件,然后当用户点击“导入钱包”时,我们就会进入场景。

现在,如果你再次在终端中运行命令 node index.js,你必须能够得到以下内容

现在我们可以获取用户输入了。

现在,我们应该根据用户输入的短语生成帐户。

为此,我们需要创建一个新的实用函数来为我们执行此操作。

但是,在此之前,我们需要添加一些依赖项,因此让我们将 package.json 中的依赖项更新为以下内容

{
    ...,
    "dependencies": {
      "crypto-js": "4.1.1",
      "dotenv": "16.3.1",
      "ethers": "5.7.2",
      "express": "4.18.2",
      "telegraf": "4.12.2"
    }
}

现在,在 utils 文件夹中,创建一个encryption.js文件并添加以下代码

const crypto = require("crypto-js");

function encrypt(text) {
  return crypto.AES.encrypt(text, process.env.TG_WALLET_BOT_TOKEN).toString();
}

function decrypt(cipherText) {
  const bytes = crypto.AES.decrypt(cipherText, process.env.TG_WALLET_BOT_TOKEN);
  return bytes.toString(crypto.enc.Utf8);
}

module.exports = {
  encrypt,
  decrypt,
};

我们只是创建了一些辅助函数来加密和解密我们的信息,因为我们不能以纯文本形式存储敏感信息。

为什么是高级加密系统 (AES) 而不是 RSA 加密?您也可以在这里使用 RSA 加密,因为我们这里不处理大量数据。我使用了 AES 加密,因此我不必维护两个密钥。

现在,使用以下代码更新 utils/index.js 文件

const misc = require("./misc");
const encryption = require("./encryption");

module.exports = {
  ...misc,
  ...encryption,
};

并且,在 utils/misc.js 文件中,让我们添加辅助函数来生成帐户。

const { encrypt } = require("./encryption");
const { Wallet } = require("ethers");

...

function generateAccount(phrase, index = 0) {
  /**
   * If the phrase does not contain spaces, it is likely a private key
   */
  const wallet = phrase.includes(" ")
    ? Wallet.fromMnemonic(phrase, `m/44'/60'/0'/0/${index}`)
    : new Wallet(phrase);

  return {
    address: wallet.address,
    privateKey: encrypt(wallet.privateKey),
    mnemonic: encrypt(phrase),
  };
}

module.exports = {
  ...,
  generateAccount,
};

在上面的代码片段中,我们检查传递的短语是否是种子短语,然后使用派生路径获取给定索引处的钱包。我们还会在返回敏感信息之前对其进行加密。

现在,我们必须使用以下代码更新 scenes/importWalletScene.js 文件中的文本处理程序

importWalletStep.on("text", (ctx) => {
  const phrase = ctx.message.text;

  try {
    const wallet = generateAccount(phrase);
    ctx.reply("Address: " + wallet.address);
  } catch (error) {
    ctx.reply(
      "😔 This does not appear to be a valid private key / mnemonic phrase. Please try again."
    );
  }

  ctx.scene.leave();
});

我认为这里的代码是不言自明的。

现在,我们只需要检查一下这段代码。

首先,让我们再次运行 npm install。

之后,你可以运行 node index.js

如果输入了错误的种子短语/私钥,你将看到以下屏幕

但是,如果您输入正确的种子短语/私钥,您将在回复中收到地址。我不会在本博客中这样做,但如果您在执行此操作时遇到任何问题,您可以对该问题发表评论,我可以尝试进行调试。

啊!最后,钱包准备好了。

3、显示钱包

如果我们想让用户稍后也可以查看导入的钱包,该怎么办?

好吧,要做到这一点,您需要将导入的钱包存储在某个地方,稍后当用户单击“显示钱包”按钮(我们将为此提供一个按钮)时,我们将显示导入钱包的公共地址。

我们将存储从generateAccount函数返回的完整对象,因此如果您以后想使用私钥或助记词进行某些操作,您可以这样做。

我们不会在这里使用任何像DB这样的持久存储,所以我们会有一个类似非托管钱包的东西。

Telegram 有一种称为会话存储的功能,基本上,它会将信息保留在会话中,并且每当您重新启动服务器时,会话都会被清除。

让我们快速添加此功能。

首先,在 /start 命令消息中添加一个新按钮。为此,请在 index.js 文件中添加以下代码

bot.command("start", (ctx) => {
  ...

  const showWalletButton = createCallBackBtn("Show Wallet", "show-wallet");
    ctx.reply(message, {
      reply_markup: {
        inline_keyboard: [[importWalletButton], [showWalletButton]],
      },
    });
});

...

bot.action("show-wallet", (ctx) => {
  if (ctx.session.wallet) {
    ctx.reply(`Your wallet address is ${ctx.session.wallet.address}`);
  } else {
    ctx.reply("You have not imported any wallet yet.");
  }
});

现在,在 scenes/importWalletScene.js 文件中,我们必须在会话中添加新生成的钱包,为此添加以下代码

importWalletStep.on("text", (ctx) => {
  try {
    const wallet = generateAccount(phrase);

    ctx.session.wallet = wallet;
    ctx.reply(
      `🎉 Your wallet has been successfully imported. Your wallet address is ${wallet.address}.`
    );
  } catch (error) {
    ...
  }
});

如果你现在在终端中运行 node index.js 命令,导入钱包,然后单击显示钱包按钮(你可以输入 /start 命令并检查),你将看到类似以下内容

终于完成了🥱。您可以在这里找到完整的代码。


原文链接:Write your own Telegram Wallet bot

DefiPlot翻译整理,转载请标明出处

通过 NowPayments 打赏