Skip to content

igboze/PayIt

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

71 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

PayIT β€” Telegram Wallet for Local Fiat Operations on Stablecoins

**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.


Table of Contents


Core Vision

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

The Problem

  • 🌍 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

The Solution

  • βœ… 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

Key Features

πŸ’° Stablecoin Holdings on Arc

  • 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)

πŸ”„ ON/OFF-Ramps (Testnet Limited)

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

πŸ‘€ Dual Account Model

  • 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

πŸ€– Multimodal AI Intent Understanding

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
PDF πŸ“„ 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]

πŸ“„ Business SME Hub

  • 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

🎯 Local Currency Operations

How it works:

  1. Business owner in Nigeria creates invoice in NGN (e.g., ₦500,000)
  2. Customer pays in USDC (e.g., $3.33) to business's Arc wallet
  3. Business receives USDC instantly, non-custodial
  4. Business uses OFF-ramp to convert USDC β†’ NGN via payment partner (e.g., Wise, MoneyGram, local MFI)
  5. NGN lands in business's local bank within hours

Reverse flow:

  1. Freelancer in Kenya receives payment in local currency (KES)
  2. Customer sends USDC via PayIT
  3. Freelancer holds USDC on Arc (secure, borderless)
  4. When needed, freelancer uses ON-ramp to convert USDC β†’ KES
  5. KES arrives in local M-Pesa or bank account

⏰ Scheduled & Recurring Payments

  • 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

πŸ” Non-Custodial Security

  • 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

How It Works

End-to-End User Flow

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"

ON/OFF-Ramp Flow (Mainnet)

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"

Architecture

Non-Custodial Wallet Design

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.

Intent Processing Pipeline

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)

Data Model

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)

Tech Stack

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+

Quick Start

Prerequisites

  • Node.js 22.5 or newer
  • A Telegram bot token (from @BotFather)
  • At least one LLM API key (OpenAI, Gemini, or Groq)

Installation

  1. Clone the repository

    git clone https://github.com/igboze/PayIt.git
    cd PayIt
  2. Install dependencies

    npm install
  3. Set up .env

    cp .env.example .env
  4. 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
  5. Run the bot

    npm start
  6. Open Telegram, find your bot, send /start

First-Time Setup

  1. Send /start to your bot in Telegram
  2. Choose Personal or Business account
  3. Set a 4-digit PIN (this is your security key)
  4. Save your private key immediately β€” it displays once, auto-deletes after 60 seconds
  5. Get testnet USDC via Circle Faucet (select "Arc Testnet")
  6. Send a test payment: send 10 to <your_address> or use voice notes

Project Structure

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

Core Modules

src/wallet.js β€” Private Key Management

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 transmitted

Security model: "Just in time" decryption β€” decrypt, use one operation, destroy.

src/ledger.js β€” Transaction History

ledger.recordTransaction({
  user_id,
  sender,
  recipient,
  amount,
  token: "USDC" | "EURC",
  tx_hash,
  status: "pending" | "confirmed" | "failed",
  timestamp
});

ledger.getTransactions(userId, limit); // Last 50 transactions

src/invoice_db.js β€” Invoice Management

invoiceDb.createInvoice({
  user_id,
  recipient,
  amount,
  currency: "NGN" | "KES" | "USD", // Display currency
  description,
  due_date,
  status: "draft" | "sent" | "paid" | "overdue"
});

invoiceDb.markPaid(invoiceId, txHash, confirmationTime);

src/offramp.js β€” OFF-Ramp Blueprint (Testnet)

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 hash

Current state: Paj Cash integration blueprint. Full implementation awaits mainnet Arc launch.

src/gateway.js β€” Circle Gateway Integration

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 automatically

agent/intent_router.js β€” Smart Classification

Three-tier classification system:

  1. Heuristic fast-path (zero LLM cost)

    • "balance" β†’ instant response
    • "0x7234..." β†’ address detection
    • "send 5000 to Maria" β†’ parse directly
  2. 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"]
    }
  3. 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

agent/orchestrator.js β€” Payment Planning

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"
}

agent/executor.js β€” Execution & Broadcasting

const results = await executePlan(plan, pin, user);

// Results:
[
  {
    success: true,
    recipient: "Maria",
    amount: 5000,
    txHash: "0xabc123...",
    confirmationTime: 2000 // ms
  }
]

Flow:

  1. User enters PIN
  2. Decrypt private key (in-memory)
  3. Sign transaction
  4. Broadcast to Arc RPC
  5. Poll for receipt (max 30 seconds)
  6. Record in ledger
  7. Send receipt to user
  8. Destroy plaintext key

agent/voice_parser.js β€” Voice Transcription

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)

agent/vision_parser.js β€” Image OCR

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)

agent/file_parser.js β€” Bulk Document Processing

// 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 LLM

Multimodal AI Agent

See AGENT_README.md for comprehensive agent documentation.

Quick Examples

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]

Mock AI Mode

For deterministic testing without external APIs:

USE_MOCK_AI=1 npm start

