Prerequisites
- A deployment of the parser (see overview).
- The raw unsigned transaction as hex (with or without
0xprefix) or base64.
Quick path
For known protocols and standard token transfers, no ABI is required. The parser ships with built-in decoders and a registry of well-known tokens. A common request includes the raw transaction and anetwork_id to help the parser label the network and resolve chain-specific token metadata. Both ChainMetadata and network_id are optional; the parser falls back to the chain ID embedded in the transaction when neither is supplied:
parsed_payload is a JSON string conforming to the schema documented in Field Types. Display it to the user before signing.
Built-in token metadata coverage
Built-in token metadata (WETH on all five chains, plus USDC, USDT, DAI, and SETH on Ethereum mainnet) is preloaded for these five chains:
The parser itself recognizes many more
network_id values (Ethereum testnets, BSC, Avalanche, Gnosis, Celo, Fantom, Blast, Mantle, World Chain, zkSync Era, Linea, Scroll, Zora, Unichain, and L2 testnets) for the purpose of labeling the network and resolving the chain ID. The authoritative list lives in src/chain_parsers/visualsign-ethereum/src/networks.rs. The five chains above are the subset that ships with token metadata baked in; on the others, token symbol and decimal resolution is limited to the built-in registry (wallet-supplied token metadata via chain_metadata is not yet supported).
How network_id resolves to a chain ID
The network_id you pass in metadata takes priority over the transaction’s embedded chain ID (resolve_chain_id in src/chain_parsers/visualsign-ethereum/src/lib.rs). If both are present and disagree, the parser uses the metadata value and logs a warning. If you omit network_id, the parser uses the chain ID embedded in the transaction (present in EIP-1559 and EIP-155 legacy transactions). It only defaults to Ethereum mainnet when no chain ID is available from either source, which is only possible for pre-EIP-155 legacy transactions.
To parse a transaction for a chain outside the five with built-in token metadata, pass the actual network_id for that chain (e.g. BSC_MAINNET, AVALANCHE_MAINNET) or omit network_id entirely and let the transaction’s chain ID drive resolution. Do not reuse one of the five token-covered network_ids for an unrelated chain: it will mislabel the Network field and may change protocol address matching.
What’s auto-decoded versus what needs an ABI
ERC-1155 contracts are recognized as a
TokenMetadata type but have no dedicated calldata decoder. To decode ERC-1155 safeTransferFrom calls into readable fields, provide the contract’s ABI.
Providing ABIs
For contracts outside the auto-decoded set, populateabi_mappings keyed by contract address. The value is the Solidity ABI JSON, optionally with a signature for provenance (see Ethereum for dApp Builders for the signing model).
gRPC
Rust library
Address casing
abi_mappings is a string-keyed map. The parser parses each key into a numeric Address before registration, so address lookup is case-insensitive and 0xdAC17... and 0xdac17... resolve to the same contract. That said, use a consistent casing convention (all lowercase or EIP-55 checksummed) across your wallet’s ABI store to avoid duplicate entries for the same contract.
Supported transaction types
The parser accepts unsigned Ethereum transactions in RLP form. Two transaction types are supported:
If your wallet may submit unsupported types, surface the error message to the user and fall back to a raw-data display (see Error Handling).
The standard API accepts unsigned transactions only. Signed envelope decoding is gated behind a developer flag (
DeveloperConfig::allow_signed_transactions) intended for tooling, not production wallet flows.
The rendered payload
The parser returns a JSONSignablePayload with a Title, optional Subtitle, and an array of Fields. For Ethereum, the top-level fields always include network, recipient, value, gas information, and nonce, followed by a decoded representation of the calldata (when applicable).
Take a Uniswap Universal Router swap as a concrete example: an execute call with four commands (two V3 swaps, a fee payment, and a WETH unwrap). The parser produces:
- Every field has a
FallbackText. Render that string if you don’t yet support the field’sType. New field types may be added in future versions, andFallbackTextis the forward-compatible escape hatch. PreviewLayoutis recursive. Multi-step operations like Universal Router commands nest layouts. Show theSubtitlecollapsed, and reveal theExpanded.Fieldson user action.- Amounts come pre-formatted when token metadata is known. When the parser can resolve a token’s decimals and symbol from the built-in registry,
AmountV2.Amountis already scaled andAmountV2.Abbreviationis set; render both verbatim. When token metadata is unknown,Amountis the raw on-chain integer andAbbreviationis absent; display the raw value alongside the contract address in that case. Note: direct ERC-20transfer/approve/transferFromcalls always use the raw on-chain integer (the ERC-20 fallback decoder does not consult the registry); token amounts are scaled and labeled only when a protocol-specific decoder (such as the Uniswap Universal Router decoder) handles the call. - Comparison operators are ASCII. Slippage and minimums use
>=and<=, not Unicode glyphs.
TextV2, AddressV2, AmountV2, Number, PreviewLayout, Divider) is documented in Field Types. The Uniswap fixture above is checked into the repo at src/chain_parsers/visualsign-ethereum/tests/fixtures/uniswap-v3swap.expected and can be reproduced end-to-end with parser_cli (see Parser CLI).
Error handling for EVM
Beyond the generic categories covered in Error Handling, the EVM parser surfaces a few EVM-specific failure modes:Next steps
- Ethereum for dApp Builders: How contract authors make their transactions render meaningfully in your wallet.
- Chain Metadata: Cross-chain reference for ABIs and IDLs.
- Attestation Verification: Required for TEE deployments.
- Parser CLI: Reproduce parsing locally against your own fixtures.