**PayIT is a Telegram-native digital wallet and finance tool built for African SMEs and individual users. It lets people send, receive, and store digital dollars (USDC) directly inside Telegram, without needing to leave the app or learn new software. On top of the wallet, PayIT gives small business owners a simple invoicing and bookkeeping layer, so they can issue invoices, track VAT and WHT, and manage their business finances in one place.
PayIT is non-custodial. This means each user holds their own funds. PayIT never has access to a user's private keys or funds. The app only stores encrypted key material on the user's behalf and signs actions on the user's instruction.
The product has two connected but distinct experiences:
Personal Wallet β for individuals sending and receiving money. Business Wallet β for SMEs that need invoicing, ledgers, and tax support.
Vision: Vision To become the simplest way for African SMEs and everyday users to hold, send, and manage stablecoins, all inside an app they already use every day: Telegram. Mission: To give African SMEs a non-custodial, secure, and tax-compliant financial tool that removes the complexity of crypto and makes stablecoin payments and invoicing accessible to anyone with a Telegram account.
- Core Vision
- Key Features
- How It Works
- Architecture
- Tech Stack
- Quick Start
- Project Structure
- Core Modules
- Multimodal AI Agent
- Configuration
- ON/OFF-Ramp Strategy
- Bot Commands
- Security & Non-Custodial Design
- Arc Testnet Details
- Deployment
- Feature Status
- Contributing
PayIT enables a new economic model:
Traditional Flow:
User earns in local currency
β
Holds in local bank (0-2% APY, unstable)
β
Converts to safe currency for savings (expensive, risky)
PayIT Flow:
User earns in local currency
β
Receives payment in USDC via PayIT (instant, borderless)
β
Holds in personal, non-custodial wallet on Arc
β
Spends in local fiat via ON/OFF ramps (seamless conversion)
β
Issues invoices in local currency, gets paid in USDC
β
Business owners track cash flow, payroll, expenses in their timezone
- π Billions without stable wealth storage β local currencies erode value
- π± No native access to stablecoins β require crypto exchanges, KYC, fees
- πΌ SMEs using primitive tools β spreadsheets for invoicing, manual payout tracking
- π Walled gardens β funds locked in custodial exchanges
- πΈ ON/OFF ramps expensive β 2-8% fees per conversion
- β Non-custodial β users control their own wallets, no hidden master key
- β Telegram-native β no app installation, runs where users already chat
- β Multimodal input β voice, text, photos, PDFs, spreadsheets, PPTX
- β AI-powered intent β understand "send 5000 pesos to Maria" as easily as "0x7234..."
- β Local FX integration β seamless ON/OFF ramps via verified payment partners
- β Business features β invoicing, payroll, expense tracking, cash flow
- β Zero intermediaries β peer-to-peer, peer-to-business
- USDC (native gas, 1:1 USD)
- EURC (Euro Coin, 1:1 EUR)
- Real-time FX rates via DeFiLlama
- Non-custodial private key encryption (AES-256-GCM + scrypt KDF)
Planned for mainnet Arc launch:
- π₯ OFF-Ramp β Convert USDC β Local Currency (NGN, KES, GHS, etc.) via payment partner
- π€ ON-Ramp β Convert Local Currency β USDC via payment partner
- π¦ Payment Providers β Integrated with local FX aggregators (e.g., Wise-like partners, mobile money networks)
- β‘ Instant settlement β USDC lands in user's Arc wallet within seconds
Current Status:
- Testnet only (no real money flows)
src/offramp.js(Paj Cash blueprint) +src/gateway.js(Circle Gateway for token deposits)- Full ON/OFF-ramp architecture ready for mainnet deployment
- Payment provider integrations in progress
- Personal Wallet β Individual use, peer-to-peer transfers
- Business Wallet β Company/SME operations (invoices, payroll, expenses)
- One PIN, two wallets β toggle context instantly, no re-authentication
Understand any input format, execute reliably:
| Input | Example | Processing |
|---|---|---|
| Text | "send 5000 pesos to Maria" | Heuristic classifier + LLM fallback |
| Voice Note | ποΈ (user records payment request) | OpenAI Whisper transcription β classifier |
| Photo | π· (invoice photo) | GPT-4o vision β extract recipient, amount, date |
| π invoice.pdf | Parse text + LLM structuring | |
| PPTX | π¨ payroll.pptx | Extract slide text, map to payment rows |
| Excel/CSV | π recipients.csv | Smart column detection (Name, Amount, Account) |
Clarification Flow: When intent is ambiguous, bot asks targeted questions with button suggestions:
User: "send 5000"
Bot: "Send 5000 USDC to who?"
[π Choose from contacts] [βοΈ Paste address] [π New person]
- Invoicing β Generate invoices in local currency, receive in USDC
- Payroll β Schedule recurring payments to employees, contractors
- Expense Tracking β Categorize business expenses, generate reports
- Cash Flow Reports β Monthly trends, income vs. expenses
- Receipt Generation β PNG receipts with QR codes for verification
How it works:
- Business owner in Nigeria creates invoice in NGN (e.g., β¦500,000)
- Customer pays in USDC (e.g., $3.33) to business's Arc wallet
- Business receives USDC instantly, non-custodial
- Business uses OFF-ramp to convert USDC β NGN via payment partner (e.g., Wise, MoneyGram, local MFI)
- NGN lands in business's local bank within hours
Reverse flow:
- Freelancer in Kenya receives payment in local currency (KES)
- Customer sends USDC via PayIT
- Freelancer holds USDC on Arc (secure, borderless)
- When needed, freelancer uses ON-ramp to convert USDC β KES
- KES arrives in local M-Pesa or bank account
- One-time transfers with PIN confirmation
- Recurring payroll (e.g., every Friday at 9 AM)
- Cron-based automation with retry logic
- Real-time job status tracking
- Private key encryption: AES-256-GCM (PIN-derived key)
- Zero backend recovery: Lost PIN = lost funds (feature, not bug)
- Transient key decryption: In-memory only during signing
- Telegram auto-delete: Key exports auto-deleted after 60 seconds
User sends voice note to bot
β
"Pls sen 5000 naira to Emeka"
β
OpenAI Whisper transcribes
β
Intent Router classifies
intent: "transfer"
recipient: "Emeka"
amount: 5000
currency: "NGN" β inferred from context
β
Orchestrator creates payment plan:
{
type: "one_time",
amount: 5000 USDC equivalent,
recipient_address: "0xEmeka...",
currency_display: "NGN"
}
β
User confirms with PIN
β
Executor signs + broadcasts to Arc
β
Receipt generated + saved to ledger
β
Bot: "β
Sent 5000 NGN (~$3.33 USDC) to Emeka"
User taps "Withdraw to NGN"
β
Bot: "Convert how much USDC to NGN?"
β
User: "500"
β
Bot calculates rate (via payment partner API):
500 USDC = β¦827,500 NGN (current rate)
Conversion fee: 1% (~$5)
You receive: β¦808,825
β
User confirms
β
500 USDC transfered to Payment Partner's Arc wallet
β
Payment Partner converts USDC β NGN
β
NGN sent to user's bank/mobile money account
β
Bot: "β
β¦808,825 received to your M-Pesa. Ref: TX_123456"
User sets PIN: 1234
β
Scrypt derives encryption key from PIN + salt
β
AES-256-GCM encrypts private key
β
Server stores: { encrypted_blob, salt }
β
To sign a transaction:
User enters PIN β derive key β decrypt β sign β destroy plaintext
Key principle: Server never holds a decryptable copy of anyone's private key.
User Input (text/voice/image/file)
β
Voice Parser (if audio) β Transcription
β
Vision Parser (if image) β OCR extraction
β
File Parser (if PDF/PPTX/Excel) β Text extraction
β
Intent Router (classify + heuristics)
ββ Fast-path: "balance" β return balance
ββ Fast-path: "send $X to Y" β parse directly
ββ LLM fallback: Structured JSON classification
β
Clarification Flow (if ambiguous) β Ask user, preserve state
β
Orchestrator (parse β structured payment plan)
β
User confirms (view summary, enter PIN)
β
Executor (sign + broadcast to Arc RPC)
β
Ledger (record transaction)
β
Formatter & Notifier (send receipt to user)
Users
βββ telegram_id
βββ deposit_address (Arc wallet)
βββ encrypted_private_key (AES-256-GCM)
βββ salt (for key derivation)
βββ active_context ("personal" or "business")
βββ phone_verified (optional, for SMS OTP)
Business Profile
βββ user_id
βββ company_name
βββ tax_id
βββ business_address
βββ contact_name
Invoices
βββ invoice_id
βββ user_id
βββ recipient
βββ amount (in local currency)
βββ currency (NGN, KES, GHS, etc.)
βββ status (draft, sent, paid, overdue)
βββ due_date
Transactions
βββ tx_id
βββ user_id
βββ sender
βββ recipient
βββ amount (USDC)
βββ tx_hash (on-chain)
βββ status (pending, confirmed, failed)
βββ timestamp
Schedules
βββ schedule_id
βββ user_id
βββ plan (serialized payment plan)
βββ cron_expression ("0 9 * * MON")
βββ next_run
βββ status (active, paused)
| Layer | Technology |
|---|---|
| Chat Interface | Telegraf (Telegram Bot API) β no app installation needed |
| Blockchain | ethers.js 6.x, Arc Testnet (Circle's EVM L1) |
| AI / LLM | OpenAI (GPT-4o, Whisper), Gemini 2.0 Flash, Groq, Anthropic Claude |
| Database | SQLite (better-sqlite3) β embedded, zero-config |
| File Processing | pdf-parse, exceljs, jszip |
| Image Generation | sharp, @resvg/resvg-js (QR codes + receipts) |
| Automation | node-cron (scheduled jobs) |
| External APIs | Circle Gateway, DeFiLlama (FX rates), Termii (SMS), Wise-like partners (FX) |
| Crypto | Native Node.js crypto (scrypt KDF + AES-256-GCM) |
| Runtime | Node.js 22.5+ |
- Node.js 22.5 or newer
- A Telegram bot token (from @BotFather)
- At least one LLM API key (OpenAI, Gemini, or Groq)
-
Clone the repository
git clone https://github.com/igboze/PayIt.git cd PayIt -
Install dependencies
npm install
-
Set up
.envcp .env.example .env
-
Configure minimum required variables
TELEGRAM_BOT_TOKEN=<your_bot_token_from_@BotFather> ADMIN_TELEGRAM_IDS=<your_numeric_telegram_id> OPENAI_API_KEY=<from_platform.openai.com> # OR use GEMINI_API_KEY or GROQ_API_KEY INVOICE_FORWARDING_SECRET=<long-random-secret> PAYIT_DB_PATH=/app/payit.db
-
Run the bot
npm start
-
Open Telegram, find your bot, send
/start
- Send
/startto your bot in Telegram - Choose Personal or Business account
- Set a 4-digit PIN (this is your security key)
- Save your private key immediately β it displays once, auto-deletes after 60 seconds
- Get testnet USDC via Circle Faucet (select "Arc Testnet")
- Send a test payment:
send 10 to <your_address>or use voice notes
PayIt/
βββ bot.js # Main Telegram bot dispatcher
βββ package.json # Dependencies (Node 22.5+, Telegraf, ethers, etc.)
β
βββ src/ # Core wallet, database, blockchain logic
β βββ db.js # User management, account creation
β βββ wallet.js # Private key encryption, signing, AES-256-GCM
β βββ ledger.js # Transaction history & recording
β βββ gateway.js # Circle Gateway integration (USDC deposits)
β βββ offramp.js # Naira withdrawal via Paj Cash (testnet blueprint)
β βββ fx.js # Foreign exchange rates (DeFiLlama API)
β βββ tokens.js # Token metadata (USDC, EURC)
β βββ otp.js # SMS OTP verification (Termii)
β βββ savings.js # Yield tracking & cash flow analytics
β βββ payee_book.js # Contact management (saved recipients)
β βββ invoice_db.js # Invoice storage, status tracking
β βββ invoice_generator.js # Generate invoices as PNG with QR codes
β βββ receipt_generator.js # Generate payment receipts as PNG
β βββ biz_db.js # Business account records (expenses, etc.)
β βββ biz_profile.js # SME profile (company name, tax ID, etc.)
β βββ swap.js # Token swaps (DEX integration, not live yet)
β βββ conversation_state.js # Temporary state during clarification flow
β βββ svg_render.js # SVG utilities for image generation
β βββ svg_fonts.js # Embedded fonts for renders
β
βββ agent/ # Multimodal AI intent processing
β βββ ai_provider.js # Unified LLM provider (OpenAI/Gemini/Groq + mock)
β βββ intent_router.js # Intent classification + heuristic fast-path
β βββ orchestrator.js # Parse intent β structured payment plan
β βββ executor.js # Execute plan (sign, broadcast, confirm)
β βββ scheduler.js # Cron automation for recurring payments
β βββ store.js # Persist schedules to SQLite
β βββ voice_parser.js # Transcribe voice β text (Whisper)
β βββ vision_parser.js # Extract payment from images (GPT-4o/Gemini)
β βββ file_parser.js # Parse PDF, PPTX, Excel for bulk payments
β βββ invoice_parser.js # Extract invoice details (Anthropic Claude)
β
βββ tests/ # Integration & E2E test suites
β βββ integration_demo.js # Intent classifier + orchestrator demo
β βββ full_e2e_mock.js # End-to-end payment flow (mock AI)
β βββ samples_demo.js # PPTX/CSV sample generation
β βββ samples/ # Test files
β
βββ .github/
β βββ workflows/ci.yml # GitHub Actions CI (run tests on push)
β
βββ SETUP.md # Step-by-step setup guide
βββ PAYIT_DOCUMENTATION.md # Technical deep-dive (testnet design)
βββ AGENT_README.md # Multimodal AI agent reference
βββ README.md # This file β project overview
βββ .env.example # Template configuration
Non-custodial encryption & signing:
// User sets PIN
const encrypted = encryptPrivateKey(privateKey, pin);
// PIN β scrypt(32768 iterations) β AES-256-GCM key β encrypt
// To send a payment
const decrypted = decryptPrivateKey(encrypted, pin);
// Only correct PIN can decrypt; happens in-memory only
const signed = await signTransaction(tx, decrypted);
// Sign & immediately destroy plaintext key
// Private key is never logged, stored, or transmittedSecurity model: "Just in time" decryption β decrypt, use one operation, destroy.
ledger.recordTransaction({
user_id,
sender,
recipient,
amount,
token: "USDC" | "EURC",
tx_hash,
status: "pending" | "confirmed" | "failed",
timestamp
});
ledger.getTransactions(userId, limit); // Last 50 transactionsinvoiceDb.createInvoice({
user_id,
recipient,
amount,
currency: "NGN" | "KES" | "USD", // Display currency
description,
due_date,
status: "draft" | "sent" | "paid" | "overdue"
});
invoiceDb.markPaid(invoiceId, txHash, confirmationTime);Architecture for FX conversion on mainnet:
// Convert USDC β Local Currency via payment partner
const offrampTx = await offramp.convertToLocalCurrency(
amount, // USDC amount
targetCurrency, // "NGN", "KES", "GHS", etc.
userWalletAddress,
recipientLocalAccount // Bank account or mobile money ID
);
// Flow:
// 1. USDC locked in multi-sig contract (or payment partner's Arc wallet)
// 2. Payment partner converts on fiat side
// 3. Local currency deposited to user's bank/mobile money
// 4. Callback confirms success, stores tx hashCurrent state: Paj Cash integration blueprint. Full implementation awaits mainnet Arc launch.
Deposit USDC from other blockchains:
// Get gateway deposit address for on-ramp
const depositAddress = await gateway.getGatewayDepositAddress(userId);
// User sends USDC from Ethereum/Base/Polygon to this address
// Circle Gateway bridges USDC to Arc automaticallyThree-tier classification system:
-
Heuristic fast-path (zero LLM cost)
"balance"β instant response"0x7234..."β address detection"send 5000 to Maria"β parse directly
-
LLM fallback (structured JSON)
{ "intent": "transfer" | "balance" | "invoice" | "schedule", "confidence": "high" | "medium" | "low", "params": { "recipients": [{ "name_or_address": "Maria", "amount": 5000 }], "currency": "NGN" }, "missing": ["recipient_address"] } -
Clarification flow (ask + preserve state)
- Bot: "Who is Maria? Paste her Arc address or choose from contacts"
- User taps button β state re-attached β execution proceeds
const plan = await parsePaymentIntent(classified, userContext);
// Returns structured plan:
{
type: "one_time" | "recurring" | "scheduled",
payments: [
{
to: "0xMaria...",
amount: 5000,
token: "USDC",
recipient_name: "Maria",
display_currency: "NGN",
display_amount: "5000 NGN (~$3.33)"
}
],
summary: "Send 5000 NGN to Maria"
}const results = await executePlan(plan, pin, user);
// Results:
[
{
success: true,
recipient: "Maria",
amount: 5000,
txHash: "0xabc123...",
confirmationTime: 2000 // ms
}
]Flow:
- User enters PIN
- Decrypt private key (in-memory)
- Sign transaction
- Broadcast to Arc RPC
- Poll for receipt (max 30 seconds)
- Record in ledger
- Send receipt to user
- Destroy plaintext key
const { text } = await transcribeVoice(audioBuffer, mimeType);
// "Please send 5000 naira to Emeka"
// Re-enters text flow:
// intent_router.classifyIntent(text, userId, context)Provider: OpenAI Whisper (supports all audio formats)
const extracted = await parseImagePayment(imageBuffer, mimeType);
// Returns:
{
document_type: "invoice" | "receipt" | "payment_request",
recipient_name: "Emeka's Shop",
amount: 5000,
currency: "NGN",
date: "2026-06-28",
confidence: "high" | "medium" | "low"
}Providers: GPT-4o vision (primary) or Gemini 2.0 Flash (fallback)
// PDF invoices
const payments = await parsePdf(buffer);
// Excel/CSV spreadsheets
const rows = await parseSpreadsheetFile(buffer, isCSV);
// Auto-detects: Name | Amount | Account | Bank columns
// Handles: "Maria | 5000 | 0xMaria... | GTBank"
// PPTX presentations
const text = await parsePptx(buffer);
// Extracts text from all slides, structures with LLMSee AGENT_README.md for comprehensive agent documentation.
Voice Note:
User: ποΈ [records] "Hey, can you send 2000 pesos to Maria?"
Bot: [Transcribes via Whisper] β [Classifies as transfer] β [Asks: "Who is Maria?"]
User: [Pastes address or chooses from contacts]
Bot: β
Sends 2000 USDC equivalent
Photo of Invoice:
User: π· [uploads photo of invoice]
Bot: [Extracts via GPT-4o vision] β Recipient: "ABC Corp", Amount: 10,000, Date: 2026-06-28
Bot: Confirm payment? [β
Yes] [β No] [βοΈ Edit]
Excel Bulk Payments:
User: π [uploads payroll.csv]
Bot: [Detects columns] Name | Amount | Account
Maria | 5000 | 0xMaria...
John | 3000 | 0xJohn...
Bot: Send 5000 + 3000 = 8000 USDC to 2 recipients? [β
Confirm]
For deterministic testing without external APIs:
USE_MOCK_AI=1 npm startAll LLM calls return realistic but canned responses. Perfect for CI/CD, demos, and offline development.
# Telegram (from @BotFather)
TELEGRAM_BOT_TOKEN=<128-char_token>
ADMIN_TELEGRAM_IDS=<your_numeric_id>
# LLM (pick at least one)
OPENAI_API_KEY=<from_platform.openai.com>
# OR
GEMINI_API_KEY=<from_aistudio.google.com>
# OR
GROQ_API_KEY=<from_console.groq.com>OPENAI_API_KEY=<your_nvidia_api_key>
OPENAI_BASE_URL=https://integrate.api.nvidia.com/v1
OPENAI_MODEL=nvidia/llama-3.1-70b-instruct
OPENAI_VISION_MODEL=nvidia/llama-3.2-90b-vision-instruct
OPENAI_TRANSCRIBE_MODEL=nvidia/whisper-1# SMS verification (Termii)
TERMII_API_KEY=
# Naira off-ramp (Paj Cash β testnet blueprint)
PAJCASH_OFFRAMP_ADDRESS=
PAJCASH_API_KEY=
# Future: Payment providers for FX
# WISE_API_KEY=
# MONEYGRAM_API_KEY=
# LOCAL_MFI_API_KEY=
# Invoice parsing (Anthropic)
ANTHROPIC_API_KEY=
# Invoice settlement fee handling
APP_FEE_RECIPIENT_ADDRESS=0x0AC27C77C56f5176c37aE23BE3a42A130E3a9359
INVOICE_SETTLEMENT_FEE_BPS=100
INVOICE_SETTLEMENT_MIN_FEE_USDC=0.25
INVOICE_SETTLEMENT_MAX_FEE_USDC=2
INVOICE_SETTLEMENT_CONTRACT_ADDRESS=
# Contract deployment
DEPLOYER_PRIVATE_KEY=
# Token swaps (when router verified)
SWAP_ROUTER_ADDRESS=
# Testing
USE_MOCK_AI=1 # Run with deterministic mock responsesβ Architecture: Complete
src/offramp.jsβ Framework for USDC β Local Currency conversionsrc/gateway.jsβ Circle Gateway integration (external chain deposits)- Smart contract interfaces designed for multi-sig + payment partner settlement
β Implementation: On hold until mainnet Arc launch
- Arc testnet has no real value (can't convert USDC to real fiat)
- Payment provider APIs not yet tested
- KYC/AML flows designed but not deployed
When Arc mainnet launches, PayIT will enable:
1. User: "Withdraw 500 USDC to NGN"
2. Bot queries payment partner for rate: "1 USDC = 1655 NGN"
3. User confirms: "Receive β¦827,500 (after 1% fee)"
4. Bot locks 500 USDC in smart contract
5. Payment partner converts on fiat side
6. NGN β User's M-Pesa / bank account
7. Receipt: "β
β¦827,500 received to 07000000000. Ref: TX_123"
1. User: "Buy 500 USDC with NGN"
2. Bot: "Send β¦827,500 to account: GTBank 0123456789"
3. User transfers NGN (via bank app, M-Pesa, etc.)
4. Payment partner receives β confirms receipt via callback
5. Bot unlocks 500 USDC from smart contract β transfers to user's Arc wallet
6. Receipt: "β
500 USDC received. Ref: RX_456"
Target integrations (mainnet):
- π³π¬ Nigeria β Wise, Flutterwave, PayStack, local MFIs
- π°πͺ Kenya β Wise, M-Pesa, Equity Bank
- π¬π Ghana β Wise, local mobile money
- πΏπ¦ South Africa β Wise, local banks
- π Global β Wise, MoneyGram, local fiat on/off-ramps
API Pattern:
// Integration template
const fxProvider = {
getRate: async (amount, fromCurrency, toCurrency) => ({ rate, fee }),
initiateOffRamp: async (amount, recipientInfo) => ({ requestId, expiresAt }),
initiateOnRamp: async (amount, bankAccount) => ({ paymentDetails, timeout }),
checkStatus: async (requestId) => ({ status, receipt })
};Arc testnet is publicly accessible but:
- π« USDC on testnet has zero real value
- π« No payment providers support testnet fiat conversion
- π« Regulators don't license testnet partnerships
- β Full architecture is ready; just waiting for mainnet Arc
| Command | Shortcut | Purpose |
|---|---|---|
/start |
N/A | First-time: onboard, generate wallet, set PIN. Repeat: show address |
/balance |
π° Balance | Show USDC + EURC balance in Arc + estimated local currency value |
/receive |
π₯ Receive | Display Arc wallet address + QR code for receiving |
/send <amount> <address> |
N/A | Send USDC to Arc address (via text or voice) |
/sendout <amount> |
N/A | Send to external linked Arc wallet |
/withdraw <amount> |
N/A | Convert USDC β Local Currency via OFF-ramp (mainnet only) |
/deposit <amount> |
N/A | Convert Local Currency β USDC via ON-ramp (mainnet only) |
/invoice |
π Invoice | Create, view, mark paid invoices (local currency display) |
/payroll |
π΅ Payroll | Schedule recurring payments to employees, contractors |
/schedule |
β° Schedule | Set up one-time or recurring transfers |
/expense |
π Expense | Log business expenses (category, amount) |
/history |
π History | View recent PayIT transactions |
/export |
π Export | Show raw private key (PIN required, auto-deletes) |
/changepin |
π Change PIN | Re-encrypt wallet under new PIN |
/verifyphone |
βοΈ Verify | SMS OTP verification (optional) |
/yields |
πΉ Yields | View stablecoin APYs (info only, no auto-deposits) |
/swap |
π Swap | Exchange USDC β EURC or other tokens (not yet live) |
/settings |
βοΈ Settings | wallet, PIN, phone, business profile |
/cashflow |
π Cash Flow | Monthly income vs expenses report (business) |
/help |
β Help | Show all commands |
Each user's private key is encrypted with their PIN:
User's PIN: 1234
β
Scrypt (N=32768, r=8, p=1)
β
256-bit encryption key
β
AES-256-GCM (AEAD cipher)
β
Encrypted blob stored in database
β οΈ Server stores ONLY encrypted blob + salt
β οΈ Server NEVER stores plaintext PIN or key
1. User initiates payment
2. Bot displays summary (recipient, amount, expected fees)
3. User enters PIN
4. Bot derives key: scrypt(PIN + salt) β 256-bit key
5. Bot decrypts private key in memory
6. Bot signs transaction (ethers.SigningKey)
7. Plaintext key destroyed immediately
8. Signed TX broadcast to Arc RPC
- π΄ Forget your PIN? No recovery. Non-custodial means no master key to reset.
- π΄ Lose your backup? Funds are locked forever. This is by design.
- β This is a feature. True non-custodial means zero backdoors.
Tell users at onboarding: "If you forget your PIN and haven't saved your private key, those funds are permanently inaccessible. Write down your key and store it safely."
- π± Telegram bot messages are not end-to-end encrypted by default
- π Private key exports are shown in chat (outside user's device)
- πΈ User can screenshot (outside bot's control)
- π₯οΈ Telegram servers log messages (outside user's control)
Mitigations:
- β Auto-delete key exports after 60 seconds
- β Show key only once per command
- β
Warn users on
/exportabout risks - β Recommend password manager for backups
Best Practices (tell users):
- Save your private key immediately after onboarding
- Store in password manager (1Password, Bitwarden, KeePass)
- Use strong, unique PIN (4+ digits)
- Never share your PIN with anyone
- Delete key exports immediately after viewing
- Monitor
/historyfor suspicious transactions
| Parameter | Value |
|---|---|
| Name | Arc (Circle's EVM L1) |
| Status | Public testnet (no mainnet yet as of Jun 2026) |
| Chain ID | 5042002 |
| RPC | https://rpc.testnet.arc.network |
| Explorer | https://testnet.arcscan.app |
| Native Gas | USDC (1:1 USD pegged) |
| Faucet | https://faucet.circle.com (select "Arc Testnet") |
- βοΈ Reset frequency: Testnet can reset; no permanent data
- π΅ Token value: USDC on testnet = 0 real value (testing only)
- β‘ Block time: ~2 seconds
- π TX cost: ~0.0001 USDC per transaction
- π Blockchain: EVM-compatible (Ethereum-like RPC)
- Visit faucet.circle.com
- Select Arc Testnet
- Paste your Arc wallet address (from
/receivein bot) - Click "Get USDC"
- Wait ~2 seconds
- Check balance in bot:
/balance
Arc mainnet hasn't launched yet (as of June 2026). Once mainnet launches:
- β Real USDC will be deployable on Arc
- β OFF/ON-ramps will connect to real fiat networks
- β Business users can onboard production workloads
- β Full financial product features unlock
# Install & run locally
npm install
npm start
# Bot polls Telegram API (no ngrok needed)FROM node:22-alpine
WORKDIR /app
COPY . .
RUN npm ci
CMD ["npm", "start"]docker build -t payit .
docker run -d \
-e TELEGRAM_BOT_TOKEN=... \
-e OPENAI_API_KEY=... \
-v $(pwd)/payit.db:/app/payit.db \
payit- Push to GitHub
- Connect service (Railway/Heroku/Render)
- Set environment variables
- Deploy with
npm start
- Generate new bot token (rotate from development token)
- Set
ADMIN_TELEGRAM_IDSto production admins only - Use production LLM API keys (separate from dev)
- Configure
.envwith payment provider credentials (mainnet) - Enable database backups (daily snapshots)
- Set up alerting for failed transactions
- Monitor database size (SQLite grows with tx volume)
- Rate-limit bot commands (prevent abuse)
- Log all financial operations (audit trail)
- Test disaster recovery (restore from backup)
- β Personal + Business wallet generation
- β PIN-based key encryption (AES-256-GCM + scrypt)
- β Send USDC/EURC on Arc
- β Balance queries
- β Transaction history
- β Private key export (with auto-delete)
- β Change PIN
- β Voice transcription (OpenAI Whisper)
- β Image OCR (GPT-4o / Gemini vision)
- β PDF invoice parsing
- β Excel/CSV bulk payments
- β PPTX slide extraction
- β Clarification button flow
- β Scheduled payments (cron)
- β Intent classification with heuristics
- β Mock AI mode (deterministic testing)
- β GitHub Actions CI/CD
- β Invoice storage & status tracking
- β Receipt generation (PNG with QR)
- π§ OFF-Ramp (architecture ready; awaiting mainnet Arc + payment partners)
- π§ ON-Ramp (architecture ready; awaiting mainnet Arc + payment partners)
- π§ Circle Gateway (can deposit USDC from other chains to Arc)
- π§ Token swaps (code ready; router address not yet verified)
- π§ Naira off-ramp (Paj Cash blueprint; not yet tested on mainnet)
- π§ SMS OTP (Termii integration; optional)
- β Multi-signature wallets
- β Smart contract interactions (yield farming, staking)
- β Autonomous yield management (intentional β manual approval required)
- β Multi-language UI
- β Mobile app (Telegram Web App version in progress)
- β Mainnet Arc support (awaiting network launch)
# Integration tests (classifier, orchestrator, file parsing, voice)
node tests/integration_demo.js
# Full end-to-end payment flow (with mock executor)
node tests/full_e2e_mock.js
# Deterministic testing (mock AI, no external APIs)
USE_MOCK_AI=1 npm startGitHub Actions workflow (.github/workflows/ci.yml) runs all tests on every push:
- Checkout code
- Install Node 22
- npm ci (clean install)
- Run integration_demo.js (USE_MOCK_AI=1)
- Run full_e2e_mock.js (USE_MOCK_AI=1)Tests use mock AI to ensure deterministic, offline execution.
We welcome contributions! Please:
-
Fork the repository
git clone https://github.com/yourusername/PayIt.git cd PayIt -
Create a feature branch
git checkout -b feature/your-feature-name
-
Make changes & test
npm install USE_MOCK_AI=1 npm start # Test locally with mock AI -
Commit with clear messages
git commit -m "feat: Describe your feature clearly" -
Push & open a PR
git push origin feature/your-feature-name
- Use
const>let>var - Follow existing code style (see
bot.js,src/wallet.js) - Add tests for new modules
- Document security-critical code
- Test with
USE_MOCK_AI=1before committing - Update
.env.exampleif adding config vars - Keep commits atomic (one feature per commit)
- π Payment provider integrations (Wise, Flutterwave, etc.)
- π± Telegram Web App (mobile UI)
- π― Additional intent patterns (heuristics)
- π Business analytics dashboard
- π Additional security audits
- π Bug fixes & edge cases
- π Documentation improvements
- Verify
TELEGRAM_BOT_TOKENis correct in.env - Check bot is running:
npm start - Confirm bot is not running in another terminal
- Check bot permissions in Telegram (not blocked by user)
Set at least one of:
OPENAI_API_KEY=...GEMINI_API_KEY=...GROQ_API_KEY=...
- Request testnet USDC: faucet.circle.com
- Wait ~2 seconds for confirmation
- Refresh balance:
/balance
- Check Arc status: testnet.arcscan.app
- Verify recipient address (must start with
0x) - Ensure enough USDC for amount + gas
- Close other processes accessing
payit.db - Restart bot:
npm start
If persistent:
rm payit.db
npm start
# User will re-onboard on next /startIf you are deploying to a container, make sure the DB path is mounted to a stable volume. For example:
docker run -v /host/path/payit.db:/app/payit.db ...If the bot is restarted in a container or hosted environment, make sure the SQLite file is backed by persistent storage. Set PAYIT_DB_PATH to a stable path and mount that path across restarts.
Example Docker-style mount:
docker run -v /host/path/payit.db:/app/payit.db ...[Specify your license: MIT, Apache 2.0, etc.]
- π Setup Guide: SETUP.md
- π Technical Docs: PAYIT_DOCUMENTATION.md
- π€ AI Agent Docs: AGENT_README.md
- π Issues: GitHub Issues
- β Non-custodial wallet generation
- β USDC + EURC support
- β Multimodal AI intent understanding
- β Invoice & payroll management
- β Scheduled payments
- ON/OFF-ramp integration (local currency β USDC)
- Payment provider partnerships
- KYC/AML compliance layer
- Business dashboard
- Multi-signature wallets (team accounts)
- Smart contract automation (yield farming, escrow)
- DeFi integrations (lending, staking)
- Mobile app (Telegram Web App)
- Multi-language support
PayIT enables anyone, anywhere to hold wealth in stablecoins and transact in local currencyβseamlessly, non-custodially, and affordably. By removing intermediaries and barriers to global financial rails, we're building the financial infrastructure for the next billion users.
Built with β€οΈ for financial inclusion. Powered by Arc, Telegram, and AI.
Last updated: June 28, 2026
Status: Testnet | Arc Mainnet awaited