Skip to main content

Try it Live

Run Transaction examples in the interactive playground

detectType

Detect transaction type from serialized bytes.

    Type Detection Logic

    Typed Transactions (EIP-2718)

    Typed transactions start with a type byte (0x00-0x04):
    [type_byte, ...rlp_payload]
     ^^^^^^^^^^
     First byte indicates type
    
    First ByteType
    0x01EIP-2930 (Access List)
    0x02EIP-1559 (Dynamic Fee)
    0x03EIP-4844 (Blob)
    0x04EIP-7702 (Authorization)
    0xc0-0xffLegacy (RLP list marker)

    Legacy Transactions

    Legacy transactions start with RLP list marker (0xc0-0xff):
    [rlp_list_marker, ...rlp_content]
     ^^^^^^^^^^^^^^^^
     RLP list encoding (≥ 0xc0)
    
    RLP list markers:
    • 0xc0-0xf7: Short list (0-55 bytes)
    • 0xf8-0xff: Long list (>55 bytes)

    Usage Patterns

    Router Pattern

    import { detectType, Type } from 'tevm/Transaction'
    import { InvalidTransactionTypeError } from 'tevm/errors'
    
    function routeTransaction(data: Uint8Array) {
      const type = detectType(data)
    
      switch (type) {
        case Type.Legacy:
          return processLegacy(data)
        case Type.EIP2930:
          return processEIP2930(data)
        case Type.EIP1559:
          return processEIP1559(data)
        case Type.EIP4844:
          return processEIP4844(data)
        case Type.EIP7702:
          return processEIP7702(data)
        default:
          throw new InvalidTransactionTypeError(`Unsupported type: ${type}`, {
            code: 'UNSUPPORTED_TRANSACTION_TYPE',
            context: { type }
          })
      }
    }
    

    Conditional Deserialization

    import { detectType, deserialize, Type } from 'tevm/Transaction'
    
    function parseTransaction(data: Uint8Array) {
      const type = detectType(data)
    
      // Can optimize deserialization based on type
      if (type === Type.Legacy) {
        return deserializeLegacy(data)
      } else {
        return deserialize(data)
      }
    }
    

    Transaction Classification

    import { detectType, Type } from 'tevm/Transaction'
    
    function classifyTransactions(
      transactions: Uint8Array[]
    ): Map<Transaction.Type, number> {
      const counts = new Map<Transaction.Type, number>()
    
      for (const data of transactions) {
        const type = detectType(data)
        counts.set(type, (counts.get(type) || 0) + 1)
      }
    
      return counts
    }
    
    // Usage
    const txData = [/* serialized transactions */]
    const counts = classifyTransactions(txData)
    
    console.log(`Legacy: ${counts.get(Type.Legacy) || 0}`)
    console.log(`EIP-1559: ${counts.get(Type.EIP1559) || 0}`)
    console.log(`EIP-4844: ${counts.get(Type.EIP4844) || 0}`)
    

    Block Analysis

    import { detectType, Type } from 'tevm/Transaction'
    
    interface BlockStats {
      totalTransactions: number
      byType: Record<string, number>
    }
    
    function analyzeBlock(transactions: Uint8Array[]): BlockStats {
      const byType: Record<string, number> = {}
    
      for (const data of transactions) {
        const type = detectType(data)
        const typeName = getTypeName(type)
        byType[typeName] = (byType[typeName] || 0) + 1
      }
    
      return {
        totalTransactions: transactions.length,
        byType
      }
    }
    
    function getTypeName(type: Transaction.Type): string {
      switch (type) {
        case Type.Legacy: return 'Legacy'
        case Type.EIP2930: return 'EIP-2930'
        case Type.EIP1559: return 'EIP-1559'
        case Type.EIP4844: return 'EIP-4844'
        case Type.EIP7702: return 'EIP-7702'
        default: return `Unknown (${type})`
      }
    }
    

    Network Statistics

    import { detectType, Type } from 'tevm/Transaction'
    
    class NetworkMonitor {
      private stats = new Map<Transaction.Type, number>()
    
      processTransaction(data: Uint8Array) {
        const type = detectType(data)
        this.stats.set(type, (this.stats.get(type) || 0) + 1)
      }
    
      getStats() {
        return {
          legacy: this.stats.get(Type.Legacy) || 0,
          eip2930: this.stats.get(Type.EIP2930) || 0,
          eip1559: this.stats.get(Type.EIP1559) || 0,
          eip4844: this.stats.get(Type.EIP4844) || 0,
          eip7702: this.stats.get(Type.EIP7702) || 0,
          total: Array(this.stats.values()).reduce((a, b) => a + b, 0)
        }
      }
    }
    

    Pre-validation

    import { detectType, Type } from 'tevm/Transaction'
    
    function validateTransactionType(
      data: Uint8Array,
      allowedTypes: Transaction.Type[]
    ): boolean {
      try {
        const type = detectType(data)
        return allowedTypes.includes(type)
      } catch {
        return false
      }
    }
    
    // Usage: Only allow EIP-1559 and EIP-4844
    import { InvalidTransactionTypeError } from 'tevm/errors'
    
    const allowed = [Type.EIP1559, Type.EIP4844]
    if (!validateTransactionType(txData, allowed)) {
      throw new InvalidTransactionTypeError('Transaction type not supported', {
        code: 'UNSUPPORTED_TRANSACTION_TYPE',
        context: { allowed }
      })
    }
    

    Efficient Filtering

    import { detectType, Type } from 'tevm/Transaction'
    
    function filterByType(
      transactions: Uint8Array[],
      targetType: Transaction.Type
    ): Uint8Array[] {
      return transactions.filter(data => {
        try {
          return detectType(data) === targetType
        } catch {
          return false
        }
      })
    }
    
    // Get only EIP-4844 blob transactions
    const blobTxs = filterByType(allTransactions, Type.EIP4844)
    

    Error Handling

    import { detectType } from 'tevm/Transaction'
    
    function safeDetectType(data: Uint8Array): Transaction.Type | null {
      try {
        return detectType(data)
      } catch (error) {
        console.error('Type detection failed:', error)
        return null
      }
    }
    
    // Usage
    const type = safeDetectType(txData)
    if (type === null) {
      console.log('Invalid or unknown transaction type')
    }
    

    Type Guard Pattern

    import { detectType, Type } from 'tevm/Transaction'
    
    function isLegacyTransaction(data: Uint8Array): boolean {
      return detectType(data) === Type.Legacy
    }
    
    function isEIP1559Transaction(data: Uint8Array): boolean {
      return detectType(data) === Type.EIP1559
    }
    
    function isBlobTransaction(data: Uint8Array): boolean {
      return detectType(data) === Type.EIP4844
    }
    

    See Also

    References