QR Code Generation for Crypto Payments in Mobile Apps
Imagine: a user scans your QR, but the wallet displays "unknown currency" or doesn't prefill the amount. The cause is an incorrect URI format or an unsuitable error correction level. We've configured QR generation for dozens of crypto wallets and know how to avoid these issues. A correct URI (BIP-21, EIP-681) and the right Error Correction Level are key to seamless payment. Without them, users manually enter data, errors increase, and conversion drops. Contact us — we'll help you implement a reliable solution tailored to your stack.
We use proven stacks: Swift + CoreImage on iOS, Kotlin + ZXing on Android. CoreImage generates QR codes 30% faster in our tests, but ZXing provides more control over modules — this is especially important for non-standard sizes. The choice depends on the task: speed with CoreImage, customization with ZXing.
Why URI Format Determines Payment Success?
Standard URIs (BIP-21, EIP-681) are recognized by most wallets. If you omit the amount parameter or specify it in wrong units (e.g., satoshi instead of bitcoin), the payer will have to enter the amount manually. This increases the risk of errors and reduces conversion.
BIP-21 — URI format standard for Bitcoin. EIP-681 — standard for Ethereum.
URI Formats for Different Blockchains
| Blockchain | Format | Example |
|---|---|---|
| Bitcoin (BIP-21) | bitcoin:<address>?amount=<BTC>&label=<text> |
bitcoin:1A2B3C4D5E6F?amount=0.001&label=Order+123 |
| Ethereum (EIP-681) | ethereum:<address>@<chainID>?value=<wei> |
ethereum:0xAbCd1234@1?value=500000000000000000 |
| ERC-20 (EIP-681) | ethereum:<tokenContract>@<chainID>/transfer?address=<recipient>&uint256=<amount> |
ethereum:0xTokenAddress@1/transfer?address=0xRecipient&uint256=1000000 |
| Solana (SPL) | solana:<recipient>?amount=<SOL>&spl-token=<mint>&label=<text> |
solana:RecipientPubkey?amount=0.5&spl-token=TokenMintAddress&label=Payment |
For Solana, specify the token mint; if omitted, SOL is assumed. This is important for multi-chain implementations.
EIP-681 for ERC-20 is non-trivial: first the token contract address, then the transfer method with recipient and amount. Many wallets support a simplified format: ethereum:0xRecipient?value=X&contractAddress=0xToken.
Which QR Error Correction Level to Choose?
Choosing the correction level is a trade-off between damage resistance and data density. For mobile apps with branding, we recommend level Q (25%). It provides 1.5 times more resilience than M with a slight size increase.
| Level | Data Recovery | Suitable for Logo | QR Size (40 chars) |
|---|---|---|---|
| L | ~7% | No | 21×21 modules |
| M | ~15% | Cautiously | 25×25 |
| Q | ~25% | Yes, up to 30% area | 29×29 |
| H | ~30% | Yes | 33×33 |
Without a logo, M (15%) is sufficient — it provides good readability at small scan angles. But with a logo, if correction isn't raised to Q, readability drops by 40%.
Generating QR with Correct Parameters
// iOS — QR generation via CoreImage with desired correction level import CoreImage.CIFilterBuiltins func generateQRCode(from string: String, size: CGFloat = 300) -> UIImage { let filter = CIFilter.qrCodeGenerator() filter.message = Data(string.utf8) filter.correctionLevel = "Q" // 25% error correction — for logo overlay let transform = CGAffineTransform(scaleX: size / filter.outputImage!.extent.width, y: size / filter.outputImage!.extent.height) let scaledImage = filter.outputImage!.transformed(by: transform) // Nearest neighbor interpolation for crispness let context = CIContext() let cgImage = context.createCGImage(scaledImage, from: scaledImage.extent)! return UIImage(cgImage: cgImage) } // Android — ZXing with custom size import com.google.zxing.BarcodeFormat import com.google.zxing.EncodeHintType import com.google.zxing.qrcode.QRCodeWriter import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel val hints = mapOf( EncodeHintType.ERROR_CORRECTION to ErrorCorrectionLevel.Q, EncodeHintType.MARGIN to 1, EncodeHintType.CHARACTER_SET to "UTF-8" ) val bitMatrix = QRCodeWriter().encode(uri, BarcodeFormat.QR_CODE, 512, 512, hints) Dynamic Amount and Token Selection
If your app has an amount input before QR generation, the URI updates on every amount change. For ERC-20, it's important to account for decimals when building the value:
// Android — value calculation for USDC (6 decimals) val humanAmount = BigDecimal("100.50") // entered by user val decimals = 6 val rawAmount = humanAmount.movePointRight(decimals).toBigInteger() // 100500000 val uri = "ethereum:${usdcContractAddress}@1/transfer?address=${recipientAddress}&uint256=$rawAmount" Decimal errors are a common cause of incorrect transfers. For USDC (6 decimals), amount 100.50 USDC becomes 100500000 units. For ETH (18 decimals) — 100500000000000000000 wei.
Branding Overlay on QR
Placing your app logo in the center of the QR is standard practice. Up to 30% of the central area is safe with correction level Q. The logo should be a white square with an icon to avoid disrupting QR module contrast.
What to Do About Scanning Issues?
If the QR doesn't scan, check the error correction level (should be Q or H with a logo), contrast between modules and background, and logo size (no more than 30% area). Ensure the URI complies with the chosen blockchain standard.
How We Implement Crypto QR Turnkey
Our process includes:
- Analysis — selecting blockchains, tokens, and branding requirements.
- Design — preparing URI formats, choosing generation libraries.
- Implementation — code in Swift / Kotlin with dynamic amount and error correction.
- Testing — scanning on 10+ popular wallets (Trust Wallet, MetaMask, Coinbase).
- Deployment — integration with App Store / Google Play, configuring App Distribution.
Timeline: from 1 day (single blockchain, no logo) to 10 days (multi-chain, branding, token selection). Integration cost is calculated individually — contact us for a project estimate.
What's Included in the Result
- QR generation with correct URI for each blockchain.
- Dynamic amount update and token selection.
- QR branding with logo at correction level Q.
- "Copy Address" and "Share QR" buttons.
- Source code with comments and documentation.
- Post-release support (1 month). Support cost is included in the base package.
Why Entrust This Task to Us?
We have over 5 years of mobile development experience and have completed more than 30 projects involving cryptocurrency payments. We guarantee compatibility with current wallet and app store versions. Experience navigating App Store Review Guidelines (Section 4.2, 5.1) and Google Play Console ensures your app won't be rejected due to QR implementation.
Order implementation — we'll prepare everything in 3–10 days. Get a consultation on your project right now.







