⚡ Node.js₿ Crypto
Crypto Wallet Address Validation
Validate Bitcoin and Ethereum wallet addresses in Node.js. Detect address types (P2PKH, P2SH, bech32), verify EIP-55 checksums, and run parallel checks with Promise.all.
Also available in Python
Contents
1. Address types covered
| Chain | Endpoint | Address types |
|---|---|---|
| Bitcoin (BTC) | /v0/btc-address | P2PKH (1…), P2SH (3…), P2WPKH / P2WSH (bc1…) |
| Ethereum (ETH) | /v0/eth-address | EIP-55 mixed-case checksum addresses |
2. Validate Bitcoin address
Endpoint: GET /v0/btc-address?value=…
{ "valid": true, "type": "P2WPKH" }
| type value | Prefix | Description |
|---|---|---|
| P2PKH | 1… | Legacy — Pay to Public Key Hash |
| P2SH | 3… | Pay to Script Hash (multisig, SegWit-wrapped) |
| P2WPKH | bc1q… (42 chars) | Native SegWit — lowest fees |
| P2WSH | bc1q… (62 chars) | Native SegWit script hash |
- Gate on
valid - Use
typeto detect address format for fee estimation - Warn users submitting legacy P2PKH addresses about higher fees
3. Validate Ethereum address
Endpoint: GET /v0/eth-address?value=…
{ "valid": true, "address": "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed", "isChecksumValid": true }
- Check
valid— 40 hex chars after 0x prefix - Check
isChecksumValid— EIP-55 mixed-case checksum - Normalise to checksummed form before storing to prevent duplicate entries
⚠️An Ethereum address is valid even without checksum casing (all lowercase passes). Always normalise to EIP-55 checksum form before storage to prevent the same address being stored twice in different cases.
4. Parallel validation with Promise.all
import { createClient } from '@isvalid-dev/sdk' const iv = createClient({ apiKey: process.env.ISVALID_API_KEY! }) type Chain = 'BTC' | 'ETH' interface WalletValidationResult { chain: Chain address: string valid: boolean details: Record<string, unknown> warnings: string[] } async function validateWallet(chain: Chain, address: string): Promise<WalletValidationResult> { const warnings: string[] = [] if (chain === 'BTC') { const result = await iv.btcAddress(address) if (result.valid && result.type === 'P2PKH') { warnings.push('Legacy P2PKH address — consider migrating to bech32 (P2WPKH) for lower fees') } return { chain, address, valid: result.valid, details: result, warnings } } else { const result = await iv.ethAddress(address) if (result.valid && !result.isChecksumValid) { warnings.push('Address is valid but lacks EIP-55 checksum casing — normalise before storage') } return { chain, address, valid: result.valid, details: result, warnings } } } async function validateBoth(btcAddress: string, ethAddress: string) { const [btc, eth] = await Promise.all([ validateWallet('BTC', btcAddress), validateWallet('ETH', ethAddress), ]) return { btc, eth } } // Example const result = await validateBoth( '1A1zP1eP5QGefi2DMPTfTL5SLmv7Divf', '0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed' ) console.log('BTC valid:', result.btc.valid, '| type:', result.btc.details.type) console.log('ETH valid:', result.eth.valid, '| checksumValid:', result.eth.details.isChecksumValid)
5. Edge cases
Wrong chain (ETH address submitted as BTC)
⚠️If a user submits an Ethereum address (0x…) to the BTC endpoint, it will return
valid: false. Detect the chain from the address format before calling the API.function detectChain(address: string): 'BTC' | 'ETH' | 'unknown' { if (/^0x[0-9a-fA-F]{40}$/.test(address)) return 'ETH' if (/^(1|3)[1-9A-HJ-NP-Za-km-z]{25,34}$/.test(address)) return 'BTC' if (/^bc1[a-z0-9]{6,}$/.test(address)) return 'BTC' return 'unknown' }
BTC testnet addresses
ℹ️Testnet addresses (prefix m, n, or tb1) are structurally similar to mainnet but must not be used in production. The API validates mainnet addresses — reject any address that fails validation.
ETH checksum normalisation
import { getAddress } from 'ethers' const result = await iv.ethAddress(userInput) if (result.valid && !result.isChecksumValid) { // Normalise to EIP-55 checksum using ethers.js or viem const normalised = getAddress(userInput.toLowerCase()) // Store normalised form }
6. Summary checklist
✓Detect chain from address format before calling API
✓Check BTC type for fee estimation (legacy vs SegWit)
✓Warn users about legacy P2PKH higher fees
✓Validate ETH isChecksumValid for EIP-55
✓Normalise ETH to checksum form before storage
✓Run BTC + ETH checks in parallel with Promise.all
✓Reject testnet addresses in production flows
✓Return 422 with field-level error on invalid addresses