All LLM calls return realistic but canned responses. Perfect for CI/CD, demos, and offline development.


Configuration

Minimum .env (Required)

# 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>

NVIDIA / OpenAI-compatible provider (optional)

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

Optional Features

# 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

ON/OFF-Ramp Strategy

Current Status (Testnet)

βœ… Architecture: Complete

  • src/offramp.js β€” Framework for USDC β†’ Local Currency conversion
  • src/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

Mainnet Roadmap

When Arc mainnet launches, PayIT will enable:

OFF-Ramp Flow

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"

ON-Ramp Flow

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"

Payment Partner Integration

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 })
};

Why Testnet Limits OFF-Ramp

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

Bot Commands

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

Security & Non-Custodial Design

Private Key Encryption

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

Transaction Signing Flow

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

Key Loss is Permanent

  • πŸ”΄ 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 Security Risks

  • πŸ“± 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 /export about risks
  • βœ… Recommend password manager for backups

Best Practices (tell users):

  1. Save your private key immediately after onboarding
  2. Store in password manager (1Password, Bitwarden, KeePass)
  3. Use strong, unique PIN (4+ digits)
  4. Never share your PIN with anyone
  5. Delete key exports immediately after viewing
  6. Monitor /history for suspicious transactions

Arc Testnet Details

Network Information

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")

Testnet Characteristics

  • βš™οΈ 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)

Getting Testnet USDC

  1. Visit faucet.circle.com
  2. Select Arc Testnet
  3. Paste your Arc wallet address (from /receive in bot)
  4. Click "Get USDC"
  5. Wait ~2 seconds
  6. Check balance in bot: /balance

Why Testnet Only?

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

Deployment

Local Development

# Install & run locally
npm install
npm start

# Bot polls Telegram API (no ngrok needed)

Docker

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

Railway / Heroku / Render

  1. Push to GitHub
  2. Connect service (Railway/Heroku/Render)
  3. Set environment variables
  4. Deploy with npm start

Production Checklist

  • Generate new bot token (rotate from development token)
  • Set ADMIN_TELEGRAM_IDS to production admins only
  • Use production LLM API keys (separate from dev)
  • Configure .env with 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)

Feature Status

βœ… Fully Implemented & Tested

  • βœ… 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)

🚧 Partially Implemented (Testnet)

  • 🚧 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)

❌ Not Yet Implemented

  • ❌ 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)

Testing

Run Test Suites

# 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 start

CI/CD

GitHub 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.


Contributing

We welcome contributions! Please:

  1. Fork the repository

    git clone https://github.com/yourusername/PayIt.git
    cd PayIt
  2. Create a feature branch

    git checkout -b feature/your-feature-name
  3. Make changes & test

    npm install
    USE_MOCK_AI=1 npm start  # Test locally with mock AI
  4. Commit with clear messages

    git commit -m "feat: Describe your feature clearly"
  5. Push & open a PR

    git push origin feature/your-feature-name

Development Guidelines

  • 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=1 before committing
  • Update .env.example if adding config vars
  • Keep commits atomic (one feature per commit)

Areas for Contribution

  • 🌍 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

Troubleshooting

Bot doesn't respond to commands

  1. Verify TELEGRAM_BOT_TOKEN is correct in .env
  2. Check bot is running: npm start
  3. Confirm bot is not running in another terminal
  4. Check bot permissions in Telegram (not blocked by user)

"No LLM provider configured"

Set at least one of:

  • OPENAI_API_KEY=...
  • GEMINI_API_KEY=...
  • GROQ_API_KEY=...

"Insufficient USDC" error

  1. Request testnet USDC: faucet.circle.com
  2. Wait ~2 seconds for confirmation
  3. Refresh balance: /balance

Transaction fails to broadcast

  1. Check Arc status: testnet.arcscan.app
  2. Verify recipient address (must start with 0x)
  3. Ensure enough USDC for amount + gas

SQLite "database is locked" error

  1. Close other processes accessing payit.db
  2. Restart bot: npm start

If persistent:

rm payit.db
npm start
# User will re-onboard on next /start

If 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 ...

Prevent wallet and points reset on redeploy

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 ...

License

[Specify your license: MIT, Apache 2.0, etc.]


Support & Resources


Roadmap

Phase 1: Testnet (Current βœ…)

  • βœ… Non-custodial wallet generation
  • βœ… USDC + EURC support
  • βœ… Multimodal AI intent understanding
  • βœ… Invoice & payroll management
  • βœ… Scheduled payments

Phase 2: Mainnet (Awaiting Arc Mainnet Launch)

  • ON/OFF-ramp integration (local currency ↔ USDC)
  • Payment provider partnerships
  • KYC/AML compliance layer
  • Business dashboard

Phase 3: Ecosystem (Future)

  • Multi-signature wallets (team accounts)
  • Smart contract automation (yield farming, escrow)
  • DeFi integrations (lending, staking)
  • Mobile app (Telegram Web App)
  • Multi-language support

Vision Statement

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

About

Payment Solution on telegram

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages