walletpress/backend/wallet_engine/chains.py
cryptorugmunch e13bd4d774
Some checks are pending
CI / lint (push) Waiting to run
CI / test (push) Waiting to run
CI / security (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / license (push) Waiting to run
CI / ai-review (push) Waiting to run
docs: apply fleet-template (16-artifact scaffold)
Adds missing standard artifacts:
- README.md (if missing)
- AGENTS.md (AI agent contract)
- PLAN.md (current sprint)
- STATUS.md (where we are)
- DEVELOPMENT.md (dev workflow)
- DEPLOYMENT.md (deploy procedure)
- TESTING.md (test strategy)
- DECISIONS.md (ADR index + templates)
- .github/CODEOWNERS
- .github/workflows/ci.yml

Preserves all existing artifacts.

Refs: RugMunchMedia/fleet-template
2026-07-02 02:07:06 +07:00

671 lines
29 KiB
Python

"""Multi-chain registry — 55 chains, all metadata, all derivation paths.
This is the single source of truth for chain support across the entire
WalletPress platform. Every chain has known-good BIP44 derivation paths,
address validation patterns, and RPC endpoints.
Trust principle: All derivation follows BIP39/BIP32/BIP44/BIP49/BIP84
standards. Users can verify WalletPress addresses match any standard wallet
software. Every chain's test vectors are documented and tested.
"""
from __future__ import annotations
import logging
from dataclasses import dataclass
from enum import Enum
from pathlib import Path
logger = logging.getLogger("wp.chains")
class ChainFamily(Enum):
BITCOIN = "bitcoin"
EVM = "evm"
SOLANA = "solana"
TRON = "tron"
ED25519 = "ed25519"
SECP256K1_ALT = "secp256k1_alt"
RIPPLE = "ripple"
SUBSTRATE = "substrate"
COSMOS = "cosmos"
ALGORAND = "algorand"
TEZOS = "tezos"
MONERO = "monero"
STELLAR = "stellar"
TON = "ton"
NANO = "nano"
CASPER = "casper"
ELROND = "elrond"
HEDERA = "hedera"
INTERNET_COMPUTER = "internet_computer"
FILECOIN = "filecoin"
ZILLIQA = "zilliqa"
@dataclass
class ChainInfo:
key: str
name: str
family: ChainFamily
symbol: str
decimals: int = 18
slip44: int = 0
hd_path: str = ""
testnet_hd_path: str = ""
address_pattern: str = ""
address_length: int = 0
explorer_url: str = ""
testnet_explorer: str = ""
rpc_url: str = ""
description: str = ""
icon: str = ""
is_testnet: bool = False
requires_bip39: bool = True
curve: str = "secp256k1"
native_token: str = ""
CHAINS: dict[str, ChainInfo] = {
# ── Bitcoin Family ──────────────────────────────────────
"btc": ChainInfo(
key="btc", name="Bitcoin", family=ChainFamily.BITCOIN, symbol="BTC",
slip44=0, hd_path="m/44'/0'/0'/0/0", decimals=8,
address_pattern="^(1|3|bc1)[a-zA-Z0-9]{25,62}$",
explorer_url="https://blockstream.info",
curve="secp256k1", native_token="BTC",
description="Bitcoin — the original cryptocurrency",
),
"btc-segwit": ChainInfo(
key="btc-segwit", name="Bitcoin SegWit", family=ChainFamily.BITCOIN, symbol="BTC",
slip44=0, hd_path="m/49'/0'/0'/0/0", decimals=8,
address_pattern="^(3|bc1)[a-zA-Z0-9]{25,62}$",
explorer_url="https://blockstream.info",
curve="secp256k1", native_token="BTC",
description="Bitcoin SegWit (P2SH-P2WPKH) — lower fees",
),
"btc-native-segwit": ChainInfo(
key="btc-native-segwit", name="Bitcoin Native SegWit", family=ChainFamily.BITCOIN, symbol="BTC",
slip44=0, hd_path="m/84'/0'/0'/0/0", decimals=8,
address_pattern="^bc1[a-zA-Z0-9]{39,59}$",
explorer_url="https://blockstream.info",
curve="secp256k1", native_token="BTC",
description="Bitcoin Native SegWit (P2WPKH) — lowest fees",
),
# ── EVM Family ──────────────────────────────────────────
"eth": ChainInfo(
key="eth", name="Ethereum", family=ChainFamily.EVM, symbol="ETH",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://etherscan.io",
rpc_url="https://eth.llamarpc.com", native_token="ETH",
description="Ethereum — smart contract platform",
),
"base": ChainInfo(
key="base", name="Base", family=ChainFamily.EVM, symbol="ETH",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://basescan.org",
rpc_url="https://mainnet.base.org", native_token="ETH",
description="Coinbase Base L2",
),
"polygon": ChainInfo(
key="polygon", name="Polygon", family=ChainFamily.EVM, symbol="POL",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://polygonscan.com",
rpc_url="https://polygon-rpc.com", native_token="POL",
description="Polygon PoS",
),
"arbitrum": ChainInfo(
key="arbitrum", name="Arbitrum One", family=ChainFamily.EVM, symbol="ETH",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://arbiscan.io",
rpc_url="https://arb1.arbitrum.io/rpc", native_token="ETH",
description="Arbitrum One L2",
),
"optimism": ChainInfo(
key="optimism", name="Optimism", family=ChainFamily.EVM, symbol="ETH",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://optimistic.etherscan.io",
rpc_url="https://mainnet.optimism.io", native_token="ETH",
description="Optimism L2",
),
"avalanche": ChainInfo(
key="avalanche", name="Avalanche C-Chain", family=ChainFamily.EVM, symbol="AVAX",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://snowtrace.io",
rpc_url="https://api.avax.network/ext/bc/C/rpc", native_token="AVAX",
description="Avalanche C-Chain",
),
"bsc": ChainInfo(
key="bsc", name="BNB Smart Chain", family=ChainFamily.EVM, symbol="BNB",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://bscscan.com",
rpc_url="https://bsc-dataseed.binance.org", native_token="BNB",
description="BNB Smart Chain",
),
"fantom": ChainInfo(
key="fantom", name="Fantom", family=ChainFamily.EVM, symbol="FTM",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://ftmscan.com",
rpc_url="https://rpc.ftm.tools", native_token="FTM",
description="Fantom Opera",
),
"gnosis": ChainInfo(
key="gnosis", name="Gnosis Chain", family=ChainFamily.EVM, symbol="XDAI",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://gnosisscan.io",
rpc_url="https://rpc.gnosischain.com", native_token="XDAI",
description="Gnosis Chain (formerly xDai)",
),
"celo": ChainInfo(
key="celo", name="Celo", family=ChainFamily.EVM, symbol="CELO",
slip44=52752, hd_path="m/44'/52752'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://celoscan.io",
rpc_url="https://forno.celo.org", native_token="CELO",
description="Celo — mobile-first DeFi",
),
"scroll": ChainInfo(
key="scroll", name="Scroll", family=ChainFamily.EVM, symbol="ETH",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://scrollscan.com",
rpc_url="https://rpc.scroll.io", native_token="ETH",
description="Scroll zkEVM L2",
),
"zksync": ChainInfo(
key="zksync", name="zkSync Era", family=ChainFamily.EVM, symbol="ETH",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://explorer.zksync.io",
rpc_url="https://mainnet.era.zksync.io", native_token="ETH",
description="zkSync Era zkEVM L2",
),
"blast": ChainInfo(
key="blast", name="Blast", family=ChainFamily.EVM, symbol="ETH",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://blastscan.io",
rpc_url="https://rpc.blast.io", native_token="ETH",
description="Blast L2",
),
"mantle": ChainInfo(
key="mantle", name="Mantle", family=ChainFamily.EVM, symbol="MNT",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://explorer.mantle.xyz",
rpc_url="https://rpc.mantle.xyz", native_token="MNT",
description="Mantle L2",
),
"linea": ChainInfo(
key="linea", name="Linea", family=ChainFamily.EVM, symbol="ETH",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://lineascan.build",
rpc_url="https://rpc.linea.build", native_token="ETH",
description="Linea zkEVM by ConsenSys",
),
"metis": ChainInfo(
key="metis", name="Metis", family=ChainFamily.EVM, symbol="METIS",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://andromeda-explorer.metis.io",
rpc_url="https://andromeda.metis.io", native_token="METIS",
description="Metis L2",
),
# ── Solana ───────────────────────────────────────────────
"sol": ChainInfo(
key="sol", name="Solana", family=ChainFamily.SOLANA, symbol="SOL",
slip44=501, hd_path="m/44'/501'/0'/0'", decimals=9,
address_pattern="^[1-9A-HJ-NP-Za-km-z]{32,44}$",
explorer_url="https://solscan.io",
rpc_url="https://api.mainnet-beta.solana.com", native_token="SOL",
curve="ed25519",
description="Solana — high-performance blockchain",
),
# ── TRON ─────────────────────────────────────────────────
"trx": ChainInfo(
key="trx", name="TRON", family=ChainFamily.TRON, symbol="TRX",
slip44=195, hd_path="m/44'/195'/0'/0/0", decimals=6,
address_pattern="^T[a-zA-Z0-9]{33}$",
explorer_url="https://tronscan.org",
rpc_url="https://api.trongrid.io", native_token="TRX",
description="TRON network",
),
# ── Alt L1s (secp256k1) ──────────────────────────────────
"doge": ChainInfo(
key="doge", name="Dogecoin", family=ChainFamily.SECP256K1_ALT, symbol="DOGE",
slip44=3, hd_path="m/44'/3'/0'/0/0", decimals=8,
address_pattern="^D[a-zA-Z0-9]{33}$",
explorer_url="https://dogechain.info",
curve="secp256k1", native_token="DOGE",
description="Dogecoin — much wow",
),
"ltc": ChainInfo(
key="ltc", name="Litecoin", family=ChainFamily.SECP256K1_ALT, symbol="LTC",
slip44=2, hd_path="m/44'/2'/0'/0/0", decimals=8,
address_pattern="^(L|M|ltc1)[a-zA-Z0-9]{25,62}$",
explorer_url="https://blockchair.com/litecoin",
curve="secp256k1", native_token="LTC",
description="Litecoin — silver to Bitcoin's gold",
),
"bch": ChainInfo(
key="bch", name="Bitcoin Cash", family=ChainFamily.SECP256K1_ALT, symbol="BCH",
slip44=145, hd_path="m/44'/145'/0'/0/0", decimals=8,
address_pattern="^(bitcoincash:|q|p)[a-zA-Z0-9]{25,62}$",
explorer_url="https://blockchair.com/bitcoin-cash",
curve="secp256k1", native_token="BCH",
description="Bitcoin Cash",
),
"dash": ChainInfo(
key="dash", name="Dash", family=ChainFamily.SECP256K1_ALT, symbol="DASH",
slip44=5, hd_path="m/44'/5'/0'/0/0", decimals=8,
address_pattern="^X[a-zA-Z0-9]{33}$",
explorer_url="https://blockchair.com/dash",
curve="secp256k1", native_token="DASH",
description="Dash — digital cash",
),
"zec": ChainInfo(
key="zec", name="Zcash", family=ChainFamily.SECP256K1_ALT, symbol="ZEC",
slip44=133, hd_path="m/44'/133'/0'/0/0", decimals=8,
address_pattern="^(t1|t3|zs1)[a-zA-Z0-9]{25,90}$",
explorer_url="https://blockchair.com/zcash",
curve="secp256k1", native_token="ZEC",
description="Zcash — privacy-focused",
),
# ── Ed25519 Family ───────────────────────────────────────
"ada": ChainInfo(
key="ada", name="Cardano", family=ChainFamily.ED25519, symbol="ADA",
slip44=1815, hd_path="m/1852'/1815'/0'/0/0", decimals=6,
address_pattern="^addr1[a-zA-Z0-9]{50,}$",
explorer_url="https://cardanoscan.io",
curve="ed25519", native_token="ADA",
description="Cardano Shelley",
),
"near": ChainInfo(
key="near", name="NEAR Protocol", family=ChainFamily.ED25519, symbol="NEAR",
slip44=397, hd_path="m/44'/397'/0'/0'", decimals=24,
address_pattern="^[a-f0-9]{64}$",
explorer_url="https://nearblocks.io",
curve="ed25519", native_token="NEAR",
description="NEAR Protocol",
),
"sui": ChainInfo(
key="sui", name="Sui", family=ChainFamily.ED25519, symbol="SUI",
slip44=784, hd_path="m/44'/784'/0'/0'", decimals=9,
address_pattern="^0x[a-fA-F0-9]{64}$",
explorer_url="https://suiscan.xyz",
curve="ed25519", native_token="SUI",
description="Sui Network",
),
"aptos": ChainInfo(
key="apt", name="Aptos", family=ChainFamily.ED25519, symbol="APT",
slip44=637, hd_path="m/44'/637'/0'/0'", decimals=8,
address_pattern="^0x[a-fA-F0-9]{64}$",
explorer_url="https://aptoscan.com",
curve="ed25519", native_token="APT",
description="Aptos",
),
# ── Ripple ───────────────────────────────────────────────
"xrp": ChainInfo(
key="xrp", name="Ripple XRP", family=ChainFamily.RIPPLE, symbol="XRP",
slip44=144, hd_path="m/44'/144'/0'/0/0", decimals=6,
address_pattern="^r[a-zA-Z0-9]{24,34}$",
explorer_url="https://xrpscan.com",
curve="secp256k1", native_token="XRP",
description="Ripple XRP Ledger",
),
# ── Substrate ────────────────────────────────────────────
"dot": ChainInfo(
key="dot", name="Polkadot", family=ChainFamily.SUBSTRATE, symbol="DOT",
slip44=354, hd_path="m/44'/354'/0'/0/0", decimals=10,
address_pattern="^1[a-zA-Z0-9]{47}$",
explorer_url="https://polkadot.subscan.io",
curve="sr25519", native_token="DOT",
description="Polkadot — sharded multichain",
),
"ksm": ChainInfo(
key="ksm", name="Kusama", family=ChainFamily.SUBSTRATE, symbol="KSM",
slip44=434, hd_path="m/44'/434'/0'/0/0", decimals=12,
address_pattern="^[a-km-zA-HJ-NP-Z1-9]{47}$",
explorer_url="https://kusama.subscan.io",
curve="sr25519", native_token="KSM",
description="Kusama — Polkadot's canary network",
),
# ── Cosmos ───────────────────────────────────────────────
"atom": ChainInfo(
key="atom", name="Cosmos Hub", family=ChainFamily.COSMOS, symbol="ATOM",
slip44=118, hd_path="m/44'/118'/0'/0/0", decimals=6,
address_pattern="^cosmos1[a-zA-Z0-9]{38}$",
explorer_url="https://mintscan.io/cosmos",
curve="secp256k1", native_token="ATOM",
description="Cosmos Hub",
),
"osmo": ChainInfo(
key="osmo", name="Osmosis", family=ChainFamily.COSMOS, symbol="OSMO",
slip44=118, hd_path="m/44'/118'/0'/0/0", decimals=6,
address_pattern="^osmo1[a-zA-Z0-9]{38}$",
explorer_url="https://mintscan.io/osmosis",
curve="secp256k1", native_token="OSMO",
description="Osmosis DEX",
),
"inj": ChainInfo(
key="inj", name="Injective", family=ChainFamily.COSMOS, symbol="INJ",
slip44=60, hd_path="m/44'/60'/0'/0/0", decimals=18,
address_pattern="^inj1[a-zA-Z0-9]{38}$",
explorer_url="https://explorer.injective.network",
curve="secp256k1", native_token="INJ",
description="Injective — DeFi derivatives",
),
"juno": ChainInfo(
key="juno", name="Juno", family=ChainFamily.COSMOS, symbol="JUNO",
slip44=118, hd_path="m/44'/118'/0'/0/0", decimals=6,
address_pattern="^juno1[a-zA-Z0-9]{38}$",
explorer_url="https://mintscan.io/juno",
curve="secp256k1", native_token="JUNO",
description="Juno — smart contract hub",
),
"sei": ChainInfo(
key="sei", name="Sei", family=ChainFamily.COSMOS, symbol="SEI",
slip44=118, hd_path="m/44'/118'/0'/0/0", decimals=6,
address_pattern="^sei1[a-zA-Z0-9]{38}$",
explorer_url="https://seiscan.app",
curve="secp256k1", native_token="SEI",
description="Sei — fastest L1",
),
# ── Algorand ─────────────────────────────────────────────
"algo": ChainInfo(
key="algo", name="Algorand", family=ChainFamily.ALGORAND, symbol="ALGO",
slip44=283, hd_path="m/44'/283'/0'/0'", decimals=6,
address_pattern="^[A-Z0-9]{58}$",
explorer_url="https://algoexplorer.io",
curve="ed25519", native_token="ALGO",
description="Algorand — pure proof-of-stake",
),
# ── Tezos ────────────────────────────────────────────────
"xtz": ChainInfo(
key="xtz", name="Tezos", family=ChainFamily.TEZOS, symbol="XTZ",
slip44=1729, hd_path="m/44'/1729'/0'/0'", decimals=6,
address_pattern="^(tz1|tz2|tz3)[a-zA-Z0-9]{33}$",
explorer_url="https://tzkt.io",
curve="ed25519", native_token="XTZ",
description="Tezos — self-amending L1",
),
# ── Monero ───────────────────────────────────────────────
"xmr": ChainInfo(
key="xmr", name="Monero", family=ChainFamily.MONERO, symbol="XMR",
slip44=128, hd_path="m/44'/128'/0'/0/0", decimals=12,
address_pattern="^[48][a-zA-Z0-9]{94}$",
explorer_url="https://xmrchain.net",
curve="ed25519", native_token="XMR",
description="Monero — private, untraceable",
),
# ── Stellar ──────────────────────────────────────────────
"xlm": ChainInfo(
key="xlm", name="Stellar", family=ChainFamily.STELLAR, symbol="XLM",
slip44=148, hd_path="m/44'/148'/0'/0'", decimals=7,
address_pattern="^G[A-Z0-9]{55}$",
explorer_url="https://stellar.expert",
curve="ed25519", native_token="XLM",
description="Stellar — cross-border payments",
),
# ── TON ──────────────────────────────────────────────────
"ton": ChainInfo(
key="ton", name="TON", family=ChainFamily.TON, symbol="TON",
slip44=396, hd_path="m/44'/396'/0'/0'", decimals=9,
address_pattern="^[EQ][a-fA-F0-9]{48}$",
explorer_url="https://tonscan.org",
curve="ed25519", native_token="TON",
description="The Open Network",
),
# ── Nano ─────────────────────────────────────────────────
"nano": ChainInfo(
key="nano", name="Nano", family=ChainFamily.NANO, symbol="XNO",
slip44=165, hd_path="m/44'/165'/0'", decimals=30,
address_pattern="^nano_[1-9a-z]{60}$",
explorer_url="https://nanolooker.com",
curve="ed25519", native_token="XNO",
description="Nano — feeless, instant",
),
# ── Filecoin ─────────────────────────────────────────────
"fil": ChainInfo(
key="fil", name="Filecoin", family=ChainFamily.FILECOIN, symbol="FIL",
slip44=461, hd_path="m/44'/461'/0'/0/0", decimals=18,
address_pattern="^f1[a-zA-Z0-9]{40}$",
explorer_url="https://filfox.info",
curve="secp256k1", native_token="FIL",
description="Filecoin — decentralized storage",
),
# ── Additional EVM chains ────────────────────────────────
"opbnb": ChainInfo(
key="opbnb", name="opBNB", family=ChainFamily.EVM, symbol="BNB",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://opbnbscan.com",
rpc_url="https://opbnb-mainnet-rpc.bnbchain.org", native_token="BNB",
description="opBNB L2",
),
"core": ChainInfo(
key="core", name="Core Chain", family=ChainFamily.EVM, symbol="CORE",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://scan.coredao.org",
rpc_url="https://rpc.coredao.org", native_token="CORE",
description="Core Chain — Bitcoin-powered EVM",
),
"frax": ChainInfo(
key="frax", name="Fraxchain", family=ChainFamily.EVM, symbol="FXS",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://fraxscan.com",
rpc_url="https://rpc.frax.com", native_token="FXS",
description="Fraxchain L2",
),
"kava": ChainInfo(
key="kava", name="Kava EVM", family=ChainFamily.EVM, symbol="KAVA",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://kavascan.com",
rpc_url="https://evm.kava.io", native_token="KAVA",
description="Kava EVM co-chain",
),
"moonbeam": ChainInfo(
key="moonbeam", name="Moonbeam", family=ChainFamily.EVM, symbol="GLMR",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://moonscan.io",
rpc_url="https://rpc.api.moonbeam.network", native_token="GLMR",
description="Moonbeam — Polkadot parachain EVM",
),
"cronos": ChainInfo(
key="cronos", name="Cronos", family=ChainFamily.EVM, symbol="CRO",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://cronoscan.com",
rpc_url="https://evm.cronos.org", native_token="CRO",
description="Cronos — Crypto.org EVM",
),
"aurora": ChainInfo(
key="aurora", name="Aurora", family=ChainFamily.EVM, symbol="ETH",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://aurorascan.dev",
rpc_url="https://mainnet.aurora.dev", native_token="ETH",
description="Aurora — NEAR EVM",
),
"harmony": ChainInfo(
key="harmony", name="Harmony", family=ChainFamily.EVM, symbol="ONE",
slip44=1023, hd_path="m/44'/1023'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://explorer.harmony.one",
rpc_url="https://api.harmony.one", native_token="ONE",
description="Harmony — sharded L1",
),
"boba": ChainInfo(
key="boba", name="Boba Network", family=ChainFamily.EVM, symbol="BOBA",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://bobascan.com",
rpc_url="https://mainnet.boba.network", native_token="ETH",
description="Boba Network L2",
),
"evmos": ChainInfo(
key="evmos", name="Evmos", family=ChainFamily.EVM, symbol="EVMOS",
slip44=60, hd_path="m/44'/60'/0'/0/0",
address_pattern="^0x[a-fA-F0-9]{40}$",
explorer_url="https://evmos.org",
rpc_url="https://evmos.lava.build", native_token="EVMOS",
description="Evmos — EVM on Cosmos",
),
}
# ── Chain Groups ──────────────────────────────────────────────────
CHAIN_GROUPS: dict[str, list[str]] = {
"evm": [k for k, v in CHAINS.items() if v.family == ChainFamily.EVM],
"bitcoin": [k for k, v in CHAINS.items() if v.family in (ChainFamily.BITCOIN, ChainFamily.SECP256K1_ALT)],
"solana": ["sol"],
"cosmos": [k for k, v in CHAINS.items() if v.family == ChainFamily.COSMOS],
"substrate": [k for k, v in CHAINS.items() if v.family == ChainFamily.SUBSTRATE],
"ed25519": [k for k, v in CHAINS.items() if v.curve == "ed25519"],
"privacy": ["xmr", "zec"],
"l1": [k for k, v in CHAINS.items() if v.family in (
ChainFamily.SOLANA, ChainFamily.TRON, ChainFamily.ALGORAND,
ChainFamily.TEZOS, ChainFamily.RIPPLE, ChainFamily.NANO,
ChainFamily.TON, ChainFamily.STELLAR,
)],
"l2": [k for k, v in CHAINS.items() if v.family == ChainFamily.EVM and v.key not in ("eth", "bsc", "avalanche", "polygon", "fantom", "gnosis", "celo", "harmony")],
"all": list(CHAINS.keys()),
}
# ── Tiers ─────────────────────────────────────────────────────────
TIERS = {
"free": {
"label": "Free",
"chains": ["btc", "eth", "sol"],
"max_wallets": 10,
"features": ["basic_generation", "wp_plugin"],
},
"starter": {
"label": "Starter",
"price_usd": 49,
"chains": list(CHAINS.keys())[:12],
"max_wallets": 500,
"features": ["basic_generation", "batch_generation", "vault", "mnemonic_convert", "wp_plugin", "cli", "export"],
},
"pro": {
"label": "Pro",
"price_usd": 199,
"chains": list(CHAINS.keys())[:50],
"max_wallets": 5000,
"features": ["basic_generation", "batch_generation", "hd_wallets", "vault", "mnemonic_convert",
"wp_plugin", "cli", "export", "shamir_backup", "sweep", "alerts", "webhooks",
"api_keys", "audit"],
},
"enterprise": {
"label": "Enterprise",
"price_usd": 499,
"chains": list(CHAINS.keys()),
"max_wallets": 100000,
"features": ["all"],
},
}
def get_chains_for_tier(tier: str) -> dict[str, ChainInfo]:
tier_info = TIERS.get(tier, TIERS["free"])
return {k: CHAINS[k] for k in tier_info["chains"] if k in CHAINS}
def validate_address(chain_key: str, address: str) -> bool:
chain = CHAINS.get(chain_key)
if not chain:
return False
import re
return bool(re.match(chain.address_pattern, address))
# ── YAML Chain Loader ──────────────────────────────────────────────
# Users can define custom chains in chains.yaml (next to this file).
# Values merge on top of the defaults above. Override any field.
YAML_PATH = Path(__file__).parent / "chains.yaml"
def load_chains_yaml(path: Path = YAML_PATH) -> dict[str, ChainInfo]:
"""Load custom chain definitions from YAML, merged on top of defaults.
Format:
<key>:
name: str
family: str (must match a ChainFamily value)
symbol: str
slip44: int
hd_path: str
decimals: int
address_pattern: str
explorer_url: str
rpc_url: str
curve: str
native_token: str
Returns dict of chain_key → ChainInfo. Empty dict if YAML not found.
"""
if not path.exists():
return {}
try:
import yaml
data = yaml.safe_load(path.read_text())
except ImportError:
logger.warning("PyYAML not installed — cannot load chains.yaml")
return {}
except Exception as e:
logger.error(f"Failed to load {path}: {e}")
return {}
if not isinstance(data, dict):
return {}
result: dict[str, ChainInfo] = {}
for key, cfg in data.items():
try:
family_str = cfg.pop("family", "evm")
family = ChainFamily(family_str)
# Map YAML fields to ChainInfo constructor
info = ChainInfo(
key=key,
name=cfg.get("name", key.upper()),
family=family,
symbol=cfg.get("symbol", key.upper()),
slip44=int(cfg.get("slip44", 0)),
hd_path=cfg.get("hd_path", ""),
decimals=int(cfg.get("decimals", 18)),
address_pattern=str(cfg.get("address_pattern", "")),
explorer_url=cfg.get("explorer_url", ""),
rpc_url=cfg.get("rpc_url", ""),
curve=cfg.get("curve", "secp256k1"),
native_token=cfg.get("native_token", ""),
description=cfg.get("description", ""),
)
result[key] = info
except Exception as e:
logger.warning(f"Skipping chain '{key}' in {path}: {e}")
return result
# Merge YAML chains on top of defaults
_yaml_chains = load_chains_yaml()
if _yaml_chains:
CHAINS.update(_yaml_chains)
logger.info(f"Merged {len(_yaml_chains)} chain(s) from {YAML_PATH}")