Skip to content
Back to Home
PR Collective

Depin Bot

TypeScript grammY @grammyjs/runner OpenAI Stable Diffusion ComfyUI IoTeX TypeORM PostgreSQL

Depin Bot is a Telegram bot that bundles OpenAI chat, DALL-E, and a self-hosted Stable Diffusion pool behind a credit balance that users top up by sending IoTeX to a per-user address. Everything settles inside Telegram, with no checkout page, wallet popup, or leaving the chat.

The runtime is grammY driven by @grammyjs/runner for concurrent updates. Sessions live in memory with a 48-hour TTL, and module dispatch is a manual chain in the message handler that walks a payable-bots map (voice, image, OpenAI) and a utility-bots map (walletconnect, payments, schedule), letting each module claim the update. Errors fall through bot.catch plus a top-level boundary, with Sentry capturing across every async path.

Image routing is prefix and command driven. DALL-E commands push jobs onto a per-user queue and the worker drains through OpenAI's image API. Stable Diffusion commands hit a separate ComfyUI-compatible balancer over HTTP: the bot posts a model + LoRA spec, gets back an operation id, queue position, and an assigned worker host, then polls until status leaves WAITING and reports completion back so the balancer can release the worker. LoRA selection is parsed from prompt flags, and GIF jobs default to a motion LoRA. Because the balancer owns scheduling, a node going offline just stops claiming jobs - the bot never tracks node health itself.

The OpenAI layer keeps a per-session conversation array seeded with a system prompt; model is picked by command (3.5, 4, 32k, vision). Replies stream by appending each chunk and editing the same Telegram message on a doubling word-count cadence (2, 4, 8 ... 64) so the API doesn't rate-limit. gpt-tokenizer counts tokens locally to price each turn.

Deposit detection is balance-polling, not log scanning. A bootstrap loop runs every minute, asks Postgres for accounts active in the last 24 hours, derives each user's IoTeX address from a server-held secret (so the same Telegram user always reaches the same address), calls eth_getBalance, and if a deposit clears the gas-reserve threshold it builds a sweep transaction to a multisig holder. A small LRU cache of pending nonces (keyed by sender, short TTL) deduplicates in-flight sweeps so a slow RPC reply can't mint two invoices for the same deposit. Each successful sweep creates an Invoice row and increments the user's crypto-credit column.

The Postgres schema is small and TypeORM-managed: users one-to-many chats, with three credit columns for the free tier, IoTeX-funded credits, and Telegram Payments. Withdrawals draw down free first, then crypto, then fiat in a single update, so a $5 fiat purchase and a $5 crypto deposit reach the same call site. Telegram Payments lands the same way: an invoice goes out inline, pre-checkout validates, and on successful_payment the cents amount is converted to IOTX at the live CoinGecko rate before bumping the fiat column.