# OpenSpec Change: enterprise-cryptocurrency - **Change ID**: enterprise-cryptocurrency - **Package**: `@suaveplan/cryptocurrency` - **Category**: finance - **Target path**: `finance/crypto/cryptocurrency` - **Status**: PROPOSED - **Date**: 2026-04-24 - **Reference spec**: `/mnt/s/web/suaveplan/enterprise/cryptocurrency.md` --- ## Summary Deliver `@suaveplan/cryptocurrency` on the genesis branch from scratch at enterprise quality. The package is a zero-runtime-dep (beyond `tslib`) pure utility library covering: wallet address validation and auto-detection across 15+ chains; EIP-55 checksumming; unit conversion (wei/gwei/ether, satoshi/bitcoin, lamport/sol, plus generic `convertUnits`); a pluggable `MemoryChainRegistry`; chain explorer URL generators; transaction hash validation; EIP-1559 + EIP-4844 blob-gas estimation helpers; a `TokenRegistry` with common tokens and balance formatting; an ABI-aware calldata/function-selector decoder; testnet chain entries; and property-based tests for round-trip unit conversions. Typed `CryptoError` hierarchy mirrors `@suaveplan/error` shape without importing it (preserving zero runtime deps). --- ## Current-state audit (genesis) Does not exist on genesis — fresh build. --- ## Workspace deps No production workspace deps (zero-dep design). Dev deps only: | Package | Role | |---|---| | `zod` (`catalog:forms`) | Address validation / chain info schemas (runtime dep by exception — tiny) | | `tslib` (`catalog:build`) | Runtime helpers | | `fast-check` (`catalog:testing`) | Property-based tests | | `@suaveplan/testing workspace:^` | Test utilities | --- ## Public API surface (from main branch, fully preserved + genesis additions) ```ts // Validation function validateAddress(address: string): AddressValidation function validateAddressForChain(address: string, chainId: ChainId): AddressValidation function validateTxHash(hash: string): TxHashValidation // Chain registry const CHAINS: Record class ChainRegistry { ... } class MemoryChainRegistry implements ChainRegistryAdapter { ... } function getAllChainIds(): ChainId[] function getChain(id: ChainId): ChainInfo | undefined function getChainByEvmId(evmId: number): ChainInfo | undefined function getEvmChains(): ChainInfo[] function getExplorerAddressUrl(chainId: ChainId, address: string): string function getExplorerTxUrl(chainId: ChainId, tx: string): string // Gas estimation (EIP-1559 + EIP-4844) function calculateEffectiveGasPrice(baseFee: bigint, maxFee: bigint, maxPriorityFee: bigint): bigint function calculateMaxFeePerGas(baseFee: bigint, multiplier?: number): bigint function estimateGas(params: GasEstimateParams): GasEstimate function estimateTxCostEth(params: GasEstimateParams): string function formatGwei(wei: bigint): string function calculateBlobGasPrice(excessBlobGas: bigint): bigint // EIP-4844 genesis addition function estimateBlobTxCost(params: BlobGasEstimateParams): GasEstimate // genesis addition // Tokens const COMMON_TOKENS: TokenInfo[] class TokenRegistry { ... } function formatTokenBalance(amount: bigint, decimals: number, options?: FormatTokenOptions): string // Transaction decode (ABI-aware — genesis improvement) function decodeCalldata(calldata: string, abi: FunctionSignature): DecodedCall function decodeTxHash(hash: string): TxMetadata function extractSelector(calldata: string): string function lookupSelector(selector: string, resolver?: SelectorResolver): Promise const KNOWN_SELECTORS: Record // Units function etherToWei(ether: number | string): bigint function weiToEther(wei: bigint): string function gweiToEther(gwei: bigint): string function bitcoinToSatoshi(btc: number | string): bigint function satoshiToBitcoin(satoshi: bigint): string function lamportToSol(lamport: bigint): string function convertUnits(value: bigint, fromDecimals: number, toDecimals: number): bigint function getUnits(chainId: ChainId): CryptoUnit // Testnet chains (genesis addition — sub-path export) // import { TESTNET_CHAINS } from '@suaveplan/cryptocurrency/chains/testnet-data' // Error hierarchy (mirrors @suaveplan/error shape, no import) class CryptoError extends Error { code: CryptoErrorCode } class UnknownChainError extends CryptoError { } class InvalidAddressError extends CryptoError { } class InvalidTxHashError extends CryptoError { } class UnsupportedUnitError extends CryptoError { } ``` --- ## File layout ```text finance/crypto/cryptocurrency/ package.json tsconfig.json vitest.config.ts src/ index.ts errors/ crypto-error/ crypto-error.ts / .md / .test.ts / index.ts address/ validator/ validator.ts / validator.md / validator.test.ts / index.ts chains/ chain-data/ chain-data.ts / chain-data.md / chain-data.test.ts / index.ts testnet-data/ testnet-data.ts / testnet-data.md / testnet-data.test.ts / index.ts chain-registry/ chain-registry.ts / .md / .test.ts / index.ts registry/ registry.ts / registry.md / registry.test.ts / index.ts gas/ gas-estimator/ gas-estimator.ts / .md / .test.ts / index.ts blob-gas-estimator/ blob-gas-estimator.ts / .md / .test.ts / index.ts tokens/ token-data/ ... token-registry/ ... transaction/ tx-decoder/ ... selector-resolver/ ... units/ converter/ ... types/ crypto.types.ts crypto.types.md tests/ property.test.ts src/__benchmarks__/ hot-paths.bench.ts ``` --- ## Impact Downstream: `@suaveplan/currency-providers` (on-chain oracle adapters), `@suaveplan/money` (token unit interop). **Prerequisites on Verdaccio**: `zod`, `tslib` (only external catalog deps).