A Telegram bot that turns any chat or community into a financial ecosystem: instant USDC tips, Polymarket-style prediction markets with live AMM odds, an AI assistant, paywalled content, and per-user wallets — all on Base. No custom contracts in the hot path: only the official USDC contract plus an optional audited-style treasury vault; everything else is instant internal accounting backed by public proof-of-reserves.
Made by @ssrjkk.
Author: @ssrjkk · @b2wmain · X / Twitter · GitHub
Links: Telegram Bot
Whitepaper: docs/WHITEPAPER.md — the full function inventory, the growth roadmap, and what the product can earn (grants, subscriptions, fees).
| Desktop | Mobile |
|---|---|
![]() |
![]() |
/tip 5 @nick— or reply/tip 5to any message- Recipient gets an immediate DM notification
/rain 10 [N]— scatter USDC across active group members- emoji reactions tip the message author (groups)
/market create 50 Who wins? | Alice | Bob 7d— creator funds the AMM liquidity- Live odds that move with demand — Hanson's Logarithmic Market Scoring Rule,
exact
Decimalmath (b = subsidy / ln(n)) /trade <id> <opt> <amount>— buy outcome shares at the live price/sell <id> <opt> [50%]— sell back any time before resolution (exit anytime, not locked until the end like parimutuel pools)/positions— your portfolio with live mark-to-market value and PnL- Resolution pays 1 USDC per winning share; the market creator keeps the remaining liquidity pool as their earnings
- Guaranteed solvency by the LMSR funding theorem: the escrow can always cover the worst-case payout, verified by property tests along aggressive random trading paths
- Deadline pings + grace-period auto-refund protection for forgotten markets
/bet create Question | Option 1 | Option 2 [24h],/bet <id> <opt> <amount>- Winners split the whole pot proportionally (2% fee on net profit to the creator)
- Inline cards, quick-amount buttons, two-tap resolution, cancel/refund paths
/oc_create 50 Who wins? | Alice | Bob 7d— creates a market in the OutcomeMarket.sol contract: the subsidy is locked on-chain, shares are real ERC-1155 tokens, every trade is a USDC transfer anyone can verify on Basescan/oc_buy <id> <opt> <amount>//oc_sell <id> <opt> [50%]— trade at the live LMSR price with hard on-chain slippage caps (maxCost/minProceeds)/oc_redeem <id>— pull resolution payouts straight from the contract/oc <id>//oc_pos— live odds and your ERC-1155 positions- Oracle proposes the winner, the owner can dispute within 2h (once — after a dispute only the owner finalizes), and anyone can refund an abandoned market 24h after close — refunds are hard-capped at $1/share so the creator subsidy can never be drained
- Labels live in a bot-side registry (the contract stores numbers only); gas for first trades is auto-topped-up from the hot wallet with a per-wallet anti-drain cooldown
/ask <question>— ask about crypto, Base, market strategy, bot usage- Works with any OpenAI-compatible API (OpenAI, Groq, OpenRouter, local
vLLM/llama.cpp) via
AI_API_URL/AI_API_KEY/AI_MODEL;AI_PROVIDERSlists fallbacks, a 429 or a revoked key parks that endpoint and the next one answers - With no model reachable,
/askstill answers from the ledger — open markets and pools with live odds, or the command list — and says that it did - Reply to a message with
/askto use it as context; rate-limited, typing indicator
/donate— personal donation page with QR (t.me/<bot>?start=donate_<id>)- Deposits auto-credit with push notifications (Basescan tx link included)
/link <address>+ signature → automatic deposit crediting (ecrecover-verified; a deposit can only be claimed by the wallet's owner — never by tx-hash sniping)/wallet— built-in custodial wallet, export/import by seed phrase/withdraw <address> <amount>— on-chain payout (1% fee, min 1 USDC, ≤5/day), staged behind an explicit Confirm tap before anything is debited, full auto-refund for stuck/reverted transactions/tx <hash>— look up any Base transaction and decode its USDC transfer
/basename— your on-chain name (ENSIP-19 reverse resolution of your deposit address against the Base L2 resolver); shows in/walletand the public donate page automatically/basename <name>.base.eth— on-chain availability check: free (with a registration hint), taken (owner address), or confirmed yours when it resolves to your linked/custodial wallet- Tips by name:
/tip <name>.base.ethresolves the basename to its on-chain owner — the chain is the source of truth, nothing is stored bot-side
/paywall create 5 Title→ sell posts for USDC (buyers read instantly)/paywall channel 5→ paid Telegram channel access, 5 USDC / 30 days, one-time invite links, expired subscribers auto-kicked- x402 HTTP payments:
POST /api/x402/tipandPOST /api/x402/paywall— AI agents pay on-chain via the 402 handshake (invoice → pay → replay-proof credit)
- Perceives crypto news → LLM filters noise → creates markets, bets, sells analysis as paywall posts — every action EAS-attested on Base
- News sources: CryptoPanic (with
CRYPTOPANIC_TOKEN) plus free RSS fallbacks (CoinDesk, CoinTelegraph); deduplication and relevance scoring built in - Runs inside the main process (
deploy/run.py) whenAGENT_TG_ID > 0and the cap set validates — no separate service needed; a silent agent death stops the process like any other watcher (fail-fast) - State (caps counters, seen-news, audit trail) lives in
AGENT_STATE_DIR(default: theagent/package dir) so a restart never resets the daily cap - Spend is capped in code (never in the prompt): daily + per-tx caps, actions per hour, circuit breaker with cooldown; caps are validated at startup and the agent refuses to run on a misconfigured set
- LLM failure = no action (fail-closed); the agent can never trade on its own markets (DB-level guard)
/agent(admin-only) — live caps state, circuit-breaker status and the agent's recent actions straight in Telegram, no web dashboard needed
- Live stats, volume chart, markets with odds/backers, leaderboards, user profiles
- Proof of Reserves
/api/solvency: bot liabilities vs on-chain USDC (read from the TipBotVault contract when deployed, else the hot wallet) - Base design system UI — light (default) + dark theme with a toggle, on the
tokens measured on base.org: brand
#0000ff/#224bff, canvases#ffffff/#111111, Schibsted Grotesk with Golos Text behind it for Cyrillic, Geist Mono for every number - Public JSON API:
/api/stats,/api/markets,/api/predictions,/api/prediction/{id},/api/leaderboard,/api/user/{id},/api/info,/api/health,/qr, rate-limited per IP
- Per-user Smart Accounts via CREATE2 (
SmartAccountFactory) — deterministic counterfactual addresses; no ETH needed from the user - VerifyingPaymaster sponsors gas — users tip/trade without ever holding ETH
(Base Sepolia proven: direct
handleOpsand gasless paymaster UserOps, status=1) - The operator holds the keys, not the user —
SmartAccount.owneris the relayer address (bot/smart_wallet.py::_owner, derived fromHOT_WALLET_KEY), and that key signs every UserOperation. Gasless is what the user pays with custody; the same rule is stated indocs/SECURITY.md(«The hot wallet is custodial by design»). bot/smart_wallet.pybuilds + signs UserOperations (EIP-191) and drivesapproveAndTradefrom the wallet's own USDC- Details:
docs/ARCHITECTURE.md(Smart Wallet section)
4 killer functions leveraging unique Base L2 capabilities:
New users get 10 FREE transactions — zero barrier to entry.
/gasless— check your free transaction balance- Uses Base Paymaster API (Pimlico) to sponsor UserOperations
- New wallets automatically qualify; gas paid by the protocol
- After 10 free txs — standard Base fees (still just fractions of a cent)
/gasless -> You have 10 of 10 free transactions left!
Gas is sponsored by Base — you pay nothing.
Why it's a breakthrough: Traditional bots require users to hold ETH for gas. Base Paymaster eliminates this entirely — users onboard with USDC only and transact for free until they're hooked.
Automated scheduled transfers — daily, weekly, biweekly, monthly.
/subscribe @user <amount> <interval>— create a subscription/subscriptions— view all active subscriptions/cancelsub <id>— cancel a subscription- Background executor runs hourly and auto-processes due payments
- Supports: daily (24h), weekly (7d), biweekly (14d), monthly (30d)
/subscribe @creator 10 monthly -> Subscription created!
@creator: $10.00 every monthly
Why it matters: the schedule lives in the bot's own Postgres and an hourly watcher debits the internal USDC balance — no external billing service, nothing to renew by hand. Creators use it for patronage, communities for paid memberships.
Issue tokens that automatically distribute your earnings to holders.
/createtoken <name> <SYMBOL> <supply> <price>— launch a creator token/buytoken <token_id> <amount>— buy a creator's tokens/claim <token_id>— claim your share of their revenue- When creators earn (tips, market winnings), revenue automatically splits:
- Proportional to holder balance
- No manual distribution needed
- Dividends accrue per second
/createtoken "My Token" MTK 1000000 0.10
-> Token created! ID: ct_123456_1790013544
Holders receive dividends from your earnings automatically.
/buytoken ct_123456_1790013544 1000
-> Bought 1000 tokens for $100.00!
[Creator earns $50 in tips]
-> Dividend auto-distributed: $0.05 per token
/claim ct_123456_1790013544
-> Claimed $50.00 in dividends!
Why it's a breakthrough: This is the creator economy natively on-chain. Fans invest in creators, creators share revenue automatically — all powered by Base's smart accounts. No traditional equity needed; the token IS the revenue share.
- Users deposit USDC into the vault contract — visible to anyone on Base
- Relayer distributes under a daily limit; owner (multisig) keeps full control
Distributedevents make every payout publicly auditable
Tippy runs as a private production deployment operated by its maintainers. The source is published for transparency and audit; there is no public run-it-yourself guide, and contract deployment stays with the team (vault/market owners are multisigs, never the hot wallet).
A plain-language walkthrough for Telegram users lives in docs/USER_GUIDE.md — the table below is the short form.
| Command | What it does |
|---|---|
/menu · /help |
Menu with all sections, command list |
/tip 5 @nick |
Instant USDC tip (or reply to a message) |
/market create 50 Q | A | B [24h] |
Create an AMM prediction market |
/markets · /trade · /sell · /positions |
Trade shares at live odds |
/oc · /oc_create · /oc_buy · /oc_sell · /oc_redeem · /oc_pos |
On-chain markets (OutcomeMarket.sol, ERC-1155) |
/bet create Q | A | B [24h] · /bets · /mybets · /resolve · /cancel |
Parimutuel polls |
/ask <question> |
AI assistant |
/deposit / /claim <tx> / /link / /confirm |
Fund your account (private chat only) |
/withdraw <addr> <amt> |
On-chain payout — 1% fee, min 1 USDC, ≤5/day (atomic DB cap), needs a Confirm tap, private chat only |
/wallet · /import · /export |
Per-user key pair, generated in chat |
/tx <hash> |
Decode a Base transaction |
/rain 10 [N] |
Group giveaway |
/donate |
Your donation page, linkable from anywhere |
/paywall ... |
Paid posts and channels |
/balance / /stats / /top / /history |
Analytics |
/gasless |
Check free gasless transactions |
/subscribe @user <amt> <interval> · /subscriptions · /cancelsub |
Recurring payments |
/createtoken <name> <SYM> <supply> <price> |
Launch a creator token |
/buytoken <id> <amount> · /claim <id> |
Buy tokens / claim dividends |
/basename |
Claim a Basename (on-chain identity) |
/settings · /language · /about · /app |
Notifications, ru/en/zh, what this is, Mini App |
/admin |
Owner-only panel: users, volume, fees, treasury against liabilities, deposit-scanner lag, AI chain and its daily budget — read-only, private chat only |
bot/
├─ main.py entrypoint, background watchers (deposits, withdrawals, deadlines)
├─ handlers/ aiogram handlers by domain
│ ├─ _common.py shared helpers, router, menu KB
│ ├─ menu.py /start, /menu, settings, language, broadcast
│ ├─ wallet.py /deposit, /withdraw, /balance, /link, /claim
│ ├─ tips.py /tip, /rain, reaction tips
│ ├─ bets.py parimutuel /bet, /bets, /resolve, /cancel
│ ├─ markets.py LMSR AMM /market, /trade, /sell, /positions
│ ├─ onchain.py /oc_* on-chain OutcomeMarket commands
│ ├─ paywall.py /paywall, paid posts/channels
│ ├─ stats.py /stats, /top, /history
│ ├─ ai.py /ask AI assistant
│ ├─ basename.py /basename on-chain identity
│ ├─ agent.py /agent admin dashboard
│ ├─ admin.py /admin — the owner's read-only panel
│ └─ breakthrough.py /gasless, /subscribe, /createtoken
├─ ledger/ PostgreSQL accounting + LMSR AMM engine (Decimal-exact)
│ ├─ __init__.py Ledger facade + singletons + lmsr_* re-exports
│ ├─ _core.py connect/schema/ping
│ ├─ _schema.py DDL
│ ├─ _conn.py ReconnectingConn
│ ├─ _users.py accounts, wallet links, create2
│ ├─ _pay.py / _paywall.py / _transfer.py x402, paywalls, transfers
│ ├─ _withdraw.py AML, batches, refunds
│ ├─ _audit.py audit_log rows: who did what to whose money
│ ├─ _ai.py the shared AI budget and provider health, as DB rows
│ ├─ _bets.py / _markets.py parimutuel + LMSR AMM (buy/sell/resolve)
│ ├─ _onchain.py on-chain outcome markets registry
│ ├─ _recurring.py subscription executor
│ ├─ _paymaster.py gasless onboarding
│ ├─ _creator.py creator tokens + dividends
│ ├─ _messages.py / _notify.py / _admin.py / _views.py
│ └─ _base.py audit_log, MICRO, LMSR math
├─ base.py web3 layer: USDC transfers, deposit scanning, tx decoding
├─ chain/ on-chain helpers
│ ├─ core.py RPC, chain head, block polling
│ ├─ transactions.py tx status, receipts
│ ├─ transfers.py USDC transfer helpers
│ ├─ tokens.py token metadata, decimals
│ ├─ dex.py price feeds
│ ├─ prices.py quote helpers
│ ├─ basenames.py ENSIP-19 reverse resolution
│ └─ network.py chain labels, explorer URLs
├─ ai.py provider chain: failover, parks, shared daily budget
├─ ai_data.py /ask without a model, answered from the ledger
├─ qr.py local QR generation
├─ smart_wallet.py ERC-4337: UserOp build/sign, paymaster data, approve+trade sync
├─ paymaster.py Base Paymaster integration: gasless onboarding (10 free txs)
├─ recurring.py Recurring payments: subscriptions executor (hourly watcher)
├─ creator_tokens.py Revenue sharing: creator tokens + dividend distribution
├─ create2.py CREATE2 deterministic address computation
├─ solvency.py Proof-of-reserves: liabilities vs on-chain USDC
├─ wallets.py Custodial wallet: seed export/import, balance
├─ tip_targets.py Username/name resolution for tip recipients
├─ commands_catalog.py Command registry for /help
├─ telegram_transport.py Telegram API wrapper (send/edit/delete)
├─ x402_sweep.py x402 invoice settlement sweeper
├─ onchain_market.py OutcomeMarket contract ABI + helpers
├─ i18n.py RU/EN/ZH message tables
├─ fees.py the one money notation: USDC labels, fee rates, percentages
├─ tx_view.py one tx_log row → one label (kind decides sign and counterparty)
└─ config.py env-driven configuration
agent/ autonomous market-maker: news → LLM → markets, EAS attestations
web/
├─ server.py FastAPI: public API, proof-of-reserves, x402 endpoints
├─ auth.py Telegram OAuth, session cookies, rate limiting
├─ mini.py Mini App: balance, tip, deposit, withdraw, markets
├─ refusals.py Refusal sentences, in the language the caller reads
├─ x402.py x402 handshake: invoice → verify → replay-proof credit
├─ x402_spec.py x402 protocol spec + types
├─ metrics.py Prometheus metrics endpoint
├─ frame.py Farcaster Frame endpoints
├─ hook.py Telegram webhook handler
└─ static/ Base-design dashboard + Mini App (CSP nonce, no inline JS)
contracts/
├─ TipBotVault.sol on-chain treasury (proof of reserves)
├─ OutcomeMarket.sol on-chain markets (ERC-1155 shares, LMSR on-chain)
├─ SmartAccount.sol ERC-4337 account (CREATE2)
├─ SmartAccountFactory.sol deterministic account factory
├─ VerifyingPaymaster.sol gas-sponsoring paymaster
├─ Create2Factory.sol generic CREATE2 factory
├─ LMSR.sol on-chain LMSR market maker
├─ MiniUSDC.sol minimal USDC mock for testing
└─ USDCForwarder.sol USDC transfer helper
scripts/ deploy, smoke, backup, restore and the i18n check
deploy/ container entrypoint, launch supervisor, tunnel, oracle bootstrap
functions/ the Cloudflare Pages edge: bundle assets, proxy the rest to the origin
tests/ real Postgres, real dispatcher, real crypto, local EVM
python -m ruff check bot web tests deploy agent scripts alembic
python -m pytest -q -m "not production" # 1336 passedTests need a PostgreSQL 16 on localhost:5432 with a tipbot role (password
tipbot): tests/conftest.py drops and recreates tipbot_test once per
session, so the dev database is never touched. Point TEST_DATABASE_URL and
TEST_ADMIN_DATABASE_URL elsewhere if your server listens somewhere else. The
171 production-marked tests are excluded from this run — they check the
deployed site and belong to the Prod Health Check workflow.
What is tested for real (not mocked): money conservation across every flow
(tips, fees, refunds, parimutuel payouts, rain, AMM buy/sell/resolve/cancel
— balances + escrows always sum to deposits), deposit-security (claiming
someone else's tx is rejected), fee math, real signature recovery, the full
aiogram dispatcher with real Update objects, USDC ABI decoding, the FastAPI
dashboard against a real ledger, background watchers, 15 end-to-end scenarios,
and 13 TipBotVault tests on a local EVM (eth-tester + py-evm, real compiled
bytecode). Only external networks are mocked (Telegram transport, RPC) —
tests/conftest.py pins the chain endpoint to a refused port, because a test
that reads a live node answers
whatever that node holds: on Base mainnet one of the suite's test addresses
carries EIP-7702 delegation code, so /withdraw there refuses it as a smart
contract while the same test passes against a Sepolia endpoint.
The LMSR engine additionally has a property test proving the funding theorem: along randomized aggressive trading paths the escrow never drops below the worst-case payout.
HOT_WALLET_KEYis money — never commit.env- Official USDC only:
0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 - Prediction markets rely on the creator resolving honestly; deadline + grace auto-refund bounds the damage of abandoned markets
- Anti-spam cooldowns, per-day withdrawal limits, gas-griefing protection
- Sensitive commands (
/withdraw,/deposit,/claim,/link,/confirm,/export,/import,/paywall subscribe) answer only in private chats; the daily withdrawal cap is enforced atomically in the database /withdrawis two-step: it only stages a payout, and the debit happens on an explicit Confirm tap. The staged request is single-use (DELETE ... RETURNING), expires inWITHDRAW_CONFIRM_TTL_SECONDS(default 10 min), is bound to the requesting tg_id, and the fee is frozen at staging time — so the number you confirm is the number that is charged- First-party destinations (zero address, hot wallet, vault, x402 pool) are
blocked by one shared
blocked_destination()helper used by both the handler and the ledger, so the refusal reason shown can never drift from the one enforced — and each reason gets its own message - All bot output is HTML-escaped (no Markdown injection from user titles); the dashboard serves a strict CSP (nonce-based scripts) with zero inline event handlers; web login nonces are single-use with a TTL and pruned
- Multi-relayer withdrawals keep per-relayer daily caps in a persisted state
file (a restart cannot reset the budget); relayer keys and caps are
validated by
python scripts/validate_env.py - The autonomous agent is fail-closed: LLM errors mean no action, caps are validated at startup, and the DB blocks trading on its own markets
- Per-user deposit addresses (CREATE2 vaults)
Smart Wallet (ERC-4337) + gasless paymastercore shipped + Sepolia-proven (P2)Withdrawal batching for gas savingsshipped (queued payouts flushed as one vault batch, direct-send fallback)- Order-book style CLOB on top of the AMM
On-chain market escrow (resolution via a UMA-style oracle)shipped as Cally (OutcomeMarket ERC-1155): an oracle proposes, the owner has 2h to dispute. Not trustless — with noORACLE_PRIVATE_KEYconfigured the bot resolves through the owner key, so one signature holds both roles.
PRs welcome — see docs/CONTRIBUTING.md for setup, style rules, and the money-conservation requirement for any fund-touching change. Security issues: docs/SECURITY.md (no public issues). Community rules: docs/CODE_OF_CONDUCT.md. Licensed under MIT.
Author: @ssrjkk · @b2wmain · X / Twitter · GitHub
Built on Base · Powered by USDC
git clone https://github.com/ssrjkk/tippy-on-base.git
cd tippy-on-base
python -m pip install -r requirements.txt -r requirements-dev.txt
cp .env.example .env # then fill in BOT_TOKEN and the wallet keyspython deploy/run.py # bot + dashboard in one process
python -m bot.main # bot only (long polling)
python -m uvicorn web.server:app # dashboard only, on WEB_HOST:WEB_PORTThe dashboard listens on WEB_HOST:WEB_PORT (0.0.0.0:8000 by default) and the
bot answers in Telegram; docs/DEPLOY.md covers the server, docs/CLOUDFLARE.md
the Pages front.
SSRJKK — GitHub · Telegram · Projects hub · Bot catalogue



