An automated system for processing cryptocurrency deposits with gas fee optimization. This project uses a microservices architecture to intelligently sweep tokens based on profitability analysis.
- Overview
- Architecture
- Getting Started
- Environment Setup
- Running the Application
- API Reference
- Smart Contracts
- Development
Crypto Processor is designed to:
- Generate unique, deterministic deposit addresses for users
- Index blockchain events for incoming token transfers
- Analyze profitability of token sweeps (considering gas costs vs token value)
- Automatically deploy and execute sweep transactions when profitable
- Track all transactions and maintain audit logs
Key Features:
- Deterministic address generation using CREATE2
- Gas-optimized transactions
- Configurable profitability multipliers
- Redis-based job queue with BullMQ
- Real-time blockchain indexing with Ponder
- PostgreSQL persistence layer
┌───────────────────────────────┐
│ External clients │
│ deposits / tokens / history │
└───────────────┬───────────────┘
│ HTTP
▼
┌──────────────────────────────────────────────────────┐
│ REST API (Hono) │
│ - POST /v1/deposits reserves deterministic addresses │
│ - GET /v1/deposits and /v1/transactions read state │
│ - POST /v1/tokens is admin-key protected │
└───────────────┬──────────────────────────────────────┘
│ Drizzle ORM
▼
┌──────────────────────────────────────────────────────┐
│ PostgreSQL │
│ users, supported_tokens, deposit_addresses, │
│ transactions, lifecycle metadata │
└───────────────▲──────────────────────────▲───────────┘
│ │
lookup/write deposits │ read config + update tx lifecycle
│ │
┌───────────────┴───────────────┐ │
│ Ponder Indexer │ │
│ - listens to ERC20 Transfers │ │
│ - matches known deposits │ │
│ - inserts deposit tx records │ │
└───────────────┬───────────────┘ │
│ enqueue sweep jobs │
▼ │
┌───────────────────────────────┐ │
│ Redis │──────────┤
│ BullMQ sweep queue │ consume │
│ sender nonce locks │ │
└───────────────────────────────┘ │
│
┌─────────────┴──────────────┐
│ Sweep Worker │
│ - checks ERC20 balance │
│ - compares token/gas value │
│ - calls deployAndSweep │
└──────┬───────────────┬─────┘
│ HTTPS │ RPC / Viem
▼ ▼
┌────────────────┐ ┌──────────────────────────────┐
│ Price API │ │ Blockchain network │
│ priceProviderId│ │ ERC20 + WalletFactory + │
└────────────────┘ │ DepositLogic contracts │
└──────────────▲───────────────┘
│ Transfer events
└── to Ponder
| Layer | Technology |
|---|---|
| API Framework | Hono, Node.js |
| ORM | Drizzle ORM |
| Database | PostgreSQL |
| Cache/Queue | Redis, BullMQ |
| Blockchain Indexing | Ponder |
| Smart Contracts | Solidity |
| Contract Dev Tools | Foundry, Viem |
| Testing | Vitest |
| Container | Docker, Docker Compose |
- Node.js 22+
- Docker & Docker Compose
- Git
-
Clone the repository:
git clone https://github.com/lexaisnotdead/crypto-payment-processor.git cd crypto-payment-processor -
Install dependencies:
npm install
Create a .env file in the root directory:
# Database
DATABASE_URL=postgres://postgres:postgres@postgres:5432/crypto_processor
DATABASE_URL_DOCKER=postgres://postgres:postgres@postgres:5432/crypto_processor
# Redis
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_URL=redis://redis:6379
REDIS_HOST_DOCKER=redis
REDIS_PORT_DOCKER=6379
REDIS_URL_DOCKER=redis://redis:6379
# Network Configuration
CHAIN_ID=11155111
RPC_URL=https://your-rpc-provider
DEFAULT_ERC20_TOKEN=0xbDeaD2A70Fe794D2f97b37EFDE497e68974a296d
DEFAULT_ERC20_PRICE_PROVIDER_ID=tether
# Wallet (for executing sweeps)
PRIVATE_KEY=0xYOUR_PRIVATE_KEY
ADMIN_API_KEY=replace-with-a-long-random-secret
# External Services
PRICE_API_BASE=https://api.coingecko.com/api/v3
# Server
PORT=3000- CHAIN_ID: Network identifier (11155111 = Sepolia testnet)
- RPC_URL: Blockchain RPC endpoint
- DEFAULT_ERC20_TOKEN: fallback token indexed by Ponder even if DB has no active tokens
- PRIVATE_KEY: Private key of wallet executing transactions (must have sufficient balance for gas)
- PRICE_API_BASE: API for fetching current token prices in USD
- Contract addresses: loaded from
addresses/<chainId>.json(fallback:addresses/latest.json)
Start all services with a single command:
docker-compose upThis will start:
- PostgreSQL - Database (port 5432)
- Redis - Cache and job queue (port 6379)
- API - REST server (port 3000)
- Worker - Background job processor
- Ponder - Blockchain indexer
Check service health:
curl http://localhost:3000/healthdocker-compose up postgres redisnpm exec tsx apps/api/src/server.tsnpm exec tsx apps/api/src/workers/index.tsnpm exec ponder start --config apps/indexer/ponder.config.tsnpm run test # Run all tests once
npm run test:watch # Run tests in watch modenpx forge build # Compile contracts
npx forge test # Run Solidity tests
npx forge deploy # Deploy contractsPOST /v1/deposits
Request body:
{
"userId": "customer-123",
"tokenAddress": "0x..."
}Response:
{
"userId": "uuid",
"tokenAddress": "0x...",
"chainId": 11155111,
"depositAddress": "0x...",
"salt": "0x...",
"index": 0
}Description: Reserves a deterministic deposit address for a user-token pair. The first call creates the record; subsequent calls return the same reservation.
GET /v1/deposits/:userId/:tokenAddress
Parameters:
userId(path): External user identifiertokenAddress(path): Token contract address
Description: Read-only lookup. Returns 404 when the reservation does not exist.
GET /v1/transactions/:userId?limit=50&cursor=2026-04-14T08:00:00.000Z
Optional Parameters:
limit: integer between1and100cursor: ISO timestamp from a previousnextCursor
Response:
{
"transactions": [
{
"id": "uuid",
"type": "SWEEP",
"status": "CONFIRMED",
"chainId": 11155111,
"tokenAddress": "0x...",
"amountWei": "1000000000000000000",
"txHash": "0x...",
"gasPriceWei": "1000000000",
"gasUsed": "50000",
"meta": {
"decision": "SWEEP",
"tokenValueUsd": "2500.00",
"gasCostUsd": "1.50",
"multiplier": "10.0"
}
}
],
"nextCursor": null
}POST /v1/tokens
Authentication: x-admin-api-key: <ADMIN_API_KEY> or Authorization: Bearer <ADMIN_API_KEY>
Optional Parameters:
chainId:11155111by defaultisActive: StatussweepGasMultiplier: Multiplier for calculating profitability
Request body:
{
"tokenAddress": "0x...",
"symbol": "USDT",
"priceProviderId": "tether",
"decimals": 6,
"chainId": 11155111,
"isActive": true,
"sweepGasMultiplier": "10.0"
}GET /v1/tokens?chainId=11155111
GET /health
Response:
{ "ok": true }Factory contract for creating deterministic wallet clones using EIP-1167 (Minimal Proxy).
Key Functions:
deployAndSweep(bytes32 salt, address token)- Creates wallet and sweeps tokenssetTreasury(address newTreasury)- Update treasury addresspredictDeterministicAddress(bytes32 salt)- Preview wallet address
Key Features:
- Deterministic deployment using CREATE2
- Automatic initialization on first deployment
- Treasury updates for existing wallets
- Automatic balance checking and sweeping
Implementation contract for individual wallet logic (deployed as proxy clones).
Key Functions:
initialize(address owner, address treasury)- Initialize new walletsweep(address token)- Sweep token balance to treasurysetTreasury(address newTreasury)- Update treasury address
Key Features:
- UUPS-compatible upgradeable contract
- Ownable (only factory can call)
- SafeERC20 for safe token transfers
- All balances go to configurable treasury
The system decides whether to sweep tokens based on:
SWEEP if: tokenValue >= gasEstimate x multiplier
Where:
tokenValue= Current token balance in USD (E18 precision)gasEstimate= Estimated gas cost in USDmultiplier= Configurable factor (default 10x)
Example:
- Token value: $2,500
- Gas cost: $100
- Multiplier: 10x
- Threshold: $100 x 10 = $1,000
- Decision: $2,500 >= $1,000 -> SWEEP
Metadata about each decision is stored in the transactions table for audit trails.