Skip to content

Telegram Bot Example with Polkadot Agent Kit

A modern Telegram bot that interacts with the Polkadot ecosystem using the Polkadot Agent Kit, supporting native and XCM token transfers, balance checks, and more—all via natural language commands.


Features

  • Native Token Transfers: Send tokens on supported chains (e.g., Westend, Polkadot, Kusama).
  • XCM Transfers: Cross-chain token transfers using XCM.
  • Balance Checks: Query the agent's balance on any supported chain.
  • LLM Integration: Uses OpenAI (if API key provided) or Ollama for natural language understanding.

Tech Stack

CategoryTechnologies
Bot FrameworkTelegraf
BlockchainPolkadot Agent Kit
LLM SupportOpenAI, Ollama, LangChain
LanguageTypeScript
Utilitiesdotenv
Package Mgmtpnpm

Installation

1. Clone the repository

bash
git clone <your-repo-url>
cd polkadot-agent-kit/examples/telegram-bot

2. Install dependencies

bash
pnpm install --ignore-workspace

3. Set up environment variables

Create a .env file in the project root:

env
TELEGRAM_BOT_TOKEN=your_bot_token_here
PRIVATE_KEY=your_agent_private_key
OPENAI_API_KEY=your_openai_api_key   # Optional, for OpenAI LLM

4. Start the bot

bash
pnpm run dev

Project Structure

src/
├── handlers.ts      # Telegram message handlers and LLM integration
├── index.ts         # Entry point, loads env and starts the bot
├── models.ts        # LLM provider abstraction (OpenAI or Ollama)
├── TelegramBot.ts   # Main bot class, agent and LLM setup

Example Usage

After starting the bot:

  1. Open Telegram and search for your bot by username.
  2. Start a chat and use commands like:
    • transfer 1 DOT to <address> on polkadot
    • check balance on polkadot
    • transfer 0.1 DOT to <address> from polkadot to polkadot_asset_hub
    • check proxies on polkadot
    • Use /help or /start for instructions.

Key Code Snippets

Entry Point (src/index.ts)

ts
import { TelegramBot } from "./TelegramBot";
import * as dotenv from "dotenv";
dotenv.config();

async function runBot() {
  const bot = new TelegramBot({
    botToken: process.env.TELEGRAM_BOT_TOKEN!,
    openAiApiKey: process.env.OPENAI_API_KEY!,
    privateKey: process.env.PRIVATE_KEY!,
  });

  await bot.start();

  process.once("SIGINT", () => bot.stop());
  process.once("SIGTERM", () => bot.stop());
}

runBot();

Main Bot Class (src/TelegramBot.ts)

ts
import { Telegraf } from "telegraf";
import { setupHandlers } from "./handlers";
import { getLangChainTools, PolkadotAgentKit } from "@polkadot-agent-kit/sdk";
import { ChatModelFactory, ChatModelOptions, ChatModelWithTools } from "./models";

export class TelegramBot {
  // ...constructor and LLM setup omitted for brevity

  async initialize() {
    await this.agent.initializeApi();
    const tools = getLangChainTools(this.agent);

    setupHandlers(this.bot, this.llm, tools);

  }

  public async start(): Promise<void> {
    await this.initialize();
    await this.bot.launch();
  }

  public async stop(): Promise<void> {
    await this.agent.disconnect();
    this.bot.stop();
  }
}

Handler Setup (src/handlers.ts)

ts
import { Telegraf } from "telegraf";
import { HumanMessage, SystemMessage } from "@langchain/core/messages";
import { DynamicStructuredTool } from "@langchain/core/tools";
import { ChatModelWithTools } from "./models";

// SYSTEM_PROMPT omitted for brevity

export function setupHandlers(
  bot: Telegraf,
  llm: ChatModelWithTools,
  toolsByName: Record<string, DynamicStructuredTool>,
): void {
  bot.start((ctx) => {
    ctx.reply(
      "Welcome to Polkadot Bot!\n" +
        "I can assist you with:\n" +
        '- Transferring native tokens  (e.g., "transfer 1 token to westend_asset_hub to <address>")\n' +
        '- Checking balance (e.g., "check balance on west/polkadot/kusama")\n' +
        '- Checking proxies (e.g., "check proxies on westend" or "check proxies")\n' +
        '- Transfer tokens through XCM (e.g., "transfer 1 WND to <address> from west to west_asset_hub ")\n' +
        "Try asking something!",
    );
  });

  bot.on("text", async (ctx) => {
    // ...LLM and tool call logic
  });

  bot.catch((err, ctx) => {
    ctx.reply("An error occurred. Please try again.");
  });
}

LLM Model Factory (src/models.ts)

ts
import { BaseChatModel } from "@langchain/core/language_models/chat_models";
import { ChatOpenAI } from "@langchain/openai";
import { ChatOllama } from "@langchain/ollama";

export class ChatModelFactory {
  static create(options: ChatModelOptions): ChatModelWithTools {
    // ...implementation
  }
}

Customization & Extension

  • LLM Provider: Uses OpenAI if OPENAI_API_KEY is set, otherwise falls back to Ollama.
  • Chain Support: Update the agent configuration to support additional chains as needed.
  • Extend Commands: Add new tools or handlers in handlers.ts to support more blockchain operations.

Scripts

CommandDescription
pnpm run devStart the bot (dev mode)
pnpm run buildCompile TypeScript
pnpm run lintLint the codebase
pnpm run formatFormat the codebase

Troubleshooting

  • Ensure all environment variables are set.
  • If using OpenAI, ensure your API key is valid and has quota.
  • For Ollama, ensure it is running locally.
  • Check logs for errors during startup or message handling.

License

MIT


Contributing

Contributions are welcome! Please feel free to submit a Pull Request.


For more details, see the source code in the src/ directory.