Skip to main content
Parse and decode a raw signed transaction
import { Transaction } from '@tevm/voltaire/Transaction';
import { Address } from '@tevm/voltaire/Address';
import { Hex } from '@tevm/voltaire/Hex';

// Raw signed EIP-1559 transaction (type 0x02)
const rawTxHex =
	"0x02f8730180843b9aca008504a817c80082520894" +
	"70997970c51812dc3a010c7d01b50e0d17dc79c8" +
	"880de0b6b3a764000080c001a0" +
	"8c5d1c1e1d7a3d0b2d9d5c5e5f5a5b5c5d5e5f5a5b5c5d5e5f5a5b5c5d5e5f5a" +
	"a0" +
	"1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b";

// Convert hex to bytes
const rawTxBytes = Hex.toBytes(rawTxHex);

// Deserialize - automatically detects transaction type
const tx = Transaction.deserialize(rawTxBytes);

// Extract transaction details based on type
if (tx.type === Transaction.Type.EIP1559) {
	// Type 2 (EIP-1559) specific fields
	const chainId = tx.chainId;
	const nonce = tx.nonce;
	const maxPriorityFeePerGas = tx.maxPriorityFeePerGas;
	const maxFeePerGas = tx.maxFeePerGas;
	const gasLimit = tx.gasLimit;
	const to = tx.to ? Address.toChecksummed(tx.to) : null;
	const value = tx.value;
	const data = Hex.fromBytes(tx.data);

	// Signature components
	const yParity = tx.yParity;
	const r = Hex.fromBytes(tx.r);
	const s = Hex.fromBytes(tx.s);

	// Recover sender from signature
	const sender = Transaction.getSender(tx);
	const senderAddress = Address.toChecksummed(sender);
}

// Handle legacy transactions (type 0)
if (tx.type === Transaction.Type.Legacy) {
	const gasPrice = tx.gasPrice;
	const v = tx.v;
	const sender = Transaction.getSender(tx);
}

// Handle EIP-2930 transactions (type 1)
if (tx.type === Transaction.Type.EIP2930) {
	const accessList = tx.accessList;
	const sender = Transaction.getSender(tx);
}

// Compute transaction hash
const txHash = Transaction.hash(tx);
const txHashHex = Hex.fromBytes(txHash);
This is a fully executable example. View the complete source with test assertions at examples/transactions/decode-transaction.ts.