Розроблення Telegram-бота для управління портфелем
Telegram — головна платформа крипто-спільноти. Управління портфелем прямо в мессенджері без перемикання між застосунками — логічний наступний крок. Бот може показувати залишки, відправляти сповіщення про зміни цін, виконувати своп через DEX-агрегатори та відслідковувати позиції у DeFi протоколах.
Архітектура
Варіанти зберігання кошелька
Режим спостереження. Користувач додає публічну адресу, бот тільки читає дані. Жодного ризику для коштів. Підходить для моніторингу.
Вбудований кошелек. Бот генерує key pair, зашифрована приватна дільниця зберігається в базі даних. Користувач встановлює пароль/PIN, який використовується для розшифровки при підписі. Найзручніший варіант для торгівлі, але вимагає безпечного зберігання.
Підключення існуючого кошелька. Через WalletConnect v2 користувач підключає MetaMask — транзакції підписуються у кошельку. Безпечно, але менш зручно (потрібен мобільний кошелек поблизу).
Стек
Telegram Bot API (telegraf.js)
↓
Bot Server (Node.js + TypeScript)
├── Portfolio Service (залишки через Alchemy/DeBank API)
├── DeFi Service (позиції: AAVE, Compound, Uniswap)
├── Wallet Service (генерація, шифрування ключів)
├── Trading Service (своп через 1inch/Paraswap API)
└── Alert Service (цінові сповіщення, попередження про ліквідацію)
↓
PostgreSQL + Redis (сеанси, кеш)
Реалізація основних функцій
Залишки та портфель
import { Telegraf, Context } from "telegraf";
import { message } from "telegraf/filters";
const bot = new Telegraf(process.env.BOT_TOKEN!);
bot.command("portfolio", async (ctx) => {
const userId = ctx.from.id;
const user = await userService.getUser(userId);
if (!user?.watchAddress) {
return ctx.reply("Додайте адресу гаманця: /add_wallet 0x...");
}
await ctx.reply("Завантажую портфель...");
const portfolio = await portfolioService.getPortfolio(user.watchAddress);
const message = formatPortfolioMessage(portfolio);
await ctx.reply(message, { parse_mode: "HTML" });
});
function formatPortfolioMessage(portfolio: Portfolio): string {
const totalUSD = portfolio.tokens.reduce((sum, t) => sum + t.valueUSD, 0);
let msg = `<b>Портфель</b> — $${totalUSD.toFixed(2)}\n\n`;
for (const token of portfolio.tokens.sort((a, b) => b.valueUSD - a.valueUSD)) {
const pct = ((token.valueUSD / totalUSD) * 100).toFixed(1);
msg += `${token.symbol}: ${token.balance.toFixed(4)} ($${token.valueUSD.toFixed(2)}, ${pct}%)\n`;
}
if (portfolio.defiPositions.length > 0) {
msg += `\n<b>DeFi позиції:</b>\n`;
for (const pos of portfolio.defiPositions) {
msg += `${pos.protocol}: $${pos.valueUSD.toFixed(2)} (${pos.type})\n`;
}
}
return msg;
}
Цінові сповіщення
interface PriceAlert {
userId: number;
token: string;
targetPrice: number;
direction: 'above' | 'below';
isTriggered: boolean;
}
// Worker який перевіряє сповіщення кожну хвилину
async function checkAlerts() {
const activeAlerts = await db.alerts.findActive();
const tokens = [...new Set(activeAlerts.map(a => a.token))];
const prices = await priceService.getPrices(tokens);
for (const alert of activeAlerts) {
const currentPrice = prices[alert.token];
const triggered =
(alert.direction === 'above' && currentPrice >= alert.targetPrice) ||
(alert.direction === 'below' && currentPrice <= alert.targetPrice);
if (triggered) {
await bot.telegram.sendMessage(
alert.userId,
`🔔 ${alert.token} досяг $${currentPrice.toFixed(2)} (ціль: $${alert.targetPrice})`
);
await db.alerts.markTriggered(alert.id);
}
}
}
Вбудовані клавіатури для навігації
Зручний UX для бота — вбудовані кнопки замість команд:
bot.command("start", async (ctx) => {
await ctx.reply("Головне меню", {
reply_markup: {
inline_keyboard: [
[
{ text: "📊 Портфель", callback_data: "portfolio" },
{ text: "💰 Залишки", callback_data: "balances" },
],
[
{ text: "🔄 Своп", callback_data: "swap" },
{ text: "🔔 Сповіщення", callback_data: "alerts" },
],
[
{ text: "⚙️ Налаштування", callback_data: "settings" },
],
],
},
});
});
Безпека зберігання ключів
Якщо бот зберігає приватні ключі користувачів — це критична відповідальність:
- Шифрування AES-256-GCM з ключем = KDF(user_pin + server_secret)
- Server secret зберігається в AWS Secrets Manager (не у коді)
- PIN ніколи не зберігається, тільки перевіряється через спробу розшифровки
- Автоматичний вихід після N хвилин неактивності
- Обмеження на транзакції (максимальна сума на день)
- Whitelist адрес-одержувачів
Джерела даних для портфеля
| Джерело | Що надає |
|---|---|
| Alchemy Token API | ERC-20 залишки по адресі |
| DeBank API | DeFi позиції (AAVE, Compound, Uniswap LP) |
| CoinGecko API | Ціни токенів |
| 1inch API | Котирування своп |
| Etherscan API | Історія транзакцій |
Базовий бот для моніторингу (watch-only, залишки, DeFi позиції, цінові сповіщення) — 2-3 тижні. Версія з вбудованим гаманцем та своп — 4-6 тижнів включаючи security review.







