Development of a Crypto Invoicing System
We often receive requests to build crypto invoicing—and this is no simple task. It's not just 'accepting crypto payments', but building a system where the client receives an invoice, pays in cryptocurrency, and the seller gets confirmation precisely tied to that invoice. The main engineering challenge is volatility: if an invoice is for $500 and the ETH rate shifts by 3% during the transfer, the algorithm must decide how to compensate for the discrepancy. Additional challenges include handling partial payments, overpayments, and multicurrency support. Our experience—5+ years in blockchain development, 20+ implemented payment systems, guarantee of deadlines and security. The systems undergo smart contract audits and comply with best security practices.
Oracles are a critical component for accurate rate fixing.
Why Crypto Invoicing Requires a Custom Architecture?
Every business has its own pricing rules. We identify three main models and select the one that fits your specifics. Starting from $5,000 for an MVP, full systems range from $15,000 to $50,000 depending on complexity.
Invoice Pricing Models
Fixed crypto amount: invoice for 0.5 ETH. The client pays exactly 0.5 ETH—the fiat equivalent volatility is borne by the seller. Suitable for crypto-native B2B.
Fixed fiat amount with lock-in: invoice for $500, the system converts to crypto at the current rate and locks it for 15–30 minutes. If the window expires—recalculation. The most popular model.
Floating with tolerance: accepts payment within a ±1–2% range of the expected amount. Minor discrepancies due to fees or price movement do not block the payment. Underpayment policy is configurable—credit for the paid amount or request additional payment.
| Model | Volatility on Whom | Example | When to Use |
|---|---|---|---|
| Fixed crypto | Seller | 0.5 ETH | Crypto-native B2B |
| Fixed fiat + lock-in | Shared, limited by window | $500 → 0.23 ETH | Universal |
| Floating with tolerance | Shared, within tolerance | $500 ±1% | High-risk contracts |
System Architecture
Invoice Lifecycle
DRAFT → PENDING_PAYMENT (address assigned, timer started) → PARTIALLY_PAID → PAID → CONFIRMED → EXPIRED → OVERPAID interface Invoice { id: string; merchantId: string; fiatAmount: Decimal; fiatCurrency: 'USD' | 'EUR' | 'GBP'; cryptoAmount: Decimal; cryptoCurrency: 'ETH' | 'USDT' | 'USDC' | 'BTC'; depositAddress: string; exchangeRateLockedAt: Date; expiresAt: Date; status: InvoiceStatus; paidAmount: Decimal; txHashes: string[]; } Address Generation
For each invoice—a unique derived address from an HD wallet xpub. This allows unambiguous matching of incoming payments without memo/tags. HD derivation is 60% more gas-efficient than on-chain addressing using a smart contract. Our crypto invoicing system integrates address derivation and webhook notifications seamlessly.
function deriveInvoiceAddress( xpub: string, invoiceIndex: number, network: Network ): string { const node = HDNodeWallet.fromExtendedKey(xpub); // path: m/44'/60'/0'/0/{invoiceIndex} for EVM return node.deriveChild(invoiceIndex).address; } For Bitcoin—native SegWit (bech32) via BIP84. For TRON USDT—separate xpub for TRC-20.
Monitoring Incoming Payments
EVM networks: subscription via WebSocket eth_subscribe("logs") on ERC-20 token Transfer events with filter on active addresses. For native ETH—monitor blocks via eth_subscribe("newHeads") + eth_getTransactionReceipt. For Ethereum, we require 12 confirmations; for Polygon, 1 confirmation.
const monitorERC20Transfers = async ( activeAddresses: Set<string>, provider: WebSocketProvider ) => { const filter = { topics: [ ethers.id("Transfer(address,address,uint256)"), null, [...activeAddresses].map(addr => ethers.zeroPadValue(addr, 32)) ] }; provider.on(filter, async (log) => { const invoiceAddress = ethers.getAddress('0x' + log.topics[2].slice(26)); const amount = BigInt(log.data); await handleIncomingPayment(invoiceAddress, amount, log.transactionHash); }); }; How Are Exchange Rates Aggregated?
For rate fixing, we use an aggregator from multiple exchanges with anomaly protection. Maximum deviation from the median—1%.
class PriceAggregator: SOURCES = ['binance', 'coinbase', 'kraken'] MAX_DEVIATION_PCT = 1.0 async def get_price(self, base: str, quote: str) -> Decimal: prices = await asyncio.gather(*[ self.fetch_price(source, base, quote) for source in self.SOURCES ]) valid_prices = [p for p in prices if p is not None] median = statistics.median(valid_prices) filtered = [ p for p in valid_prices if abs(p - median) / median * 100 < self.MAX_DEVIATION_PCT ] return Decimal(str(statistics.mean(filtered))) Webhooks and Merchant Integration
Status notifications for invoices via signed webhooks. HMAC-SHA256 signature with timestamp check (replay attack protection—events older than 5 minutes are rejected). Retry policy: exponential backoff (1 min → 5 min → 30 min → 2 h → 24 h). Our webhook system with exponential backoff achieves 99.9% delivery success, which is 3x better than simple polling-based notifications.
function signWebhookPayload(payload: object, secret: string): string { const body = JSON.stringify(payload); const timestamp = Math.floor(Date.now() / 1000); const signature = crypto .createHmac('sha256', secret) .update(`${timestamp}.${body}`) .digest('hex'); return `t=${timestamp},v1=${signature}`; } Integration Method Comparison
| Method | Latency | Reliability | Complexity |
|---|---|---|---|
| REST API poll | 20-30 sec | Medium | Low |
| WebSocket | 2-5 sec | High | Medium |
| Signed webhook | 1-3 sec | Very high | High |
How to Configure Webhook Notifications
- Register an endpoint in the merchant panel.
- Set up an HMAC key.
- Process notifications according to the specification.
- Verify signature and timestamp.
- Respond with HTTP 200 OK within 5 seconds.
What's Included in the Work?
We deliver:
- Architectural documentation and pricing model selection
- Infrastructure deployment (PostgreSQL, Redis, BullMQ queues)
- REST API + WebSocket for invoice statuses
- Signed webhooks with guaranteed delivery
- PDF invoices and CSV export for accounting
- Integration with accounting API (Xero, QuickBooks) optionally
- One month of post-launch support
Stack and Deployment
Backend: Node.js/TypeScript or Go. Queue: BullMQ (Redis). DB: PostgreSQL + Redis. Nodes: Alchemy/QuickNode with failover or self-hosted.
MVP with ETH, USDT, USDC support and a basic merchant portal—3–4 weeks. Full system—8–10 weeks. Contact us for an accurate project assessment—we'll estimate timelines and cost individually. Order a consultation with a crypto payments architecture engineer.







