Files
suaveplan/openspec/changes/enterprise-cryptocurrency/proposal.md
2026-05-27 23:29:53 +01:00

5.7 KiB

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)

// Validation
function validateAddress(address: string): AddressValidation
function validateAddressForChain(address: string, chainId: ChainId): AddressValidation
function validateTxHash(hash: string): TxHashValidation

// Chain registry
const CHAINS: Record<ChainId, ChainInfo>
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<FunctionSignature | undefined>
const KNOWN_SELECTORS: Record<string, FunctionSignature>

// 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

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).