butr
Core concepts

Platforms and chains

Every connector is evm, svm, sui, or bitcoin. Platforms are tracked independently. Chains use CAIP-2 identifiers.

ChainPlatform

type ChainPlatform = "evm" | "svm" | "sui" | "bitcoin" | "polkadot";

Every connector carries a chainPlatform. butr tracks each platform independently — a user can connect MetaMask (evm), Phantom Solana (svm), Slush Sui (sui), and Phantom Bitcoin (bitcoin) simultaneously, and each platform has its own selected wallet. A single multi-chain wallet (Phantom EVM + Phantom SVM + Phantom BTC) appears as separate pool entries with different chainPlatform values.

ChainBase — the CAIP-2 shape

butr only needs four fields per chain. It follows CAIP-2 and never inspects beyond these.

type ChainBase = {
  id: string; // "eip155:1", "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"
  name: string; // "Ethereum", "Solana"
  namespace: string; // "eip155", "solana"
  reference: string; // "1", "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"
};

Chain ids are opaque strings to butr — it never parses them. You extend ChainBase with app-specific fields (logos, explorers, RPC URLs) via structural typing; butr passes the whole object through untouched.

Chain registries

Static lists ship with the protocol packages. You don't have to use them — any ChainBase-shaped object works — but they cover the common networks.

ExportPackageContents
EVM_CHAINS, EVM_CHAINS_LIST@usebutr/evmEthereum (+ Sepolia, Holesky), Polygon, Arbitrum, Optimism, Base, and more.
SVM_CHAINS, SVM_CHAINS_LIST@usebutr/svmSolana mainnet / testnet / devnet.
SUI_CHAINS, SUI_CHAINS_LIST@usebutr/suiSui mainnet / testnet / devnet.
BITCOIN_CHAINS, BITCOIN_CHAINS_LIST@usebutr/bitcoinBitcoin mainnet / testnet / regtest.
POLKADOT_CHAINS, POLKADOT_CHAINS_LIST@usebutr/polkadotPolkadot / Paseo testnet / Kusama.
CHAINS, CHAINS_BY_PLATFORM@usebutr/walletsAll five registries, keyed by platform.

CHAINS_BY_PLATFORM[wallet.connector.chainPlatform] is the idiomatic way to get the right chain list for a connected wallet — see multi-chain switching.

Platform differences

EVMSVMSuiBitcoinPolkadot
DiscoveryEIP-6963 (+ injected fallback)Wallet StandardWallet StandardWallet Standard (+ injected fallback)injectedWeb3 (+ Wallet Standard)
Accounts exposedone or many (MetaMask multi-account)all at onceall at onceone or many (per address format)all at once (SS58-encoded)
requestAccountsprompts via wallet_requestPermissionsno picker — resolves as a refreshno pickerno pickerno picker — wallet lists all accounts
Chain switchingreal, via wallet_switchEthereumChainlocal state + per-call chain inputlocal state + per-call chain inputlocal state — switching network = re-connectlocal state + per-call genesisHash input
Signature formatEIP-191 / 712, input echoedSolana format, may re-encode signedMessagesui:signPersonalMessage, returns bytesBitcoin Signed Message — not interchangeableSCALE-encoded payload; signRaw for raw bytes
Transaction shapeRLP-encoded; broadcast separatelyversioned/legacy tx bytes; signAndSendBCS-encoded Transaction blocksPSBT (BIP-174); consumer finalises and broadcastSCALE extrinsic bytes (PAPI); broadcast via RPC node

Source: packages/core/src/types/chain.ts, packages/{evm,svm,sui,bitcoin,polkadot,wallets}/src/chains.ts.

On this page