Bytes & Hex
Overview
When working with Ethereum, data can commonly be represented as either:
- hexadecimal strings (a
0x
-prefixed string containing of hexadecimal characters), and/or - byte arrays (a sequence of unsigned 8-bit integers)
For the purposes of this guide, we will refer to them as "Hex" and "Bytes" respectively.
Bytes & Hex are representations of byte data, commonly used for addresses, hashes, signatures, and other encoded/serialized data.
The following types are used to represent Hex & Bytes:
Hex.Hex
: astring
prefixed with0x
.Bytes.Bytes
– aUint8Array
instance.
Instantiation
Hex
& Bytes
can be instantiated from their respective .from
functions: Hex.from
& Bytes.from
.
import { Bytes, Hex } from 'ox'
const hex = Hex.from('0xdeadbeef')
// '0xdeadbeef'
const bytes = Bytes.from([0xde, 0xad, 0xbe, 0xef])
// Uint8Array [0xde, 0xad, 0xbe, 0xef]
It is also possible to instantiate Hex
and Bytes
from primitive JavaScript types using:
Hex.fromBoolean
/Bytes.fromBoolean
Hex.fromNumber
/Bytes.fromNumber
Hex.fromString
/Bytes.fromString
import { Bytes, Hex } from 'ox'
const bool = Hex.fromBoolean(true)
'0x01' const bigint = Hex.fromNumber(420n)
'0x01a4' const number = Bytes.fromNumber(420)
Uint8Array [1, 164] const string = Hex.fromString('hello')
'0x68656c6c6f'
Conversion
Hex
& Bytes
can be converted to primitive JavaScript types using:
Hex.toBigInt
/Bytes.toBigInt
Hex.toBoolean
/Bytes.toBoolean
Hex.toNumber
/Bytes.toNumber
Hex.toString
/Bytes.toString
import { Bytes, Hex } from 'ox'
const bool = Bytes.toBoolean(Bytes.from([1]))
true const bigint = Hex.toBigInt('0x01a4')
420n const number = Bytes.toNumber(Bytes.from([1, 164]))
420 const string = Hex.toString('0x68656c6c6f')
'hello'
Manipulation
Concatenation
Hex & Bytes can be concatenated using their respective .concat
methods: Hex.concat
& Bytes.concat
:
import { Bytes, Hex } from 'ox'
Hex.concat('0xdead', '0xbeef')
'0xdeadbeef' Bytes.concat(
Bytes.from([0xde, 0xad]),
Bytes.from([0xbe, 0xef]),
)
Uint8Array [0xde, 0xad, 0xbe, 0xef]
Equality
Hex & Bytes can be compared for equality using the isEqual
method: Hex.isEqual
& Bytes.isEqual
:
import { Bytes } from 'ox'
const a = Bytes.from([0xde, 0xad, 0xbe, 0xef])
const b = Bytes.from([0xca, 0xfe, 0xba, 0xbe])
Bytes.isEqual(a, b)
false
Padding
Hex & Bytes can be padded to the left or right with empty bytes using their respective .padLeft
& .padRight
methods: Hex.padLeft
, Hex.padRight
, Bytes.padLeft
, Bytes.padRight
.
By default, the length of the final size is 32
bytes.
import { Bytes, Hex } from 'ox'
Hex.padLeft(Hex.from('0xdead'))
'0x00000000000000000000000000000000000000000000000000000000000000dead' Bytes.padLeft(Bytes.from([0xde, 0xad]), 4)
Uint8Array [0x00, 0x00, 0xde, 0xad] Hex.padRight(Hex.from('0xdead'))
'0xdead000000000000000000000000000000000000000000000000000000000000' Bytes.padRight(Bytes.from([0xde, 0xad]), 4)
Uint8Array [0xde, 0xad, 0x00, 0x00]
Size
The size of a Hex
or Bytes
can be retrieved using the .size
property: Hex.size
& Bytes.size
.
import { Bytes, Hex } from 'ox'
Hex.size('0xdeadbeefdeadbeefdeadbeefdeadbeef')
16 Bytes.size(Bytes.from([0xde, 0xad, 0xbe, 0xef]))
4
Slicing
Hex & Bytes can be sliced using their respective .slice
functions: Hex.slice
& Bytes.slice
.
import { Bytes, Hex } from 'ox'
Hex.slice('0x0123456789', 1, 4)
'0x234567' Bytes.slice(Bytes.from([0xde, 0xad, 0xbe, 0xef]), 0, 2)
Uint8Array [0xde, 0xad]
Trimming
Hex & Bytes can be trimmed of their leading & trailing empty bytes using their respective functions: Hex.trimLeft
, Hex.trimRight
, Bytes.trimLeft
, Bytes.trimRight
.
import { Bytes, Hex } from 'ox'
Hex.trimLeft('0x00000000000000000000000000000000000000000000000000000000000000dead')
'0xdead' Bytes.trimLeft(Bytes.from([0x00, 0x00, 0xde, 0xad]))
Uint8Array [0xde, 0xad] Hex.trimRight('0xdead000000000000000000000000000000000000000000000000000000000000')
'0xdead' Bytes.trimRight(Bytes.from([0xde, 0xad, 0x00, 0x00]))
Uint8Array [0xde, 0xad]
Validation
Hex & Bytes can be validated using their respective .validate
functions: Hex.validate
& Bytes.validate
.
import { Bytes, Hex } from 'ox'
Hex.validate('0xdeadbeefz')
false Bytes.validate(Bytes.from([0xde, 0xad, 0xbe, 0xef]))
true
It is also possible to assert that a Hex
or Bytes
is valid using .assert
: Hex.assert
& Bytes.assert
. This will throw an error if the value is invalid.
import { Bytes, Hex } from 'ox'
Hex.assert('abc')
Error: Hex.InvalidHexValueError Bytes.assert(Bytes.from([0xde, 0xad, 0xbe, 0xef]))
no error :)
Related Modules
Module | Description |
---|---|
Bytes | A set of Ethereum-related utility functions for working with Uint8Array instances. |
Hex | A set of Ethereum-related utility functions for working with hexadecimal string values (e.g. "0xdeadbeef" ). |