# @suaveplan/cryptocurrency - Universal cryptocurrency utilities: wallet address validation across 15 chains with EIP-55 checksumming, unit conversion (ETH/BTC/SOL), chain registry with async adapter, EIP-1559 gas estimation, ERC-20 token registry, calldata/selector decoder, transaction hash parsing. Zero browser/Node deps; injectable LoggerLike; typed CryptocurrencyError hierarchy. Universal cryptocurrency utilities for wallet address validation, unit conversion, chain registry, gas estimation, ERC-20 token registry, calldata / function-selector decoding, and transaction hash parsing. Zero browser or Node-specific dependencies — runs unchanged under Node ≥ 18, Bun, modern browsers, and Web Workers. Not a wallet, not a signing library — just pure utility primitives. ## Documentation tree - [address](./src/address/validator.md) — Provides the three address / hash validation primitives that the rest of the package builds on: `validateAddress` for c… - [validator](./src/address/validator.md) — Provides the three address / hash validation primitives that the rest of the package builds on: `validateAddress` for c… - [chain-data](./src/chains/chain-data.md) — Holds the canonical `CHAINS` constant: a `Record` containing one entry per supported mainnet networ… - [chain-registry](./src/chains/chain-registry.md) — Provides the async chain-registry façade for callers that need dynamic chain data — custom mainnet sets, runtime regist… - [registry](./src/chains/registry.md) — Exposes the synchronous fast-path over the built-in `CHAINS` constant. Every helper here is a pure function that reads… - [error-codes](./src/error-codes/error-codes.md) — Declares the stable, namespaced error registry for `@suaveplan/cryptocurrency` and the typed `CryptocurrencyError` clas… - [error-codes](./src/error-codes/error-codes.md) — Declares the stable, namespaced error registry for `@suaveplan/cryptocurrency` and the typed `CryptocurrencyError` clas… - [gas](./src/gas/gas-estimator.md) — Provides EIP-1559 gas-estimation primitives for Ethereum-style chains. Every helper accepts and returns `bigint` values… - [gas-estimator](./src/gas/gas-estimator.md) — Provides EIP-1559 gas-estimation primitives for Ethereum-style chains. Every helper accepts and returns `bigint` values… - [token-data](./src/tokens/token-data.md) — Provides the `COMMON_TOKENS` constant: a curated list of eight well-known ERC-20 tokens on Ethereum mainnet — USDT, USD… - [token-registry](./src/tokens/token-registry.md) — Provides the `TokenRegistry` class for adding, retrieving, and searching ERC-20 / token information across chains, plus… - [transaction](./src/transaction/tx-decoder.md) — Provides naive transaction-hash classification and 4-byte function-selector decoding for EVM calldata. `decodeTxHash` c… - [tx-decoder](./src/transaction/tx-decoder.md) — Provides naive transaction-hash classification and 4-byte function-selector decoding for EVM calldata. `decodeTxHash` c… - [units](./src/units/converter.md) — Provides generic and convenience unit conversion for cryptocurrency denominations. The generic `convertUnits` operates… - [converter](./src/units/converter.md) — Provides generic and convenience unit conversion for cryptocurrency denominations. The generic `convertUnits` operates… ## Install ```bash bun add @suaveplan/cryptocurrency ``` ## Quick start ```ts import { estimateGas, formatGwei, getChain, getExplorerTxUrl, satoshiToBitcoin, validateAddress, weiToEther, } from "@suaveplan/cryptocurrency"; // Multi-chain address validation with auto-detection const r = validateAddress("0x742d35Cc6634C0532925a3b844Bc9e7595f2bD28"); // { valid: true, normalized: "0x...", chains: ["ethereum", "polygon", ...] } // Unit conversion (bigint-pure) weiToEther("1000000000000000000"); // "1" satoshiToBitcoin("100000000"); // "1" // Chain metadata + explorer URLs const eth = getChain("ethereum"); // { id: "ethereum", evmChainId: 1, decimals: 18, ... } const url = getExplorerTxUrl("ethereum", "0xabc..."); // EIP-1559 gas estimation const estimate = estimateGas({ gasLimit: 21000n, baseFeePerGas: 30000000000n, maxPriorityFeePerGas: 2000000000n, }); formatGwei(estimate.gasPrice); // "32" ``` ## Features - **Address validation across 15 chains** (Bitcoin, Ethereum, Solana, Polygon, Arbitrum, Optimism, Avalanche, BSC, Base, TRON, Litecoin, Dogecoin, Cardano, Polkadot, Cosmos) via `validateAddress` / `validateAddressForChain`. - **Transaction hash classification** (EVM / UTXO / Solana) via `validateTxHash` and `decodeTxHash`. - **EIP-55 checksumming** for EVM addresses (simplified positional algorithm preserved from upstream; full keccak256 deferred to a follow-up change). - **Static chain registry** with `getChain` / `getAllChainIds` / `getEvmChains` / `getChainByEvmId` / explorer URL helpers. - **Async chain registry** (`ChainRegistry` + `MemoryChainRegistry`) supporting custom adapters and typed `CryptocurrencyError({ code: CRYPTOCURRENCY.UNKNOWN_CHAIN })`. - **Bigint-pure unit conversion** across ETH / BTC / SOL (`convertUnits`, `weiToEther`, `etherToWei`, `gweiToEther`, `satoshiToBitcoin`, `bitcoinToSatoshi`, `lamportToSol`, `getUnits`). - **EIP-1559 gas estimation** (`estimateGas`, `calculateMaxFeePerGas`, `calculateEffectiveGasPrice`, `formatGwei`, `estimateTxCostEth`). - **ERC-20 token registry** (`TokenRegistry`, `COMMON_TOKENS`, `formatTokenBalance`) — case-insensitive address lookups, substring search by symbol / name. - **Calldata + function-selector decoder** (`KNOWN_SELECTORS`, `lookupSelector`, `extractSelector`, `decodeCalldata`). - **Typed `CryptocurrencyError` hierarchy** with `CRYPTOCURRENCY.*` code registry and optional `chainId` / `currency` / `unit` discriminants. - **Optional `LoggerLike` injection** on `ChainRegistry` (no-op default) emitting `chain.registered` / `chain.lookup.miss` events. - **Tree-shakeable subpath exports** — import only what you use. - **Universal tier** — no `node:*`, no `bun:*`, no `fs` / `path` / `crypto` imports. ## Modules Co-located docs for every implementation file: - [`src/address/validator.md`](./src/address/validator.md) — `validateAddress`, `validateAddressForChain`, `validateTxHash`. - [`src/chains/chain-data.md`](./src/chains/chain-data.md) — `CHAINS` constant. - [`src/chains/chain-registry.md`](./src/chains/chain-registry.md) — `ChainRegistry`, `MemoryChainRegistry`, `LoggerLike` integration. - [`src/chains/registry.md`](./src/chains/registry.md) — synchronous getters. - [`src/error-codes/error-codes.md`](./src/error-codes/error-codes.md) — `CRYPTOCURRENCY_CODES`, `CryptocurrencyError`. - [`src/gas/gas-estimator.md`](./src/gas/gas-estimator.md) — EIP-1559 gas helpers. - [`src/tokens/token-data.md`](./src/tokens/token-data.md) — `COMMON_TOKENS`. - [`src/tokens/token-registry.md`](./src/tokens/token-registry.md) — `TokenRegistry`, `formatTokenBalance`. - [`src/transaction/tx-decoder.md`](./src/transaction/tx-decoder.md) — calldata / selector / tx-hash decoder. - [`src/types/crypto.types.md`](./src/types/crypto.types.md) — public type contract. - [`src/units/converter.md`](./src/units/converter.md) — generic + convenience unit conversion. ## Subpath exports Every public module ships its own subpath so consumers can tree-shake: ```ts import { validateAddress } from "@suaveplan/cryptocurrency/address/validator"; import { CHAINS } from "@suaveplan/cryptocurrency/chains/chain-data"; import { ChainRegistry } from "@suaveplan/cryptocurrency/chains/chain-registry"; import { getChain } from "@suaveplan/cryptocurrency/chains/registry"; import { CRYPTOCURRENCY_CODES } from "@suaveplan/cryptocurrency/error-codes/error-codes"; import { estimateGas } from "@suaveplan/cryptocurrency/gas/gas-estimator"; import { COMMON_TOKENS } from "@suaveplan/cryptocurrency/tokens/token-data"; import { TokenRegistry } from "@suaveplan/cryptocurrency/tokens/token-registry"; import { decodeCalldata } from "@suaveplan/cryptocurrency/transaction/tx-decoder"; import type { ChainInfo } from "@suaveplan/cryptocurrency/types/crypto.types"; import { convertUnits } from "@suaveplan/cryptocurrency/units/converter"; ``` ## Error handling ```ts import { CRYPTOCURRENCY_CODES, CryptocurrencyError, convertUnits, } from "@suaveplan/cryptocurrency"; try { convertUnits("1", "wei", "ether", "XYZ"); } catch (err) { if (err instanceof CryptocurrencyError) { if (err.code === CRYPTOCURRENCY_CODES.UNKNOWN_CURRENCY) { console.error(`unsupported currency: ${err.currency}`); } } } ``` ## What this package is not - **Not a wallet** — no key management, no transaction signing. - **Not an RPC client** — no on-chain calls; the `ChainRegistry` adapter contract lets you wire your own RPC layer. - **Not an ABI decoder** — `decodeCalldata` only recognises 4-byte selectors. Full ABI decoding (dynamic types, tuples) lands in a follow-up change. - **Not an ENS resolver** — name-resolution lands in a separate package. - **Not RFC-correct EIP-55** — uses a simplified positional checksum preserved from upstream; full keccak256 lands in a follow-up change. ## License MIT