# Module BSV::Primitives::Hex <a id="module-BSV-Primitives-Hex"></a>

Strict hex encoding/decoding utilities.

Ruby's +Array#pack('H*')+ silently drops non-hex characters and truncates
odd-length strings. This module rejects both, raising `ArgumentError` on
invalid input so consumer-facing parse paths fail loudly rather than producing
garbage.

Internal paths that serialise/deserialise trusted hex (e.g. round-tripping our
own +unpack1('H*')+ output) can continue using +pack('H*')+ directly — the
validation overhead isn't warranted when the hex is known-good.

**@example**
```ruby
BSV::Primitives::Hex.decode('deadbeef')          #=> "\xDE\xAD\xBE\xEF"
BSV::Primitives::Hex.decode('nope')              #=> ArgumentError
BSV::Primitives::Hex.decode('abc')               #=> ArgumentError (odd length)
BSV::Primitives::Hex.encode("\xDE\xAD")          #=> "dead"
```

## Constants
### `HEX_RE` <a id="constant-HEX_RE"></a> <a id="HEX_RE-constant"></a>
Matches an even number of hex characters (case-insensitive). Empty string is
valid (decodes to empty bytes).

## Public Class Methods
### `decode(str, name: = 'hex value')` <a id="method-c-decode"></a> <a id="decode-class_method"></a>
Decode a hex string to binary bytes.
- **@param** `str` [String] hex string (must be even-length, hex-only)
- **@param** `name` [String] label for the error message
- **@raise** [ArgumentError] if +str+ is not valid hex
- **@return** [String] binary string (ASCII-8BIT encoding)

### `encode(bytes)` <a id="method-c-encode"></a> <a id="encode-class_method"></a>
Encode binary bytes as lowercase hex.
- **@param** `bytes` [String] binary data
- **@return** [String] lowercase hex string (UTF-8 encoding)

### `valid?(str)` <a id="method-c-valid-3F"></a> <a id="valid?-class_method"></a>
Test whether `str` is valid hex (even-length, hex-only).
- **@param** `str` [String]
- **@return** [Boolean]

### `validate!(str, name: = 'hex value')` <a id="method-c-validate-21"></a> <a id="validate!-class_method"></a>
Validate `str` as hex, raising on failure.
- **@param** `str` [String]
- **@param** `name` [String] label for the error message (e.g. +'txid'+)
- **@raise** [ArgumentError] if +str+ is not valid hex
- **@return** [String] the input string (pass-through for chaining)

### `validate_dtxid_hex!(value, name: = 'dtxid_hex')` <a id="method-c-validate_dtxid_hex-21"></a> <a id="validate_dtxid_hex!-class_method"></a>
Validate that `value` is a 64-character display-order hex transaction ID.
- **@param** `value` [String] expected 64-char hex string
- **@param** `name` [String] label for the error message (e.g. +'dtxid_hex'+)
- **@raise** [ArgumentError] if +value+ is not a 64-char hex string
- **@return** [String] the input value (pass-through for chaining)

### `validate_hash32!(value, name: = 'hash')` <a id="method-c-validate_hash32-21"></a> <a id="validate_hash32!-class_method"></a>
Validate that `value` is a 32-byte binary hash.

General-purpose validator for any 32-byte hash (merkle nodes, roots, etc.) —
not specific to transaction IDs. For txid-specific validation use
{.validate_wtxid!} or {.validate_dtxid_hex!} instead.
- **@param** `value` [String] expected 32-byte binary string
- **@param** `name` [String] label for the error message
- **@raise** [ArgumentError] if +value+ is not a 32-byte binary string
- **@return** [String] the input value (pass-through for chaining)

### `validate_wtxid!(value, name: = 'wtxid')` <a id="method-c-validate_wtxid-21"></a> <a id="validate_wtxid!-class_method"></a>
Validate that `value` is a 32-byte wire-order transaction ID.
- **@param** `value` [String] expected 32-byte binary string
- **@param** `name` [String] label for the error message (e.g. +'prev_wtxid'+)
- **@raise** [ArgumentError] if +value+ is not a 32-byte binary string
- **@return** [String] the input value (pass-through for chaining)
